r4379: Add a 'Manage Thumbnails' link to the Options box (Thomas Leonard).
[rox-filer/translations.git] / ROX-Filer / src / xtypes.c
blob7198ef77450a36e448457ef9ec33e22e078debd6
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2005, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
23 /*
24 * xtypes.c - Extended filesystem attribute support for MIME types
27 #include "config.h"
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
37 #include <glib.h>
39 #include "global.h"
40 #include "type.h"
41 #include "xtypes.h"
42 #include "options.h"
44 static Option o_xattr_ignore;
46 #define XTYPE_ATTR "user.mime_type"
48 #define RETURN_IF_IGNORED(val) if(o_xattr_ignore.int_value) return (val)
50 #if defined(HAVE_GETXATTR)
51 /* Linux implementation */
53 #include <dlfcn.h>
55 static int (*dyn_setxattr)(const char *path, const char *name,
56 const void *value, size_t size, int flags) = NULL;
57 static ssize_t (*dyn_getxattr)(const char *path, const char *name,
58 void *value, size_t size) = NULL;
59 static ssize_t (*dyn_listxattr)(const char *path, char *list,
60 size_t size) = NULL;
62 void xattr_init(void)
64 void *libc;
66 libc = dlopen("libc.so.6", RTLD_LAZY | RTLD_NOLOAD);
67 if (!libc)
69 /* Try a different name for uClib support */
70 libc = dlopen("libc.so", RTLD_LAZY | RTLD_NOLOAD);
73 if (!libc)
74 return; /* Give up on xattr support */
76 dyn_setxattr = (void *) dlsym(libc, "setxattr");
77 dyn_getxattr = (void *) dlsym(libc, "getxattr");
78 dyn_listxattr = (void *) dlsym(libc, "listxattr");
80 option_add_int(&o_xattr_ignore, "xattr_ignore", FALSE);
83 int xattr_supported(const char *path)
85 char buf[1];
86 ssize_t nent;
88 RETURN_IF_IGNORED(FALSE);
90 if (!dyn_getxattr)
91 return FALSE;
93 if(path) {
94 errno=0;
95 nent=dyn_getxattr(path, XTYPE_ATTR, buf, sizeof(buf));
97 if(nent<0 && errno==ENOTSUP)
98 return FALSE;
101 return TRUE;
104 int xattr_have(const char *path)
106 char buf[1];
107 ssize_t nent;
109 RETURN_IF_IGNORED(FALSE);
111 if (!dyn_listxattr)
112 return FALSE;
114 errno=0;
115 nent=dyn_listxattr(path, buf, sizeof(buf));
117 if(nent<0 && errno==ERANGE)
118 return TRUE;
120 return (nent>0);
123 gchar *xattr_get(const char *path, const char *attr, int *len)
125 ssize_t size;
126 gchar *buf;
128 RETURN_IF_IGNORED(NULL);
130 if (!dyn_getxattr)
131 return NULL;
133 size = dyn_getxattr(path, attr, "", 0);
134 if (size > 0)
136 int new_size;
138 buf = g_new(gchar, size + 1);
139 new_size = dyn_getxattr(path, attr, buf, size);
141 if(size == new_size)
143 buf[size] = '\0';
145 if(len)
146 *len=(int) size;
148 return buf;
151 g_free(buf);
154 return NULL;
158 /* 0 on success */
159 int xattr_set(const char *path, const char *attr,
160 const char *value, int value_len)
162 if(o_xattr_ignore.int_value)
164 errno = ENOSYS;
165 return 1;
168 if (!dyn_setxattr)
170 errno = ENOSYS;
171 return 1; /* Set attr failed */
174 if(value && value_len<0)
175 value_len = strlen(value);
177 return dyn_setxattr(path, attr, value, value_len, 0);
181 #elif defined(HAVE_ATTROPEN)
183 /* Solaris 9 implementation */
185 void xattr_init(void)
187 option_add_int(&o_xattr_ignore, "xattr_ignore", FALSE);
190 int xattr_supported(const char *path)
192 RETURN_IF_IGNORED(FALSE);
193 #ifdef _PC_XATTR_ENABLED
194 if(!path)
195 return TRUE;
197 return pathconf(path, _PC_XATTR_ENABLED);
198 #else
199 return FALSE;
200 #endif
203 int xattr_have(const char *path)
205 RETURN_IF_IGNORED(FALSE);
206 #ifdef _PC_XATTR_EXISTS
207 return pathconf(path, _PC_XATTR_EXISTS)>0;
208 #else
209 return FALSE;
210 #endif
213 #define MAX_ATTR_SIZE BUFSIZ
214 gchar *xattr_get(const char *path, const char *attr, int *len)
216 int fd;
217 char *buf=NULL;
218 int nb;
220 RETURN_IF_IGNORED(NULL);
222 #ifdef _PC_XATTR_EXISTS
223 if(!pathconf(path, _PC_XATTR_EXISTS))
224 return NULL;
225 #endif
227 fd=attropen(path, attr, O_RDONLY);
229 if(fd>=0) {
230 buf = g_new(gchar, MAX_ATTR_SIZE);
231 nb=read(fd, buf, MAX_ATTR_SIZE);
232 if(nb>0) {
233 buf[nb]=0;
235 close(fd);
237 if(len)
238 *len=nb;
241 return buf;
244 int xattr_set(const char *path, const char *attr,
245 const char *value, int value_len)
247 int fd;
248 int nb;
250 if(o_xattr_ignore.int_value)
252 errno = ENOSYS;
253 return 1;
256 if(value && value_len<0)
257 value_len = strlen(value);
259 fd=attropen(path, attr, O_WRONLY|O_CREAT, 0644);
260 if(fd>0) {
262 nb=write(fd, value, value_len);
263 if(nb==value_len)
264 ftruncate(fd, (off_t) nb);
266 close(fd);
268 if(nb>0)
269 return 0;
272 return 1; /* Set type failed */
275 #else
276 /* No extended attributes available */
278 void xattr_init(void)
282 int xattr_supported(const char *path)
284 return FALSE;
287 int xattr_have(const char *path)
289 return FALSE;
292 gchar *xattr_get(const char *path, const char *attr, int *len)
294 /* Fall back to non-extended */
295 return NULL;
298 int xattr_set(const char *path, const char *attr,
299 const char *value, int value_len)
301 errno = ENOSYS;
302 return 1; /* Set type failed */
305 #endif
307 MIME_type *xtype_get(const char *path)
309 MIME_type *type = NULL;
310 gchar *buf;
311 char *nl;
313 buf = xattr_get(path, XTYPE_ATTR, NULL);
315 if(buf)
317 nl = strchr(buf, '\n');
318 if(nl)
319 *nl = 0;
320 type = mime_type_lookup(buf);
321 g_free(buf);
323 return type;
326 int xtype_set(const char *path, const MIME_type *type)
328 int res;
329 gchar *ttext;
331 if(o_xattr_ignore.int_value)
333 errno = ENOSYS;
334 return 1;
337 ttext = g_strdup_printf("%s/%s", type->media_type, type->subtype);
338 res = xattr_set(path, XTYPE_ATTR, ttext, -1);
339 g_free(ttext);
341 return res;