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)
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
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
24 * xtypes.c - Extended filesystem attribute support for MIME types
33 #include <sys/types.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 */
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
,
66 libc
= dlopen("libc.so.6", RTLD_LAZY
| RTLD_NOLOAD
);
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 xattr_supported(const char *path
)
82 RETURN_IF_IGNORED(FALSE
);
89 nent
=dyn_getxattr(path
, XTYPE_ATTR
, buf
, sizeof(buf
));
91 if(nent
<0 && errno
==ENOTSUP
)
98 int xattr_have(const char *path
)
103 RETURN_IF_IGNORED(FALSE
);
109 nent
=dyn_listxattr(path
, buf
, sizeof(buf
));
111 if(nent
<0 && errno
==ERANGE
)
117 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
122 RETURN_IF_IGNORED(NULL
);
127 size
= dyn_getxattr(path
, attr
, "", 0);
132 buf
= g_new(gchar
, size
+ 1);
133 new_size
= dyn_getxattr(path
, attr
, buf
, size
);
153 int xattr_set(const char *path
, const char *attr
,
154 const char *value
, int value_len
)
156 if(o_xattr_ignore
.int_value
)
165 return 1; /* Set attr failed */
168 if(value
&& value_len
<0)
169 value_len
= strlen(value
);
171 return dyn_setxattr(path
, attr
, value
, value_len
, 0);
175 #elif defined(HAVE_ATTROPEN)
177 /* Solaris 9 implementation */
179 void xattr_init(void)
181 option_add_int(&o_xattr_ignore
, "xattr_ignore", FALSE
);
184 int xattr_supported(const char *path
)
186 RETURN_IF_IGNORED(FALSE
);
187 #ifdef _PC_XATTR_ENABLED
191 return pathconf(path
, _PC_XATTR_ENABLED
);
197 int xattr_have(const char *path
)
199 RETURN_IF_IGNORED(FALSE
);
200 #ifdef _PC_XATTR_EXISTS
201 return pathconf(path
, _PC_XATTR_EXISTS
)>0;
207 #define MAX_ATTR_SIZE BUFSIZ
208 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
214 RETURN_IF_IGNORED(NULL
);
216 #ifdef _PC_XATTR_EXISTS
217 if(!pathconf(path
, _PC_XATTR_EXISTS
))
221 fd
=attropen(path
, attr
, O_RDONLY
);
224 buf
= g_new(gchar
, MAX_ATTR_SIZE
);
225 nb
=read(fd
, buf
, MAX_ATTR_SIZE
);
238 int xattr_set(const char *path
, const char *attr
,
239 const char *value
, int value_len
)
244 if(o_xattr_ignore
.int_value
)
250 if(value
&& value_len
<0)
251 value_len
= strlen(value
);
253 fd
=attropen(path
, attr
, O_WRONLY
|O_CREAT
, 0644);
256 nb
=write(fd
, value
, value_len
);
258 ftruncate(fd
, (off_t
) nb
);
266 return 1; /* Set type failed */
270 /* No extended attributes available */
272 void xattr_init(void)
276 int xattr_supported(const char *path
)
281 int xattr_have(const char *path
)
286 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
288 /* Fall back to non-extended */
292 int xattr_set(const char *path
, const char *attr
,
293 const char *value
, int value_len
)
296 return 1; /* Set type failed */
301 MIME_type
*xtype_get(const char *path
)
303 MIME_type
*type
= NULL
;
307 buf
= xattr_get(path
, XTYPE_ATTR
, NULL
);
311 nl
= strchr(buf
, '\n');
314 type
= mime_type_lookup(buf
);
320 int xtype_set(const char *path
, const MIME_type
*type
)
325 if(o_xattr_ignore
.int_value
)
331 ttext
= g_strdup_printf("%s/%s", type
->media_type
, type
->subtype
);
332 res
= xattr_set(path
, XTYPE_ATTR
, ttext
, -1);