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 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
00025 #include <iconv.h>
00026 #endif
00027 #if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
00028 #include <libcharset.h>
00029 #elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
00030 #include <langinfo.h>
00031 #endif
00032
00033 extern int verbose;
00034 extern int dry_run;
00035 extern int daemon_log_format_has_i;
00036 extern int preserve_acls;
00037 extern int preserve_xattrs;
00038 extern int preserve_perms;
00039 extern int preserve_executability;
00040 extern int preserve_times;
00041 extern int omit_dir_times;
00042 extern int am_root;
00043 extern int am_server;
00044 extern int am_sender;
00045 extern int am_generator;
00046 extern int am_starting_up;
00047 extern int allow_8bit_chars;
00048 extern int preserve_uid;
00049 extern int preserve_gid;
00050 extern int inplace;
00051 extern int keep_dirlinks;
00052 extern int make_backups;
00053 extern mode_t orig_umask;
00054 extern struct stats stats;
00055 extern struct chmod_mode_struct *daemon_chmod_modes;
00056
00057 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
00058 iconv_t ic_chck = (iconv_t)-1;
00059
00060 static const char *default_charset(void)
00061 {
00062 #if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
00063 return locale_charset();
00064 #elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
00065 return nl_langinfo(CODESET);
00066 #else
00067 return "";
00068 #endif
00069 }
00070
00071 void setup_iconv()
00072 {
00073 if (!am_server && !allow_8bit_chars) {
00074 const char *defset = default_charset();
00075
00076
00077 ic_chck = iconv_open(defset, defset);
00078
00079 if (verbose > 3) {
00080 if (ic_chck == (iconv_t)-1) {
00081 rprintf(FINFO,
00082 "note: iconv_open(\"%s\", \"%s\") failed (%d)"
00083 " -- using isprint() instead of iconv().\n",
00084 defset, defset, errno);
00085 } else {
00086 rprintf(FINFO,
00087 "note: iconv_open(\"%s\", \"%s\") succeeded.\n",
00088 defset, defset);
00089 }
00090 }
00091 }
00092 }
00093 #endif
00094
00095
00096
00097
00098 void free_sums(struct sum_struct *s)
00099 {
00100 if (s->sums) free(s->sums);
00101 free(s);
00102 }
00103
00104
00105
00106 mode_t dest_mode(mode_t flist_mode, mode_t cur_mode, int dflt_perms,
00107 int exists)
00108 {
00109
00110
00111 if (exists) {
00112 if (preserve_executability && S_ISREG(flist_mode)) {
00113
00114
00115
00116 if (!(flist_mode & 0111))
00117 cur_mode &= ~0111;
00118 else if (!(cur_mode & 0111))
00119 cur_mode |= (cur_mode & 0444) >> 2;
00120 }
00121 } else
00122 cur_mode = flist_mode & ACCESSPERMS & dflt_perms;
00123 if (daemon_chmod_modes && !S_ISLNK(flist_mode))
00124 cur_mode = tweak_mode(cur_mode, daemon_chmod_modes);
00125 return (flist_mode & ~CHMOD_BITS) | (cur_mode & CHMOD_BITS);
00126 }
00127
00128 int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
00129 int flags)
00130 {
00131 int updated = 0;
00132 STRUCT_STAT st2;
00133 int change_uid, change_gid;
00134
00135 if (!st) {
00136 if (dry_run)
00137 return 1;
00138 if (link_stat(fname, &st2, 0) < 0) {
00139 rsyserr(FERROR, errno, "stat %s failed",
00140 full_fname(fname));
00141 return 0;
00142 }
00143 st = &st2;
00144 if (!preserve_perms && S_ISDIR(file->mode)
00145 && st->st_mode & S_ISGID) {
00146
00147
00148 file->mode |= S_ISGID;
00149 }
00150 }
00151
00152 if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
00153 flags |= ATTRS_SKIP_MTIME;
00154 if (!(flags & ATTRS_SKIP_MTIME)
00155 && cmp_time(st->st_mtime, file->modtime) != 0) {
00156 int ret = set_modtime(fname, file->modtime, st->st_mode);
00157 if (ret < 0) {
00158 rsyserr(FERROR, errno, "failed to set times on %s",
00159 full_fname(fname));
00160 return 0;
00161 }
00162 if (ret == 0)
00163 updated = 1;
00164 }
00165
00166 change_uid = am_root && preserve_uid && st->st_uid != file->uid;
00167 change_gid = preserve_gid && file->gid != GID_NONE
00168 && st->st_gid != file->gid;
00169 #if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
00170 if (S_ISLNK(st->st_mode))
00171 ;
00172 else
00173 #endif
00174 if (change_uid || change_gid) {
00175 if (verbose > 2) {
00176 if (change_uid) {
00177 rprintf(FINFO,
00178 "set uid of %s from %ld to %ld\n",
00179 fname,
00180 (long)st->st_uid, (long)file->uid);
00181 }
00182 if (change_gid) {
00183 rprintf(FINFO,
00184 "set gid of %s from %ld to %ld\n",
00185 fname,
00186 (long)st->st_gid, (long)file->gid);
00187 }
00188 }
00189 if (do_lchown(fname,
00190 change_uid ? file->uid : st->st_uid,
00191 change_gid ? file->gid : st->st_gid) != 0) {
00192
00193
00194 rsyserr(FERROR, errno, "%s %s failed",
00195 change_uid ? "chown" : "chgrp",
00196 full_fname(fname));
00197 return 0;
00198 }
00199
00200
00201
00202 if (st->st_mode & (S_ISUID | S_ISGID)) {
00203 link_stat(fname, st,
00204 keep_dirlinks && S_ISDIR(st->st_mode));
00205 }
00206 updated = 1;
00207 }
00208
00209 #ifdef SUPPORT_ACLS
00210
00211
00212
00213
00214
00215
00216 if (preserve_acls && set_acl(fname, file, &st->st_mode) == 0)
00217 updated = 1;
00218 #endif
00219 #ifdef SUPPORT_XATTRS
00220 if (preserve_xattrs && set_xattr(fname, file) == 0)
00221 updated = 1;
00222 #endif
00223
00224 #ifdef HAVE_CHMOD
00225 if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
00226 int ret = do_chmod(fname, file->mode);
00227 if (ret < 0) {
00228 rsyserr(FERROR, errno,
00229 "failed to set permissions on %s",
00230 full_fname(fname));
00231 return 0;
00232 }
00233 if (ret == 0)
00234 updated = 1;
00235 }
00236 #endif
00237
00238 if (verbose > 1 && flags & ATTRS_REPORT) {
00239 enum logcode code = daemon_log_format_has_i || dry_run
00240 ? FCLIENT : FINFO;
00241 if (updated)
00242 rprintf(code, "%s\n", fname);
00243 else
00244 rprintf(code, "%s is uptodate\n", fname);
00245 }
00246 return updated;
00247 }
00248
00249 RETSIGTYPE sig_int(UNUSED(int val))
00250 {
00251
00252
00253
00254
00255
00256
00257
00258
00259 msleep(400);
00260 exit_cleanup(RERR_SIGNAL);
00261 }
00262
00263
00264
00265
00266
00267 void finish_transfer(char *fname, char *fnametmp, char *partialptr,
00268 struct file_struct *file, int ok_to_set_time,
00269 int overwriting_basis)
00270 {
00271 int ret;
00272
00273 if (inplace) {
00274 if (verbose > 2)
00275 rprintf(FINFO, "finishing %s\n", fname);
00276 fnametmp = fname;
00277 goto do_set_file_attrs;
00278 }
00279
00280 if (make_backups && overwriting_basis && !make_backup(fname))
00281 return;
00282
00283
00284 set_file_attrs(fnametmp, file, NULL,
00285 ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
00286
00287
00288 if (verbose > 2)
00289 rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
00290 ret = robust_rename(fnametmp, fname, partialptr,
00291 file->mode & INITACCESSPERMS);
00292 if (ret < 0) {
00293 rsyserr(FERROR, errno, "%s %s -> \"%s\"",
00294 ret == -2 ? "copy" : "rename",
00295 full_fname(fnametmp), fname);
00296 do_unlink(fnametmp);
00297 return;
00298 }
00299 if (ret == 0) {
00300
00301 return;
00302 }
00303
00304
00305 fnametmp = partialptr ? partialptr : fname;
00306
00307 do_set_file_attrs:
00308 set_file_attrs(fnametmp, file, NULL,
00309 ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
00310
00311 if (partialptr) {
00312 if (do_rename(fnametmp, fname) < 0) {
00313 rsyserr(FERROR, errno, "rename %s -> \"%s\"",
00314 full_fname(fnametmp), fname);
00315 } else
00316 handle_partial_dir(partialptr, PDIR_DELETE);
00317 }
00318 }
00319
00320 const char *who_am_i(void)
00321 {
00322 if (am_starting_up)
00323 return am_server ? "server" : "client";
00324 return am_sender ? "sender" : am_generator ? "generator" : "receiver";
00325 }