Merge branch 'master' into names
authorWouter Verhelst <w@uter.be>
Tue, 27 Jul 2010 22:54:37 +0000 (18:54 -0400)
committerWouter Verhelst <w@uter.be>
Tue, 27 Jul 2010 22:54:37 +0000 (18:54 -0400)
1  2 
nbd-client.c

diff --combined nbd-client.c
@@@ -35,7 -35,6 +35,7 @@@
  #include <sys/mman.h>
  #include <errno.h>
  #include <getopt.h>
 +#include <stdarg.h>
  
  #ifndef __GNUC__
  #error I need GCC to work
@@@ -72,13 -71,16 +72,13 @@@ int check_conn(char* devname, int do_pr
        return 0;
  }
  
 -int opennet(char *name, int port, int sdp) {
 +int opennet(char *name, char* portstr, int sdp) {
        int sock;
 -      char portstr[6];
        struct addrinfo hints;
        struct addrinfo *ai = NULL;
        struct addrinfo *rp = NULL;
        int e;
  
 -      snprintf(portstr, sizeof(portstr), "%d", port);
 -
        memset(&hints,'\0',sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        return sock;
  }
  
 -void negotiate(int sock, u64 *rsize64, u32 *flags) {
 +void negotiate(int sock, u64 *rsize64, u32 *flags, char* name) {
        u64 magic, size64;
 +      uint16_t tmp;
        char buf[256] = "\0\0\0\0\0\0\0\0\0";
  
        printf("Negotiation: ");
        if (read(sock, &magic, sizeof(magic)) < 0)
                err("Failed/2: %m");
        magic = ntohll(magic);
 -      if (magic != cliserv_magic)
 -              err("Not enough cliserv_magic");
 -      printf(".");
 +      if(name) {
 +              uint32_t opt;
 +              uint64_t namesize;
 +              uint64_t reserved = 0;
 +
 +              if (magic != opts_magic)
 +                      err("Not enough opts_magic");
 +              printf(".");
 +              if(read(sock, &tmp, sizeof(uint16_t)) < 0) {
 +                      err("Failed reading flags: %m");
 +              }
 +              *flags = ((u32)ntohs(tmp)) << 16;
 +
 +              /* reserved for future use*/
 +              write(sock, &reserved, sizeof(reserved));
 +
 +              /* Write the export name that we're after */
 +              magic = ntohll(cliserv_magic);
 +              write(sock, &magic, sizeof(magic));
 +              opt = ntohl(NBD_OPT_EXPORT_NAME);
 +              write(sock, &opt, sizeof(opt));
 +              namesize = (u64)strlen(name);
 +              namesize = ntohll(namesize);
 +              write(sock, &namesize, sizeof(namesize));
 +              write(sock, name, strlen(name));
 +      } else {
 +              if (magic != cliserv_magic)
 +                      err("Not enough cliserv_magic");
 +              printf(".");
 +      }
  
        if (read(sock, &size64, sizeof(size64)) < 0)
                err("Failed/3: %m\n");
                printf("size = %lu", (unsigned long)(size64));
  #endif
  
 -      if (read(sock, flags, sizeof(*flags)) < 0)
 -              err("Failed/4: %m\n");
 -      *flags = ntohl(*flags);
 +      if(!name) {
 +              if (read(sock, flags, sizeof(*flags)) < 0)
 +                      err("Failed/4: %m\n");
 +              *flags = ntohl(*flags);
 +      } else {
 +              if(read(sock, &tmp, sizeof(tmp)) < 0)
 +                      err("Failed/4: %m\n");
 +              *flags |= (uint32_t)ntohs(tmp);
 +      }
  
        if (read(sock, &buf, 124) < 0)
                err("Failed/5: %m\n");
@@@ -257,18 -225,9 +257,18 @@@ void finish_sock(int sock, int nbd, in
                mlockall(MCL_CURRENT | MCL_FUTURE);
  }
  
 -void usage(void) {
 -      fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
 -      fprintf(stderr, "Usage: nbd-client host port nbd_device [-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S] [-persist|-p] [-nofork|-n]\n");
 +void usage(char* errmsg, ...) {
 +      if(errmsg) {
 +              char tmp[256];
 +              va_list ap;
 +              va_start(ap, errmsg);
 +              snprintf(tmp, 256, "ERROR: %s\n\n", errmsg);
 +              vfprintf(stderr, errmsg, ap);
 +              va_end(ap);
 +      } else {
 +              fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
 +      }
 +      fprintf(stderr, "Usage: nbd-client host port nbd_device [-block-size|-b block size] [-timeout|-t timeout] [-swap|-s] [-sdp|-S] [-persist|-p] [-nofork|-n] [-name|-N name]\n");
        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");
@@@ -301,7 -260,7 +301,7 @@@ void disconnect(char* device) 
  }
  
  int main(int argc, char *argv[]) {
 -      int port=0;
 +      char* port=NULL;
        int sock, nbd;
        int blocksize=1024;
        char *hostname=NULL;
        u32 flags;
        int c;
        int nonspecial=0;
 +      char* name=NULL;
        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' },
 +              { "name", required_argument, NULL, 'N' },
                { "nofork", no_argument, NULL, 'n' },
                { "persist", no_argument, NULL, 'p' },
                { "sdp", no_argument, NULL, 'S' },
  
        logging();
  
 -      while((c=getopt_long_only(argc, argv, "-b:c:d:hnpSst:", long_options, NULL))>=0) {
 +      while((c=getopt_long_only(argc, argv, "-b:c:d:hnN:pSst:", long_options, NULL))>=0) {
                switch(c) {
                case 1:
                        // non-option argument
                                        optarg+=8;
                                        goto timeout;
                                }
 -                              fprintf(stderr, "ERROR: unknown option %s encountered\n", optarg);
 +                              usage("unknown option %s encountered", optarg);
                                exit(EXIT_FAILURE);
                        }
                        switch(nonspecial++) {
                                        break;
                                case 1:
                                        // port
 -                                      port = strtol(optarg, NULL, 0);
 +                                      if(!strtol(optarg, NULL, 0)) {
 +                                              // not parseable as a number, assume it's the device and we have a name
 +                                              nbddev = optarg;
 +                                              nonspecial++;
 +                                      } else {
 +                                              port = optarg;
 +                                              if(name) {
 +                                                      usage("port and name specified at the same time. This is not supported.");
 +                                                      exit(EXIT_FAILURE);
 +                                              }
 +                                      }
                                        break;
                                case 2:
                                        // device
                                        nbddev = optarg;
                                        break;
                                default:
 -                                      fprintf(stderr, "ERROR: too many non-option arguments specified\n");
 +                                      usage("too many non-option arguments specified");
                                        exit(EXIT_FAILURE);
                        }
                        break;
                        blocksize=(int)strtol(optarg, NULL, 0);
                        break;
                case 'c':
-                       check_conn(optarg, 1);
-                       exit(EXIT_SUCCESS);
+                       return check_conn(optarg, 1);
                case 'd':
                        disconnect(optarg);
                        exit(EXIT_SUCCESS);
                case 'h':
 -                      usage();
 +                      usage(NULL);
                        exit(EXIT_SUCCESS);
                case 'n':
                        nofork=1;
                        break;
 +              case 'N':
 +                      name=optarg;
 +                      if(port) {
 +                              usage("port and name specified at the same time. This is not supported.");
 +                              exit(EXIT_FAILURE);
 +                      }
 +                      port = NBD_DEFAULT_PORT;
 +                      break;
                case 'p':
                        cont=1;
                        break;
                }
        }
  
 -      if(!port || !hostname || !nbddev) {
 -              usage();
 +      if((!port && !name) || !hostname || !nbddev) {
 +              usage("not enough information specified");
                exit(EXIT_FAILURE);
        }
  
  
        sock = opennet(hostname, port, sdp);
  
 -      negotiate(sock, &size64, &flags);
 +      negotiate(sock, &size64, &flags, name);
        setsizes(nbd, size64, blocksize, flags);
        set_timeout(nbd, timeout);
        finish_sock(sock, nbd, swap);
                                        close(sock); close(nbd);
                                        sock = opennet(hostname, port, sdp);
                                        nbd = open(nbddev, O_RDWR);
 -                                      negotiate(sock, &new_size, &new_flags);
 +                                      negotiate(sock, &new_size, &new_flags, name);
                                        if (size64 != new_size) {
                                                err("Size of the device changed. Bye");
                                        }