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

Diff for /src/usr.bin/rdist/client.c between version 1.17 and 1.18

version 1.17, 2003/05/06 22:10:11 version 1.18, 2003/05/14 01:34:35
Line 33 
Line 33 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
   #include "defs.h"
   #include "y.tab.h"
   
 #ifndef lint  #ifndef lint
 #if 0  #if 0
 static char RCSid[] =  static char RCSid[] __attribute__((__unused__)) =
 "$From: client.c,v 6.80 1996/02/28 20:34:27 mcooper Exp $";  "$From: client.c,v 1.13 1999/11/01 00:22:14 christos Exp $";
 #else  #else
 static char RCSid[] =  static char RCSid[] __attribute__((__unused__)) =
 "$OpenBSD$";  "$OpenBSD$";
 #endif  #endif
   
 static char sccsid[] = "@(#)client.c";  static char sccsid[] __attribute__((__unused__)) =
   "@(#)client.c";
   
 static char copyright[] =  static char copyright[] __attribute__((__unused__)) =
 "@(#) Copyright (c) 1983 Regents of the University of California.\n\  "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  All rights reserved.\n";   All rights reserved.\n";
 #endif /* not lint */  #endif /* not lint */
Line 53 
Line 57 
  * Routines used in client mode to communicate with remove server.   * Routines used in client mode to communicate with remove server.
  */   */
   
 #include "defs.h"  
 #include "y.tab.h"  
   
 /*  /*
  * Update status   * Update status
Line 63 
Line 65 
 #define US_NOENT        1       /* Entry does not exist */  #define US_NOENT        1       /* Entry does not exist */
 #define US_OUTDATE      2       /* Entry is out of date */  #define US_OUTDATE      2       /* Entry is out of date */
 #define US_DOCOMP       3       /* Do a binary comparison */  #define US_DOCOMP       3       /* Do a binary comparison */
 #define US_MODE         4       /* Modes of file differ */  #define US_CHMOG        4       /* Modes or ownership of file differ */
   
 struct  linkbuf *ihead = NULL;  /* list of files with more than one link */  struct  linkbuf *ihead = NULL;  /* list of files with more than one link */
 char    buf[BUFSIZ];            /* general purpose buffer */  char    buf[BUFSIZ];            /* general purpose buffer */
Line 74 
Line 76 
 char    *Tdest;                 /* pointer to last T dest*/  char    *Tdest;                 /* pointer to last T dest*/
 struct namelist *updfilelist = NULL; /* List of updated files */  struct namelist *updfilelist = NULL; /* List of updated files */
   
 static int sendit();  static void runspecial(char *, opt_t, char *, int);
   static void addcmdspecialfile(char *, char *, int);
   static void freecmdspecialfiles(void);
   static struct linkbuf *linkinfo(struct stat *);
   static int sendhardlink(opt_t, struct linkbuf *, char *, int);
   static int sendfile(char *, opt_t, struct stat *, char *, char *, int);
   static int rmchk(opt_t);
   static int senddir(char *, opt_t, struct stat *, char *, char *, int);
   static int sendlink(char *, opt_t, struct stat *, char *, char *, int);
   static int update(char *, opt_t, struct stat *);
   static int dostat(char *, struct stat *, opt_t);
   static int statupdate(int, char *, opt_t, char *, int, struct stat *, char *, char *);
   static int fullupdate(int, char *, opt_t, char *, int, struct stat *, char *, char *);
   static int sendit(char *, opt_t, int);
   
 /*  /*
  * return remote file pathname (relative from target)   * return remote file pathname (relative from target)
  */   */
 char *remfilename(src, dest, path, rname, destdir)  char *
         char *src, *dest, *path, *rname;  remfilename(char *src, char *dest, char *path, char *rname, int destdir)
         int destdir;  
 {  {
         extern struct namelist *filelist;          extern struct namelist *filelist;
         char *lname, *cp;          char *lname, *cp;
Line 109 
Line 123 
         if (path && *path) {          if (path && *path) {
                 cp = strrchr(path, '/');                  cp = strrchr(path, '/');
                 if (cp == NULL)                  if (cp == NULL)
                         (void) snprintf(buff, sizeof buff, "%s/%s", dest, path);                          (void) snprintf(buff, sizeof(buff), "%s/%s", dest, path);
                 else {                  else {
                         srclen = strlen(src);                          srclen = strlen(src);
                         pathlen = strlen(path);                          pathlen = strlen(path);
Line 127 
Line 141 
                                 }                                  }
                         }                          }
                         if ((*cp != '/') && *cp)                          if ((*cp != '/') && *cp)
                                 (void) snprintf(buff, sizeof buff,                                  (void) snprintf(buff, sizeof(buff), "%s/%s",
                                     "%s/%s", dest, cp);                                                  dest, cp);
                         else                          else
                                 (void) snprintf(buff, sizeof buff,                                  (void) snprintf(buff, sizeof(buff), "%s%s",
                                     "%s%s", dest, cp);                                                  dest, cp);
                 }                  }
         } else          } else
                 strlcpy(lname, dest, buf + sizeof buff - lname);                  (void) strlcpy(lname, dest, buf + sizeof buff - lname);
   
         debugmsg(DM_MISC, "remfilename: remote filename=%s\n", lname);          debugmsg(DM_MISC, "remfilename: remote filename=%s\n", lname);
   
