]> arthur.barton.de Git - netatalk.git/blobdiff - etc/cnid_dbd/cnid_metad.c
increase number of cnid_dbd slots to 512
[netatalk.git] / etc / cnid_dbd / cnid_metad.c
index 1288c82456e64af29de4d907c24b80a5705e6833..422d0b486b6e3ed21127a570885d3527f76a5c36 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * $Id: cnid_metad.c,v 1.1.4.9 2004-01-04 21:36:20 didg Exp $
+ * $Id: cnid_metad.c,v 1.1.4.15.2.4 2009-03-06 14:53:04 didg Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
- * All Rights Reserved.  See COPYRIGHT.
+ * All Rights Reserved.  See COPYING.
  *
  */
 
@@ -40,7 +40,8 @@
 #include <sys/socket.h>
 #include <stdio.h>
 #include <time.h>
-
+#include <sys/ioctl.h>
+  
 #ifndef WEXITSTATUS 
 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
 #endif /* ! WEXITSTATUS */
@@ -92,8 +93,9 @@
 
 static int srvfd;
 static int rqstfd;
+volatile sig_atomic_t alarmed = 0;
 
-#define MAXSRV 128
+#define MAXSRV 512
 
 #define MAXSPAWN   3                   /* Max times respawned in.. */
 
@@ -109,12 +111,12 @@ struct server {
     time_t tm;                    /* When respawned last */
     int count;                    /* Times respawned in the last TESTTIME secondes */
     int toofast; 
-    int   sv[2];
+    int control_fd;               /* file descriptor to child cnid_dbd process */
 };
 
 static struct server srv[MAXSRV +1];
 
-static struct server *test_usockfn(char *dir, char *fn)
+static struct server *test_usockfn(char *dir, char *fn _U_)
 {
 int i;
     for (i = 1; i <= MAXSRV; i++) {
@@ -132,11 +134,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;
@@ -148,7 +158,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;
@@ -163,8 +173,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;
 }
 
@@ -173,6 +185,7 @@ 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];
@@ -181,7 +194,7 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
     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;
        }
@@ -233,8 +246,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;
     }
         
@@ -251,16 +264,15 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
         */
 
        close(srvfd);
-       close(up->sv[0]);
+       close(sv[0]);
        
        for (i = 1; i <= MAXSRV; i++) {
             if (srv[i].pid && up != &srv[i]) {
-               close(srv[i].sv[0]);
-               close(srv[i].sv[1]);
+               close(srv[i].control_fd);
             }
         }
 
-       sprintf(buf1, "%i", up->sv[1]);
+       sprintf(buf1, "%i", sv[1]);
        sprintf(buf2, "%i", rqstfd);
        
        if (up->count == MAXSPAWN) {
@@ -282,8 +294,8 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
      *  Parent.
      */
     up->pid = pid;
-    /* FIXME Any reason we do not close up->sv[1] here? Do we need both
-       descriptors in the srv table? */
+    close(sv[1]);
+    up->control_fd = sv[0];
     return 0;
 }
 
@@ -352,16 +364,21 @@ char    *group;
  
 }
 
+/* ------------------ */
+void catch_alarm(int sig) {
+       alarmed = 1;
+}
+
 /* ------------------ */
 int main(int argc, char *argv[])
 {
     char  dbdir[MAXPATHLEN + 1];
-    int   len;
+    int   len, actual_len;
     pid_t pid;
     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;
@@ -370,6 +387,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) {
@@ -460,6 +479,7 @@ int main(int argc, char *argv[])
     }
 
     signal(SIGPIPE, SIG_IGN);
+    signal(SIGALRM, catch_alarm);
 
     while (1) {
         rqstfd = usockfd_check(srvfd, 10000000);
@@ -471,8 +491,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;
                }
             }
@@ -489,9 +508,18 @@ int main(int argc, char *argv[])
        }
         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 ... */
+        alarm(5); /* to prevent read from getting stuck */
         ret = read(rqstfd, &len, sizeof(int));
+       alarm(0);
+       if (alarmed) {
+           alarmed = 0;
+           LOG(log_severe, logtype_cnid, "Read(1) bailed with alarm (timeout)");
+           goto loop_end;
+       }
+       
         if (!ret) {
             /* already close */
             goto loop_end;
@@ -512,7 +540,16 @@ int main(int argc, char *argv[])
             LOG(log_error, logtype_cnid, "wrong len parameter: %d", len);
             goto loop_end;
         }
-        if (read(rqstfd, dbdir, len) != len) {
+        
+        alarm(5);
+       actual_len = read(rqstfd, dbdir, len);
+       alarm(0);
+       if (alarmed) {
+           alarmed = 0;
+           LOG(log_severe, logtype_cnid, "Read(2) bailed with alarm (timeout)");
+           goto loop_end;
+       }
+        if (actual_len != len) {
             LOG(log_error, logtype_cnid, "error/short read (dir): %s", strerror(errno));
             goto loop_end;
         }