| version 1.1.1.1.2.1, 2013/07/22 00:20:21 | version 1.1.1.3, 2016/11/01 09:54:32 | 
| Line 4 | Line 4 | 
 | * | * | 
 | * Copyright (C) 1998 Andrew Tridgell | * Copyright (C) 1998 Andrew Tridgell | 
 | * Copyright (C) 2002 Martin Pool | * Copyright (C) 2002 Martin Pool | 
| * 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 29 | Line 29 | 
 | #include <sys/attr.h> | #include <sys/attr.h> | 
 | #endif | #endif | 
 |  |  | 
 |  | #if defined HAVE_SYS_FALLOCATE && !defined HAVE_FALLOCATE | 
 |  | #include <sys/syscall.h> | 
 |  | #endif | 
 |  |  | 
 | extern int dry_run; | extern int dry_run; | 
 | extern int am_root; | extern int am_root; | 
 |  | extern int am_sender; | 
 | extern int read_only; | extern int read_only; | 
 | extern int list_only; | extern int list_only; | 
 | extern int preserve_perms; | extern int preserve_perms; | 
| Line 53  int do_unlink(const char *fname) | Line 58  int do_unlink(const char *fname) | 
 | return unlink(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; | if (dry_run) return 0; | 
 | RETURN_ERROR_IF_RO_OR_LO; | RETURN_ERROR_IF_RO_OR_LO; | 
| return symlink(fname1, fname2); |  | 
|  | #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_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); | 
 | } | } | 
 |  |  | 
 |  | #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_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 = do_open_nofollow(path, O_RDONLY); | 
 |  | 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 | #ifdef HAVE_LINK | 
 | int do_link(const char *fname1, const char *fname2) | int do_link(const char *fname1, const char *fname2) | 
 | { | { | 
| Line 100  int do_mknod(const char *pathname, mode_t mode, dev_t | Line 147  int do_mknod(const char *pathname, mode_t mode, dev_t | 
 | if (S_ISSOCK(mode)) { | if (S_ISSOCK(mode)) { | 
 | int sock; | int sock; | 
 | struct sockaddr_un saddr; | struct sockaddr_un saddr; | 
 |  | unsigned int len = strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path); | 
 |  | if (len >= sizeof saddr.sun_path) { | 
 |  | errno = ENAMETOOLONG; | 
 |  | return -1; | 
 |  | } | 
 | #ifdef HAVE_SOCKADDR_UN_LEN | #ifdef HAVE_SOCKADDR_UN_LEN | 
| unsigned int len = | saddr.sun_len = len + 1; | 
 | #endif | #endif | 
 | strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path); |  | 
 | #ifdef HAVE_SOCKADDR_UN_LEN |  | 
 | saddr.sun_len = len >= sizeof saddr.sun_path |  | 
 | ? sizeof saddr.sun_path : len + 1; |  | 
 | #endif |  | 
 | saddr.sun_family = AF_UNIX; | saddr.sun_family = AF_UNIX; | 
 |  |  | 
 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 | 
| Line 217  void trim_trailing_slashes(char *name) | Line 264  void trim_trailing_slashes(char *name) | 
 | } | } | 
 | } | } | 
 |  |  | 
 | int do_mkdir_path(char *fname, mode_t mode) |  | 
 | { |  | 
 | char fnametmp[MAXPATHLEN], *fnametmpptr; |  | 
 | STRUCT_STAT st; |  | 
 |  |  | 
 | if (fname) { |  | 
 | strcpy(fnametmp, fname); |  | 
 | if ((fnametmpptr = strrchr(fnametmp, '/')) != NULL) { |  | 
 | *fnametmpptr = '\0'; |  | 
 | if (do_stat(fnametmp, &st) < 0) |  | 
 | do_mkdir_path(fnametmp, mode); |  | 
 | } |  | 
 | } |  | 
 | return do_mkdir(fname, mode); |  | 
 | } |  | 
 |  |  | 
 | int do_mkdir(char *fname, mode_t mode) | int do_mkdir(char *fname, mode_t mode) | 
 | { | { | 
 | if (dry_run) return 0; | if (dry_run) return 0; | 
| Line 390  int do_utime(const char *fname, time_t modtime, UNUSED | Line 421  int do_utime(const char *fname, time_t modtime, UNUSED | 
 | #else | #else | 
 | #error Need utimes or utime function. | #error Need utimes or utime function. | 
 | #endif | #endif | 
 |  |  | 
 |  | #ifdef SUPPORT_PREALLOCATION | 
 |  | int do_fallocate(int fd, OFF_T offset, OFF_T length) | 
 |  | { | 
 |  | #ifdef FALLOC_FL_KEEP_SIZE | 
 |  | #define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE | 
 |  | #else | 
 |  | #define DO_FALLOC_OPTIONS 0 | 
 |  | #endif | 
 |  | RETURN_ERROR_IF(dry_run, 0); | 
 |  | RETURN_ERROR_IF_RO_OR_LO; | 
 |  | #if defined HAVE_FALLOCATE | 
 |  | return fallocate(fd, DO_FALLOC_OPTIONS, offset, length); | 
 |  | #elif defined HAVE_SYS_FALLOCATE | 
 |  | return syscall(SYS_fallocate, fd, DO_FALLOC_OPTIONS, (loff_t)offset, (loff_t)length); | 
 |  | #elif defined HAVE_EFFICIENT_POSIX_FALLOCATE | 
 |  | return posix_fallocate(fd, offset, length); | 
 |  | #else | 
 |  | #error Coding error in SUPPORT_PREALLOCATION logic. | 
 |  | #endif | 
 |  | } | 
 |  | #endif | 
 |  |  | 
 |  | int do_open_nofollow(const char *pathname, int flags) | 
 |  | { | 
 |  | #ifndef O_NOFOLLOW | 
 |  | STRUCT_STAT f_st, l_st; | 
 |  | #endif | 
 |  | int fd; | 
 |  |  | 
 |  | if (flags != O_RDONLY) { | 
 |  | RETURN_ERROR_IF(dry_run, 0); | 
 |  | RETURN_ERROR_IF_RO_OR_LO; | 
 |  | #ifndef O_NOFOLLOW | 
 |  | /* This function doesn't support write attempts w/o O_NOFOLLOW. */ | 
 |  | errno = EINVAL; | 
 |  | return -1; | 
 |  | #endif | 
 |  | } | 
 |  |  | 
 |  | #ifdef O_NOFOLLOW | 
 |  | fd = open(pathname, flags|O_NOFOLLOW); | 
 |  | #else | 
 |  | if (do_lstat(pathname, &l_st) < 0) | 
 |  | return -1; | 
 |  | if (S_ISLNK(l_st.st_mode)) { | 
 |  | errno = ELOOP; | 
 |  | return -1; | 
 |  | } | 
 |  | if ((fd = open(pathname, flags)) < 0) | 
 |  | return fd; | 
 |  | if (do_fstat(fd, &f_st) < 0) { | 
 |  | close_and_return_error: | 
 |  | { | 
 |  | int save_errno = errno; | 
 |  | close(fd); | 
 |  | errno = save_errno; | 
 |  | } | 
 |  | return -1; | 
 |  | } | 
 |  | if (l_st.st_dev != f_st.st_dev || l_st.st_ino != f_st.st_ino) { | 
 |  | errno = EINVAL; | 
 |  | goto close_and_return_error; | 
 |  | } | 
 |  | #endif | 
 |  |  | 
 |  | return fd; | 
 |  | } |