A couple more support/rrsync tweaks:
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index e236ca5..b5c15fb 100644 (file)
--- a/util.c
+++ b/util.c
@@ -4,7 +4,7 @@
  * Copyright (C) 1996-2000 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003-2007 Wayne Davison
+ * Copyright (C) 2003-2008 Wayne Davison
  *
  * 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
@@ -147,8 +147,9 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
                t[1].tv_usec = 0;
 # ifdef HAVE_LUTIMES
                if (S_ISLNK(mode)) {
-                       lutimes(fname, t);
-                       return 0; /* ignore errors */
+                       if (lutimes(fname, t) < 0)
+                               return errno == ENOSYS ? 1 : -1;
+                       return 0;
                }
 # endif
                return utimes(fname, t);
@@ -274,20 +275,20 @@ int copy_file(const char *source, const char *dest, int ofd,
        int len;   /* Number of bytes read into `buf'. */
 
        if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
-               rsyserr(FERROR, errno, "open %s", full_fname(source));
+               rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
                return -1;
        }
 
        if (ofd < 0) {
                if (robust_unlink(dest) && errno != ENOENT) {
-                       rsyserr(FERROR, errno, "unlink %s", full_fname(dest));
+                       rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
                        return -1;
                }
 
                if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
                 && (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
                  || (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
-                       rsyserr(FERROR, errno, "open %s", full_fname(dest));
+                       rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest));
                        close(ifd);
                        return -1;
                }
@@ -295,7 +296,7 @@ int copy_file(const char *source, const char *dest, int ofd,
 
        while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
                if (full_write(ofd, buf, len) < 0) {
-                       rsyserr(FERROR, errno, "write %s", full_fname(dest));
+                       rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
                        close(ifd);
                        close(ofd);
                        return -1;
@@ -303,19 +304,19 @@ int copy_file(const char *source, const char *dest, int ofd,
        }
 
        if (len < 0) {
-               rsyserr(FERROR, errno, "read %s", full_fname(source));
+               rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
                close(ifd);
                close(ofd);
                return -1;
        }
 
        if (close(ifd) < 0) {
-               rsyserr(FINFO, errno, "close failed on %s",
+               rsyserr(FWARNING, errno, "close failed on %s",
                        full_fname(source));
        }
 
        if (close(ofd) < 0) {
-               rsyserr(FERROR, errno, "close failed on %s",
+               rsyserr(FERROR_XFER, errno, "close failed on %s",
                        full_fname(dest));
                return -1;
        }
@@ -371,7 +372,7 @@ int robust_unlink(const char *fname)
        } while ((rc = access(path, 0)) == 0 && counter != start);
 
        if (verbose > 0) {
-               rprintf(FINFO,"renaming %s to %s because of text busy\n",
+               rprintf(FWARNING, "renaming %s to %s because of text busy\n",
                        fname, path);
        }
 
@@ -465,31 +466,27 @@ void kill_all(int sig)
 }
 
 /** Turn a user name into a uid */
-int name_to_uid(const char *name, uid_t *uid)
+int name_to_uid(const char *name, uid_t *uid_p)
 {
        struct passwd *pass;
        if (!name || !*name)
                return 0;
-       pass = getpwnam(name);
-       if (pass) {
-               *uid = pass->pw_uid;
-               return 1;
-       }
-       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)
+int name_to_gid(const char *name, gid_t *gid_p)
 {
        struct group *grp;
        if (!name || !*name)
                return 0;
-       grp = getgrnam(name);
-       if (grp) {
-               *gid = grp->gr_gid;
-               return 1;
-       }
-       return 0;
+       if (!(grp = getgrnam(name)))
+               return 0;
+       *gid_p = grp->gr_gid;
+       return 1;
 }
 
 /** Lock a byte range in a open file */
@@ -528,6 +525,8 @@ void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
        char **argv = *argv_ptr;
        int argc = *argc_ptr;
        int maxargs = *maxargs_ptr;
+       int count, have_glob_results;
+
 #if !defined HAVE_GLOB || !defined HAVE_GLOB_H
        if (argc == maxargs) {
                maxargs += MAX_ARGS;
@@ -556,25 +555,52 @@ void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
                out_of_memory("glob_expand");
 
        memset(&globbuf, 0, sizeof globbuf);
-       if (!filter_server_path(s))
-               glob(s, 0, NULL, &globbuf);
-       if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) {
-               maxargs += globbuf.gl_pathc + MAX_ARGS;
+       glob(s, 0, NULL, &globbuf);
+       /* Note: we check the first match against the filter list,
+        * just in case the user specified a wildcard in the path. */
+       if ((count = globbuf.gl_pathc) > 0) {
+               if (filter_server_path(globbuf.gl_pathv[0])) {
+                       int slashes = 0;
+                       char *cp;
+                       /* Truncate original arg at glob's truncation point. */
+                       for (cp = globbuf.gl_pathv[0]; *cp; cp++) {
+                               if (*cp == '/')
+                                       slashes++;
+                       }
+                       for (cp = s; *cp; cp++) {
+                               if (*cp == '/') {
+                                       if (--slashes <= 0) {
+                                               *cp = '\0';
+                                               break;
+                                       }
+                               }
+                       }
+                       have_glob_results = 0;
+                       count = 1;
+               } else
+                       have_glob_results = 1;
+       } else {
+               /* This truncates "s" at a filtered element, if present. */
+               filter_server_path(s);
+               have_glob_results = 0;
+               count = 1;
+       }
+       if (count + argc > maxargs) {
+               maxargs += count + MAX_ARGS;
                if (!(argv = realloc_array(argv, char *, maxargs)))
                        out_of_memory("glob_expand");
                *argv_ptr = argv;
                *maxargs_ptr = maxargs;
        }
-       if (globbuf.gl_pathc == 0)
-               argv[argc++] = s;
-       else {
+       if (have_glob_results) {
                int i;
                free(s);
-               for (i = 0; i < (int)globbuf.gl_pathc; i++) {
+               for (i = 0; i < count; i++) {
                        if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
                                out_of_memory("glob_expand");
                }
-       }
+       } else
+               argv[argc++] = s;
        globfree(&globbuf);
 #endif
        *argc_ptr = argc;
@@ -898,6 +924,9 @@ int push_dir(const char *dir, int set_path_only)
                curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
        }
 
+       if (verbose >= 5 && !set_path_only)
+               rprintf(FINFO, "[%s] push_dir(%s)\n", who_am_i(), curr_dir);
+
        return 1;
 }
 
@@ -916,6 +945,9 @@ int pop_dir(const char *dir)
        if (sanitize_paths)
                curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
 
+       if (verbose >= 5)
+               rprintf(FINFO, "[%s] pop_dir(%s)\n", who_am_i(), curr_dir);
+
        return 1;
 }