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

1.1       misho       1: /*
                      2:  * Extended attribute support for rsync.
                      3:  *
                      4:  * Copyright (C) 2004 Red Hat, Inc.
                      5:  * Copyright (C) 2003-2008 Wayne Davison
                      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: 
                     25: #ifdef SUPPORT_XATTRS
                     26: 
                     27: #if defined HAVE_LINUX_XATTRS
                     28: 
                     29: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                     30: {
                     31:        return lgetxattr(path, name, value, size);
                     32: }
                     33: 
                     34: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                     35: {
                     36:        return fgetxattr(filedes, name, value, size);
                     37: }
                     38: 
                     39: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                     40: {
                     41:        return lsetxattr(path, name, value, size, 0);
                     42: }
                     43: 
                     44: int sys_lremovexattr(const char *path, const char *name)
                     45: {
                     46:        return lremovexattr(path, name);
                     47: }
                     48: 
                     49: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                     50: {
                     51:        return llistxattr(path, list, size);
                     52: }
                     53: 
                     54: #elif HAVE_OSX_XATTRS
                     55: 
                     56: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                     57: {
                     58:        return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
                     59: }
                     60: 
                     61: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                     62: {
                     63:        return fgetxattr(filedes, name, value, size, 0, 0);
                     64: }
                     65: 
                     66: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                     67: {
                     68:        return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
                     69: }
                     70: 
                     71: int sys_lremovexattr(const char *path, const char *name)
                     72: {
                     73:        return removexattr(path, name, XATTR_NOFOLLOW);
                     74: }
                     75: 
                     76: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                     77: {
                     78:        return listxattr(path, list, size, XATTR_NOFOLLOW);
                     79: }
                     80: 
                     81: #elif HAVE_FREEBSD_XATTRS
                     82: 
                     83: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
                     84: {
                     85:        return extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
                     86: }
                     87: 
                     88: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
                     89: {
                     90:        return extattr_get_fd(filedes, EXTATTR_NAMESPACE_USER, name, value, size);
                     91: }
                     92: 
                     93: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
                     94: {
                     95:        return extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
                     96: }
                     97: 
                     98: int sys_lremovexattr(const char *path, const char *name)
                     99: {
                    100:        return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name);
                    101: }
                    102: 
                    103: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                    104: {
                    105:        unsigned char keylen;
                    106:        ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
                    107: 
                    108:        if (len <= 0 || (size_t)len > size)
                    109:                return len;
                    110: 
                    111:        /* FreeBSD puts a single-byte length before each string, with no '\0'
                    112:         * terminator.  We need to change this into a series of null-terminted
                    113:         * strings.  Since the size is the same, we can simply transform the
                    114:         * output in place. */
                    115:        for (off = 0; off < len; off += keylen + 1) {
                    116:                keylen = ((unsigned char*)list)[off];
                    117:                if (off + keylen >= len) {
                    118:                        /* Should be impossible, but kernel bugs happen! */
                    119:                        errno = EINVAL;
                    120:                        return -1;
                    121:                }
                    122:                memmove(list+off, list+off+1, keylen);
                    123:                list[off+keylen] = '\0';
                    124:        }
                    125: 
                    126:        return len;
                    127: }
                    128: 
