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

Diff for /src/usr.bin/rsync/flist.c between version 1.6 and 1.7

version 1.6, 2019/02/12 18:59:34 version 1.7, 2019/02/12 19:02:06
Line 20 
Line 20 
 #include <assert.h>  #include <assert.h>
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <inttypes.h>  
 #include <fts.h>  #include <fts.h>
   #include <grp.h>
   #include <inttypes.h>
 #include <search.h>  #include <search.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
Line 49 
Line 50 
 #define FLIST_TIME_SAME  0x0080 /* time is repeat */  #define FLIST_TIME_SAME  0x0080 /* time is repeat */
   
 /*  /*
    * Combination of name and numeric id for groups and users.
    */
   struct  ident {
           int32_t  id; /* the gid_t or uid_t */
           int32_t  mapped; /* if receiving, the mapped gid */
           char    *name; /* resolved name */
   };
   
   /*
    * Free a list of struct ident previously allocated with flist_gid_add().
    * Does nothing if the pointer is NULL.
    */
   static void
   flist_ident_free(struct ident *p, size_t sz)
   {
           size_t   i;
   
           if (NULL == p)
                   return;
           for (i = 0; i < sz; i++)
                   free(p[i].name);
           free(p);
   }
   
   /*
    * Given a list of groups from the remote host, fill in our local
    * identifiers of the same names.
    * Use the remote numeric identifier if we can't find the group OR the
    * group has identifier zero.
    */
   static void
   flist_gid_remap(struct sess *sess, struct ident *gids, size_t gidsz)
   {
           size_t           i;
           struct group    *grp;
   
           for (i = 0; i < gidsz; i++) {
                   if (NULL == (grp = getgrnam(gids[i].name)))
                           gids[i].mapped = gids[i].id;
                   else if (0 == grp->gr_gid)
                           gids[i].mapped = gids[i].id;
                   else
                           gids[i].mapped = grp->gr_gid;
                   LOG4(sess, "remapped group %s: %" PRId32 " -> %" PRId32,
                           gids[i].name, gids[i].id, gids[i].mapped);
           }
   }
   
   /*
    * If "gid" is not part of the list of known groups, add it.
    * This also verifies that the group name isn't too long.
    * Return zero on failure, non-zero on success.
    */
   static int
   flist_gid_add(struct sess *sess, struct ident **gids, size_t *gidsz, gid_t gid)
   {
           struct group    *grp;
           size_t           i, sz;
           void            *pp;
   
           for (i = 0; i < *gidsz; i++)
                   if ((*gids)[i].id == (int32_t)gid)
                           return 1;
   
           /*
            * Look us up in /etc/group.
            * Make sure that the group name length is sane: we transmit it
            * using a single byte.
            */
   
           assert(i == *gidsz);
           if (NULL == (grp = getgrgid(gid))) {
                   ERR(sess, "%u: unknown gid", gid);
                   return 0;
           } else if ((sz = strlen(grp->gr_name)) > UINT8_MAX) {
                   ERRX(sess, "%u: group name too long: %s", gid, grp->gr_name);
                   return 0;
           } else if (0 == sz) {
                   ERRX(sess, "%u: group name zero-length", gid);
                   return 0;
           }
   
           /* Add the group to the array. */
   
           pp = reallocarray(*gids, *gidsz + 1, sizeof(struct ident));
           if (NULL == pp) {
                   ERR(sess, "reallocarray");
                   return 0;
           }
           *gids = pp;
           (*gids)[*gidsz].id = gid;
           (*gids)[*gidsz].name = strdup(grp->gr_name);
           if (NULL == (*gids)[*gidsz].name) {
                   ERR(sess, "strdup");
                   return 0;
           }
   
           LOG4(sess, "adding group to list: %s (%u)",
                   (*gids)[*gidsz].name, (*gids)[*gidsz].id);
           (*gidsz)++;
           return 1;
   }
   
   /*
  * Requied way to sort a filename list.   * Requied way to sort a filename list.
  */   */
 static int  static int
