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