X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/72914a606ec66f61678c6d077e515f08908e76a3..1e8ae5ede66ba337ba6abbb4afad2b3319c1db74:/flist.c diff --git a/flist.c b/flist.c index c33323ed..caca010f 100644 --- a/flist.c +++ b/flist.c @@ -49,6 +49,38 @@ extern int io_error; static struct exclude_struct **local_exclude_list; +static void clean_flist(struct file_list *flist, int strip_root); + + +static void list_file_entry(struct file_struct *f) +{ + char perms[11] = "----------"; + char *perm_map = "rwxrwxrwx"; + int i; + + for (i=0;i<9;i++) { + if (f->mode & (1<mode)) perms[0] = 'l'; + if (S_ISDIR(f->mode)) perms[0] = 'd'; + if (S_ISBLK(f->mode)) perms[0] = 'b'; + if (S_ISCHR(f->mode)) perms[0] = 'c'; + if (S_ISSOCK(f->mode)) perms[0] = 's'; + if (S_ISFIFO(f->mode)) perms[0] = 'p'; + + if (preserve_links && S_ISLNK(f->mode)) { + rprintf(FINFO,"%s %11.0f %s %s -> %s\n", + perms, + (double)f->length, timestring(f->modtime), + f_name(f), f->link); + } else { + rprintf(FINFO,"%s %11.0f %s %s\n", + perms, + (double)f->length, timestring(f->modtime), f_name(f)); + } +} + + int link_stat(const char *Path, STRUCT_STAT *Buffer) { #if SUPPORT_LINKS @@ -87,12 +119,29 @@ static void set_filesystem(char *fname) } +static int to_wire_mode(mode_t mode) +{ + if (S_ISLNK(mode) && (S_IFLNK != 0120000)) { + return (mode & ~(_S_IFMT)) | 0120000; + } + return (int)mode; +} + +static mode_t from_wire_mode(int mode) +{ + if ((mode & (_S_IFMT)) == 0120000 && (S_IFLNK != 0120000)) { + return (mode & ~(_S_IFMT)) | S_IFLNK; + } + return (mode_t)mode; +} + + static void send_directory(int f,struct file_list *flist,char *dir); static char *flist_dir; -void send_file_entry(struct file_struct *file,int f,unsigned base_flags) +static void send_file_entry(struct file_struct *file,int f,unsigned base_flags) { unsigned char flags; static time_t last_time; @@ -145,7 +194,7 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags) if (!(flags & SAME_TIME)) write_int(f,(int)file->modtime); if (!(flags & SAME_MODE)) - write_int(f,(int)file->mode); + write_int(f,to_wire_mode(file->mode)); if (preserve_uid && !(flags & SAME_UID)) { add_uid(file->uid); write_int(f,(int)file->uid); @@ -181,7 +230,7 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags) last_gid = file->gid; last_time = file->modtime; - strlcpy(lastname,fname,MAXPATHLEN-1); + strlcpy(lastname,fname,MAXPATHLEN); lastname[MAXPATHLEN-1] = 0; } @@ -216,21 +265,15 @@ static void receive_file_entry(struct file_struct **fptr, if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry"); - strlcpy(thisname,lastname,l1); + strlcpy(thisname,lastname,l1+1); read_sbuf(f,&thisname[l1],l2); thisname[l1+l2] = 0; - strlcpy(lastname,thisname,MAXPATHLEN-1); + strlcpy(lastname,thisname,MAXPATHLEN); lastname[MAXPATHLEN-1] = 0; clean_fname(thisname); - if (relative_paths && thisname[0] == '/') { - /* strip / off absolute paths in destination */ - memmove(thisname, thisname+1, strlen(thisname)); - if (!thisname[0]) strcpy(thisname,"."); - } - if ((p = strrchr(thisname,'/'))) { static char *lastdir; *p = 0; @@ -252,7 +295,7 @@ static void receive_file_entry(struct file_struct **fptr, file->flags = flags; file->length = read_longint(f); file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f); - file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f); + file->mode = (flags & SAME_MODE) ? last_mode : from_wire_mode(read_int(f)); if (preserve_uid) file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f); if (preserve_gid) @@ -327,7 +370,7 @@ static struct file_struct *make_file(char *fname) char *p; char cleaned_name[MAXPATHLEN]; - strlcpy(cleaned_name, fname, MAXPATHLEN-1); + strlcpy(cleaned_name, fname, MAXPATHLEN); cleaned_name[MAXPATHLEN-1] = 0; clean_fname(cleaned_name); fname = cleaned_name; @@ -436,7 +479,7 @@ static struct file_struct *make_file(char *fname) -static void send_file_name(int f,struct file_list *flist,char *fname, +void send_file_name(int f,struct file_list *flist,char *fname, int recursive, unsigned base_flags) { struct file_struct *file; @@ -488,7 +531,7 @@ static void send_directory(int f,struct file_list *flist,char *dir) return; } - strlcpy(fname,dir,MAXPATHLEN-1); + strlcpy(fname,dir,MAXPATHLEN); l = strlen(fname); if (fname[l-1] != '/') { if (l == MAXPATHLEN-1) { @@ -497,11 +540,13 @@ static void send_directory(int f,struct file_list *flist,char *dir) closedir(d); return; } - strlcat(fname,"/", MAXPATHLEN-1); + strlcat(fname,"/", MAXPATHLEN); l++; } p = fname + strlen(fname); + local_exclude_list = NULL; + if (cvs_exclude) { if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) { strcpy(p,".cvsignore"); @@ -517,10 +562,14 @@ static void send_directory(int f,struct file_list *flist,char *dir) if (strcmp(dname,".")==0 || strcmp(dname,"..")==0) continue; - strlcpy(p,dname,MAXPATHLEN-(l+1)); + strlcpy(p,dname,MAXPATHLEN-l); send_file_name(f,flist,fname,recurse,0); } + if (local_exclude_list) { + add_exclude_list("!", &local_exclude_list, 0); + } + closedir(d); } @@ -530,7 +579,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) { int i,l; STRUCT_STAT st; - char *p,*dir; + char *p,*dir,*olddir; char lastpath[MAXPATHLEN]=""; struct file_list *flist; int64 start_write; @@ -559,11 +608,11 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) char fname2[MAXPATHLEN]; char *fname = fname2; - strlcpy(fname,argv[i],MAXPATHLEN-1); + strlcpy(fname,argv[i],MAXPATHLEN); l = strlen(fname); if (l != 1 && fname[l-1] == '/') { - strlcat(fname,".",MAXPATHLEN-1); + strlcat(fname,".",MAXPATHLEN); } if (link_stat(fname,&st) != 0) { @@ -578,6 +627,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) } dir = NULL; + olddir = NULL; if (!relative_paths) { p = strrchr(fname,'/'); @@ -594,7 +644,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) thus getting their permissions right */ *p = 0; if (strcmp(lastpath,fname)) { - strlcpy(lastpath, fname, sizeof(lastpath)-1); + strlcpy(lastpath, fname, sizeof(lastpath)); *p = '/'; for (p=fname+1; (p=strchr(p,'/')); p++) { int copy_links_saved = copy_links; @@ -613,7 +663,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) fname = "."; if (dir && *dir) { - char *olddir = push_dir(dir, 1); + olddir = push_dir(dir, 1); if (!olddir) { io_error=1; @@ -623,21 +673,22 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) } flist_dir = dir; - if (one_file_system) - set_filesystem(fname); + } + + if (one_file_system) + set_filesystem(fname); + + if (!recurse || !send_included_file_names(f,flist)) send_file_name(f,flist,fname,recurse,FLAG_DELETE); + + if (olddir != NULL) { flist_dir = NULL; if (pop_dir(olddir) != 0) { rprintf(FERROR,"pop_dir %s : %s\n", dir,strerror(errno)); - exit_cleanup(1); + exit_cleanup(RERR_FILESELECT); } - continue; } - - if (one_file_system) - set_filesystem(fname); - send_file_name(f,flist,fname,recurse,FLAG_DELETE); } if (f != -1) { @@ -647,7 +698,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[]) if (verbose && recurse && !am_server && f != -1) rprintf(FINFO,"done\n"); - clean_flist(flist); + clean_flist(flist, 0); /* now send the uid/gid list. This was introduced in protocol version 15 */ @@ -678,6 +729,7 @@ struct file_list *recv_file_list(int f) struct file_list *flist; unsigned char flags; int64 start_read; + extern int list_only; if (verbose && recurse && !am_server) { rprintf(FINFO,"receiving file list ... "); @@ -728,7 +780,7 @@ struct file_list *recv_file_list(int f) if (verbose > 2) rprintf(FINFO,"received %d names\n",flist->count); - clean_flist(flist); + clean_flist(flist, relative_paths); if (verbose && recurse && !am_server) { rprintf(FINFO,"done\n"); @@ -744,6 +796,14 @@ struct file_list *recv_file_list(int f) io_error |= read_int(f); } + if (list_only) { + int i; + for (i=0;icount;i++) { + list_file_entry(flist->files[i]); + } + } + + if (verbose > 2) rprintf(FINFO,"recv_file_list done\n"); @@ -826,7 +886,7 @@ void flist_free(struct file_list *flist) * This routine ensures we don't have any duplicate names in our file list. * duplicate names can cause corruption because of the pipelining */ -void clean_flist(struct file_list *flist) +static void clean_flist(struct file_list *flist, int strip_root) { int i; @@ -848,6 +908,37 @@ void clean_flist(struct file_list *flist) free_file(flist->files[i]); } } + + if (strip_root) { + /* we need to strip off the root directory in the case + of relative paths, but this must be done _after_ + the sorting phase */ + for (i=0;icount;i++) { + if (flist->files[i]->dirname && + flist->files[i]->dirname[0] == '/') { + memmove(&flist->files[i]->dirname[0], + &flist->files[i]->dirname[1], + strlen(flist->files[i]->dirname)); + } + + if (flist->files[i]->dirname && + !flist->files[i]->dirname[0]) { + flist->files[i]->dirname = NULL; + } + } + } + + + if (verbose <= 3) return; + + for (i=0;icount;i++) { + rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n", + getpid(), i, + NS(flist->files[i]->dirname), + NS(flist->files[i]->basename), + flist->files[i]->mode, + (int)flist->files[i]->length); + } } @@ -865,9 +956,11 @@ char *f_name(struct file_struct *f) n = (n+1)%10; if (f->dirname) { - slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename); + strlcpy(p, f->dirname, MAXPATHLEN); + strlcat(p, "/", MAXPATHLEN); + strlcat(p, f->basename, MAXPATHLEN); } else { - strlcpy(p, f->basename, MAXPATHLEN-1); + strlcpy(p, f->basename, MAXPATHLEN); } return p;