]> arthur.barton.de Git - netatalk.git/blobdiff - etc/cnid_dbd/cnid_metad.c
fix a signed/unsigned, 16/32 bits mismatch. from Burkhard Schmidt, bs at cpfs.mpg.de.
[netatalk.git] / etc / cnid_dbd / cnid_metad.c
index affe50c17aaebdfc716333ae6a247d1291573231..d5c44d028d597305cc233532519e51386a11d6c0 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * $Id: cnid_metad.c,v 1.1.4.7 2003-12-01 22:23:12 lenneis Exp $
+ * $Id: cnid_metad.c,v 1.1.4.15 2004-09-06 07:19:21 didg Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
- * All Rights Reserved.  See COPYRIGHT.
+ * All Rights Reserved.  See COPYING.
  *
  */
 
@@ -96,17 +96,20 @@ static int rqstfd;
 #define MAXSRV 128
 
 #define MAXSPAWN   3                   /* Max times respawned in.. */
-#define TESTTIME   20                  /* this much seconds */
 
 #define DEFAULTHOST  "localhost"
 #define DEFAULTPORT  4700
+#define TESTTIME   22                  /* this much seconds apfd client tries to
+                                        * to reconnect every 5 secondes, catch it
+                                        */
 
 struct server {
     char  *name;
     pid_t pid;
     time_t tm;                    /* When respawned last */
     int count;                    /* Times respawned in the last TESTTIME secondes */
-    int   sv[2];
+    int toofast; 
+    int control_fd;               /* file descriptor to child cnid_dbd process */
 };
 
 static struct server srv[MAXSRV +1];
@@ -129,11 +132,19 @@ static int send_cred(int socket, int fd)
    struct msghdr msgh; 
    struct iovec iov[1];
    struct cmsghdr *cmsgp = NULL;
-   char buf[CMSG_SPACE(sizeof fd)];
+   char *buf;
+   size_t size;
    int er=0;
 
+   size = CMSG_SPACE(sizeof fd);
+   buf = malloc(size);
+   if (!buf) {
+       LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
+       return -1;
+   }
+
    memset(&msgh,0,sizeof (msgh));
-   memset(buf,0,sizeof (buf));
+   memset(buf,0, size);
 
    msgh.msg_name = NULL;
    msgh.msg_namelen = 0;
@@ -145,7 +156,7 @@ static int send_cred(int socket, int fd)
    iov[0].iov_len = sizeof(er);
 
    msgh.msg_control = buf;
-   msgh.msg_controllen = sizeof(buf);
+   msgh.msg_controllen = size;
 
    cmsgp = CMSG_FIRSTHDR(&msgh);
    cmsgp->cmsg_level = SOL_SOCKET;
@@ -160,8 +171,10 @@ static int send_cred(int socket, int fd)
    } while ( ret == -1 && errno == EINTR );
    if (ret == -1) {
        LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
+       free(buf);
        return -1;
    }
+   free(buf);
    return 0;
 }
 
