On RHEL 5, 'file' command prints 'AMD x86-64' for 'x86-64' arch.
[libguestfs.git] / daemon / xattr.c
1 /* libguestfs - the guestfsd daemon
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <unistd.h>
23
24 #include "../src/guestfs_protocol.h"
25 #include "daemon.h"
26 #include "actions.h"
27
28 #if defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
29
30 #ifdef HAVE_ATTR_XATTR_H
31 #include <attr/xattr.h>
32 #else
33 #ifdef HAVE_SYS_XATTR_H
34 #include <sys/xattr.h>
35 #endif
36 #endif
37
38 static guestfs_int_xattr_list *getxattrs (char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t (*getxattr) (const char *path, const char *name, void *value, size_t size));
39 static int _setxattr (char *xattr, char *val, int vallen, char *path, int (*setxattr) (const char *path, const char *name, const void *value, size_t size, int flags));
40 static int _removexattr (char *xattr, char *path, int (*removexattr) (const char *path, const char *name));
41
42 guestfs_int_xattr_list *
43 do_getxattrs (char *path)
44 {
45 #if defined(HAVE_LISTXATTR) && defined(HAVE_GETXATTR)
46   return getxattrs (path, listxattr, getxattr);
47 #else
48   reply_with_error ("getxattrs: no support for listxattr and getxattr");
49   return NULL;
50 #endif
51 }
52
53 guestfs_int_xattr_list *
54 do_lgetxattrs (char *path)
55 {
56 #if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR)
57   return getxattrs (path, llistxattr, lgetxattr);
58 #else
59   reply_with_error ("lgetxattrs: no support for llistxattr and lgetxattr");
60   return NULL;
61 #endif
62 }
63
64 int
65 do_setxattr (char *xattr, char *val, int vallen, char *path)
66 {
67 #if defined(HAVE_SETXATTR)
68   return _setxattr (xattr, val, vallen, path, setxattr);
69 #else
70   reply_with_error ("setxattr: no support for setxattr");
71   return -1;
72 #endif
73 }
74
75 int
76 do_lsetxattr (char *xattr, char *val, int vallen, char *path)
77 {
78 #if defined(HAVE_LSETXATTR)
79   return _setxattr (xattr, val, vallen, path, lsetxattr);
80 #else
81   reply_with_error ("lsetxattr: no support for lsetxattr");
82   return -1;
83 #endif
84 }
85
86 int
87 do_removexattr (char *xattr, char *path)
88 {
89 #if defined(HAVE_REMOVEXATTR)
90   return _removexattr (xattr, path, removexattr);
91 #else
92   reply_with_error ("removexattr: no support for removexattr");
93   return -1;
94 #endif
95 }
96
97 int
98 do_lremovexattr (char *xattr, char *path)
99 {
100 #if defined(HAVE_LREMOVEXATTR)
101   return _removexattr (xattr, path, lremovexattr);
102 #else
103   reply_with_error ("lremovexattr: no support for lremovexattr");
104   return -1;
105 #endif
106 }
107
108 static guestfs_int_xattr_list *
109 getxattrs (char *path,
110            ssize_t (*listxattr) (const char *path, char *list, size_t size),
111            ssize_t (*getxattr) (const char *path, const char *name,
112                                 void *value, size_t size))
113 {
114   ssize_t len, vlen;
115   char *buf = NULL;
116   int i, j;
117   guestfs_int_xattr_list *r = NULL;
118
119   NEED_ROOT (NULL);
120   ABS_PATH (path, NULL);
121
122   CHROOT_IN;
123   len = listxattr (path, NULL, 0);
124   CHROOT_OUT;
125   if (len == -1) {
126     reply_with_perror ("listxattr");
127     goto error;
128   }
129
130   buf = malloc (len);
131   if (buf == NULL) {
132     reply_with_perror ("malloc");
133     goto error;
134   }
135
136   CHROOT_IN;
137   len = listxattr (path, buf, len);
138   CHROOT_OUT;
139   if (len == -1) {
140     reply_with_perror ("listxattr");
141     goto error;
142   }
143
144   r = calloc (1, sizeof (*r));
145   if (r == NULL) {
146     reply_with_perror ("malloc");
147     goto error;
148   }
149
150   /* What we get from the kernel is a string "foo\0bar\0baz" of length
151    * len.  First count the strings.
152    */
153   r->guestfs_int_xattr_list_len = 0;
154   for (i = 0; i < len; i += strlen (&buf[i]) + 1)
155     r->guestfs_int_xattr_list_len++;
156
157   r->guestfs_int_xattr_list_val =
158     calloc (r->guestfs_int_xattr_list_len, sizeof (guestfs_int_xattr));
159   if (r->guestfs_int_xattr_list_val == NULL) {
160     reply_with_perror ("calloc");
161     goto error;
162   }
163
164   for (i = 0, j = 0; i < len; i += strlen (&buf[i]) + 1, ++j) {
165     CHROOT_IN;
166     vlen = getxattr (path, &buf[i], NULL, 0);
167     CHROOT_OUT;
168     if (vlen == -1) {
169       reply_with_perror ("getxattr");
170       goto error;
171     }
172
173     r->guestfs_int_xattr_list_val[j].attrname = strdup (&buf[i]);
174     r->guestfs_int_xattr_list_val[j].attrval.attrval_val = malloc (vlen);
175     r->guestfs_int_xattr_list_val[j].attrval.attrval_len = vlen;
176
177     if (r->guestfs_int_xattr_list_val[j].attrname == NULL ||
178         r->guestfs_int_xattr_list_val[j].attrval.attrval_val == NULL) {
179       reply_with_perror ("malloc");
180       goto error;
181     }
182
183     CHROOT_IN;
184     vlen = getxattr (path, &buf[i],
185                      r->guestfs_int_xattr_list_val[j].attrval.attrval_val,
186                      vlen);
187     CHROOT_OUT;
188     if (vlen == -1) {
189       reply_with_perror ("getxattr");
190       goto error;
191     }
192   }
193
194   free (buf);
195
196   return r;
197
198  error:
199   free (buf);
200   if (r) {
201     if (r->guestfs_int_xattr_list_val)
202       for (i = 0; i < r->guestfs_int_xattr_list_len; ++i) {
203         free (r->guestfs_int_xattr_list_val[i].attrname);
204         free (r->guestfs_int_xattr_list_val[i].attrval.attrval_val);
205       }
206     free (r->guestfs_int_xattr_list_val);
207   }
208   free (r);
209   return NULL;
210 }
211
212 static int
213 _setxattr (char *xattr, char *val, int vallen, char *path,
214            int (*setxattr) (const char *path, const char *name,
215                             const void *value, size_t size, int flags))
216 {
217   int r;
218
219   CHROOT_IN;
220   r = setxattr (path, xattr, val, vallen, 0);
221   CHROOT_OUT;
222   if (r == -1) {
223     reply_with_perror ("setxattr");
224     return -1;
225   }
226
227   return 0;
228 }
229
230 static int
231 _removexattr (char *xattr, char *path,
232               int (*removexattr) (const char *path, const char *name))
233 {
234   int r;
235
236   CHROOT_IN;
237   r = removexattr (path, xattr);
238   CHROOT_OUT;
239   if (r == -1) {
240     reply_with_perror ("removexattr");
241     return -1;
242   }
243
244   return 0;
245 }
246
247 #else /* no xattr.h */
248
249 guestfs_int_xattr_list *
250 do_getxattrs (char *path)
251 {
252   reply_with_error ("getxattrs: no support for xattrs");
253   return NULL;
254 }
255
256 guestfs_int_xattr_list *
257 do_lgetxattrs (char *path)
258 {
259   reply_with_error ("lgetxattrs: no support for xattrs");
260   return NULL;
261 }
262
263 int
264 do_setxattr (char *xattr, char *val, int vallen, char *path)
265 {
266   reply_with_error ("setxattr: no support for xattrs");
267   return -1;
268 }
269
270 int
271 do_lsetxattr (char *xattr, char *val, int vallen, char *path)
272 {
273   reply_with_error ("lsetxattr: no support for xattrs");
274   return -1;
275 }
276
277 int
278 do_removexattr (char *xattr, char *path)
279 {
280   reply_with_error ("removexattr: no support for xattrs");
281   return -1;
282 }
283
284 int
285 do_lremovexattr (char *xattr, char *path)
286 {
287   reply_with_error ("lremovexattr: no support for xattrs");
288   return -1;
289 }
290
291 #endif /* no xattr.h */