Line 232 
Line 337 
 }  }
   
 /*  /*
    * Send a list of struct ident.
    * See flist_recv_ident().
    * We should only do this if we're preserving gids/uids.
    * Return zero on failure, non-zero on success.
    */
   static int
   flist_send_ident(struct sess *sess,
           int fd, const struct ident *ids, size_t idsz)
   {
           size_t   i, sz;
   
           for (i = 0; i < idsz; i++) {
                   assert(NULL != ids[i].name);
                   sz = strlen(ids[i].name);
                   assert(sz > 0 && sz <= UINT8_MAX);
                   if (!io_write_int(sess, fd, ids[i].id)) {
                           ERRX1(sess, "io_write_int");
                           return 0;
                   } else if (!io_write_byte(sess, fd, sz)) {
                           ERRX1(sess, "io_write_byte");
                           return 0;
                   } else if (!io_write_buf(sess, fd, ids[i].name, sz)) {
                           ERRX1(sess, "io_write_byte");
                           return 0;
                   }
           }
   
           if (!io_write_int(sess, fd, 0)) {
                   ERRX1(sess, "io_write_int");
                   return 0;
           }
   
           return 1;
   }
   
   /*
  * Serialise our file list (which may be zero-length) to the wire.   * Serialise our file list (which may be zero-length) to the wire.
  * Makes sure that the receiver isn't going to block on sending us   * Makes sure that the receiver isn't going to block on sending us
  * return messages on the log channel.   * return messages on the log channel.
Line 241 
Line 382 
 flist_send(struct sess *sess, int fdin, int fdout, const struct flist *fl,  flist_send(struct sess *sess, int fdin, int fdout, const struct flist *fl,
     size_t flsz)      size_t flsz)
 {  {
         size_t           i, fnlen;          size_t           i, sz, gidsz = 0;
         uint8_t          flag;          uint8_t          flag;
         const struct flist *f;          const struct flist *f;
         const char      *fn;          const char      *fn;
           struct ident    *gids = NULL;
           int              rc = 0;
   
         /* Double-check that we've no pending multiplexed data. */          /* Double-check that we've no pending multiplexed data. */
   
Line 253 
Line 396 
         for (i = 0; i < flsz; i++) {          for (i = 0; i < flsz; i++) {
                 f = &fl[i];                  f = &fl[i];
                 fn = f->wpath;                  fn = f->wpath;
                 fnlen = strlen(f->wpath);                  sz = strlen(f->wpath);
                 assert(fnlen > 0);                  assert(sz > 0);
   
                 /*                  /*
                  * If applicable, unclog the read buffer.                   * If applicable, unclog the read buffer.
Line 267 
Line 410 
                     io_read_check(sess, fdin) &&                      io_read_check(sess, fdin) &&
                      !io_read_flush(sess, fdin)) {                       !io_read_flush(sess, fdin)) {
                         ERRX1(sess, "io_read_flush");                          ERRX1(sess, "io_read_flush");
                         return 0;                          goto out;
                 }                  }
   
                 /*                  /*
Line 289 
Line 432 
   
                 if (!io_write_byte(sess, fdout, flag)) {                  if (!io_write_byte(sess, fdout, flag)) {
                         ERRX1(sess, "io_write_byte");                          ERRX1(sess, "io_write_byte");
                         return 0;                          goto out;
                 } else if (!io_write_int(sess, fdout, fnlen)) {                  } else if (!io_write_int(sess, fdout, sz)) {
                         ERRX1(sess, "io_write_int");                          ERRX1(sess, "io_write_int");
                         return 0;                          goto out;
                 } else if (!io_write_buf(sess, fdout, fn, fnlen)) {                  } else if (!io_write_buf(sess, fdout, fn, sz)) {
                         ERRX1(sess, "io_write_buf");                          ERRX1(sess, "io_write_buf");
                         return 0;                          goto out;
                 } else if (!io_write_long(sess, fdout, f->st.size)) {                  } else if (!io_write_long(sess, fdout, f->st.size)) {
                         ERRX1(sess, "io_write_long");                          ERRX1(sess, "io_write_long");
                         return 0;                          goto out;
                 } else if (!io_write_int(sess, fdout, f->st.mtime)) {                  } else if (!io_write_int(sess, fdout, f->st.mtime)) {
                         ERRX1(sess, "io_write_int");                          ERRX1(sess, "io_write_int");
                         return 0;                          goto out;
                 } else if (!io_write_int(sess, fdout, f->st.mode)) {                  } else if (!io_write_int(sess, fdout, f->st.mode)) {
                         ERRX1(sess, "io_write_int");                          ERRX1(sess, "io_write_int");
                         return 0;                          goto out;
                 }                  }
   
                 /* Conditional part: gid. */                  /* Conditional part: gid. */
   
                 if (sess->opts->preserve_gids &&                  if (sess->opts->preserve_gids) {
                     ! io_write_int(sess, fdout, f->st.gid)) {                          if (!io_write_int(sess, fdout, f->st.gid)) {
                         ERRX1(sess, "io_write_int");                                  ERRX1(sess, "io_write_int");
                         return 0;                                  goto out;
                           }
                           if (!flist_gid_add(sess, &gids, &gidsz, f->st.gid)) {
                                   ERRX1(sess, "flist_gid_add");
                                   goto out;
                           }
                 }                  }
   
                 /* Conditional part: link. */                  /* Conditional part: link. */
Line 320 
Line 468 
                 if (S_ISLNK(f->st.mode) &&                  if (S_ISLNK(f->st.mode) &&
                     sess->opts->preserve_links) {                      sess->opts->preserve_links) {
                         fn = f->link;                          fn = f->link;
                         fnlen = strlen(f->link);                          sz = strlen(f->link);
                         if (!io_write_int(sess, fdout, fnlen)) {                          if (!io_write_int(sess, fdout, sz)) {
                                 ERRX1(sess, "io_write_int");                                  ERRX1(sess, "io_write_int");
                                 return 0;                                  goto out;
                         }                          }
                         if (!io_write_buf(sess, fdout, fn, fnlen)) {                          if (!io_write_buf(sess, fdout, fn, sz)) {
                                 ERRX1(sess, "io_write_int");                                  ERRX1(sess, "io_write_int");
                                 return 0;                                  goto out;
                         }                          }
                 }                  }
   
Line 335 
Line 483 
                         sess->total_size += f->st.size;                          sess->total_size += f->st.size;
         }          }
   
           /* Signal end of file list. */
   
         if (!io_write_byte(sess, fdout, 0)) {          if (!io_write_byte(sess, fdout, 0)) {
                 ERRX1(sess, "io_write_byte");                  ERRX1(sess, "io_write_byte");
                 return 0;                  goto out;
         }          }
   
         return 1;          /* Conditionally write gid list and terminator. */
   
           if (sess->opts->preserve_gids) {
                   LOG2(sess, "sending gid list: %zu", gidsz);
                   if (!flist_send_ident(sess, fdout, gids, gidsz)) {
                           ERRX1(sess, "flist_send_ident");
                           goto out;
                   }
           }
   
           rc = 1;
   out:
           flist_ident_free(gids, gidsz);
           return rc;
 }  }
   
 /*  /*
Line 508 
Line 671 
 }  }
   
 /*  /*
    * Receive a list of struct ident.
    * See flist_send_ident().
    * We should only do this if we're preserving gids/uids.
    * Return zero on failure, non-zero on success.
    */
   static int
   flist_recv_ident(struct sess *sess,
           int fd, struct ident **ids, size_t *idsz)
   {
           int32_t  id;
           uint8_t  sz;
           void    *pp;
   
           for (;;) {
                   if (!io_read_int(sess, fd, &id)) {
                           ERRX1(sess, "io_read_int");
                           return 0;
                   } else if (0 == id)
                           break;
   
                   pp = reallocarray(*ids,
                           *idsz + 1, sizeof(struct ident));
                   if (NULL == pp) {
                           ERR(sess, "reallocarray");
                           return 0;
                   }
                   *ids = pp;
                   memset(&(*ids)[*idsz], 0, sizeof(struct ident));
                   if (!io_read_byte(sess, fd, &sz)) {
                           ERRX1(sess, "io_read_byte");
                           return 0;
                   }
                   (*ids)[*idsz].id = id;
                   (*ids)[*idsz].name = calloc(sz + 1, 1);
                   if (NULL == (*ids)[*idsz].name) {
                           ERR(sess, "calloc");
                           return 0;
                   }
                   if (!io_read_buf(sess, fd, (*ids)[*idsz].name, sz)) {
                           ERRX1(sess, "io_read_buf");
                           return 0;
                   }
                   (*idsz)++;
           }
   
           return 1;
   }
   
   /*
  * Receive a file list from the wire, filling in length "sz" (which may   * Receive a file list from the wire, filling in length "sz" (which may
  * possibly be zero) and list "flp" on success.   * possibly be zero) and list "flp" on success.
  * Return zero on failure, non-zero on success.   * Return zero on failure, non-zero on success.
Line 518 
Line 730 
         struct flist    *fl = NULL;          struct flist    *fl = NULL;
         struct flist    *ff;          struct flist    *ff;
         const struct flist *fflast = NULL;          const struct flist *fflast = NULL;
         size_t           flsz = 0, flmax = 0, lsz;          size_t           i, j, flsz = 0, flmax = 0, lsz, gidsz = 0;
         uint8_t          flag;          uint8_t          flag;
         char             last[MAXPATHLEN];          char             last[MAXPATHLEN];
         uint64_t         lval; /* temporary values... */          uint64_t         lval; /* temporary values... */
         int32_t          ival;          int32_t          ival;
           struct ident    *gids = NULL;
   
         last[0] = '\0';          last[0] = '\0';
   
