00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "rsync.h"
00024
00025 extern int verbose;
00026 extern int dry_run;
00027 extern int preserve_times;
00028 extern int am_root;
00029 extern int preserve_uid;
00030 extern int preserve_gid;
00031 extern int preserve_perms;
00032 extern int make_backups;
00033
00034
00035
00036
00037
00038 void free_sums(struct sum_struct *s)
00039 {
00040 if (s->sums) free(s->sums);
00041 free(s);
00042 }
00043
00044
00045
00046
00047
00048
00049 int delete_file(char *fname)
00050 {
00051 DIR *d;
00052 struct dirent *di;
00053 char buf[MAXPATHLEN];
00054 extern int force_delete;
00055 STRUCT_STAT st;
00056 int ret;
00057 extern int recurse;
00058
00059 #if SUPPORT_LINKS
00060 ret = do_lstat(fname, &st);
00061 #else
00062 ret = do_stat(fname, &st);
00063 #endif
00064 if (ret) {
00065 return -1;
00066 }
00067
00068 if (!S_ISDIR(st.st_mode)) {
00069 if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
00070 rprintf(FERROR,"delete_file: unlink(%s) : %s\n", fname, strerror(errno));
00071 return -1;
00072 }
00073
00074 if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
00075 if (!force_delete || !recurse ||
00076 (errno != ENOTEMPTY && errno != EEXIST)) {
00077 rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
00078 return -1;
00079 }
00080
00081
00082 d = opendir(fname);
00083 if (!d) {
00084 rprintf(FERROR,"delete_file: opendir(%s): %s\n",
00085 fname,strerror(errno));
00086 return -1;
00087 }
00088
00089 for (di=readdir(d); di; di=readdir(d)) {
00090 char *dname = d_name(di);
00091 if (strcmp(dname,".")==0 ||
00092 strcmp(dname,"..")==0)
00093 continue;
00094 snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
00095 if (verbose > 0)
00096 rprintf(FINFO,"deleting %s\n", buf);
00097 if (delete_file(buf) != 0) {
00098 closedir(d);
00099 return -1;
00100 }
00101 }
00102
00103 closedir(d);
00104
00105 if (do_rmdir(fname) != 0) {
00106 rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
00107 return -1;
00108 }
00109
00110 return 0;
00111 }
00112
00113 static int is_in_group(gid_t gid)
00114 {
00115 #ifdef GETGROUPS_T
00116 static gid_t last_in = (gid_t) -2, last_out;
00117 static int ngroups = -2;
00118 static GETGROUPS_T *gidset;
00119 int n;
00120
00121 if (gid == last_in)
00122 return last_out;
00123 if (ngroups < -1) {
00124
00125 ngroups = getgroups(0, 0);
00126 if (ngroups > 0) {
00127 gidset = (GETGROUPS_T *) malloc(ngroups * sizeof(GETGROUPS_T));
00128 ngroups = getgroups(ngroups, gidset);
00129 }
00130 }
00131
00132 last_in = gid;
00133 last_out = 0;
00134 for (n = 0; n < ngroups; n++) {
00135 if (gidset[n] == gid) {
00136 last_out = 1;
00137 break;
00138 }
00139 }
00140 return last_out;
00141
00142 #else
00143 return 0;
00144 #endif
00145 }
00146
00147 int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
00148 int report)
00149 {
00150 int updated = 0;
00151 STRUCT_STAT st2;
00152 int change_uid, change_gid;
00153
00154 if (dry_run) return 0;
00155
00156 if (!st) {
00157 if (link_stat(fname,&st2) != 0) {
00158 rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
00159 return 0;
00160 }
00161 st = &st2;
00162 }
00163
00164 if (preserve_times && !S_ISLNK(st->st_mode) &&
00165 cmp_modtime(st->st_mtime, file->modtime) != 0) {
00166
00167
00168 if (set_modtime(fname,file->modtime) != 0 &&
00169 !S_ISDIR(st->st_mode)) {
00170 rprintf(FERROR,"failed to set times on %s : %s\n",
00171 fname,strerror(errno));
00172 return 0;
00173 } else {
00174 updated = 1;
00175 }
00176 }
00177
00178 change_uid = am_root && preserve_uid && st->st_uid != file->uid;
00179 change_gid = preserve_gid && file->gid != (gid_t) -1 && \
00180 st->st_gid != file->gid;
00181 if (change_gid && !am_root) {
00182
00183
00184 change_gid = is_in_group(file->gid);
00185 }
00186 if (change_uid || change_gid) {
00187 if (do_lchown(fname,
00188 change_uid?file->uid:st->st_uid,
00189 change_gid?file->gid:st->st_gid) != 0) {
00190
00191
00192 rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno));
00193 return 0;
00194 }
00195
00196
00197
00198 if (st->st_mode & (S_ISUID | S_ISGID)) {
00199 link_stat(fname, st);
00200 }
00201 updated = 1;
00202 }
00203
00204 #ifdef HAVE_CHMOD
00205 if (!S_ISLNK(st->st_mode)) {
00206 if (st->st_mode != file->mode) {
00207 updated = 1;
00208 if (do_chmod(fname,file->mode) != 0) {
00209 rprintf(FERROR,"failed to set permissions on %s : %s\n",
00210 fname,strerror(errno));
00211 return 0;
00212 }
00213 }
00214 }
00215 #endif
00216
00217 if (verbose > 1 && report) {
00218 if (updated)
00219 rprintf(FINFO,"%s\n",fname);
00220 else
00221 rprintf(FINFO,"%s is uptodate\n",fname);
00222 }
00223 return updated;
00224 }
00225
00226
00227 void sig_int(void)
00228 {
00229 exit_cleanup(RERR_SIGNAL);
00230 }
00231
00232
00233
00234
00235 void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
00236 {
00237 if (make_backups && !make_backup(fname))
00238 return;
00239
00240
00241 if (robust_rename(fnametmp,fname) != 0) {
00242 if (errno == EXDEV) {
00243
00244
00245 if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
00246 rprintf(FERROR,"copy %s -> %s : %s\n",
00247 fnametmp,fname,strerror(errno));
00248 } else {
00249 set_perms(fname,file,NULL,0);
00250 }
00251 } else {
00252 rprintf(FERROR,"rename %s -> %s : %s\n",
00253 fnametmp,fname,strerror(errno));
00254 }
00255 do_unlink(fnametmp);
00256 } else {
00257 set_perms(fname,file,NULL,0);
00258 }
00259 }