Diff for /embedaddon/rsync/rsync.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2016/11/01 09:54:32 version 1.1.1.4, 2021/03/17 00:32:36
Line 3 Line 3
  *   *
  * Copyright (C) 1996 Andrew Tridgell   * Copyright (C) 1996 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras   * Copyright (C) 1996 Paul Mackerras
 * Copyright (C) 2003-2015 Wayne Davison * Copyright (C) 2003-2020 Wayne Davison
  *   *
  * This program is free software; you can redistribute it and/or modify   * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
Line 31  extern int dry_run; Line 31  extern int dry_run;
 extern int preserve_acls;  extern int preserve_acls;
 extern int preserve_xattrs;  extern int preserve_xattrs;
 extern int preserve_perms;  extern int preserve_perms;
   extern int preserve_fileflags;
 extern int preserve_executability;  extern int preserve_executability;
 extern int preserve_times;  extern int preserve_times;
   extern int copy_devices;
 extern int am_root;  extern int am_root;
 extern int am_server;  extern int am_server;
 extern int am_daemon;  extern int am_daemon;
 extern int am_sender;  extern int am_sender;
 extern int am_receiver;  extern int am_receiver;
 extern int am_generator;  extern int am_generator;
   extern int am_dbadmin;
 extern int am_starting_up;  extern int am_starting_up;
 extern int allow_8bit_chars;  extern int allow_8bit_chars;
 extern int protocol_version;  extern int protocol_version;
 extern int got_kill_signal;  extern int got_kill_signal;
   extern int called_from_signal_handler;
 extern int inc_recurse;  extern int inc_recurse;
 extern int inplace;  extern int inplace;
 extern int flist_eof;  extern int flist_eof;
 extern int file_old_total;  extern int file_old_total;
 extern int keep_dirlinks;  extern int keep_dirlinks;
 extern int make_backups;  extern int make_backups;
   extern char *link_by_hash_dir;
   extern int sanitize_paths;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;  extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct chmod_mode_struct *daemon_chmod_modes;  extern struct chmod_mode_struct *daemon_chmod_modes;
 #ifdef ICONV_OPTION  #ifdef ICONV_OPTION
 extern char *iconv_opt;  extern char *iconv_opt;
 #endif  #endif
   
   #define UPDATED_OWNER (1<<0)
   #define UPDATED_GROUP (1<<1)
   #define UPDATED_MTIME (1<<2)
   #define UPDATED_ATIME (1<<3)
   #define UPDATED_ACLS  (1<<4)
   #define UPDATED_MODE  (1<<5)
   
   #define UPDATED_TIMES (UPDATED_MTIME|UPDATED_ATIME)
   
 #ifdef ICONV_CONST  #ifdef ICONV_CONST
 iconv_t ic_chck = (iconv_t)-1;  iconv_t ic_chck = (iconv_t)-1;
 # ifdef ICONV_OPTION  # ifdef ICONV_OPTION
Line 307  void send_protected_args(int fd, char *args[]) Line 322  void send_protected_args(int fd, char *args[])
 #endif  #endif
 }  }
   
