Hello community,

here is the log from the commit of package nbd for openSUSE:Factory checked in 
at 2012-05-22 08:16:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/nbd (Old)
 and      /work/SRC/openSUSE:Factory/.nbd.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "nbd", Maintainer is "[email protected]"

Changes:
--------
--- /work/SRC/openSUSE:Factory/nbd/nbd.changes  2012-03-01 17:21:19.000000000 
+0100
+++ /work/SRC/openSUSE:Factory/.nbd.new/nbd.changes     2012-05-22 
08:16:58.000000000 +0200
@@ -1,0 +2,8 @@
+Fri May 18 13:44:05 UTC 2012 - [email protected]
+
+- Update to nbd-3.1
+  * minor bug fixes
+  * new feature: ability for the client to list the exports a server
+    supports
+
+-------------------------------------------------------------------

Old:
----
  nbd-3.0.tar.bz2

New:
----
  nbd-3.1.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ nbd.spec ++++++
--- /var/tmp/diff_new_pack.y74Ox1/_old  2012-05-22 08:16:59.000000000 +0200
+++ /var/tmp/diff_new_pack.y74Ox1/_new  2012-05-22 08:16:59.000000000 +0200
@@ -15,22 +15,20 @@
 # Please submit bugfixes or comments via http://bugs.opensuse.org/
 #
 
-# norootforbuild
-
 
 Name:           nbd
-BuildRequires:  doxygen glib2-devel >= 2.26.0
+BuildRequires:  doxygen
+BuildRequires:  glib2-devel >= 2.26.0
 PreReq:         %insserv_prereq coreutils
-Version:        3.0
-Release:        1
-License:        GPL-2.0+
-Group:          Productivity/Networking/Other
-AutoReqProv:    on
+Version:        3.1
+Release:        0
 Source:         %{name}-%{version}.tar.bz2
 Source2:        init.nbd-server
 Patch2:         nbd-2.9.25-close.diff
 Patch3:         nbd-2.9.25-doxyfile.diff
 Summary:        Network Block Device Server and Client Utilities
+License:        GPL-2.0+
+Group:          Productivity/Networking/Other
 Url:            http://nbd.sourceforge.net/
 Prefix:         /usr
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
@@ -64,7 +62,6 @@
     Paul Clements <[email protected]>
 
 %package doc
-License:        GPL-2.0+
 Summary:        Network Block Device Server and Client Utilities
 Group:          Productivity/Networking/Other
 Requires:       nbd = %{version}

++++++ nbd-3.0.tar.bz2 -> nbd-3.1.tar.bz2 ++++++
++++ 2637 lines of diff (skipped)
++++    retrying with extended exclude list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/README new/nbd-3.1/README
--- old/nbd-3.0/README  2011-10-01 12:28:58.000000000 +0200
+++ new/nbd-3.1/README  2012-05-13 17:15:38.000000000 +0200
@@ -9,8 +9,8 @@
 nbd-server and nbd-client on the same machine, you may run into some
 deadlock issues if you do that[1].
 
-To install the package, please see the INSTALL file. You'll need to
-install it on both the client and the server.
+To install the package, do the normal configure/make/make install dance.
+You'll need to install it on both the client and the server.
 
 Using NBD is quite easy. First, on the client, you need to create the
 device nodes:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/cliserv.h new/nbd-3.1/cliserv.h
--- old/nbd-3.0/cliserv.h       2011-10-01 12:28:58.000000000 +0200
+++ new/nbd-3.1/cliserv.h       2012-05-13 17:15:38.000000000 +0200
@@ -56,6 +56,7 @@
 
 u64 cliserv_magic = 0x00420281861253LL;
 u64 opts_magic = 0x49484156454F5054LL;
+u64 rep_magic = 0x3e889045565a9LL;
 #define INIT_PASSWD "NBDMAGIC"
 
 #define INFO(a) do { } while(0)
@@ -148,4 +149,20 @@
                                         * served */
 
 /* Options that the client can select to the server */
