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-2014 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>
41 extern int preserve_perms
;
42 extern int preserve_executability
;
44 #define RETURN_ERROR_IF(x,e) \
52 #define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
54 int do_unlink(const char *fname
)
56 if (dry_run
) return 0;
57 RETURN_ERROR_IF_RO_OR_LO
;
62 int do_symlink(const char *lnk
, const char *fname
)
64 if (dry_run
) return 0;
65 RETURN_ERROR_IF_RO_OR_LO
;
67 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
68 /* For --fake-super, we create a normal file with mode 0600
69 * and write the lnk into it. */
71 int ok
, len
= strlen(lnk
);
72 int fd
= open(fname
, O_WRONLY
|O_CREAT
|O_TRUNC
, S_IWUSR
|S_IRUSR
);
75 ok
= write(fd
, lnk
, len
) == len
;
82 return symlink(lnk
, fname
);
85 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
86 ssize_t
do_readlink(const char *path
, char *buf
, size_t bufsiz
)
88 /* For --fake-super, we read the link from the file. */
90 int fd
= do_open_nofollow(path
, O_RDONLY
);
92 int len
= read(fd
, buf
, bufsiz
);
98 /* A real symlink needs to be turned into a fake one on the receiving
99 * side, so tell the generator that the link has no length. */
102 /* Otherwise fall through and let the sender report the real length. */
105 return readlink(path
, buf
, bufsiz
);
111 int do_link(const char *fname1
, const char *fname2
)
113 if (dry_run
) return 0;
114 RETURN_ERROR_IF_RO_OR_LO
;
115 return link(fname1
, fname2
);
119 int do_lchown(const char *path
, uid_t owner
, gid_t group
)
121 if (dry_run
) return 0;
122 RETURN_ERROR_IF_RO_OR_LO
;
126 return lchown(path
, owner
, group
);
129 int do_mknod(const char *pathname
, mode_t mode
, dev_t dev
)
131 if (dry_run
) return 0;
132 RETURN_ERROR_IF_RO_OR_LO
;
134 /* For --fake-super, we create a normal file with mode 0600. */
136 int fd
= open(pathname
, O_WRONLY
|O_CREAT
|O_TRUNC
, S_IWUSR
|S_IRUSR
);
137 if (fd
< 0 || close(fd
) < 0)
142 #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
144 return mkfifo(pathname
, mode
);
146 #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
147 if (S_ISSOCK(mode
)) {
149 struct sockaddr_un saddr
;
150 unsigned int len
= strlcpy(saddr
.sun_path
, pathname
, sizeof saddr
.sun_path
);
151 if (len
>= sizeof saddr
.sun_path
) {
152 errno
= ENAMETOOLONG
;
155 #ifdef HAVE_SOCKADDR_UN_LEN
156 saddr
.sun_len
= len
+ 1;
158 saddr
.sun_family
= AF_UNIX
;
160 if ((sock
= socket(PF_UNIX
, SOCK_STREAM
, 0)) < 0
161 || (unlink(pathname
) < 0 && errno
!= ENOENT
)
162 || (bind(sock
, (struct sockaddr
*)&saddr
, sizeof saddr
)) < 0)
166 return do_chmod(pathname
, mode
);
173 return mknod(pathname
, mode
, dev
);
179 int do_rmdir(const char *pathname
)
181 if (dry_run
) return 0;
182 RETURN_ERROR_IF_RO_OR_LO
;
183 return rmdir(pathname
);
186 int do_open(const char *pathname
, int flags
, mode_t mode
)
188 if (flags
!= O_RDONLY
) {
189 RETURN_ERROR_IF(dry_run
, 0);
190 RETURN_ERROR_IF_RO_OR_LO
;
193 return open(pathname
, flags
| O_BINARY
, mode
);
197 int do_chmod(const char *path
, mode_t mode
)
200 if (dry_run
) return 0;
201 RETURN_ERROR_IF_RO_OR_LO
;
203 code
= lchmod(path
, mode
& CHMOD_BITS
);
206 # if defined HAVE_SETATTRLIST
207 struct attrlist attrList
;
208 uint32_t m
= mode
& CHMOD_BITS
; /* manpage is wrong: not mode_t! */
210 memset(&attrList
, 0, sizeof attrList
);
211 attrList
.bitmapcount
= ATTR_BIT_MAP_COUNT
;
212 attrList
.commonattr
= ATTR_CMN_ACCESSMASK
;
213 code
= setattrlist(path
, &attrList
, &m
, sizeof m
, FSOPT_NOFOLLOW
);
218 code
= chmod(path
, mode
& CHMOD_BITS
); /* DISCOURAGED FUNCTION */
219 #endif /* !HAVE_LCHMOD */
220 if (code
!= 0 && (preserve_perms
|| preserve_executability
))
226 int do_rename(const char *fname1
, const char *fname2
)
228 if (dry_run
) return 0;
229 RETURN_ERROR_IF_RO_OR_LO
;
230 return rename(fname1
, fname2
);
233 #ifdef HAVE_FTRUNCATE
234 int do_ftruncate(int fd
, OFF_T size
)
238 if (dry_run
) return 0;
239 RETURN_ERROR_IF_RO_OR_LO
;
242 ret
= ftruncate(fd
, size
);
243 } while (ret
< 0 && errno
== EINTR
);
249 void trim_trailing_slashes(char *name
)
252 /* Some BSD systems cannot make a directory if the name
253 * contains a trailing slash.
254 * <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
256 /* Don't change empty string; and also we can't improve on
261 if (name
[--l
] != '/')
267 int do_mkdir(char *fname
, mode_t mode
)
269 if (dry_run
) return 0;
270 RETURN_ERROR_IF_RO_OR_LO
;
271 trim_trailing_slashes(fname
);
272 return mkdir(fname
, mode
);
275 /* like mkstemp but forces permissions */
276 int do_mkstemp(char *template, mode_t perms
)
278 RETURN_ERROR_IF(dry_run
, 0);
279 RETURN_ERROR_IF(read_only
, EROFS
);
282 #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
284 int fd
= mkstemp(template);
287 if (fchmod(fd
, perms
) != 0 && preserve_perms
) {
288 int errno_save
= errno
;
294 #if defined HAVE_SETMODE && O_BINARY
295 setmode(fd
, O_BINARY
);
300 if (!mktemp(template))
302 return do_open(template, O_RDWR
|O_EXCL
|O_CREAT
, perms
);
306 int do_stat(const char *fname
, STRUCT_STAT
*st
)
308 #ifdef USE_STAT64_FUNCS
309 return stat64(fname
, st
);
311 return stat(fname
, st
);
315 int do_lstat(const char *fname
, STRUCT_STAT
*st
)
318 # ifdef USE_STAT64_FUNCS
319 return lstat64(fname
, st
);
321 return lstat(fname
, st
);
324 return do_stat(fname
, st
);
328 int do_fstat(int fd
, STRUCT_STAT
*st
)
330 #ifdef USE_STAT64_FUNCS
331 return fstat64(fd
, st
);
333 return fstat(fd
, st
);
337 OFF_T
do_lseek(int fd
, OFF_T offset
, int whence
)
345 return lseek64(fd
, offset
, whence
);
347 return lseek(fd
, offset
, whence
);
351 #ifdef HAVE_UTIMENSAT
352 int do_utimensat(const char *fname
, time_t modtime
, uint32 mod_nsec
)
354 struct timespec t
[2];
356 if (dry_run
) return 0;
357 RETURN_ERROR_IF_RO_OR_LO
;
360 t
[0].tv_nsec
= UTIME_NOW
;
361 t
[1].tv_sec
= modtime
;
362 t
[1].tv_nsec
= mod_nsec
;
363 return utimensat(AT_FDCWD
, fname
, t
, AT_SYMLINK_NOFOLLOW
);
368 int do_lutimes(const char *fname
, time_t modtime
, uint32 mod_nsec
)
372 if (dry_run
) return 0;
373 RETURN_ERROR_IF_RO_OR_LO
;
375 t
[0].tv_sec
= time(NULL
);
377 t
[1].tv_sec
= modtime
;
378 t
[1].tv_usec
= mod_nsec
/ 1000;
379 return lutimes(fname
, t
);
384 int do_utimes(const char *fname
, time_t modtime
, uint32 mod_nsec
)
388 if (dry_run
) return 0;
389 RETURN_ERROR_IF_RO_OR_LO
;
391 t
[0].tv_sec
= time(NULL
);
393 t
[1].tv_sec
= modtime
;
394 t
[1].tv_usec
= mod_nsec
/ 1000;
395 return utimes(fname
, t
);
398 #elif defined HAVE_UTIME
399 int do_utime(const char *fname
, time_t modtime
, UNUSED(uint32 mod_nsec
))
401 #ifdef HAVE_STRUCT_UTIMBUF
407 if (dry_run
) return 0;
408 RETURN_ERROR_IF_RO_OR_LO
;
410 # ifdef HAVE_STRUCT_UTIMBUF
411 tbuf
.actime
= time(NULL
);
412 tbuf
.modtime
= modtime
;
413 return utime(fname
, &tbuf
);
417 return utime(fname
, t
);
422 #error Need utimes or utime function.
425 #ifdef SUPPORT_PREALLOCATION
426 int do_fallocate(int fd
, OFF_T offset
, OFF_T length
)
428 #ifdef FALLOC_FL_KEEP_SIZE
429 #define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE
431 #define DO_FALLOC_OPTIONS 0
433 RETURN_ERROR_IF(dry_run
, 0);
434 RETURN_ERROR_IF_RO_OR_LO
;
435 #if defined HAVE_FALLOCATE
436 return fallocate(fd
, DO_FALLOC_OPTIONS
, offset
, length
);
437 #elif defined HAVE_SYS_FALLOCATE
438 return syscall(SYS_fallocate
, fd
, DO_FALLOC_OPTIONS
, (loff_t
)offset
, (loff_t
)length
);
439 #elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
440 return posix_fallocate(fd
, offset
, length
);
442 #error Coding error in SUPPORT_PREALLOCATION logic.
447 int do_open_nofollow(const char *pathname
, int flags
)
450 STRUCT_STAT f_st
, l_st
;
454 if (flags
!= O_RDONLY
) {
455 RETURN_ERROR_IF(dry_run
, 0);
456 RETURN_ERROR_IF_RO_OR_LO
;
458 /* This function doesn't support write attempts w/o O_NOFOLLOW. */
465 fd
= open(pathname
, flags
|O_NOFOLLOW
);
467 if (do_lstat(pathname
, &l_st
) < 0)
469 if (S_ISLNK(l_st
.st_mode
)) {
473 if ((fd
= open(pathname
, flags
)) < 0)
475 if (do_fstat(fd
, &f_st
) < 0) {
476 close_and_return_error
:
478 int save_errno
= errno
;
484 if (l_st
.st_dev
!= f_st
.st_dev
|| l_st
.st_ino
!= f_st
.st_ino
) {
486 goto close_and_return_error
;