From: yoe Date: Thu, 26 Jul 2007 14:30:45 +0000 (+0000) Subject: r270: Implement prerun and postrun options X-Git-Url: http://git.alex.org.uk r270: Implement prerun and postrun options --- diff --git a/nbd-server.5.sgml b/nbd-server.5.sgml index d44abd0..ba528b9 100644 --- a/nbd-server.5.sgml +++ b/nbd-server.5.sgml @@ -320,7 +320,8 @@ manpage.1: manpage.sgml will use sparse files to implement the copy-on-write option; such files take up less space then they appear to, which allows nbd-server to handle the - file as if it was just as large as the block device it's for. + file as if it was just as large as the block device it's + for. If this option is disabled, nbd-server @@ -414,17 +415,64 @@ manpage.1: manpage.sgml after it. nbd-server will use the number as a network mask in CIDR style, and use that as a hash cutoff point. In the above example, if - has been specified - as cidrhash 16, then + has been specified as + cidrhash 16, then nbd-server will try to open - /export/192.168.0.0/192.168.1.100; if - were specified as + /export/192.168.0.0/192.168.1.100; + if were specified as cidrhash 26, then nbd-server will try to open /export/192.168.1.64/192.168.1.100. + + + + Optional; string + + If specified, then this command will be ran after a + client has connected to the server (and has been + accepted), but before the server starts serving. If + the command contains the literal string '%s', then + this string will be replaced by the filename of the + file which nbd-server wants to export. + + + This is useful to create export files on the fly, or + to verify that a file can be used for export, to + write something to a log file, or similar. + + + If the command runs with a non-zero exit status, + then nbd-server will assume the export will fail, + and refuse to serve it. + + + + + + + Optional; string + + If specified, then it is assumed to be a command + that will be ran when a client has + disconnected. This can be useful to clean up + whatever has set up, to log + something, or similar. + + + If the literal string '%s' is present in the + command, it will be replaced by the file name that + has just been closed. + + + In contrast to the option, + the exit state of is + ignored. + + + diff --git a/nbd-server.c b/nbd-server.c index a7f759f..26c8f59 100644 --- a/nbd-server.c +++ b/nbd-server.c @@ -179,6 +179,10 @@ typedef struct { VIRT_STYLE virtstyle;/**< The style of virtualization, if any */ uint8_t cidrlen; /**< The length of the mask when we use CIDR-style virtualization */ + gchar* prerun; /**< command to be ran after connecting a client, + but before starting to serve */ + gchar* postrun; /**< command that will be ran after the client + disconnects */ } SERVER; /** @@ -530,6 +534,8 @@ GArray* parse_cfile(gchar* f, GError** e) { { "timeout", FALSE, PARAM_INT, NULL, 0 }, { "filesize", FALSE, PARAM_INT, NULL, 0 }, { "virtstyle", FALSE, PARAM_STRING, NULL, 0 }, + { "prerun", FALSE, PARAM_STRING, NULL, 0 }, + { "postrun", FALSE, PARAM_STRING, NULL, 0 }, { "readonly", FALSE, PARAM_BOOL, NULL, F_READONLY }, { "multifile", FALSE, PARAM_BOOL, NULL, F_MULTIFILE }, { "copyonwrite", FALSE, PARAM_BOOL, NULL, F_COPYONWRITE }, @@ -576,8 +582,11 @@ GArray* parse_cfile(gchar* f, GError** e) { lp[3].target=&(s.timeout); lp[4].target=&(s.expected_size); lp[5].target=&(virtstyle); - lp[6].target=lp[7].target=lp[8].target= - lp[9].target=lp[10].target=&(s.flags); + lp[6].target=&(s.prerun); + lp[7].target=&(s.postrun); + lp[8].target=lp[9].target=lp[10].target= + lp[11].target=lp[12].target=&(s.flags); + /* After the [generic] group, start parsing exports */ if(i==1) { p=lp; @@ -1045,7 +1054,7 @@ void negotiate(CLIENT *client) { * pieces. Preferably with a chainsaw. * * @param client The client we're going to serve to. - * @return never + * @return when the client disconnects **/ int mainloop(CLIENT *client) { struct nbd_request request; @@ -1233,6 +1242,25 @@ int copyonwrite_prepare(CLIENT* client) { } /** + * Run a command. This is used for the ``prerun'' and ``postrun'' config file + * options + * + * @param command the command to be ran. Read from the config file + * @param file the file name we're about to export + **/ +int do_run(gchar* command, gchar* file) { + gchar* cmd; + int retval=0; + + if(*command) { + cmd = g_strdup_printf(command, file); + retval=system(cmd); + g_free(cmd); + } + return retval; +} + +/** * Serve a connection. * * @todo allow for multithreading, perhaps use libevent. Not just yet, though; @@ -1249,7 +1277,10 @@ void serveconnection(CLIENT *client) { setmysockopt(client->net); - mainloop(client); + if(!do_run(client->server->prerun, client->exportname)) { + mainloop(client); + } + do_run(client->server->postrun, client->exportname); } /** @@ -1499,6 +1530,7 @@ int serveloop(GArray* servers) { #endif // NOFORK msg2(LOG_INFO,"Starting to serve"); serveconnection(client); + exit(EXIT_SUCCESS); } } }