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

📄 cmds.c

📁 ftp服务器源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		(htons(addr.sin_port) & 0xff00) >> 8,		(htons(addr.sin_port) & 0x00ff));	return 1;}/* * cmd_pwd():	Handles PWD command (print working directory). * *		Note that if somebody contacts you with the message `the server *		says curr_dir() is outside root_dir()', you should fix your *		/betaftpd.users file, if you use nonroot. If not, it's a bug. *		Try to get it _reproducible_, and mail it to me. */int cmd_pwd(struct conn * const c){	char temp[512], *cdir = NULL;	cdir = do_pwd(c, temp, c->curr_dir);	if (cdir != NULL) {		numeric(c, 257, "\"%s\" is current working directory.", cdir);	}	return 1;}/* * do_pwd():	Translates an absolute path to a path suitable for viewing *		to the user (ie. removes the root_dir, and removes a trailing *		slash if it exists). Note that the retbuf is only used as a *		storage place -- the pointer to the right place within retbuf *		is _returned_. */char *do_pwd(struct conn * const c, char * const retbuf, const char * const dir) {	char *cdir = NULL;	strcpy(retbuf, dir);	if (strncmp(retbuf, c->root_dir, strlen(c->root_dir)) != 0) {		numeric(c, 550, "curr_dir is outside root_dir, please contact site administrator.");		return NULL;	}	cdir = retbuf + strlen(c->root_dir) - 1;	if (cdir[strlen(cdir) - 1] == '/' && strlen(cdir) > 1) {		cdir[strlen(cdir) - 1] = 0;	} else if (strlen(cdir) == 0) {		strcpy(cdir, "/");	}		return cdir;}/* * cmd_cwd():	Handles CWD command (change working directory). Uses *		cmd_cwd_internal() (see below). */int cmd_cwd(struct conn * const c){	cmd_cwd_internal(c, c->recv_buf);	return 1;}/* * cmd_cdup():  Handles a CDUP command (identical to `CWD ..'). Note that *		RFC959 gives two different response codes (250 and 200) -- *		250 is the same as CWD gives, which sounds logical to me. *		wu-ftpd uses it as well. * *		Note that using a CDUP to try to get outside root_dir returns *		an error, instead of just staying in the root directory (as *		the OS and thus wu-ftpd does). */int cmd_cdup(struct conn * const c){	cmd_cwd_internal(c, "..");	return 1;}/* * cmd_cwd_internal(): *		Does the work for CWD and CDUP (modularized to save some *		space and have clearer code). Mostly, it just uses do_chdir(), *		and sees where that takes us. It adds a trailing slash if needed. */void cmd_cwd_internal(struct conn * const c, const char * const newd){	if (do_chdir(c, newd) != -1) {		int i;		getcwd(c->curr_dir, 254);		i = strlen(c->curr_dir);		if (c->curr_dir[i - 1] != '/') {			c->curr_dir[i++] = '/';			c->curr_dir[i] = '\0';		}#if WANT_MESSAGE		dump_file(c, 250, ".message");		list_readmes(c);#endif		numeric(c, 250, "CWD successful.");	}}/* * cmd_rest():	Handles the REST command. All it does is tell the file *		sending functions to start at the correct number. We should *		perhaps add some better error checking to this? */int cmd_rest(struct conn * const c){	c->rest_pos = abs(atoi(c->recv_buf));	numeric(c, 350, "Setting resume at %u bytes.", c->rest_pos);	return 1;}/* * cmd_retr():	Handles the RETR command. This command doesn't send the *		file, but it opens it and tells the socket handling code *		to check for activity on the data socket. When the *		connection occurs (or succeeds, if we're using PORT mode), *		the actual file transfer begins. */int cmd_retr(struct conn * const c){	struct ftran *f = c->transfer;	if ((f == NULL) || ((f->state != 1) && (f->state != 3))) {		numeric(c, 425, "No data connection set up; please use PASV or PORT.");		return 1;	}#if WANT_ASCII	if ((c->rest_pos > 0) && (c->ascii_mode == 1)) {		numeric(c, 500, "Cannot resume while in ASCII mode.");		return 1;	}#endif	f->local_file = do_openfile(c, c->recv_buf, f->filename, O_RDONLY#if WANT_NONROOT		, 4#endif	);	f->dir_listing = 0;	if (f->local_file == -1) {		numeric(f->owner, 550, strerror(errno));		destroy_ftran(f);	} else if (f->local_file == -2) {		f->local_file = -1;		destroy_ftran(f);	} else {#if WANT_UPLOAD		f->upload = 0;#endif		prepare_for_transfer(f);	}	return 1;}#if WANT_UPLOAD/* * cmd_stor():	Handles the STOR command (upload file). Pushes the *		work down to do_store(), below. */int cmd_stor(struct conn * const c){	do_store(c, 0);	return 1;}/* * cmd_appe():	Handles the APPE command (append to file). Pushes *		the work down to do_store(), below. */int cmd_appe(struct conn * const c){	do_store(c, 1);	return 1;}/* * do_store():	Initiate an upload. Most of the comments to do_retr() *		(above) apply to this one as well. */void do_store(struct conn * const c, const int append){	struct ftran *f = c->transfer;	if ((f == NULL) || ((f->state != 1) && (f->state != 3))) {		numeric(c, 425, "No data connection set up; please use PASV or PORT.");		return;	}#if WANT_ASCII	if ((c->rest_pos > 0) && (c->ascii_mode == 1)) {		numeric(c, 500, "Cannot resume while in ASCII mode.");		return;	}#endif	f->local_file = do_openfile(c, c->recv_buf, f->filename, O_WRONLY |		O_CREAT | ((append || c->rest_pos > 0) ? 0 : O_TRUNC)#if WANT_NONROOT	        , 2#endif	);	f->dir_listing = 0;	if (f->local_file == -1) {	        numeric(f->owner, 550, strerror(errno));	} else if (f->local_file == -2) {		f->local_file = -1;	} else {	        f->upload = 1;	        f->append = append;#if WANT_ASCII		f->ascii_mode = c->ascii_mode;#endif	        prepare_for_transfer(f);	}}#endif /* WANT_UPLOAD *//* * cmd_size():	Handle the SIZE command -- returns the size of a *		file. Note that this command is not part of RFC959, *		and thus there is no clear specification (except *		for some ftpext documents, which we try to follow *		as closely as we can). BetaFTPD deviates from wu-ftpd *		in that it lets you check the `size' of directories *		as well (instead of giving 550). This is _not_ the *		size of all the files in the directory, rather how *		much space the directory inode uses. */int cmd_size(struct conn * const c){#if WANT_ASCII	if (c->ascii_mode) {		numeric(c, 550, "SIZE not available in ASCII mode.");		return 1;	}#endif	{		const char * const fname = translate_path(c, c->recv_buf);		struct stat buf;			TRAP_ERROR(fname == NULL || lstat(fname, &buf) == -1, 550, return 1);			numeric(c, 213, "%lu", (unsigned long)(buf.st_size));		return 1;	}}/* * cmd_mdtm():	Handle the MDTM command -- returns the modification *		date/time of a file. See the comments on cmd_size(), *		above. */int cmd_mdtm(struct conn * const c){	const char * const fname = translate_path(c, c->recv_buf);	struct stat buf;	struct tm *m;	TRAP_ERROR(fname == NULL || lstat(fname, &buf) == -1, 550, return 1);	m = gmtime(&(buf.st_mtime));	/* at least wu-ftpd does it in GMT */	numeric(c, 213, "%u%02u%02u%02u%02u%02u", m->tm_year + 1900,		m->tm_mon + 1, m->tm_mday, m->tm_hour, m->tm_min, m->tm_sec);	return 1;}/* * cmd_abor():	Handle the ABOR command (abort a file transfer). This should *		be clean enough, but isn't tested extensively. */int cmd_abor(struct conn * const c){	if (c->transfer != NULL) {		numeric(c, 426, "File transfer aborted.");		destroy_ftran(c->transfer);	}	numeric(c, 226, "ABOR command processed OK.");	return 1;}/* * cmd_dele():	Handle the DELE command (delete a file). */int cmd_dele(struct conn * const c){	const char * const fname = translate_path(c, c->recv_buf);		TRAP_ERROR(fname == NULL || unlink(fname) == -1, 550, return 1);	numeric(c, 250, "File deleted OK.");	return 1;}/* * cmd_rnfr():	Handle the RNFR command (take a filename to rename from). */int cmd_rnfr(struct conn * const c){	const char * const fname = translate_path(c, c->recv_buf);	char cwd[256];	struct stat buf;	c->rename_from[0] = '\0';	if (fname == NULL) return 1;		getcwd(cwd, 256);	snprintf(c->rename_from, 256, "%s/%s", cwd, fname);	/* Just check that the file exists. */	TRAP_ERROR(lstat(c->rename_from, &buf) == -1, 550, c->rename_from[0] = '\0'; return 1);	numeric(c, 350, "File exists, send RNTO.");	return 1;}/* * cmd_rnto():	Handle the RNTO command (do the actual renaming). */int cmd_rnto(struct conn * const c){	const char * const fname = translate_path(c, c->recv_buf);	if (fname == NULL) return 1;	if (c->rename_from[0] == '\0') {		numeric(c, 503, "Please send RNFR first.");		return 1;	}	TRAP_ERROR(rename(c->rename_from, fname) == -1, 550, c->rename_from[0] = '\0'; return 1);	c->rename_from[0] = '\0';	numeric(c, 250, "File renamed successfully.");	return 1;}/* * cmd_mkd():	Handle the MKD/XMKD command (create a new directory). *		RFC959 is not clear on the error codes for this command -- *		one place, 521 is cited as the correct error, but is *		mentioned nowhere else. Different FTP servers differ here *		as well. Thus, I've followed what appears to be the intention *		(having `analogous' errors with STOR), and use 550 instead. * *		Making directories is probably the topic covered most *		extensively by RFC959 (and in the most confusing way as *		well). I try to follow the conventions, but it isn't always *		easy :-) (This code isn't quite easy to understand, because *		temp2 is used twice, in two different roles.) */int cmd_mkd(struct conn * const c){	const char * const fname = translate_path(c, c->recv_buf);	char temp[512], temp2[1024], *cdir;	int i, j;	TRAP_ERROR(fname == NULL || mkdir(fname, 0755) == -1, 550, return 1);	chdir(fname);	getcwd(temp2, 512);	cdir = do_pwd(c, temp, temp2);	/* double the quotes in the output */ 	for (i = 0, j = 0; i <= strlen(cdir); i++, j++) {		temp2[j] = cdir[i];		if (cdir[i] == '"') {			temp2[++j] = '"';		}	}	numeric(c, 257, "\"%s\" created.", temp2);	return 1;}/* * cmd_rmd():	Handle the RMD/XRMD command. Works just like DELE, only for *		directories. */int cmd_rmd(struct conn * const c){	const char * const fname = translate_path(c, c->recv_buf);	TRAP_ERROR(fname == NULL || rmdir(fname) == -1, 550, return 1);	numeric(c, 250, "Directory deleted.");	return 1;}/* * cmd_allo():	Handle the ALLO command. The command does not do anything, except *		sit around and play compliant. Some Windows FTP servers (Serv-U, *		for instance), verifies that there is enough space on the disk, *		but since we have no idea on what the filesystem will be stored on, *		we just ignore the command. * *		We could theoretically use this information to give more information *		to the full-screen mode, but close to no FTP clients send this *		command, and it would touch too much code. */int cmd_allo(struct conn * const c){	numeric(c, 202, "No storage allocation necessary.");	return 1;}/* * cmd_stat():	Handle the STAT command. Please see README for more details. *		Note that this command is run with euid=root, since it has *		to be able to run before USER. * *		Note that we need to bypass numeric(), to get a multi-line *		reply. */#if WANT_STATchar conn_state[5][27] = {	"Not logged in",	"Waiting for e-mail address",	"Waiting for password",	"Logged in",	"Waiting for password",		/* actually non-existant user */};char ftran_state[6][42] = {	"Not initialized",	"Decided PASV address/port",	"Waiting on PASV socket",	"Got PORT address/port",	"Connecting on PORT address/port",	"Transferring file (or connecting on PORT)"};#endifint cmd_stat(struct conn * const c){ #if WANT_STAT	char buf[1024];	int i, err;	struct ftran *f = c->transfer;	snprintf(buf, 1024, "211- FTP server status:\r\n"			    "     BetaFTPD version " VERSION " (http://members.xoom.com/sneeze/betaftpd.html)\r\n"			    "     Connected to %s\r\n"			    "     Control connection state: %s\r\n"#if WANT_ASCII			    "     TYPE: %s; STRUcture: File; transfer MODE: Stream\r\n"#else			    "     TYPE: Image; STRUcture: File; transfer MODE: Stream\r\n"#endif			    "     Data connection state: %s\r\n"			    "211 End of status\r\n",				inet_ntoa(((struct sockaddr_in *)(&(c->addr)))->sin_addr),				conn_state[c->auth],#if WANT_ASCII				(c->ascii_mode == 1) ? "ASCII, FORM: Nonprint" : "Image",#endif				(f) ? ftran_state[f->state] : ftran_state[0]);	i = strlen(buf);	err = send(c->sock, buf, i, 0);       	if (err == -1 && errno == EPIPE) {               	destroy_conn(c);		return 0;	}#else	numeric(c, 502, "STAT command disabled for security reasons.");#endif	return 1;}#if HAVE_MMAP/* * _mwrite():	This define is for mmap-listing. It works as a write() *		(not in parameter, but in function), and is used in *		cmd_list() and cmd_nlst() only. *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -