📄 gnbdsrv.c
字号:
/* * * Copyright 1999-2001 Sistina Software, Inc. * Portions Copyright 2001 The OpenGFS Project * * This is free software released under the GNU General Public License. * There is no warranty for this software. See the file COPYING for * details. * * See the file AUTHORS for a list of contributors. * */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <netdb.h>#include <errno.h>#include <dirent.h>#include <ctype.h>#include <sys/time.h>#include <sys/wait.h>#include "utils.h"#include <signal.h>#include <poll.h>char exec_path[1024];serv_list_t *serv = NULL;int handle_pipe_read(int read_fd, int write_fd){ /* no sane amount of data will be larger than this */ /* XXX: famous last words --hch */ char buf[4096]; int n; fd_set read_set; struct timeval tv; char *name_ptr, *path_ptr; unsigned int port; pid_t pid; int info_fd = 0; serv_list_t serv_info; if ((n = read(read_fd, buf, 4096)) <= 0) { perror("gportd: couldn't read from fifo"); return -1; } buf[n] = 0; name_ptr = strchr(buf, '/'); if (name_ptr != NULL) *name_ptr++ = 0; if (strcmp(buf, "create") == 0 && name_ptr != NULL) { path_ptr = strchr(name_ptr, '/'); if (path_ptr == NULL) { fprintf(stderr, "gportd: Malformed create request from client\n"); return -1; } *path_ptr++ = 0; if (match(name_ptr, serv) != 0) { fprintf(stderr, "a server with this name already exists\n"); return -1; } fprintf(stderr, "gportd: creating server \"%s\", which servers %s\n", name_ptr, path_ptr); strncpy(serv_info.name, name_ptr, 300); strncpy(serv_info.path, path_ptr, 300); info_fd = open_socket(0, 24314); if (info_fd < 0) return -1; if ((pid = fork()) < 0) { perror("gportd: cannot fork server process"); goto fail; } if (pid == 0) { /* child process */ close(info_fd); if (execlp(exec_path, "gnbdd", path_ptr, NULL) < 0) { fprintf(stderr, "gportd: unable to start server for %s: %s\n", buf, strerror(errno)); goto fail; } } serv_info.pid = pid; FD_ZERO(&read_set); FD_SET(info_fd, &read_set); while (1) { int val; tv.tv_sec = 5; tv.tv_usec = 0; if ((val = select(info_fd + 1, &read_set, NULL, NULL, &tv)) < 0) { perror ("portd: error while waiting for response from server"); goto fail; } if (val) break; fprintf(stderr, "gportd: timeout\n"); if ((val = waitpid(pid, NULL, WNOHANG)) == 0) continue; if (val == pid) { /* need to fix. Print status, not errno */ fprintf(stderr, "gportd: \"%s\" server failed: %s\n", buf, strerror(errno)); goto fail; } perror("gportd: error waiting for server"); goto fail; } if (read(info_fd, &port, sizeof (port)) != sizeof (port)) { fprintf(stderr, "gportd: error reading from \"%s\" server: %s\n", buf, strerror(errno)); goto fail; } serv_info.port = port; serv = add(serv_info, serv); close(info_fd); goto pass; } if (strcmp(buf, "remove") == 0 && name_ptr != NULL) { int pid; fprintf(stderr, "gportd: removing server \"%s\"\n", name_ptr); if ((pid = get_pid(name_ptr, serv)) < 0) { fprintf(stderr, "gportd: server \"%s\" is not currently running\n", name_ptr); return -1; } if (kill(pid, SIGKILL) < 0) { /* problem. server could die while doing a transaction. Should probably avoid this */ fprintf(stderr, "gportd: cannot kill server \"%s\"\n", name_ptr); return -1; } if (waitpid(pid, NULL, 0) != pid) { fprintf(stderr, "gportd: failed while waiting for " "server \"%s\" to die: %s\n", name_ptr, strerror(errno)); return -1; } serv = remove_serv(name_ptr, serv); goto pass; } fprintf(stderr, "gportd: unknown command %s\n", buf); return -1;fail: close(info_fd); return -1;pass: while ((n = read(write_fd, buf, 4096)) != 0) { if (n < 0) { fprintf(stderr, "error reading from gnbd_wrpipe: %s\n", strerror(errno)); return -1; } if (buf[n - 1] == EOF) break; } return 0;}int handle_pipe_write(int pipe_fd){ char buf[4096]; fd_set write_set; int count = 0; int serv_num = 0; serv_list_t *ptr = serv; count += sprintf(buf + count, "gportd running on port: 14243\n\n"); if (ptr == NULL) count += sprintf(buf + count, "no gnbdd servers running\n"); else while (ptr != NULL) { serv_num++; count += sprintf(buf + count, "Server[%d] : %-20s\n" "--------------------------\n" " file : %-20s\n" " port : %d\n" " pid : %d\n", serv_num, ptr->name, ptr->path, ptr->port, ptr->pid); ptr = ptr->next; } buf[count++] = EOF; FD_ZERO(&write_set); FD_SET(pipe_fd, &write_set); if (select(pipe_fd + 1, NULL, &write_set, NULL, NULL) < 0) { perror("error selecting"); return -1; } if (write(pipe_fd, buf, count) != count) { fprintf(stderr, "couldn't write to pipe\n"); return -1; } return 0;}int handle_sock_read(int msg_sock){ char buf[300]; int count = 0; serv_list_t *ptr = serv; while (ptr != NULL) { count = sprintf(buf, "%s/%d", ptr->name, ptr->port); buf[count++] = 0; if (write(msg_sock, buf, count) != count) { perror("error writing to socket"); return -1; } count = read(msg_sock, buf, 300); if (count != 5 || strcmp(buf, "next") != 0) { perror("error reading from socket"); break; } ptr = ptr->next; } if (write(msg_sock, "bye", 4) != 4) { perror("error writing socket"); return -1; } read(msg_sock, buf, 300); return 0;}int main(int argc, char *argv[]){ int read_fd; int write_fd; fd_set read_set, write_set; int sock_fd = 0; int msg_sock = 0; int max_fd; if (argc > 2) { fprintf(stderr, "Usage: %s [<path to gnbdd>]\n", argv[0]); return 1; } if (argc == 2) { strcpy(exec_path, argv[1]); if (exec_path[strlen(exec_path) - 1] != '/') strcat(exec_path, "/gnbdd"); else strcat(exec_path, "gnbdd"); } else strcpy(exec_path, "gnbdd"); if (mkfifo("/dev/gnbd_wrpipe", S_IWUSR | S_IRUSR) == -1 && errno != EEXIST) { perror("error creating fifo \"/dev/gnbd_wrpipe\""); return 1; } if (mkfifo("/dev/gnbd_rdpipe", S_IWUSR | S_IRUSR) == -1 && errno != EEXIST) { perror("error creating fifo \"/dev/gnbd_rdpipe\""); return 1; } read_fd = open("/dev/gnbd_rdpipe", O_RDWR); if (read_fd < 0) { perror("couldn't open gnbd_rdpipe"); return 1; } write_fd = open("/dev/gnbd_wrpipe", O_RDWR); if (write_fd < 0) { perror("couldn't open gnbd_wrpipe"); return 1; } sock_fd = open_socket(1, 14243); if (sock_fd < 0) goto fail; if (read_fd > write_fd) max_fd = (read_fd > sock_fd) ? read_fd : sock_fd; else max_fd = (write_fd > sock_fd) ? write_fd : sock_fd; max_fd++; while (1) { FD_ZERO(&read_set); FD_ZERO(&write_set); FD_SET(read_fd, &read_set); FD_SET(sock_fd, &read_set); FD_SET(write_fd, &write_set); if (select(max_fd, &read_set, &write_set, NULL, NULL) < 0) { perror("error selecting on file descriptors"); goto fail; } if (FD_ISSET(read_fd, &read_set)) handle_pipe_read(read_fd, write_fd); if (FD_ISSET(write_fd, &write_set)) handle_pipe_write(write_fd); if (FD_ISSET(sock_fd, &read_set)) { msg_sock = accept(sock_fd, 0, 0); if (msg_sock < 0) { perror("error accepting connection"); goto fail; } handle_sock_read(msg_sock); close(msg_sock); msg_sock = 0; } } return 0;fail: if (msg_sock) close(msg_sock); if (sock_fd) close(sock_fd); if (read_fd) close(read_fd); if (write_fd) close(write_fd); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -