/**************************************************************************** Create a directory given an absolute path, perms based upon another directory path ****************************************************************************/ static int make_bak_dir(char *fname,char *bak_path) { STRUCT_STAT st; STRUCT_STAT *st2; char fullpath[MAXPATHLEN]; extern int orig_umask; char *p; char *q; while(strncmp(bak_path,"./",2)==0) bak_path += 2; if(bak_path[strlen(bak_path)-1]!='/') { snprintf(fullpath,sizeof(fullpath),"%s/",bak_path); } else { snprintf(fullpath,sizeof(fullpath),"%s",bak_path); } p=fullpath; q=&fullpath[strlen(fullpath)]; /* End of bak_path string */ strcat(fullpath,fname); /* Make the directories */ while ((p=strchr(p,'/'))) { *p = 0; if(do_lstat(fullpath,&st)!=0) { do_mkdir(fullpath,0777 & ~orig_umask); if(p>q) { if(do_lstat(q,&st)!=0) { rprintf(FERROR,"make_bak_dir stat %s : %s\n",fullpath,strerror(errno)); } else { st2=&st; set_modtime(fullpath,st2->st_mtime); if(do_lchown(fullpath,st2->st_uid,st2->st_gid)!=0) { rprintf(FERROR,"make_bak_dir chown %s : %s\n",fullpath,strerror(errno)); }; if(do_chmod(fullpath,st2->st_mode)!=0) { rprintf(FERROR,"make_bak_dir failed to set permissions on %s : %s\n",fullpath,strerror(errno)); }; }; } }; *p = '/'; p++; } return 0; }
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st, int report) { int updated = 0; STRUCT_STAT st2; int change_uid, change_gid; extern int am_daemon; if (dry_run) return 0; if (!st) { if (link_stat(fname,&st2) != 0) { rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno)); return 0; } st = &st2; } if (preserve_times && !S_ISLNK(st->st_mode) && st->st_mtime != file->modtime) { /* don't complain about not setting times on directories because some filesystems can't do it */ if (set_modtime(fname,file->modtime) != 0 && !S_ISDIR(st->st_mode)) { rprintf(FERROR,"failed to set times on %s : %s\n", fname,strerror(errno)); return 0; } else { updated = 1; } } change_uid = am_root && preserve_uid && st->st_uid != file->uid; change_gid = !am_daemon && preserve_gid && file->gid != (gid_t) -1 && \ st->st_gid != file->gid; if (change_gid && !am_root) { /* enforce bsd-style group semantics: non-root can only change to groups that the user is a member of */ change_gid = is_in_group(file->gid); } if (change_uid || change_gid) { if (do_lchown(fname, change_uid?file->uid:st->st_uid, change_gid?file->gid:st->st_gid) != 0) { /* shouldn't have attempted to change uid or gid unless have the privilege */ rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno)); return 0; } updated = 1; } #ifdef HAVE_CHMOD if (!S_ISLNK(st->st_mode)) { int file_mode; if (preserve_perms) file_mode = file->mode; else file_mode = file->mode & ACCESSPERMS; if (st->st_mode != file->mode) { updated = 1; if (do_chmod(fname,file_mode) != 0) { rprintf(FERROR,"failed to set permissions on %s : %s\n", fname,strerror(errno)); return 0; } } } #endif if (verbose > 1 && report) { if (updated) rprintf(FINFO,"%s\n",fname); else rprintf(FINFO,"%s is uptodate\n",fname); } return updated; }
/**************************************************************************** Create a directory given an absolute path, perms based upon another directory path ****************************************************************************/ static int make_bak_dir(char *fullpath) { STRUCT_STAT st; char *rel = fullpath + backup_dir_len; char *end = rel + strlen(rel); char *p = end; while (strncmp(fullpath, "./", 2) == 0) fullpath += 2; /* Try to find an existing dir, starting from the deepest dir. */ while (1) { if (--p == fullpath) { p += strlen(p); goto failure; } if (*p == '/') { *p = '\0'; if (mkdir_defmode(fullpath) == 0) break; if (errno != ENOENT) { rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed", full_fname(fullpath)); goto failure; } } } /* Make all the dirs that we didn't find on the way here. */ while (1) { if (p >= rel) { /* Try to transfer the directory settings of the * actual dir that the files are coming from. */ if (do_stat(rel, &st) < 0) { rsyserr(FERROR, errno, "make_bak_dir stat %s failed", full_fname(rel)); } else { do_lchown(fullpath, st.st_uid, st.st_gid); #ifdef HAVE_CHMOD do_chmod(fullpath, st.st_mode); #endif } } *p = '/'; p += strlen(p); if (p == end) break; if (mkdir_defmode(fullpath) < 0) { rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed", full_fname(fullpath)); goto failure; } } return 0; failure: while (p != end) { *p = '/'; p += strlen(p); } return -1; }