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>