1.1.1.2 ! misho     129: #elif HAVE_SOLARIS_XATTRS
        !           130: 
        !           131: static ssize_t read_xattr(int attrfd, void *buf, size_t buflen)
        !           132: {
        !           133:        STRUCT_STAT sb;
        !           134:        ssize_t ret;
        !           135: 
        !           136:        if (fstat(attrfd, &sb) < 0)
        !           137:                ret = -1;
        !           138:        else if (sb.st_size > SSIZE_MAX) {
        !           139:                errno = ERANGE;
        !           140:                ret = -1;
        !           141:        } else if (buflen == 0)
        !           142:                ret = sb.st_size;
        !           143:        else if (sb.st_size > buflen) {
        !           144:                errno = ERANGE;
        !           145:                ret = -1;
        !           146:        } else {
        !           147:                size_t bufpos;
        !           148:                for (bufpos = 0; bufpos < sb.st_size; ) {
        !           149:                        ssize_t cnt = read(attrfd, buf + bufpos, sb.st_size - bufpos);
        !           150:                        if (cnt <= 0) {
        !           151:                                if (cnt < 0 && errno == EINTR)
        !           152:                                        continue;
        !           153:                                bufpos = -1;
        !           154:                                break;
        !           155:                        }
        !           156:                        bufpos += cnt;
        !           157:                }
        !           158:                ret = bufpos;
        !           159:        }
        !           160: 
        !           161:        close(attrfd);
        !           162: 
        !           163:        return ret;
        !           164: }
        !           165: 
        !           166: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
        !           167: {
        !           168:        int attrfd;
        !           169: 
        !           170:        if ((attrfd = attropen(path, name, O_RDONLY)) < 0) {
        !           171:                errno = ENOATTR;
        !           172:                return -1;
        !           173:        }
        !           174: 
        !           175:        return read_xattr(attrfd, value, size);
        !           176: }
        !           177: 
        !           178: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
        !           179: {
        !           180:        int attrfd;
        !           181: 
        !           182:        if ((attrfd = openat(filedes, name, O_RDONLY|O_XATTR, 0)) < 0) {
        !           183:                errno = ENOATTR;
        !           184:                return -1;
        !           185:        }
        !           186: 
        !           187:        return read_xattr(attrfd, value, size);
        !           188: }
        !           189: 
        !           190: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
        !           191: {
        !           192:        int attrfd;
        !           193:        size_t bufpos;
        !           194:        mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
        !           195: 
        !           196:        if ((attrfd = attropen(path, name, O_CREAT|O_TRUNC|O_WRONLY, mode)) < 0)
        !           197:                return -1;
        !           198: 
        !           199:        for (bufpos = 0; bufpos < size; ) {
        !           200:                ssize_t cnt = write(attrfd, value+bufpos, size);
        !           201:                if (cnt <= 0) {
        !           202:                        if (cnt < 0 && errno == EINTR)
        !           203:                                continue;
        !           204:                        bufpos = -1;
        !           205:                        break;
        !           206:                }
        !           207:                bufpos += cnt;
        !           208:        }
        !           209: 
        !           210:        close(attrfd);
        !           211: 
        !           212:        return bufpos > 0 ? 0 : -1;
        !           213: }
        !           214: 
        !           215: int sys_lremovexattr(const char *path, const char *name)
        !           216: {
        !           217:        int attrdirfd;
        !           218:        int ret;
        !           219: 
        !           220:        if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0)
        !           221:                return -1;
        !           222: 
        !           223:        ret = unlinkat(attrdirfd, name, 0);
        !           224: 
        !           225:        close(attrdirfd);
        !           226: 
        !           227:        return ret;
        !           228: }
        !           229: 
        !           230: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
        !           231: {
        !           232:        int attrdirfd;
        !           233:        DIR *dirp;
        !           234:        struct dirent *dp;
        !           235:        ssize_t ret = 0;
        !           236: 
        !           237:        if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0) {
        !           238:                errno = ENOTSUP;
        !           239:                return -1;
        !           240:        }
        !           241: 
        !           242:        if ((dirp = fdopendir(attrdirfd)) == NULL) {
        !           243:                close(attrdirfd);
        !           244:                return -1;
        !           245:        }
        !           246: 
        !           247:        while ((dp = readdir(dirp))) {
        !           248:                int len = strlen(dp->d_name);
        !           249: 
        !           250:                if (dp->d_name[0] == '.' && (len == 1 || (len == 2 && dp->d_name[1] == '.')))
        !           251:                        continue;
        !           252:                if (len == 11 && dp->d_name[0] == 'S' && strncmp(dp->d_name, "SUNWattr_r", 10) == 0
        !           253:                 && (dp->d_name[10] == 'o' || dp->d_name[10] == 'w'))
        !           254:                        continue;
        !           255: 
        !           256:                if ((ret += len+1) > size) {
        !           257:                        if (size == 0)
        !           258:                                continue;
        !           259:                        ret = -1;
        !           260:                        errno = ERANGE;
        !           261:                        break;
        !           262:                }
        !           263:                memcpy(list, dp->d_name, len+1);
        !           264:                list += len+1;
        !           265:        }
        !           266: 
        !           267:        closedir(dirp);
        !           268:        close(attrdirfd);
        !           269: 
        !           270:        return ret;
        !           271: }
        !           272: 
1.1       misho     273: #else
                    274: 
                    275: #error You need to create xattr compatibility functions.
                    276: 
                    277: #endif
                    278: 
                    279: #endif /* SUPPORT_XATTRS */

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