|
Lines 66-71
Link Here
|
| 66 |
pid_t update_child; |
66 |
pid_t update_child; |
| 67 |
int incoming_update_type = -1; |
67 |
int incoming_update_type = -1; |
| 68 |
char* update_status = NULL; |
68 |
char* update_status = NULL; |
|
|
69 |
time_t filelist_mtime = 0; |
| 69 |
|
70 |
|
| 70 |
static const char* filelist_name = "filelist"; |
71 |
static const char* filelist_name = "filelist"; |
| 71 |
static const char* new_filelist_name = "new-filelist"; |
72 |
static const char* new_filelist_name = "new-filelist"; |
|
Lines 78-83
Link Here
|
| 78 |
#define ENOTFILELIST (1 << 16) |
79 |
#define ENOTFILELIST (1 << 16) |
| 79 |
#define EWRONGVERSION (ENOTFILELIST + 1) |
80 |
#define EWRONGVERSION (ENOTFILELIST + 1) |
| 80 |
|
81 |
|
|
|
82 |
bool report_error(MsgQ* status_mq, const char* fmt, ...); |
| 83 |
|
| 81 |
int compare_pointers(void* p1, void* p2) |
84 |
int compare_pointers(void* p1, void* p2) |
| 82 |
{ |
85 |
{ |
| 83 |
return p1 != p2; |
86 |
return p1 != p2; |
|
Lines 119-138
Link Here
|
| 119 |
return is_already_shared_inode(root, st.st_dev, st.st_ino); |
122 |
return is_already_shared_inode(root, st.st_dev, st.st_ino); |
| 120 |
} |
123 |
} |
| 121 |
|
124 |
|
| 122 |
DCFileList* read_local_file_list(const char* path) |
125 |
void lock_file (const char* path) |
|
|
126 |
{ |
| 127 |
int fd, timeout = 20; |
| 128 |
char fn [300]; |
| 129 |
snprintf (fn, sizeof (fn), "%s.lock", path); |
| 130 |
while ((fd = open (fn, O_RDONLY | O_CREAT | O_EXCL, 0600) < 0)) { |
| 131 |
if (errno != EEXIST) { |
| 132 |
/* It seems there's no way to report an error from here to parent? */ |
| 133 |
/*report_error(result_mq, _("%s: Failed to create filelist lock, filelist will be not multiprocess-safe\n"), fn);*/ |
| 134 |
break; |
| 135 |
} |
| 136 |
/* Wait some time for the lock to be released */ |
| 137 |
sleep (1); |
| 138 |
if (!--timeout) { |
| 139 |
/*report_error(result_mq, _("%s: Filelist semaphore locked, but owner seems dead, breaking lock\n"), fn);*/ |
| 140 |
break; |
| 141 |
} |
| 142 |
} |
| 143 |
if (fd >= 0) |
| 144 |
close (fd); |
| 145 |
} |
| 146 |
|
| 147 |
void unlock_file (const char* path) |
| 148 |
{ |
| 149 |
char fn [300]; |
| 150 |
snprintf (fn, sizeof (fn), "%s.lock", path); |
| 151 |
unlink (fn); |
| 152 |
} |
| 153 |
|
| 154 |
/* if old_root is not NULL, rereads the file list only if file changed */ |
| 155 |
DCFileList* read_local_file_list(const char* path, DCFileList *old_root) |
| 123 |
{ |
156 |
{ |
| 124 |
struct stat st; |
157 |
struct stat st; |
| 125 |
DCFileList *root = NULL; |
158 |
DCFileList *root = NULL; |
| 126 |
|
159 |
|
|
|
160 |
/* First of all, check if filelist is not locked by other process */ |
| 161 |
lock_file (path); |
| 162 |
|
| 127 |
if (stat(path, &st) < 0) { |
163 |
if (stat(path, &st) < 0) { |
| 128 |
if (errno != ENOENT) { |
164 |
if (errno != ENOENT) { |
| 129 |
TRACE(("cannot stat %s: %d, %s\n", path, errno, errstr)); |
165 |
TRACE(("cannot stat %s: %d, %s\n", path, errno, errstr)); |
|
|
166 |
unlock_file (path); |
| 130 |
return NULL; |
167 |
return NULL; |
| 131 |
} |
168 |
} |
| 132 |
} else if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { |
169 |
} else if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { |
|
|
170 |
unlock_file (path); |
| 133 |
return NULL; |
171 |
return NULL; |
| 134 |
} |
172 |
} |
| 135 |
|
173 |
|
|
|
174 |
if (old_root && filelist_mtime == st.st_mtime) { |
| 175 |
unlock_file (path); |
| 176 |
return old_root; |
| 177 |
} |
| 178 |
filelist_mtime = st.st_mtime; |
| 179 |
|
| 136 |
int fd = open(path, O_RDONLY); |
180 |
int fd = open(path, O_RDONLY); |
| 137 |
if (fd >= 0) { |
181 |
if (fd >= 0) { |
| 138 |
void* mapped = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
182 |
void* mapped = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
|
Lines 158-169
Link Here
|
| 158 |
root = new_file_node("", DC_TYPE_DIR, NULL); |
202 |
root = new_file_node("", DC_TYPE_DIR, NULL); |
| 159 |
} |
203 |
} |
| 160 |
|
204 |
|
|
|
205 |
unlock_file (path); |
| 206 |
|
| 207 |
if (old_root) |
| 208 |
filelist_free (old_root); |
| 209 |
|
| 161 |
return root; |
210 |
return root; |
| 162 |
} |
211 |
} |
| 163 |
|
212 |
|
| 164 |
bool write_local_file_list(const char* path, DCFileList* root) |
213 |
bool write_local_file_list(const char* path, DCFileList* root) |
| 165 |
{ |
214 |
{ |
| 166 |
bool result = false; |
215 |
bool result = false; |
|
|
216 |
struct stat st; |
| 217 |
|
| 218 |
/* Check if filelist is not locked by other process */ |
| 219 |
lock_file (path); |
| 220 |
|
| 167 |
int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
221 |
int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
| 168 |
if (fd >= 0) { |
222 |
if (fd >= 0) { |
| 169 |
unsigned char* data = NULL; |
223 |
unsigned char* data = NULL; |
|
Lines 194-201
Link Here
|
| 194 |
result = (size == data_size); |
248 |
result = (size == data_size); |
| 195 |
|
249 |
|
| 196 |
cleanup: |
250 |
cleanup: |
|
|
251 |
/* Update filelist mtime */ |
| 252 |
if (stat(path, &st) == 0) |
| 253 |
filelist_mtime = st.st_mtime; |
| 254 |
|
| 197 |
close(fd); |
255 |
close(fd); |
| 198 |
} |
256 |
} |
|
|
257 |
|
| 258 |
unlock_file (path); |
| 199 |
return result; |
259 |
return result; |
| 200 |
} |
260 |
} |
| 201 |
|
261 |
|
|
Lines 487-492
Link Here
|
| 487 |
/* Inability to register these signals is not a fatal error. */ |
547 |
/* Inability to register these signals is not a fatal error. */ |
| 488 |
sigact.sa_flags = SA_RESTART; |
548 |
sigact.sa_flags = SA_RESTART; |
| 489 |
sigact.sa_handler = SIG_IGN; |
549 |
sigact.sa_handler = SIG_IGN; |
|
|
550 |
sigemptyset (&sigact.sa_mask); |
| 490 |
#ifdef HAVE_STRUCT_SIGACTION_SA_RESTORER |
551 |
#ifdef HAVE_STRUCT_SIGACTION_SA_RESTORER |
| 491 |
sigact.sa_restorer = NULL; |
552 |
sigact.sa_restorer = NULL; |
| 492 |
#endif |
553 |
#endif |
|
Lines 503-509
Link Here
|
| 503 |
goto cleanup; |
564 |
goto cleanup; |
| 504 |
} |
565 |
} |
| 505 |
|
566 |
|
| 506 |
if (NULL == (root = read_local_file_list(flist_filename))) { |
567 |
if (NULL == (root = read_local_file_list(flist_filename, NULL))) { |
| 507 |
if (errno == ENOTFILELIST) { |
568 |
if (errno == ENOTFILELIST) { |
| 508 |
report_error(result_mq, "Cannot load FileList - %s: Invalid file format\n", flist_filename); |
569 |
report_error(result_mq, "Cannot load FileList - %s: Invalid file format\n", flist_filename); |
| 509 |
} else if (errno == EWRONGVERSION) { |
570 |
} else if (errno == EWRONGVERSION) { |
|
Lines 527-533
Link Here
|
| 527 |
max_fd = MAX(hash_result_mq->fd, max_fd); |
588 |
max_fd = MAX(hash_result_mq->fd, max_fd); |
| 528 |
|
589 |
|
| 529 |
while (true) { |
590 |
while (true) { |
| 530 |
tv.tv_sec = filelist_refresh_timeout; |
591 |
tv.tv_sec = FILELIST_SLAVE_MODE ? 60 : filelist_refresh_timeout; |
| 531 |
tv.tv_usec = 0; |
592 |
tv.tv_usec = 0; |
| 532 |
|
593 |
|
| 533 |
fd_set r_ready = readable, w_ready = writable; |
594 |
fd_set r_ready = readable, w_ready = writable; |
|
Lines 577-589
Link Here
|
| 577 |
fflush(stderr); |
638 |
fflush(stderr); |
| 578 |
*/ |
639 |
*/ |
| 579 |
} |
640 |
} |
|
|
641 |
|
| 642 |
if (FILELIST_SLAVE_MODE && update_hash) { |
| 643 |
/* Unexpected hash update received while in slave filelist mode */ |
| 644 |
update_hash = false; |
| 645 |
} |
| 646 |
|
| 580 |
time_t now = time(NULL); |
647 |
time_t now = time(NULL); |
| 581 |
if (update_hash && ((hashing == NULL && hash_files->cur == 0) || (now - hash_start) > filelist_hash_refresh_timeout)) { |
648 |
if (update_hash && ((hashing == NULL && hash_files->cur == 0) || (now - hash_start) > filelist_hash_refresh_timeout)) { |
| 582 |
hash_start = now; |
649 |
hash_start = now; |
| 583 |
if (write_local_file_list(new_flist_filename, root)) { |
650 |
if (write_local_file_list(new_flist_filename, root)) { |
| 584 |
rename(new_flist_filename, flist_filename); |
651 |
rename(new_flist_filename, flist_filename); |
| 585 |
} else { |
652 |
} else { |
| 586 |
unlink(new_filelist_name); |
653 |
unlink(new_flist_filename); |
| 587 |
} |
654 |
} |
| 588 |
|
655 |
|
| 589 |
if (!send_filelist(result_mq, root)) { |
656 |
if (!send_filelist(result_mq, root)) { |
|
Lines 607-617
Link Here
|
| 607 |
msgq_get(request_mq, MSGQ_INT, &update_type, MSGQ_END); |
674 |
msgq_get(request_mq, MSGQ_INT, &update_type, MSGQ_END); |
| 608 |
} else { |
675 |
} else { |
| 609 |
if (update_type == FILELIST_UPDATE_REFRESH_INTERVAL) { |
676 |
if (update_type == FILELIST_UPDATE_REFRESH_INTERVAL) { |
| 610 |
time_t interval = 0; |
677 |
msgq_get(request_mq, MSGQ_INT, &filelist_refresh_timeout, MSGQ_END); |
| 611 |
msgq_get(request_mq, MSGQ_INT, &interval, MSGQ_END); |
|
|
| 612 |
if (interval != 0) { |
| 613 |
filelist_refresh_timeout = interval; |
| 614 |
} |
| 615 |
} else { |
678 |
} else { |
| 616 |
char *name; |
679 |
char *name; |
| 617 |
int len = 0; |
680 |
int len = 0; |
|
Lines 626-638
Link Here
|
| 626 |
case FILELIST_UPDATE_ADD_DIR_NAME: |
689 |
case FILELIST_UPDATE_ADD_DIR_NAME: |
| 627 |
if (is_already_shared(root, name)) { |
690 |
if (is_already_shared(root, name)) { |
| 628 |
// report error here |
691 |
// report error here |
| 629 |
report_error(result_mq, "%s directory is already shared as subfolder of existing shared tree\n", name); |
692 |
report_error(result_mq, _("%s directory is already shared as subfolder of existing shared tree\n"), name); |
| 630 |
} else { |
693 |
} else if (FILELIST_SLAVE_MODE) |
|
|
694 |
report_error(result_mq, _("Cannot add directory %s to share list while in slave filelist mode\n"), name); |
| 695 |
else { |
| 631 |
char* bname = xstrdup(base_name(name)); |
696 |
char* bname = xstrdup(base_name(name)); |
| 632 |
|
697 |
|
| 633 |
if (hmap_contains_key(root->dir.children, bname)) { |
698 |
if (hmap_contains_key(root->dir.children, bname)) { |
| 634 |
/* we already have the shared directory with the same name */ |
699 |
/* we already have the shared directory with the same name */ |
| 635 |
report_error(result_mq, "%s directory cannot be shared as %s because there is already shared directory with the same name\n", name, bname); |
700 |
report_error(result_mq, _("%s directory cannot be shared as %s because there is already shared directory with the same name\n"), name, bname); |
| 636 |
} else { |
701 |
} else { |
| 637 |
DCFileList* node = new_file_node(bname, DC_TYPE_DIR, root); |
702 |
DCFileList* node = new_file_node(bname, DC_TYPE_DIR, root); |
| 638 |
node->dir.real_path = xstrdup(name); |
703 |
node->dir.real_path = xstrdup(name); |
|
Lines 642-669
Link Here
|
| 642 |
} |
707 |
} |
| 643 |
break; |
708 |
break; |
| 644 |
case FILELIST_UPDATE_DEL_DIR_NAME: |
709 |
case FILELIST_UPDATE_DEL_DIR_NAME: |
| 645 |
//selected = 0; |
|
|
| 646 |
{ |
710 |
{ |
| 647 |
char* bname = xstrdup(base_name(name)); |
711 |
char* bname = xstrdup(base_name(name)); |
| 648 |
|
712 |
|
| 649 |
DCFileList* node = hmap_get(root->dir.children, bname); |
713 |
DCFileList* node = hmap_get(root->dir.children, bname); |
| 650 |
if (node != NULL && node->type == DC_TYPE_DIR) { |
714 |
if (node != NULL && node->type == DC_TYPE_DIR && |
| 651 |
if (strcmp(node->dir.real_path, name) == 0) { |
715 |
strcmp(node->dir.real_path, name) == 0) { |
|
|
716 |
if (FILELIST_SLAVE_MODE) |
| 717 |
report_error(result_mq, _("Cannot remove directory %s from share list while in slave filelist mode\n"), name); |
| 718 |
else { |
| 652 |
node = hmap_remove(root->dir.children, bname); |
719 |
node = hmap_remove(root->dir.children, bname); |
| 653 |
filelist_free(node); |
720 |
filelist_free(node); |
| 654 |
if (write_local_file_list(new_flist_filename, root)) { |
721 |
if (write_local_file_list(new_flist_filename, root)) { |
| 655 |
rename(new_flist_filename, flist_filename); |
722 |
rename(new_flist_filename, flist_filename); |
| 656 |
} else { |
723 |
} else { |
| 657 |
unlink(new_filelist_name); |
724 |
unlink(new_flist_filename); |
| 658 |
} |
725 |
} |
| 659 |
|
726 |
|
| 660 |
if (!send_filelist(result_mq, root)) { |
727 |
if (!send_filelist(result_mq, root)) { |
| 661 |
goto cleanup; |
728 |
goto cleanup; |
| 662 |
} |
729 |
} |
| 663 |
} else { |
|
|
| 664 |
report_error(result_mq, "%s directory is not shared\n"); |
| 665 |
} |
730 |
} |
| 666 |
} |
731 |
} |
|
|
732 |
else |
| 733 |
report_error(result_mq, _("%s directory is not shared\n"), name); |
| 667 |
free(bname); |
734 |
free(bname); |
| 668 |
} |
735 |
} |
| 669 |
break; |
736 |
break; |
|
Lines 703-720
Link Here
|
| 703 |
} |
770 |
} |
| 704 |
} |
771 |
} |
| 705 |
} |
772 |
} |
| 706 |
if (selected == 0) { |
773 |
|
|
|
774 |
if (FILELIST_SLAVE_MODE && selected >= 0) { |
| 775 |
// Check if filelist has been changed since we last read it |
| 776 |
DCFileList *new_root = read_local_file_list(flist_filename, root); |
| 777 |
if (new_root != root) { |
| 778 |
root = new_root; |
| 779 |
send_filelist(result_mq, root); |
| 780 |
} |
| 781 |
} |
| 782 |
else if (selected == 0) { |
| 707 |
// just look through shared directories for new or deleted files |
783 |
// just look through shared directories for new or deleted files |
| 708 |
if (hashing == NULL && !initial) |
784 |
if (hashing == NULL && !initial) |
| 709 |
report_status(result_mq, "Refreshing FileList"); |
785 |
report_status(result_mq, _("Refreshing FileList")); |
| 710 |
|
786 |
|
| 711 |
if (lookup_filelist_changes(root, hash_files)) { |
787 |
if (lookup_filelist_changes(root, hash_files)) { |
| 712 |
if (write_local_file_list(new_flist_filename, root)) { |
788 |
if (write_local_file_list(new_flist_filename, root)) { |
| 713 |
rename(new_flist_filename, flist_filename); |
789 |
rename(new_flist_filename, flist_filename); |
| 714 |
} else { |
790 |
} else { |
| 715 |
unlink(new_filelist_name); |
791 |
unlink(new_flist_filename); |
| 716 |
} |
792 |
} |
| 717 |
|
793 |
|
| 718 |
if (!send_filelist(result_mq, root)) { |
794 |
if (!send_filelist(result_mq, root)) { |
| 719 |
break; |
795 |
break; |
| 720 |
} |
796 |
} |