int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr,int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr, char *buf, int *len_ptr)
                       char *buf, int *len_ptr) 
 {  {
         int len, iflags = 0;          int len, iflags = 0;
         struct file_list *flist;          struct file_list *flist;
Line 396  int read_ndx_and_attrs(int f_in, int f_out, int *iflag Line 410  int read_ndx_and_attrs(int f_in, int f_out, int *iflag
         if (iflags & ITEM_XNAME_FOLLOWS) {          if (iflags & ITEM_XNAME_FOLLOWS) {
                 if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)                  if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
                         exit_cleanup(RERR_PROTOCOL);                          exit_cleanup(RERR_PROTOCOL);
   
                   if (sanitize_paths) {
                           sanitize_path(buf, buf, "", 0, SP_DEFAULT);
                           len = strlen(buf);
                   }
         } else {          } else {
                 *buf = '\0';                  *buf = '\0';
                 len = -1;                  len = -1;
Line 404  int read_ndx_and_attrs(int f_in, int f_out, int *iflag Line 423  int read_ndx_and_attrs(int f_in, int f_out, int *iflag
   
         if (iflags & ITEM_TRANSFER) {          if (iflags & ITEM_TRANSFER) {
                 int i = ndx - cur_flist->ndx_start;                  int i = ndx - cur_flist->ndx_start;
                if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {                struct file_struct *file = cur_flist->files[i];
                 if (i < 0 || !(S_ISREG(file->mode) || (copy_devices && IS_DEVICE(file->mode)))) {
                         rprintf(FERROR,                          rprintf(FERROR,
                                 "received request to transfer non-regular file: %d [%s]\n",                                  "received request to transfer non-regular file: %d [%s]\n",
                                 ndx, who_am_i());                                  ndx, who_am_i());
Line 452  mode_t dest_mode(mode_t flist_mode, mode_t stat_mode,  Line 472  mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, 
         return new_mode;          return new_mode;
 }  }
   
   #if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
   /* Set a file's st_flags. */
   static int set_fileflags(const char *fname, uint32 fileflags)
   {
           if (do_chflags(fname, fileflags) != 0) {
                   rsyserr(FERROR_XFER, errno,
                           "failed to set file flags on %s",
                           full_fname(fname));
                   return 0;
           }
   
           return 1;
   }
   
   /* Remove immutable flags from an object, so it can be altered/removed. */
   int make_mutable(const char *fname, mode_t mode, uint32 fileflags, uint32 iflags)
   {
           if (S_ISLNK(mode) || !(fileflags & iflags))
                   return 0;
           if (!set_fileflags(fname, fileflags & ~iflags))
                   return -1;
           return 1;
   }
   
   /* Undo a prior make_mutable() call that returned a 1. */
   int undo_make_mutable(const char *fname, uint32 fileflags)
   {
           if (!set_fileflags(fname, fileflags))
                   return -1;
           return 1;
   }
   #endif
   
   static int same_mtime(struct file_struct *file, STRUCT_STAT *st, int extra_accuracy)
   {
   #ifdef ST_MTIME_NSEC
           uint32 f1_nsec = F_MOD_NSEC_or_0(file);
           uint32 f2_nsec = (uint32)st->ST_MTIME_NSEC;
   #else
           uint32 f1_nsec = 0, f2_nsec = 0;
   #endif
   
           if (extra_accuracy) /* ignore modify_window when setting the time after a transfer or checksum check */
                   return file->modtime == st->st_mtime && f1_nsec == f2_nsec;
   
           return same_time(file->modtime, f1_nsec, st->st_mtime , f2_nsec);
   }
   
 int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,  int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                    const char *fnamecmp, int flags)                     const char *fnamecmp, int flags)
 {  {
Line 489  int set_file_attrs(const char *fname, struct file_stru Line 557  int set_file_attrs(const char *fname, struct file_stru
                 get_acl(fname, sxp);                  get_acl(fname, sxp);
 #endif  #endif
   
        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file)
                   && !(omit_dir_changes && S_ISDIR(sxp->st.st_mode));
         change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)          change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
                  && sxp->st.st_gid != (gid_t)F_GROUP(file);                  && sxp->st.st_gid != (gid_t)F_GROUP(file)
                   && !(omit_dir_changes && S_ISDIR(sxp->st.st_mode));
 #ifndef CAN_CHOWN_SYMLINK  #ifndef CAN_CHOWN_SYMLINK
         if (S_ISLNK(sxp->st.st_mode)) {          if (S_ISLNK(sxp->st.st_mode)) {
                 ;                  ;
Line 513  int set_file_attrs(const char *fname, struct file_stru Line 583  int set_file_attrs(const char *fname, struct file_stru
                 if (am_root >= 0) {                  if (am_root >= 0) {
                         uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;                          uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
                         gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;                          gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
                        if (do_lchown(fname, uid, gid) != 0) {                        if (do_lchown(fname, uid, gid, sxp->st.st_mode, ST_FLAGS(sxp->st)) != 0) {
                                 /* We shouldn't have attempted to change uid                                  /* We shouldn't have attempted to change uid
                                  * or gid unless have the privilege. */                                   * or gid unless have the privilege. */
                                 rsyserr(FERROR_XFER, errno, "%s %s failed",                                  rsyserr(FERROR_XFER, errno, "%s %s failed",
                                    change_uid ? "chown" : "chgrp",                                        change_uid ? "chown" : "chgrp",
                                    full_fname(fname));                                        full_fname(fname));
                                 goto cleanup;                                  goto cleanup;
                         }                          }
                         if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)                          if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
Line 533  int set_file_attrs(const char *fname, struct file_stru Line 603  int set_file_attrs(const char *fname, struct file_stru
                                           keep_dirlinks && S_ISDIR(sxp->st.st_mode));                                            keep_dirlinks && S_ISDIR(sxp->st.st_mode));
                         }                          }
                 }                  }
                updated = 1;                if (change_uid)
                         updated |= UPDATED_OWNER;
                 if (change_gid)
                         updated |= UPDATED_GROUP;
         }          }
   
 #ifdef SUPPORT_XATTRS  #ifdef SUPPORT_XATTRS
         if (am_root < 0)          if (am_root < 0)
                 set_stat_xattr(fname, file, new_mode);                  set_stat_xattr(fname, file, new_mode);
        if (preserve_xattrs && fnamecmp)        if (preserve_xattrs && fnamecmp) {
                 uint32 tmpflags = sxp->st.st_flags;
                 sxp->st.st_flags = F_FFLAGS(file); /* set_xattr() needs to check UF_COMPRESSED */
                 set_xattr(fname, file, fnamecmp, sxp);                  set_xattr(fname, file, fnamecmp, sxp);
                   sxp->st.st_flags = tmpflags;
                   if (S_ISDIR(sxp->st.st_mode))
                           link_stat(fname, &sx2.st, 0);
           }
 #endif  #endif
   
         if (!preserve_times          if (!preserve_times
          || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))           || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
          || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))           || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
                flags |= ATTRS_SKIP_MTIME;                flags |= ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME;
         else if (sxp != &sx2)
                 memcpy(&sx2.st, &sxp->st, sizeof (sx2.st));
         if (!atimes_ndx || S_ISDIR(sxp->st.st_mode))
                 flags |= ATTRS_SKIP_ATIME;
         /* Don't set the creation date on the root folder of an HFS+ volume. */
         if (sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode))
                 flags |= ATTRS_SKIP_CRTIME;
         if (!(flags & ATTRS_SKIP_MTIME)          if (!(flags & ATTRS_SKIP_MTIME)
         && (sxp->st.st_mtime != file->modtime#ifdef SUPPORT_HFS_COMPRESSION
          && !(sxp->st.st_flags & UF_COMPRESSED) /* setting this alters mtime, so defer to after set_fileflags */
 #endif
          && !same_mtime(file, &sxp->st, flags & ATTRS_ACCURATE_TIME)) {
                 sx2.st.st_mtime = file->modtime;
 #ifdef ST_MTIME_NSEC  #ifdef ST_MTIME_NSEC
          || (NSEC_BUMP(file) && (uint32)sxp->st.ST_MTIME_NSEC != F_MOD_NSEC(file))                sx2.st.ST_MTIME_NSEC = F_MOD_NSEC_or_0(file);
 #endif  #endif
          )) {                updated |= UPDATED_MTIME;
                int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);        }
         if (!(flags & ATTRS_SKIP_ATIME)) {
                 time_t file_atime = F_ATIME(file);
                 if (flags & ATTRS_ACCURATE_TIME || !same_time(sxp->st.st_atime, 0, file_atime, 0)) {
                         sx2.st.st_atime = file_atime;
 #ifdef ST_ATIME_NSEC
                         sx2.st.ST_ATIME_NSEC = 0;
 #endif
                         updated |= UPDATED_ATIME;
                 }
         }
         if (updated & UPDATED_TIMES) {
                 int ret = set_times(fname, &sx2.st);
                 if (ret < 0) {                  if (ret < 0) {
                         rsyserr(FERROR_XFER, errno, "failed to set times on %s",                          rsyserr(FERROR_XFER, errno, "failed to set times on %s",
                                 full_fname(fname));                                  full_fname(fname));
                         goto cleanup;                          goto cleanup;
                 }                  }
                if (ret == 0) /* ret == 1 if symlink could not be set */                if (ret > 0) { /* ret == 1 if symlink could not be set */
                        updated = 1;                        updated &= ~UPDATED_TIMES;
                else 
                         file->flags |= FLAG_TIME_FAILED;                          file->flags |= FLAG_TIME_FAILED;
         }  
   
 #ifdef HAVE_CHMOD  
         if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {  
                 int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);  
                 if (ret < 0) {  
                         rsyserr(FERROR_XFER, errno,  
                                 "failed to set permissions on %s",  
                                 full_fname(fname));  
                         goto cleanup;  
                 }                  }
                if (ret == 0) /* ret == 1 if symlink could not be set */        }
 #ifdef SUPPORT_CRTIMES
         if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
                 time_t file_crtime = F_CRTIME(file);
                 if (sxp->crtime == 0)
                         sxp->crtime = get_create_time(fname);
                 if (!same_time(sxp->crtime, 0L, file_crtime, 0L)
                  && set_create_time(fname, file_crtime) == 0)
                         updated = 1;                          updated = 1;
         }          }
 #endif  #endif
Line 588  int set_file_attrs(const char *fname, struct file_stru Line 686  int set_file_attrs(const char *fname, struct file_stru
          * need to chmod(). */           * need to chmod(). */
         if (preserve_acls && !S_ISLNK(new_mode)) {          if (preserve_acls && !S_ISLNK(new_mode)) {
                 if (set_acl(fname, file, sxp, new_mode) > 0)                  if (set_acl(fname, file, sxp, new_mode) > 0)
                        updated = 1;                        updated |= UPDATED_ACLS;
         }          }
 #endif  #endif
   
   #ifdef HAVE_CHMOD
           if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
                   int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode, ST_FLAGS(sxp->st));
                   if (ret < 0) {
                           rsyserr(FERROR_XFER, errno,
                                   "failed to set permissions on %s",
                                   full_fname(fname));
                           goto cleanup;
                   }
                   if (ret == 0) /* ret == 1 if symlink could not be set */
                           updated |= UPDATED_MODE;
           }
   #endif
   
   #ifdef SUPPORT_FILEFLAGS
           if (preserve_fileflags && !S_ISLNK(sxp->st.st_mode)
            && sxp->st.st_flags != F_FFLAGS(file)) {
                   uint32 fileflags = F_FFLAGS(file);
                   if (flags & ATTRS_DELAY_IMMUTABLE)
                           fileflags &= ~ALL_IMMUTABLE;
                   if (sxp->st.st_flags != fileflags
                    && !set_fileflags(fname, fileflags))
                           goto cleanup;
                   updated = 1;
   #ifdef SUPPORT_HFS_COMPRESSION
                   int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), new_mode, fileflags);
                   if (ret < 0) {
                           rsyserr(FERROR_XFER, errno, "failed to set times on %s",
                                   full_fname(fname));
                           goto cleanup;
                   }
                   if (ret != 0)
                           file->flags |= FLAG_TIME_FAILED;
   #endif
           }
   #endif
   
         if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {          if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
                 if (updated)                  if (updated)
                         rprintf(FCLIENT, "%s\n", fname);                          rprintf(FCLIENT, "%s\n", fname);
Line 607  int set_file_attrs(const char *fname, struct file_stru Line 742  int set_file_attrs(const char *fname, struct file_stru
 /* This is only called for SIGINT, SIGHUP, and SIGTERM. */  /* This is only called for SIGINT, SIGHUP, and SIGTERM. */
 void sig_int(int sig_num)  void sig_int(int sig_num)
 {  {
           called_from_signal_handler = 1;
   
         /* KLUGE: if the user hits Ctrl-C while ssh is prompting          /* KLUGE: if the user hits Ctrl-C while ssh is prompting
          * for a password, then our cleanup's sending of a SIGUSR1           * for a password, then our cleanup's sending of a SIGUSR1
          * signal to all our children may kill ssh before it has a           * signal to all our children may kill ssh before it has a
Line 630  void sig_int(int sig_num) Line 767  void sig_int(int sig_num)
          * we didn't already set the flag. */           * we didn't already set the flag. */
         if (!got_kill_signal && (am_server || am_receiver)) {          if (!got_kill_signal && (am_server || am_receiver)) {
                 got_kill_signal = sig_num;                  got_kill_signal = sig_num;
                   called_from_signal_handler = 0;
                 return;                  return;
         }          }
   
Line 640  void sig_int(int sig_num) Line 778  void sig_int(int sig_num)
  * attributes (e.g. permissions, ownership, etc.).  If the robust_rename()   * attributes (e.g. permissions, ownership, etc.).  If the robust_rename()
  * call is forced to copy the temp file and partialptr is both non-NULL and   * call is forced to copy the temp file and partialptr is both non-NULL and
  * not an absolute path, we stage the file into the partial-dir and then   * not an absolute path, we stage the file into the partial-dir and then
 * rename it into place.  This returns 1 on succcess or 0 on failure. */ * rename it into place.  This returns 1 on success or 0 on failure. */
 int finish_transfer(const char *fname, const char *fnametmp,  int finish_transfer(const char *fname, const char *fnametmp,
                     const char *fnamecmp, const char *partialptr,                      const char *fnamecmp, const char *partialptr,
                     struct file_struct *file, int ok_to_set_time,                      struct file_struct *file, int ok_to_set_time,
Line 656  int finish_transfer(const char *fname, const char *fna Line 794  int finish_transfer(const char *fname, const char *fna
                 goto do_set_file_attrs;                  goto do_set_file_attrs;
         }          }
   
        if (make_backups > 0 && overwriting_basis) {        if (make_backups > 1 && overwriting_basis) {
                 int ok = make_backup(fname, False);                  int ok = make_backup(fname, False);
                 if (!ok)                  if (!ok)
                        return 1;                        exit_cleanup(RERR_FILEIO);
                 if (ok == 1 && fnamecmp == fname)                  if (ok == 1 && fnamecmp == fname)
                         fnamecmp = get_backup_name(fname);                          fnamecmp = get_backup_name(fname);
         }          }
   
         /* Change permissions before putting the file into place. */          /* Change permissions before putting the file into place. */
         set_file_attrs(fnametmp, file, NULL, fnamecmp,          set_file_attrs(fnametmp, file, NULL, fnamecmp,
                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);                       ATTRS_DELAY_IMMUTABLE
                        | (ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME | ATTRS_SKIP_CRTIME));
   
         /* move tmp file over real file */          /* move tmp file over real file */
         if (DEBUG_GTE(RECV, 1))          if (DEBUG_GTE(RECV, 1))
Line 683  int finish_transfer(const char *fname, const char *fna Line 822  int finish_transfer(const char *fname, const char *fna
         }          }
         if (ret == 0) {          if (ret == 0) {
                 /* The file was moved into place (not copied), so it's done. */                  /* The file was moved into place (not copied), so it's done. */
   #ifdef SUPPORT_FILEFLAGS
                   if (preserve_fileflags && F_FFLAGS(file) & ALL_IMMUTABLE)
                           set_fileflags(fname, F_FFLAGS(file));
   #endif
                 return 1;                  return 1;
         }          }
         /* The file was copied, so tweak the perms of the copied file.  If it          /* The file was copied, so tweak the perms of the copied file.  If it
Line 691  int finish_transfer(const char *fname, const char *fna Line 834  int finish_transfer(const char *fname, const char *fna
   
   do_set_file_attrs:    do_set_file_attrs:
         set_file_attrs(fnametmp, file, NULL, fnamecmp,          set_file_attrs(fnametmp, file, NULL, fnamecmp,
                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);                       ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME | ATTRS_SKIP_CRTIME);
   
         if (temp_copy_name) {          if (temp_copy_name) {
                 if (do_rename(fnametmp, fname) < 0) {                  if (do_rename(fnametmp, fname) < 0) {
Line 742  struct file_list *flist_for_ndx(int ndx, const char *f Line 885  struct file_list *flist_for_ndx(int ndx, const char *f
   
 const char *who_am_i(void)  const char *who_am_i(void)
 {  {
           if (am_dbadmin)
                   return "rsyncdb";
         if (am_starting_up)          if (am_starting_up)
                 return am_server ? "server" : "client";                  return am_server ? "server" : "client";
         return am_sender ? "sender"          return am_sender ? "sender"

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>