X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/cda2ae84b3b0f78387c5937094b4f5525c92fc19..f62c17e3786ac6643981d9ec68a1cd130ffcf149:/flist.c diff --git a/flist.c b/flist.c index b97c919e..1082c400 100644 --- a/flist.c +++ b/flist.c @@ -51,8 +51,60 @@ static char topsrcname[MAXPATHLEN]; static struct exclude_struct **local_exclude_list; +static struct file_struct null_file; + static void clean_flist(struct file_list *flist, int strip_root); +static struct string_area *string_area_new(int size) +{ + struct string_area *a; + + if (size <= 0) size = ARENA_SIZE; + a = malloc(sizeof(*a)); + if (!a) out_of_memory("string_area_new"); + a->current = a->base = malloc(size); + if (!a->current) out_of_memory("string_area_new buffer"); + a->end = a->base + size; + a->next = NULL; + + return a; +} + +static void string_area_free(struct string_area *a) +{ + struct string_area *next; + + for ( ; a ; a = next) { + next = a->next; + free(a->base); + } +} + +static char *string_area_malloc(struct string_area **ap, int size) +{ + char *p; + struct string_area *a; + + /* does the request fit into the current space? */ + a = *ap; + if (a->current + size >= a->end) { + /* no; get space, move new string_area to front of the list */ + a = string_area_new(size > ARENA_SIZE ? size : ARENA_SIZE); + a->next = *ap; + *ap = a; + } + + /* have space; do the "allocation." */ + p = a->current; + a->current += size; + return p; +} + +static char *string_area_strdup(struct string_area **ap, const char *src) +{ + char* dest = string_area_malloc(ap, strlen(src) + 1); + return strcpy(dest, src); +} static void list_file_entry(struct file_struct *f) { @@ -133,8 +185,6 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer) static int match_file_name(char *fname,STRUCT_STAT *st) { if (check_exclude(fname,local_exclude_list,st)) { - if (verbose > 2) - rprintf(FINFO,"excluding file %s\n",fname); return 0; } return 1; @@ -299,7 +349,11 @@ static void receive_file_entry(struct file_struct **fptr, memset((char *)file, 0, sizeof(*file)); (*fptr) = file; - if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry"); + if (l2 >= MAXPATHLEN-l1) { + rprintf(FERROR,"overflow: flags=0x%x l1=%d l2=%d lastname=%s\n", + flags, l1, l2, lastname); + overflow("receive_file_entry"); + } strlcpy(thisname,lastname,l1+1); read_sbuf(f,&thisname[l1],l2); @@ -409,7 +463,12 @@ static int skip_filesystem(char *fname, STRUCT_STAT *st) return (st2.st_dev != filesystem_dev); } -static struct file_struct *make_file(int f, char *fname) +#define STRDUP(ap, p) (ap ? string_area_strdup(ap, p) : strdup(p)) +#define MALLOC(ap, i) (ap ? string_area_malloc(ap, i) : malloc(i)) + +/* create a file_struct for a named file */ +struct file_struct *make_file(int f, char *fname, struct string_area **ap, + int noexcludes) { struct file_struct *file; STRUCT_STAT st; @@ -418,6 +477,7 @@ static struct file_struct *make_file(int f, char *fname) char cleaned_name[MAXPATHLEN]; char linkbuf[MAXPATHLEN]; extern int delete_excluded; + extern int module_id; strlcpy(cleaned_name, fname, MAXPATHLEN); cleaned_name[MAXPATHLEN-1] = 0; @@ -431,11 +491,14 @@ static struct file_struct *make_file(int f, char *fname) if (readlink_stat(fname,&st,linkbuf) != 0) { io_error = 1; - rprintf(FERROR,"%s: %s\n", + rprintf(FERROR,"readlink %s: %s\n", fname,strerror(errno)); return NULL; } + /* we use noexcludes from backup.c */ + if (noexcludes) goto skip_excludes; + if (S_ISDIR(st.st_mode) && !recurse) { rprintf(FINFO,"skipping directory %s\n",fname); return NULL; @@ -449,7 +512,13 @@ static struct file_struct *make_file(int f, char *fname) /* f is set to -1 when calculating deletion file list */ if (((f != -1) || !delete_excluded) && !match_file_name(fname,&st)) return NULL; - + + + if (lp_ignore_nonreadable(module_id) && access(fname, R_OK) != 0) + return NULL; + + skip_excludes: + if (verbose > 2) rprintf(FINFO,"make_file(%d,%s)\n",f,fname); @@ -466,11 +535,11 @@ static struct file_struct *make_file(int f, char *fname) file->dirname = strdup(fname); lastdir = file->dirname; } - file->basename = strdup(p+1); + file->basename = STRDUP(ap, p+1); *p = '/'; } else { file->dirname = NULL; - file->basename = strdup(fname); + file->basename = STRDUP(ap, fname); } file->modtime = st.st_mtime; @@ -486,12 +555,12 @@ static struct file_struct *make_file(int f, char *fname) #if SUPPORT_LINKS if (S_ISLNK(st.st_mode)) { - file->link = strdup(linkbuf); + file->link = STRDUP(ap, linkbuf); } #endif if (always_checksum) { - file->sum = (char *)malloc(MD4_SUM_LENGTH); + file->sum = (char *)MALLOC(ap, MD4_SUM_LENGTH); if (!file->sum) out_of_memory("md4 sum"); /* drat. we have to provide a null checksum for non-regular files in order to be compatible with earlier versions @@ -528,7 +597,7 @@ void send_file_name(int f,struct file_list *flist,char *fname, { struct file_struct *file; - file = make_file(f,fname); + file = make_file(f,fname, &flist->string_area, 0); if (!file) return; @@ -618,7 +687,6 @@ static void send_directory(int f,struct file_list *flist,char *dir) } - struct file_list *send_file_list(int f,int argc,char *argv[]) { int i,l; @@ -630,19 +698,14 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) if (verbose && recurse && !am_server && f != -1) { rprintf(FINFO,"building file list ... "); + if (verbose > 1) + rprintf(FINFO, "\n"); rflush(FINFO); } start_write = stats.total_written; - flist = (struct file_list *)malloc(sizeof(flist[0])); - if (!flist) out_of_memory("send_file_list"); - - flist->count=0; - flist->malloced = 1000; - flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])* - flist->malloced); - if (!flist->files) out_of_memory("send_file_list"); + flist = flist_new(); if (f != -1) { io_start_buffering(f); @@ -668,8 +731,10 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) } if (link_stat(fname,&st) != 0) { - io_error=1; - rprintf(FERROR,"%s : %s\n",fname,strerror(errno)); + if (f != -1) { + io_error=1; + rprintf(FERROR,"link_stat %s : %s\n",fname,strerror(errno)); + } continue; } @@ -737,8 +802,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) if (one_file_system) set_filesystem(fname); - if (!recurse || !send_included_file_names(f,flist)) - send_file_name(f,flist,fname,recurse,FLAG_DELETE); + send_file_name(f,flist,fname,recurse,FLAG_DELETE); if (olddir != NULL) { flist_dir = NULL; @@ -856,7 +920,8 @@ struct file_list *recv_file_list(int f) /* if protocol version is >= 17 then recv the io_error flag */ if (f != -1 && remote_version >= 17) { extern int module_id; - if (lp_ignore_errors(module_id)) { + extern int ignore_errors; + if (lp_ignore_errors(module_id) || ignore_errors) { read_int(f); } else { io_error |= read_int(f); @@ -922,16 +987,38 @@ int flist_find(struct file_list *flist,struct file_struct *f) /* * free up one file */ -static void free_file(struct file_struct *file) +void free_file(struct file_struct *file) { if (!file) return; if (file->basename) free(file->basename); if (file->link) free(file->link); if (file->sum) free(file->sum); - memset((char *)file, 0, sizeof(*file)); + *file = null_file; } +/* + * allocate a new file list + */ +struct file_list *flist_new() +{ + struct file_list *flist; + + flist = (struct file_list *)malloc(sizeof(flist[0])); + if (!flist) out_of_memory("send_file_list"); + + flist->count=0; + flist->malloced = 1000; + flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])* + flist->malloced); + if (!flist->files) out_of_memory("send_file_list"); +#if ARENA_SIZE > 0 + flist->string_area = string_area_new(0); +#else + flist->string_area = NULL; +#endif + return flist; +} /* * free up all elements in a flist */ @@ -939,11 +1026,14 @@ void flist_free(struct file_list *flist) { int i; for (i=1;icount;i++) { - free_file(flist->files[i]); + if (!flist->string_area) + free_file(flist->files[i]); free(flist->files[i]); } memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count); free(flist->files); + if (flist->string_area) + string_area_free(flist->string_area); memset((char *)flist, 0, sizeof(*flist)); free(flist); } @@ -972,7 +1062,13 @@ static void clean_flist(struct file_list *flist, int strip_root) if (verbose > 1 && !am_server) rprintf(FINFO,"removing duplicate name %s from file list %d\n", f_name(flist->files[i-1]),i-1); - free_file(flist->files[i]); + /* it's not great that the flist knows the semantics of the + * file memory usage, but i'd rather not add a flag byte + * to that struct. XXX can i use a bit in the flags field? */ + if (flist->string_area) + flist->files[i][0] = null_file; + else + free_file(flist->files[i]); } } @@ -999,12 +1095,12 @@ static void clean_flist(struct file_list *flist, int strip_root) if (verbose <= 3) return; for (i=0;icount;i++) { - rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n", + rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n", getpid(), i, NS(flist->files[i]->dirname), NS(flist->files[i]->basename), flist->files[i]->mode, - (int)flist->files[i]->length); + (double)flist->files[i]->length); } }