Avoid a test failure if `id` didn't work.
[rsync.git] / syscall.c
1 /*
2  * Syscall wrappers to ensure that nothing gets done in dry_run mode
3  * and to handle system peculiarities.
4  *
5  * Copyright (C) 1998 Andrew Tridgell
6  * Copyright (C) 2002 Martin Pool
7  * Copyright (C) 2003-2020 Wayne Davison
8  *
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.
13  *
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.
18  *
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.
21  */
22
23 #include "rsync.h"
24
25 #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
26 #include <sys/un.h>
27 #endif
28 #ifdef HAVE_SYS_ATTR_H
29 #include <sys/attr.h>
30 #endif
31
32 #if defined HAVE_SYS_FALLOCATE && !defined HAVE_FALLOCATE
33 #include <sys/syscall.h>
34 #endif
35
36 extern int dry_run;
37 extern int am_root;
38 extern int am_sender;
39 extern int read_only;
40 extern int list_only;
41 extern int inplace;
42 extern int preallocate_files;
43 extern int preserve_perms;
44 extern int preserve_executability;
45 extern int open_noatime;
46
47 #ifndef S_BLKSIZE
48 # if defined hpux || defined __hpux__ || defined __hpux
49 #  define S_BLKSIZE 1024
50 # elif defined _AIX && defined _I386
51 #  define S_BLKSIZE 4096
52 # else
53 #  define S_BLKSIZE 512
54 # endif
55 #endif
56
57 #define RETURN_ERROR_IF(x,e) \
58         do { \
59                 if (x) { \
60                         errno = (e); \
61                         return -1; \
62                 } \
63         } while (0)
64
65 #define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
66
67 int do_unlink(const char *fname)
68 {
69         if (dry_run) return 0;
70         RETURN_ERROR_IF_RO_OR_LO;
71         return unlink(fname);
72 }
73
74 #ifdef SUPPORT_LINKS
75 int do_symlink(const char *lnk, const char *fname)
76 {
77         if (dry_run) return 0;
78         RETURN_ERROR_IF_RO_OR_LO;
79
80 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
81         /* For --fake-super, we create a normal file with mode 0600
82          * and write the lnk into it. */
83         if (am_root < 0) {
84                 int ok, len = strlen(lnk);
85                 int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
86                 if (fd < 0)
87                         return -1;
88                 ok = write(fd, lnk, len) == len;
89                 if (close(fd) < 0)
90                         ok = 0;
91                 return ok ? 0 : -1;
92         }
93 #endif
94
95         return symlink(lnk, fname);
96 }
97
98 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
99 ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
100 {
101         /* For --fake-super, we read the link from the file. */
102         if (am_root < 0) {
103                 int fd = do_open_nofollow(path, O_RDONLY);
104                 if (fd >= 0) {
105                         int len = read(fd, buf, bufsiz);
106                         close(fd);
107                         return len;
108                 }
109                 if (errno != ELOOP)
110                         return -1;
111                 /* A real symlink needs to be turned into a fake one on the receiving
112                  * side, so tell the generator that the link has no length. */
113                 if (!am_sender)
114                         return 0;
115                 /* Otherwise fall through and let the sender report the real length. */
116         }
117
118         return readlink(path, buf, bufsiz);
119 }
120 #endif
121 #endif
122
123 #ifdef HAVE_LINK
124 int do_link(const char *old_path, const char *new_path)
125 {
126         if (dry_run) return 0;
127         RETURN_ERROR_IF_RO_OR_LO;
128         return link(old_path, new_path);
129 }
130 #endif
131
132 int do_lchown(const char *path, uid_t owner, gid_t group)
133 {
134         if (dry_run) return 0;
135         RETURN_ERROR_IF_RO_OR_LO;
136 #ifndef HAVE_LCHOWN
137 #define lchown chown
138 #endif
139         return lchown(path, owner, group);
140 }
141
142 int do_mknod(const char *pathname, mode_t mode, dev_t dev)
143 {
144         if (dry_run) return 0;
145         RETURN_ERROR_IF_RO_OR_LO;
146
147         /* For --fake-super, we create a normal file with mode 0600. */
148         if (am_root < 0) {
149                 int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
150                 if (fd < 0 || close(fd) < 0)
151                         return -1;
152                 return 0;
153         }
154
155 #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
156         if (S_ISFIFO(mode))
157                 return mkfifo(pathname, mode);
158 #endif
159 #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
160         if (S_ISSOCK(mode)) {
161                 int sock;
162                 struct sockaddr_un saddr;
163                 unsigned int len = strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
164                 if (len >= sizeof saddr.sun_path) {
165                         errno = ENAMETOOLONG;
166                         return -1;
167                 }
168 #ifdef HAVE_SOCKADDR_UN_LEN
169                 saddr.sun_len = len + 1;
170 #endif
171                 saddr.sun_family = AF_UNIX;
172
173                 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
174                  || (unlink(pathname) < 0 && errno != ENOENT)
175                  || (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
176                         return -1;
177                 close(sock);
178 #ifdef HAVE_CHMOD
179                 return do_chmod(pathname, mode);
180 #else
181                 return 0;
182 #endif
183         }
184 #endif
185 #ifdef HAVE_MKNOD
186         return mknod(pathname, mode, dev);
187 #else
188         return -1;
189 #endif
190 }
191
192 int do_rmdir(const char *pathname)
193 {
194         if (dry_run) return 0;
195         RETURN_ERROR_IF_RO_OR_LO;
196         return rmdir(pathname);
197 }
198
199 int do_open(const char *pathname, int flags, mode_t mode)
200 {
201         if (flags != O_RDONLY) {
202                 RETURN_ERROR_IF(dry_run, 0);
203                 RETURN_ERROR_IF_RO_OR_LO;
204         }
205
206 #ifdef O_NOATIME
207         if (open_noatime)
208                 flags |= O_NOATIME;
209 #endif
210
211         return open(pathname, flags | O_BINARY, mode);
212 }
213
214 #ifdef HAVE_CHMOD
215 int do_chmod(const char *path, mode_t mode)
216 {
217         int code;
218         if (dry_run) return 0;
219         RETURN_ERROR_IF_RO_OR_LO;
220 #ifdef HAVE_LCHMOD
221         code = lchmod(path, mode & CHMOD_BITS);
222 #else
223         if (S_ISLNK(mode)) {
224 # if defined HAVE_SETATTRLIST
225                 struct attrlist attrList;
226                 uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
227
228                 memset(&attrList, 0, sizeof attrList);
229                 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
230                 attrList.commonattr = ATTR_CMN_ACCESSMASK;
231                 code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
232 # else
233                 code = 1;
234 # endif
235         } else
236                 code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
237 #endif /* !HAVE_LCHMOD */
238         if (code != 0 && (preserve_perms || preserve_executability))
239                 return code;
240         return 0;
241 }
242 #endif
243
244 int do_rename(const char *old_path, const char *new_path)
245 {
246         if (dry_run) return 0;
247         RETURN_ERROR_IF_RO_OR_LO;
248         return rename(old_path, new_path);
249 }
250
251 #ifdef HAVE_FTRUNCATE
252 int do_ftruncate(int fd, OFF_T size)
253 {
254         int ret;
255
256         if (dry_run) return 0;
257         RETURN_ERROR_IF_RO_OR_LO;
258
259         do {
260                 ret = ftruncate(fd, size);
261         } while (ret < 0 && errno == EINTR);
262
263         return ret;
264 }
265 #endif
266
267 void trim_trailing_slashes(char *name)
268 {
269         int l;
270         /* Some BSD systems cannot make a directory if the name
271          * contains a trailing slash.
272          * <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
273
274         /* Don't change empty string; and also we can't improve on
275          * "/" */
276
277         l = strlen(name);
278         while (l > 1) {
279                 if (name[--l] != '/')
280                         break;
281                 name[l] = '\0';
282         }
283 }
284
285 int do_mkdir(char *fname, mode_t mode)
286 {
287         if (dry_run) return 0;
288         RETURN_ERROR_IF_RO_OR_LO;
289         trim_trailing_slashes(fname);
290         return mkdir(fname, mode);
291 }
292
293 /* like mkstemp but forces permissions */
294 int do_mkstemp(char *template, mode_t perms)
295 {
296         RETURN_ERROR_IF(dry_run, 0);
297         RETURN_ERROR_IF(read_only, EROFS);
298         perms |= S_IWUSR;
299
300 #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
301         {
302                 int fd = mkstemp(template);
303                 if (fd == -1)
304                         return -1;
305                 if (fchmod(fd, perms) != 0 && preserve_perms) {
306                         int errno_save = errno;
307                         close(fd);
308                         unlink(template);
309                         errno = errno_save;
310                         return -1;
311                 }
312 #if defined HAVE_SETMODE && O_BINARY
313                 setmode(fd, O_BINARY);
314 #endif
315                 return fd;
316         }
317 #else
318         if (!mktemp(template))
319                 return -1;
320         return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
321 #endif
322 }
323
324 int do_stat(const char *fname, STRUCT_STAT *st)
325 {
326 #ifdef USE_STAT64_FUNCS
327         return stat64(fname, st);
328 #else
329         return stat(fname, st);
330 #endif
331 }
332
333 int do_lstat(const char *fname, STRUCT_STAT *st)
334 {
335 #ifdef SUPPORT_LINKS
336 # ifdef USE_STAT64_FUNCS
337         return lstat64(fname, st);
338 # else
339         return lstat(fname, st);
340 # endif
341 #else
342         return do_stat(fname, st);
343 #endif
344 }
345
346 int do_fstat(int fd, STRUCT_STAT *st)
347 {
348 #ifdef USE_STAT64_FUNCS
349         return fstat64(fd, st);
350 #else
351         return fstat(fd, st);
352 #endif
353 }
354
355 OFF_T do_lseek(int fd, OFF_T offset, int whence)
356 {
357 #ifdef HAVE_LSEEK64
358 #if !SIZEOF_OFF64_T
359         OFF_T lseek64();
360 #else
361         off64_t lseek64();
362 #endif
363         return lseek64(fd, offset, whence);
364 #else
365         return lseek(fd, offset, whence);
366 #endif
367 }
368
369 #ifdef HAVE_SETATTRLIST
370 int do_setattrlist_times(const char *fname, STRUCT_STAT *stp)
371 {
372         struct attrlist attrList;
373         struct timespec ts;
374
375         if (dry_run) return 0;
376         RETURN_ERROR_IF_RO_OR_LO;
377
378         ts.tv_sec = stp->st_mtime;
379         ts.tv_nsec = stp->ST_MTIME_NSEC;
380
381         memset(&attrList, 0, sizeof attrList);
382         attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
383         attrList.commonattr = ATTR_CMN_MODTIME;
384         return setattrlist(fname, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
385 }
386 #endif
387
388 #ifdef HAVE_UTIMENSAT
389 int do_utimensat(const char *fname, STRUCT_STAT *stp)
390 {
391         struct timespec t[2];
392
393         if (dry_run) return 0;
394         RETURN_ERROR_IF_RO_OR_LO;
395
396         t[0].tv_sec = stp->st_atime;
397 #ifdef ST_ATIME_NSEC
398         t[0].tv_nsec = stp->ST_ATIME_NSEC;
399 #else
400         t[0].tv_nsec = 0;
401 #endif
402         t[1].tv_sec = stp->st_mtime;
403 #ifdef ST_MTIME_NSEC
404         t[1].tv_nsec = stp->ST_MTIME_NSEC;
405 #else
406         t[1].tv_nsec = 0;
407 #endif
408         return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
409 }
410 #endif
411
412 #ifdef HAVE_LUTIMES
413 int do_lutimes(const char *fname, STRUCT_STAT *stp)
414 {
415         struct timeval t[2];
416
417         if (dry_run) return 0;
418         RETURN_ERROR_IF_RO_OR_LO;
419
420         t[0].tv_sec = stp->st_atime;
421 #ifdef ST_ATIME_NSEC
422         t[0].tv_usec = stp->ST_ATIME_NSEC / 1000;
423 #else
424         t[0].tv_usec = 0;
425 #endif
426         t[1].tv_sec = stp->st_mtime;
427 #ifdef ST_MTIME_NSEC
428         t[1].tv_usec = stp->ST_MTIME_NSEC / 1000;
429 #else
430         t[1].tv_usec = 0;
431 #endif
432         return lutimes(fname, t);
433 }
434 #endif
435
436 #ifdef HAVE_UTIMES
437 int do_utimes(const char *fname, STRUCT_STAT *stp)
438 {
439         struct timeval t[2];
440
441         if (dry_run) return 0;
442         RETURN_ERROR_IF_RO_OR_LO;
443
444         t[0].tv_sec = stp->st_atime;
445 #ifdef ST_ATIME_NSEC
446         t[0].tv_usec = stp->ST_ATIME_NSEC / 1000;
447 #else
448         t[0].tv_usec = 0;
449 #endif
450         t[1].tv_sec = stp->st_mtime;
451 #ifdef ST_MTIME_NSEC
452         t[1].tv_usec = stp->ST_MTIME_NSEC / 1000;
453 #else
454         t[1].tv_usec = 0;
455 #endif
456         return utimes(fname, t);
457 }
458
459 #elif defined HAVE_UTIME
460 int do_utime(const char *fname, STRUCT_STAT *stp)
461 {
462 #ifdef HAVE_STRUCT_UTIMBUF
463         struct utimbuf tbuf;
464 #else
465         time_t t[2];
466 #endif
467
468         if (dry_run) return 0;
469         RETURN_ERROR_IF_RO_OR_LO;
470
471 # ifdef HAVE_STRUCT_UTIMBUF
472         tbuf.actime = stp->st_atime;
473         tbuf.modtime = stp->st_mtime;
474         return utime(fname, &tbuf);
475 # else
476         t[0] = stp->st_atime;
477         t[1] = stp->st_mtime;
478         return utime(fname, t);
479 # endif
480 }
481
482 #else
483 #error Need utimes or utime function.
484 #endif
485
486 #ifdef SUPPORT_PREALLOCATION
487 #ifdef FALLOC_FL_KEEP_SIZE
488 #define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE
489 #else
490 #define DO_FALLOC_OPTIONS 0
491 #endif
492
493 OFF_T do_fallocate(int fd, OFF_T offset, OFF_T length)
494 {
495         int opts = inplace || preallocate_files ? DO_FALLOC_OPTIONS : 0;
496         int ret;
497         RETURN_ERROR_IF(dry_run, 0);
498         RETURN_ERROR_IF_RO_OR_LO;
499         if (length & 1) /* make the length not match the desired length */
500                 length++;
501         else
502                 length--;
503 #if defined HAVE_FALLOCATE
504         ret = fallocate(fd, opts, offset, length);
505 #elif defined HAVE_SYS_FALLOCATE
506         ret = syscall(SYS_fallocate, fd, opts, (loff_t)offset, (loff_t)length);
507 #elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
508         ret = posix_fallocate(fd, offset, length);
509 #else
510 #error Coding error in SUPPORT_PREALLOCATION logic.
511 #endif
512         if (ret < 0)
513                 return ret;
514         if (opts == 0) {
515                 STRUCT_STAT st;
516                 if (do_fstat(fd, &st) < 0)
517                         return length;
518                 return st.st_blocks * S_BLKSIZE;
519         }
520         return 0;
521 }
522 #endif
523
524 /* Punch a hole at pos for len bytes. The current file position must be at pos and will be
525  * changed to be at pos + len. */
526 int do_punch_hole(int fd, OFF_T pos, OFF_T len)
527 {
528 #ifdef HAVE_FALLOCATE
529 # ifdef HAVE_FALLOC_FL_PUNCH_HOLE
530         if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, pos, len) == 0) {
531                 if (do_lseek(fd, len, SEEK_CUR) != pos + len)
532                         return -1;
533                 return 0;
534         }
535 # endif
536 # ifdef HAVE_FALLOC_FL_ZERO_RANGE
537         if (fallocate(fd, FALLOC_FL_ZERO_RANGE, pos, len) == 0) {
538                 if (do_lseek(fd, len, SEEK_CUR) != pos + len)
539                         return -1;
540                 return 0;
541         }
542 # endif
543 #else
544         (void)pos;
545 #endif
546         {
547                 char zeros[4096];
548                 memset(zeros, 0, sizeof zeros);
549                 while (len > 0) {
550                         int chunk = len > (int)sizeof zeros ? (int)sizeof zeros : len;
551                         int wrote = write(fd, zeros, chunk);
552                         if (wrote <= 0) {
553                                 if (wrote < 0 && errno == EINTR)
554                                         continue;
555                                 return -1;
556                         }
557                         len -= wrote;
558                 }
559         }
560         return 0;
561 }
562
563 int do_open_nofollow(const char *pathname, int flags)
564 {
565 #ifndef O_NOFOLLOW
566         STRUCT_STAT f_st, l_st;
567 #endif
568         int fd;
569
570         if (flags != O_RDONLY) {
571                 RETURN_ERROR_IF(dry_run, 0);
572                 RETURN_ERROR_IF_RO_OR_LO;
573 #ifndef O_NOFOLLOW
574                 /* This function doesn't support write attempts w/o O_NOFOLLOW. */
575                 errno = EINVAL;
576                 return -1;
577 #endif
578         }
579
580 #ifdef O_NOFOLLOW
581         fd = open(pathname, flags|O_NOFOLLOW);
582 #else
583         if (do_lstat(pathname, &l_st) < 0)
584                 return -1;
585         if (S_ISLNK(l_st.st_mode)) {
586                 errno = ELOOP;
587                 return -1;
588         }
589         if ((fd = open(pathname, flags)) < 0)
590                 return fd;
591         if (do_fstat(fd, &f_st) < 0) {
592           close_and_return_error:
593                 {
594                         int save_errno = errno;
595                         close(fd);
596                         errno = save_errno;
597                 }
598                 return -1;
599         }
600         if (l_st.st_dev != f_st.st_dev || l_st.st_ino != f_st.st_ino) {
601                 errno = EINVAL;
602                 goto close_and_return_error;
603         }
604 #endif
605
606         return fd;
607 }