-#define NBD_OPT_EXPORT_NAME    (1 << 0)        /* Client wants to select a 
named export (is followed by length and name of export) */
+#define NBD_OPT_EXPORT_NAME    (1)     /** Client wants to select a named 
export (is followed by name of export) */
+#define NBD_OPT_ABORT          (2)     /** Client wishes to abort negotiation 
*/
+#define NBD_OPT_LIST           (3)     /** Client request list of supported 
exports (not followed by data) */
+
+/* Replies the server can send during negotiation */
+#define NBD_REP_ACK            (1)     /** ACK a request. Data: option number 
to be acked */
+#define NBD_REP_SERVER         (2)     /** Reply to NBD_OPT_LIST (one of these 
per server; must be followed by NBD_REP_ACK to signal the end of the list */
+#define NBD_REP_FLAG_ERROR     (1 << 31)       /** If the high bit is set, the 
reply is an error */
+#define NBD_REP_ERR_UNSUP      (1 | NBD_REP_FLAG_ERROR)        /** Client 
requested an option not understood by this version of the server */
+#define NBD_REP_ERR_POLICY     (2 | NBD_REP_FLAG_ERROR)        /** Client 
requested an option not allowed by server configuration. (e.g., the option was 
disabled) */
+#define NBD_REP_ERR_INVALID    (3 | NBD_REP_FLAG_ERROR)        /** Client 
issued an invalid request */
+#define NBD_REP_ERR_PLATFORM   (4 | NBD_REP_FLAG_ERROR)        /** Option not 
supported on this platform */
+
+/* Global flags */
+#define NBD_FLAG_FIXED_NEWSTYLE (1 << 0)       /* new-style export that 
actually supports extending */
+/* Flags from client to server. Only one such option currently. */
+#define NBD_FLAG_C_FIXED_NEWSTYLE NBD_FLAG_FIXED_NEWSTYLE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/configure.ac new/nbd-3.1/configure.ac
--- old/nbd-3.0/configure.ac    2012-02-21 11:04:29.000000000 +0100
+++ new/nbd-3.1/configure.ac    2012-05-15 09:43:33.000000000 +0200
@@ -1,7 +1,7 @@
 dnl Configure script for NBD system
 dnl (c) 1998 Martin Mares <[email protected]>, (c) 2000 Pavel Machek <[email protected]>,
 dnl (c) 2003-2006 Wouter Verhelst <[email protected]>
-AC_INIT([nbd],[3.0],[[email protected]])
+AC_INIT([nbd],[3.1],[[email protected]])
 AM_INIT_AUTOMAKE(foreign dist-bzip2)
 AM_MAINTAINER_MODE
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/man/nbd-client.8.in.sgml new/nbd-3.1/man/nbd-client.8.in.sgml
--- old/nbd-3.0/man/nbd-client.8.in.sgml        2011-10-01 12:28:58.000000000 
+0200
+++ new/nbd-3.1/man/nbd-client.8.in.sgml        2012-05-15 09:55:51.000000000 
+0200
@@ -74,6 +74,10 @@
       <command>&dhpackage;</command>
       <arg choice="plain"><option>-c 
<replaceable>nbd-device</replaceable></option></arg>
     </cmdsynopsis>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <arg choice="plain"><option>-l 
<replaceable>host</replaceable></option></arg>
+    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
     <title>DESCRIPTION</title>
@@ -167,6 +171,22 @@
        </listitem>
       </varlistentry>
       <varlistentry>
+        <term><option>-list</option></term>
+       <term><option>-l</option></term>
+       <listitem>
+         <para>
+           Ask the server for a list of available exports. If the
+           server is exporting over IPv6 as well as over IPv4, this
+           will list all exports twice; otherwise, it should list them
+           all only once.</para>
+         <para>Note that this option <emph>only</emph> works
+           with nbd-server processes running version 3.1 or above, and
+           must be enabled in server configuration (with the
+           "allowlist" option) before it can be used.
+         </para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
        <term><option>-persist</option></term>
        <term><option>-p</option></term>
        <listitem>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/man/nbd-client.8.sh.in new/nbd-3.1/man/nbd-client.8.sh.in
--- old/nbd-3.0/man/nbd-client.8.sh.in  2011-10-01 12:31:44.000000000 +0200
+++ new/nbd-3.1/man/nbd-client.8.sh.in  2012-05-15 09:57:47.000000000 +0200
@@ -10,7 +10,7 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <[email protected]>.
-.TH "NBD-CLIENT" "8" "01 October 2011" "" ""
+.TH "NBD-CLIENT" "8" "$Date$" "" ""
 
 .SH NAME
 nbd-client \- connect to a server running nbd-server(1), to use its    
exported block device
@@ -24,6 +24,9 @@
 
 \fBnbd-client\fR \fB-c \fInbd-device\fB\fR
 
+
+\fBnbd-client\fR \fB-l \fIhost\fB\fR
+
 .SH "DESCRIPTION"
 .PP
 With \fBnbd-client\fR, you can connect to a
@@ -97,6 +100,19 @@
 Disconnect the specified nbd device from the
 server
 .TP
+\fB-list\fR
+.TP
+\fB-l\fR
+Ask the server for a list of available exports. If the
+server is exporting over IPv6 as well as over IPv4, this
+will list all exports twice; otherwise, it should list them
+all only once.
+
+Note that this option only works
+with nbd-server processes running version 3.1 or above, and
+must be enabled in server configuration (with the
+"allowlist" option) before it can be used.
+.TP
 \fB-persist\fR
 .TP
 \fB-p\fR
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/man/nbd-server.5.in.sgml new/nbd-3.1/man/nbd-server.5.in.sgml
--- old/nbd-3.0/man/nbd-server.5.in.sgml        2011-11-29 08:54:43.000000000 
+0100
+++ new/nbd-3.1/man/nbd-server.5.in.sgml        2012-05-15 09:57:45.000000000 
+0200
@@ -110,6 +110,18 @@
     <!-- These are in alphabetical order, please keep it that way -->    
     <variablelist>
       <varlistentry>
