2 * Syscall wrappers to ensure that nothing gets done in dry_run mode
3 * and to handle system peculiarities.
5 * Copyright (C) 1998 Andrew Tridgell
6 * Copyright (C) 2002 Martin Pool
7 * Copyright (C) 2003-2015 Wayne Davison
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, visit the http://fsf.org website.
25 #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
28 #ifdef HAVE_SYS_ATTR_H
32 #if defined HAVE_SYS_FALLOCATE && !defined HAVE_FALLOCATE
33 #include <sys/syscall.h>
42 extern int preallocate_files;
43 extern int preserve_perms;
44 extern int preserve_executability;
46 #define RETURN_ERROR_IF(x,e) \
54 #define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
56 int do_unlink(const char *fname)
58 if (dry_run) return 0;
59 RETURN_ERROR_IF_RO_OR_LO;
64 int do_symlink(const char *lnk, const char *fname)
66 if (dry_run) return 0;
67 RETURN_ERROR_IF_RO_OR_LO;
69 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
70 /* For --fake-super, we create a normal file with mode 0600
71 * and write the lnk into it. */
73 int ok, len = strlen(lnk);
74 int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
77 ok = write(fd, lnk, len) == len;
84 return symlink(lnk, fname);
87 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
88 ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
90 /* For --fake-super, we read the link from the file. */
92 int fd = do_open_nofollow(path, O_RDONLY);
94 int len = read(fd, buf, bufsiz);
100 /* A real symlink needs to be turned into a fake one on the receiving
101 * side, so tell the generator that the link has no length. */
104 /* Otherwise fall through and let the sender report the real length. */
107 return readlink(path, buf, bufsiz);
113 int do_link(const char *fname1, const char *fname2)
115 if (dry_run) return 0;
116 RETURN_ERROR_IF_RO_OR_LO;
117 return link(fname1, fname2);
121 int do_lchown(const char *path, uid_t owner, gid_t group)
123 if (dry_run) return 0;
124 RETURN_ERROR_IF_RO_OR_LO;
128 return lchown(path, owner, group);
131 int do_mknod(const char *pathname, mode_t mode, dev_t dev)
133 if (dry_run) return 0;
134 RETURN_ERROR_IF_RO_OR_LO;
136 /* For --fake-super, we create a normal file with mode 0600. */
138 int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
139 if (fd < 0 || close(fd) < 0)
144 #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
146 return mkfifo(pathname, mode);
148 #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
149 if (S_ISSOCK(mode)) {
151 struct sockaddr_un saddr;
152 unsigned int len = strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
153 if (len >= sizeof saddr.sun_path) {
154 errno = ENAMETOOLONG;
157 #ifdef HAVE_SOCKADDR_UN_LEN
158 saddr.sun_len = len + 1;
160 saddr.sun_family = AF_UNIX;
162 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
163 || (unlink(pathname) < 0 && errno != ENOENT)
164 || (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
168 return do_chmod(pathname, mode);
175 return mknod(pathname, mode, dev);
181 int do_rmdir(const char *pathname)
183 if (dry_run) return 0;
184 RETURN_ERROR_IF_RO_OR_LO;
185 return rmdir(pathname);
188 int do_open(const char *pathname, int flags, mode_t mode)
190 if (flags != O_RDONLY) {
191 RETURN_ERROR_IF(dry_run, 0);
192 RETURN_ERROR_IF_RO_OR_LO;
195 return open(pathname, flags | O_BINARY, mode);
199 int do_chmod(const char *path, mode_t mode)
202 if (dry_run) return 0;
203 RETURN_ERROR_IF_RO_OR_LO;
205 code = lchmod(path, mode & CHMOD_BITS);
208 # if defined HAVE_SETATTRLIST
209 struct attrlist attrList;
210 uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
212 memset(&attrList, 0, sizeof attrList);
213 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
214 attrList.commonattr = ATTR_CMN_ACCESSMASK;
215 code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
220 code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
221 #endif /* !HAVE_LCHMOD */
222 if (code != 0 && (preserve_perms || preserve_executability))
228 int do_rename(const char *fname1, const char *fname2)
230 if (dry_run) return 0;
231 RETURN_ERROR_IF_RO_OR_LO;
232 return rename(fname1, fname2);
235 #ifdef HAVE_FTRUNCATE
236 int do_ftruncate(int fd, OFF_T size)
240 if (dry_run) return 0;
241 RETURN_ERROR_IF_RO_OR_LO;
244 ret = ftruncate(fd, size);
245 } while (ret < 0 && errno == EINTR);
251 void trim_trailing_slashes(char *name)
254 /* Some BSD systems cannot make a directory if the name
255 * contains a trailing slash.
256 * <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
258 /* Don't change empty string; and also we can't improve on
263 if (name[--l] != '/')
269 int do_mkdir(char *fname, mode_t mode)
271 if (dry_run) return 0;
272 RETURN_ERROR_IF_RO_OR_LO;
273 trim_trailing_slashes(fname);
274 return mkdir(fname, mode);
277 /* like mkstemp but forces permissions */
278 int do_mkstemp(char *template, mode_t perms)
280 RETURN_ERROR_IF(dry_run, 0);
281 RETURN_ERROR_IF(read_only, EROFS);
284 #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
286 int fd = mkstemp(template);
289 if (fchmod(fd, perms) != 0 && preserve_perms) {
290 int errno_save = errno;
296 #if defined HAVE_SETMODE && O_BINARY
297 setmode(fd, O_BINARY);
302 if (!mktemp(template))
304 return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
308 int do_stat(const char *fname, STRUCT_STAT *st)
310 #ifdef USE_STAT64_FUNCS
311 return stat64(fname, st);
313 return stat(fname, st);
317 int do_lstat(const char *fname, STRUCT_STAT *st)
320 # ifdef USE_STAT64_FUNCS
321 return lstat64(fname, st);
323 return lstat(fname, st);
326 return do_stat(fname, st);
330 int do_fstat(int fd, STRUCT_STAT *st)
332 #ifdef USE_STAT64_FUNCS
333 return fstat64(fd, st);
335 return fstat(fd, st);
339 OFF_T do_lseek(int fd, OFF_T offset, int whence)
347 return lseek64(fd, offset, whence);
349 return lseek(fd, offset, whence);
353 #ifdef HAVE_UTIMENSAT
354 int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
356 struct timespec t[2];
358 if (dry_run) return 0;
359 RETURN_ERROR_IF_RO_OR_LO;
362 t[0].tv_nsec = UTIME_NOW;
363 t[1].tv_sec = modtime;
364 t[1].tv_nsec = mod_nsec;
365 return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
370 int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
374 if (dry_run) return 0;
375 RETURN_ERROR_IF_RO_OR_LO;
377 t[0].tv_sec = time(NULL);
379 t[1].tv_sec = modtime;
380 t[1].tv_usec = mod_nsec / 1000;
381 return lutimes(fname, t);
386 int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
390 if (dry_run) return 0;
391 RETURN_ERROR_IF_RO_OR_LO;
393 t[0].tv_sec = time(NULL);
395 t[1].tv_sec = modtime;
396 t[1].tv_usec = mod_nsec / 1000;
397 return utimes(fname, t);
400 #elif defined HAVE_UTIME
401 int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
403 #ifdef HAVE_STRUCT_UTIMBUF
409 if (dry_run) return 0;
410 RETURN_ERROR_IF_RO_OR_LO;
412 # ifdef HAVE_STRUCT_UTIMBUF
413 tbuf.actime = time(NULL);
414 tbuf.modtime = modtime;
415 return utime(fname, &tbuf);
419 return utime(fname, t);
424 #error Need utimes or utime function.
427 #ifdef SUPPORT_PREALLOCATION
428 #ifdef FALLOC_FL_KEEP_SIZE
429 #define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE
431 #define DO_FALLOC_OPTIONS 0
434 OFF_T do_fallocate(int fd, OFF_T offset, OFF_T length)
436 int opts = inplace || preallocate_files ? 0 : DO_FALLOC_OPTIONS;
438 RETURN_ERROR_IF(dry_run, 0);
439 RETURN_ERROR_IF_RO_OR_LO;
440 if (length & 1) /* make the length not match the desired length */
444 #if defined HAVE_FALLOCATE
445 ret = fallocate(fd, opts, offset, length);
446 #elif defined HAVE_SYS_FALLOCATE
447 ret = syscall(SYS_fallocate, fd, opts, (loff_t)offset, (loff_t)length);
448 #elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
449 ret = posix_fallocate(fd, offset, length);
451 #error Coding error in SUPPORT_PREALLOCATION logic.
457 if (do_fstat(fd, &st) < 0)
459 return st.st_blocks * 512;
465 /* Punch a hole at pos for len bytes. The current file position must be at pos and will be
466 * changed to be at pos + len. */
467 int do_punch_hole(int fd, UNUSED(OFF_T pos), int len)
469 #ifdef HAVE_FALLOCATE
470 # ifdef HAVE_FALLOC_FL_PUNCH_HOLE
471 if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, pos, len) == 0) {
472 if (do_lseek(fd, len, SEEK_CUR) != pos + len)
477 # ifdef HAVE_FALLOC_FL_ZERO_RANGE
478 if (fallocate(fd, FALLOC_FL_ZERO_RANGE, pos, len) == 0) {
479 if (do_lseek(fd, len, SEEK_CUR) != pos + len)
487 memset(zeros, 0, sizeof zeros);
489 int chunk = len > (int)sizeof zeros ? (int)sizeof zeros : len;
490 int wrote = write(fd, zeros, chunk);
492 if (wrote < 0 && errno == EINTR)
502 int do_open_nofollow(const char *pathname, int flags)
505 STRUCT_STAT f_st, l_st;
509 if (flags != O_RDONLY) {
510 RETURN_ERROR_IF(dry_run, 0);
511 RETURN_ERROR_IF_RO_OR_LO;
513 /* This function doesn't support write attempts w/o O_NOFOLLOW. */
520 fd = open(pathname, flags|O_NOFOLLOW);
522 if (do_lstat(pathname, &l_st) < 0)
524 if (S_ISLNK(l_st.st_mode)) {
528 if ((fd = open(pathname, flags)) < 0)
530 if (do_fstat(fd, &f_st) < 0) {
531 close_and_return_error:
533 int save_errno = errno;
539 if (l_st.st_dev != f_st.st_dev || l_st.st_ino != f_st.st_ino) {
541 goto close_and_return_error;