[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.29 and 1.29.2.1

version 1.29, 2021/06/30 13:10:04 version 1.29.2.1, 2021/11/09 13:40:41
Line 19 
Line 19 
 #include <sys/stat.h>  #include <sys/stat.h>
   
 #include <assert.h>  #include <assert.h>
   #include <err.h>
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <inttypes.h>  #include <inttypes.h>
Line 166 
Line 167 
  * Return <0 on failure 0 on success.   * Return <0 on failure 0 on success.
  */   */
 static int  static int
 pre_link(struct upload *p, struct sess *sess)  pre_symlink(struct upload *p, struct sess *sess)
 {  {
         struct stat              st;          struct stat              st;
         const struct flist      *f;          const struct flist      *f;
Line 266 
Line 267 
 }  }
   
 /*  /*
  * See pre_link(), but for devices.   * See pre_symlink(), but for devices.
  * FIXME: this is very similar to the other pre_xxx() functions.   * FIXME: this is very similar to the other pre_xxx() functions.
  * Return <0 on failure 0 on success.   * Return <0 on failure 0 on success.
  */   */
Line 355 
Line 356 
 }  }
   
 /*  /*
  * See pre_link(), but for FIFOs.   * See pre_symlink(), but for FIFOs.
  * FIXME: this is very similar to the other pre_xxx() functions.   * FIXME: this is very similar to the other pre_xxx() functions.
  * Return <0 on failure 0 on success.   * Return <0 on failure 0 on success.
  */   */
Line 432 
Line 433 
 }  }
   
 /*  /*
  * See pre_link(), but for socket files.   * See pre_symlink(), but for socket files.
  * FIXME: this is very similar to the other pre_xxx() functions.   * FIXME: this is very similar to the other pre_xxx() functions.
  * Return <0 on failure 0 on success.   * Return <0 on failure 0 on success.
  */   */
