r74: * Added checks for GLib (not used yet, but will be in this release)
[nbd.git] / nbd-server.c
index bc4b101..58050bc 100644 (file)
  *     <wouter@debian.org>
  */
 
-/* used in cliserv.h, so must come first */
-#define MY_NAME "nbd_server"
 /* Includes LFS defines, which defines behaviours of some of the following
  * headers, so must come before those */
-#include "cliserv.h"
+#include "config.h"
+#include "lfs.h"
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/wait.h>          /* wait */
+#ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
+#endif
 #include <sys/param.h>
+#ifdef HAVE_SYS_MOUNT_H
 #include <sys/mount.h>         /* For BLKGETSIZE */
+#endif
 #include <signal.h>            /* sigaction */
 #include <netinet/tcp.h>
 #include <netinet/in.h>                /* sockaddr_in, htons, in_addr */
 #include <strings.h>
 #include <dirent.h>
 
+#include <glib.h>
+
+/* used in cliserv.h, so must come first */
+#define MY_NAME "nbd_server"
+#include "cliserv.h"
+
 /** how much space for child PIDs we have by default. Dynamically
    allocated, and will be realloc()ed if out of space, so this should
    probably be fair for most situations. */
 
 /** Logging macros, now nothing goes to syslog unless you say ISSERVER */
 #ifdef ISSERVER
-#define msg2(a,b) syslog(a,b)
-#define msg3(a,b,c) syslog(a,b,c)
-#define msg4(a,b,c,d) syslog(a,b,c,d)
+#define msg2(a,b) syslog(a,"%s", b)
+#define msg3(a,b,c) syslog(a,"%s %s", b,c)
+#define msg4(a,b,c,d) syslog(a,"%s %s %s", b,c,d)
 #else
-#define msg2(a,b) do { fprintf(stderr,b) ; fputs("\n",stderr) ; } while(0) 
-#define msg3(a,b,c) do { fprintf(stderr,b,c); fputs("\n",stderr) ; } while(0) 
-#define msg4(a,b,c,d) do { fprintf(stderr,b,c,d); fputs("\n",stderr) ; } while(0)
+#define msg2(a,b) do { fprintf(stderr,"%s\n", b) ; } while(0) 
+#define msg3(a,b,c) do { fprintf(stderr,"%s %s\n", b,c); } while(0) 
+#define msg4(a,b,c,d) do { fprintf(stderr,"%s %s %s\n", b,c,d); } while(0)
 #endif
 
 /* Debugging macros */
 #define F_READONLY 1      /**< flag to tell us a file is readonly */
 #define F_MULTIFILE 2    /**< flag to tell us a file is exported using -m */
 #define F_COPYONWRITE 4          /**< flag to tell us a file is exported using copyonwrite */
-char difffilename[256]; /**< filename of the copy-on-write file. Doesn't belong here! */
+char difffilename[1024]; /**< filename of the copy-on-write file. Doesn't belong here! */
 unsigned int timeout = 0; /**< disconnect timeout */
 int autoreadonly = 0; /**< 1 = switch to readonly if opening readwrite isn't
                        possible */
