From 0e5665d3abcfad22b94727ba8a71ecb6a79b33b3 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Wed, 9 Nov 2005 19:39:46 +0000 Subject: [PATCH] Made recursively deleting extraneous directories more memory efficient by removing the need for a MAXPATHLEN buffer on the stack of delete_item(). --- generator.c | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/generator.c b/generator.c index 0f53891f..e645d21f 100644 --- a/generator.c +++ b/generator.c @@ -103,13 +103,18 @@ static int is_backup_file(char *fn) /* Delete a file or directory. If DEL_FORCE_RECURSE is set in the flags, or if * force_delete is set, this will delete recursively as long as DEL_NO_RECURSE - * is not set in the flags. */ + * is not set in the flags. + * + * Note that fname must point to a MAXPATHLEN buffer if the mode indicates it's + * a directory! (The buffer is used for recursion, but returned unchanged.) + */ static int delete_item(char *fname, int mode, int flags) { struct file_list *dirlist; - char buf[MAXPATHLEN]; int j, dlen, zap_dir, ok; + unsigned remainder; void *save_filters; + char *p; if (!S_ISDIR(mode)) { if (max_delete && ++deletion_count > max_delete) @@ -160,21 +165,29 @@ static int delete_item(char *fname, int mode, int flags) flags |= DEL_FORCE_RECURSE; /* mark subdir dels as not "in the way" */ deletion_count--; - dlen = strlcpy(buf, fname, MAXPATHLEN); - save_filters = push_local_filters(buf, dlen); + dlen = strlen(fname); + save_filters = push_local_filters(fname, dlen); + + dirlist = get_dirlist(fname, dlen, 0); + + p = fname + dlen; + if (dlen != 1 || *fname != '/') + *p++ = '/'; + remainder = MAXPATHLEN - (p - fname); - dirlist = get_dirlist(buf, dlen, 0); for (j = dirlist->count; j--; ) { struct file_struct *fp = dirlist->files[j]; if (fp->flags & FLAG_MOUNT_POINT) continue; - f_name_to(fp, buf); - delete_item(buf, fp->mode, flags & ~DEL_TERSE); + strlcpy(p, fp->basename, remainder); + delete_item(fname, fp->mode, flags & ~DEL_TERSE); } flist_free(dirlist); + fname[dlen] = '\0'; + pop_local_filters(save_filters); if (max_delete && ++deletion_count > max_delete) @@ -294,6 +307,8 @@ static void do_delete_pass(struct file_list *flist) delete_in_dir(flist, fbuf, file); } + //delete_in_dir(NULL, NULL, NULL); + if (do_progress && !am_server) rprintf(FINFO, " \r"); } @@ -593,6 +608,8 @@ static int phase = 0; * regular files that have changed, we try to find a basis file and then * start sending checksums. * + * When fname is non-null, it must point to a MAXPATHLEN buffer! + * * Note that f_out is set to -1 when doing final directory-permission and * modification-time repair. */ static void recv_generator(char *fname, struct file_struct *file, int ndx, @@ -1241,9 +1258,12 @@ void generate_files(int f_out, struct file_list *flist, char *local_name) if (!file->basename) continue; - recv_generator(local_name ? local_name : f_name_to(file, fbuf), - file, i, itemizing, maybe_PERMS_REPORT, code, - f_out); + if (local_name) + strlcpy(fbuf, local_name, sizeof fbuf); + else + f_name_to(file, fbuf); + recv_generator(fbuf, file, i, itemizing, maybe_PERMS_REPORT, + code, f_out); /* We need to ensure that any dirs we create have writeable * permissions during the time we are putting files within @@ -1292,9 +1312,12 @@ void generate_files(int f_out, struct file_list *flist, char *local_name) * to catch initial checksum errors */ while ((i = get_redo_num(itemizing, code)) != -1) { struct file_struct *file = flist->files[i]; - recv_generator(local_name ? local_name : f_name_to(file, fbuf), - file, i, itemizing, maybe_PERMS_REPORT, code, - f_out); + if (local_name) + strlcpy(fbuf, local_name, sizeof fbuf); + else + f_name_to(file, fbuf); + recv_generator(fbuf, file, i, itemizing, maybe_PERMS_REPORT, + code, f_out); } phase++; -- 2.34.1