2 * $Id: cnid.c,v 1.1.4.8 2004-01-14 23:15:19 lenneis Exp $
4 * Copyright (c) 2003 the Netatalk Team
5 * Copyright (c) 2003 Rafal Lewczuk <rlewczuk@pronet.pl>
7 * This program is free software; you can redistribute and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation version 2 of the License or later
10 * version if explicitly stated by any of above copyright holders.
17 #endif /* HAVE_CONFIG_H */
19 #include <sys/types.h>
26 #include <atalk/cnid.h>
27 #include <atalk/list.h>
28 #include <atalk/logger.h>
33 /* List of all registered modules. */
34 static struct list_head modules = ATALK_LIST_HEAD_INIT(modules);
36 static sigset_t sigblockset;
37 static const struct itimerval none = {{0, 0}, {0, 0}};
38 static struct itimerval savetimer;
40 /* Registers new CNID backend module. */
42 /* Once module has been registered, it cannot be unregistered. */
43 void cnid_register(struct _cnid_module *module)
45 struct list_head *ptr;
47 /* Check if our module is already registered. */
48 list_for_each(ptr, &modules)
49 if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, module->name)) {
50 LOG(log_error, logtype_afpd, "Module with name [%s] is already registered !", module->name);
54 LOG(log_info, logtype_afpd, "Registering CNID module [%s]", module->name);
55 ptr = &(module->db_list);
56 list_add_tail(ptr, &modules);
60 static int cnid_dir(const char *dir, mode_t mask)
64 if (stat(dir, &st) < 0) {
67 if (ad_stat( dir, &st) < 0)
70 LOG(log_info, logtype_cnid, "Setting uid/gid to %d/%d", st.st_uid, st.st_gid);
71 if (setegid(st.st_gid) < 0 || seteuid(st.st_uid) < 0) {
72 LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno));
76 if (mkdir(dir, 0777 & ~mask) < 0)
79 LOG(log_info, logtype_cnid, "Setting uid/gid to %d/%d", st.st_uid, st.st_gid);
80 if (setegid(st.st_gid) < 0 || seteuid(st.st_uid) < 0) {
81 LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno));
88 /* Opens CNID database using particular back-end */
89 struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags)
92 cnid_module *mod = NULL;
93 struct list_head *ptr;
97 list_for_each(ptr, &modules) {
98 if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, type)) {
99 mod = list_entry(ptr, cnid_module, db_list);
105 LOG(log_error, logtype_afpd, "Cannot find module named [%s] in registered module list!", type);
109 if ((mod->flags & CNID_FLAG_SETUID)) {
113 LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno));
116 if (cnid_dir(volpath, mask) < 0) {
117 if ( setegid(gid) < 0 || seteuid(uid) < 0) {
118 LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
125 db = mod->cnid_open(volpath, mask);
126 /* FIXME should module know about it ? */
128 db->flags |= CNID_FLAG_NODEV;
131 if ((mod->flags & CNID_FLAG_SETUID)) {
133 if ( setegid(gid) < 0 || seteuid(uid) < 0) {
134 LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
140 LOG(log_error, logtype_afpd, "Cannot open CNID db at [%s].", volpath);
143 db->flags |= mod->flags;
145 if ((db->flags & CNID_FLAG_BLOCK)) {
146 sigemptyset(&sigblockset);
147 sigaddset(&sigblockset, SIGTERM);
148 sigaddset(&sigblockset, SIGHUP);
149 sigaddset(&sigblockset, SIGUSR1);
150 sigaddset(&sigblockset, SIGALRM);
156 /* ------------------- */
157 static void block_signal( u_int32_t flags)
159 if ((flags & CNID_FLAG_BLOCK)) {
160 sigprocmask(SIG_BLOCK, &sigblockset, NULL);
161 setitimer(ITIMER_REAL, &none, &savetimer);
165 /* ------------------- */
166 static void unblock_signal(u_int32_t flags)
168 if ((flags & CNID_FLAG_BLOCK)) {
169 setitimer(ITIMER_REAL, &savetimer, NULL);
170 sigprocmask(SIG_UNBLOCK, &sigblockset, NULL);
174 /* Closes CNID database. Currently it's just a wrapper around db->cnid_close(). */
175 void cnid_close(struct _cnid_db *db)
180 LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument !");
183 /* cnid_close free db */
187 unblock_signal(flags);
190 /* --------------- */
191 cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
192 const char *name, const int len, cnid_t hint)
196 block_signal(cdb->flags);
197 ret = cdb->cnid_add(cdb, st, did, name, len, hint);
198 unblock_signal(cdb->flags);
202 /* --------------- */
203 int cnid_delete(struct _cnid_db *cdb, cnid_t id)
207 block_signal(cdb->flags);
208 ret = cdb->cnid_delete(cdb, id);
209 unblock_signal(cdb->flags);
214 /* --------------- */
215 cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, const char *name,const int len)
219 block_signal(cdb->flags);
220 ret = cdb->cnid_get(cdb, did, name, len);
221 unblock_signal(cdb->flags);
225 /* --------------- */
226 int cnid_getstamp(struct _cnid_db *cdb, void *buffer, const int len)
230 if (!cdb->cnid_getstamp) {
231 memset(buffer, 0, len);
232 /* return the current time. it will invalide cache */
233 if (len < sizeof(time_t))
238 block_signal(cdb->flags);
239 ret = cdb->cnid_getstamp(cdb, buffer, len);
240 unblock_signal(cdb->flags);
244 /* --------------- */
245 cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
246 const char *name, const int len)
250 block_signal(cdb->flags);
251 ret = cdb->cnid_lookup(cdb, st, did, name, len);
252 unblock_signal(cdb->flags);
256 /* --------------- */
257 char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, u_int32_t len)
261 block_signal(cdb->flags);
262 ret = cdb->cnid_resolve(cdb, id, buffer, len);
263 unblock_signal(cdb->flags);
267 /* --------------- */
268 int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
269 const cnid_t did, const char *name, const int len)
273 block_signal(cdb->flags);
274 ret = cdb->cnid_update(cdb, id, st, did, name, len);
275 unblock_signal(cdb->flags);