📄 gclient.c
字号:
int major_nr; bytes = get_proc_data(buf, 31); if (bytes < 0) return -1; major = strchr(buf, ':'); major = major + 2; tail = strchr(major, '\n'); *tail = 0; major_nr = (int) strtoul(major, &tail, 0); if (major_nr == 0 || tail == major) return -1; return major_nr;}int addclient(char *name, char *hostname, char *port_ptr){ int fd; struct sockaddr_in server; struct hostent *hp; char path[300]; char *tailptr; int minor_nr; int major_nr; uint16_t port_nr; major_nr = get_major_nr(); if (major_nr < 0) return 1; if ((fd = open("/dev/gnbdcomm", O_WRONLY)) < 0) { if (errno == ENOENT) { fprintf(stderr, "creating /dev/gnbdcomm\n"); if (mknod ("/dev/gnbdcomm", S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, makedev(major_nr, 0)) < 0) { perror("cannot create gnbdcomm"); return 1; } } else { perror("cannot open comm device"); return 1; } } if (mkdir("/dev/gnbd", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) { if (errno == EEXIST) { if ((major_nr = validate_devs(fd)) < 0) goto fail; } else { perror("unable to create directory /dev/gnbd/"); goto fail; } } if ((port_nr = (uint16_t)strtoul(port_ptr, &tailptr, 0)) == 0 && tailptr == port_ptr) { fprintf(stderr, "invalid port number %s: %s\n", port_ptr, strerror(errno)); goto fail; } hp = gethostbyname(hostname); /* Check the reply is a 4 byte address .. important */ if (hp == NULL || hp->h_length!=4) { fprintf(stderr, "cannot resolve host ip from name %s: %s", hostname, strerror(errno)); goto fail; } if (memcpy(&(server.sin_addr.s_addr), hp->h_addr, hp->h_length) == NULL) { fprintf(stderr, "cannot copy host address: %s\n", strerror(errno)); goto fail; } minor_nr = do_device_create(fd, name); if (minor_nr < 0) { fprintf(stderr, "couldn't create gnbd device %s: %s\n", name, strerror(errno)); goto fail; } if (do_setipport(fd, (uint16_t) minor_nr, port_nr, server.sin_addr) < 0) { fprintf(stderr, "couldn't set the ip address and port for %s: %s\n", name, strerror(errno)); goto fail; } snprintf(path, 300, "/dev/gnbd/%s", name); if (mknod(path, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, makedev(major_nr, minor_nr)) < 0) { fprintf(stderr, "couldn't create gnbd block device file %s: %s\n", path, strerror(errno)); goto fail; } if (validate_devs(fd) < 0) goto fail; printm("imported GNBD '%s'\n", name); close(fd); return 0; fail: close(fd); return 1;}int setclients(int num, char **serv){ int major_nr, minor_nr, i, n, fd, sock_fd; int total = 0; uint16_t port_nr; struct in_addr ipaddr; char path[300]; char buf[300]; char *port; char *tailptr; errno = 0; major_nr = get_major_nr(); if (major_nr < 0) return 1; if ((fd = open("/dev/gnbdcomm", O_WRONLY)) < 0) { if (errno == ENOENT) { fprintf(stderr, "creating /dev/gnbdcomm\n"); if (mknod ("/dev/gnbdcomm", S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, makedev(major_nr, 0)) < 0) { perror("cannot create gnbdcomm"); return 1; } if ((fd = open("/dev/gnbdcomm", O_WRONLY)) < 0) { perror("cannot open comm device?!?!"); return 1; } } else if (errno == ENODEV) { if (unlink("/dev/gnbdcomm") < 0) { perror("cannot remove old gnbdcomm"); return 1; } if (mknod ("/dev/gnbdcomm", S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, makedev(major_nr, 0)) < 0) { perror("cannot create gnbdcomm"); return 1; } if ((fd = open("/dev/gnbdcomm", O_WRONLY)) < 0) { perror("cannot open comm device?!?!"); return 1; } } else { perror("cannot open comm device"); return 1; } } if (mkdir("/dev/gnbd", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) { if (errno == EEXIST) { if ((major_nr = validate_devs(fd)) < 0) goto fail; } else { perror("unable to create directory /dev/gnbd/"); goto fail; } } for (i = 0; i < num; i++) { sock_fd = connect_to_server(serv[i], (unsigned int) 14243, &ipaddr); if (sock_fd < 0) { continue; } write(sock_fd, "port", 5); while (1) { path[10] = 0; total = 0; while ((n = read(sock_fd, buf + total, 300 - total)) != 0) { if (n < 0) { fprintf(stderr, "error reading from the server: %s\n", strerror(errno)); goto sock_fail; } total += n; if (buf[total - 1] == 0) break; } if (strncmp(buf, "bye", 3) == 0) break; if ((port = strchr(buf, '/')) == NULL) { fprintf(stderr, "malformed server message: %s\n", buf); goto sock_fail; } *port++ = 0; if ((port_nr = (uint16_t) strtoul(port, &tailptr, 0)) == 0 && tailptr == port) { fprintf(stderr, "invalid port number %s: %s\n", port, strerror(errno)); goto sock_fail; } errno = 0; if ((minor_nr = do_device_create(fd, buf)) < 0) { if (errno == EEXIST) { printm ("duplicate GNBD '%s', skipping\n", buf); if (write(sock_fd, "next", 5) != 5) { fprintf(stderr, "error writing to the server: %s\n", strerror(errno)); goto sock_fail; } continue; } fprintf(stderr, "couldn't create gnbd device %s: %s\n", buf, strerror(errno)); goto sock_fail; } if (do_setipport (fd, (uint16_t) minor_nr, port_nr, ipaddr) < 0) { fprintf(stderr, "couldn't set the ip address and port for %s: %s\n", buf, strerror(errno)); goto sock_fail; } snprintf(path, 300, "/dev/gnbd/%s", buf); if (mknod(path, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, makedev(major_nr, minor_nr)) < 0) { fprintf(stderr, "couldn't create gnbd block device file %s: %s\n", path, strerror(errno)); goto sock_fail; } printm("imported GNBD '%s' from server %s\n", buf, serv[i]); if (write(sock_fd, "next", 5) != 5) { fprintf(stderr, "error writing to the server: %s\n", strerror(errno)); goto sock_fail; } } write(sock_fd, "quit", 5); close(sock_fd); } if (validate_devs(fd) < 0) goto fail; close(fd); return 0; sock_fail: close(sock_fd); fail: close(fd); return 1;}int debug(int num, char **debug, int on){ /* NOTHING */ return 0;}int remove_client(char *name){ int comm_fd; int found = 0; uint16_t minor = 0; char *name_ptr; char *minor_ptr; char *bufptr; char path[300]; int bytes; char buf[4096]; if (name == NULL) { perror("gnbd client name is NULL\n"); return -1; } if ((comm_fd = open("/dev/gnbdcomm", O_WRONLY)) < 0) { perror("cannot open comm device"); return -1; } bytes = get_proc_data(buf, 4096); if (bytes < 0) return -1; snprintf(path, 300, "/dev/gnbd/%s", name); if (remove(path) < 0) { fprintf(stderr, "blockdevice %s does not exist\n", path); } bufptr = buf; while ((name_ptr = strchr(bufptr, '/')) != NULL) { name_ptr++; bufptr = strchr(name_ptr, '/'); *bufptr++ = 0; if (strcmp(name_ptr, name) != 0) continue; minor_ptr = strchr(bufptr, ':'); minor_ptr += 2; minor = (uint16_t) strtoul(minor_ptr, &bufptr, 0); if (minor == 0 || bufptr == minor_ptr) { fprintf(stderr, "couldn't find the minor number for %s: %s\n", name, strerror(errno)); close(comm_fd); return -1; } found = 1; break; } if (found == 0) { fprintf(stderr, "couldn't find gnbd client info for %s\n", name); close(comm_fd); return 0; } if (do_device_remove(comm_fd, (int) minor) < 0) { fprintf(stderr, "couldn't remove device %s: %s\n", name, strerror(errno)); close(comm_fd); return -1; } printm("removed GNBD '%s'\n", name); close(comm_fd); return 0;}int remove_all(void){ DIR *dp; int bytes; char buf[4096]; char *name_ptr; char *bufptr; devlist_t *del_list = NULL; devlist_t *list_ptr; struct dirent *entry; bytes = get_proc_data(buf, 4096); if (bytes < 0) return -1; bufptr = buf; while ((name_ptr = strchr(bufptr, '/')) != NULL) { name_ptr++; bufptr = strchr(name_ptr, '/'); if (bufptr == NULL) { perror("malformed /proc/gnbd file?!?!?\n"); return 1; } *bufptr++ = 0; del_list = add(name_ptr, del_list); } dp = opendir("/dev/gnbd/"); if (dp != NULL) { while ((entry = readdir(dp)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (match(entry->d_name, del_list) < 0) del_list = add(entry->d_name, del_list); } if (closedir(dp) < 0) { perror("error closing directory /dev/gnbd"); del_list = clear(del_list); return 1; } } list_ptr = del_list; while (list_ptr != NULL) { remove_client(list_ptr->name); list_ptr = getnext(list_ptr); } return 0;}int usage(void){ printf("Usage:\n\n"); printf("gclient <hostname> [<other hostnames>]\n"); printf (" Import all GNBD's exported from specified host(s).\n\n"); printf("gclient -a <GNBD> <hostname> <port>\n"); printf(" Import named GNBD from specified host and port.\n\n"); printf("gclient -r <GNBD> [<other GNBD's>]\n"); printf(" Remove named GNBD(s).\n\n"); printf("gclient -l\n"); printf(" List all imported GNBD's.\n\n"); printf("gclient -g <hostname> [<other hostnames>]\n"); printf(" List exported GNBD's on specified host(s).\n\n"); printf("gclient -v\n"); printf(" Remove all invalid GNBD's.\n\n"); printf("gclient -d <debug flag> [<additional debug flags>]\n"); printf (" Turn debugging on (must be compiled into gnbd.o module).\n\n"); printf("gclient -o <debug flag> [<additional debug flags>]\n"); printf(" Turn debugging off.\n\n"); printf("gclient -h\n"); printf(" Print help.\n\n"); printf("-q toggles gclient to quiet mode, so it does not print on " "success\n\n");#if 0 printf ("Register a gnbd client for each gnbd server on the given hosts\n" " gclient <hostname> [<additional host names>]\n"); printf ("Add a gnbd client with with the given name, host, and port\n" " gclient -a <name> <hostname> <port>\n"); printf("Remove a gnbd client\n" " gclient -r <client name> [<additional client names>]\n"); printf("Remove all current gnbd clients\n" " gclient -r\n"); printf("List all current gnbd clients\n" " gclient -l\n"); printf("List all the gnbd servers on the given hosts\n" " gcleint -s <hostname> [<additional host names>]\n"); printf("Remove all invalid gnbd clients\n" " gclient -v\n"); printf ("Turn gnbd debugging on (must be compiled into gnbd.o module)\n" " gclient -d <debug flag> [<additional debug flags>]\n"); printf("Turn gnbd debugging off\n" " gclient -o <debug flag> [<additional debug flags>]\n"); printf("Print this message\n" " gclient -h\n\n");#endif return 1;}int main(int argc, char **argv){ int c; int i; loop: c = getopt(argc, argv, "qasgrlvdoh"); switch (c) { case 'q': message_flag = 0; goto loop; case -1: if (argc == optind) return usage(); return setclients(argc - optind, &argv[optind]); case 'a': if (argc - optind != 3) return usage(); return addclient(argv[optind], argv[optind + 1], argv[optind + 2]); case 's': if (argc != optind + 1) return usage(); return stomith(argv[optind]); case 'g': if (argc == optind) return usage(); for (i = optind; i < argc; i++) getserver(argv[i]); return 0; case 'r': if (argc == optind) return remove_all(); for (i = optind; i < argc; i++) remove_client(argv[i]); return 0; case 'l': if (optind != argc) { fprintf(stderr, "unnecessary argument after list request: %s\n\n", argv[optind]); return usage(); } return list(); case 'v': if (optind != argc) { fprintf(stderr, "unnecessary argument after validate request: %s\n\n", argv[optind]); return usage(); } if (setclients(0, NULL) == 0) { printm("GNBD list is now uptodate\n"); return 0; } return 1; case 'd': if (argc == optind) { fprintf(stderr, "missing argument for debug request\n\n"); return usage(); } return debug(argc - optind, &argv[optind], 1); case 'o': if (argc == optind) { fprintf(stderr, "missing argument for debug request\n\n"); return usage(); } return debug(argc - optind, &argv[optind], 0); case '?': if (isprint(optopt)) fprintf(stderr, "Unknown option: -%c\n\n", optopt); else fprintf(stderr, "Unknown option\n\n"); return usage(); case 'h': default: return usage(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -