Diff for /embedaddon/rsync/util.c between versions 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2012/02/17 15:09:30 version 1.1.1.3, 2016/11/01 09:54:32
Line 4 Line 4
  * Copyright (C) 1996-2000 Andrew Tridgell   * Copyright (C) 1996-2000 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras   * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>   * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
 * Copyright (C) 2003-2009 Wayne Davison * Copyright (C) 2003-2015 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 22 Line 22
   
 #include "rsync.h"  #include "rsync.h"
 #include "ifuncs.h"  #include "ifuncs.h"
   #include "itypes.h"
   #include "inums.h"
   
extern int verbose;extern int dry_run;
 extern int module_id;  extern int module_id;
   extern int protect_args;
 extern int modify_window;  extern int modify_window;
 extern int relative_paths;  extern int relative_paths;
 extern int preserve_times;  extern int preserve_times;
 extern int human_readable;  
 extern int preserve_xattrs;  extern int preserve_xattrs;
   extern int preallocate_files;
 extern char *module_dir;  extern char *module_dir;
 extern unsigned int module_dirlen;  extern unsigned int module_dirlen;
 extern mode_t orig_umask;  
 extern char *partial_dir;  extern char *partial_dir;
extern struct filter_list_struct daemon_filter_list;extern filter_rule_list daemon_filter_list;
   
 int sanitize_paths = 0;  int sanitize_paths = 0;
   