Line 144 
Line 158 
 /*  /*
  * Return true if name is in the list.   * Return true if name is in the list.
  */   */
 int inlist(list, file)  int
         struct namelist *list;  inlist(struct namelist *list, char *file)
         char *file;  
 {  {
         struct namelist *nl;          struct namelist *nl;
   
Line 159 
Line 172 
 /*  /*
  * Run any special commands for this file   * Run any special commands for this file
  */   */
 static void runspecial(starget, opts, rname, destdir)  static void
         char *starget;  runspecial(char *starget, opt_t opts, char *rname, int destdir)
         opt_t opts;  
         char *rname;  
         int destdir;  
 {  {
         struct subcmd *sc;          struct subcmd *sc;
         extern struct subcmd *subcmds;          extern struct subcmd *subcmds;
Line 195 
Line 205 
  * If we're doing a target with a "cmdspecial" in it, then   * If we're doing a target with a "cmdspecial" in it, then
  * save the name of the file being updated for use with "cmdspecial".   * save the name of the file being updated for use with "cmdspecial".
  */   */
 static void addcmdspecialfile(starget, rname, destdir)  static void
         char *starget;  addcmdspecialfile(char *starget, char *rname, int destdir)
         char *rname;  
         int destdir;  
 {  {
         char *rfile;          char *rfile;
         struct namelist *new;          struct namelist *new;
Line 228 
Line 236 
 /*  /*
  * Free the file list   * Free the file list
  */   */
 static void freecmdspecialfiles()  static void
   freecmdspecialfiles(void)
 {  {
         struct namelist *ptr, *save;          struct namelist *ptr, *save;
   
Line 247 
Line 256 
 /*  /*
  * Run commands for an entire cmd   * Run commands for an entire cmd
  */   */
 extern void runcmdspecial(cmd, filev, opts)  void
         struct cmd *cmd;  runcmdspecial(struct cmd *cmd, opt_t opts)
         char **filev;  
         opt_t opts;  
 {  {
         struct subcmd *sc;          struct subcmd *sc;
         struct namelist *f;          struct namelist *f;
Line 292 
Line 299 
 /*  /*
  * For security, reject filenames that contains a newline   * For security, reject filenames that contains a newline
  */   */
 int checkfilename(name)  int
         char *name;  checkfilename(char *name)
 {  {
         char *cp;          char *cp;
   
Line 310 
Line 317 
         return(0);          return(0);
 }  }
   
 void freelinkinfo(lp)  void
         struct linkbuf *lp;  freelinkinfo(struct linkbuf *lp)
 {  {
         if (lp->pathname)          if (lp->pathname)
                 free(lp->pathname);                  free(lp->pathname);
Line 325 
Line 332 
 /*  /*
  * Save and retrieve hard link info   * Save and retrieve hard link info
  */   */
 static struct linkbuf *linkinfo(statp)  static struct linkbuf *
         struct stat *statp;  linkinfo(struct stat *statp)
 {  {
         struct linkbuf *lp;          struct linkbuf *lp;
   
Line 356 
Line 363 
 /*  /*
  * Send a hardlink   * Send a hardlink
  */   */
 static int sendhardlink(opts, lp, rname, destdir)  static int
         opt_t opts;  sendhardlink(opt_t opts, struct linkbuf *lp, char *rname, int destdir)
         struct linkbuf *lp;  
         char *rname;  
         int destdir;  
 {  {
         static char buff[MAXPATHLEN];          static char buff[MAXPATHLEN];
           char *lname;    /* name of file to link to */
           char ername[MAXPATHLEN*4], elname[MAXPATHLEN*4];
   
         debugmsg(DM_MISC,          debugmsg(DM_MISC,
                "sendhardlink: rname='%s' pathname='%s' src='%s' target='%s'\n",                 "sendhardlink: rname='%s' pathname='%s' src='%s' target='%s'\n",
                  rname, lp->pathname ? lp->pathname : "(null)", lp->src                  rname, lp->pathname ? lp->pathname : "",
                  ? lp->src : "(null)", lp->target ? lp->target : "(null)");                  lp->src ? lp->src : "", lp->target ? lp->target : "");
   
         if (lp->target == NULL)          if (lp->target == NULL)
                 (void) sendcmd(C_RECVHARDLINK, "%o %s %s",                  lname = lp->pathname;
                                opts, lp->pathname, rname);  
         else {          else {
                 strlcpy(buff, remfilename(lp->src, lp->target,                  lname = buff;
                     lp->pathname, rname, destdir), sizeof buff);                  strlcpy(lname, remfilename(lp->src, lp->target,
                 debugmsg(DM_MISC, "sendhardlink: lname=%s\n", buff);                                            lp->pathname, rname,
                 (void) sendcmd(C_RECVHARDLINK, "%o %s %s",                                            destdir), sizeof(buff));
                                opts, buff, rname);                  debugmsg(DM_MISC, "sendhardlink: lname=%s\n", lname);
         }          }
           ENCODE(elname, lname);
           ENCODE(ername, rname);
           (void) sendcmd(C_RECVHARDLINK, "%o %s %s",
                          opts, elname, ername);
   
         return(response());          return(response());
 }  }
Line 386 
Line 395 
 /*  /*
  * Send a file   * Send a file
  */   */
 static int sendfile(rname, opts, stb, user, group, destdir)  static int
         char *rname;  sendfile(char *rname, opt_t opts, struct stat *stb, char *user,
         opt_t opts;           char *group, int destdir)
         struct stat *stb;  
         char *user, *group;  
         int destdir;  
 {  {
         int goterr, f;          int goterr, f;
         off_t i;          off_t i;
           char ername[MAXPATHLEN*4];
   
         if (stb->st_nlink > 1) {          if (stb->st_nlink > 1) {
                 struct linkbuf *lp;                  struct linkbuf *lp;
Line 411 
Line 418 
         /*          /*
          * Send file info           * Send file info
          */           */
           ENCODE(ername, rname);
   
         (void) sendcmd(C_RECVREG, "%o %04o %ld %ld %ld %s %s %s",          (void) sendcmd(C_RECVREG, "%o %04o %ld %ld %ld %s %s %s",
                        opts, stb->st_mode & 07777,                         opts, stb->st_mode & 07777, (long) stb->st_size,
                        (long) stb->st_size,  
                        stb->st_mtime, stb->st_atime,                         stb->st_mtime, stb->st_atime,
                        user, group, rname);                         user, group, ername);
         if (response() < 0) {          if (response() < 0) {
                 (void) close(f);                  (void) close(f);
                 return(-1);                  return(-1);
         }          }
   
         debugmsg(DM_MISC, "Send file '%s' %d bytes\n",  
                  rname, (long) stb->st_size);  
   
           debugmsg(DM_MISC, "Send file '%s' %ld bytes\n", rname,
                    (long) stb->st_size);
   
         /*          /*
          * Set remote time out alarm handler.           * Set remote time out alarm handler.
          */           */
Line 434 
Line 443 
          */           */
         goterr = 0;          goterr = 0;
         for (i = 0; i < stb->st_size; i += BUFSIZ) {          for (i = 0; i < stb->st_size; i += BUFSIZ) {
                 int amt = BUFSIZ;                  off_t amt = BUFSIZ;
   
                 (void) alarm(rtimeout);                  (void) alarm(rtimeout);
                 if (i + amt > stb->st_size)                  if (i + amt > stb->st_size)
                         amt = stb->st_size - i;                          amt = stb->st_size - i;
                 if (read(f, buf, amt) != amt) {                  if (read(f, buf, (size_t) amt) != (ssize_t) amt) {
                         error("%s: File changed size", target);                          error("%s: File changed size", target);
                         err();                          err();
                         ++goterr;                          ++goterr;
Line 451 
Line 460 
                          * this situation gracefully.                           * this situation gracefully.
                          */                           */
                 }                  }
                 if (xwrite(rem_w, buf, amt) < 0) {                  if (xwrite(rem_w, buf, (size_t) amt) < 0) {
                         error("%s: Error writing to client: %s",                          error("%s: Error writing to client: %s",
                               target, SYSERR);                                target, SYSERR);
                         err();                          err();
                         ++goterr;                          ++goterr;
Line 495 
Line 504 
  * Return 0 if nothing happened.   * Return 0 if nothing happened.
  * Return > 0 if anything is updated.   * Return > 0 if anything is updated.
  */   */
 static int rmchk(opts)  static int
         opt_t opts;  rmchk(opt_t opts)
 {  {
         u_char *s;          u_char *s;
         struct stat stb;          struct stat stb;
         int didupdate = 0;          int didupdate = 0;
         int n;          int n;
           char targ[MAXPATHLEN*4];
   
         debugmsg(DM_CALL, "rmchk()\n");          debugmsg(DM_CALL, "rmchk()\n");
   
Line 526 
Line 536 
                          * CC_NO -- file exists - DON'T remove.                           * CC_NO -- file exists - DON'T remove.
                          * CC_YES -- file doesn't exist - REMOVE.                           * CC_YES -- file doesn't exist - REMOVE.
                          */                           */
                         snprintf(ptarget, target + sizeof(target) - ptarget,                          if (DECODE(targ, (char *) s) == -1) {
                             "%s%s", (ptarget[-1] == '/' ? "" : "/"), s);                                  error("rmchk: cannot decode file");
                                   return(-1);
                           }
                           (void) snprintf(ptarget,
                                           sizeof(target) - (ptarget - target),
                                           "%s%s",
                                           (ptarget[-1] == '/' ? "" : "/"),
                                           targ);
                         debugmsg(DM_MISC, "check %s\n", target);                          debugmsg(DM_MISC, "check %s\n", target);
                         if (except(target))                          if (except(target))
                                 (void) sendcmd(CC_NO, NULL);                                  (void) sendcmd(CC_NO, NULL);
Line 577 
Line 594 
  * Return 0 if nothing happened.   * Return 0 if nothing happened.
  * Return > 0 if anything is updated.   * Return > 0 if anything is updated.
  */   */
 static int senddir(rname, opts, stb, user, group, destdir)  static int
         char *rname;  senddir(char *rname, opt_t opts, struct stat *stb, char *user,
         opt_t opts;          char *group, int destdir)
         struct stat *stb;  
         char *user, *group;  
         int destdir;  
 {  {
         DIRENTRY *dp;          DIRENTRY *dp;
         DIR *d;          DIR *d;
         char *optarget, *cp;          char *optarget, *cp;
         int len;          int len;
         int didupdate = 0;          int didupdate = 0;
           char ername[MAXPATHLEN*4];
   
         /*          /*
          * Don't descend into directory  
          */  
         if (IS_ON(opts, DO_NODESCEND))  
                 return(0);  
   
         if ((d = opendir(target)) == NULL) {  
                 error("%s: opendir failed: %s", target, SYSERR);  
                 return(-1);  
         }  
   
         /*  
          * Send recvdir command in recvit() format.           * Send recvdir command in recvit() format.
          */           */
           ENCODE(ername, rname);
         (void) sendcmd(C_RECVDIR, "%o %04o 0 0 0 %s %s %s",          (void) sendcmd(C_RECVDIR, "%o %04o 0 0 0 %s %s %s",
                        opts, stb->st_mode & 07777, user, group, rname);                         opts, stb->st_mode & 07777, user, group, ername);
         if (response() < 0)          if (response() < 0)
                 return(-1);                  return(-1);
   
           /*
            * Don't descend into directory
            */
           if (IS_ON(opts, DO_NODESCEND))
                   return(0);
   
         if (IS_ON(opts, DO_REMOVE))          if (IS_ON(opts, DO_REMOVE))
                 if (rmchk(opts) > 0)                  if (rmchk(opts) > 0)
                         ++didupdate;                          ++didupdate;
   
           if ((d = opendir(target)) == NULL) {
                   error("%s: opendir failed: %s", target, SYSERR);
                   return(-1);
           }
   
         optarget = ptarget;          optarget = ptarget;
         len = ptarget - target;          len = ptarget - target;
         while ((dp = readdir(d))) {          while ((dp = readdir(d)) != NULL) {
                 if (!strcmp(dp->d_name, ".") ||                  if (!strcmp(dp->d_name, ".") ||
                     !strcmp(dp->d_name, ".."))                      !strcmp(dp->d_name, ".."))
                         continue;                          continue;
Line 628 
Line 644 
                 if (ptarget[-1] != '/')                  if (ptarget[-1] != '/')
                         *ptarget++ = '/';                          *ptarget++ = '/';
                 cp = dp->d_name;                  cp = dp->d_name;
                 while ((*ptarget++ = *cp++))                  while ((*ptarget++ = *cp++) != '\0')
                         ;                          continue;
                 ptarget--;                  ptarget--;
                 if (sendit(dp->d_name, opts, destdir) > 0)                  if (sendit(dp->d_name, opts, destdir) > 0)
                         didupdate = 1;                          didupdate = 1;
Line 648 
Line 664 
 /*  /*
  * Send a link   * Send a link
  */   */
 static int sendlink(rname, opts, stb, user, group, destdir)  static int
         char *rname;  sendlink(char *rname, opt_t opts, struct stat *stb, char *user,
         opt_t opts;           char *group, int destdir)
         struct stat *stb;  
         char *user;  
         char *group;  
         int destdir;  
 {  {
         int f, n;          int f, n;
         static char tbuf[BUFSIZ];          static char tbuf[BUFSIZ];
         char lbuf[MAXPATHLEN];          char lbuf[MAXPATHLEN];
         u_char *s;          u_char *s;
           char ername[MAXPATHLEN*4];
   
         debugmsg(DM_CALL, "sendlink(%s, %x, stb, %d)\n", rname, opts, destdir);          debugmsg(DM_CALL, "sendlink(%s, %x, stb, %d)\n", rname, opts, destdir);
   
Line 673 
Line 686 
         /*          /*
          * Gather and send basic link info           * Gather and send basic link info
          */           */
           ENCODE(ername, rname);
         (void) sendcmd(C_RECVSYMLINK, "%o %04o %ld %ld %ld %s %s %s",          (void) sendcmd(C_RECVSYMLINK, "%o %04o %ld %ld %ld %s %s %s",
                        opts, stb->st_mode & 07777,                         opts, stb->st_mode & 07777, (long) stb->st_size,
                        (long) stb->st_size,  
                        stb->st_mtime, stb->st_atime,                         stb->st_mtime, stb->st_atime,
                        user, group, rname);                         user, group, ername);
         if (response() < 0)          if (response() < 0)
                 return(-1);                  return(-1);
   
Line 690 
Line 703 
                 error("%s: readlink failed", target);                  error("%s: readlink failed", target);
                 err();                  err();
         }          }
         (void) snprintf(tbuf, sizeof tbuf, "%.*s", (int) stb->st_size, lbuf);          (void) snprintf(tbuf, sizeof(tbuf), "%.*s", (int) stb->st_size, lbuf);
         (void) sendcmd(C_NONE, "%s\n", tbuf);          ENCODE(ername, tbuf);
           (void) sendcmd(C_NONE, "%s\n", ername);
   
         if (n != stb->st_size) {          if (n != stb->st_size) {
                 error("%s: file changed size", target);                  error("%s: file changed size", target);
Line 765 
Line 779 
  *      US_NOENT        - remote doesn't exist   *      US_NOENT        - remote doesn't exist
  *      US_OUTDATE      - out of date   *      US_OUTDATE      - out of date
  *      US_DOCOMP       - comparing binaries to determine if out of date   *      US_DOCOMP       - comparing binaries to determine if out of date
  *      US_MODE         - File modes do not match   *      US_CHMOG        - File modes or ownership do not match
  */   */
 static int update(rname, opts, statp)  static int
         char *rname;  update(char *rname, opt_t opts, struct stat *statp)
         opt_t opts;  
         struct stat *statp;  
 {  {
         off_t size;          off_t size;
         time_t mtime;          time_t mtime;
Line 779 
Line 791 
         char *owner = NULL, *group = NULL;          char *owner = NULL, *group = NULL;
         int done, n;          int done, n;
         u_char *cp;          u_char *cp;
           char ername[MAXPATHLEN*4];
   
         debugmsg(DM_CALL, "update(%s, 0x%x, 0x%x)\n", rname, opts, statp);          debugmsg(DM_CALL, "update(%s, 0x%x, 0x%x)\n", rname, opts, statp);
   
Line 791 
Line 804 
         /*          /*
          * Check to see if the file exists on the remote machine.           * Check to see if the file exists on the remote machine.
          */           */
         (void) sendcmd(C_QUERY, "%s", rname);          ENCODE(ername, rname);
           (void) sendcmd(C_QUERY, "%s", ername);
   
         for (done = 0; !done;) {          for (done = 0; !done;) {
                 n = remline(cp = respbuff, sizeof(respbuff), TRUE);                  n = remline(cp = respbuff, sizeof(respbuff), TRUE);
Line 843 
Line 857 
                         /* Goto top of loop */                          /* Goto top of loop */
   
                 default:                  default:
                         error("update: unexpected response to query '%s'", cp);                          error("update: unexpected response to query '%s'", respbuff);
                         return(US_NOTHING);                          return(US_NOTHING);
                 }                  }
         }          }
Line 860 
Line 874 
         /*          /*
          * Parse size           * Parse size
          */           */
         size = strtol(cp, (char **)&cp, 10);          size = (off_t) strtol(cp, (char **)&cp, 10);
         if (*cp++ != ' ') {          if (*cp++ != ' ') {
                 error("update: size not delimited");                  error("update: size not delimited");
                 return(US_NOTHING);                  return(US_NOTHING);
Line 912 
Line 926 
   
         debugmsg(DM_MISC, "update(%s,) local mode %04o remote mode %04o\n",          debugmsg(DM_MISC, "update(%s,) local mode %04o remote mode %04o\n",
                  rname, lmode, rmode);                   rname, lmode, rmode);
         debugmsg(DM_MISC, "update(%s,) size %d mtime %d owner '%s' grp '%s'\n",          debugmsg(DM_MISC, "update(%s,) size %ld mtime %d owner '%s' grp '%s'\n",
                  rname, (int) size, mtime, owner, group);                   rname, (long) size, mtime, owner, group);
   
         if (statp->st_mtime != mtime) {          if (statp->st_mtime != mtime) {
                 if (statp->st_mtime < mtime && IS_ON(opts, DO_YOUNGER)) {                  if (statp->st_mtime < mtime && IS_ON(opts, DO_YOUNGER)) {
Line 925 
Line 939 
                 return(US_OUTDATE);                  return(US_OUTDATE);
         }          }
   
         /*          if (statp->st_size != size) {
          * If the mode of a file does not match the local mode, the                  debugmsg(DM_MISC, "size does not match (%ld != %ld).\n",
          * whole file is updated.  This is done both to insure that                           (long) statp->st_size, (long) size);
          * a bogus version of the file has not been installed and to                  return(US_OUTDATE);
          * avoid having to handle weird cases of chmod'ing symlinks          }
          * and such.  
          */  
         if (!IS_ON(opts, DO_NOCHKMODE) && lmode != rmode) {          if (!IS_ON(opts, DO_NOCHKMODE) && lmode != rmode) {
                 debugmsg(DM_MISC, "modes do not match (%04o != %04o).\n",                  debugmsg(DM_MISC, "modes do not match (%04o != %04o).\n",
                          lmode, rmode);                           lmode, rmode);
                 return(US_OUTDATE);                  return(US_CHMOG);
         }          }
   
         if (statp->st_size != size) {  
                 debugmsg(DM_MISC, "size does not match (%d != %d).\n",  
                          (int) statp->st_size, size);  
                 return(US_OUTDATE);  
         }  
   
         /*          /*
          * Check ownership           * Check ownership
Line 956 
Line 964 
                                          "owner does not match (%s != %s).\n",                                           "owner does not match (%s != %s).\n",
                                          getusername(statp->st_uid,                                           getusername(statp->st_uid,
                                                      target, opts), owner);                                                       target, opts), owner);
                                 return(US_OUTDATE);                                  return(US_CHMOG);
                         }                          }
                 } else {                  } else {
                         /*                          /*
                          * Check numerically.                           * Check numerically.
                          * Allow negative numbers.                           * Allow negative numbers.
                          */                           */
                         while (*owner && !isdigit(*owner) && (*owner != '-'))                          while (*owner && !isdigit((unsigned char)*owner) &&
                               (*owner != '-'))
                                 ++owner;                                  ++owner;
                         if (owner && atoi(owner) != statp->st_uid) {                          if (owner && (UID_T) atoi(owner) != statp->st_uid) {
                                 debugmsg(DM_MISC,                                  debugmsg(DM_MISC,
                                          "owner does not match (%d != %s).\n",                                           "owner does not match (%d != %s).\n",
                                          statp->st_uid, owner);                                           statp->st_uid, owner);
                                 return(US_OUTDATE);                                  return(US_CHMOG);
                         }                          }
                 }                  }
         }          }
Line 983 
Line 992 
                                          "group does not match (%s != %s).\n",                                           "group does not match (%s != %s).\n",
                                          getgroupname(statp->st_gid,                                           getgroupname(statp->st_gid,
                                                       target, opts), group);                                                        target, opts), group);
                                 return(US_OUTDATE);                                  return(US_CHMOG);
                         }                          }
                 } else {                  } else {
                         /* Check numerically */                          /* Check numerically */
                         /* Allow negative gid */                          /* Allow negative gid */
                         while (*group && !isdigit(*group) && (*group != '-'))                          while (*group && !isdigit((unsigned char) *group) &&
                               (*group != '-'))
                                 ++group;                                  ++group;
                         if (group && atoi(group) != statp->st_gid) {                          if (group && (UID_T) atoi(group) != statp->st_gid) {
                                 debugmsg(DM_MISC,                                  debugmsg(DM_MISC,
                                          "group does not match (%d != %s).\n",                                           "group does not match (%d != %s).\n",
                                          statp->st_gid, group);                                           statp->st_gid, group);
                                 return(US_OUTDATE);                                  return(US_CHMOG);
                         }                          }
                 }                  }
         }          }
Line 1005 
Line 1015 
 /*  /*
  * Stat a file   * Stat a file
  */   */
 static int dostat(file, statbuf, opts)  static int
         char *file;  dostat(char *file, struct stat *statbuf, opt_t opts)
         struct stat *statbuf;  
         opt_t opts;  
 {  {
         int s;          int s;
   
Line 1024 
Line 1032 
 }  }
   
 /*  /*
    * We need to just change file info.
    */
   static int
   statupdate(int u, char *target, opt_t opts, char *rname, int destdir,
              struct stat *st, char *user, char *group)
   {
           int rv = 0;
           char ername[MAXPATHLEN*4];
           int lmode = st->st_mode & 07777;
   
           if (u == US_CHMOG) {
                   if (IS_ON(opts, DO_VERIFY)) {
                           message(MT_INFO,
                                   "%s: need to change to perm %04o, owner %s, group %s",
                                   target, lmode, user, group);
                           runspecial(target, opts, rname, destdir);
                   }
                   else {
                           message(MT_CHANGE, "%s: change to perm %04o, owner %s, group %s",
                                   target, lmode, user, group);
                           ENCODE(ername, rname);
                           (void) sendcmd(C_CHMOG, "%o %04o %s %s %s",
                                          opts, lmode, user, group, ername);
                           (void) response();
                   }
                   rv = 1;
           }
           return(rv);
   }
   
   
   /*
    * We need to install/update:
    */
   static int
   fullupdate(int u, char *target, opt_t opts, char *rname, int destdir,
              struct stat *st, char *user, char *group)
   {
           /*
            * No entry - need to install
            */
           if (u == US_NOENT) {
                   if (IS_ON(opts, DO_VERIFY)) {
                           message(MT_INFO, "%s: need to install", target);
                           runspecial(target, opts, rname, destdir);
                           return(1);
                   }
                   if (!IS_ON(opts, DO_QUIET))
                           message(MT_CHANGE, "%s: installing", target);
                   FLAG_OFF(opts, (DO_COMPARE|DO_REMOVE));
           }
   
           /*
            * Handle special file types, including directories and symlinks
            */
           if (S_ISDIR(st->st_mode)) {
                   if (senddir(rname, opts, st, user, group, destdir) > 0)
                           return(1);
                   return(0);
           } else if (S_ISLNK(st->st_mode)) {
                   if (u == US_NOENT)
                           FLAG_ON(opts, DO_COMPARE);
                   /*
                    * Since we always send link info to the server
                    * so the server can determine if the remote link
                    * is correct, we never get any acknowledge meant
                    * from the server whether the link was really
                    * updated or not.
                    */
                   (void) sendlink(rname, opts, st, user, group, destdir);
                   return(0);
           } else if (S_ISREG(st->st_mode)) {
                   if (u == US_OUTDATE) {
                           if (IS_ON(opts, DO_VERIFY)) {
                                   message(MT_INFO, "%s: need to update", target);
                                   runspecial(target, opts, rname, destdir);
                                   return(1);
                           }
                           if (!IS_ON(opts, DO_QUIET))
                                   message(MT_CHANGE, "%s: updating", target);
                   }
                   return (sendfile(rname, opts, st, user, group, destdir) == 0);
           } else {
                   message(MT_INFO, "%s: unknown file type 0%o", target,
                           st->st_mode);
                   return(0);
           }
   }
   
   /*
  * Transfer the file or directory in target[].   * Transfer the file or directory in target[].
  * rname is the name of the file on the remote host.   * rname is the name of the file on the remote host.
  *   *
Line 1031 
Line 1129 
  * Return 0 if nothing happened.   * Return 0 if nothing happened.
  * Return > 0 if anything is updated.   * Return > 0 if anything is updated.
  */   */
 static int sendit(rname, opts, destdir)  static int
         char *rname;  sendit(char *rname, opt_t opts, int destdir)
         opt_t opts;  
         int destdir;  
 {  {
         static struct stat stb;          static struct stat stb;
         extern struct subcmd *subcmds;  
         char *user, *group;          char *user, *group;
         int u, len;          int u, len;
         int didupdate = 0;  
   
         /*          /*
          * Remove possible accidental newline           * Remove possible accidental newline
Line 1077 
Line 1171 
                 return(0);                  return(0);
         }          }
   
         /*  
          * File mode needs changing  
          */  
         if (u == US_MODE) {  
                 if (IS_ON(opts, DO_VERIFY)) {  
                         message(MT_INFO, "%s: need to chmod to %04o",  
                                 target, stb.st_mode & 07777);  
                         runspecial(target, opts, rname, destdir);  
                         return(1);  
                 }  
                 message(MT_CHANGE, "%s: chmod to %04o",  
                         target, stb.st_mode & 07777);  
                 (void) sendcmd(C_CHMOD, "%o %04o %s",  
                                opts, stb.st_mode & 07777, rname);  
                 (void) response();  
                 return(1);  
         }  
   
         user = getusername(stb.st_uid, target, opts);          user = getusername(stb.st_uid, target, opts);
         group = getgroupname(stb.st_gid, target, opts);          group = getgroupname(stb.st_gid, target, opts);
   
         /*          if (u == US_CHMOG && IS_OFF(opts, DO_UPDATEPERM))
          * No entry - need to install                  u = US_OUTDATE;
          */  
         if (u == US_NOENT) {  
                 if (IS_ON(opts, DO_VERIFY)) {  
                         message(MT_INFO, "%s: need to install", target);  
                         runspecial(target, opts, rname, destdir);  
                         return(1);  
                 }  
                 if (!IS_ON(opts, DO_QUIET))  
                         message(MT_CHANGE, "%s: installing", target);  
                 FLAG_OFF(opts, (DO_COMPARE|DO_REMOVE));  
         }  
   
         /*          if (u == US_NOENT || u == US_OUTDATE || u == US_DOCOMP)
          * Handle special file types, including directories and symlinks                  return(fullupdate(u, target, opts, rname, destdir, &stb,
          */                                    user, group));
         if (S_ISDIR(stb.st_mode)) {  
                 if (senddir(rname, opts, &stb, user, group, destdir) > 0)  
                         didupdate = 1;  
         } else if (S_ISLNK(stb.st_mode)) {  
                 if (u != US_NOENT)  
                         FLAG_ON(opts, DO_COMPARE);  
                 /*  
                  * Since we always send link info to the server  
                  * so the server can determine if the remote link  
                  * is correct, we never get any acknowledge meant  
                  * from the server whether the link was really  
                  * updated or not.  
                  */  
                 (void) sendlink(rname, opts, &stb, user, group, destdir);  
         } else if (S_ISREG(stb.st_mode)) {  
                 if (u == US_OUTDATE) {  
                         if (IS_ON(opts, DO_VERIFY)) {  
                                 message(MT_INFO, "%s: need to update", target);  
                                 runspecial(target, opts, rname, destdir);  
                                 return(1);  
                         }  
                         if (!IS_ON(opts, DO_QUIET))  
                                 message(MT_CHANGE, "%s: updating", target);  
                 }  
                 if (sendfile(rname, opts, &stb, user, group, destdir) == 0)  
                         didupdate = 1;  
         } else  
                 error("%s: unknown file type", target);  
   
         return(didupdate);          if (u == US_CHMOG)
                   return(statupdate(u, target, opts, rname, destdir, &stb,
                                     user, group));
   
           return(0);
 }  }
   
 /*  /*
  * Remove temporary files and do any cleanup operations before exiting.   * Remove temporary files and do any cleanup operations before exiting.
  */   */
 extern void cleanup()  void
   cleanup(int dummy)
 {  {
         char *file;          char *file;
 #ifdef USE_STATDB  #ifdef USE_STATDB
Line 1159 
Line 1201 
         (void) unlink(statfile);          (void) unlink(statfile);
 #endif  #endif
   
         if ((file = getnotifyfile()))          if ((file = getnotifyfile()) != NULL)
                 (void) unlink(file);                  (void) unlink(file);
 }  }
   
Line 1172 
Line 1214 
  * Return 0 if nothing updated.   * Return 0 if nothing updated.
  * Return > 0 if something was updated.   * Return > 0 if something was updated.
  */   */
 extern int install(src, dest, ddir, destdir, opts)  int
         char *src, *dest;  install(char *src, char *dest, int ddir, int destdir, opt_t opts)
         int ddir, destdir;  
         opt_t opts;  
 {  {
         static char destcopy[MAXPATHLEN];          static char destcopy[MAXPATHLEN];
         char *rname;          char *rname;
         int didupdate = 0;          int didupdate = 0;
           char ername[MAXPATHLEN*4];
   
         debugmsg(DM_CALL,          debugmsg(DM_CALL,
                 "install(src=%s,dest=%s,ddir=%d,destdir=%d,opts=%d) start\n",                  "install(src=%s,dest=%s,ddir=%d,destdir=%d,opts=%d) start\n",
Line 1190 
Line 1231 
         if (IS_ON(opts, DO_WHOLE))          if (IS_ON(opts, DO_WHOLE))
                 source[0] = CNULL;                  source[0] = CNULL;
         else          else
                 (void) strlcpy(source, src, sizeof source);                  (void) strlcpy(source, src, sizeof(source));
   
         if (dest == NULL) {          if (dest == NULL) {
                 FLAG_OFF(opts, DO_WHOLE); /* WHOLE only useful if renaming */                  FLAG_OFF(opts, DO_WHOLE); /* WHOLE only useful if renaming */
Line 1205 
Line 1246 
                 char *cp;                  char *cp;
   
                 cp = getondistoptlist(opts);                  cp = getondistoptlist(opts);
                 (void) snprintf(buff, sizeof buff, "%s%s%s %s %s",                  (void) snprintf(buff, sizeof(buff), "%s%s%s %s %s",
                                IS_ON(opts, DO_VERIFY) ? "verify" : "install",                                 IS_ON(opts, DO_VERIFY) ? "verify" : "install",
                                (cp) ? " -o" : "", (cp) ? cp : "",                                 (cp) ? " -o" : "", (cp) ? cp : "",
                                src, dest);                                 src, dest);
Line 1250 
Line 1291 
         /*          /*
          * Pass the destination file/directory name to remote.           * Pass the destination file/directory name to remote.
          */           */
           ENCODE(ername, dest);
         if (ddir)          if (ddir)
                 (void) sendcmd(C_DIRTARGET, "%o %s", opts, dest);                  (void) sendcmd(C_DIRTARGET, "%o %s", opts, ername);
         else          else
                 (void) sendcmd(C_TARGET, "%o %s", opts, dest);                  (void) sendcmd(C_TARGET, "%o %s", opts, ername);
         if (response() < 0)          if (response() < 0)
                 return(-1);                  return(-1);
   
Line 1264 
Line 1306 
          * hardlink info.           * hardlink info.
          */           */
         if (destdir || (src && dest && strcmp(src, dest))) {          if (destdir || (src && dest && strcmp(src, dest))) {
                 (void) strlcpy(destcopy, dest, sizeof destcopy);                  (void) strlcpy(destcopy, dest, sizeof(destcopy));
                 Tdest = destcopy;                  Tdest = destcopy;
         }          }
   

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.18