X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fcnid_dbd%2Fcnid_metad.c;h=42b398f792c30707ad3c44db9d4e11353696256c;hb=f254fd618b53e97cc5382b23709d4f3de1e70b41;hp=7b86219cf73e349e6edc2bb05a254786a8d50ad3;hpb=edf01c724768d494e522ec84380e8e49b37a2bd6;p=netatalk.git diff --git a/etc/cnid_dbd/cnid_metad.c b/etc/cnid_dbd/cnid_metad.c index 7b86219c..42b398f7 100644 --- a/etc/cnid_dbd/cnid_metad.c +++ b/etc/cnid_dbd/cnid_metad.c @@ -87,11 +87,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include @@ -106,7 +107,7 @@ static volatile sig_atomic_t sigchild = 0; static uint maxvol; #define MAXSPAWN 3 /* Max times respawned in.. */ -#define TESTTIME 42 /* this much seconds apfd client tries to * +#define TESTTIME 10 /* this much seconds apfd client tries to * * to reconnect every 5 secondes, catch it */ #define MAXVOLS 4096 #define DEFAULTHOST "localhost" @@ -116,7 +117,7 @@ struct server { char *v_path; pid_t pid; time_t tm; /* When respawned last */ - int count; /* Times respawned in the last TESTTIME secondes */ + unsigned int count; /* Times respawned in the last TESTTIME secondes */ int control_fd; /* file descriptor to child cnid_dbd process */ }; @@ -124,16 +125,17 @@ static struct server srv[MAXVOLS]; static void daemon_exit(int i) { - server_unlock(_PATH_CNID_METAD_LOCK); exit(i); } /* ------------------ */ -static void sigterm_handler(int sig) +static void sig_handler(int sig) { switch( sig ) { - case SIGTERM : - LOG(log_info, logtype_afpd, "shutting down on signal %d", sig ); + case SIGTERM: + case SIGQUIT: + LOG(log_note, logtype_afpd, "shutting down on %s", + sig == SIGTERM ? "SIGTERM" : "SIGQUIT"); break; default : LOG(log_error, logtype_afpd, "unexpected signal: %d", sig); @@ -182,8 +184,8 @@ static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath) time(&t); if (!up) { /* find an empty slot (i < maxvol) or the first free slot (i == maxvol)*/ - for (i = 0; i <= maxvol; i++) { - if (srv[i].v_path == NULL && i < MAXVOLS) { + for (i = 0; i <= maxvol && i < MAXVOLS; i++) { + if (srv[i].v_path == NULL) { up = &srv[i]; if ((up->v_path = strdup(volpath)) == NULL) return -1; @@ -199,25 +201,30 @@ static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath) return -1; } } else { - /* we have a slot but no process, check for respawn too fast */ - if ( (t < (up->tm + TESTTIME)) /* We're in the respawn time window */ - && - (up->count > MAXSPAWN) ) { /* ...and already tried to fork too often */ - LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn too fast just exiting"); - return -1; /* just exit, dont sleep, because we might have work to do for another client */ - } - if ( t >= (up->tm + TESTTIME) ) { /* out of respawn too fast windows reset the count */ - LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn window ended"); - up->tm = t; - up->count = 0; + /* we have a slot but no process */ + if (up->count > 0) { + /* check for respawn too fast */ + if (t < (up->tm + TESTTIME)) { + /* We're in the respawn time window */ + if (up->count > MAXSPAWN) { + /* ...and already tried to fork too often */ + LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawning too fast"); + return -1; /* just exit, dont sleep, because we might have work to do for another client */ + } + } else { + /* out of respawn too fast windows reset the count */ + LOG(log_info, logtype_cnid, "maybe_start_dbd: respawn window ended"); + up->count = 0; + } } up->count++; - LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn count now is: %u", up->count); + up->tm = t; + LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn count: %u", up->count); if (up->count > MAXSPAWN) { /* We spawned too fast. From now until the first time we tried + TESTTIME seconds we will just return -1 above */ - LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: reached MAXSPAWN threshhold"); - } + LOG(log_info, logtype_cnid, "maybe_start_dbd: reached MAXSPAWN threshhold"); + } } /* @@ -277,66 +284,46 @@ static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath) } /* ------------------ */ -static int set_dbdir(char *dbdir) +static int set_dbdir(const char *dbdir, const char *vpath) { - int len; + EC_INIT; struct stat st; + bstring oldpath, newpath; + char *cmd_argv[4]; - len = strlen(dbdir); + LOG(log_debug, logtype_cnid, "set_dbdir: volume: %s, db path: %s", vpath, dbdir); - if (stat(dbdir, &st) < 0 && mkdir(dbdir, 0755) < 0) { - LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", dbdir); - return -1; - } + EC_NULL_LOG( oldpath = bformat("%s/%s/", vpath, DBHOME) ); + EC_NULL_LOG( newpath = bformat("%s/%s/", dbdir, DBHOME) ); - if (dbdir[len - 1] != '/') { - strcat(dbdir, "/"); - len++; - } - strcpy(dbdir + len, DBHOME); - if (stat(dbdir, &st) < 0 && mkdir(dbdir, 0755 ) < 0) { + if (lstat(dbdir, &st) < 0 && mkdir(dbdir, 0755) < 0) { LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", dbdir); - return -1; + EC_FAIL; } - return 0; -} - -/* ------------------ */ -static uid_t user_to_uid (char *username) -{ - struct passwd *this_passwd; - - /* check for anything */ - if ( !username || strlen ( username ) < 1 ) return 0; - - /* grab the /etc/passwd record relating to username */ - this_passwd = getpwnam ( username ); - - /* return false if there is no structure returned */ - if (this_passwd == NULL) return 0; - /* return proper uid */ - return this_passwd->pw_uid; - -} - -/* ------------------ */ -static gid_t group_to_gid ( char *group) -{ - struct group *this_group; - - /* check for anything */ - if ( !group || strlen ( group ) < 1 ) return 0; - - /* grab the /etc/groups record relating to group */ - this_group = getgrnam ( group ); + if (lstat(cfrombstr(oldpath), &st) == 0 && lstat(cfrombstr(newpath), &st) != 0 && errno == ENOENT) { + /* There's an .AppleDB in the volume root, we move it */ + cmd_argv[0] = "mv"; + cmd_argv[1] = bdata(oldpath); + cmd_argv[2] = (char *)dbdir; + cmd_argv[3] = NULL; + if (run_cmd("mv", cmd_argv) != 0) { + LOG(log_error, logtype_cnid, "set_dbdir: moving CNID db from \"%s\" to \"%s\" failed", + bdata(oldpath), dbdir); + EC_FAIL; + } - /* return false if there is no structure returned */ - if (this_group == NULL) return 0; + } - /* return proper gid */ - return this_group->gr_gid; + if (lstat(cfrombstr(newpath), &st) < 0 && mkdir(cfrombstr(newpath), 0755 ) < 0) { + LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", bdata(newpath)); + EC_FAIL; + } +EC_CLEANUP: + bdestroy(oldpath); + bdestroy(newpath); + EC_EXIT; } /* ------------------ */ @@ -362,13 +349,17 @@ static void set_signal(void) daemon_exit(EXITERR_SYS); } - /* Catch SIGTERM */ - sv.sa_handler = sigterm_handler; + /* Catch SIGTERM and SIGQUIT */ + sv.sa_handler = sig_handler; sigfillset(&sv.sa_mask ); if (sigaction(SIGTERM, &sv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); daemon_exit(EXITERR_SYS); } + if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } /* Ignore the rest */ sv.sa_handler = SIG_IGN; @@ -405,7 +396,7 @@ static void set_signal(void) /* block everywhere but in pselect */ sigemptyset(&set); sigaddset(&set, SIGCHLD); - sigprocmask(SIG_BLOCK, &set, NULL); + sigprocmask(SIG_SETMASK, &set, NULL); } static int setlimits(void) @@ -442,7 +433,6 @@ int main(int argc, char *argv[]) int cc; uid_t uid = 0; gid_t gid = 0; - int err = 0; int debug = 0; int ret; sigset_t set; @@ -467,30 +457,19 @@ int main(int argc, char *argv[]) } } - /* Check for PID lockfile */ - if (check_lockfile("cnid_metad", _PATH_CNID_METAD_LOCK)) - return -1; - if (!debug && daemonize(0, 0) != 0) exit(EXITERR_SYS); - /* Create PID lockfile */ - if (create_lockfile("cnid_metad", _PATH_CNID_METAD_LOCK)) - return -1; - - if (afp_config_parse(&obj) != 0) + if (afp_config_parse(&obj, "cnid_metad") != 0) daemon_exit(1); - set_processname("cnid_metad"); - setuplog(obj.options.logconfig, obj.options.logfile); - - if (load_volumes(&obj, NULL) != 0) + if (load_volumes(&obj) != 0) daemon_exit(1); (void)setlimits(); - host = iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700"); - if (port = strrchr(host, ':')) + host = atalk_iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700"); + if ((port = strrchr(host, ':'))) *port++ = 0; else port = DEFAULTPORT; @@ -536,8 +515,12 @@ int main(int argc, char *argv[]) if (WIFEXITED(status)) { LOG(log_info, logtype_cnid, "cnid_dbd[%i] exited with exit code %i", pid, WEXITSTATUS(status)); + } else { + /* cnid_dbd did a clean exit probably on idle timeout, reset bookkeeping */ + srv[i].tm = 0; + srv[i].count = 0; } - else if (WIFSIGNALED(status)) { + if (WIFSIGNALED(status)) { LOG(log_info, logtype_cnid, "cnid_dbd[%i] got signal %i", pid, WTERMSIG(status)); } @@ -582,7 +565,7 @@ int main(int argc, char *argv[]) LOG(log_debug, logtype_cnid, "main: request for volume: %s", volpath); - if (load_volumes(&obj, NULL) != 0) { + if (load_volumes(&obj) != 0) { LOG(log_severe, logtype_cnid, "main: error reloading config"); goto loop_end; } @@ -594,7 +577,7 @@ int main(int argc, char *argv[]) LOG(log_maxdebug, logtype_cnid, "main: dbpath: %s", vol->v_dbpath); - if (set_dbdir(vol->v_dbpath) < 0) { + if (set_dbdir(vol->v_dbpath, volpath) < 0) { goto loop_end; }