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)
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
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
22 * xtypes.c - Extended filesystem attribute support for MIME types
31 #include <sys/types.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 */
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
,
62 libc
= dlopen("libc.so.6", RTLD_LAZY
| RTLD_NOLOAD
);
65 /* Try a different name for uClib support */
66 libc
= dlopen("libc.so", RTLD_LAZY
| RTLD_NOLOAD
);
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
)
84 RETURN_IF_IGNORED(FALSE
);
91 nent
=dyn_getxattr(path
, XATTR_MIME_TYPE
, buf
, sizeof(buf
));
93 if(nent
<0 && errno
==ENOTSUP
)
100 int xattr_have(const char *path
)
105 RETURN_IF_IGNORED(FALSE
);
111 nent
=dyn_listxattr(path
, buf
, sizeof(buf
));
113 if(nent
<0 && errno
==ERANGE
)
119 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
124 RETURN_IF_IGNORED(NULL
);
129 size
= dyn_getxattr(path
, attr
, "", 0);
134 buf
= g_new(gchar
, size
+ 1);
135 new_size
= dyn_getxattr(path
, attr
, buf
, size
);
155 int xattr_set(const char *path
, const char *attr
,
156 const char *value
, int value_len
)
158 if(o_xattr_ignore
.int_value
)
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
193 return pathconf(path
, _PC_XATTR_ENABLED
);
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;
209 #define MAX_ATTR_SIZE BUFSIZ
210 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
216 RETURN_IF_IGNORED(NULL
);
218 #ifdef _PC_XATTR_EXISTS
219 if(!pathconf(path
, _PC_XATTR_EXISTS
))
223 fd
=attropen(path
, attr
, O_RDONLY
);
226 buf
= g_new(gchar
, MAX_ATTR_SIZE
);
227 nb
=read(fd
, buf
, MAX_ATTR_SIZE
);
240 int xattr_set(const char *path
, const char *attr
,
241 const char *value
, int value_len
)
246 if(o_xattr_ignore
.int_value
)
252 if(value
&& value_len
<0)
253 value_len
= strlen(value
);
255 fd
=attropen(path
, attr
, O_WRONLY
|O_CREAT
, 0644);
258 nb
=write(fd
, value
, value_len
);
260 ftruncate(fd
, (off_t
) nb
);
268 return 1; /* Set type failed */
272 /* No extended attributes available */
274 void xattr_init(void)
278 int xattr_supported(const char *path
)
283 int xattr_have(const char *path
)
288 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
290 /* Fall back to non-extended */
294 int xattr_set(const char *path
, const char *attr
,
295 const char *value
, int value_len
)
298 return 1; /* Set type failed */
303 MIME_type
*xtype_get(const char *path
)
305 MIME_type
*type
= NULL
;
309 buf
= xattr_get(path
, XATTR_MIME_TYPE
, NULL
);
313 nl
= strchr(buf
, '\n');
316 type
= mime_type_lookup(buf
);
322 int xtype_set(const char *path
, const MIME_type
*type
)
327 if(o_xattr_ignore
.int_value
)
333 ttext
= g_strdup_printf("%s/%s", type
->media_type
, type
->subtype
);
334 res
= xattr_set(path
, XATTR_MIME_TYPE
, ttext
, -1);