@@ -170,13 +183,16 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
 {
     pid_t pid;
     struct server *up;
+    int sv[2];
     int i;
     time_t t;
+    char buf1[8];
+    char buf2[8];
 
     up = test_usockfn(dbdir, usockfn);
     if (up && up->pid) {
        /* we already have a process, send our fd */
-       if (send_cred(up->sv[0], rqstfd) < 0) {
+       if (send_cred(up->control_fd, rqstfd) < 0) {
            /* FIXME */
            return -1;
        }
@@ -192,6 +208,7 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
                 free(up->name);
                 up->tm = t;
                 up->count = 0;
+                up->toofast = 0;
                 /* copy name */
                 up->name = strdup(dbdir);
                 break;
@@ -205,12 +222,18 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
     else {
         /* we have a slot but no process, check for respawn too fast */
         if (up->tm + TESTTIME > t) {
+            if (up->toofast) {
+                /* silently exit */
+                return -1;
+            }
             up->count++;
         } else {
             up->count = 0;
+           up->toofast = 0;
             up->tm = t;
         }
-        if (up->count >= MAXSPAWN) {
+        if (up->count > MAXSPAWN) {
+           up->toofast = 1;
             up->tm = t;
            LOG(log_error, logtype_cnid, "respawn too fast %s", up->name);
            /* FIXME should we sleep a little ? */
@@ -221,8 +244,8 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
     /* create socketpair for comm between parent and child 
      * FIXME Do we really need a permanent pipe between them ?
      */
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, up->sv) < 0) {
-       LOG(log_error, logtype_cnid, "error in fork: %s", strerror(errno));
+    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
+       LOG(log_error, logtype_cnid, "error in socketpair: %s", strerror(errno));
        return -1;
     }
         
@@ -231,21 +254,36 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
        return -1;
     }    
     if (pid == 0) {
+        int ret;
        /*
         *  Child. Close descriptors and start the daemon. If it fails
         *  just log it. The client process will fail connecting
         *  afterwards anyway.
         */
-       close(0);
-       close(1);
+
        close(srvfd);
-       dup2(up->sv[1], 0);
-       dup2(rqstfd, 1);
+       close(sv[0]);
+       
+       for (i = 1; i <= MAXSRV; i++) {
+            if (srv[i].pid && up != &srv[i]) {
+               close(srv[i].control_fd);
+            }
+        }
 
-       close(up->sv[0]);
-       close(up->sv[1]);
-       close(rqstfd);
-       if (execlp(dbdpn, dbdpn, dbdir, NULL) < 0) {
+       sprintf(buf1, "%i", sv[1]);
+       sprintf(buf2, "%i", rqstfd);
+       
+       if (up->count == MAXSPAWN) {
+           /* there's a pb with the db inform child 
+            * it will run recover, delete the db whatever
+           */
+           LOG(log_error, logtype_cnid, "try with -d %s", up->name);
+           ret = execlp(dbdpn, dbdpn, "-d", dbdir, buf1, buf2, NULL);
+       }
+       else {
+           ret = execlp(dbdpn, dbdpn, dbdir, buf1, buf2, NULL);
+       }
+       if (ret < 0) {
            LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno));
            exit(0);
        }
@@ -254,6 +292,8 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
      *  Parent.
      */
     up->pid = pid;
+    close(sv[1]);
+    up->control_fd = sv[0];
     return 0;
 }
 
@@ -331,7 +371,7 @@ int main(int argc, char *argv[])
     int   status;
     char  *dbdpn = _PATH_CNID_DBD;
     char  *host = DEFAULTHOST;
-    int   port = DEFAULTPORT;
+    u_int16_t   port = DEFAULTPORT;
     struct db_param *dbp;
     int    i;
     int    cc;
@@ -340,6 +380,8 @@ int main(int argc, char *argv[])
     int    err = 0;
     int    debug = 0;
     int    ret;
+
+    set_processname("cnid_metad");
     
     while (( cc = getopt( argc, argv, "ds:p:h:u:g:")) != -1 ) {
         switch (cc) {
@@ -432,6 +474,7 @@ int main(int argc, char *argv[])
     signal(SIGPIPE, SIG_IGN);
 
     while (1) {
+        rqstfd = usockfd_check(srvfd, 10000000);
        /* Collect zombie processes and log what happened to them */       
         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
            for (i = 1; i <= MAXSRV; i++) {
@@ -440,8 +483,7 @@ int main(int argc, char *argv[])
 #if 0                   
                    free(srv[i].name);
 #endif                   
-                   close(srv[i].sv[0]);
-                   close(srv[i].sv[1]);
+                   close(srv[i].control_fd);
                    break;
                }
             }
@@ -456,7 +498,7 @@ int main(int argc, char *argv[])
            /* FIXME should */
            
        }
-        if ((rqstfd = usockfd_check(srvfd, 10000000)) <= 0)
+        if (rqstfd <= 0)
             continue;
         /* TODO: Check out read errors, broken pipe etc. in libatalk. Is
            SIGIPE ignored there? Answer: Ignored for dsi, but not for asp ... */