From 5eb3b5ac51c8221009041928a5a08c101d2be743 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 19 Feb 2014 16:19:42 +0100 Subject: [PATCH] Support for using $u username variable in AFP volume definitions * Prepare CNID backend dbd for user variable expansion * Store a struct vol pointer in the CNID db handles. * Pass three arguments to the CNID daemon: - the afp.conf volume section name - the volume path - an optional username * Rename several struct elements by prefixing them with a struct tag, helps catching bad or missing assignments. * Disable uniconv, doesn't use laod_volumes() and thus wont work with the new CNID dbd backend. From FR#90. Signed-off-by: Ralph Boehme --- NEWS | 2 + bin/Makefile.am | 2 +- bin/ad/ad_util.c | 8 +- doc/manpages/man1/dbd.1.xml | 10 +- doc/manpages/man5/afp.conf.5.xml | 2 +- etc/afpd/file.c | 8 +- etc/afpd/volume.c | 17 +-- etc/cnid_dbd/cmd_dbd.c | 33 ++++-- etc/cnid_dbd/cnid_metad.c | 106 ++++++++++++++---- etc/cnid_dbd/main.c | 29 ++++- include/atalk/cnid.h | 33 ++---- include/atalk/cnid_bdb_private.h | 6 +- include/atalk/cnid_mysql_private.h | 5 +- include/atalk/cnid_private.h | 3 - include/atalk/util.h | 4 + libatalk/cnid/cdb/cnid_cdb_add.c | 6 +- libatalk/cnid/cdb/cnid_cdb_close.c | 3 +- libatalk/cnid/cdb/cnid_cdb_delete.c | 2 +- libatalk/cnid/cdb/cnid_cdb_get.c | 2 +- libatalk/cnid/cdb/cnid_cdb_lookup.c | 6 +- libatalk/cnid/cdb/cnid_cdb_open.c | 44 +++----- libatalk/cnid/cdb/cnid_cdb_rebuild_add.c | 4 +- libatalk/cnid/cdb/cnid_cdb_resolve.c | 2 +- libatalk/cnid/cdb/cnid_cdb_update.c | 8 +- libatalk/cnid/cnid.c | 67 +++++------ libatalk/cnid/dbd/cnid_dbd.c | 135 ++++++++++++----------- libatalk/cnid/last/cnid_last.c | 27 ++--- libatalk/cnid/mysql/cnid_mysql.c | 64 +++++------ libatalk/cnid/tdb/cnid_tdb_add.c | 4 +- libatalk/cnid/tdb/cnid_tdb_close.c | 5 +- libatalk/cnid/tdb/cnid_tdb_delete.c | 2 +- libatalk/cnid/tdb/cnid_tdb_get.c | 2 +- libatalk/cnid/tdb/cnid_tdb_lookup.c | 4 +- libatalk/cnid/tdb/cnid_tdb_open.c | 45 +++----- libatalk/cnid/tdb/cnid_tdb_resolve.c | 2 +- libatalk/cnid/tdb/cnid_tdb_update.c | 8 +- libatalk/util/netatalk_conf.c | 4 +- libatalk/util/unix.c | 4 +- man/man1/dbd.1.in | 7 +- man/man5/afp.conf.5.in | 2 +- 40 files changed, 389 insertions(+), 338 deletions(-) diff --git a/NEWS b/NEWS index afbc751a..7e85ab8f 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ Changes in 3.1.2 * FIX: put the Solaris share reservation after our locking stuff, bug #560. * UPD: Improve Linux quota behaviour * FIX: xattrs on *BSD, bug #562 +* NEW: afpd: support for using $u username variable in AFP volume + definitions. FR#90. Changes in 3.1.1 ================ diff --git a/bin/Makefile.am b/bin/Makefile.am index f5d1448a..9aedd4b6 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am for bin/ -SUBDIRS = afppasswd cnid megatron uniconv misc +SUBDIRS = afppasswd cnid megatron misc if HAVE_ATFUNCS SUBDIRS += ad diff --git a/bin/ad/ad_util.c b/bin/ad/ad_util.c index 782bbffa..27f42b05 100644 --- a/bin/ad/ad_util.c +++ b/bin/ad/ad_util.c @@ -124,13 +124,9 @@ int openvol(AFPObj *obj, const char *path, afpvol_t *vol) if ((vol->vol->v_flags & AFPVOL_NODEV)) flags |= CNID_FLAG_NODEV; - if ((vol->vol->v_cdb = cnid_open(vol->vol->v_path, - 0000, + if ((vol->vol->v_cdb = cnid_open(vol->vol, "dbd", - flags, - vol->vol->v_cnidserver, - vol->vol->v_cnidport, - NULL, NULL)) == NULL) + flags)) == NULL) ERROR("Cant initialize CNID database connection for %s", vol->vol->v_path); cnid_getstamp(vol->vol->v_cdb, diff --git a/doc/manpages/man1/dbd.1.xml b/doc/manpages/man1/dbd.1.xml index 36b7aba0..46753789 100644 --- a/doc/manpages/man1/dbd.1.xml +++ b/doc/manpages/man1/dbd.1.xml @@ -22,7 +22,7 @@ dbd - -fsv + -cfFstuvV volumepath @@ -81,6 +81,14 @@ + + -u + + + username for use with AFP volumes using user variable $u + + + -v diff --git a/doc/manpages/man5/afp.conf.5.xml b/doc/manpages/man5/afp.conf.5.xml index cc46ce99..b6094c4e 100644 --- a/doc/manpages/man5/afp.conf.5.xml +++ b/doc/manpages/man5/afp.conf.5.xml @@ -157,7 +157,7 @@ VARIABLE SUBSTITUTIONS You can use variables in volume names. The use of variables in paths - is not supported for now. + is limited to $u. diff --git a/etc/afpd/file.c b/etc/afpd/file.c index cb8a968a..9c78b1b2 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -252,7 +252,7 @@ restart: } LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", vol->v_path); - vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL, NULL, NULL); + vol->v_cdb = cnid_open(vol, "tdb", flags); if (vol->v_cdb) { if (!(vol->v_flags & AFPVOL_TM)) { vol->v_flags |= AFPVOL_RO; @@ -1662,7 +1662,7 @@ int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si return( AFPERR_PARAM); } - if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { return AFPERR_NOOP; } @@ -1801,7 +1801,7 @@ int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ return( AFPERR_PARAM); } - if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { return AFPERR_NOOP; } @@ -1909,7 +1909,7 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ return( AFPERR_PARAM); } - if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { return AFPERR_NOOP; } diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index a3ee7927..7bdff75d 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -369,7 +369,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, str } /* prior 2.1 only VOLPBIT_ATTR_RO is defined */ if (obj->afp_version > 20) { - if (vol->v_cdb != NULL && (vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) + if (vol->v_cdb != NULL && (vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) ashort |= VOLPBIT_ATTR_FILEID; ashort |= VOLPBIT_ATTR_CATSEARCH; @@ -639,16 +639,7 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) flags |= CNID_FLAG_NODEV; } - LOG(log_debug, logtype_afpd, "CNID server: %s:%s", volume->v_cnidserver, volume->v_cnidport); - - volume->v_cdb = cnid_open(volume->v_path, - volume->v_umask, - volume->v_cnidscheme, - flags, - volume->v_cnidserver, - volume->v_cnidport, - (const void *)obj, - volume->v_uuid); + volume->v_cdb = cnid_open(volume, volume->v_cnidscheme, flags); if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) { /* The first attempt failed and it wasn't yet an attempt to open in-memory */ @@ -657,7 +648,7 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", volume->v_path); flags |= CNID_FLAG_MEMORY; - volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags, NULL, NULL, NULL, NULL); + volume->v_cdb = cnid_open(volume, "tdb", flags); #ifdef SERVERTEXT /* kill ourself with SIGUSR2 aka msg pending */ if (volume->v_cdb) { @@ -855,7 +846,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t * fixing the trash at DID 17. * FIXME (RL): should it be done inside a CNID backend ? (always returning Trash DID when asked) ? */ - if ((volume->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if ((volume->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { /* FIXME find db time stamp */ if (cnid_getstamp(volume->v_cdb, volume->v_stamp, sizeof(volume->v_stamp)) < 0) { diff --git a/etc/cnid_dbd/cmd_dbd.c b/etc/cnid_dbd/cmd_dbd.c index 266b986b..17df52a9 100644 --- a/etc/cnid_dbd/cmd_dbd.c +++ b/etc/cnid_dbd/cmd_dbd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,7 @@ static void usage (void) " -F location of the afp.conf config file\n" " -f delete and recreate CNID database\n" " -t show statistics while running\n" + " -u username for use with AFP volumes using user variable $u\n" " -v verbose\n" " -V show version info\n\n" ); @@ -136,9 +138,9 @@ int main(int argc, char **argv) AFPObj obj = { 0 }; struct vol *vol = NULL; const char *volpath = NULL; - + char *username; int c; - while ((c = getopt(argc, argv, ":cfF:rstvV")) != -1) { + while ((c = getopt(argc, argv, ":cfF:rstu:vV")) != -1) { switch(c) { case 'c': flags |= DBD_FLAGS_V2TOEA; @@ -159,6 +161,9 @@ int main(int argc, char **argv) case 't': flags |= DBD_FLAGS_STATS; break; + case 'u': + username = strdup(optarg); + break; case 'v': flags |= DBD_FLAGS_VERBOSE; break; @@ -203,6 +208,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } + /* Initialize CNID subsystem */ cnid_init(); @@ -212,6 +218,18 @@ int main(int argc, char **argv) else setuplog("default:note", "/dev/tty"); + /* Set username */ + if (username) { + strncpy(obj.username, username, MAXUSERLEN); + struct passwd *pwd; + pwd = getpwnam(obj.username); + if (!pwd) { + dbd_log( LOGSTD, "unknown user"); + exit(EXIT_FAILURE); + } + obj.uid = pwd->pw_uid; + } + if (load_volumes(&obj, lv_all) != 0) { dbd_log( LOGSTD, "Couldn't load volumes"); exit(EXIT_FAILURE); @@ -232,14 +250,9 @@ int main(int argc, char **argv) dbd_log(LOGSTD, "\"%s\" isn't a \"dbd\" CNID volume", vol->v_path); exit(EXIT_FAILURE); } - if ((vol->v_cdb = cnid_open(vol->v_path, - 0000, - vol->v_cnidscheme, - vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0, - vol->v_cnidserver, - vol->v_cnidport, - &obj, - vol->v_uuid)) == NULL) { + vol->v_cdb = cnid_open(vol, vol->v_cnidscheme, + vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0); + if (vol->v_cdb == NULL) { dbd_log(LOGSTD, "Cant initialize CNID database connection for %s", vol->v_path); exit(EXIT_FAILURE); } diff --git a/etc/cnid_dbd/cnid_metad.c b/etc/cnid_dbd/cnid_metad.c index 1b991cb8..b05d72db 100644 --- a/etc/cnid_dbd/cnid_metad.c +++ b/etc/cnid_dbd/cnid_metad.c @@ -155,8 +155,17 @@ static struct server *test_usockfn(const char *path) return NULL; } -/* -------------------- */ -static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath) +/** + * Pass connection request to existing cnid_dbd process or start a new one + * + * @param[in] obj handle + * @param[in] dbdpn Path to cnid_dbd binary + * @param[in] volpath Path of AFP volume + * @param[in] username Optional username, may be NULL + * + * @return 0 on success, -1 on error + **/ + int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath, const char *username) { pid_t pid; struct server *up; @@ -266,9 +275,21 @@ static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath) LOG(log_warning, logtype_cnid, "Multiple attempts to start CNID db daemon for \"%s\" failed, wiping the slate clean...", up->v_path); - ret = execlp(dbdpn, dbdpn, "-F", obj->options.configfile, "-p", volpath, "-t", buf1, "-l", buf2, "-d", NULL); + ret = execlp(dbdpn, dbdpn, + "-F", obj->options.configfile, + "-p", volpath, + "-t", buf1, + "-l", buf2, + "-u", username, + NULL); } else { - ret = execlp(dbdpn, dbdpn, "-F", obj->options.configfile, "-p", volpath, "-t", buf1, "-l", buf2, NULL); + ret = execlp(dbdpn, dbdpn, + "-F", obj->options.configfile, + "-p", volpath, + "-t", buf1, + "-l", buf2, + "-u", username, + NULL); } /* Yikes! We're still here, so exec failed... */ LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno)); @@ -419,11 +440,23 @@ static int setlimits(void) return 0; } +static uid_t uid_from_name(const char *name) +{ + struct passwd *pwd; + + pwd = getpwnam(name); + if (pwd == NULL) + return 0; + return pwd->pw_uid; +} + /* ------------------ */ int main(int argc, char *argv[]) { - char volpath[MAXPATHLEN + 1]; - int len, actual_len; + char *volname = NULL; + char *volpath = NULL; + char *username = NULL; + int len[DBD_NUM_OPEN_ARGS], actual_len; pid_t pid; int status; char *dbdpn = _PATH_CNID_DBD; @@ -463,9 +496,6 @@ int main(int argc, char *argv[]) if (afp_config_parse(&obj, "cnid_metad") != 0) daemon_exit(1); - if (load_volumes(&obj, lv_all) != 0) - daemon_exit(1); - (void)setlimits(); host = atalk_iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700"); @@ -529,7 +559,7 @@ int main(int argc, char *argv[]) if (rqstfd <= 0) continue; - ret = readt(rqstfd, &len, sizeof(int), 1, 4); + ret = readt(rqstfd, &len[0], sizeof(int) * DBD_NUM_OPEN_ARGS, 1, 4); if (!ret) { /* already close */ @@ -539,31 +569,58 @@ int main(int argc, char *argv[]) LOG(log_severe, logtype_cnid, "error read: %s", strerror(errno)); goto loop_end; } - else if (ret != sizeof(int)) { + else if (ret != DBD_NUM_OPEN_ARGS * sizeof(int)) { LOG(log_error, logtype_cnid, "short read: got %d", ret); goto loop_end; } + /* * checks for buffer overruns. The client libatalk side does it too * before handing the dir path over but who trusts clients? */ - if (!len || len +DBHOMELEN +2 > MAXPATHLEN) { - LOG(log_error, logtype_cnid, "wrong len parameter: %d", len); + if (!len[0] || !len[1]) { + LOG(log_error, logtype_cnid, "wrong len parameter: len[0]: %d, len[1]: %d", len[0], len[1]); goto loop_end; } - actual_len = readt(rqstfd, volpath, len, 1, 5); - if (actual_len < 0) { - LOG(log_severe, logtype_cnid, "Read(2) error : %s", strerror(errno)); + volname = malloc(len[0]); + volpath = malloc(len[1]); + if (len[2]) { + username = malloc(len[2]); + } + if (!volname || !volpath || (len[2] && !username)) { + LOG(log_severe, logtype_cnid, "malloc: %s", strerror(errno)); goto loop_end; } - if (actual_len != len) { - LOG(log_error, logtype_cnid, "error/short read (dir): %s", strerror(errno)); + + actual_len = readt(rqstfd, volname, len[0], 1, 5); + if (actual_len != len[0]) { + LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno)); + goto loop_end; + } + + actual_len = readt(rqstfd, volpath, len[1], 1, 5); + if (actual_len != len[1]) { + LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno)); goto loop_end; } - volpath[len] = '\0'; - LOG(log_debug, logtype_cnid, "main: request for volume: %s", volpath); + if (len[2]) { + actual_len = readt(rqstfd, username, len[2], 1, 5); + if (actual_len != len[2]) { + LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno)); + goto loop_end; + } + strlcpy(obj.username, username, MAXUSERLEN); + obj.uid = uid_from_name(username); + if (!obj.uid) + goto loop_end; + } else { + obj.username[0] = 0; + } + + LOG(log_debug, logtype_cnid, "user: %s, volume %s, path %s", + username ? username : "-", volname, volpath); if (load_volumes(&obj, lv_all) != 0) { LOG(log_severe, logtype_cnid, "main: error reloading config"); @@ -577,12 +634,17 @@ int main(int argc, char *argv[]) LOG(log_maxdebug, logtype_cnid, "main: dbpath: %s", vol->v_dbpath); - if (set_dbdir(vol->v_dbpath, volpath) < 0) { + if (set_dbdir(vol->v_dbpath, vol->v_path) < 0) { goto loop_end; } - maybe_start_dbd(&obj, dbdpn, vol->v_path); + maybe_start_dbd(&obj, dbdpn, vol->v_path, username); + loop_end: close(rqstfd); + unload_volumes(&obj); + SAFE_FREE(volname); + SAFE_FREE(volpath); + SAFE_FREE(username); } } diff --git a/etc/cnid_dbd/main.c b/etc/cnid_dbd/main.c index 994c8ff6..ddcf6674 100644 --- a/etc/cnid_dbd/main.c +++ b/etc/cnid_dbd/main.c @@ -474,6 +474,16 @@ static void set_signal(void) } } +static uid_t uid_from_name(const char *name) +{ + struct passwd *pwd; + + pwd = getpwnam(name); + if (pwd == NULL) + return 0; + return pwd->pw_uid; +} + /* ------------------------ */ int main(int argc, char *argv[]) { @@ -482,8 +492,9 @@ int main(int argc, char *argv[]) int ctrlfd = -1, clntfd = -1; AFPObj obj = { 0 }; char *volpath = NULL; + char *username = NULL; - while (( ret = getopt( argc, argv, "dF:l:p:t:vV")) != -1 ) { + while (( ret = getopt( argc, argv, ":dF:l:p:t:u:vV")) != -1 ) { switch (ret) { case 'd': /* this is now just ignored, as we do it automatically anyway */ @@ -501,10 +512,15 @@ int main(int argc, char *argv[]) case 't': ctrlfd = atoi(optarg); break; + case 'u': + username = strdup(optarg); + break; case 'v': case 'V': printf("cnid_dbd (Netatalk %s)\n", VERSION); return -1; + case ':': + break; } } @@ -515,6 +531,17 @@ int main(int argc, char *argv[]) EC_ZERO( afp_config_parse(&obj, "cnid_dbd") ); + if (username) { + strlcpy(obj.username, username, MAXUSERLEN); + obj.uid = uid_from_name(username); + if (!obj.uid) { + EC_FAIL_LOG("unknown user: '%s'", username); + } + } + + LOG(log_debug, logtype_cnid, "user: %s, path %s", + username ? username : "-", volpath); + EC_ZERO( load_volumes(&obj, lv_all) ); EC_NULL( vol = getvolbypath(&obj, volpath) ); EC_ZERO( load_charset(vol) ); diff --git a/include/atalk/cnid.h b/include/atalk/cnid.h index 9c8e0bac..4fefcd04 100644 --- a/include/atalk/cnid.h +++ b/include/atalk/cnid.h @@ -49,10 +49,10 @@ /* * This is instance of CNID database object. */ -struct _cnid_db { - uint32_t flags; /* Flags describing some CNID backend aspects. */ - char *volpath; /* Volume path this particular CNID db refers to. */ - void *_private; /* back-end speficic data */ +typedef struct _cnid_db { + uint32_t cnid_db_flags; /* Flags describing some CNID backend aspects. */ + struct vol *cnid_db_vol; + void *cnid_db_private; /* back-end speficic data */ cnid_t (*cnid_add) (struct _cnid_db *cdb, const struct stat *st, cnid_t did, const char *name, size_t, cnid_t hint); @@ -71,25 +71,15 @@ struct _cnid_db { int (*cnid_find) (struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen); int (*cnid_wipe) (struct _cnid_db *cdb); -}; -typedef struct _cnid_db cnid_db; +} cnid_db; /* * Consolidation of args passedn from main cnid_open to modules cnid_XXX_open, so * that it's easier to add aditional args as required. */ struct cnid_open_args { - const char *dir; - mode_t mask; - uint32_t flags; - - /* for dbd */ - const char *cnidserver; - const char *cnidport; - - /* for MySQL */ - const void *obj; - char *voluuid; + uint32_t cnid_args_flags; + struct vol *cnid_args_vol; }; /* @@ -111,14 +101,7 @@ void cnid_init(); void cnid_register(struct _cnid_module *module); /* This function opens a CNID database for selected volume. */ -struct _cnid_db *cnid_open(const char *volpath, - mode_t mask, - char *type, - int flags, - const char *cnidsrv, - const char *cnidport, - const void *obj, - char *uuid); +struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags); cnid_t cnid_add (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, const char *name, const size_t len, cnid_t hint); int cnid_delete (struct _cnid_db *cdb, cnid_t id); diff --git a/include/atalk/cnid_bdb_private.h b/include/atalk/cnid_bdb_private.h index 8aab3e05..f87eddd0 100644 --- a/include/atalk/cnid_bdb_private.h +++ b/include/atalk/cnid_bdb_private.h @@ -36,6 +36,7 @@ #define CNID_DBD_RES_SRCH_DONE 0x06 #define DBD_MAX_SRCH_RSLTS 100 +#define DBD_NUM_OPEN_ARGS 3 struct cnid_dbd_rqst { int op; @@ -57,10 +58,7 @@ struct cnid_dbd_rply { }; typedef struct CNID_bdb_private { - uint32_t magic; - char db_dir[MAXPATHLEN + 1]; /* Database directory without /.AppleDB appended */ - char *cnidserver; - char *cnidport; + struct vol *vol; int fd; /* File descriptor to cnid_dbd */ char stamp[ADEDLEN_PRIVSYN]; /* db timestamp */ char *client_stamp; diff --git a/include/atalk/cnid_mysql_private.h b/include/atalk/cnid_mysql_private.h index 6affaf7a..79a54e8a 100644 --- a/include/atalk/cnid_mysql_private.h +++ b/include/atalk/cnid_mysql_private.h @@ -7,12 +7,9 @@ #define CNID_MYSQL_FLAG_DEPLETED (1 << 0) /* CNID set overflowed */ typedef struct CNID_mysql_private { + struct vol *vol; uint32_t cnid_mysql_flags; - uint32_t cnid_mysql_magic; - char *cnid_mysql_volname; - const void *cnid_mysql_obj; MYSQL *cnid_mysql_con; - atalk_uuid_t cnid_mysql_voluuid; char *cnid_mysql_voluuid_str; cnid_t cnid_mysql_hint; MYSQL_STMT *cnid_lookup_stmt; diff --git a/include/atalk/cnid_private.h b/include/atalk/cnid_private.h index f5f825fa..c030ff99 100644 --- a/include/atalk/cnid_private.h +++ b/include/atalk/cnid_private.h @@ -5,9 +5,6 @@ #ifndef _ATALK_CNID_PRIVATE_H #define _ATALK_CNID_PRIVATE_H 1 -#define CNID_DB_MAGIC 0x434E4944U /* CNID */ -#define CNID_DATA_MAGIC 0x434E4945U /* CNIE */ - #define CNID_OFS 0 #define CNID_LEN 4 diff --git a/include/atalk/util.h b/include/atalk/util.h index 38e1e7b2..312160be 100644 --- a/include/atalk/util.h +++ b/include/atalk/util.h @@ -73,6 +73,10 @@ #define ntoh64(x) (hton64(x)) #endif +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) +#endif + #ifdef WITH_SENDFILE extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count); #endif diff --git a/libatalk/cnid/cdb/cnid_cdb_add.c b/libatalk/cnid/cdb/cnid_cdb_add.c index a1e69a76..18f42c3c 100644 --- a/libatalk/cnid/cdb/cnid_cdb_add.c +++ b/libatalk/cnid/cdb/cnid_cdb_add.c @@ -173,7 +173,7 @@ cnid_t cnid_cdb_add(struct _cnid_db *cdb, const struct stat *st, cnid_t id; int rc; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { errno = CNID_ERR_PARAM; return CNID_INVALID; } @@ -192,7 +192,7 @@ cnid_t cnid_cdb_add(struct _cnid_db *cdb, const struct stat *st, memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); - if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) { + if ((data.data = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { LOG(log_error, logtype_default, "cnid_add: Path name is too long"); errno = CNID_ERR_PATH; return CNID_INVALID; @@ -248,7 +248,7 @@ int cnid_cdb_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) int rc; CNID_private *db; - if (!cdb || !(db = cdb->_private) || !buffer || !len) { + if (!cdb || !(db = cdb->cnid_db_private) || !buffer || !len) { errno = CNID_ERR_PARAM; return -1; } diff --git a/libatalk/cnid/cdb/cnid_cdb_close.c b/libatalk/cnid/cdb/cnid_cdb_close.c index d34a418b..c5aeceec 100644 --- a/libatalk/cnid/cdb/cnid_cdb_close.c +++ b/libatalk/cnid/cdb/cnid_cdb_close.c @@ -16,7 +16,7 @@ void cnid_cdb_close(struct _cnid_db *cdb) { return; } - if (!(db = cdb->_private)) { + if (!(db = cdb->cnid_db_private)) { return; } db->db_didname->sync(db->db_didname, 0); @@ -30,7 +30,6 @@ void cnid_cdb_close(struct _cnid_db *cdb) { db->dbenv->close(db->dbenv, 0); free(db); - free(cdb->volpath); free(cdb); } diff --git a/libatalk/cnid/cdb/cnid_cdb_delete.c b/libatalk/cnid/cdb/cnid_cdb_delete.c index ace358aa..deaeca44 100644 --- a/libatalk/cnid/cdb/cnid_cdb_delete.c +++ b/libatalk/cnid/cdb/cnid_cdb_delete.c @@ -21,7 +21,7 @@ int cnid_cdb_delete(struct _cnid_db *cdb, const cnid_t id) { DBT key; int rc; - if (!cdb || !(db = cdb->_private) || !id || (db->flags & CNIDFLAG_DB_RO)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || (db->flags & CNIDFLAG_DB_RO)) { return -1; } diff --git a/libatalk/cnid/cdb/cnid_cdb_get.c b/libatalk/cnid/cdb/cnid_cdb_get.c index d4e09055..9c682a8c 100644 --- a/libatalk/cnid/cdb/cnid_cdb_get.c +++ b/libatalk/cnid/cdb/cnid_cdb_get.c @@ -14,7 +14,7 @@ cnid_t cnid_cdb_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l cnid_t id; int rc; - if (!cdb || !(db = cdb->_private) || (len > MAXPATHLEN)) { + if (!cdb || !(db = cdb->cnid_db_private) || (len > MAXPATHLEN)) { return 0; } diff --git a/libatalk/cnid/cdb/cnid_cdb_lookup.c b/libatalk/cnid/cdb/cnid_cdb_lookup.c index 7b2f933c..950709d5 100644 --- a/libatalk/cnid/cdb/cnid_cdb_lookup.c +++ b/libatalk/cnid/cdb/cnid_cdb_lookup.c @@ -26,11 +26,11 @@ cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, cnid_t id_devino, id_didname,id = 0; int rc; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { return 0; } - if ((buf = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) { + if ((buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long"); return 0; } @@ -63,7 +63,7 @@ cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, type_devino = ntohl(type_devino); } - buf = make_cnid_data(cdb->flags, st, did, name, len); + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); key.data = buf +CNID_DID_OFS; key.size = CNID_DID_LEN + len + 1; diff --git a/libatalk/cnid/cdb/cnid_cdb_open.c b/libatalk/cnid/cdb/cnid_cdb_open.c index 757d1b0d..0a8cfa39 100644 --- a/libatalk/cnid/cdb/cnid_cdb_open.c +++ b/libatalk/cnid/cdb/cnid_cdb_open.c @@ -38,6 +38,7 @@ #ifdef CNID_BACKEND_CDB +#include #include #include "cnid_cdb_private.h" @@ -109,7 +110,7 @@ static int my_open(DB * p, const char *f, const char *d, DBTYPE t, u_int32_t fla } /* --------------- */ -static struct _cnid_db *cnid_cdb_new(const char *volpath) +static struct _cnid_db *cnid_cdb_new(struct vol *vol) { struct _cnid_db *cdb; int major, minor, patch; @@ -127,13 +128,8 @@ static struct _cnid_db *cnid_cdb_new(const char *volpath) if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) return NULL; - if ((cdb->volpath = strdup(volpath)) == NULL) { - free(cdb); - return NULL; - } - - cdb->flags = CNID_FLAG_PERSISTENT; - + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT; cdb->cnid_add = cnid_cdb_add; cdb->cnid_delete = cnid_cdb_delete; cdb->cnid_get = cnid_cdb_get; @@ -188,19 +184,16 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) int open_flag, len; static int first = 0; int rc; - - if (!args->dir || *args->dir == 0) { - return NULL; - } + struct vol *vol = args->cnid_args_vol; /* this checks .AppleDB. We need space for dir + '/' + DBHOMELEN + '/' + DBLEN */ - if ((len = strlen(args->dir)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) { - LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", args->dir); + if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) { + LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", vol->v_path); return NULL; } - if ((cdb = cnid_cdb_new(args->dir)) == NULL) { + if ((cdb = cnid_cdb_new(vol)) == NULL) { LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database"); return NULL; } @@ -210,17 +203,16 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) goto fail_cdb; } - cdb->_private = (void *) db; - db->magic = CNID_DB_MAGIC; + cdb->cnid_db_private = (void *) db; - strcpy(path, args->dir); + strcpy(path, vol->v_path); if (path[len - 1] != '/') { strcat(path, "/"); len++; } strcpy(path + len, DBHOME); - if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) { + if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) { LOG(log_error, logtype_default, "cnid_open: DBHOME mkdir failed for %s", path); goto fail_adouble; } @@ -247,7 +239,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) } /* Open the database environment. */ - if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~args->mask)) != 0) { + if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~vol->v_umask)) != 0) { LOG(log_error, logtype_default, "cnid_open: dbenv->open (rw) of %s failed: %s", path, db_strerror(rc)); /* FIXME: This should probably go. Even if it worked, any use for a read-only DB? Didier? */ if (rc == DB_RUNRECOVERY) { @@ -260,10 +252,10 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) /* We can't get a full transactional environment, so multi-access * is out of the question. Let's assume a read-only environment, * and try to at least get a shared memory pool. */ - if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~args->mask)) != 0) { + if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~vol->v_umask)) != 0) { /* Nope, not a MPOOL, either. Last-ditch effort: we'll try to * open the environment with no flags. */ - if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~args->mask)) != 0) { + if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~vol->v_umask)) != 0) { LOG(log_error, logtype_default, "cnid_open: dbenv->open of %s failed: %s", path, db_strerror(rc)); goto fail_lock; } @@ -282,7 +274,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) goto fail_appinit; } - if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~args->mask)) != 0) { + if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~vol->v_umask)) != 0) { LOG(log_error, logtype_default, "cnid_open: Failed to open dev/ino database: %s", db_strerror(rc)); goto fail_appinit; @@ -297,7 +289,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) goto fail_appinit; } - if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~args->mask))) { + if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~vol->v_umask))) { LOG(log_error, logtype_default, "cnid_open: Failed to open did/name database: %s", db_strerror(rc)); goto fail_appinit; @@ -312,7 +304,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) goto fail_appinit; } - if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~args->mask)) != 0) { + if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~vol->v_umask)) != 0) { LOG(log_error, logtype_default, "cnid_open: Failed to open devino database: %s", db_strerror(rc)); goto fail_appinit; @@ -373,8 +365,6 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) free(db); fail_cdb: - if (cdb->volpath != NULL) - free(cdb->volpath); free(cdb); return NULL; diff --git a/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c b/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c index 4620782e..95167465 100644 --- a/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c +++ b/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c @@ -79,7 +79,7 @@ cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st, DBT key, data; int rc; - if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) { errno = CNID_ERR_PARAM; return CNID_INVALID; } @@ -101,7 +101,7 @@ cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st, memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); - if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) { + if ((data.data = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { LOG(log_error, logtype_default, "cnid_add: Path name is too long"); errno = CNID_ERR_PATH; return CNID_INVALID; diff --git a/libatalk/cnid/cdb/cnid_cdb_resolve.c b/libatalk/cnid/cdb/cnid_cdb_resolve.c index 63ed9f8a..d3f6dab9 100644 --- a/libatalk/cnid/cdb/cnid_cdb_resolve.c +++ b/libatalk/cnid/cdb/cnid_cdb_resolve.c @@ -14,7 +14,7 @@ char *cnid_cdb_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le DBT key, data; int rc; - if (!cdb || !(db = cdb->_private) || !id || !(*id)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { return NULL; } diff --git a/libatalk/cnid/cdb/cnid_cdb_update.c b/libatalk/cnid/cdb/cnid_cdb_update.c index f7676c84..90c7d93f 100644 --- a/libatalk/cnid/cdb/cnid_cdb_update.c +++ b/libatalk/cnid/cdb/cnid_cdb_update.c @@ -20,7 +20,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, int notfound = 0; char getbuf[CNID_HEADER_LEN + MAXPATHLEN +1]; - if (!cdb || !(db = cdb->_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) { return -1; } @@ -28,7 +28,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, memset(&pkey, 0, sizeof(pkey)); memset(&data, 0, sizeof(data)); - buf = make_cnid_data(cdb->flags, st, did, name, len); + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); key.data = buf +CNID_DEVINO_OFS; key.size = CNID_DEVINO_LEN; @@ -54,7 +54,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, } memset(&pkey, 0, sizeof(pkey)); - buf = make_cnid_data(cdb->flags, st, did, name, len); + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); key.data = buf + CNID_DID_OFS; key.size = CNID_DID_LEN + len + 1; @@ -83,7 +83,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, memset(&data, 0, sizeof(data)); /* Make a new entry. */ - buf = make_cnid_data(cdb->flags, st, did, name, len); + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); data.data = buf; memcpy(data.data, &id, sizeof(id)); data.size = CNID_HEADER_LEN + len + 1; diff --git a/libatalk/cnid/cnid.c b/libatalk/cnid/cnid.c index 9212cacc..fde4d70f 100644 --- a/libatalk/cnid/cnid.c +++ b/libatalk/cnid/cnid.c @@ -30,6 +30,7 @@ #include #include #include +#include /* List of all registered modules. */ static struct list_head modules = ATALK_LIST_HEAD_INIT(modules); @@ -91,8 +92,7 @@ static int cnid_dir(const char *dir, mode_t mask) } /* Opens CNID database using particular back-end */ -struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags, - const char *cnidsrv, const char *cnidport, const void *obj, char *uuid) +struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags) { struct _cnid_db *db; cnid_module *mod = NULL; @@ -119,7 +119,7 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno)); return NULL; } - if (cnid_dir(volpath, mask) < 0) { + if (cnid_dir(vol->v_path, vol->v_umask) < 0) { if ( setegid(gid) < 0 || seteuid(uid) < 0) { LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); exit(EXITERR_SYS); @@ -128,7 +128,11 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla } } - struct cnid_open_args args = {volpath, mask, flags, cnidsrv, cnidport, obj, uuid}; + struct cnid_open_args args = { + .cnid_args_flags = flags, + .cnid_args_vol = vol + }; + db = mod->cnid_open(&args); if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) { @@ -140,16 +144,15 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla } if (NULL == db) { - LOG(log_error, logtype_afpd, "Cannot open CNID db at [%s].", volpath); + LOG(log_error, logtype_afpd, "Cannot open CNID db at [%s].", vol->v_path); return NULL; } - /* FIXME should module know about it ? */ - if ((flags & CNID_FLAG_NODEV)) { - db->flags |= CNID_FLAG_NODEV; - } - db->flags |= mod->flags; - if ((db->flags & CNID_FLAG_BLOCK)) { + db->cnid_db_flags |= mod->flags; + if (flags & CNID_FLAG_NODEV) + db->cnid_db_flags |= CNID_FLAG_NODEV; + + if (db->cnid_db_flags & CNID_FLAG_BLOCK) { sigemptyset(&sigblockset); sigaddset(&sigblockset, SIGTERM); sigaddset(&sigblockset, SIGHUP); @@ -207,7 +210,7 @@ void cnid_close(struct _cnid_db *db) return; } /* cnid_close free db */ - flags = db->flags; + flags = db->cnid_db_flags; block_signal(flags); db->cnid_close(db); unblock_signal(flags); @@ -222,9 +225,9 @@ cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, if (len == 0) return CNID_INVALID; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint)); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -233,9 +236,9 @@ int cnid_delete(struct _cnid_db *cdb, cnid_t id) { int ret; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = cdb->cnid_delete(cdb, id); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -245,9 +248,9 @@ cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const size_t { cnid_t ret; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = valide(cdb->cnid_get(cdb, did, name, len)); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -266,9 +269,9 @@ time_t t; memcpy(buffer, &t, sizeof(time_t)); return 0; } - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = cdb->cnid_getstamp(cdb, buffer, len); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -278,9 +281,9 @@ cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did { cnid_t ret; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = valide(cdb->cnid_lookup(cdb, st, did, name, len)); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -294,9 +297,9 @@ int cnid_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buff return -1; } - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = cdb->cnid_find(cdb, name, namelen, buffer, buflen); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -305,9 +308,9 @@ char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) { char *ret; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = cdb->cnid_resolve(cdb, id, buffer, len); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); if (ret && !strcmp(ret, "..")) { LOG(log_error, logtype_afpd, "cnid_resolve: name is '..', corrupted db? "); ret = NULL; @@ -321,9 +324,9 @@ int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, { int ret; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = cdb->cnid_update(cdb, id, st, did, name, len); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -333,9 +336,9 @@ cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_ { cnid_t ret; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); ret = cdb->cnid_rebuild_add(cdb, st, did, name, len, hint); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } @@ -344,9 +347,9 @@ int cnid_wipe(struct _cnid_db *cdb) { int ret = 0; - block_signal(cdb->flags); + block_signal(cdb->cnid_db_flags); if (cdb->cnid_wipe) ret = cdb->cnid_wipe(cdb); - unblock_signal(cdb->flags); + unblock_signal(cdb->cnid_db_flags); return ret; } diff --git a/libatalk/cnid/dbd/cnid_dbd.c b/libatalk/cnid/dbd/cnid_dbd.c index 1b365065..d4606400 100644 --- a/libatalk/cnid/dbd/cnid_dbd.c +++ b/libatalk/cnid/dbd/cnid_dbd.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "cnid_dbd.h" @@ -227,24 +228,46 @@ static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs) static int init_tsock(CNID_bdb_private *db) { int fd; - int len; - struct iovec iov[2]; + int len[DBD_NUM_OPEN_ARGS]; + int iovecs; + struct iovec iov[DBD_NUM_OPEN_ARGS + 1] = {{0}}; + struct vol *vol = db->vol; + ssize_t iovlen; - LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", - db->db_dir, db->cnidserver, db->cnidport); + LOG(log_debug, logtype_cnid, "connecting to CNID server: %s:%s", + vol->v_cnidserver, vol->v_cnidport); - if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0) + if ((fd = tsock_getfd(vol->v_cnidserver, vol->v_cnidport)) < 0) return -1; - len = strlen(db->db_dir); + LOG(log_debug, logtype_cnid, "connecting volume '%s', path: %s, user: %s", + vol->v_configname, vol->v_path, vol->v_obj->username[0] ? vol->v_obj->username : "-"); + + iovecs = 1 + DBD_NUM_OPEN_ARGS - 1; + + len[0] = strlen(vol->v_configname) + 1; + len[1] = strlen(vol->v_path) + 1; + len[2] = strlen(vol->v_obj->username); - iov[0].iov_base = &len; - iov[0].iov_len = sizeof(int); + iov[0].iov_base = &len[0]; + iov[0].iov_len = DBD_NUM_OPEN_ARGS * sizeof(int); - iov[1].iov_base = db->db_dir; - iov[1].iov_len = len; + iov[1].iov_base = vol->v_configname; + iov[1].iov_len = len[0]; - if (write_vec(fd, iov, len + sizeof(int), 2) != len + sizeof(int)) { + iov[2].iov_base = vol->v_path; + iov[2].iov_len = len[1]; + + if (len[2] > 0) { + len[2] += 1; + iovecs++; + iov[3].iov_base = vol->v_obj->username; + iov[3].iov_len = len[2]; + } + + iovlen = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len; + + if (write_vec(fd, iov, iovlen, iovecs) != iovlen) { LOG(log_error, logtype_cnid, "init_tsock: Error/short write: %s", strerror(errno)); close(fd); return -1; @@ -275,8 +298,8 @@ static int send_packet(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst) } if (write_vec(db->fd, iov, towrite, vecs) != towrite) { - LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (db_dir %s): %s", - db->db_dir, strerror(errno)); + LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (volume %s): %s", + db->vol->v_localname, strerror(errno)); return -1; } @@ -327,21 +350,21 @@ static int dbd_rpc(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY); if (ret != sizeof(struct cnid_dbd_rply)) { - LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s", - db->db_dir, ret == -1 ? strerror(errno) : "closed"); + LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (volume %s): %s", + db->vol->v_localname, ret == -1 ? strerror(errno) : "closed"); rply->name = nametmp; return -1; } rply->name = nametmp; if (rply->namelen && rply->namelen > len) { LOG(log_error, logtype_cnid, - "dbd_rpc: Error reading name (db_dir %s): %s name too long: %d. only wanted %d, garbage?", - db->db_dir, rply->name, rply->namelen, len); + "dbd_rpc: Error reading name (volume %s): %s name too long: %d. only wanted %d, garbage?", + db->vol->v_localname, rply->name, rply->namelen, len); return -1; } if (rply->namelen && (ret = readt(db->fd, rply->name, rply->namelen, 0, ONE_DELAY)) != (ssize_t)rply->namelen) { - LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s", - db->db_dir, ret == -1?strerror(errno):"closed"); + LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (volume %s): %s", + db->vol->v_localname, ret == -1?strerror(errno):"closed"); return -1; } @@ -367,7 +390,7 @@ static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cni } else { /* db->notfirst == 0 */ db->notfirst = 1; } - LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->db_dir); + LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->vol->v_localname); } if (!dbd_rpc(db, rqst, rply)) { LOG(log_maxdebug, logtype_cnid, "transmit: {done}"); @@ -381,14 +404,14 @@ static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cni if (errno == ECONNREFUSED) { /* errno carefully injected in tsock_getfd */ /* give up */ - LOG(log_error, logtype_cnid, "transmit: connection refused (db_dir %s)", db->db_dir); + LOG(log_error, logtype_cnid, "transmit: connection refused (volume %s)", db->vol->v_localname); return -1; } if (!clean) { /* don't sleep if just got disconnected by cnid server */ time(&t); if (t - orig > MAX_DELAY) { - LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (db_dir %s) timed out.", db->db_dir); + LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (volume %s) timed out.", db->vol->v_localname); return -1; } /* sleep a little before retry */ @@ -402,20 +425,15 @@ static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cni } /* ---------------------- */ -static struct _cnid_db *cnid_dbd_new(const char *volpath) +static struct _cnid_db *cnid_dbd_new(struct vol *vol) { struct _cnid_db *cdb; if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL) return NULL; - if ((cdb->volpath = strdup(volpath)) == NULL) { - free(cdb); - return NULL; - } - - cdb->flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; - + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; cdb->cnid_add = cnid_dbd_add; cdb->cnid_delete = cnid_dbd_delete; cdb->cnid_get = cnid_dbd_get; @@ -437,11 +455,7 @@ struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args) CNID_bdb_private *db = NULL; struct _cnid_db *cdb = NULL; - if (!args->dir) { - return NULL; - } - - if ((cdb = cnid_dbd_new(args->dir)) == NULL) { + if ((cdb = cnid_dbd_new(args->cnid_args_vol)) == NULL) { LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database"); return NULL; } @@ -451,27 +465,19 @@ struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args) goto cnid_dbd_open_fail; } - cdb->_private = db; + cdb->cnid_db_private = db; - /* We keep a copy of the directory in the db structure so that we can - transparently reconnect later. */ - strcpy(db->db_dir, args->dir); - db->magic = CNID_DB_MAGIC; db->fd = -1; - db->cnidserver = strdup(args->cnidserver); - db->cnidport = strdup(args->cnidport); + db->vol = args->cnid_args_vol; - LOG(log_debug, logtype_cnid, "cnid_dbd_open: Finished initializing cnid dbd module for volume '%s'", db->db_dir); + LOG(log_debug, logtype_cnid, "Finished initializing CNID dbd module for volume '%s'", + args->cnid_args_vol->v_localname); return cdb; cnid_dbd_open_fail: - if (cdb != NULL) { - if (cdb->volpath != NULL) { - free(cdb->volpath); - } + if (cdb != NULL) free(cdb); - } if (db != NULL) free(db); @@ -488,15 +494,14 @@ void cnid_dbd_close(struct _cnid_db *cdb) return; } - if ((db = cdb->_private) != NULL) { - LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->db_dir); + if ((db = cdb->cnid_db_private) != NULL) { + LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->vol->v_localname); if (db->fd >= 0) close(db->fd); free(db); } - free(cdb->volpath); free(cdb); return; @@ -537,7 +542,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { LOG(log_error, logtype_cnid, "cnid_add: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -552,7 +557,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_ADD; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } @@ -601,7 +606,7 @@ cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !name) { LOG(log_error, logtype_cnid, "cnid_dbd_get: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -654,7 +659,7 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le struct cnid_dbd_rply rply; char *name; - if (!cdb || !(db = cdb->_private) || !id || !(*id)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { LOG(log_error, logtype_cnid, "cnid_resolve: Parameter error"); errno = CNID_ERR_PARAM; return NULL; @@ -710,7 +715,7 @@ int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) { CNID_bdb_private *db; - if (!cdb || !(db = cdb->_private) || len != ADEDLEN_PRIVSYN) { + if (!cdb || !(db = cdb->cnid_db_private) || len != ADEDLEN_PRIVSYN) { LOG(log_error, logtype_cnid, "cnid_getstamp: Parameter error"); errno = CNID_ERR_PARAM; return -1; @@ -730,7 +735,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { LOG(log_error, logtype_cnid, "cnid_lookup: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -745,7 +750,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_LOOKUP; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } @@ -791,7 +796,7 @@ int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void * struct cnid_dbd_rply rply; int count; - if (!cdb || !(db = cdb->_private) || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !name) { LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -846,7 +851,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; - if (!cdb || !(db = cdb->_private) || !id || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name) { LOG(log_error, logtype_cnid, "cnid_update: Parameter error"); errno = CNID_ERR_PARAM; return -1; @@ -861,7 +866,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_UPDATE; rqst.cnid = id; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } rqst.ino = st->st_ino; @@ -901,7 +906,7 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID) { LOG(log_error, logtype_cnid, "cnid_rebuild_add: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -916,7 +921,7 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_REBUILD_ADD; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } @@ -962,7 +967,7 @@ int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id) struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; - if (!cdb || !(db = cdb->_private) || !id) { + if (!cdb || !(db = cdb->cnid_db_private) || !id) { LOG(log_error, logtype_cnid, "cnid_delete: Parameter error"); errno = CNID_ERR_PARAM; return -1; @@ -999,7 +1004,7 @@ int cnid_dbd_wipe(struct _cnid_db *cdb) struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; - if (!cdb || !(db = cdb->_private)) { + if (!cdb || !(db = cdb->cnid_db_private)) { LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error"); errno = CNID_ERR_PARAM; return -1; diff --git a/libatalk/cnid/last/cnid_last.c b/libatalk/cnid/last/cnid_last.c index cc2ae1c7..2314217c 100644 --- a/libatalk/cnid/last/cnid_last.c +++ b/libatalk/cnid/last/cnid_last.c @@ -58,10 +58,10 @@ cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st, struct _cnid_last_private *priv; - if (!cdb || !(cdb->_private)) + if (!cdb || !(cdb->cnid_db_private)) return CNID_INVALID; - priv = (struct _cnid_last_private *) (cdb->_private); + priv = (struct _cnid_last_private *) (cdb->cnid_db_private); if (S_ISDIR(st->st_mode)) return htonl(priv->last_did++); @@ -73,8 +73,7 @@ cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st, void cnid_last_close(struct _cnid_db *cdb) { - free(cdb->volpath); - free(cdb->_private); + free(cdb->cnid_db_private); free(cdb); } @@ -105,7 +104,7 @@ cnid_t cnid_last_lookup(struct _cnid_db *cdb _U_, const struct stat *st _U_, cni } -static struct _cnid_db *cnid_last_new(const char *volpath) +static struct _cnid_db *cnid_last_new(struct vol *vol) { struct _cnid_db *cdb; struct _cnid_last_private *priv; @@ -113,23 +112,17 @@ static struct _cnid_db *cnid_last_new(const char *volpath) if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) return NULL; - if ((cdb->volpath = strdup(volpath)) == NULL) { - free(cdb); - return NULL; - } - - if ((cdb->_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) { - free(cdb->volpath); + if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) { free(cdb); return NULL; } /* Set up private state */ - priv = (struct _cnid_last_private *) (cdb->_private); + priv = (struct _cnid_last_private *) (cdb->cnid_db_private); priv->last_did = 17; /* Set up standard fields */ - cdb->flags = 0; + cdb->cnid_db_flags = 0; cdb->cnid_add = cnid_last_add; cdb->cnid_delete = cnid_last_delete; cdb->cnid_get = cnid_last_get; @@ -147,11 +140,7 @@ struct _cnid_db *cnid_last_open(struct cnid_open_args *args) { struct _cnid_db *cdb; - if (!args->dir) { - return NULL; - } - - if ((cdb = cnid_last_new(args->dir)) == NULL) { + if ((cdb = cnid_last_new(args->cnid_args_vol)) == NULL) { LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database"); return NULL; } diff --git a/libatalk/cnid/mysql/cnid_mysql.c b/libatalk/cnid/mysql/cnid_mysql.c index c661f9ac..aa04bf81 100644 --- a/libatalk/cnid/mysql/cnid_mysql.c +++ b/libatalk/cnid/mysql/cnid_mysql.c @@ -7,6 +7,8 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#undef _FORTIFY_SOURCE + #include #include #include @@ -36,6 +38,8 @@ #include #include #include +#include + static MYSQL_BIND lookup_param[4], lookup_result[5]; static MYSQL_BIND add_param[4], put_param[5]; @@ -240,7 +244,7 @@ int cnid_mysql_delete(struct _cnid_db *cdb, const cnid_t id) EC_INIT; CNID_mysql_private *db; - if (!cdb || !(db = cdb->_private) || !id) { + if (!cdb || !(db = cdb->cnid_db_private) || !id) { LOG(log_error, logtype_cnid, "cnid_mysql_delete: Parameter error"); errno = CNID_ERR_PARAM; EC_FAIL; @@ -268,8 +272,9 @@ void cnid_mysql_close(struct _cnid_db *cdb) return; } - if ((db = cdb->_private) != NULL) { - LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->cnid_mysql_volname); + if ((db = cdb->cnid_db_private) != NULL) { + LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", + cdb->cnid_db_vol->v_localname); free(db->cnid_mysql_voluuid_str); @@ -280,7 +285,6 @@ void cnid_mysql_close(struct _cnid_db *cdb) free(db); } - free(cdb->volpath); free(cdb); return; @@ -297,7 +301,7 @@ int cnid_mysql_update(struct _cnid_db *cdb, CNID_mysql_private *db; cnid_t update_id; - if (!cdb || !(db = cdb->_private) || !id || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name) { LOG(log_error, logtype_cnid, "cnid_update: Parameter error"); errno = CNID_ERR_PARAM; EC_FAIL; @@ -366,7 +370,7 @@ cnid_t cnid_mysql_lookup(struct _cnid_db *cdb, cnid_t id = CNID_INVALID; bool have_result = false; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { LOG(log_error, logtype_cnid, "cnid_mysql_lookup: Parameter error"); errno = CNID_ERR_PARAM; EC_FAIL; @@ -505,7 +509,7 @@ cnid_t cnid_mysql_add(struct _cnid_db *cdb, MYSQL_STMT *stmt; my_ulonglong lastid; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { LOG(log_error, logtype_cnid, "cnid_mysql_add: Parameter error"); errno = CNID_ERR_PARAM; EC_FAIL; @@ -609,7 +613,7 @@ cnid_t cnid_mysql_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t MYSQL_RES *result = NULL; MYSQL_ROW row; - if (!cdb || !(db = cdb->_private) || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !name) { LOG(log_error, logtype_cnid, "cnid_mysql_get: Parameter error"); errno = CNID_ERR_PARAM; EC_FAIL; @@ -658,7 +662,7 @@ char *cnid_mysql_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t MYSQL_RES *result = NULL; MYSQL_ROW row; - if (!cdb || !(db = cdb->_private)) { + if (!cdb || !(db = cdb->cnid_db_private)) { LOG(log_error, logtype_cnid, "cnid_mysql_get: Parameter error"); errno = CNID_ERR_PARAM; EC_FAIL; @@ -700,7 +704,7 @@ int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) MYSQL_RES *result = NULL; MYSQL_ROW row; - if (!cdb || !(db = cdb->_private)) { + if (!cdb || !(db = cdb->cnid_db_private)) { LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -711,7 +715,7 @@ int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) if (cnid_mysql_execute(db->cnid_mysql_con, "SELECT Stamp FROM volumes WHERE VolPath='%s'", - db->cnid_mysql_volname)) { + cdb->cnid_db_vol->v_path)) { if (mysql_errno(db->cnid_mysql_con) != ER_DUP_ENTRY) { LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); EC_FAIL; @@ -724,7 +728,7 @@ int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) EC_FAIL; } if (!mysql_num_rows(result)) { - LOG(log_error, logtype_cnid, "Can't get DB stamp for volumes \"%s\"", db->cnid_mysql_volname); + LOG(log_error, logtype_cnid, "Can't get DB stamp for volumes \"%s\"", cdb->cnid_db_vol->v_path); EC_FAIL; } row = mysql_fetch_row(result); @@ -758,7 +762,7 @@ int cnid_mysql_wipe(struct _cnid_db *cdb) CNID_mysql_private *db; MYSQL_RES *result = NULL; - if (!cdb || !(db = cdb->_private)) { + if (!cdb || !(db = cdb->cnid_db_private)) { LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error"); errno = CNID_ERR_PARAM; return -1; @@ -787,19 +791,15 @@ EC_CLEANUP: EC_EXIT; } -static struct _cnid_db *cnid_mysql_new(const char *volpath) +static struct _cnid_db *cnid_mysql_new(struct vol *vol) { struct _cnid_db *cdb; if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL) return NULL; - if ((cdb->volpath = strdup(volpath)) == NULL) { - free(cdb); - return NULL; - } - - cdb->flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; cdb->cnid_add = cnid_mysql_add; cdb->cnid_delete = cnid_mysql_delete; cdb->cnid_get = cnid_mysql_get; @@ -817,7 +817,6 @@ static struct _cnid_db *cnid_mysql_new(const char *volpath) static const char *printuuid(const unsigned char *uuid) { static char uuidstring[64]; - const char *uuidmask; int i = 0; unsigned char c; @@ -838,16 +837,13 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args) struct _cnid_db *cdb = NULL; MYSQL_RES *result = NULL; MYSQL_ROW row; + struct vol *vol = args->cnid_args_vol; - EC_NULL( cdb = cnid_mysql_new(args->dir) ); + EC_NULL( cdb = cnid_mysql_new(vol) ); EC_NULL( db = (CNID_mysql_private *)calloc(1, sizeof(CNID_mysql_private)) ); - cdb->_private = db; + cdb->cnid_db_private = db; - db->cnid_mysql_volname = strdup(args->dir); /* db_dir contains the volume name */ - db->cnid_mysql_magic = CNID_DB_MAGIC; - db->cnid_mysql_obj = args->obj; - memcpy(db->cnid_mysql_voluuid, args->voluuid, sizeof(atalk_uuid_t)); - db->cnid_mysql_voluuid_str = strdup(printuuid(db->cnid_mysql_voluuid)); + db->cnid_mysql_voluuid_str = strdup(printuuid(vol->v_uuid)); /* Initialize and connect to MySQL server */ EC_NULL( db->cnid_mysql_con = mysql_init(NULL) ); @@ -856,7 +852,7 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args) int my_timeout = 600; EC_ZERO( mysql_options(db->cnid_mysql_con, MYSQL_OPT_CONNECT_TIMEOUT, &my_timeout) ); - const AFPObj *obj = db->cnid_mysql_obj; + const AFPObj *obj = vol->v_obj; EC_NULL( mysql_real_connect(db->cnid_mysql_con, obj->options.cnid_mysql_host, @@ -883,7 +879,7 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args) "INSERT INTO volumes (VolUUID,Volpath,Stamp,Depleted) " "VALUES('%s','%s','%s',0)", db->cnid_mysql_voluuid_str, - db->cnid_mysql_volname, + vol->v_path, blob)) { if (mysql_errno(db->cnid_mysql_con) != ER_DUP_ENTRY) { LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); @@ -934,18 +930,14 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args) EC_ZERO( init_prepared_stmt(db) ); LOG(log_debug, logtype_cnid, "Finished initializing MySQL CNID module for volume '%s'", - db->cnid_mysql_volname); + vol->v_path); EC_CLEANUP: if (result) mysql_free_result(result); if (ret != 0) { - if (cdb) { - if (cdb->volpath != NULL) { - free(cdb->volpath); - } + if (cdb) free(cdb); - } cdb = NULL; if (db) free(db); diff --git a/libatalk/cnid/tdb/cnid_tdb_add.c b/libatalk/cnid/tdb/cnid_tdb_add.c index 3203eda9..b3babcd3 100644 --- a/libatalk/cnid/tdb/cnid_tdb_add.c +++ b/libatalk/cnid/tdb/cnid_tdb_add.c @@ -160,7 +160,7 @@ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st, TDB_DATA key, data; int rc; - if (!cdb || !(priv = cdb->_private) || !st || !name) { + if (!cdb || !(priv = cdb->cnid_db_private) || !st || !name) { errno = CNID_ERR_PARAM; return CNID_INVALID; } @@ -183,7 +183,7 @@ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st, key.dptr = (unsigned char *)&hint; key.dsize = sizeof(cnid_t); - if ((data.dptr = make_tdb_data(cdb->flags, lstp, did, name, len)) == NULL) { + if ((data.dptr = make_tdb_data(cdb->cnid_db_flags, lstp, did, name, len)) == NULL) { LOG(log_error, logtype_default, "tdb_add: Path name is too long"); errno = CNID_ERR_PATH; return CNID_INVALID; diff --git a/libatalk/cnid/tdb/cnid_tdb_close.c b/libatalk/cnid/tdb/cnid_tdb_close.c index c5001816..4879e10b 100644 --- a/libatalk/cnid/tdb/cnid_tdb_close.c +++ b/libatalk/cnid/tdb/cnid_tdb_close.c @@ -13,10 +13,9 @@ void cnid_tdb_close(struct _cnid_db *cdb) { struct _cnid_tdb_private *db; - free(cdb->volpath); - db = (struct _cnid_tdb_private *)cdb->_private; + db = (struct _cnid_tdb_private *)cdb->cnid_db_private; tdb_close(db->tdb_cnid); - free(cdb->_private); + free(cdb->cnid_db_private); free(cdb); } diff --git a/libatalk/cnid/tdb/cnid_tdb_delete.c b/libatalk/cnid/tdb/cnid_tdb_delete.c index a16a9951..95441098 100644 --- a/libatalk/cnid/tdb/cnid_tdb_delete.c +++ b/libatalk/cnid/tdb/cnid_tdb_delete.c @@ -19,7 +19,7 @@ int cnid_tdb_delete(struct _cnid_db *cdb, const cnid_t id) struct _cnid_tdb_private *db; TDB_DATA key, data; - if (!cdb || !(db = cdb->_private) || !id) { + if (!cdb || !(db = cdb->cnid_db_private) || !id) { return -1; } memset(&key, 0, sizeof(key)); diff --git a/libatalk/cnid/tdb/cnid_tdb_get.c b/libatalk/cnid/tdb/cnid_tdb_get.c index 4e7f638d..5c753677 100644 --- a/libatalk/cnid/tdb/cnid_tdb_get.c +++ b/libatalk/cnid/tdb/cnid_tdb_get.c @@ -14,7 +14,7 @@ cnid_t cnid_tdb_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l TDB_DATA key, data; cnid_t id; - if (!cdb || !(db = cdb->_private) || (len > MAXPATHLEN)) { + if (!cdb || !(db = cdb->cnid_db_private) || (len > MAXPATHLEN)) { return 0; } diff --git a/libatalk/cnid/tdb/cnid_tdb_lookup.c b/libatalk/cnid/tdb/cnid_tdb_lookup.c index c95631af..7c7bdff1 100644 --- a/libatalk/cnid/tdb/cnid_tdb_lookup.c +++ b/libatalk/cnid/tdb/cnid_tdb_lookup.c @@ -21,11 +21,11 @@ cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, int update = 0; cnid_t id_devino = 0, id_didname = 0,id = 0; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { return 0; } - if ((buf = (char *)make_tdb_data(cdb->flags, st, did, name, len)) == NULL) { + if ((buf = (char *)make_tdb_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long"); return 0; } diff --git a/libatalk/cnid/tdb/cnid_tdb_open.c b/libatalk/cnid/tdb/cnid_tdb_open.c index 0aee5b4d..7e2558fe 100644 --- a/libatalk/cnid/tdb/cnid_tdb_open.c +++ b/libatalk/cnid/tdb/cnid_tdb_open.c @@ -12,6 +12,8 @@ #include "cnid_tdb.h" #include +#include + #include #define DBHOME ".AppleDB" #define DBHOMELEN 9 /* strlen(DBHOME) +1 for / */ @@ -23,30 +25,22 @@ #define DBVERSION2 0x00000002U #define DBVERSION DBVERSION2 -static struct _cnid_db *cnid_tdb_new(const char *volpath) +static struct _cnid_db *cnid_tdb_new(struct vol *vol) { struct _cnid_db *cdb; - struct _cnid_tdb_private *priv; if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) return NULL; - if ((cdb->volpath = strdup(volpath)) == NULL) { - free(cdb); - return NULL; - } + cdb->cnid_db_vol = vol; - if ((cdb->_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) { - free(cdb->volpath); + if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) { free(cdb); return NULL; } - /* Set up private state */ - priv = (struct _cnid_tdb_private *) (cdb->_private); - /* Set up standard fields */ - cdb->flags = CNID_FLAG_PERSISTENT; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT; cdb->cnid_add = cnid_tdb_add; cdb->cnid_delete = cnid_tdb_delete; @@ -72,31 +66,27 @@ struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args) TDB_DATA key, data; int hash_size = 131071; int tdb_flags = 0; + struct vol *vol = args->cnid_args_vol; - if (!args->dir) { - /* note: dir and path are not used for in memory db */ + if ((cdb = cnid_tdb_new(vol)) == NULL) { + LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb"); return NULL; } - if ((len = strlen(args->dir)) > (MAXPATHLEN - DBLEN - 1)) { - LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", args->dir); - return NULL; - } - - if ((cdb = cnid_tdb_new(args->dir)) == NULL) { - LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb"); + if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBLEN - 1)) { + LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", vol->v_path); return NULL; } - strcpy(path, args->dir); + strcpy(path, vol->v_path); if (path[len - 1] != '/') { strcat(path, "/"); len++; } strcpy(path + len, DBHOME); - if (!(args->flags & CNID_FLAG_MEMORY)) { - if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) { + if (!(args->cnid_args_flags & CNID_FLAG_MEMORY)) { + if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) { LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path); goto fail; } @@ -107,12 +97,12 @@ struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args) } strcat(path, "/"); - db = (struct _cnid_tdb_private *)cdb->_private; + db = (struct _cnid_tdb_private *)cdb->cnid_db_private; path[len + DBHOMELEN] = '\0'; strcat(path, DBCNID); - db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~args->mask); + db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~vol->v_umask); if (!db->tdb_cnid) { LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path); goto fail; @@ -146,8 +136,7 @@ struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args) return cdb; fail: - free(cdb->_private); - free(cdb->volpath); + free(cdb->cnid_db_private); free(cdb); return NULL; diff --git a/libatalk/cnid/tdb/cnid_tdb_resolve.c b/libatalk/cnid/tdb/cnid_tdb_resolve.c index 851f9e55..b999ca3e 100644 --- a/libatalk/cnid/tdb/cnid_tdb_resolve.c +++ b/libatalk/cnid/tdb/cnid_tdb_resolve.c @@ -15,7 +15,7 @@ char *cnid_tdb_resolve(struct _cnid_db *cdb, cnid_t * id, void *buffer, size_t l struct _cnid_tdb_private *db; TDB_DATA key, data; - if (!cdb || !(db = cdb->_private) || !id || !(*id)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { return NULL; } key.dptr = (unsigned char *)id; diff --git a/libatalk/cnid/tdb/cnid_tdb_update.c b/libatalk/cnid/tdb/cnid_tdb_update.c index 6d23b109..9688d866 100644 --- a/libatalk/cnid/tdb/cnid_tdb_update.c +++ b/libatalk/cnid/tdb/cnid_tdb_update.c @@ -13,7 +13,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, struct _cnid_tdb_private *db; TDB_DATA key, data, altdata; - if (!cdb || !(db = cdb->_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) { return -1; } @@ -22,7 +22,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, /* Get the old info. search by dev/ino */ - data.dptr = make_tdb_data(cdb->flags, st, did, name, len); + data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len); data.dsize = CNID_HEADER_LEN + len + 1; key.dptr = data.dptr +CNID_DEVINO_OFS; key.dsize = CNID_DEVINO_LEN; @@ -47,7 +47,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, } /* search by did/name */ - data.dptr = make_tdb_data(cdb->flags, st, did, name, len); + data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len); data.dsize = CNID_HEADER_LEN + len + 1; key.dptr = (unsigned char *)data.dptr +CNID_DID_OFS; key.dsize = data.dsize - CNID_DID_OFS; @@ -71,7 +71,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, /* Make a new entry. */ - data.dptr = make_tdb_data(cdb->flags, st, did, name, len); + data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len); data.dsize = CNID_HEADER_LEN + len + 1; memcpy(data.dptr, &id, sizeof(id)); diff --git a/libatalk/util/netatalk_conf.c b/libatalk/util/netatalk_conf.c index 2bb6d9f8..482aa777 100644 --- a/libatalk/util/netatalk_conf.c +++ b/libatalk/util/netatalk_conf.c @@ -1677,13 +1677,15 @@ struct vol *getvolbypath(AFPObj *obj, const char *path) subpath = prw; strlcat(tmpbuf, user, MAXPATHLEN); - if (getpwnam(user) == NULL) { + if ((pw = getpwnam(user)) == NULL) { /* (5b) */ char *tuser; if ((tuser = getuserbypath(tmpbuf)) != NULL) { free(user); user = strdup(tuser); } + if ((pw = getpwnam(user)) == NULL) + EC_FAIL_LOG("unknown user: %s", user); } strlcpy(obj->username, user, MAXUSERLEN); strlcat(tmpbuf, "/", MAXPATHLEN); diff --git a/libatalk/util/unix.c b/libatalk/util/unix.c index 37bfe140..dcef1c82 100644 --- a/libatalk/util/unix.c +++ b/libatalk/util/unix.c @@ -436,7 +436,7 @@ char *realpath_safe(const char *path) #ifdef REALPATH_TAKES_NULL if ((resolved_path = realpath(path, NULL)) == NULL) { - LOG(log_error, logtype_afpd, "realpath() cannot resolve path \"%s\"", path); + LOG(log_debug, logtype_afpd, "realpath() cannot resolve path \"%s\"", path); return NULL; } return resolved_path; @@ -445,7 +445,7 @@ char *realpath_safe(const char *path) return NULL; if (realpath(path, resolved_path) == NULL) { free(resolved_path); - LOG(log_error, logtype_afpd, "realpath() cannot resolve path \"%s\"", path); + LOG(log_debug, logtype_afpd, "realpath() cannot resolve path \"%s\"", path); return NULL; } /* Safe some memory */ diff --git a/man/man1/dbd.1.in b/man/man1/dbd.1.in index ad233a9b..fb60ce9a 100644 --- a/man/man1/dbd.1.in +++ b/man/man1/dbd.1.in @@ -31,7 +31,7 @@ dbd \- CNID database maintenance .SH "SYNOPSIS" .HP \w'\fBdbd\fR\fB\fR\ 'u -\fBdbd\fR\fB\fR [\-fsv] \fIvolumepath\fR +\fBdbd\fR\fB\fR [\-cfFstuvV] \fIvolumepath\fR .SH "DESCRIPTION" .PP \fBdbd\fR @@ -63,6 +63,11 @@ scan volume: treat the volume as read only and don\*(Aqt perform any filesystem show statistics while running .RE .PP +\-u +.RS 4 +username for use with AFP volumes using user variable $u +.RE +.PP \-v .RS 4 verbose diff --git a/man/man5/afp.conf.5.in b/man/man5/afp.conf.5.in index e90e4014..723cf689 100644 --- a/man/man5/afp.conf.5.in +++ b/man/man5/afp.conf.5.in @@ -174,7 +174,7 @@ in parentheses indicates that a parameter is specific to the [Global] section\&. indicates that a parameter can be specified in a volume specific section\&. .SH "VARIABLE SUBSTITUTIONS" .PP -You can use variables in volume names\&. The use of variables in paths is not supported for now\&. +You can use variables in volume names\&. The use of variables in paths is limited to $u\&. .sp .RS 4 .ie n \{\ -- 2.39.2