r287: Fixes from Tefnet <developers@tefnet.pl>
[nbd.git] / nbd-server.c
index 09a5256..3577fc5 100644 (file)
@@ -68,6 +68,7 @@
 #include <sys/mount.h>         /* For BLKGETSIZE */
 #endif
 #include <signal.h>            /* sigaction */
+#include <errno.h>
 #include <netinet/tcp.h>
 #include <netinet/in.h>                /* sockaddr_in, htons, in_addr */
 #include <netdb.h>             /* hostent, gethostby*, getservby* */
@@ -406,6 +407,7 @@ SERVER* cmdline(int argc, char *argv[]) {
        }
        serve=g_new0(SERVER, 1);
        serve->authname = g_strdup(default_authname);
+       serve->virtstyle=VIRT_IPLIT;
        while((c=getopt_long(argc, argv, "-a:C:cl:mo:rp:", long_options, &i))>=0) {
                switch (c) {
                case 1:
@@ -1052,7 +1054,7 @@ void negotiate(CLIENT *client) {
 /** sending macro. */
 #define SEND(net,reply) writeit( net, &reply, sizeof( reply ));
 /** error macro. */
-#define ERROR(client,reply) { reply.error = htonl(-1); SEND(client->net,reply); reply.error = 0; }
+#define ERROR(client,reply,errcode) { reply.error = htonl(errcode); SEND(client->net,reply); reply.error = 0; }
 /**
  * Serve a file to a single client.
  *
@@ -1112,13 +1114,13 @@ int mainloop(CLIENT *client) {
                memcpy(reply.handle, request.handle, sizeof(reply.handle));
                if ((request.from + len) > (OFFT_MAX)) {
                        DEBUG("[Number too large!]");
-                       ERROR(client, reply);
+                       ERROR(client, reply, EINVAL);
                        continue;
                }
 
                if (((ssize_t)((off_t)request.from + len) > client->exportsize)) {
                        DEBUG("[RANGE!]");
-                       ERROR(client, reply);
+                       ERROR(client, reply, EINVAL);
                        continue;
                }
 
@@ -1129,12 +1131,12 @@ int mainloop(CLIENT *client) {
                        if ((client->server->flags & F_READONLY) ||
                            (client->server->flags & F_AUTOREADONLY)) {
                                DEBUG("[WRITE to READONLY!]");
-                               ERROR(client, reply);
+                               ERROR(client, reply, EPERM);
                                continue;
                        }
                        if (expwrite(request.from, buf, len, client)) {
                                DEBUG("Write failed: %m" );
-                               ERROR(client, reply);
+                               ERROR(client, reply, errno);
                                continue;
                        }
                        SEND(client->net, reply);
@@ -1146,7 +1148,7 @@ int mainloop(CLIENT *client) {
                DEBUG("exp->buf, ");
                if (expread(request.from, buf + sizeof(struct nbd_reply), len, client)) {
                        DEBUG("Read failed: %m");
-                       ERROR(client, reply);
+                       ERROR(client, reply, errno);
                        continue;
                }
 
@@ -1258,7 +1260,7 @@ int do_run(gchar* command, gchar* file) {
        gchar* cmd;
        int retval=0;
 
-       if(*command) {
+       if(command && *command) {
                cmd = g_strdup_printf(command, file);
                retval=system(cmd);
                g_free(cmd);
@@ -1275,6 +1277,9 @@ int do_run(gchar* command, gchar* file) {
  * @param client a connected client
  **/
 void serveconnection(CLIENT *client) {
+       if(do_run(client->server->prerun, client->exportname)) {
+               exit(EXIT_FAILURE);
+       }
        setupexport(client);
 
        if (client->server->flags & F_COPYONWRITE) {
@@ -1283,9 +1288,7 @@ void serveconnection(CLIENT *client) {
 
        setmysockopt(client->net);
 
-       if(!do_run(client->server->prerun, client->exportname)) {
-               mainloop(client);
-       }
+       mainloop(client);
        do_run(client->server->postrun, client->exportname);
 }
 
@@ -1523,7 +1526,8 @@ int serveloop(GArray* servers) {
                                        }
                                        /* child */
                                        g_hash_table_destroy(children);
-                                       for(i=0;i<servers->len,serve=(g_array_index(servers, SERVER*, i));i++) {
+                                       for(i=0;i<servers->len;i++) {
+                                               serve=g_array_index(servers, SERVER*, i);
                                                close(serve->socket);
                                        }
                                        /* FALSE does not free the
@@ -1549,16 +1553,16 @@ int serveloop(GArray* servers) {
 void dousers(void) {
        struct passwd *pw;
        struct group *gr;
-       if(runuser) {
-               pw=getpwnam(runuser);
-               if(setuid(pw->pw_uid)<0)
-                       msg3(LOG_DEBUG, "Could not set UID: %s", strerror(errno));
-       }
        if(rungroup) {
                gr=getgrnam(rungroup);
                if(setgid(gr->gr_gid)<0)
                        msg3(LOG_DEBUG, "Could not set GID: %s", strerror(errno));
        }
+       if(runuser) {
+               pw=getpwnam(runuser);
+               if(setuid(pw->pw_uid)<0)
+                       msg3(LOG_DEBUG, "Could not set UID: %s", strerror(errno));
+       }
 }
 
 /**
@@ -1581,7 +1585,8 @@ int main(int argc, char *argv[]) {
        serve=cmdline(argc, argv);
        servers = parse_cfile(config_file_pos, &err);
        if(!servers || !servers->len) {
-               g_warning("Could not parse config file: %s", err->message);
+               g_warning("Could not parse config file: %s", 
+                               err ? err->message : "Unknown error");
        }
        if(serve) {
                g_array_append_val(servers, *serve);