X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/0379c8eca1716810c06a0c8710c06d77a6256be6..ae03e0e008006c5be045c478327c860625daab0e:/syscall.c diff --git a/syscall.c b/syscall.c index 4369c6e3..aba0009d 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,12 +54,54 @@ 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) @@ -151,10 +195,11 @@ int do_chmod(const char *path, mode_t mode) int code; if (dry_run) return 0; RETURN_ERROR_IF_RO_OR_LO; - if (S_ISLNK(mode)) { #ifdef HAVE_LCHMOD - code = lchmod(path, mode & CHMOD_BITS); -#elif defined HAVE_SETATTRLIST + code = lchmod(path, mode & CHMOD_BITS); +#else + if (S_ISLNK(mode)) { +# if defined HAVE_SETATTRLIST struct attrlist attrList; uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */ @@ -162,13 +207,14 @@ int do_chmod(const char *path, mode_t mode) attrList.bitmapcount = ATTR_BIT_MAP_COUNT; attrList.commonattr = ATTR_CMN_ACCESSMASK; code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW); -#else +# else code = 1; -#endif +# endif } else - code = chmod(path, mode & CHMOD_BITS); - if (code != 0 && preserve_perms) - return code; + code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ +#endif /* !HAVE_LCHMOD */ + if (code != 0 && (preserve_perms || preserve_executability)) + return code; return 0; } #endif @@ -281,12 +327,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 -}