+        <term><option>allowlist</option></term>
+       <listitem>
+         <para>
+           Optional; boolean
+          </para>
+          <para>
+            Whether to allow the client to fetch a list of exports from
+            this server. If enabled, the client can run
+            <command>nbd-client -l</command> to get a list of exports
+            on this server.
+          </para>
+      <varlistentry>
        <term><option>group</option></term>
        <listitem>
          <para>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/man/nbd-server.5.sh.in new/nbd-3.1/man/nbd-server.5.sh.in
--- old/nbd-3.0/man/nbd-server.5.sh.in  2011-11-29 08:58:20.000000000 +0100
+++ new/nbd-3.1/man/nbd-server.5.sh.in  2012-05-15 09:57:47.000000000 +0200
@@ -10,7 +10,7 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <[email protected]>.
-.TH "NBD-SERVER" "5" "29 November 2011" "" ""
+.TH "NBD-SERVER" "5" "$Date: 2006-10-18 15:01:57 +0200 (wo, 18 okt 2006) $" "" 
""
 
 .SH NAME
 $sysconfdir/nbd-server/config \- configuration file for nbd-server
@@ -59,6 +59,14 @@
 leading whitespace is stripped (but trailing whitespace is not).
 .SH "OPTIONS FOR SECTION [GENERIC]"
 .TP
+\fBallowlist\fR
+Optional; boolean
+
+Whether to allow the client to fetch a list of exports from
+this server. If enabled, the client can run
+\fBnbd-client -l\fR to get a list of exports
+on this server.
+.TP
 \fBgroup\fR
 Optional; string.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/nbd-client.c new/nbd-3.1/nbd-client.c
--- old/nbd-3.0/nbd-client.c    2012-02-21 11:03:32.000000000 +0100
+++ new/nbd-3.1/nbd-client.c    2012-05-13 17:15:38.000000000 +0200
@@ -46,14 +46,16 @@
 #include <sdp_inet.h>
 #endif
 
