Preparing for release of 3.2.4pre2
[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-2022 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 #ifdef SUPPORT_CRTIMES
58 #ifdef HAVE_GETATTRLIST
59 #pragma pack(push, 4)
60 struct create_time {
61         uint32 length;
62         struct timespec crtime;
63 };
64 #pragma pack(pop)
65 #elif defined __CYGWIN__
66 #include <windows.h>
67 #endif
68 #endif
69
70 #define RETURN_ERROR_IF(x,e) \
71         do { \
72                 if (x) { \
73                         errno = (e); \
74                         return -1; \
75                 } \
76         } while (0)
77
78 #define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
79
80 int do_unlink(const char *path)
81 {
82         if (dry_run) return 0;
83         RETURN_ERROR_IF_RO_OR_LO;
84         return unlink(path);
85 }
86
87 #ifdef SUPPORT_LINKS
88 int do_symlink(const char *lnk, const char *path)
89 {
90         if (dry_run) return 0;
91         RETURN_ERROR_IF_RO_OR_LO;
92
93 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
94         /* For --fake-super, we create a normal file with mode 0600
95          * and write the lnk into it. */
96         if (am_root < 0) {
97                 int ok, len = strlen(lnk);
98                 int fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
99                 if (fd < 0)
100                         return -1;
101                 ok = write(fd, lnk, len) == len;
102                 if (close(fd) < 0)
103                         ok = 0;
104                 return ok ? 0 : -1;
105         }
106 #endif
107
108         return symlink(lnk, path);
109 }
110
111 #if defined NO_SYMLINK_XATTRS || defined NO_SYMLINK_USER_XATTRS
112 ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
113 {
114         /* For --fake-super, we read the link from the file. */
115         if (am_root < 0) {
116                 int fd = do_open_nofollow(path, O_RDONLY);
117                 if (fd >= 0) {
118                         int len = read(fd, buf, bufsiz);
119                         close(fd);
120                         return len;
121                 }
122                 if (errno != ELOOP)
123                         return -1;
124                 /* A real symlink needs to be turned into a fake one on the receiving
125                  * side, so tell the generator that the link has no length. */
126                 if (!am_sender)
127                         return 0;
128                 /* Otherwise fall through and let the sender report the real length. */
129         }
130
131         return readlink(path, buf, bufsiz);
132 }
133 #endif
134 #endif
135
136 #if defined HAVE_LINK || defined HAVE_LINKAT
137 int do_link(const char *old_path, const char *new_path)
138 {
139         if (dry_run) return 0;
140         RETURN_ERROR_IF_RO_OR_LO;
141 #ifdef HAVE_LINKAT
142         return linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0);
143 #else
144         return link(old_path, new_path);
145 #endif
146 }
147 #endif
148
149 int do_lchown(const char *path, uid_t owner, gid_t group)
150 {
151         if (dry_run) return 0;
152         RETURN_ERROR_IF_RO_OR_LO;
153 #ifndef HAVE_LCHOWN
154 #define lchown chown
155 #endif
156         return lchown(path, owner, group);
157 }
158
159 int do_mknod(const char *pathname, mode_t mode, dev_t dev)
160 {
161         if (dry_run) return 0;
162         RETURN_ERROR_IF_RO_OR_LO;
163
164         /* For --fake-super, we create a normal file with mode 0600. */
165         if (am_root < 0) {
166                 int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
167                 if (fd < 0 || close(fd) < 0)
168                         return -1;
169                 return 0;
170         }
171
172 #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
173         if (S_ISFIFO(mode))
174                 return mkfifo(pathname, mode);
175 #endif
176 #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
177         if (S_ISSOCK(mode)) {
178                 int sock;
179                 struct sockaddr_un saddr;
180                 unsigned int len = strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
181                 if (len >= sizeof saddr.sun_path) {
182                         errno = ENAMETOOLONG;
183                         return -1;
184                 }
185 #ifdef HAVE_SOCKADDR_UN_LEN
186                 saddr.sun_len = len + 1;
187 #endif
188                 saddr.sun_family = AF_UNIX;
189
190                 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
191                  || (unlink(pathname) < 0 && errno != ENOENT)
192                  || (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
193                         return -1;
194                 close(sock);
195 #ifdef HAVE_CHMOD
196                 return do_chmod(pathname, mode);
197 #else
198                 return 0;
199 #endif
200         }
201 #endif
202 #ifdef HAVE_MKNOD
203         return mknod(pathname, mode, dev);
204 #else
205         return -1;
206 #endif
207 }
208
209 int do_rmdir(const char *pathname)
210 {
211         if (dry_run) return 0;
212         RETURN_ERROR_IF_RO_OR_LO;
213         return rmdir(pathname);
214 }
215
216 int do_open(const char *pathname, int flags, mode_t mode)
217 {
218         if (flags != O_RDONLY) {
219                 RETURN_ERROR_IF(dry_run, 0);
220                 RETURN_ERROR_IF_RO_OR_LO;
221         }
222
223 #ifdef O_NOATIME
224         if (open_noatime)
225                 flags |= O_NOATIME;
226 #endif
227
228         return open(pathname, flags | O_BINARY, mode);
229 }
230
231 #ifdef HAVE_CHMOD
232 int do_chmod(const char *path, mode_t mode)
233 {
234         static int switch_step = 0;
235         int code;
236
237         if (dry_run) return 0;
238         RETURN_ERROR_IF_RO_OR_LO;
239
240         switch (switch_step) {
241 #ifdef HAVE_LCHMOD
242         case 0:
243                 if ((code = lchmod(path, mode & CHMOD_BITS)) == 0)
244                         break;
245                 if (errno == ENOSYS)
246                         switch_step++;
247                 else if (errno != ENOTSUP)
248                         break;
249 #endif
250
251         default:
252                 if (S_ISLNK(mode)) {
253 # if defined HAVE_SETATTRLIST
254                         struct attrlist attrList;
255                         uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
256
257                         memset(&attrList, 0, sizeof attrList);
258                         attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
259                         attrList.commonattr = ATTR_CMN_ACCESSMASK;
260                         code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
261 # else
262                         code = 1;
263 # endif
264                 } else
265                         code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
266                 break;
267         }
268         if (code != 0 && (preserve_perms || preserve_executability))
269                 return code;
270         return 0;
271 }
272 #endif
273
274 int do_rename(const char *old_path, const char *new_path)
275 {
276         if (dry_run) return 0;
277         RETURN_ERROR_IF_RO_OR_LO;
278         return rename(old_path, new_path);
279 }
280
281 #ifdef HAVE_FTRUNCATE
282 int do_ftruncate(int fd, OFF_T size)
283 {
284         int ret;
285
286         if (dry_run) return 0;
287         RETURN_ERROR_IF_RO_OR_LO;
288
289         do {
290                 ret = ftruncate(fd, size);
291         } while (ret < 0 && errno == EINTR);
292
293         return ret;
294 }
295 #endif
296
297 void trim_trailing_slashes(char *name)
298 {
299         int l;
300         /* Some BSD systems cannot make a directory if the name
301          * contains a trailing slash.
302          * <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
303
304         /* Don't change empty string; and also we can't improve on
305          * "/" */
306
307         l = strlen(name);
308         while (l > 1) {
309                 if (name[--l] != '/')
310                         break;
311                 name[l] = '\0';
312         }
313 }
314
315 int do_mkdir(char *path, mode_t mode)
316 {
317         if (dry_run) return 0;
318         RETURN_ERROR_IF_RO_OR_LO;
319         trim_trailing_slashes(path);
320         return mkdir(path, mode);
321 }
322
323 /* like mkstemp but forces permissions */
324 int do_mkstemp(char *template, mode_t perms)
325 {
326         RETURN_ERROR_IF(dry_run, 0);
327         RETURN_ERROR_IF(read_only, EROFS);
328         perms |= S_IWUSR;
329
330 #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
331         {
332                 int fd = mkstemp(template);
333                 if (fd == -1)
334                         return -1;
335                 if (fchmod(fd, perms) != 0 && preserve_perms) {
336                         int errno_save = errno;
337                         close(fd);
338                         unlink(template);
339                         errno = errno_save;
340                         return -1;
341                 }
342 #if defined HAVE_SETMODE && O_BINARY
343                 setmode(fd, O_BINARY);
344 #endif
345                 return fd;
346         }
347 #else
348         if (!mktemp(template))
349                 return -1;
350         return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
351 #endif
352 }
353
354 int do_stat(const char *path, STRUCT_STAT *st)
355 {
356 #ifdef USE_STAT64_FUNCS
357         return stat64(path, st);
358 #else
359         return stat(path, st);
360 #endif
361 }
362
363 int do_lstat(const char *path, STRUCT_STAT *st)
364 {
365 #ifdef SUPPORT_LINKS
366 # ifdef USE_STAT64_FUNCS
367         return lstat64(path, st);
368 # else
369         return lstat(path, st);
370 # endif
371 #else
372         return do_stat(path, st);
373 #endif
374 }
375
376 int do_fstat(int fd, STRUCT_STAT *st)
377 {
378 #ifdef USE_STAT64_FUNCS
379         return fstat64(fd, st);
380 #else
381         return fstat(fd, st);
382 #endif
383 }
384
385 OFF_T do_lseek(int fd, OFF_T offset, int whence)
386 {
387 #ifdef HAVE_LSEEK64
388 #if !SIZEOF_OFF64_T
389         OFF_T lseek64();
390 #else
391         off64_t lseek64();
392 #endif
393         return lseek64(fd, offset, whence);
394 #else
395         return lseek(fd, offset, whence);
396 #endif
397 }
398
399 #ifdef HAVE_SETATTRLIST
400 int do_setattrlist_times(const char *path, STRUCT_STAT *stp)
401 {
402         struct attrlist attrList;
403         struct timespec ts[2];
404
405         if (dry_run) return 0;
406         RETURN_ERROR_IF_RO_OR_LO;
407
408         /* Yes, this is in the opposite order of utime and similar. */
409         ts[0].tv_sec = stp->st_mtime;
410         ts[0].tv_nsec = stp->ST_MTIME_NSEC;
411
412         ts[1].tv_sec = stp->st_atime;
413         ts[1].tv_nsec = stp->ST_ATIME_NSEC;
414
415         memset(&attrList, 0, sizeof attrList);
416         attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
417         attrList.commonattr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME;
418         return setattrlist(path, &attrList, ts, sizeof ts, FSOPT_NOFOLLOW);
419 }
420
421 #ifdef SUPPORT_CRTIMES
422 int do_setattrlist_crtime(const char *path, time_t crtime)
423 {
424         struct attrlist attrList;
425         struct timespec ts;
426
427         if (dry_run) return 0;
428         RETURN_ERROR_IF_RO_OR_LO;
429
430         ts.tv_sec = crtime;
431         ts.tv_nsec = 0;
432
433         memset(&attrList, 0, sizeof attrList);
434         attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
435         attrList.commonattr = ATTR_CMN_CRTIME;
436         return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
437 }
438 #endif
439 #endif /* HAVE_SETATTRLIST */
440
441 #ifdef SUPPORT_CRTIMES
442 time_t get_create_time(const char *path, STRUCT_STAT *stp)
443 {
444 #ifdef HAVE_GETATTRLIST
445         static struct create_time attrBuf;
446         struct attrlist attrList;
447
448         (void)stp;
449         memset(&attrList, 0, sizeof attrList);
450         attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
451         attrList.commonattr = ATTR_CMN_CRTIME;
452         if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
453                 return 0;
454         return attrBuf.crtime.tv_sec;
455 #elif defined __CYGWIN__
456         (void)path;
457         return stp->st_birthtime;
458 #else
459 #error Unknown crtimes implementation
460 #endif
461 }
462
463 #if defined __CYGWIN__
464 int do_SetFileTime(const char *path, time_t crtime)
465 {
466         if (dry_run) return 0;
467         RETURN_ERROR_IF_RO_OR_LO;
468
469         int cnt = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
470         if (cnt == 0)
471             return -1;
472         WCHAR *pathw = new_array(WCHAR, cnt);
473         if (!pathw)
474             return -1;
475         MultiByteToWideChar(CP_UTF8, 0, path, -1, pathw, cnt);
476         HANDLE handle = CreateFileW(pathw, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
477                                     NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
478         free(pathw);
479         if (handle == INVALID_HANDLE_VALUE)
480             return -1;
481         int64 temp_time = Int32x32To64(crtime, 10000000) + 116444736000000000LL;
482         FILETIME birth_time;
483         birth_time.dwLowDateTime = (DWORD)temp_time;
484         birth_time.dwHighDateTime = (DWORD)(temp_time >> 32);
485         int ok = SetFileTime(handle, &birth_time, NULL, NULL);
486         CloseHandle(handle);
487         return ok ? 0 : -1;
488 }
489 #endif
490 #endif /* SUPPORT_CRTIMES */
491
492 #ifdef HAVE_UTIMENSAT
493 int do_utimensat(const char *path, STRUCT_STAT *stp)
494 {
495         struct timespec t[2];
496
497         if (dry_run) return 0;
498         RETURN_ERROR_IF_RO_OR_LO;
499
500         t[0].tv_sec = stp->st_atime;
501 #ifdef ST_ATIME_NSEC
502         t[0].tv_nsec = stp->ST_ATIME_NSEC;
503 #else
504         t[0].tv_nsec = 0;
505 #endif
506         t[1].tv_sec = stp->st_mtime;
507 #ifdef ST_MTIME_NSEC
508         t[1].tv_nsec = stp->ST_MTIME_NSEC;
509 #else
510         t[1].tv_nsec = 0;
511 #endif
512         return utimensat(AT_FDCWD, path, t, AT_SYMLINK_NOFOLLOW);
513 }
514 #endif
515
516 #ifdef HAVE_LUTIMES
517 int do_lutimes(const char *path, STRUCT_STAT *stp)
518 {
519         struct timeval t[2];
520
521         if (dry_run) return 0;
522         RETURN_ERROR_IF_RO_OR_LO;
523
524         t[0].tv_sec = stp->st_atime;
525 #ifdef ST_ATIME_NSEC
526         t[0].tv_usec = stp->ST_ATIME_NSEC / 1000;
527 #else
528         t[0].tv_usec = 0;
529 #endif
530         t[1].tv_sec = stp->st_mtime;
531 #ifdef ST_MTIME_NSEC
532         t[1].tv_usec = stp->ST_MTIME_NSEC / 1000;
533 #else
534         t[1].tv_usec = 0;
535 #endif
536         return lutimes(path, t);
537 }
538 #endif
539
540 #ifdef HAVE_UTIMES
541 int do_utimes(const char *path, STRUCT_STAT *stp)
542 {
543         struct timeval t[2];
544
545         if (dry_run) return 0;
546         RETURN_ERROR_IF_RO_OR_LO;
547
548         t[0].tv_sec = stp->st_atime;
549 #ifdef ST_ATIME_NSEC
550         t[0].tv_usec = stp->ST_ATIME_NSEC / 1000;
551 #else
552         t[0].tv_usec = 0;
553 #endif
554         t[1].tv_sec = stp->st_mtime;
555 #ifdef ST_MTIME_NSEC
556         t[1].tv_usec = stp->ST_MTIME_NSEC / 1000;
557 #else
558         t[1].tv_usec = 0;
559 #endif
560         return utimes(path, t);
561 }
562
563 #elif defined HAVE_UTIME
564 int do_utime(const char *path, STRUCT_STAT *stp)
565 {
566 #ifdef HAVE_STRUCT_UTIMBUF
567         struct utimbuf tbuf;
568 #else
569         time_t t[2];
570 #endif
571
572         if (dry_run) return 0;
573         RETURN_ERROR_IF_RO_OR_LO;
574
575 # ifdef HAVE_STRUCT_UTIMBUF
576         tbuf.actime = stp->st_atime;
577         tbuf.modtime = stp->st_mtime;
578         return utime(path, &tbuf);
579 # else
580         t[0] = stp->st_atime;
581         t[1] = stp->st_mtime;
582         return utime(path, t);
583 # endif
584 }
585
586 #else
587 #error Need utimes or utime function.
588 #endif
589
590 #ifdef SUPPORT_PREALLOCATION
591 #ifdef FALLOC_FL_KEEP_SIZE
592 #define DO_FALLOC_OPTIONS FALLOC_FL_KEEP_SIZE
593 #else
594 #define DO_FALLOC_OPTIONS 0
595 #endif
596
597 OFF_T do_fallocate(int fd, OFF_T offset, OFF_T length)
598 {
599         int opts = inplace || preallocate_files ? DO_FALLOC_OPTIONS : 0;
600         int ret;
601         RETURN_ERROR_IF(dry_run, 0);
602         RETURN_ERROR_IF_RO_OR_LO;
603         if (length & 1) /* make the length not match the desired length */
604                 length++;
605         else
606                 length--;
607 #if defined HAVE_FALLOCATE
608         ret = fallocate(fd, opts, offset, length);
609 #elif defined HAVE_SYS_FALLOCATE
610         ret = syscall(SYS_fallocate, fd, opts, (loff_t)offset, (loff_t)length);
611 #elif defined HAVE_EFFICIENT_POSIX_FALLOCATE
612         ret = posix_fallocate(fd, offset, length);
613 #else
614 #error Coding error in SUPPORT_PREALLOCATION logic.
615 #endif
616         if (ret < 0)
617                 return ret;
618         if (opts == 0) {
619                 STRUCT_STAT st;
620                 if (do_fstat(fd, &st) < 0)
621                         return length;
622                 return st.st_blocks * S_BLKSIZE;
623         }
624         return 0;
625 }
626 #endif
627
628 /* Punch a hole at pos for len bytes. The current file position must be at pos and will be
629  * changed to be at pos + len. */
630 int do_punch_hole(int fd, OFF_T pos, OFF_T len)
631 {
632 #ifdef HAVE_FALLOCATE
633 # ifdef HAVE_FALLOC_FL_PUNCH_HOLE
634         if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, pos, len) == 0) {
635                 if (do_lseek(fd, len, SEEK_CUR) != pos + len)
636                         return -1;
637                 return 0;
638         }
639 # endif
640 # ifdef HAVE_FALLOC_FL_ZERO_RANGE
641         if (fallocate(fd, FALLOC_FL_ZERO_RANGE, pos, len) == 0) {
642                 if (do_lseek(fd, len, SEEK_CUR) != pos + len)
643                         return -1;
644                 return 0;
645         }
646 # endif
647 #else
648         (void)pos;
649 #endif
650         {
651                 char zeros[4096];
652                 memset(zeros, 0, sizeof zeros);
653                 while (len > 0) {
654                         int chunk = len > (int)sizeof zeros ? (int)sizeof zeros : len;
655                         int wrote = write(fd, zeros, chunk);
656                         if (wrote <= 0) {
657                                 if (wrote < 0 && errno == EINTR)
658                                         continue;
659                                 return -1;
660                         }
661                         len -= wrote;
662                 }
663         }
664         return 0;
665 }
666
667 int do_open_nofollow(const char *pathname, int flags)
668 {
669 #ifndef O_NOFOLLOW
670         STRUCT_STAT f_st, l_st;
671 #endif
672         int fd;
673
674         if (flags != O_RDONLY) {
675                 RETURN_ERROR_IF(dry_run, 0);
676                 RETURN_ERROR_IF_RO_OR_LO;
677 #ifndef O_NOFOLLOW
678                 /* This function doesn't support write attempts w/o O_NOFOLLOW. */
679                 errno = EINVAL;
680                 return -1;
681 #endif
682         }
683
684 #ifdef O_NOFOLLOW
685         fd = open(pathname, flags|O_NOFOLLOW);
686 #else
687         if (do_lstat(pathname, &l_st) < 0)
688                 return -1;
689         if (S_ISLNK(l_st.st_mode)) {
690                 errno = ELOOP;
691                 return -1;
692         }
693         if ((fd = open(pathname, flags)) < 0)
694                 return fd;
695         if (do_fstat(fd, &f_st) < 0) {
696           close_and_return_error:
697                 {
698                         int save_errno = errno;
699                         close(fd);
700                         errno = save_errno;
701                 }
702                 return -1;
703         }
704         if (l_st.st_dev != f_st.st_dev || l_st.st_ino != f_st.st_ino) {
705                 errno = EINVAL;
706                 goto close_and_return_error;
707         }
708 #endif
709
710         return fd;
711 }