@@ -348,15 +357,20 @@ void sigchld_handler(int s)
 {
         int* status=NULL;
        int i;
+       char buf[80];
        pid_t pid;
 
        while((pid=wait(status)) > 0) {
                if(WIFEXITED(status)) {
-                       msg3(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
+                       memset(buf,'\0', 80);
+                       snprintf(buf, 79, "%d", WEXITSTATUS(status));
+                       msg3(LOG_INFO, "Child exited with ", buf);
                }
                for(i=0;children[i]!=pid&&i<child_arraysize;i++);
                if(i>=child_arraysize) {
-                       msg3(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld",(long) pid);
+                       memset(buf, '\0', 80);
+                       snprintf(buf, 79, "%ld", (long)pid);
+                       msg3(LOG_INFO, "SIGCHLD received for an unknown child with PID ", buf);
                } else {
                        children[i]=(pid_t)0;
                        DEBUG2("Removing %d from the list of children", pid);
@@ -401,13 +415,17 @@ off_t size_autodetect(int export)
        struct stat stat_buf;
        int error;
 
-       DEBUG("looking for export size with lseek SEEK_END\n");
-       es = lseek(export, (off_t)0, SEEK_END);
-       if (es > ((off_t)0)) {
+#ifdef HAVE_SYS_MOUNT_H
+#ifdef HAVE_SYS_IOCTL_H
+#ifdef BLKGETSIZE
+       DEBUG("looking for export size with ioctl BLKGETSIZE\n");
+       if (!ioctl(export, BLKGETSIZE, &es32) && es32) {
+               es = (off_t)es32 * (off_t)512;
                return es;
-        } else {
-                DEBUG2("lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
-        }
+       }
+#endif /* BLKGETSIZE */
+#endif /* HAVE_SYS_IOCTL_H */
+#endif /* HAVE_SYS_MOUNT_H */
 
        DEBUG("looking for export size with fstat\n");
        stat_buf.st_size = 0;
@@ -417,14 +435,15 @@ off_t size_autodetect(int export)
         } else {
                 err("fstat failed: %m");
         }
-       
-#ifdef BLKGETSIZE
-       DEBUG("looking for export size with ioctl BLKGETSIZE\n");
-       if (!ioctl(export, BLKGETSIZE, &es32) && es32) {
-               es = (off_t)es32 * (off_t)512;
+
+       DEBUG("looking for export size with lseek SEEK_END\n");
+       es = lseek(export, (off_t)0, SEEK_END);
+       if (es > ((off_t)0)) {
                return es;
-       }
-#endif
+        } else {
+                DEBUG2("lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
+        }
+
        err("Could not find size of exported block device: %m");
        return OFFT_MAX;
 }
@@ -724,11 +743,16 @@ int mainloop(int net)
  **/
 int splitexport(void) {
        off_t i ;
-       
+
        for (i=0; i<exportsize; i+=hunksize) {
                char exportname3[1024];
-               
-               sprintf(exportname3, exportname2, i/hunksize);
+
+               if(flags & F_MULTIFILE) {
+                       snprintf(exportname3, 1024, "%s.%d", exportname2, (int)(i/hunksize));
+               } else {
+                       strncpy(exportname3, exportname2, 1024);
+               }
+               exportname3[1023]='\0';
                printf( "Opening %s\n", exportname3 );
                if ((export[i/hunksize] = open(exportname3, (flags & F_READONLY) ? O_RDONLY : O_RDWR)) == -1) {
                        /* Read WRITE ACCESS was requested by media is only read only */
@@ -740,8 +764,9 @@ int splitexport(void) {
        }
 
        if (flags & F_COPYONWRITE) {
-               sprintf(difffilename,"%s-%s-%d.diff",exportname2,clientname,
+               snprintf(difffilename, 1024, "%s-%s-%d.diff",exportname2,clientname,
                        (int)getpid()) ;
+               difffilename[1023]='\0';
                msg3(LOG_INFO,"About to create map and diff file %s",difffilename) ;
                difffile=open(difffilename,O_RDWR | O_CREAT | O_TRUNC,0600) ;
                if (difffile<0) err("Could not create diff file (%m)") ;
@@ -760,7 +785,8 @@ int splitexport(void) {
  *
  * @param net A network socket connected to an nbd client
  **/
-void serveconnection(int net) {   
+void serveconnection(int net) {
+       char buf[80];
        splitexport();
        if (exportsize == OFFT_MAX) {
                exportsize = size_autodetect(export[0]);
@@ -768,9 +794,11 @@ void serveconnection(int net) {
        if (exportsize > OFFT_MAX) {
                err("Size of exported file is too big\n");
        }
-       else
-               msg3(LOG_INFO, "size of exported file/device is %Lu",
-                    (unsigned long long)exportsize);
+       else {
+               memset(buf, '\0', 80);
+               snprintf(buf, 79, "%Lu", (unsigned long long)exportsize);
+               msg3(LOG_INFO, "size of exported file/device is ", buf);
+       }
 
        setmysockopt(net);
 
@@ -778,7 +806,7 @@ void serveconnection(int net) {
 }
 
 /**
- * Find the name of the file we have to serve. This will use sprintf()
+ * Find the name of the file we have to serve. This will use snprintf()
  * to put the IP address of the client inside a filename containing
  * "%s". That name is then written to exportname2
  *
@@ -795,7 +823,8 @@ void set_peername(int net,char *clientname)
        if (getpeername( net, (struct sockaddr *) &addrin, &addrinlen ) < 0)
                err("getsockname failed: %m");
        peername = inet_ntoa(addrin.sin_addr);
-       sprintf(exportname2, exportname, peername);
+       snprintf(exportname2, 1024, exportname, peername);
+       exportname2[1023]='\0';
 
        msg4(LOG_INFO, "connect from %s, assigned file is %s", 
             peername, exportname2);