r3400: Try to load xattr functions dynamically (somewhat untested since I don't have
[rox-filer.git] / ROX-Filer / src / xtypes.c
blobb1d3612d484baebe9f8d73d469d2581207c5f2f0
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2003, 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"
43 #define XTYPE_ATTR "user.mime_type"
45 #if defined(HAVE_GETXATTR)
46 /* Linux implementation */
48 #include <dlfcn.h>
50 static int (*dyn_setxattr)(const char *path, const char *name,
51 const void *value, size_t size, int flags) = NULL;
52 static ssize_t (*dyn_getxattr)(const char *path, const char *name,
53 void *value, size_t size) = NULL;
55 void xtype_init(void)
57 void *libc;
59 libc = dlopen("libc.so.6", RTLD_LAZY | RTLD_NOLOAD);
60 if (!libc)
61 return; /* Give up on xattr support */
63 (void *) dyn_setxattr = dlsym(libc, "setxattr");
64 (void *) dyn_getxattr = dlsym(libc, "setxattr");
67 MIME_type *xtype_get(const char *path)
69 ssize_t size;
70 gchar *buf;
71 MIME_type *type = NULL;
73 if (!dyn_getxattr)
74 return type_from_path(path); /* Old libc */
76 size = dyn_getxattr(path, XTYPE_ATTR, "", 0);
77 if (size > 0)
79 int new_size;
81 buf = g_new(gchar, size + 1);
82 new_size = dyn_getxattr(path, XTYPE_ATTR, buf, size);
84 if (size == new_size)
86 buf[size] = '\0';
87 type = mime_type_lookup(buf);
89 g_free(buf);
92 if (type)
93 return type;
95 /* Fall back to non-extended */
96 return type_from_path(path);
99 /* 0 on success */
100 int xtype_set(const char *path, const MIME_type *type)
102 int res;
103 gchar *ttext;
105 if (!dyn_setxattr)
107 errno = ENOSYS;
108 return 1; /* Set type failed */
111 ttext = g_strdup_printf("%s/%s", type->media_type, type->subtype);
112 res = dyn_setxattr(path, XTYPE_ATTR, ttext, strlen(ttext), 0);
113 g_free(ttext);
115 return res;
118 #elif defined(HAVE_ATTROPEN)
120 void xtype_init(void)
124 /* Solaris 9 implementation */
126 MIME_type *xtype_get(const char *path)
128 int fd;
129 char buf[1024];
130 int nb;
131 MIME_type *type=NULL;
133 fd=attropen(path, XTYPE_ATTR, O_RDONLY);
135 /*printf("%s: fd=%d ", path, fd);*/
136 if(fd>0) {
137 nb=read(fd, buf, sizeof(buf));
138 /*printf("nb=%d ", nb);*/
139 if(nb>0) {
140 buf[nb]=0;
141 /*printf("buf=%s ", buf);*/
142 type=mime_type_lookup(buf);
144 close(fd);
146 /*printf("%s -> %s\n", path, type? mime_type_comment(type): "Unknown");*/
147 if(type)
148 return type;
150 /* Fall back to non-extended */
151 return type_from_path(path);
154 int xtype_set(const char *path, const MIME_type *type)
156 int fd;
157 gchar *ttext;
158 int nb;
160 fd=attropen(path, XTYPE_ATTR, O_WRONLY|O_CREAT, 0644);
161 if(fd>0) {
162 ttext=g_strdup_printf("%s/%s", type->media_type, type->subtype);
163 nb=write(fd, ttext, strlen(ttext));
164 if(nb==strlen(ttext))
165 ftruncate(fd, (off_t) nb);
166 g_free(ttext);
168 close(fd);
170 if(nb>0)
171 return 0;
174 return 1; /* Set type failed */
177 #else
178 /* No extended attricutes available */
180 void xtype_init(void)
184 MIME_type *xtype_get(const char *path)
186 /* Fall back to non-extended */
187 return type_from_path(path);
190 int xtype_set(const char *path, const MIME_type *type)
192 errno = ENOSYS;
193 return 1; /* Set type failed */
196 #endif