Annotation of embedaddon/rsync/lib/sysxattrs.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:  * Extended attribute support for rsync.
                      3:  *
                      4:  * Copyright (C) 2004 Red Hat, Inc.
1.1.1.4 ! misho       5:  * Copyright (C) 2003-2019 Wayne Davison
1.1       misho       6:  * Written by Jay Fenlason.
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 3 of the License, or
                     11:  * (at your option) any later version.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful,
                     14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:  * GNU General Public License for more details.
                     17:  *
                     18:  * You should have received a copy of the GNU General Public License along
                     19:  * with this program; if not, visit the http://fsf.org website.
                     20:  */
                     21: 
                     22: #include "rsync.h"
                     23: #include "sysxattrs.h"
                     24: 
1.1.1.4 ! misho      25: extern int preserve_hfs_compression;
        !            26: 
1.1       misho      27: #ifdef SUPPORT_XATTRS
                     28: 
1.1.1.3   misho      29: #ifdef HAVE_OSX_XATTRS
1.1.1.4 ! misho      30: #ifndef XATTR_SHOWCOMPRESSION
        !            31: #define XATTR_SHOWCOMPRESSION 0x0020
        !            32: #endif
1.1.1.3   misho      33: #define GETXATTR_FETCH_LIMIT (64*1024*1024)
1.1.1.4 ! misho      34: 
        !            35: int xattr_options = XATTR_NOFOLLOW;
1.1.1.3   misho      36: #endif
                     37: 
1.1       misho      38: #if defined HAVE_LINUX_XATTRS
                     39: 
                     40: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                     41: {
                     42:        return lgetxattr(path, name, value, size);
                     43: }
                     44: 
                     45: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                     46: {
                     47:        return fgetxattr(filedes, name, value, size);
                     48: }
                     49: 
                     50: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                     51: {
                     52:        return lsetxattr(path, name, value, size, 0);
                     53: }
                     54: 
                     55: int sys_lremovexattr(const char *path, const char *name)
                     56: {
                     57:        return lremovexattr(path, name);
                     58: }
                     59: 
                     60: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                     61: {
                     62:        return llistxattr(path, list, size);
                     63: }
                     64: 
                     65: #elif HAVE_OSX_XATTRS
                     66: 
                     67: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                     68: {
1.1.1.4 ! misho      69:        ssize_t len;
        !            70: 
        !            71:        if (preserve_hfs_compression)
        !            72:                xattr_options |= XATTR_SHOWCOMPRESSION;
        !            73: 
        !            74:        len = getxattr(path, name, value, size, 0, xattr_options);
1.1.1.3   misho      75: 
                     76:        /* If we're retrieving data, handle resource forks > 64MB specially */
                     77:        if (value != NULL && len == GETXATTR_FETCH_LIMIT && (size_t)len < size) {
                     78:                /* getxattr will only return 64MB of data at a time, need to call again with a new offset */
                     79:                u_int32_t offset = len;
                     80:                size_t data_retrieved = len;
                     81:                while (data_retrieved < size) {
1.1.1.4 ! misho      82:                        len = getxattr(path, name, value + offset, size - data_retrieved, offset, xattr_options);
1.1.1.3   misho      83:                        if (len <= 0)
                     84:                                break;
                     85:                        data_retrieved += len;
                     86:                        offset += (u_int32_t)len;
                     87:                }
                     88:                len = data_retrieved;
                     89:        }
                     90: 
                     91:        return len;
1.1       misho      92: }
                     93: 
                     94: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                     95: {
                     96:        return fgetxattr(filedes, name, value, size, 0, 0);
                     97: }
                     98: 
                     99: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                    100: {
                    101:        return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
                    102: }
                    103: 
                    104: int sys_lremovexattr(const char *path, const char *name)
                    105: {
1.1.1.4 ! misho     106:        if (preserve_hfs_compression)
        !           107:                xattr_options |= XATTR_SHOWCOMPRESSION;
        !           108:        return removexattr(path, name, xattr_options);
1.1       misho     109: }
                    110: 
                    111: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                    112: {
1.1.1.4 ! misho     113:        if (preserve_hfs_compression)
        !           114:                xattr_options |= XATTR_SHOWCOMPRESSION;
        !           115:        return listxattr(path, list, size, xattr_options);
1.1       misho     116: }
                    117: 
                    118: #elif HAVE_FREEBSD_XATTRS
                    119: 
                    120: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                    121: {
                    122:        return extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
                    123: }
                    124: 
                    125: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                    126: {
                    127:        return extattr_get_fd(filedes, EXTATTR_NAMESPACE_USER, name, value, size);
                    128: }
                    129: 
                    130: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                    131: {
                    132:        return extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
                    133: }
                    134: 
                    135: int sys_lremovexattr(const char *path, const char *name)
                    136: {
                    137:        return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name);
                    138: }
                    139: 
                    140: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                    141: {
                    142:        unsigned char keylen;
                    143:        ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
                    144: 
                    145:        if (len <= 0 || (size_t)len > size)
                    146:                return len;
                    147: 
                    148:        /* FreeBSD puts a single-byte length before each string, with no '\0'
                    149:         * terminator.  We need to change this into a series of null-terminted
                    150:         * strings.  Since the size is the same, we can simply transform the
                    151:         * output in place. */
                    152:        for (off = 0; off < len; off += keylen + 1) {
                    153:                keylen = ((unsigned char*)list)[off];
                    154:                if (off + keylen >= len) {
                    155:                        /* Should be impossible, but kernel bugs happen! */
                    156:                        errno = EINVAL;
                    157:                        return -1;
                    158:                }
                    159:                memmove(list+off, list+off+1, keylen);
                    160:                list[off+keylen] = '\0';
                    161:        }
                    162: 
                    163:        return len;
                    164: }
                    165: 