Line 632 
Line 845 
                         sess->total_size += ff->st.size;                          sess->total_size += ff->st.size;
         }          }
   
           /*
            * Now conditionally read the group list.
            * We then remap all group identifiers to the local ids.
            */
   
           if (sess->opts->preserve_gids) {
                   if (!flist_recv_ident(sess, fd, &gids, &gidsz)) {
                           ERRX1(sess, "flist_recv_ident");
                           goto out;
                   }
                   LOG2(sess, "received gid list: %zu", gidsz);
                   flist_gid_remap(sess, gids, gidsz);
           }
   
         /* Remember to order the received list. */          /* Remember to order the received list. */
   
         LOG2(sess, "received file metadata list: %zu", flsz);          LOG2(sess, "received file metadata list: %zu", flsz);
Line 639 
Line 866 
         flist_topdirs(sess, fl, flsz);          flist_topdirs(sess, fl, flsz);
         *sz = flsz;          *sz = flsz;
         *flp = fl;          *flp = fl;
   
           /* Lastly, reassign group identifiers. */
   
           if (sess->opts->preserve_gids) {
                   for (i = 0; i < flsz; i++) {
                           for (j = 0; j < gidsz; j++)
                                   if ((int32_t)fl[i].st.gid == gids[j].id)
                                           break;
                           assert(j < gidsz);
                           fl[i].st.gid = gids[j].mapped;
                   }
           }
   
           flist_ident_free(gids, gidsz);
         return 1;          return 1;
 out:  out:
         flist_free(fl, flsz);          flist_free(fl, flsz);
           flist_ident_free(gids, gidsz);
         *sz = 0;          *sz = 0;
         *flp = NULL;          *flp = NULL;
         return 0;          return 0;

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7