/*** (a) get those softlinks that points to a directory this is to deal with the following scenario previous structure dir_path (a directory) db (a directory) newly updated structure on master dir_path -> db db rsync --dry-run generates dir_path -> db [a link is done on target] deleting dir_path/sub/filename1 [wrong file gets removed ] deleting dir_path/sub/filename2... file_operations.c does this when dir_path -> db is due delete dir_path (rm -rf) make the softlink But then the following delete will have undesired deletion. ------------------------------------------------------------ (b) t0 name -> xyz name -> xyz (target) t1 name/ name -> xyz rsync generates name/ update_directory() won't have effect name/f1 delivered to wrong place name/f2 deleting name too late ** the deletion should be done before not after. For now, I will fail this code for this situation. ***/ void get_dir_softlinks(char *filename, char * basedir) { FILE * fd; char line[PATH_MAX]; struct stat st; if ((fd = fopen(filename, "r")) == NULL) { fprintf(stderr, "Cannot open file -- %s \n", filename); exit(-1); } while (1) { /* for each line in the file */ char *pc; char fn[PATH_MAX]; if (fgets(line, PATH_MAX, fd)==NULL) break; strip(line); if (strlen(line) == 0) continue; /* skip blank line */ /* the softlink case is indicated by -> */ pc= strstr(line, " -> "); if (pc) { /* it is a softlink */ *pc = '\0'; /* check if it is a directory */ sprintf(fn, "%s/%s", basedir, line); /* check if the link-target is a directory */ if (stat(fn, &st)<0) continue; /* We skip this bad entry - no longer exist */ if (S_ISDIR(st.st_mode)) { append_string_list(line, &softlink_list); } } else { /* not a softlink --> find if it is a directory */ /* find a line without ' ' and with trailing '/' */ pc = strstr(line, " "); /* the first space */ if (!pc) { char * plast = &line[0] + strlen(line) - 1; if (*plast == '/') { append_string_list(line, &newdir_list); } } } } fclose(fd); }
int avahi_entry_group_update_service_txt_strlst( AvahiEntryGroup *group, AvahiIfIndex interface, AvahiProtocol protocol, AvahiPublishFlags flags, const char *name, const char *type, const char *domain, AvahiStringList *txt) { DBusMessage *message = NULL, *reply = NULL; int r = AVAHI_OK; DBusError error; AvahiClient *client; int32_t i_interface, i_protocol; uint32_t u_flags; assert(group); assert(name); assert(type); client = group->client; if (!group->path || !avahi_client_is_connected(group->client)) return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE); if (!domain) domain = ""; dbus_error_init(&error); if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt"))) { r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } i_interface = (int32_t) interface; i_protocol = (int32_t) protocol; u_flags = (uint32_t) flags; if (!dbus_message_append_args( message, DBUS_TYPE_INT32, &i_interface, DBUS_TYPE_INT32, &i_protocol, DBUS_TYPE_UINT32, &u_flags, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &type, DBUS_TYPE_STRING, &domain, DBUS_TYPE_INVALID) || append_string_list(message, txt) < 0) { r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY); goto fail; } if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) || dbus_error_is_set (&error)) { r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); goto fail; } if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); goto fail; } dbus_message_unref(message); dbus_message_unref(reply); return AVAHI_OK; fail: if (dbus_error_is_set(&error)) { r = avahi_client_set_dbus_error(client, &error); dbus_error_free(&error); } if (message) dbus_message_unref(message); if (reply) dbus_message_unref(reply); return r; }
int main(int argc, char * argv[]) { char * filename; char * basedir; FILE *fd; char line[PATH_MAX]; if (argc < 3) { fprintf(stderr, "Usage: trFilelist synclist_filename basedir\n"); exit(-1); } filename = argv[1]; basedir = argv[2]; init_string_list(&file_list, 10); init_uint_list(&ino_list, 10); init_string_list(&dir_list, 100); init_string_list(&softlink_list, 10); init_string_list(&newdir_list, 100); get_dir_softlinks(filename, basedir); if ((fd = fopen(filename, "r")) == NULL) { fprintf(stderr, "Cannot open file -- %s \n", filename); return -1; } while (1) { /* for each line in the file */ char *pc; char fn[PATH_MAX]; struct stat st; int newdir_flag; if (fgets(line, PATH_MAX, fd)==NULL) break; strip(line); if (strlen(line) == 0) continue; /* skip blank line */ if (strcmp(line, ".")==0) continue; if (strcmp(line, "./")==0) continue; /* first we look for deleting entry */ if (strncmp(line, "deleting ", 9)==0) { /* deleting (directory) file_path */ char * p1, *p2, *pf; p1 = strstr(line, " "); /* the first space */ p2 = strstr(p1+1, " "); /* deleting directory filepath * 20070912 this is old */ pf = (p2) ? p2+1 : p1+1;/* it's always p1+1 */ newdir_flag = has_newdir(pf, &newdir_list); if ((has_sub_string(pf, &softlink_list)<0) && newdir_flag<0) { /* see comments above get_dir_softlinks() */ printf("deleting %s\n", pf); } else if (newdir_flag>=0) { /* temporary action */ /*** we can simply skip this block later. 20070912 ***/ /***/ fprintf(stderr, "CRITICAL ERROR: An old softlink has been changed to a directory!\n"); fprintf(stderr, " For now, we crash this code for human intervention\n"); fprintf(stderr, " line= %s\n", line); exit(-1); /***/ } continue; } /* the softlink case is indicated by -> */ pc= strstr(line, " -> "); if (pc) { *pc = '\0'; output_subs(line); printf("%s\n", line); continue; } /* if rsync's -H is turned on, the output may contain file => tar_hardlink_file (relative address) */ pc= strstr(line, " => "); if (pc) { *pc = '\0'; output_subs(line); printf("%s %s\n", line, pc+4); continue; } /* the rest of the entries should be valid paths */ sprintf(fn, "%s/%s", basedir, line); if (lstat(fn, &st)<0) continue; /* We skip this bad entry - (1) the header and tail lines (2) perhaps the file no longer exists */ /* is this a hardlink? */ if (st.st_nlink > 1) { int index; output_subs(line); if ((index = find_unit((unsigned int)st.st_ino, &ino_list))<0) { append_uint_list((unsigned int)st.st_ino, &ino_list); append_string_list(line, &file_list); /* relative path */ printf("%s\n", line); } else { printf("%s %s\n", line, file_list.str[index]); } continue; } /* all others */ output_subs(line); printf("%s\n", line); } /* end of one line */ fclose(fd); return 0; }