Annotation of embedaddon/rsync/syscall.c, revision 1.1.1.1

1.1       misho       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-2009 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: extern int dry_run;
                     33: extern int am_root;
                     34: extern int read_only;
                     35: extern int list_only;
                     36: extern int preserve_perms;
                     37: extern int preserve_executability;
                     38: 
                     39: #define RETURN_ERROR_IF(x,e) \
                     40:        do { \
                     41:                if (x) { \
                     42:                        errno = (e); \
                     43:                        return -1; \
                     44:                } \
                     45:        } while (0)
                     46: 
                     47: #define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
                     48: 
                     49: int do_unlink(const char *fname)
                     50: {
                     51:        if (dry_run) return 0;
                     52:        RETURN_ERROR_IF_RO_OR_LO;
                     53:        return unlink(fname);
                     54: }
                     55: 
                     56: int do_symlink(const char *fname1, const char *fname2)
                     57: {
                     58:        if (dry_run) return 0;
                     59:        RETURN_ERROR_IF_RO_OR_LO;
                     60:        return symlink(fname1, fname2);
                     61: }
                     62: 
                     63: #ifdef HAVE_LINK
                     64: int do_link(const char *fname1, const char *fname2)
                     65: {
                     66:        if (dry_run) return 0;
                     67:        RETURN_ERROR_IF_RO_OR_LO;
                     68:        return link(fname1, fname2);
                     69: }
                     70: #endif
                     71: 
                     72: int do_lchown(const char *path, uid_t owner, gid_t group)
                     73: {
                     74:        if (dry_run) return 0;
                     75:        RETURN_ERROR_IF_RO_OR_LO;
                     76: #ifndef HAVE_LCHOWN
                     77: #define lchown chown
                     78: #endif
                     79:        return lchown(path, owner, group);
                     80: }
                     81: 
                     82: int do_mknod(const char *pathname, mode_t mode, dev_t dev)
                     83: {
                     84:        if (dry_run) return 0;
                     85:        RETURN_ERROR_IF_RO_OR_LO;
                     86: 
                     87:        /* For --fake-super, we create a normal file with mode 0600. */
                     88:        if (am_root < 0) {
                     89:                int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
                     90:                if (fd < 0 || close(fd) < 0)
                     91:                        return -1;
                     92:                return 0;
                     93:        }
                     94: 
                     95: #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
                     96:        if (S_ISFIFO(mode))
                     97:                return mkfifo(pathname, mode);
                     98: #endif
                     99: #if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
                    100:        if (S_ISSOCK(mode)) {
                    101:                int sock;
                    102:                struct sockaddr_un saddr;
                    103: #ifdef HAVE_SOCKADDR_UN_LEN
                    104:                unsigned int len =
                    105: #endif
                    106:                    strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
                    107: #ifdef HAVE_SOCKADDR_UN_LEN
                    108:                saddr.sun_len = len >= sizeof saddr.sun_path
                    109:                              ? sizeof saddr.sun_path : len + 1;
                    110: #endif
                    111:                saddr.sun_family = AF_UNIX;
                    112: 
                    113:                if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
                    114:                    || (unlink(pathname) < 0 && errno != ENOENT)
                    115:                    || (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
                    116:                        return -1;
                    117:                close(sock);
                    118: #ifdef HAVE_CHMOD
                    119:                return do_chmod(pathname, mode);
                    120: #else
                    121:                return 0;
                    122: #endif
                    123:        }
                    124: #endif
                    125: #ifdef HAVE_MKNOD
                    126:        return mknod(pathname, mode, dev);
                    127: #else
                    128:        return -1;
                    129: #endif
                    130: }
                    131: 
                    132: int do_rmdir(const char *pathname)
                    133: {
                    134:        if (dry_run) return 0;
                    135:        RETURN_ERROR_IF_RO_OR_LO;
                    136:        return rmdir(pathname);
                    137: }
                    138: 
                    139: int do_open(const char *pathname, int flags, mode_t mode)
                    140: {
                    141:        if (flags != O_RDONLY) {
                    142:                RETURN_ERROR_IF(dry_run, 0);
                    143:                RETURN_ERROR_IF_RO_OR_LO;
                    144:        }
                    145: 
                    146:        return open(pathname, flags | O_BINARY, mode);
                    147: }
                    148: 
                    149: #ifdef HAVE_CHMOD
                    150: int do_chmod(const char *path, mode_t mode)
                    151: {
                    152:        int code;
                    153:        if (dry_run) return 0;
                    154:        RETURN_ERROR_IF_RO_OR_LO;
                    155: #ifdef HAVE_LCHMOD
                    156:        code = lchmod(path, mode & CHMOD_BITS);
                    157: #else
                    158:        if (S_ISLNK(mode)) {
                    159: # if defined HAVE_SETATTRLIST
                    160:                struct attrlist attrList;
                    161:                uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
                    162: 
                    163:                memset(&attrList, 0, sizeof attrList);
                    164:                attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
                    165:                attrList.commonattr = ATTR_CMN_ACCESSMASK;
                    166:                code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
                    167: # else
                    168:                code = 1;
                    169: # endif
                    170:        } else
                    171:                code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
                    172: #endif /* !HAVE_LCHMOD */
                    173:        if (code != 0 && (preserve_perms || preserve_executability))
                    174:                return code;
                    175:        return 0;
                    176: }
                    177: #endif
                    178: 
                    179: int do_rename(const char *fname1, const char *fname2)
                    180: {
                    181:        if (dry_run) return 0;
                    182:        RETURN_ERROR_IF_RO_OR_LO;
                    183:        return rename(fname1, fname2);
                    184: }
                    185: 
                    186: #ifdef HAVE_FTRUNCATE
                    187: int do_ftruncate(int fd, OFF_T size)
                    188: {
                    189:        int ret;
                    190: 
                    191:        if (dry_run) return 0;
                    192:        RETURN_ERROR_IF_RO_OR_LO;
                    193: 
                    194:        do {
                    195:                ret = ftruncate(fd, size);
                    196:        } while (ret < 0 && errno == EINTR);
                    197: 
                    198:        return ret;
                    199: }
                    200: #endif
                    201: 
                    202: void trim_trailing_slashes(char *name)
                    203: {
                    204:        int l;
                    205:        /* Some BSD systems cannot make a directory if the name
                    206:         * contains a trailing slash.
                    207:         * <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
                    208: 
                    209:        /* Don't change empty string; and also we can't improve on
                    210:         * "/" */
                    211: 
                    212:        l = strlen(name);
                    213:        while (l > 1) {
                    214:                if (name[--l] != '/')
                    215:                        break;
                    216:                name[l] = '\0';
                    217:        }
                    218: }
                    219: 
                    220: int do_mkdir(char *fname, mode_t mode)
                    221: {
                    222:        if (dry_run) return 0;
                    223:        RETURN_ERROR_IF_RO_OR_LO;
                    224:        trim_trailing_slashes(fname);
                    225:        return mkdir(fname, mode);
                    226: }
                    227: 
                    228: /* like mkstemp but forces permissions */
                    229: int do_mkstemp(char *template, mode_t perms)
                    230: {
                    231:        RETURN_ERROR_IF(dry_run, 0);
                    232:        RETURN_ERROR_IF(read_only, EROFS);
                    233:        perms |= S_IWUSR;
                    234: 
                    235: #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
                    236:        {
                    237:                int fd = mkstemp(template);
                    238:                if (fd == -1)
                    239:                        return -1;
                    240:                if (fchmod(fd, perms) != 0 && preserve_perms) {
                    241:                        int errno_save = errno;
                    242:                        close(fd);
                    243:                        unlink(template);
                    244:                        errno = errno_save;
                    245:                        return -1;
                    246:                }
                    247: #if defined HAVE_SETMODE && O_BINARY
                    248:                setmode(fd, O_BINARY);
                    249: #endif
                    250:                return fd;
                    251:        }
                    252: #else
                    253:        if (!mktemp(template))
                    254:                return -1;
                    255:        return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
                    256: #endif
                    257: }
                    258: 
                    259: int do_stat(const char *fname, STRUCT_STAT *st)
                    260: {
                    261: #ifdef USE_STAT64_FUNCS
                    262:        return stat64(fname, st);
                    263: #else
                    264:        return stat(fname, st);
                    265: #endif
                    266: }
                    267: 
                    268: int do_lstat(const char *fname, STRUCT_STAT *st)
                    269: {
                    270: #ifdef SUPPORT_LINKS
                    271: # ifdef USE_STAT64_FUNCS
                    272:        return lstat64(fname, st);
                    273: # else
                    274:        return lstat(fname, st);
                    275: # endif
                    276: #else
                    277:        return do_stat(fname, st);
                    278: #endif
                    279: }
                    280: 
                    281: int do_fstat(int fd, STRUCT_STAT *st)
                    282: {
                    283: #ifdef USE_STAT64_FUNCS
                    284:        return fstat64(fd, st);
                    285: #else
                    286:        return fstat(fd, st);
                    287: #endif
                    288: }
                    289: 
                    290: OFF_T do_lseek(int fd, OFF_T offset, int whence)
                    291: {
                    292: #ifdef HAVE_LSEEK64
                    293: #if !SIZEOF_OFF64_T
                    294:        OFF_T lseek64();
                    295: #else
                    296:        off64_t lseek64();
                    297: #endif
                    298:        return lseek64(fd, offset, whence);
                    299: #else
                    300:        return lseek(fd, offset, whence);
                    301: #endif
                    302: }
                    303: 
                    304: #ifdef HAVE_UTIMENSAT
                    305: int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
                    306: {
                    307:        struct timespec t[2];
                    308: 
                    309:        if (dry_run) return 0;
                    310:        RETURN_ERROR_IF_RO_OR_LO;
                    311: 
                    312:        t[0].tv_sec = 0;
                    313:        t[0].tv_nsec = UTIME_NOW;
                    314:        t[1].tv_sec = modtime;
                    315:        t[1].tv_nsec = mod_nsec;
                    316:        return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
                    317: }
                    318: #endif
                    319: 
                    320: #ifdef HAVE_LUTIMES
                    321: int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
                    322: {
                    323:        struct timeval t[2];
                    324: 
                    325:        if (dry_run) return 0;
                    326:        RETURN_ERROR_IF_RO_OR_LO;
                    327: 
                    328:        t[0].tv_sec = time(NULL);
                    329:        t[0].tv_usec = 0;
                    330:        t[1].tv_sec = modtime;
                    331:        t[1].tv_usec = mod_nsec / 1000;
                    332:        return lutimes(fname, t);
                    333: }
                    334: #endif
                    335: 
                    336: #ifdef HAVE_UTIMES
                    337: int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
                    338: {
                    339:        struct timeval t[2];
                    340: 
                    341:        if (dry_run) return 0;
                    342:        RETURN_ERROR_IF_RO_OR_LO;
                    343: 
                    344:        t[0].tv_sec = time(NULL);
                    345:        t[0].tv_usec = 0;
                    346:        t[1].tv_sec = modtime;
                    347:        t[1].tv_usec = mod_nsec / 1000;
                    348:        return utimes(fname, t);
                    349: }
                    350: 
                    351: #elif defined HAVE_UTIME
                    352: int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
                    353: {
                    354: #ifdef HAVE_STRUCT_UTIMBUF
                    355:        struct utimbuf tbuf;
                    356: #else
                    357:        time_t t[2];
                    358: #endif
                    359: 
                    360:        if (dry_run) return 0;
                    361:        RETURN_ERROR_IF_RO_OR_LO;
                    362: 
                    363: # ifdef HAVE_STRUCT_UTIMBUF
                    364:        tbuf.actime = time(NULL);
                    365:        tbuf.modtime = modtime;
                    366:        return utime(fname, &tbuf);
                    367: # else
                    368:        t[0] = time(NULL);
                    369:        t[1] = modtime;
                    370:        return utime(fname, t);
                    371: # endif
                    372: }
                    373: 
                    374: #else
                    375: #error Need utimes or utime function.
                    376: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>