[BACK]Return to uploader.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rsync

Diff for /src/usr.bin/rsync/uploader.c between version 1.10 and 1.11

version 1.10, 2019/02/16 10:47:20 version 1.11, 2019/02/16 10:48:05
Line 50 
Line 50 
         size_t              bufpos; /* position in buf */          size_t              bufpos; /* position in buf */
         size_t              idx; /* current transfer index */          size_t              idx; /* current transfer index */
         mode_t              oumask; /* umask for creating files */          mode_t              oumask; /* umask for creating files */
           char               *root; /* destination directory path */
         int                 rootfd; /* destination directory */          int                 rootfd; /* destination directory */
         size_t              csumlen; /* checksum length */          size_t              csumlen; /* checksum length */
         int                 fdout; /* write descriptor to sender */          int                 fdout; /* write descriptor to sender */
Line 168 
Line 169 
 pre_link(struct upload *p, struct sess *sess)  pre_link(struct upload *p, struct sess *sess)
 {  {
         struct stat              st;          struct stat              st;
         struct timespec          tv[2];  
         const struct flist      *f;          const struct flist      *f;
         int                      rc, newlink = 0, updatelink = 0;          int                      rc, newlink = 0, updatelink = 0;
         mode_t                   mode;          char                    *b, *temp = NULL;
         char                    *b;  
   
         f = &p->fl[p->idx];          f = &p->fl[p->idx];
         assert(S_ISLNK(f->st.mode));          assert(S_ISLNK(f->st.mode));
Line 228 
Line 227 
                 LOG3(sess, "%s: creating "                  LOG3(sess, "%s: creating "
                         "symlink: %s", f->path, f->link);                          "symlink: %s", f->path, f->link);
   
                 if (mktemplate(&b, f->path, sess->opts->recursive) == -1) {                  if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                         ERR(sess, "asprintf");                          ERR(sess, "asprintf");
                         return -1;                          return -1;
                 }                  }
                 if (mkstemplinkat(f->link, p->rootfd, b) == NULL) {                  if (mkstemplinkat(f->link, p->rootfd, temp) == NULL) {
                         WARN(sess, "%s: symlinkat", b);                          WARN(sess, "%s: symlinkat", temp);
                         free(b);                          free(temp);
                         return -1;                          return -1;
                 }                  }
                 newlink = 1;                  newlink = 1;
         }          }
   
         /*          rsync_set_metadata_at(sess, newlink, p->rootfd, f,
          * Optionally preserve times/perms on the symlink.              newlink ? temp : f->path);
          * FIXME: run rsync_set_metadata()?  
          */  
   
         if (sess->opts->preserve_times) {          if (newlink) {
                 struct timeval now;                  if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                           ERR(sess, "%s: renameat %s", temp, f->path);
                           (void)unlinkat(p->rootfd, temp, 0);
                           free(temp);
                           return -1;
                   }
                   free(temp);
           }
   
                 gettimeofday(&now, NULL);          log_link(sess, f);
                 TIMEVAL_TO_TIMESPEC(&now, &tv[0]);          return 0;
                 tv[1].tv_sec = f->st.mtime;  }
                 tv[1].tv_nsec = 0;  
                 rc = utimensat(p->rootfd, newlink ? b : f->path, tv,  /*
                     AT_SYMLINK_NOFOLLOW);   * Return <0 on failure 0 on success.
                 if (rc == -1) {   */
                         ERR(sess, "%s: futimes", f->path);  static int
                         if (newlink) {  pre_dev(struct upload *p, struct sess *sess)
                                 (void)unlinkat(p->rootfd, b, 0);  {
                                 free(b);          struct stat              st;
           const struct flist      *f;
           int                      rc, newdev = 0, updatedev = 0;
           char                    *temp = NULL;
   
           f = &p->fl[p->idx];
           assert(S_ISBLK(f->st.mode) || S_ISCHR(f->st.mode));
   
           if (!sess->opts->devices || getuid() != 0) {
                   WARNX(sess, "skipping non-regular file %s", f->path);
                   return 0;
           } else if (sess->opts->dry_run) {
                   log_file(sess, f);
                   return 0;
           }
   
           /* See if the dev already exists */
           assert(p->rootfd != -1);
   
           rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
   
           if (rc != -1 && !(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) {
                   if (S_ISDIR(st.st_mode)) {
                           if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                                   WARN(sess, "%s", f->path);
                                   return -1;
                         }                          }
                   }
                   rc = -1; /* overwrite object with dev */
           } else if (rc == -1 && errno != ENOENT) {
                   WARN(sess, "%s: fstatat", f->path);
                   return -1;
           }
   
           /*
            * If the device already exists make sure it is of the correct type.
            */
   
           if (rc != -1) {
                   if ((f->st.mode & (S_IFCHR|S_IFBLK)) !=
                       (st.st_mode & (S_IFCHR|S_IFBLK)) || f->st.rdev !=
                       st.st_rdev) {
                           LOG3(sess, "%s: updating dev", f->path);
                           updatedev = 1;
                   }
           }
   
           if (rc == -1 || updatedev) {
                   newdev = 1;
                   if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                           ERR(sess, "asprintf");
                         return -1;                          return -1;
                 }                  }
                 LOG4(sess, "%s: updated symlink date", f->path);                  if (mkstempnodat(p->rootfd, temp, f->st.mode &
                       (S_IFCHR|S_IFBLK), f->st.rdev) == NULL) {
                           WARN(sess, "%s: mknodat", temp);
                           free(temp);
                           return -1;
                   }
         }          }
   
         if (newlink || sess->opts->preserve_perms) {          rsync_set_metadata_at(sess, newdev, p->rootfd, f,
                 if (updatelink && !sess->opts->preserve_perms)              newdev ? temp : f->path);
                         /* carry over permissions from replaced symlink */  
                         mode = st.st_mode;  
                 else  
                         mode = f->st.mode;  
   
                 rc = fchmodat(p->rootfd, newlink ? b : f->path, mode,          if (newdev) {
                     AT_SYMLINK_NOFOLLOW);                  if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                 if (rc == -1) {                          ERR(sess, "%s: renameat %s", temp, f->path);
                         ERR(sess, "%s: fchmodat", newlink ? b : f->path);                          (void)unlinkat(p->rootfd, temp, 0);
                         if (newlink) {                          free(temp);
                                 (void)unlinkat(p->rootfd, b, 0);                          return -1;
                                 free(b);                  }
                   free(temp);
           }
           log_file(sess, f);
           return 0;
   }
   
   /*
    * Return <0 on failure 0 on success.
    */
   static int
   pre_fifo(struct upload *p, struct sess *sess)
   {
           struct stat              st;
           const struct flist      *f;
           int                      rc, newfifo = 0;
           char                    *temp = NULL;
   
           f = &p->fl[p->idx];
           assert(S_ISFIFO(f->st.mode));
   
           if (!sess->opts->specials) {
                   WARNX(sess, "skipping non-regular file %s", f->path);
                   return 0;
           } else if (sess->opts->dry_run) {
                   log_file(sess, f);
                   return 0;
           }
   
           /* See if the fifo already exists */
           assert(p->rootfd != -1);
   
           rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
   
           if (rc != -1 && !S_ISFIFO(st.st_mode)) {
                   if (S_ISDIR(st.st_mode)) {
                           if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                                   WARN(sess, "%s", f->path);
                                   return -1;
                         }                          }
                   }
                   rc = -1; /* overwrite object with fifo */
           } else if (rc == -1 && errno != ENOENT) {
                   WARN(sess, "%s: fstatat", f->path);
                   return -1;
           }
   
           if (rc == -1) {
                   newfifo = 1;
                   if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                           ERR(sess, "asprintf");
                         return -1;                          return -1;
                 }                  }
                 LOG4(sess, "%s: updated symlink mode", f->path);                  if (mkstempfifoat(p->rootfd, temp) == NULL) {
                           WARN(sess, "%s: mkfifoat", temp);
                           free(temp);
                           return -1;
                   }
         }          }
   
         if (newlink) {          rsync_set_metadata_at(sess, newfifo, p->rootfd, f,
                 if (renameat(p->rootfd, b, p->rootfd, f->path) == -1) {              newfifo ? temp : f->path);
                         ERR(sess, "%s: renameat %s", b, f->path);  
                         (void)unlinkat(p->rootfd, b, 0);          if (newfifo) {
                         free(b);                  if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                           ERR(sess, "%s: renameat %s", temp, f->path);
                           (void)unlinkat(p->rootfd, temp, 0);
                           free(temp);
                         return -1;                          return -1;
                 }                  }
                 free(b);                  free(temp);
         }          }
           log_file(sess, f);
           return 0;
   }
   
         log_link(sess, f);  /*
    * Return <0 on failure 0 on success.
    */
   static int
   pre_sock(struct upload *p, struct sess *sess)
   {
           struct stat              st;
           const struct flist      *f;
           int                      rc, newsock = 0;
           char                    *temp = NULL;
   
           f = &p->fl[p->idx];
           assert(S_ISSOCK(f->st.mode));
   
           if (!sess->opts->specials) {
                   WARNX(sess, "skipping non-regular file %s", f->path);
                   return 0;
           } else if (sess->opts->dry_run) {
                   log_file(sess, f);
                   return 0;
           }
   
           rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
   
           if (rc != -1 && !S_ISSOCK(st.st_mode)) {
                   if (S_ISDIR(st.st_mode)) {
                           if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                                   WARN(sess, "%s", f->path);
                                   return -1;
                           }
                   }
                   rc = -1; /* overwrite object with sock */
           } else if (rc == -1 && errno != ENOENT) {
                   WARN(sess, "%s: fstatat", f->path);
                   return -1;
           }
   
           if (rc == -1) {
                   newsock = 1;
   
                   if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                           ERR(sess, "asprintf");
                           return -1;
                   }
   
                   if (mkstempsock(p->root, temp) == NULL) {
                           WARN(sess, "%s: mksockat", temp);
                           free(temp);
                           return -1;
                   }
           }
   
           rsync_set_metadata_at(sess, newsock, p->rootfd, f,
               newsock ? temp : f->path);
   
           if (newsock) {
                   if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                           ERR(sess, "%s: renameat %s", temp, f->path);
                           (void)unlinkat(p->rootfd, temp, 0);
                           free(temp);
                           return -1;
                   }
                   free(temp);
           }
           log_file(sess, f);
         return 0;          return 0;
 }  }
   
