+ if (ioctl(nbd, NBD_CLEAR_SOCK)<0)
+ err("Ioctl failed: %m\n");
+ printf("done\n");
+}
+
+int main(int argc, char *argv[]) {
+ char* port=NULL;
+ int sock, nbd;
+ int blocksize=1024;
+ char *hostname=NULL;
+ char *nbddev=NULL;
+ int swap=0;
+ int cont=0;
+ int timeout=0;
+ int sdp=0;
+ int G_GNUC_UNUSED nofork=0; // if -dNOFORK
+ u64 size64;
+ 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' },
+ { "swap", no_argument, NULL, 's' },
+ { "timeout", required_argument, NULL, 't' },
+ { 0, 0, 0, 0 },
+ };
+
+ logging();
+
+ while((c=getopt_long_only(argc, argv, "-b:c:d:hnN:pSst:", long_options, NULL))>=0) {
+ switch(c) {
+ case 1:
+ // non-option argument
+ if(strchr(optarg, '=')) {
+ // old-style 'bs=' or 'timeout='
+ // argument
+ fprintf(stderr, "WARNING: old-style command-line argument encountered. This is deprecated.\n");
+ if(!strncmp(optarg, "bs=", 3)) {
+ optarg+=3;
+ goto blocksize;
+ }
+ if(!strncmp(optarg, "timeout=", 8)) {
+ optarg+=8;
+ goto timeout;
+ }
+ usage("unknown option %s encountered", optarg);
+ exit(EXIT_FAILURE);
+ }
+ switch(nonspecial++) {
+ case 0:
+ // host
+ hostname=optarg;
+ break;
+ case 1:
+ // port
+ 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;
+ }
+ break;
+ case 2:
+ // device
+ nbddev = optarg;
+ break;
+ default:
+ usage("too many non-option arguments specified");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'b':
+ blocksize:
+ blocksize=(int)strtol(optarg, NULL, 0);
+ break;
+ case 'c':
+ return check_conn(optarg, 1);
+ case 'd':
+ disconnect(optarg);
+ exit(EXIT_SUCCESS);
+ case 'h':
+ usage(NULL);
+ exit(EXIT_SUCCESS);
+ case 'n':
+ nofork=1;
+ break;
+ case 'N':
+ name=optarg;
+ if(!port) {
+ port = NBD_DEFAULT_PORT;
+ }
+ break;
+ case 'p':
+ cont=1;
+ break;
+ case 's':
+ swap=1;
+ break;
+ case 'S':
+ sdp=1;
+ break;
+ case 't':
+ timeout:
+ timeout=strtol(optarg, NULL, 0);
+ break;
+ default:
+ fprintf(stderr, "E: option eaten by 42 mice\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if((!port && !name) || !hostname || !nbddev) {
+ usage("not enough information specified");
+ exit(EXIT_FAILURE);
+ }
+
+ nbd = open(nbddev, O_RDWR);
+ if (nbd < 0)
+ err("Cannot open NBD: %m\nPlease ensure the 'nbd' module is loaded.");
+ ++argv; --argc; /* skip device */
+
+ sock = opennet(hostname, port, sdp);
+
+ negotiate(sock, &size64, &flags, name);
+ setsizes(nbd, size64, blocksize, flags);
+ set_timeout(nbd, timeout);
+ finish_sock(sock, nbd, swap);