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
);
69 /* Try a different name for uClib support */
70 libc
= dlopen("libc.so", RTLD_LAZY
| RTLD_NOLOAD
);
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
)
88 RETURN_IF_IGNORED(FALSE
);
95 nent
=dyn_getxattr(path
, XTYPE_ATTR
, buf
, sizeof(buf
));
97 if(nent
<0 && errno
==ENOTSUP
)
104 int xattr_have(const char *path
)
109 RETURN_IF_IGNORED(FALSE
);
115 nent
=dyn_listxattr(path
, buf
, sizeof(buf
));
117 if(nent
<0 && errno
==ERANGE
)
123 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
128 RETURN_IF_IGNORED(NULL
);
133 size
= dyn_getxattr(path
, attr
, "", 0);
138 buf
= g_new(gchar
, size
+ 1);
139 new_size
= dyn_getxattr(path
, attr
, buf
, size
);
159 int xattr_set(const char *path
, const char *attr
,
160 const char *value
, int value_len
)
162 if(o_xattr_ignore
.int_value
)
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
197 return pathconf(path
, _PC_XATTR_ENABLED
);
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;
213 #define MAX_ATTR_SIZE BUFSIZ
214 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
220 RETURN_IF_IGNORED(NULL
);
222 #ifdef _PC_XATTR_EXISTS
223 if(!pathconf(path
, _PC_XATTR_EXISTS
))
227 fd
=attropen(path
, attr
, O_RDONLY
);
230 buf
= g_new(gchar
, MAX_ATTR_SIZE
);
231 nb
=read(fd
, buf
, MAX_ATTR_SIZE
);
244 int xattr_set(const char *path
, const char *attr
,
245 const char *value
, int value_len
)
250 if(o_xattr_ignore
.int_value
)
256 if(value
&& value_len
<0)
257 value_len
= strlen(value
);
259 fd
=attropen(path
, attr
, O_WRONLY
|O_CREAT
, 0644);
262 nb
=write(fd
, value
, value_len
);
264 ftruncate(fd
, (off_t
) nb
);
272 return 1; /* Set type failed */
276 /* No extended attributes available */
278 void xattr_init(void)
282 int xattr_supported(const char *path
)
287 int xattr_have(const char *path
)
292 gchar
*xattr_get(const char *path
, const char *attr
, int *len
)
294 /* Fall back to non-extended */
298 int xattr_set(const char *path
, const char *attr
,
299 const char *value
, int value_len
)
302 return 1; /* Set type failed */
307 MIME_type
*xtype_get(const char *path
)
309 MIME_type
*type
= NULL
;
313 buf
= xattr_get(path
, XTYPE_ATTR
, NULL
);
317 nl
= strchr(buf
, '\n');
320 type
= mime_type_lookup(buf
);
326 int xtype_set(const char *path
, const MIME_type
*type
)
331 if(o_xattr_ignore
.int_value
)
337 ttext
= g_strdup_printf("%s/%s", type
->media_type
, type
->subtype
);
338 res
= xattr_set(path
, XTYPE_ATTR
, ttext
, -1);