X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/11b02d927f2d809aeade01768b16b690220c1049..870cf55287e68a344fe3c1ea7eccf887ad5b1bbc:/syscall.c diff --git a/syscall.c b/syscall.c index 0dfcaa01..945a11d4 100644 --- a/syscall.c +++ b/syscall.c @@ -4,7 +4,7 @@ * * Copyright (C) 1998 Andrew Tridgell * Copyright (C) 2002 Martin Pool - * Copyright (C) 2003-2007 Wayne Davison + * Copyright (C) 2003-2009 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 @@ -31,9 +31,11 @@ extern int dry_run; extern int am_root; +extern int am_sender; extern int read_only; extern int list_only; extern int preserve_perms; +extern int preserve_executability; #define RETURN_ERROR_IF(x,e) \ do { \ @@ -52,13 +54,55 @@ int do_unlink(const char *fname) return unlink(fname); } -int do_symlink(const char *fname1, const char *fname2) +#ifdef SUPPORT_LINKS +int do_symlink(const char *lnk, const char *fname) { if (dry_run) return 0; RETURN_ERROR_IF_RO_OR_LO; - return symlink(fname1, fname2); + +#ifdef NO_SYMLINK_XATTRS + /* For --fake-super, we create a normal file with mode 0600 + * and write the lnk into it. */ + if (am_root < 0) { + int ok, len = strlen(lnk); + int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR); + if (fd < 0) + return -1; + ok = write(fd, lnk, len) == len; + if (close(fd) < 0) + ok = 0; + return ok ? 0 : -1; + } +#endif + + return symlink(lnk, fname); } +#ifdef NO_SYMLINK_XATTRS +ssize_t do_readlink(const char *path, char *buf, size_t bufsiz) +{ + /* For --fake-super, we read the link from the file. */ + if (am_root < 0) { + int fd = open(path, O_RDONLY|O_NOFOLLOW); + if (fd >= 0) { + int len = read(fd, buf, bufsiz); + close(fd); + return len; + } + if (errno != ELOOP) + return -1; + /* A real symlink needs to be turned into a fake one on the receiving + * side, so tell the generator that the link has no length. */ + if (!am_sender) + return 0; + /* Otherwise fall through and let the sender report the real length. */ + } + + return readlink(path, buf, bufsiz); +} +#endif +#endif + #ifdef HAVE_LINK int do_link(const char *fname1, const char *fname2) { @@ -166,9 +210,9 @@ int do_chmod(const char *path, mode_t mode) code = 1; #endif } else - code = chmod(path, mode & CHMOD_BITS); - if (code != 0 && preserve_perms) - return code; + code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ + if (code != 0 && (preserve_perms || preserve_executability)) + return code; return 0; } #endif @@ -211,6 +255,7 @@ int do_mkstemp(char *template, mode_t perms) { RETURN_ERROR_IF(dry_run, 0); RETURN_ERROR_IF(read_only, EROFS); + perms |= S_IWUSR; #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64) { @@ -280,12 +325,3 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence) return lseek(fd, offset, whence); #endif } - -char *d_name(struct dirent *di) -{ -#ifdef HAVE_BROKEN_READDIR - return (di->d_name - 2); -#else - return di->d_name; -#endif -}