⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gnbdsrv.c

📁 openGFS , a kind of file system.
💻 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 + -