Line 641 
Line 642 
 }  }
   
 /*  /*
    * Check if file exists in the specified root directory.
    * Returns:
    *    -1 on error
    *     0 if file is considered the same
    *     1 if file exists and is possible match
    *     2 if file exists but quick check failed
    *     3 if file does not exist
    * The stat pointer st is only valid for 0, 1, and 2 returns.
    */
   static int
   check_file(int rootfd, const struct flist *f, struct stat *st)
   {
           if (fstatat(rootfd, f->path, st, AT_SYMLINK_NOFOLLOW) == -1) {
                   if (errno == ENOENT)
                           return 3;
   
                   ERR("%s: fstatat", f->path);
                   return -1;
           }
   
           /* non-regular file needs attention */
           if (!S_ISREG(st->st_mode))
                   return 2;
   
           /* quick check if file is the same */
           /* TODO: add support for --checksum, --size-only and --ignore-times */
           if (st->st_size == f->st.size) {
                   if (st->st_mtime == f->st.mtime)
                           return 0;
                   return 1;
           }
   
           /* file needs attention */
           return 2;
   }
   
   /*
  * Try to open the file at the current index.   * Try to open the file at the current index.
  * If the file does not exist, returns with >0.   * If the file does not exist, returns with >0.
  * Return <0 on failure, 0 on success w/nothing to be done, >0 on   * Return <0 on failure, 0 on success w/nothing to be done, >0 on
  * success and the file needs attention.   * success and the file needs attention.
  */   */
 static int  static int
 pre_file(const struct upload *p, int *filefd, struct stat *st,  pre_file(const struct upload *p, int *filefd, off_t *size,
     struct sess *sess)      struct sess *sess)
 {  {
         const struct flist *f;          const struct flist *f;
         int rc;          struct stat st;
           int i, rc, match = -1;
   
         f = &p->fl[p->idx];          f = &p->fl[p->idx];
         assert(S_ISREG(f->st.mode));          assert(S_ISREG(f->st.mode));
Line 665 
Line 704 
                 return 0;                  return 0;
         }          }
   
           if (sess->opts->max_size >= 0 && f->st.size > sess->opts->max_size) {
                   WARNX("skipping over max-size file %s", f->path);
                   return 0;
           }
           if (sess->opts->min_size >= 0 && f->st.size < sess->opts->min_size) {
                   WARNX("skipping under min-size file %s", f->path);
                   return 0;
           }
   
         /*          /*
          * For non dry-run cases, we'll write the acknowledgement later           * For non dry-run cases, we'll write the acknowledgement later
          * in the rsync_uploader() function.           * in the rsync_uploader() function.
          */           */
   
           *size = 0;
         *filefd = -1;          *filefd = -1;
         rc = fstatat(p->rootfd, f->path, st, AT_SYMLINK_NOFOLLOW);  
   
         if (rc == -1) {          rc = check_file(p->rootfd, f, &st);
                 if (errno == ENOENT)          if (rc == -1)
                         return 1;  
   
                 ERR("%s: fstatat", f->path);  
                 return -1;                  return -1;
         }          if (rc == 2 && !S_ISREG(st.st_mode)) {
         if (!S_ISREG(st->st_mode)) {                  if (S_ISDIR(st.st_mode) &&
                 if (S_ISDIR(st->st_mode) &&  
                     unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {                      unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                         ERR("%s: unlinkat", f->path);                          ERR("%s: unlinkat", f->path);
                         return -1;                          return -1;
                 }                  }
                 return 1;  
         }          }
           if (rc == 0) {
         /* quick check if file is the same */  
         if (st->st_size == f->st.size &&  
             st->st_mtime == f->st.mtime) {  
                 LOG3("%s: skipping: up to date", f->path);  
                 if (!rsync_set_metadata_at(sess, 0, p->rootfd, f, f->path)) {                  if (!rsync_set_metadata_at(sess, 0, p->rootfd, f, f->path)) {
                         ERRX1("rsync_set_metadata");                          ERRX1("rsync_set_metadata");
                         return -1;                          return -1;
                 }                  }
                   LOG3("%s: skipping: up to date", f->path);
                 return 0;                  return 0;
         }          }
   
         *filefd = openat(p->rootfd, f->path, O_RDONLY | O_NOFOLLOW, 0);          /* check alternative locations for better match */
           for (i = 0; sess->opts->basedir[i] != NULL; i++) {
                   const char *root = sess->opts->basedir[i];
                   int dfd, x;
   
                   dfd = openat(p->rootfd, root, O_RDONLY | O_DIRECTORY);
                   if (dfd == -1)
                           err(ERR_FILE_IO, "%s: openat", root);
                   x = check_file(dfd, f, &st);
                   /* found a match */
                   if (x == 0) {
                           if (rc >= 0) {
                                   /* found better match, delete file in rootfd */
                                   if (unlinkat(p->rootfd, f->path, 0) == -1 &&
                                       errno != ENOENT) {
                                           ERR("%s: unlinkat", f->path);
                                           return -1;
                                   }
                           }
                           LOG3("%s: skipping: up to date in %s", f->path, root);
                           /* TODO: depending on mode link or copy file */
                           close(dfd);
                           return 0;
                   } else if (x == 1 && match == -1) {
                           /* found a local file that is a close match */
                           match = i;
                   }
                   close(dfd);
           }
           if (match != -1) {
                   /* copy match from basedir into root as a start point */
                   copy_file(p->rootfd, sess->opts->basedir[match], f);
                   if (fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW) ==
                       -1) {
                           ERR("%s: fstatat", f->path);
                           return -1;
                   }
           }
   
           *size = st.st_size;
           *filefd = openat(p->rootfd, f->path, O_RDONLY | O_NOFOLLOW);
         if (*filefd == -1 && errno != ENOENT) {          if (*filefd == -1 && errno != ENOENT) {
                 ERR("%s: openat", f->path);                  ERR("%s: openat", f->path);
                 return -1;                  return -1;
Line 778 
Line 858 
         struct sess *sess, int *fileoutfd)          struct sess *sess, int *fileoutfd)
 {  {
         struct blkset       blk;          struct blkset       blk;
         struct stat         st;  
         void               *mbuf, *bufp;          void               *mbuf, *bufp;
         ssize_t             msz;          ssize_t             msz;
         size_t              i, pos, sz;          size_t              i, pos, sz;
         off_t               offs;          off_t               offs, filesize;
         int                 c;          int                 c;
   
         /* Once finished this should never get called again. */          /* Once finished this should never get called again. */
Line 849 
Line 928 
                         if (S_ISDIR(u->fl[u->idx].st.mode))                          if (S_ISDIR(u->fl[u->idx].st.mode))
                                 c = pre_dir(u, sess);                                  c = pre_dir(u, sess);
                         else if (S_ISLNK(u->fl[u->idx].st.mode))                          else if (S_ISLNK(u->fl[u->idx].st.mode))
                                 c = pre_link(u, sess);                                  c = pre_symlink(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, &st, sess);                                  c = pre_file(u, fileinfd, &filesize, sess);
                         else if (S_ISBLK(u->fl[u->idx].st.mode) ||                          else if (S_ISBLK(u->fl[u->idx].st.mode) ||
                             S_ISCHR(u->fl[u->idx].st.mode))                              S_ISCHR(u->fl[u->idx].st.mode))
                                 c = pre_dev(u, sess);                                  c = pre_dev(u, sess);
Line 896 
Line 975 
         memset(&blk, 0, sizeof(struct blkset));          memset(&blk, 0, sizeof(struct blkset));
         blk.csum = u->csumlen;          blk.csum = u->csumlen;
   
         if (*fileinfd != -1 && st.st_size > 0) {          if (*fileinfd != -1 && filesize > 0) {
                 init_blkset(&blk, st.st_size);                  init_blkset(&blk, filesize);
                 assert(blk.blksz);                  assert(blk.blksz);
   
                 blk.blks = calloc(blk.blksz, sizeof(struct blk));                  blk.blks = calloc(blk.blksz, sizeof(struct blk));
Line 956 
Line 1035 
         /* Make sure the block metadata buffer is big enough. */          /* Make sure the block metadata buffer is big enough. */
   
         u->bufsz =          u->bufsz =
              sizeof(int32_t) + /* identifier */              sizeof(int32_t) + /* identifier */
              sizeof(int32_t) + /* block count */              sizeof(int32_t) + /* block count */
              sizeof(int32_t) + /* block length */              sizeof(int32_t) + /* block length */
              sizeof(int32_t) + /* checksum length */              sizeof(int32_t) + /* checksum length */
              sizeof(int32_t) + /* block remainder */              sizeof(int32_t) + /* block remainder */
              blk.blksz *              blk.blksz *
              (sizeof(int32_t) + /* short checksum */              (sizeof(int32_t) + /* short checksum */
               blk.csum); /* long checksum */              blk.csum); /* long checksum */
   
         if (u->bufsz > u->bufmax) {          if (u->bufsz > u->bufmax) {
                 if ((bufp = realloc(u->buf, u->bufsz)) == NULL) {                  if ((bufp = realloc(u->buf, u->bufsz)) == NULL) {

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.29.2.1