1.1.1.2   misho     166: #elif HAVE_SOLARIS_XATTRS
                    167: 
                    168: static ssize_t read_xattr(int attrfd, void *buf, size_t buflen)
                    169: {
                    170:        STRUCT_STAT sb;
                    171:        ssize_t ret;
                    172: 
                    173:        if (fstat(attrfd, &sb) < 0)
                    174:                ret = -1;
                    175:        else if (sb.st_size > SSIZE_MAX) {
                    176:                errno = ERANGE;
                    177:                ret = -1;
                    178:        } else if (buflen == 0)
                    179:                ret = sb.st_size;
                    180:        else if (sb.st_size > buflen) {
                    181:                errno = ERANGE;
                    182:                ret = -1;
                    183:        } else {
                    184:                size_t bufpos;
                    185:                for (bufpos = 0; bufpos < sb.st_size; ) {
                    186:                        ssize_t cnt = read(attrfd, buf + bufpos, sb.st_size - bufpos);
                    187:                        if (cnt <= 0) {
                    188:                                if (cnt < 0 && errno == EINTR)
                    189:                                        continue;
                    190:                                bufpos = -1;
                    191:                                break;
                    192:                        }
                    193:                        bufpos += cnt;
                    194:                }
                    195:                ret = bufpos;
                    196:        }
                    197: 
                    198:        close(attrfd);
                    199: 
                    200:        return ret;
                    201: }
                    202: 
                    203: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                    204: {
                    205:        int attrfd;
                    206: 
                    207:        if ((attrfd = attropen(path, name, O_RDONLY)) < 0) {
                    208:                errno = ENOATTR;
                    209:                return -1;
                    210:        }
                    211: 
                    212:        return read_xattr(attrfd, value, size);
                    213: }
                    214: 
                    215: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                    216: {
                    217:        int attrfd;
                    218: 
                    219:        if ((attrfd = openat(filedes, name, O_RDONLY|O_XATTR, 0)) < 0) {
                    220:                errno = ENOATTR;
                    221:                return -1;
                    222:        }
                    223: 
                    224:        return read_xattr(attrfd, value, size);
                    225: }
                    226: 
                    227: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                    228: {
                    229:        int attrfd;
                    230:        size_t bufpos;
                    231:        mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
                    232: 
                    233:        if ((attrfd = attropen(path, name, O_CREAT|O_TRUNC|O_WRONLY, mode)) < 0)
                    234:                return -1;
                    235: 
                    236:        for (bufpos = 0; bufpos < size; ) {
                    237:                ssize_t cnt = write(attrfd, value+bufpos, size);
                    238:                if (cnt <= 0) {
                    239:                        if (cnt < 0 && errno == EINTR)
                    240:                                continue;
                    241:                        bufpos = -1;
                    242:                        break;
                    243:                }
                    244:                bufpos += cnt;
                    245:        }
                    246: 
                    247:        close(attrfd);
                    248: 
                    249:        return bufpos > 0 ? 0 : -1;
                    250: }
                    251: 
                    252: int sys_lremovexattr(const char *path, const char *name)
                    253: {
                    254:        int attrdirfd;
                    255:        int ret;
                    256: 
                    257:        if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0)
                    258:                return -1;
                    259: 
                    260:        ret = unlinkat(attrdirfd, name, 0);
                    261: 
                    262:        close(attrdirfd);
                    263: 
                    264:        return ret;
                    265: }
                    266: 
                    267: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                    268: {
                    269:        int attrdirfd;
                    270:        DIR *dirp;
                    271:        struct dirent *dp;
                    272:        ssize_t ret = 0;
                    273: 
                    274:        if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0) {
                    275:                errno = ENOTSUP;
                    276:                return -1;
                    277:        }
                    278: 
                    279:        if ((dirp = fdopendir(attrdirfd)) == NULL) {
                    280:                close(attrdirfd);
                    281:                return -1;
                    282:        }
                    283: 
                    284:        while ((dp = readdir(dirp))) {
                    285:                int len = strlen(dp->d_name);
                    286: 
                    287:                if (dp->d_name[0] == '.' && (len == 1 || (len == 2 && dp->d_name[1] == '.')))
                    288:                        continue;
                    289:                if (len == 11 && dp->d_name[0] == 'S' && strncmp(dp->d_name, "SUNWattr_r", 10) == 0
                    290:                 && (dp->d_name[10] == 'o' || dp->d_name[10] == 'w'))
                    291:                        continue;
                    292: 
                    293:                if ((ret += len+1) > size) {
                    294:                        if (size == 0)
                    295:                                continue;
                    296:                        ret = -1;
                    297:                        errno = ERANGE;
                    298:                        break;
                    299:                }
                    300:                memcpy(list, dp->d_name, len+1);
                    301:                list += len+1;
                    302:        }
                    303: 
                    304:        closedir(dirp);
                    305:        close(attrdirfd);
                    306: 
                    307:        return ret;
                    308: }
                    309: 
1.1       misho     310: #else
                    311: 
                    312: #error You need to create xattr compatibility functions.
                    313: 
                    314: #endif
                    315: 
                    316: #endif /* SUPPORT_XATTRS */

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