Lines 95-101
Link Here
|
95 |
//static bool shutting_down = false; |
95 |
//static bool shutting_down = false; |
96 |
|
96 |
|
97 |
#define FS_SERVER_MAJOR_VERSION 1 |
97 |
#define FS_SERVER_MAJOR_VERSION 1 |
98 |
#define FS_SERVER_MID_VERSION 9 |
98 |
#define FS_SERVER_MID_VERSION 10 |
99 |
#define FS_SERVER_MINOR_VERSION 0 |
99 |
#define FS_SERVER_MINOR_VERSION 0 |
100 |
|
100 |
|
101 |
typedef struct fs_entry { |
101 |
typedef struct fs_entry { |
Lines 221-226
Link Here
|
221 |
return result; |
221 |
return result; |
222 |
} |
222 |
} |
223 |
|
223 |
|
|
|
224 |
/// a mutex that guards both dirs_forbidden_to_stat and dirs_forbidden_to_stat_data |
225 |
static pthread_mutex_t forbidden_dirs_mutex = PTHREAD_MUTEX_INITIALIZER; |
226 |
|
227 |
/// directories that are forbidden to stat; the last element is null |
228 |
static const char** dirs_forbidden_to_stat = NULL; |
229 |
|
230 |
/// just a buffer to keep strings in dirs_forbidden_to_stat |
231 |
static char* dirs_forbidden_to_stat_buffer = NULL; |
232 |
|
233 |
static void free_dirs_forbidden_to_stat() { |
234 |
mutex_lock_wrapper(&forbidden_dirs_mutex); |
235 |
if (dirs_forbidden_to_stat) { |
236 |
free(dirs_forbidden_to_stat); |
237 |
} |
238 |
if (dirs_forbidden_to_stat_buffer) { |
239 |
free(dirs_forbidden_to_stat_buffer); |
240 |
} |
241 |
mutex_unlock_wrapper(&forbidden_dirs_mutex); |
242 |
} |
243 |
|
244 |
static bool is_dir_forbidden_to_stat(const char* path2check) { |
245 |
bool forbidden = false; |
246 |
mutex_lock_wrapper(&forbidden_dirs_mutex); |
247 |
if (dirs_forbidden_to_stat) { |
248 |
for(const char** path = dirs_forbidden_to_stat; *path; path++) { |
249 |
if (strcmp(path2check, *path) == 0) { |
250 |
forbidden = true; |
251 |
} |
252 |
} |
253 |
} |
254 |
mutex_unlock_wrapper(&forbidden_dirs_mutex); |
255 |
return forbidden; |
256 |
} |
257 |
|
258 |
static void set_dirs_forbidden_to_stat(const char* dir_list) { |
259 |
mutex_lock_wrapper(&forbidden_dirs_mutex); |
260 |
dirs_forbidden_to_stat_buffer = strdup(dir_list); |
261 |
int cnt = 1; |
262 |
for(const char* p = dirs_forbidden_to_stat_buffer; *p; p++) { |
263 |
if (*p == ':') { |
264 |
cnt++; |
265 |
} |
266 |
} |
267 |
dirs_forbidden_to_stat = calloc(cnt+1, sizeof(char*)); // cnt+1 reserves space for trailing null |
268 |
const char** curr_path = dirs_forbidden_to_stat; |
269 |
*curr_path = dirs_forbidden_to_stat_buffer; |
270 |
for(char* p = dirs_forbidden_to_stat_buffer; *p; p++) { |
271 |
if (*p == ':') { |
272 |
*p = '\0'; |
273 |
curr_path++; |
274 |
*curr_path = p+1; |
275 |
} |
276 |
} |
277 |
mutex_unlock_wrapper(&forbidden_dirs_mutex); |
278 |
} |
279 |
|
280 |
static void dump_dirs_forbidden_to_stat(TraceLevel level) { |
281 |
if (is_traceable(level)) { |
282 |
trace(level, "Directories forbidden to stat:\n"); |
283 |
mutex_lock_wrapper(&forbidden_dirs_mutex); |
284 |
for(const char** path = dirs_forbidden_to_stat; *path; path++) { |
285 |
trace(level, "%s\n", *path); |
286 |
} |
287 |
mutex_unlock_wrapper(&forbidden_dirs_mutex); |
288 |
} |
289 |
} |
290 |
|
291 |
static void fill_dummy_stat(struct stat *stat_buf) { |
292 |
memset(stat_buf, '\0', sizeof(struct stat)); |
293 |
stat_buf->st_uid = 0; |
294 |
stat_buf->st_mode = __S_IFDIR; |
295 |
stat_buf->st_size = 0; |
296 |
stat_buf->st_dev = 0; |
297 |
stat_buf->st_ino = 0; |
298 |
} |
299 |
|
300 |
static int lstat_wrapper(const char *path, struct stat *stat_buf) { |
301 |
if (is_dir_forbidden_to_stat(path)) { |
302 |
fill_dummy_stat(stat_buf); |
303 |
return 0; |
304 |
} else { |
305 |
return lstat(path, stat_buf); |
306 |
} |
307 |
} |
308 |
|
309 |
static int stat_wrapper(const char *path, struct stat *stat_buf) { |
310 |
if (is_dir_forbidden_to_stat(path)) { |
311 |
fill_dummy_stat(stat_buf); |
312 |
return 0; |
313 |
} else { |
314 |
return stat(path, stat_buf); |
315 |
} |
316 |
} |
317 |
|
224 |
#define DECLARE_DECODE(type, type_name, maxlen) \ |
318 |
#define DECLARE_DECODE(type, type_name, maxlen) \ |
225 |
static const char* decode_##type_name (const char* text, type* result) { \ |
319 |
static const char* decode_##type_name (const char* text, type* result) { \ |
226 |
*result = 0; \ |
320 |
*result = 0; \ |
Lines 711-717
Link Here
|
711 |
const char *abspath, const char *basename, |
805 |
const char *abspath, const char *basename, |
712 |
buffer work_buf) { |
806 |
buffer work_buf) { |
713 |
struct stat stat_buf; |
807 |
struct stat stat_buf; |
714 |
if (lstat(abspath, &stat_buf) == 0) { |
808 |
if (lstat_wrapper(abspath, &stat_buf) == 0) { |
715 |
|
809 |
|
716 |
//int escaped_name_size = escape_strlen(entry->d_name); |
810 |
//int escaped_name_size = escape_strlen(entry->d_name); |
717 |
escape_strcpy(work_buf.data, basename); |
811 |
escape_strcpy(work_buf.data, basename); |
Lines 882-888
Link Here
|
882 |
} |
976 |
} |
883 |
|
977 |
|
884 |
struct stat stat_buf; |
978 |
struct stat stat_buf; |
885 |
if (lstat(path, &stat_buf) == 0) { |
979 |
if (lstat_wrapper(path, &stat_buf) == 0) { |
886 |
if (S_ISDIR(stat_buf.st_mode)) { |
980 |
if (S_ISDIR(stat_buf.st_mode)) { |
887 |
if (!clean_dir(path)) { |
981 |
if (!clean_dir(path)) { |
888 |
response_error(request_id, path, errno, "can't remote directory content"); |
982 |
response_error(request_id, path, errno, "can't remote directory content"); |
Lines 942-948
Link Here
|
942 |
|
1036 |
|
943 |
static void response_stat(int request_id, const char* path) { |
1037 |
static void response_stat(int request_id, const char* path) { |
944 |
struct stat stat_buf; |
1038 |
struct stat stat_buf; |
945 |
if (stat(path, &stat_buf) == 0) { |
1039 |
if (stat_wrapper(path, &stat_buf) == 0) { |
946 |
int buf_size = MAXNAMLEN * 2 + 80; // *2 because of escaping. TODO: accurate size calculation |
1040 |
int buf_size = MAXNAMLEN * 2 + 80; // *2 because of escaping. TODO: accurate size calculation |
947 |
char* escaped_name = malloc_wrapper(buf_size); |
1041 |
char* escaped_name = malloc_wrapper(buf_size); |
948 |
const char* basename = get_basename(path); |
1042 |
const char* basename = get_basename(path); |
Lines 984-995
Link Here
|
984 |
|
1078 |
|
985 |
// if file exists, return error |
1079 |
// if file exists, return error |
986 |
struct stat stat_buf; |
1080 |
struct stat stat_buf; |
987 |
if (lstat(request->path2, &stat_buf) == 0) { |
1081 |
if (lstat_wrapper(request->path2, &stat_buf) == 0) { |
988 |
response_error(request->id, request->path2, 0, "file already exists"); |
1082 |
response_error(request->id, request->path2, 0, "file already exists"); |
989 |
response_end(request->id, request->path2); |
1083 |
response_end(request->id, request->path2); |
990 |
return; |
1084 |
return; |
991 |
} |
1085 |
} |
992 |
if (lstat(request->path, &stat_buf) == -1) { |
1086 |
if (lstat_wrapper(request->path, &stat_buf) == -1) { |
993 |
response_error(request->id, request->path, errno, err_to_string(errno)); |
1087 |
response_error(request->id, request->path, errno, err_to_string(errno)); |
994 |
response_end(request->id, request->path2); |
1088 |
response_end(request->id, request->path2); |
995 |
return; |
1089 |
return; |
Lines 1170-1176
Link Here
|
1170 |
// check whether it is directory and print clear error message |
1264 |
// check whether it is directory and print clear error message |
1171 |
// (copy_plain_file will print unclear "Operation not permitted" in this case) |
1265 |
// (copy_plain_file will print unclear "Operation not permitted" in this case) |
1172 |
struct stat stat_buf; |
1266 |
struct stat stat_buf; |
1173 |
if (lstat(request->path, &stat_buf) == -1) { |
1267 |
if (lstat_wrapper(request->path, &stat_buf) == -1) { |
1174 |
response_error(request->id, request->path, errno, err_to_string(errno)); |
1268 |
response_error(request->id, request->path, errno, err_to_string(errno)); |
1175 |
return; |
1269 |
return; |
1176 |
} |
1270 |
} |
Lines 1472-1477
Link Here
|
1472 |
} else { |
1566 |
} else { |
1473 |
report_error("Unexpected option value: %s=%s\n", option, value); |
1567 |
report_error("Unexpected option value: %s=%s\n", option, value); |
1474 |
} |
1568 |
} |
|
|
1569 |
} else if (strcmp(option, "dirs-forbidden-to-stat") == 0) { |
1570 |
set_dirs_forbidden_to_stat(value); |
1571 |
dump_dirs_forbidden_to_stat(TRACE_FINER); |
1475 |
} else { |
1572 |
} else { |
1476 |
report_error("Unexpected option key: %s\n", option); |
1573 |
report_error("Unexpected option key: %s\n", option); |
1477 |
} |
1574 |
} |
Lines 1983-1988
Link Here
|
1983 |
dirtab_free(); |
2080 |
dirtab_free(); |
1984 |
log_close(); |
2081 |
log_close(); |
1985 |
err_shutdown(); |
2082 |
err_shutdown(); |
|
|
2083 |
free_dirs_forbidden_to_stat(); |
1986 |
trace(TRACE_INFO, "Shut down.\n"); |
2084 |
trace(TRACE_INFO, "Shut down.\n"); |
1987 |
exit(0); |
2085 |
exit(0); |
1988 |
} |
2086 |
} |