+#define NBDC_DO_LIST 1
+
 int check_conn(char* devname, int do_print) {
        char buf[256];
        char* p;
        int fd;
        int len;
 
-       if(!strncmp(devname, "/dev/", 5)) {
-               devname+=5;
+       if( (p=strrchr(devname, '/')) ) {
+               devname=p+1;
        }
        if((p=strchr(devname, 'p'))) {
                /* We can't do checks on partitions. */
@@ -124,7 +126,96 @@
        return sock;
 }
 
-void negotiate(int sock, u64 *rsize64, u32 *flags, char* name) {
+void ask_list(int sock) {
+       uint32_t opt;
+       uint32_t opt_server;
+       uint32_t len;
+       uint32_t reptype;
+       uint64_t magic;
+       char buf[1024];
+
+       magic = ntohll(opts_magic);
+       if (write(sock, &magic, sizeof(magic)) < 0)
+               err("Failed/2.2: %m");
+
+       /* Ask for the list */
+       opt = htonl(NBD_OPT_LIST);
+       if(write(sock, &opt, sizeof(opt)) < 0) {
+               err("writing list option failed: %m");
+       }
+       /* Send the length (zero) */
+       len = htonl(0);
+       if(write(sock, &len, sizeof(len)) < 0) {
+               err("writing length failed: %m");
+       }
+       /* newline, move away from the "Negotiation:" line */
+       printf("\n");
+       do {
+               memset(buf, 0, 1024);
+               if(read(sock, &magic, sizeof(magic)) < 0) {
+                       err("Reading magic from server: %m");
+               }
+               if(read(sock, &opt_server, sizeof(opt_server)) < 0) {
+                       err("Reading option: %m");
+               }
+               if(read(sock, &reptype, sizeof(reptype)) <0) {
+                       err("Reading reply from server: %m");
+               }
+               if(read(sock, &len, sizeof(len)) < 0) {
+                       err("Reading length from server: %m");
+               }
+               magic=ntohll(magic);
+               len=ntohl(len);
+               reptype=ntohl(reptype);
+               if(magic != rep_magic) {
+                       err("Not enough magic from server");
+               }
+               if(reptype & NBD_REP_FLAG_ERROR) {
+                       switch(reptype) {
+                               case NBD_REP_ERR_POLICY:
+                                       fprintf(stderr, "\nE: listing not 
allowed by server.\n");
+                                       break;
+                               default:
+                                       fprintf(stderr, "\nE: unexpected error 
from server.\n");
+                                       break;
+                       }
+                       if(len) {
+                               if(read(sock, buf, len) < 0) {
+                                       fprintf(stderr, "\nE: could not read 
error message from server\n");
+                               }
+                               fprintf(stderr, "Server said: %s\n", buf);
+                       }
+                       exit(EXIT_FAILURE);
+               } else {
+                       if(len) {
+                               if(reptype != NBD_REP_SERVER) {
+                                       err("Server sent us a reply we don't 
understand!");
+                               }
+                               if(read(sock, &len, sizeof(len)) < 0) {
+                                       fprintf(stderr, "\nE: could not read 
export name length from server\n");
+                                       exit(EXIT_FAILURE);
+                               }
+                               len=ntohl(len);
+                               if(read(sock, buf, len) < 0) {
+                                       fprintf(stderr, "\nE: could not read 
export name from server\n");
+                                       exit(EXIT_FAILURE);
+                               }
+                               printf("%s\n", buf);
+                       }
+               }
+       } while(reptype != NBD_REP_ACK);
+       opt=htonl(NBD_OPT_ABORT);
+       len=htonl(0);
+       magic=htonll(opts_magic);
+       if (write(sock, &magic, sizeof(magic)) < 0)
+               err("Failed/2.2: %m");
+       if (write(sock, &opt, sizeof(opt)) < 0)
+               err("Failed writing abort");
+       if (write(sock, &len, sizeof(len)) < 0)
+               err("Failed writing length");
+}
+
+void negotiate(int sock, u64 *rsize64, u32 *flags, char* name, uint32_t 
needed_flags, uint32_t client_flags, uint32_t do_opts) {
        u64 magic, size64;
        uint16_t tmp;
        char buf[256] = "\0\0\0\0\0\0\0\0\0";
@@ -143,7 +234,6 @@
        if(name) {
                uint32_t opt;
                uint32_t namesize;
-               uint32_t reserved = 0;
 
                if (magic != opts_magic)
                        err("Not enough opts_magic");
@@ -152,15 +242,28 @@
                        err("Failed reading flags: %m");
                }
                *flags = ((u32)ntohs(tmp));
+               if((needed_flags & *flags) != needed_flags) {
+                       /* There's currently really only one reason why this
+                        * check could possibly fail, but we may need to change
+                        * this error message in the future... */
+                       fprintf(stderr, "\nE: Server does not support listing 
exports\n");
+                       exit(EXIT_FAILURE);
+               }
 
-               /* reserved for future use*/
-               if (write(sock, &reserved, sizeof(reserved)) < 0)
+               client_flags = htonl(client_flags);
+               if (write(sock, &client_flags, sizeof(client_flags)) < 0)
                        err("Failed/2.1: %m");
 
+               if(do_opts & NBDC_DO_LIST) {
+                       ask_list(sock);
+                       exit(EXIT_SUCCESS);
+               }
+
                /* Write the export name that we're after */
-               magic = ntohll(opts_magic);
+               magic = htonll(opts_magic);
                if (write(sock, &magic, sizeof(magic)) < 0)
                        err("Failed/2.2: %m");
+
                opt = ntohl(NBD_OPT_EXPORT_NAME);
                if (write(sock, &opt, sizeof(opt)) < 0)
                        err("Failed/2.3: %m");
@@ -273,7 +376,7 @@
                va_list ap;
                va_start(ap, errmsg);
                snprintf(tmp, 256, "ERROR: %s\n\n", errmsg);
-               vfprintf(stderr, errmsg, ap);
+               vfprintf(stderr, tmp, ap);
                va_end(ap);
        } else {
                fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
@@ -283,6 +386,7 @@
        fprintf(stderr, "Or   : nbd-client -d nbd_device\n");
        fprintf(stderr, "Or   : nbd-client -c nbd_device\n");
        fprintf(stderr, "Or   : nbd-client -h|--help\n");
+       fprintf(stderr, "Or   : nbd-client -l|--list host\n");
        fprintf(stderr, "Default value for blocksize is 1024 (recommended for 
ethernet)\n");
        fprintf(stderr, "Allowed values for blocksize are 
512,1024,2048,4096\n"); /* will be checked in kernel :) */
        fprintf(stderr, "Note, that kernel 2.4.2 and older ones do not work 
correctly with\n");
@@ -328,11 +432,15 @@
        int c;
        int nonspecial=0;
        char* name=NULL;
+       uint32_t needed_flags;
+       uint32_t cflags;
+       uint32_t opts;
        struct option long_options[] = {
                { "block-size", required_argument, NULL, 'b' },
                { "check", required_argument, NULL, 'c' },
                { "disconnect", required_argument, NULL, 'd' },
                { "help", no_argument, NULL, 'h' },
+               { "list", no_argument, NULL, 'l' },
                { "name", required_argument, NULL, 'N' },
                { "nofork", no_argument, NULL, 'n' },
                { "persist", no_argument, NULL, 'p' },
@@ -344,7 +452,7 @@
 
        logging();
 
-       while((c=getopt_long_only(argc, argv, "-b:c:d:hnN:pSst:", long_options, 
NULL))>=0) {
+       while((c=getopt_long_only(argc, argv, "-b:c:d:hlnN:pSst:", 
long_options, NULL))>=0) {
                switch(c) {
                case 1:
                        // non-option argument
@@ -399,6 +507,14 @@
                case 'h':
                        usage(NULL);
                        exit(EXIT_SUCCESS);
+               case 'l':
+                       needed_flags |= NBD_FLAG_FIXED_NEWSTYLE;
+                       cflags |= NBD_FLAG_C_FIXED_NEWSTYLE;
+                       opts |= NBDC_DO_LIST;
+                       name="";
+                       nbddev="";
+                       port = NBD_DEFAULT_PORT;
+                       break;
                case 'n':
                        nofork=1;
                        break;
@@ -432,13 +548,14 @@
                exit(EXIT_FAILURE);
        }
 
+       sock = opennet(hostname, port, sdp);
+
+       negotiate(sock, &size64, &flags, name, needed_flags, cflags, opts);
+
        nbd = open(nbddev, O_RDWR);
        if (nbd < 0)
          err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
 
-       sock = opennet(hostname, port, sdp);
-
-       negotiate(sock, &size64, &flags, name);
        setsizes(nbd, size64, blocksize, flags);
        set_timeout(nbd, timeout);
        finish_sock(sock, nbd, swap);
@@ -474,8 +591,9 @@
 #endif
 
                if (ioctl(nbd, NBD_DO_IT) < 0) {
-                       fprintf(stderr, "Kernel call returned: %m");
-                       if(errno==EBADR) {
+                       int error = errno;
+                       fprintf(stderr, "nbd,%d: Kernel call returned: %d", 
getpid(), error);
+                       if(error==EBADR) {
                                /* The user probably did 'nbd-client -d' on us.
                                 * quit */
                                cont=0;
@@ -488,7 +606,7 @@
                                        close(sock); close(nbd);
                                        sock = opennet(hostname, port, sdp);
                                        nbd = open(nbddev, O_RDWR);
-                                       negotiate(sock, &new_size, &new_flags, 
name);
+                                       negotiate(sock, &new_size, &new_flags, 
name, needed_flags, cflags, opts);
                                        if (size64 != new_size) {
                                                err("Size of the device 
changed. Bye");
                                        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/nbd-server.c new/nbd-3.1/nbd-server.c
--- old/nbd-3.0/nbd-server.c    2012-02-21 11:04:29.000000000 +0100
+++ new/nbd-3.1/nbd-server.c    2012-05-13 17:15:38.000000000 +0200
@@ -59,6 +59,7 @@
  * headers, so must come before those */
 #include "lfs.h"
 
+#include <assert.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -118,8 +119,8 @@
 gchar* runuser=NULL;
 /** What group we're running as */
 gchar* rungroup=NULL;
-/** whether to export using the old negotiation protocol (port-based) */
-gboolean do_oldstyle=FALSE;
+/** global flags */
+int glob_flags=0;
 
 /* Whether we should avoid forking */
 int dontfork = 0;
@@ -154,6 +155,8 @@
                               authorization file (yuck) */
 #define BUFSIZE ((1024*1024)+sizeof(struct nbd_reply)) /**< Size of buffer 
that can hold requests */
 #define DIFFPAGESIZE 4096 /**< diff file uses those chunks */
+
+/** Per-export flags: */
 #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
@@ -167,6 +170,11 @@
 #define F_ROTATIONAL 512  /**< Whether server wants the client to implement 
the elevator algorithm */
 #define F_TEMPORARY 1024  /**< Whether the backing file is temporary and 
should be created then unlinked */
 #define F_TRIM 2048       /**< Whether server wants TRIM (discard) to be sent 
by the client */
+#define F_FIXED 4096     /**< Client supports fixed new-style protocol (and 
can thus send us extra options */
+
+/** Global flags: */
+#define F_OLDSTYLE 1     /**< Allow oldstyle (port-based) exports */
+#define F_LIST 2         /**< Allow clients to list the exports on a server */
 GHashTable *children;
 char pidfname[256]; /**< name of our PID file */
 char pidftemplate[256]; /**< template to be used for the filename of the PID 
file */
@@ -248,6 +256,7 @@
        u32 *difmap;         /**< see comment on the global difmap for this one 
*/
        gboolean modern;     /**< client was negotiated using modern 
negotiation protocol */
        int transactionlogfd;/**< fd for transaction log */
+       int clientfeats;     /**< Features supported by this client */
 } CLIENT;
 
 /**
@@ -588,7 +597,7 @@
                g_free(serve);
                serve=NULL;
        } else {
-               do_oldstyle = TRUE;
+               glob_flags |= F_OLDSTYLE;
        }
        if(do_output) {
                if(!serve) {
@@ -768,6 +777,7 @@
        gchar* fname;
        GArray* retval = NULL;
        GArray* tmp;
+       struct stat stbuf;
 
        if(!dir) {
                g_set_error(e, errdomain, CFILE_DIR_UNKNOWN, "Invalid directory 
specified: %s", strerror(errno));
@@ -776,13 +786,24 @@
        errno=0;
        while((de = readdir(dirh))) {
                int saved_errno=errno;
+               fname = g_build_filename(dir, de->d_name, NULL);
                switch(de->d_type) {
+                       case DT_UNKNOWN:
+                               /* Filesystem doesn't return type of
+                                * file through readdir. Run stat() on
+                                * the file instead */
+                               if(stat(fname, &stbuf)) {
+                                       perror("stat");
+                                       goto err_out;
+                               }
+                               if (!S_ISREG(stbuf.st_mode)) {
+                                       goto next;
+                               }
                        case DT_REG:
                                /* Skip unless the name ends with '.conf' */
                                if(strcmp((de->d_name + strlen(de->d_name) - 
5), ".conf")) {
                                        continue;
                                }
-                               fname = g_build_filename(dir, de->d_name, NULL);
                                tmp = parse_cfile(fname, FALSE, e);
                                errno=saved_errno;
                                if(*e) {
@@ -792,10 +813,11 @@
                                        retval = g_array_new(FALSE, TRUE, 
sizeof(SERVER));
                                retval = g_array_append_vals(retval, tmp->data, 
tmp->len);
                                g_array_free(tmp, TRUE);
-                               g_free(fname);
                        default:
                                break;
                }
+       next:
+               g_free(fname);
        }
        if(errno) {
                g_set_error(e, errdomain, CFILE_READDIR_ERR, "Error trying to 
read directory: %s", strerror(errno));
@@ -850,10 +872,11 @@
        PARAM gp[] = {
                { "user",       FALSE, PARAM_STRING,    &runuser,       0 },
                { "group",      FALSE, PARAM_STRING,    &rungroup,      0 },
-               { "oldstyle",   FALSE, PARAM_BOOL,      &do_oldstyle,   1 },
+               { "oldstyle",   FALSE, PARAM_BOOL,      &glob_flags,    
F_OLDSTYLE },
                { "listenaddr", FALSE, PARAM_STRING,    &modern_listen, 0 },
                { "port",       FALSE, PARAM_STRING,    &modernport,    0 },
                { "includedir", FALSE, PARAM_STRING,    &cfdir,         0 },
+               { "allowlist",  FALSE, PARAM_BOOL,      &glob_flags,    F_LIST 
},
        };
        PARAM* p=gp;
        int p_size=sizeof(gp)/sizeof(PARAM);
@@ -895,13 +918,13 @@
                if(i==1 || !have_global) {
                        p=lp;
                        p_size=lp_size;
-                       if(!do_oldstyle) {
+                       if(!(glob_flags & F_OLDSTYLE)) {
                                lp[1].required = FALSE;
                        }
                } 
                for(j=0;j<p_size;j++) {
-                       g_assert(p[j].target != NULL);
-                       
g_assert(p[j].ptype==PARAM_INT||p[j].ptype==PARAM_STRING||p[j].ptype==PARAM_BOOL||p[j].ptype==PARAM_INT64);
+                       assert(p[j].target != NULL);
+                       
assert(p[j].ptype==PARAM_INT||p[j].ptype==PARAM_STRING||p[j].ptype==PARAM_BOOL||p[j].ptype==PARAM_INT64);
                        switch(p[j].ptype) {
                                case PARAM_INT:
                                        ival = g_key_file_get_integer(cfile,
@@ -987,7 +1010,7 @@
                } else {
                        s.virtstyle=VIRT_IPLIT;
                }
-               if(s.port && !do_oldstyle) {
+               if(s.port && !(glob_flags & F_OLDSTYLE)) {
                        g_warning("A port was specified, but oldstyle exports 
were not requested. This may not do what you expect.");
                        g_warning("Please read 'man 5 nbd-server' and search 
for oldstyle for more info");
                }
@@ -1168,7 +1191,7 @@
        }
 
        /* end should never go negative, since first startoff is 0 and a >= 0 */
-       g_assert(end >= 0);
+       assert(end >= 0);
 
        fi = g_array_index(export, FILE_INFO, end);
        *fhandle = fi.fhandle;
@@ -1485,6 +1508,77 @@
        return 0;
 }
 
+static void send_reply(uint32_t opt, int net, uint32_t reply_type, size_t 
datasize, void* data) {
+       uint64_t magic = htonll(0x3e889045565a9LL);
+       reply_type = htonl(reply_type);
+       uint32_t datsize = htonl(datasize);
+       struct iovec v_data[] = {
+               { &magic, sizeof(magic) },
+               { &opt, sizeof(opt) },
+               { &reply_type, sizeof(reply_type) },
+               { &datsize, sizeof(datsize) },
+               { data, datasize },
+       };
+       writev(net, v_data, 5);
+}
+
+static CLIENT* handle_export_name(uint32_t opt, int net, GArray* servers, 
uint32_t cflags) {
+       uint32_t namelen;
+       char* name;
+       int i;
+
+       if (read(net, &namelen, sizeof(namelen)) < 0)
+               err("Negotiation failed/7: %m");
+       namelen = ntohl(namelen);
+       name = malloc(namelen+1);
+       name[namelen]=0;
+       if (read(net, name, namelen) < 0)
+               err("Negotiation failed/8: %m");
+       for(i=0; i<servers->len; i++) {
+               SERVER* serve = &(g_array_index(servers, SERVER, i));
+               if(!strcmp(serve->servename, name)) {
+                       CLIENT* client = g_new0(CLIENT, 1);
+                       client->server = serve;
+                       client->exportsize = OFFT_MAX;
+                       client->net = net;
+                       client->modern = TRUE;
+                       client->transactionlogfd = -1;
+                       client->clientfeats = cflags;
+                       free(name);
+                       return client;
+               }
+       }
+       free(name);
+       return NULL;
+}
+
+static void handle_list(uint32_t opt, int net, GArray* servers, uint32_t 
cflags) {
+       uint32_t len;
+       int i;
+       char buf[1024];
+       char *ptr = buf + sizeof(len);
+
+       if (read(net, &len, sizeof(len)) < 0)
+               err("Negotiation failed/8: %m");
+       len = ntohl(len);
+       if(len) {
+               send_reply(opt, net, NBD_REP_ERR_INVALID, 0, NULL);
+       }
+       if(!(glob_flags & F_LIST)) {
+               send_reply(opt, net, NBD_REP_ERR_POLICY, 0, NULL);
+               err_nonfatal("Client tried disallowed list option");
+               return;
+       }
+       for(i=0; i<servers->len; i++) {
+               SERVER* serve = &(g_array_index(servers, SERVER, i));
+               len = htonl(strlen(serve->servename));
+               memcpy(buf, &len, sizeof(len));
+               strcpy(ptr, serve->servename);
+               send_reply(opt, net, NBD_REP_SERVER, 
strlen(serve->servename)+sizeof(len), buf);
+       }
+       send_reply(opt, net, NBD_REP_ACK, 0, NULL);
+}
+
 /**
  * Do the initial negotiation.
  *
@@ -1498,7 +1592,10 @@
        uint64_t magic;
 
        memset(zeros, '\0', sizeof(zeros));
-       g_assert(((phase & NEG_INIT) && (phase & NEG_MODERN)) || client);
+       assert(((phase & NEG_INIT) && (phase & NEG_MODERN)) || client);
+       if(phase & NEG_MODERN) {
+               smallflags |= NBD_FLAG_FIXED_NEWSTYLE;
+       }
        if(phase & NEG_INIT) {
                /* common */
                if (write(net, INIT_PASSWD, 8) < 0) {
@@ -1521,54 +1618,50 @@
        }
        if ((phase & NEG_MODERN) && (phase & NEG_INIT)) {
                /* modern */
-               uint32_t reserved;
+               uint32_t cflags;
                uint32_t opt;
-               uint32_t namelen;
-               char* name;
-               int i;
 
                if(!servers)
                        err("programmer error");
+               smallflags = htons(smallflags);
                if (write(net, &smallflags, sizeof(uint16_t)) < 0)
-                       err("Negotiation failed/3: %m");
-               if (read(net, &reserved, sizeof(reserved)) < 0)
-                       err("Negotiation failed/4: %m");
-               if (read(net, &magic, sizeof(magic)) < 0)
-                       err("Negotiation failed/5: %m");
-               magic = ntohll(magic);
-               if(magic != opts_magic) {
-                       close(net);
-                       return NULL;
-               }
-               if (read(net, &opt, sizeof(opt)) < 0)
-                       err("Negotiation failed/6: %m");
-               opt = ntohl(opt);
-               if(opt != NBD_OPT_EXPORT_NAME) {
+                       err_nonfatal("Negotiation failed/3: %m");
+               if (read(net, &cflags, sizeof(cflags)) < 0)
+                       err_nonfatal("Negotiation failed/4: %m");
+               cflags = htonl(cflags);
+               do {
+                       if (read(net, &magic, sizeof(magic)) < 0)
+                               err_nonfatal("Negotiation failed/5: %m");
+                       magic = ntohll(magic);
+                       if(magic != opts_magic) {
+                               close(net);
+                               return NULL;
+                       }
+                       if (read(net, &opt, sizeof(opt)) < 0)
+                               err_nonfatal("Negotiation failed/6: %m");
+                       opt = ntohl(opt);
+                       switch(opt) {
+                       case NBD_OPT_EXPORT_NAME:
+                               // NBD_OPT_EXPORT_NAME must be the last
+                               // selected option, so return from here
+                               // if that is chosen.
+                               return handle_export_name(opt, net, servers, 
cflags);
+                               break;
+                       case NBD_OPT_LIST:
+                               handle_list(opt, net, servers, cflags);
+                               break;
+                       case NBD_OPT_ABORT:
+                               // handled below
+                               break;
+                       default:
+                               send_reply(opt, net, NBD_REP_ERR_UNSUP, 0, 
NULL);
+                               break;
+                       }
+               } while((opt != NBD_OPT_EXPORT_NAME) && (opt != NBD_OPT_ABORT));
+               if(opt == NBD_OPT_ABORT) {
                        close(net);
                        return NULL;
                }
-               if (read(net, &namelen, sizeof(namelen)) < 0)
-                       err("Negotiation failed/7: %m");
-               namelen = ntohl(namelen);
-               name = malloc(namelen+1);
-               name[namelen]=0;
-               if (read(net, name, namelen) < 0)
-                       err("Negotiation failed/8: %m");
-               for(i=0; i<servers->len; i++) {
-                       SERVER* serve = &(g_array_index(servers, SERVER, i));
-                       if(!strcmp(serve->servename, name)) {
-                               CLIENT* client = g_new0(CLIENT, 1);
-                               client->server = serve;
-                               client->exportsize = OFFT_MAX;
-                               client->net = net;
-                               client->modern = TRUE;
-                               client->transactionlogfd = -1;
-                               free(name);
-                               return client;
-                       }
-               }
-               free(name);
-               return NULL;
        }
        /* common */
        size_host = htonll((u64)(client->exportsize));
@@ -1852,11 +1945,11 @@
 
                /* If we created the file, it will be length zero */
                if (!lastsize && cancreate) {
-                       /* we can ignore errors as we recalculate the size */
-                       ftruncate (fi.fhandle, client->server->expected_size);
-                       lastsize = size_autodetect(fi.fhandle);
-                       if (lastsize != client->server->expected_size)
-                               err("Could not expand file");
+                       assert(!multifile);
+                       if(ftruncate (fi.fhandle, 
client->server->expected_size)<0) {
+                               err("Could not expand file: %m");
+                       }
+                       lastsize = client->server->expected_size;
                        break; /* don't look for any more files */
                }
 
@@ -2233,7 +2326,7 @@
        gchar *port = NULL;
        int e;
 
-       if(!do_oldstyle) {
+       if(!(glob_flags & F_OLDSTYLE)) {
                return serve->servename ? 1 : 0;
        }
        memset(&hints,'\0',sizeof(hints));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/nbd-3.0/nbd-tester-client.c new/nbd-3.1/nbd-tester-client.c
--- old/nbd-3.0/nbd-tester-client.c     2011-10-01 12:28:58.000000000 +0200
+++ new/nbd-3.1/nbd-tester-client.c     2012-05-13 17:15:42.000000000 +0200
@@ -605,7 +605,7 @@
                                        goto err_open;
                                }
                        }
-                       printf("%d: Requests(+): %d\n", (int)mypid, ++requests);
+                       printf("%d: Requests(+): %d\r", (int)mypid, ++requests);
                        if (sendflush) {
                                long long int j = i ^ (1LL<<63);
                                req.type = htonl(NBD_CMD_FLUSH);
@@ -615,7 +615,7 @@
                                        retval=-1;
                                        goto err_open;
                                }
-                               printf("%d: Requests(+): %d\n", (int)mypid, 
++requests);
+                               printf("%d: Requests(+): %d\r", (int)mypid, 
++requests);
                        }
                }
                do {
@@ -631,7 +631,7 @@
                                        retval=-1;
                                        goto err_open;
                                }
-                               printf("%d: Requests(-): %d\n", (int)mypid, 
--requests);
+                               printf("%d: Requests(-): %d\r", (int)mypid, 
--requests);
                        }
                } while FD_ISSET(sock, &set);
                /* Now wait until we can write again or until a second have
@@ -659,9 +659,10 @@
                        /* Okay, there's something ready for
                         * reading here */
                        read_packet_check_header(sock, (testflags & 
TEST_WRITE)?0:1024, i);
-                       printf("%d: Requests(-): %d\n", (int)mypid, --requests);
+                       printf("%d: Requests(-): %d\r", (int)mypid, --requests);
                }
        } while (requests);
+       printf("\n");
        if(gettimeofday(&stop, NULL)<0) {
                retval=-1;
                snprintf(errstr, errstr_len, "Could not measure end time: %s", 
strerror(errno));
@@ -714,8 +715,8 @@
 }
                
 static inline int checkbuf(char *buf, uint64_t seq, uint64_t blknum) {
-       char cmp[512];
-       makebuf(cmp, seq, blknum);
+       uint64_t cmp[64]; // 512/8 = 64
+       makebuf((char *)cmp, seq, blknum);
        return memcmp(cmp, buf, 512)?-1:0;
 }
 
@@ -1100,13 +1101,15 @@
                                goto err_open;
                        }
                                
-                       prc = g_hash_table_lookup(handlehash, rep.handle);
+                       uint64_t handle;
+                       memcpy(&handle,rep.handle,8);
+                       prc = g_hash_table_lookup(handlehash, &handle);
                        if (!prc) {
                                retval=-1;
                                snprintf(errstr, errstr_len, "Unrecognised 
handle in reply: 0x%llX", *(long long unsigned int*)(rep.handle));
                                goto err_open;
                        }
-                       if (!g_hash_table_remove(handlehash, rep.handle)) {
+                       if (!g_hash_table_remove(handlehash, &handle)) {
                                retval=-1;
                                snprintf(errstr, errstr_len, "Could not remove 
handle from hash: 0x%llX", *(long long unsigned int*)(rep.handle));
                                goto err_open;
@@ -1185,7 +1188,7 @@
                }
 
                if (!(printer++ % 1000) || !(readtransactionfile || 
txqueue.numitems || inflight.numitems) )
-                       printf("%d: Seq %08lld Queued: %08d Inflight: %08d 
Done: %08lld\n",
+                       printf("%d: Seq %08lld Queued: %08d Inflight: %08d 
Done: %08lld\r",
                               (int)mypid,
                               (long long int) seq,
                               txqueue.numitems,
@@ -1194,6 +1197,8 @@
 
        }
 
+       printf("\n");
+
        if (gettimeofday(&stop, NULL)<0) {
                retval=-1;
                snprintf(errstr, errstr_len, "Could not measure end time: %s", 
strerror(errno));

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to