Line 94  int fd_pair(int fd[2]) Line 96  int fd_pair(int fd[2])
   
 void print_child_argv(const char *prefix, char **cmd)  void print_child_argv(const char *prefix, char **cmd)
 {  {
           int cnt = 0;
         rprintf(FCLIENT, "%s ", prefix);          rprintf(FCLIENT, "%s ", prefix);
         for (; *cmd; cmd++) {          for (; *cmd; cmd++) {
                 /* Look for characters that ought to be quoted.  This                  /* Look for characters that ought to be quoted.  This
Line 107  void print_child_argv(const char *prefix, char **cmd) Line 110  void print_child_argv(const char *prefix, char **cmd)
                 } else {                  } else {
                         rprintf(FCLIENT, "%s ", *cmd);                          rprintf(FCLIENT, "%s ", *cmd);
                 }                  }
                   cnt++;
         }          }
        rprintf(FCLIENT, "\n");        rprintf(FCLIENT, " (%d args)\n", cnt);
 }  }
   
 NORETURN void out_of_memory(const char *str)  
 {  
         rprintf(FERROR, "ERROR: out of memory in %s [%s]\n", str, who_am_i());  
         exit_cleanup(RERR_MALLOC);  
 }  
   
 NORETURN void overflow_exit(const char *str)  
 {  
         rprintf(FERROR, "ERROR: buffer overflow in %s [%s]\n", str, who_am_i());  
         exit_cleanup(RERR_MALLOC);  
 }  
   
 /* This returns 0 for success, 1 for a symlink if symlink time-setting  /* This returns 0 for success, 1 for a symlink if symlink time-setting
  * is not possible, or -1 for any other error. */   * is not possible, or -1 for any other error. */
int set_modtime(const char *fname, time_t modtime, mode_t mode)int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode)
 {  {
         static int switch_step = 0;          static int switch_step = 0;
   
        if (verbose > 2) {        if (DEBUG_GTE(TIME, 1)) {
                 rprintf(FINFO, "set modtime of %s to (%ld) %s",                  rprintf(FINFO, "set modtime of %s to (%ld) %s",
                         fname, (long)modtime,                          fname, (long)modtime,
                         asctime(localtime(&modtime)));                          asctime(localtime(&modtime)));
Line 138  int set_modtime(const char *fname, time_t modtime, mod Line 130  int set_modtime(const char *fname, time_t modtime, mod
         switch (switch_step) {          switch (switch_step) {
 #ifdef HAVE_UTIMENSAT  #ifdef HAVE_UTIMENSAT
 #include "case_N.h"  #include "case_N.h"
                if (do_utimensat(fname, modtime, 0) == 0)                if (do_utimensat(fname, modtime, mod_nsec) == 0)
                         break;                          break;
                 if (errno != ENOSYS)                  if (errno != ENOSYS)
                         return -1;                          return -1;
Line 148  int set_modtime(const char *fname, time_t modtime, mod Line 140  int set_modtime(const char *fname, time_t modtime, mod
   
 #ifdef HAVE_LUTIMES  #ifdef HAVE_LUTIMES
 #include "case_N.h"  #include "case_N.h"
                if (do_lutimes(fname, modtime, 0) == 0)                if (do_lutimes(fname, modtime, mod_nsec) == 0)
                         break;                          break;
                 if (errno != ENOSYS)                  if (errno != ENOSYS)
                         return -1;                          return -1;
Line 167  int set_modtime(const char *fname, time_t modtime, mod Line 159  int set_modtime(const char *fname, time_t modtime, mod
   
 #include "case_N.h"  #include "case_N.h"
 #ifdef HAVE_UTIMES  #ifdef HAVE_UTIMES
                if (do_utimes(fname, modtime, 0) == 0)                if (do_utimes(fname, modtime, mod_nsec) == 0)
                         break;                          break;
 #else  #else
                if (do_utime(fname, modtime, 0) == 0)                if (do_utime(fname, modtime, mod_nsec) == 0)
                         break;                          break;
 #endif  #endif
   
Line 180  int set_modtime(const char *fname, time_t modtime, mod Line 172  int set_modtime(const char *fname, time_t modtime, mod
         return 0;          return 0;
 }  }
   
 /* This creates a new directory with default permissions.  Since there  
  * might be some directory-default permissions affecting this, we can't  
  * force the permissions directly using the original umask and mkdir(). */  
 int mkdir_defmode(char *fname)  
 {  
         int ret;  
   
         umask(orig_umask);  
         ret = do_mkdir(fname, ACCESSPERMS);  
         umask(0);  
   
         return ret;  
 }  
   
 /* Create any necessary directories in fname.  Any missing directories are  /* Create any necessary directories in fname.  Any missing directories are
 * created with default permissions. */ * created with default permissions.  Returns < 0 on error, or the number
int create_directory_path(char *fname) * of directories created. */
 int make_path(char *fname, int flags)
 {  {
        char *p;        char *end, *p;
         int ret = 0;          int ret = 0;
   
        while (*fname == '/')        if (flags & MKP_SKIP_SLASH) {
                fname++;                while (*fname == '/')
        while (strncmp(fname, "./", 2) == 0)                        fname++;
         }
 
         while (*fname == '.' && fname[1] == '/')
                 fname += 2;                  fname += 2;
   
        umask(orig_umask);        if (flags & MKP_DROP_NAME) {
        p = fname;                end = strrchr(fname, '/');
        while ((p = strchr(p,'/')) != NULL) {                if (!end || end == fname)
                *p = '\0';                        return 0;
                if (do_mkdir(fname, ACCESSPERMS) < 0 && errno != EEXIST)                *end = '\0';
                    ret = -1;        } else
                *p++ = '/';                end = fname + strlen(fname);
 
         /* Try to find an existing dir, starting from the deepest dir. */
         for (p = end; ; ) {
                 if (dry_run) {
                         STRUCT_STAT st;
                         if (do_stat(fname, &st) == 0) {
                                 if (S_ISDIR(st.st_mode))
                                         errno = EEXIST;
                                 else
                                         errno = ENOTDIR;
                         }
                 } else if (do_mkdir(fname, ACCESSPERMS) == 0) {
                         ret++;
                         break;
                 }
 
                 if (errno != ENOENT) {
                         STRUCT_STAT st;
                         if (errno != EEXIST || (do_stat(fname, &st) == 0 && !S_ISDIR(st.st_mode)))
                                 ret = -ret - 1;
                         break;
                 }
                 while (1) {
                         if (p == fname) {
                                 /* We got a relative path that doesn't exist, so assume that '.'
                                  * is there and just break out and create the whole thing. */
                                 p = NULL;
                                 goto double_break;
                         }
                         if (*--p == '/') {
                                 if (p == fname) {
                                         /* We reached the "/" dir, which we assume is there. */
                                         goto double_break;
                                 }
                                 *p = '\0';
                                 break;
                         }
                 }
         }          }
        umask(0);  double_break:
   
           /* Make all the dirs that we didn't find on the way here. */
           while (p != end) {
                   if (p)
                           *p = '/';
                   else
                           p = fname;
                   p += strlen(p);
                   if (ret < 0) /* Skip mkdir on error, but keep restoring the path. */
                           continue;
                   if (do_mkdir(fname, ACCESSPERMS) < 0)
                           ret = -ret - 1;
                   else
                           ret++;
           }
   
           if (flags & MKP_DROP_NAME)
                   *end = '/';
   
         return ret;          return ret;
 }  }
   
Line 280  static int safe_read(int desc, char *ptr, size_t len) Line 318  static int safe_read(int desc, char *ptr, size_t len)
  *   *
  * This is used in conjunction with the --temp-dir, --backup, and   * This is used in conjunction with the --temp-dir, --backup, and
  * --copy-dest options. */   * --copy-dest options. */
int copy_file(const char *source, const char *dest, int ofd,int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
              mode_t mode, int create_bak_dir) 
 {  {
         int ifd;          int ifd;
         char buf[1024 * 8];          char buf[1024 * 8];
         int len;   /* Number of bytes read into `buf'. */          int len;   /* Number of bytes read into `buf'. */
   #ifdef PREALLOCATE_NEEDS_TRUNCATE
           OFF_T preallocated_len = 0, offset = 0;
   #endif
   
         if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {          if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
                 int save_errno = errno;                  int save_errno = errno;
Line 302  int copy_file(const char *source, const char *dest, in Line 342  int copy_file(const char *source, const char *dest, in
                         return -1;                          return -1;
                 }                  }
   
   #ifdef SUPPORT_XATTRS
                   if (preserve_xattrs)
                           mode |= S_IWUSR;
   #endif
                   mode &= INITACCESSPERMS;
                 if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {                  if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
                        int save_errno = errno ? errno : EINVAL; /* 0 paranoia */                        int save_errno = errno;
                        if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {                        rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
                                if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)                        close(ifd);
                                        save_errno = errno ? errno : save_errno;                        errno = save_errno;
                                else                        return -1;
                                        save_errno = 0; 
                        } 
                        if (save_errno) { 
                                rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest)); 
                                close(ifd); 
                                errno = save_errno; 
                                return -1; 
                        } 
                 }                  }
         }          }
   
   #ifdef SUPPORT_PREALLOCATION
           if (preallocate_files) {
                   STRUCT_STAT srcst;
   
                   /* Try to preallocate enough space for file's eventual length.  Can
                    * reduce fragmentation on filesystems like ext4, xfs, and NTFS. */
                   if (do_fstat(ifd, &srcst) < 0)
                           rsyserr(FWARNING, errno, "fstat %s", full_fname(source));
                   else if (srcst.st_size > 0) {
                           if (do_fallocate(ofd, 0, srcst.st_size) == 0) {
   #ifdef PREALLOCATE_NEEDS_TRUNCATE
                                   preallocated_len = srcst.st_size;
   #endif
                           } else
                                   rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(dest));
                   }
           }
   #endif
   
         while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {          while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
                 if (full_write(ofd, buf, len) < 0) {                  if (full_write(ofd, buf, len) < 0) {
                         int save_errno = errno;                          int save_errno = errno;
Line 328  int copy_file(const char *source, const char *dest, in Line 384  int copy_file(const char *source, const char *dest, in
                         errno = save_errno;                          errno = save_errno;
                         return -1;                          return -1;
                 }                  }
   #ifdef PREALLOCATE_NEEDS_TRUNCATE
                   offset += len;
   #endif
         }          }
   
         if (len < 0) {          if (len < 0) {
Line 344  int copy_file(const char *source, const char *dest, in Line 403  int copy_file(const char *source, const char *dest, in
                         full_fname(source));                          full_fname(source));
         }          }
   
   #ifdef PREALLOCATE_NEEDS_TRUNCATE
           /* Source file might have shrunk since we fstatted it.
            * Cut off any extra preallocated zeros from dest file. */
           if (offset < preallocated_len && do_ftruncate(ofd, offset) < 0) {
                   /* If we fail to truncate, the dest file may be wrong, so we
                    * must trigger the "partial transfer" error. */
                   rsyserr(FERROR_XFER, errno, "ftruncate %s", full_fname(dest));
           }
   #endif
   
         if (close(ofd) < 0) {          if (close(ofd) < 0) {
                 int save_errno = errno;                  int save_errno = errno;
                 rsyserr(FERROR_XFER, errno, "close failed on %s",                  rsyserr(FERROR_XFER, errno, "close failed on %s",
Line 407  int robust_unlink(const char *fname) Line 476  int robust_unlink(const char *fname)
                         counter = 1;                          counter = 1;
         } while ((rc = access(path, 0)) == 0 && counter != start);          } while ((rc = access(path, 0)) == 0 && counter != start);
   
        if (verbose > 0) {        if (INFO_GTE(MISC, 1)) {
                 rprintf(FWARNING, "renaming %s to %s because of text busy\n",                  rprintf(FWARNING, "renaming %s to %s because of text busy\n",
                         fname, path);                          fname, path);
         }          }
Line 450  int robust_rename(const char *from, const char *to, co Line 519  int robust_rename(const char *from, const char *to, co
                                         return -2;                                          return -2;
                                 to = partialptr;                                  to = partialptr;
                         }                          }
                        if (copy_file(from, to, -1, mode, 0) != 0)                        if (copy_file(from, to, -1, mode) != 0)
                                 return -2;                                  return -2;
                         do_unlink(from);                          do_unlink(from);
                         return 1;                          return 1;
Line 504  void kill_all(int sig) Line 573  void kill_all(int sig)
         }          }
 }  }
   
 /** Turn a user name into a uid */  
 int name_to_uid(const char *name, uid_t *uid_p)  
 {  
         struct passwd *pass;  
         if (!name || !*name)  
                 return 0;  
         if (!(pass = getpwnam(name)))  
                 return 0;  
         *uid_p = pass->pw_uid;  
         return 1;  
 }  
   
 /** Turn a group name into a gid */  
 int name_to_gid(const char *name, gid_t *gid_p)  
 {  
         struct group *grp;  
         if (!name || !*name)  
                 return 0;  
         if (!(grp = getgrnam(name)))  
                 return 0;  
         *gid_p = grp->gr_gid;  
         return 1;  
 }  
   
 /** Lock a byte range in a open file */  /** Lock a byte range in a open file */
 int lock_range(int fd, int offset, int len)  int lock_range(int fd, int offset, int len)
 {  {
Line 719  void glob_expand_module(char *base1, char *arg, char * Line 764  void glob_expand_module(char *base1, char *arg, char *
         if (strncmp(arg, base, base_len) == 0)          if (strncmp(arg, base, base_len) == 0)
                 arg += base_len;                  arg += base_len;
   
           if (protect_args) {
                   glob_expand(arg, argv_p, argc_p, maxargs_p);
                   return;
           }
   
         if (!(arg = strdup(arg)))          if (!(arg = strdup(arg)))
                 out_of_memory("glob_expand_module");                  out_of_memory("glob_expand_module");
   
        if (asprintf(&base," %s/", base1) <= 0)        if (asprintf(&base," %s/", base1) < 0)
                 out_of_memory("glob_expand_module");                  out_of_memory("glob_expand_module");
         base_len++;          base_len++;
   
Line 824  int count_dir_elements(const char *p) Line 874  int count_dir_elements(const char *p)
  * CFN_KEEP_TRAILING_SLASH is flagged, and will also collapse ".." elements   * CFN_KEEP_TRAILING_SLASH is flagged, and will also collapse ".." elements
  * (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged.  If the   * (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged.  If the
  * resulting name would be empty, returns ".". */   * resulting name would be empty, returns ".". */
unsigned int clean_fname(char *name, int flags)int clean_fname(char *name, int flags)
 {  {
         char *limit = name - 1, *t = name, *f = name;          char *limit = name - 1, *t = name, *f = name;
         int anchored;          int anchored;
Line 832  unsigned int clean_fname(char *name, int flags) Line 882  unsigned int clean_fname(char *name, int flags)
         if (!name)          if (!name)
                 return 0;                  return 0;
   
   #define DOT_IS_DOT_DOT_DIR(bp) (bp[1] == '.' && (bp[2] == '/' || !bp[2]))
   
         if ((anchored = *f == '/') != 0) {          if ((anchored = *f == '/') != 0) {
                 *t++ = *f++;                  *t++ = *f++;
 #ifdef __CYGWIN__  #ifdef __CYGWIN__
Line 844  unsigned int clean_fname(char *name, int flags) Line 896  unsigned int clean_fname(char *name, int flags)
         } else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {          } else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {
                 *t++ = *f++;                  *t++ = *f++;
                 *t++ = *f++;                  *t++ = *f++;
        }        } else if (flags & CFN_REFUSE_DOT_DOT_DIRS && *f == '.' && DOT_IS_DOT_DOT_DIR(f))
                 return -1;
         while (*f) {          while (*f) {
                 /* discard extra slashes */                  /* discard extra slashes */
                 if (*f == '/') {                  if (*f == '/') {
Line 860  unsigned int clean_fname(char *name, int flags) Line 913  unsigned int clean_fname(char *name, int flags)
                         if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR)                          if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR)
                                 break;                                  break;
                         /* collapse ".." dirs */                          /* collapse ".." dirs */
                        if (flags & CFN_COLLAPSE_DOT_DOT_DIRS                        if (flags & (CFN_COLLAPSE_DOT_DOT_DIRS|CFN_REFUSE_DOT_DOT_DIRS) && DOT_IS_DOT_DOT_DIR(f)) {
                         && f[1] == '.' && (f[2] == '/' || !f[2])) { 
                                 char *s = t - 1;                                  char *s = t - 1;
                                   if (flags & CFN_REFUSE_DOT_DOT_DIRS)
                                           return -1;
                                 if (s == name && anchored) {                                  if (s == name && anchored) {
                                         f += 2;                                          f += 2;
                                         continue;                                          continue;
Line 885  unsigned int clean_fname(char *name, int flags) Line 939  unsigned int clean_fname(char *name, int flags)
                 *t++ = '.';                  *t++ = '.';
         *t = '\0';          *t = '\0';
   
   #undef DOT_IS_DOT_DOT_DIR
   
         return t - name;          return t - name;
 }  }
   
Line 992  char *sanitize_path(char *dest, const char *p, const c Line 1048  char *sanitize_path(char *dest, const char *p, const c
  * Also cleans the path using the clean_fname() function. */   * Also cleans the path using the clean_fname() function. */
 int change_dir(const char *dir, int set_path_only)  int change_dir(const char *dir, int set_path_only)
 {  {
        static int initialised;        static int initialised, skipped_chdir;
         unsigned int len;          unsigned int len;
   
         if (!initialised) {          if (!initialised) {
Line 1008  int change_dir(const char *dir, int set_path_only) Line 1064  int change_dir(const char *dir, int set_path_only)
                 return 0;                  return 0;
   
         len = strlen(dir);          len = strlen(dir);
        if (len == 1 && *dir == '.')        if (len == 1 && *dir == '.' && (!skipped_chdir || set_path_only))
                 return 1;                  return 1;
   
         if (*dir == '/') {          if (*dir == '/') {
Line 1018  int change_dir(const char *dir, int set_path_only) Line 1074  int change_dir(const char *dir, int set_path_only)
                 }                  }
                 if (!set_path_only && chdir(dir))                  if (!set_path_only && chdir(dir))
                         return 0;                          return 0;
                   skipped_chdir = set_path_only;
                 memcpy(curr_dir, dir, len + 1);                  memcpy(curr_dir, dir, len + 1);
         } else {          } else {
                 if (curr_dir_len + 1 + len >= sizeof curr_dir) {                  if (curr_dir_len + 1 + len >= sizeof curr_dir) {
Line 1032  int change_dir(const char *dir, int set_path_only) Line 1089  int change_dir(const char *dir, int set_path_only)
                         curr_dir[curr_dir_len] = '\0';                          curr_dir[curr_dir_len] = '\0';
                         return 0;                          return 0;
                 }                  }
                   skipped_chdir = set_path_only;
         }          }
   
        curr_dir_len = clean_fname(curr_dir, CFN_COLLAPSE_DOT_DOT_DIRS);        curr_dir_len = clean_fname(curr_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
         if (sanitize_paths) {          if (sanitize_paths) {
                 if (module_dirlen > curr_dir_len)                  if (module_dirlen > curr_dir_len)
                         module_dirlen = curr_dir_len;                          module_dirlen = curr_dir_len;
                 curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);                  curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
         }          }
   
        if (verbose >= 5 && !set_path_only)        if (DEBUG_GTE(CHDIR, 1) && !set_path_only)
                 rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir);                  rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir);
   
         return 1;          return 1;
Line 1104  char *full_fname(const char *fn) Line 1162  char *full_fname(const char *fn)
         } else          } else
                 m1 = m2 = m3 = "";                  m1 = m2 = m3 = "";
   
        if (asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3) <= 0)        if (asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3) < 0)
                 out_of_memory("full_fname");                  out_of_memory("full_fname");
   
         return result;          return result;
Line 1238  int unsafe_symlink(const char *dest, const char *src) Line 1296  int unsafe_symlink(const char *dest, const char *src)
         return depth < 0;          return depth < 0;
 }  }
   
 #define HUMANIFY(mult) \  
         do { \  
                 if (num >= mult || num <= -mult) { \  
                         double dnum = (double)num / mult; \  
                         char units; \  
                         if (num < 0) \  
                                 dnum = -dnum; \  
                         if (dnum < mult) \  
                                 units = 'K'; \  
                         else if ((dnum /= mult) < mult) \  
                                 units = 'M'; \  
                         else { \  
                                 dnum /= mult; \  
                                 units = 'G'; \  
                         } \  
                         if (num < 0) \  
                                 dnum = -dnum; \  
                         snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \  
                         return bufs[n]; \  
                 } \  
         } while (0)  
   
 /* Return the int64 number as a string.  If the --human-readable option was  
  * specified, we may output the number in K, M, or G units.  We can return  
  * up to 4 buffers at a time. */  
 char *human_num(int64 num)  
 {  
         static char bufs[4][128]; /* more than enough room */  
         static unsigned int n;  
         char *s;  
         int negated;  
   
         n = (n + 1) % (sizeof bufs / sizeof bufs[0]);  
   
         if (human_readable) {  
                 if (human_readable == 1)  
                         HUMANIFY(1000);  
                 else  
                         HUMANIFY(1024);  
         }  
   
         s = bufs[n] + sizeof bufs[0] - 1;  
         *s = '\0';  
   
         if (!num)  
                 *--s = '0';  
         if (num < 0) {  
                 /* A maximum-size negated number can't fit as a positive,  
                  * so do one digit in negated form to start us off. */  
                 *--s = (char)(-(num % 10)) + '0';  
                 num = -(num / 10);  
                 negated = 1;  
         } else  
                 negated = 0;  
   
         while (num) {  
                 *--s = (char)(num % 10) + '0';  
                 num /= 10;  
         }  
   
         if (negated)  
                 *--s = '-';  
   
         return s;  
 }  
   
 /* Return the double number as a string.  If the --human-readable option was  
  * specified, we may output the number in K, M, or G units.  We use a buffer  
  * from human_num() to return our result. */  
 char *human_dnum(double dnum, int decimal_digits)  
 {  
         char *buf = human_num(dnum);  
         int len = strlen(buf);  
         if (isDigit(buf + len - 1)) {  
                 /* There's extra room in buf prior to the start of the num. */  
                 buf -= decimal_digits + 2;  
                 snprintf(buf, len + decimal_digits + 3, "%.*f", decimal_digits, dnum);  
         }  
         return buf;  
 }  
   
 /* Return the date and time as a string.  Some callers tweak returned buf. */  /* Return the date and time as a string.  Some callers tweak returned buf. */
 char *timestring(time_t t)  char *timestring(time_t t)
 {  {
Line 1338  char *timestring(time_t t) Line 1315  char *timestring(time_t t)
         return TimeBuf;          return TimeBuf;
 }  }
   
 /**  
  * Sleep for a specified number of milliseconds.  
  *  
  * Always returns TRUE.  (In the future it might return FALSE if  
  * interrupted.)  
  **/  
 int msleep(int t)  
 {  
         int tdiff = 0;  
         struct timeval tval, t1, t2;  
   
         gettimeofday(&t1, NULL);  
   
         while (tdiff < t) {  
                 tval.tv_sec = (t-tdiff)/1000;  
                 tval.tv_usec = 1000*((t-tdiff)%1000);  
   
                 errno = 0;  
                 select(0,NULL,NULL, NULL, &tval);  
   
                 gettimeofday(&t2, NULL);  
                 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +  
                         (t2.tv_usec - t1.tv_usec)/1000;  
         }  
   
         return True;  
 }  
   
 /* Determine if two time_t values are equivalent (either exact, or in  /* Determine if two time_t values are equivalent (either exact, or in
  * the modification timestamp window established by --modify-window).   * the modification timestamp window established by --modify-window).
  *   *
Line 1378  int msleep(int t) Line 1327  int msleep(int t)
 int cmp_time(time_t file1, time_t file2)  int cmp_time(time_t file1, time_t file2)
 {  {
         if (file2 > file1) {          if (file2 > file1) {
                if (file2 - file1 <= modify_window)                /* The final comparison makes sure that modify_window doesn't overflow a
                        return 0;                 * time_t, which would mean that file2 must be in the equality window. */
                return -1;                if (!modify_window || (file2 > file1 + modify_window && file1 + modify_window > file1))
                         return -1;
         } else if (file1 > file2) {
                 if (!modify_window || (file1 > file2 + modify_window && file2 + modify_window > file2))
                         return 1;
         }          }
        if (file1 - file2 <= modify_window)        return 0;
                return 0; 
        return 1; 
 }  }
   
   
 #ifdef __INSURE__XX  #ifdef __INSURE__XX
 #include <dlfcn.h>  #include <dlfcn.h>
   
Line 1399  int cmp_time(time_t file1, time_t file2) Line 1349  int cmp_time(time_t file1, time_t file2)
 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)  int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
 {  {
         static int (*fn)();          static int (*fn)();
        int ret;        int ret, pid_int = getpid();
         char *cmd;          char *cmd;
   
        asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",        if (asprintf(&cmd,
                getpid(), getpid(), getpid());            "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; "
             "gdb /proc/%d/exe %d'", pid_int, pid_int, pid_int) < 0)
                 return -1;
   
         if (!fn) {          if (!fn) {
                 static void *h;                  static void *h;
Line 1421  int _Insure_trap_error(int a1, int a2, int a3, int a4, Line 1373  int _Insure_trap_error(int a1, int a2, int a3, int a4,
 }  }
 #endif  #endif
   
 #define MALLOC_MAX 0x40000000  
   
 void *_new_array(unsigned long num, unsigned int size, int use_calloc)  
 {  
         if (num >= MALLOC_MAX/size)  
                 return NULL;  
         return use_calloc ? calloc(num, size) : malloc(num * size);  
 }  
   
 void *_realloc_array(void *ptr, unsigned int size, size_t num)  
 {  
         if (num >= MALLOC_MAX/size)  
                 return NULL;  
         if (!ptr)  
                 return malloc(size * num);  
         return realloc(ptr, size * num);  
 }  
   
 /* Take a filename and filename length and return the most significant  /* Take a filename and filename length and return the most significant
  * filename suffix we can find.  This ignores suffixes such as "~",   * filename suffix we can find.  This ignores suffixes such as "~",
  * ".bak", ".orig", ".~1~", etc. */   * ".bak", ".orig", ".~1~", etc. */
Line 1503  const char *find_filename_suffix(const char *fn, int f Line 1437  const char *find_filename_suffix(const char *fn, int f
   
 #define UNIT (1 << 16)  #define UNIT (1 << 16)
   
uint32 fuzzy_distance(const char *s1, int len1, const char *s2, int len2)uint32 fuzzy_distance(const char *s1, unsigned len1, const char *s2, unsigned len2)
 {  {
         uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;          uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;
         int32 cost;          int32 cost;
        int i1, i2;        unsigned i1, i2;
   
         if (!len1 || !len2) {          if (!len1 || !len2) {
                 if (!len1) {                  if (!len1) {
Line 1671  int flist_ndx_pop(flist_ndx_list *lp) Line 1605  int flist_ndx_pop(flist_ndx_list *lp)
         return ndx;          return ndx;
 }  }
   
   /* Make sure there is room for one more item in the item list.  If there
    * is not, expand the list as indicated by the value of "incr":
    *  - if incr < 0 then increase the malloced size by -1 * incr
    *  - if incr >= 0 then either make the malloced size equal to "incr"
    *    or (if that's not large enough) double the malloced size
    * After the size check, the list's count is incremented by 1 and a pointer
    * to the "new" list item is returned.
    */
 void *expand_item_list(item_list *lp, size_t item_size,  void *expand_item_list(item_list *lp, size_t item_size,
                        const char *desc, int incr)                         const char *desc, int incr)
 {  {
Line 1681  void *expand_item_list(item_list *lp, size_t item_size Line 1623  void *expand_item_list(item_list *lp, size_t item_size
                 if (incr < 0)                  if (incr < 0)
                         new_size += -incr; /* increase slowly */                          new_size += -incr; /* increase slowly */
                 else if (new_size < (size_t)incr)                  else if (new_size < (size_t)incr)
                        new_size += incr;                        new_size = incr;
                else                else if (new_size)
                         new_size *= 2;                          new_size *= 2;
                if (new_size < lp->malloced)                else
                         new_size = 1;
                 if (new_size <= lp->malloced)
                         overflow_exit("expand_item_list");                          overflow_exit("expand_item_list");
                 /* Using _realloc_array() lets us pass the size, not a type. */                  /* Using _realloc_array() lets us pass the size, not a type. */
                 new_ptr = _realloc_array(lp->items, item_size, new_size);                  new_ptr = _realloc_array(lp->items, item_size, new_size);
                if (verbose >= 4) {                if (DEBUG_GTE(FLIST, 3)) {
                        rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n",                        rprintf(FINFO, "[%s] expand %s to %s bytes, did%s move\n",
                                who_am_i(), desc, (double)new_size * item_size,                                who_am_i(), desc, big_num(new_size * item_size),
                                 new_ptr == lp->items ? " not" : "");                                  new_ptr == lp->items ? " not" : "");
                 }                  }
                 if (!new_ptr)                  if (!new_ptr)

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


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