X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/29a89172f77ed76dcf53612e96dc35daf15d7362..e9489cd6cb380b30727bd3d074eacc59abca080e:/util.c diff --git a/util.c b/util.c index a40ce7b5..c71830bd 100644 --- a/util.c +++ b/util.c @@ -29,6 +29,7 @@ extern int module_id; extern int modify_window; extern int relative_paths; extern int human_readable; +extern int preserve_xattrs; extern char *module_dir; extern unsigned int module_dirlen; extern mode_t orig_umask; @@ -264,6 +265,8 @@ static int safe_read(int desc, char *ptr, size_t len) /* Copy a file. If ofd < 0, copy_file unlinks and opens the "dest" file. * Otherwise, it just writes to and closes the provided file descriptor. + * In either case, if --xattrs are being preserved, the dest file will + * have its xattrs set from the source file. * * This is used in conjunction with the --temp-dir, --backup, and * --copy-dest options. */ @@ -275,38 +278,54 @@ 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) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "open %s", full_fname(source)); + errno = save_errno; return -1; } if (ofd < 0) { if (robust_unlink(dest) && errno != ENOENT) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest)); + errno = save_errno; 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_XFER, errno, "open %s", full_fname(dest)); - close(ifd); - return -1; + if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) { + if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) + save_errno = errno ? errno : save_errno; + else + save_errno = 0; + } + if (save_errno) { + rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest)); + close(ifd); + errno = save_errno; + return -1; + } } } while ((len = safe_read(ifd, buf, sizeof buf)) > 0) { if (full_write(ofd, buf, len) < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest)); close(ifd); close(ofd); + errno = save_errno; return -1; } } if (len < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "read %s", full_fname(source)); close(ifd); close(ofd); + errno = save_errno; return -1; } @@ -316,11 +335,18 @@ int copy_file(const char *source, const char *dest, int ofd, } if (close(ofd) < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "close failed on %s", full_fname(dest)); + errno = save_errno; return -1; } +#ifdef SUPPORT_XATTRS + if (preserve_xattrs) + copy_xattrs(source, dest); +#endif + return 0; } @@ -401,8 +427,11 @@ int robust_rename(const char *from, const char *to, const char *partialptr, switch (errno) { #ifdef ETXTBSY case ETXTBSY: - if (robust_unlink(to) != 0) + if (robust_unlink(to) != 0) { + errno = ETXTBSY; return -1; + } + errno = ETXTBSY; break; #endif case EXDEV: @@ -582,7 +611,7 @@ static inline void call_glob_match(const char *name, int len, int from_glob, } else use_buf = glob.arg_buf; - if (from_glob || arg) { + if (from_glob || (arg && len)) { STRUCT_STAT st; int is_dir; @@ -1329,7 +1358,7 @@ void *_new_array(unsigned long num, unsigned int size, int use_calloc) return use_calloc ? calloc(num, size) : malloc(num * size); } -void *_realloc_array(void *ptr, unsigned int size, unsigned long num) +void *_realloc_array(void *ptr, unsigned int size, size_t num) { if (num >= MALLOC_MAX/size) return NULL; @@ -1550,7 +1579,10 @@ void *expand_item_list(item_list *lp, size_t item_size, new_size += incr; else new_size *= 2; - new_ptr = realloc_array(lp->items, char, new_size * item_size); + if (new_size < lp->malloced) + overflow_exit("expand_item_list"); + /* Using _realloc_array() lets us pass the size, not a type. */ + new_ptr = _realloc_array(lp->items, item_size, new_size); if (verbose >= 4) { rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n", who_am_i(), desc, (double)new_size * item_size,