Switching to GPL 3.
[rsync/rsync.git] / lib / sysxattrs.c
1 /*
2  * Extended attribute support for rsync.
3  *
4  * Copyright (C) 2004 Red Hat, Inc.
5  * Written by Jay Fenlason.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 3 as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, visit the http://fsf.org website.
18  */
19
20 #include "rsync.h"
21 #include "sysxattrs.h"
22
23 #ifdef SUPPORT_XATTRS
24
25 #if defined HAVE_LINUX_XATTRS
26
27 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
28 {
29         return lgetxattr(path, name, value, size);
30 }
31
32 ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
33 {
34         return fgetxattr(filedes, name, value, size);
35 }
36
37 int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
38 {
39         return lsetxattr(path, name, value, size, 0);
40 }
41
42 int sys_lremovexattr(const char *path, const char *name)
43 {
44         return lremovexattr(path, name);
45 }
46
47 ssize_t sys_llistxattr(const char *path, char *list, size_t size)
48 {
49         return llistxattr(path, list, size);
50 }
51
52 #elif HAVE_OSX_XATTRS
53
54 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
55 {
56         return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
57 }
58
59 ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
60 {
61         return fgetxattr(filedes, name, value, size, 0, 0);
62 }
63
64 int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
65 {
66         return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
67 }
68
69 int sys_lremovexattr(const char *path, const char *name)
70 {
71         return removexattr(path, name, XATTR_NOFOLLOW);
72 }
73
74 ssize_t sys_llistxattr(const char *path, char *list, size_t size)
75 {
76         return listxattr(path, list, size, XATTR_NOFOLLOW);
77 }
78
79 #elif HAVE_FREEBSD_XATTRS
80
81 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
82 {
83         return extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
84 }
85
86 ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
87 {
88         return extattr_get_fd(filedes, EXTATTR_NAMESPACE_USER, name, value, size);
89 }
90
91 int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
92 {
93         return extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
94 }
95
96 int sys_lremovexattr(const char *path, const char *name)
97 {
98         return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name);
99 }
100
101 ssize_t sys_llistxattr(const char *path, char *list, size_t size)
102 {
103         unsigned char keylen;
104         ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
105
106         if (len <= 0 || (size_t)len > size)
107                 return len;
108
109         /* FreeBSD puts a single-byte length before each string, with no '\0'
110          * terminator.  We need to change this into a series of null-terminted
111          * strings.  Since the size is the same, we can simply transform the
112          * output in place. */
113         for (off = 0; off < len; off += keylen + 1) {
114                 keylen = ((unsigned char*)list)[off];
115                 if (off + keylen >= len) {
116                         /* Should be impossible, but kernel bugs happen! */
117                         errno = EINVAL;
118                         return -1;
119                 }
120                 memmove(list+off, list+off+1, keylen);
121                 list[off+keylen] = '\0';
122         }
123
124         return len;
125 }
126
127 #else
128
129 #error You need to create xattr compatibility functions.
130
131 #endif
132
133 #endif /* SUPPORT_XATTRS */