Converted README to markdown
[rox-filer.git] / ROX-Filer / src / xtypes.c
blob1969efcae00e2b831870ba9b780e1130e65c063f
1 /*
2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
21 /*
22 * xtypes.c - Extended filesystem attribute support for MIME types
25 #include "config.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
35 #include <glib.h>
37 #include "global.h"
38 #include "type.h"
39 #include "xtypes.h"
40 #include "options.h"
42 Option o_xattr_ignore;
44 #define RETURN_IF_IGNORED(val) if(o_xattr_ignore.int_value) return (val)
46 #if defined(HAVE_GETXATTR)
47 /* Linux implementation */
49 #include <dlfcn.h>
51 static int (*dyn_setxattr)(const char *path, const char *name,
52 const void *value, size_t size, int flags) = NULL;
53 static ssize_t (*dyn_getxattr)(const char *path, const char *name,
54 void *value, size_t size) = NULL;
55 static ssize_t (*dyn_listxattr)(const char *path, char *list,
56 size_t size) = NULL;
58 void xattr_init(void)
60 void *libc;
62 libc = dlopen("libc.so.6", RTLD_LAZY | RTLD_NOLOAD);
63 if (!libc)
65 /* Try a different name for uClib support */
66 libc = dlopen("libc.so", RTLD_LAZY | RTLD_NOLOAD);
69 if (!libc)
70 return; /* Give up on xattr support */
72 dyn_setxattr = (void *) dlsym(libc, "setxattr");
73 dyn_getxattr = (void *) dlsym(libc, "getxattr");
74 dyn_listxattr = (void *) dlsym(libc, "listxattr");
76 option_add_int(&o_xattr_ignore, "xattr_ignore", FALSE);
79 int xattr_supported(const char *path)
81 char buf[1];
82 ssize_t nent;
84 RETURN_IF_IGNORED(FALSE);
86 if (!dyn_getxattr)
87 return FALSE;
89 if(path) {
90 errno=0;
91 nent=dyn_getxattr(path, XATTR_MIME_TYPE, buf, sizeof(buf));
93 if(nent<0 && errno==ENOTSUP)
94 return FALSE;
97 return TRUE;
100 int xattr_have(const char *path)
102 char buf[1];
103 ssize_t nent;
105 RETURN_IF_IGNORED(FALSE);
107 if (!dyn_listxattr)
108 return FALSE;
110 errno=0;
111 nent=dyn_listxattr(path, buf, sizeof(buf));
113 if(nent<0 && errno==ERANGE)
114 return TRUE;
116 return (nent>0);
119 gchar *xattr_get(const char *path, const char *attr, int *len)
121 ssize_t size;
122 gchar *buf;
124 RETURN_IF_IGNORED(NULL);
126 if (!dyn_getxattr)
127 return NULL;
129 size = dyn_getxattr(path, attr, "", 0);
130 if (size > 0)
132 int new_size;
134 buf = g_new(gchar, size + 1);
135 new_size = dyn_getxattr(path, attr, buf, size);
137 if(size == new_size)
139 buf[size] = '\0';
141 if(len)
142 *len=(int) size;
144 return buf;
147 g_free(buf);
150 return NULL;
154 /* 0 on success */
155 int xattr_set(const char *path, const char *attr,
156 const char *value, int value_len)
158 if(o_xattr_ignore.int_value)
160 errno = ENOSYS;
161 return 1;
164 if (!dyn_setxattr)
166 errno = ENOSYS;
167 return 1; /* Set attr failed */
170 if(value && value_len<0)
171 value_len = strlen(value);
173 return dyn_setxattr(path, attr, value, value_len, 0);
177 #elif defined(HAVE_ATTROPEN)
179 /* Solaris 9 implementation */
181 void xattr_init(void)
183 option_add_int(&o_xattr_ignore, "xattr_ignore", FALSE);
186 int xattr_supported(const char *path)
188 RETURN_IF_IGNORED(FALSE);
189 #ifdef _PC_XATTR_ENABLED
190 if(!path)
191 return TRUE;
193 return pathconf(path, _PC_XATTR_ENABLED);
194 #else
195 return FALSE;
196 #endif
199 int xattr_have(const char *path)
201 RETURN_IF_IGNORED(FALSE);
202 #ifdef _PC_XATTR_EXISTS
203 return pathconf(path, _PC_XATTR_EXISTS)>0;
204 #else
205 return FALSE;
206 #endif
209 #define MAX_ATTR_SIZE BUFSIZ
210 gchar *xattr_get(const char *path, const char *attr, int *len)
212 int fd;
213 char *buf=NULL;
214 int nb;
216 RETURN_IF_IGNORED(NULL);
218 #ifdef _PC_XATTR_EXISTS
219 if(!pathconf(path, _PC_XATTR_EXISTS))
220 return NULL;
221 #endif
223 fd=attropen(path, attr, O_RDONLY);
225 if(fd>=0) {
226 buf = g_new(gchar, MAX_ATTR_SIZE);
227 nb=read(fd, buf, MAX_ATTR_SIZE);
228 if(nb>0) {
229 buf[nb]=0;
231 close(fd);
233 if(len)
234 *len=nb;
237 return buf;
240 int xattr_set(const char *path, const char *attr,
241 const char *value, int value_len)
243 int fd;
244 int nb;
246 if(o_xattr_ignore.int_value)
248 errno = ENOSYS;
249 return 1;
252 if(value && value_len<0)
253 value_len = strlen(value);
255 fd=attropen(path, attr, O_WRONLY|O_CREAT, 0644);
256 if(fd>0) {
258 nb=write(fd, value, value_len);
259 if(nb==value_len)
260 ftruncate(fd, (off_t) nb);
262 close(fd);
264 if(nb>0)
265 return 0;
268 return 1; /* Set type failed */
271 #else
272 /* No extended attributes available */
274 void xattr_init(void)
278 int xattr_supported(const char *path)
280 return FALSE;
283 int xattr_have(const char *path)
285 return FALSE;
288 gchar *xattr_get(const char *path, const char *attr, int *len)
290 /* Fall back to non-extended */
291 return NULL;
294 int xattr_set(const char *path, const char *attr,
295 const char *value, int value_len)
297 errno = ENOSYS;
298 return 1; /* Set type failed */
301 #endif
303 MIME_type *xtype_get(const char *path)
305 MIME_type *type = NULL;
306 gchar *buf;
307 char *nl;
309 buf = xattr_get(path, XATTR_MIME_TYPE, NULL);
311 if(buf)
313 nl = strchr(buf, '\n');
314 if(nl)
315 *nl = 0;
316 type = mime_type_lookup(buf);
317 g_free(buf);
319 return type;
322 int xtype_set(const char *path, const MIME_type *type)
324 int res;
325 gchar *ttext;
327 if(o_xattr_ignore.int_value)
329 errno = ENOSYS;
330 return 1;
333 ttext = g_strdup_printf("%s/%s", type->media_type, type->subtype);
334 res = xattr_set(path, XATTR_MIME_TYPE, ttext, -1);
335 g_free(ttext);
337 return res;