/*
- * $Id: cnid.c,v 1.2 2005-04-28 20:49:57 bfernhomberg Exp $
- *
* Copyright (c) 2003 the Netatalk Team
* Copyright (c) 2003 Rafal Lewczuk <rlewczuk@pronet.pl>
*
static sigset_t sigblockset;
static const struct itimerval none = {{0, 0}, {0, 0}};
-static struct itimerval savetimer;
/* Registers new CNID backend module. */
}
/* Opens CNID database using particular back-end */
-struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags)
+struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags,
+ const char *cnidsrv, const char *cnidport)
{
struct _cnid_db *db;
cnid_module *mod = NULL;
struct list_head *ptr;
- uid_t uid; /* uninitialized, OK 310105 */
- gid_t gid;
-
+ uid_t uid = -1;
+ gid_t gid = -1;
+
list_for_each(ptr, &modules) {
if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, type)) {
mod = list_entry(ptr, cnid_module, db_list);
return NULL;
}
- if ((mod->flags & CNID_FLAG_SETUID)) {
+ if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) {
uid = geteuid();
gid = getegid();
if (seteuid(0)) {
}
}
- db = mod->cnid_open(volpath, mask);
+ struct cnid_open_args args = {volpath, mask, flags, cnidsrv, cnidport};
+ db = mod->cnid_open(&args);
- if ((mod->flags & CNID_FLAG_SETUID)) {
+ if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) {
seteuid(0);
if ( setegid(gid) < 0 || seteuid(uid) < 0) {
LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
return NULL;
}
/* FIXME should module know about it ? */
- if (flags) {
+ if ((flags & CNID_FLAG_NODEV)) {
db->flags |= CNID_FLAG_NODEV;
}
db->flags |= mod->flags;
sigaddset(&sigblockset, SIGTERM);
sigaddset(&sigblockset, SIGHUP);
sigaddset(&sigblockset, SIGUSR1);
+ sigaddset(&sigblockset, SIGUSR2);
sigaddset(&sigblockset, SIGALRM);
}
static void block_signal( u_int32_t flags)
{
if ((flags & CNID_FLAG_BLOCK)) {
- sigprocmask(SIG_BLOCK, &sigblockset, NULL);
- setitimer(ITIMER_REAL, &none, &savetimer);
+ pthread_sigmask(SIG_BLOCK, &sigblockset, NULL);
}
}
static void unblock_signal(u_int32_t flags)
{
if ((flags & CNID_FLAG_BLOCK)) {
- setitimer(ITIMER_REAL, &savetimer, NULL);
- sigprocmask(SIG_UNBLOCK, &sigblockset, NULL);
+ pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL);
+ }
+}
+
+/* -------------------
+ protect against bogus value from the DB.
+ adddir really doesn't like 2
+*/
+static cnid_t valide(cnid_t id)
+{
+ if (id == CNID_INVALID)
+ return id;
+
+ if (id < CNID_START) {
+ static int err = 0;
+ if (!err) {
+ err = 1;
+ LOG(log_error, logtype_afpd, "Error: Invalid cnid, corrupted DB?");
}
+ return CNID_INVALID;
+ }
+ return id;
}
/* Closes CNID database. Currently it's just a wrapper around db->cnid_close(). */
/* --------------- */
cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
- char *name, const int len, cnid_t hint)
+ const char *name, const size_t len, cnid_t hint)
{
cnid_t ret;
block_signal(cdb->flags);
- ret = cdb->cnid_add(cdb, st, did, name, len, hint);
+ ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint));
unblock_signal(cdb->flags);
return ret;
}
/* --------------- */
-cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const int len)
+cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const size_t len)
{
cnid_t ret;
block_signal(cdb->flags);
- ret = cdb->cnid_get(cdb, did, name, len);
+ ret = valide(cdb->cnid_get(cdb, did, name, len));
unblock_signal(cdb->flags);
return ret;
}
/* --------------- */
-int cnid_getstamp(struct _cnid_db *cdb, void *buffer, const int len)
+int cnid_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
{
cnid_t ret;
time_t t;
/* --------------- */
cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
- char *name, const int len)
+ char *name, const size_t len)
{
-cnid_t ret;
+ cnid_t ret;
block_signal(cdb->flags);
- ret = cdb->cnid_lookup(cdb, st, did, name, len);
+ ret = valide(cdb->cnid_lookup(cdb, st, did, name, len));
unblock_signal(cdb->flags);
return ret;
}
/* --------------- */
-char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, u_int32_t len)
+int cnid_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen)
+{
+ int ret;
+
+ if (cdb->cnid_find == NULL) {
+ LOG(log_error, logtype_cnid, "cnid_find not supported by CNID backend");
+ return -1;
+ }
+
+ block_signal(cdb->flags);
+ ret = cdb->cnid_find(cdb, name, namelen, buffer, buflen);
+ unblock_signal(cdb->flags);
+ return ret;
+}
+
+/* --------------- */
+char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len)
{
char *ret;
block_signal(cdb->flags);
ret = cdb->cnid_resolve(cdb, id, buffer, len);
unblock_signal(cdb->flags);
+ if (ret && !strcmp(ret, "..")) {
+ LOG(log_error, logtype_afpd, "cnid_resolve: name is '..', corrupted db? ");
+ ret = NULL;
+ }
return ret;
}
/* --------------- */
int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
- const cnid_t did, char *name, const int len)
+ const cnid_t did, char *name, const size_t len)
{
int ret;
/* --------------- */
cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
- const char *name, const int len, cnid_t hint)
+ char *name, const size_t len, cnid_t hint)
{
cnid_t ret;