r3768: Updated years.
[rox-filer.git] / ROX-Filer / src / xtypes.c
blobfe48622b88a97c73372ea635bf8f927e31590059
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 xtype_init(void)
64 void *libc;
66 libc = dlopen("libc.so.6", RTLD_LAZY | RTLD_NOLOAD);
67 if (!libc)
68 return; /* Give up on xattr support */
70 dyn_setxattr = (void *) dlsym(libc, "setxattr");
71 dyn_getxattr = (void *) dlsym(libc, "getxattr");
72 dyn_listxattr = (void *) dlsym(libc, "listxattr");
74 option_add_int(&o_xattr_ignore, "xattr_ignore", FALSE);
77 int xtype_supported(const char *path)
79 char buf[1];
80 ssize_t nent;
82 RETURN_IF_IGNORED(FALSE);
84 if (!dyn_getxattr)
85 return FALSE;
87 if(path) {
88 errno=0;
89 nent=dyn_getxattr(path, XTYPE_ATTR, buf, sizeof(buf));
91 if(nent<0 && errno==ENOTSUP)
92 return FALSE;
95 return TRUE;
98 int xtype_have_attr(const char *path)
100 char buf[1];
101 ssize_t nent;
103 RETURN_IF_IGNORED(FALSE);
105 if (!dyn_listxattr)
106 return FALSE;
108 errno=0;
109 nent=dyn_listxattr(path, buf, sizeof(buf));
111 if(nent<0 && errno==ERANGE)
112 return TRUE;
114 return (nent>0);
117 MIME_type *xtype_get(const char *path)
119 ssize_t size;
120 gchar *buf;
121 MIME_type *type = NULL;
123 RETURN_IF_IGNORED(type_from_path(path));
125 if (!dyn_getxattr)
126 return type_from_path(path); /* Old libc */
128 size = dyn_getxattr(path, XTYPE_ATTR, "", 0);
129 if (size > 0)
131 int new_size;
133 buf = g_new(gchar, size + 1);
134 new_size = dyn_getxattr(path, XTYPE_ATTR, buf, size);
136 if (size == new_size)
138 buf[size] = '\0';
139 type = mime_type_lookup(buf);
141 g_free(buf);
144 if (type)
145 return type;
147 /* Fall back to non-extended */
148 return type_from_path(path);
151 /* 0 on success */
152 int xtype_set(const char *path, const MIME_type *type)
154 int res;
155 gchar *ttext;
157 if(o_xattr_ignore.int_value)
159 errno = ENOSYS;
160 return 1;
163 if (!dyn_setxattr)
165 errno = ENOSYS;
166 return 1; /* Set type failed */
169 ttext = g_strdup_printf("%s/%s", type->media_type, type->subtype);
170 res = dyn_setxattr(path, XTYPE_ATTR, ttext, strlen(ttext), 0);
171 g_free(ttext);
173 return res;
176 #elif defined(HAVE_ATTROPEN)
178 /* Solaris 9 implementation */
180 void xtype_init(void)
182 option_add_int(&o_xattr_ignore, "xattr_ignore", FALSE);
185 int xtype_supported(const char *path)
187 RETURN_IF_IGNORED(FALSE);
188 #ifdef _PC_XATTR_ENABLED
189 if(!path)
190 return TRUE;
192 return pathconf(path, _PC_XATTR_ENABLED);
193 #else
194 return FALSE;
195 #endif
198 int xtype_have_attr(const char *path)
200 RETURN_IF_IGNORED(FALSE);
201 #ifdef _PC_XATTR_EXISTS
202 return pathconf(path, _PC_XATTR_EXISTS)>0;
203 #else
204 return FALSE;
205 #endif
208 MIME_type *xtype_get(const char *path)
210 int fd;
211 char buf[1024];
212 int nb;
213 MIME_type *type=NULL;
215 RETURN_IF_IGNORED(type_from_path(path));
217 #ifdef _PC_XATTR_EXISTS
218 if(!pathconf(path, _PC_XATTR_EXISTS))
219 return type_from_path(path);
220 #endif
222 fd=attropen(path, XTYPE_ATTR, O_RDONLY);
224 if(fd>=0) {
225 nb=read(fd, buf, sizeof(buf));
226 if(nb>0) {
227 buf[nb]=0;
228 type=mime_type_lookup(buf);
230 close(fd);
233 if(type)
234 return type;
236 /* Fall back to non-extended */
237 return type_from_path(path);
240 int xtype_set(const char *path, const MIME_type *type)
242 int fd;
243 gchar *ttext;
244 int nb;
246 if(o_xattr_ignore.int_value)
248 errno = ENOSYS;
249 return 1;
252 fd=attropen(path, XTYPE_ATTR, O_WRONLY|O_CREAT, 0644);
253 if(fd>0) {
254 ttext=g_strdup_printf("%s/%s",
255 type->media_type, type->subtype);
256 nb=write(fd, ttext, strlen(ttext));
257 if(nb==strlen(ttext))
258 ftruncate(fd, (off_t) nb);
259 g_free(ttext);
261 close(fd);
263 if(nb>0)
264 return 0;
267 return 1; /* Set type failed */
270 #else
271 /* No extended attributes available */
273 void xtype_init(void)
277 int xtype_supported(const char *path)
279 return FALSE;
282 int xtype_have_attr(const char *path)
284 return FALSE;
287 MIME_type *xtype_get(const char *path)
289 /* Fall back to non-extended */
290 return type_from_path(path);
293 int xtype_set(const char *path, const MIME_type *type)
295 errno = ENOSYS;
296 return 1; /* Set type failed */
299 #endif