Line 474 
Line 651 
  * On success, upload_free() must be called with the allocated pointer.   * On success, upload_free() must be called with the allocated pointer.
  */   */
 struct upload *  struct upload *
 upload_alloc(struct sess *sess, int rootfd, int fdout,  upload_alloc(struct sess *sess, const char *root, int rootfd, int fdout,
         size_t clen, const struct flist *fl, size_t flsz, mode_t msk)          size_t clen, const struct flist *fl, size_t flsz, mode_t msk)
 {  {
         struct upload   *p;          struct upload   *p;
Line 486 
Line 663 
   
         p->state = UPLOAD_FIND_NEXT;          p->state = UPLOAD_FIND_NEXT;
         p->oumask = msk;          p->oumask = msk;
           p->root = strdup(root);
           if (p->root == NULL) {
                   ERR(sess, "strdup");
                   free(p);
                   return NULL;
           }
         p->rootfd = rootfd;          p->rootfd = rootfd;
         p->csumlen = clen;          p->csumlen = clen;
         p->fdout = fdout;          p->fdout = fdout;
Line 494 
Line 677 
         p->newdir = calloc(flsz, sizeof(int));          p->newdir = calloc(flsz, sizeof(int));
         if (p->newdir == NULL) {          if (p->newdir == NULL) {
                 ERR(sess, "calloc");                  ERR(sess, "calloc");
                   free(p->root);
                 free(p);                  free(p);
                 return NULL;                  return NULL;
         }          }
Line 510 
Line 694 
   
         if (p == NULL)          if (p == NULL)
                 return;                  return;
           free(p->root);
         free(p->newdir);          free(p->newdir);
         free(p->buf);          free(p->buf);
         free(p);          free(p);
Line 603 
Line 788 
                                 c = pre_link(u, sess);                                  c = pre_link(u, sess);
                         else if (S_ISREG(u->fl[u->idx].st.mode))                          else if (S_ISREG(u->fl[u->idx].st.mode))
                                 c = pre_file(u, fileinfd, sess);                                  c = pre_file(u, fileinfd, sess);
                           else if (S_ISBLK(u->fl[u->idx].st.mode) ||
                               S_ISCHR(u->fl[u->idx].st.mode))
                                   c = pre_dev(u, sess);
                           else if (S_ISFIFO(u->fl[u->idx].st.mode))
                                   c = pre_fifo(u, sess);
                           else if (S_ISSOCK(u->fl[u->idx].st.mode))
                                   c = pre_sock(u, sess);
                         else                          else
                                 c = 0;                                  c = 0;
   

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11