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

📄 cmds.c

📁 ftp服务器源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
 *		Note that this function returns the new position in the *		`file'. The caller is expected to send this information *		back in `pos' at the next call to _mwrite(). */int _mwrite(const char * const buf, const struct ftran * const f,	    const int pos, const int count, const int size){	if (pos + count >= size) return size;	/* out of space */	memcpy(f->file_data + pos, buf, count);	return pos + count;}#endif/* * mwrite:	This is a short_hand define, making calls to _mwrite() very *		similiar to calls to write(). It works both with and without *		mmap(). */#if HAVE_MMAP#define mwrite(buf, count) pos = _mwrite((buf), (f), (pos), (count), (size));#else#define mwrite(buf, count) write(f->local_file, buf, count);#endif/* * long_listing(): *		Formats output in `ls -l' style. It returns one line for the *		file PATHNAME, and returns it in retbuf. Setting do_classify *		to nonzero has the same effect as `ls -F'. * *		This command is so long, because simply there is so much to *		be done. GNU ls has some extra functions, but it's close to *		3000 lines too... */int long_listing(char * const retbuf, const char * const pathname, const int do_classify){	int i, year;	char newd[512], temp[1026];	struct stat buf;	struct tm *t;	time_t now;	char username[17], groupname[17];	time(&now);	year = localtime(&now)->tm_year;	{#if !WANT_NONROOT		struct passwd *p;		struct group *g;#endif		if (lstat(pathname, &buf) == -1) return 0;#if WANT_NONROOT		strcpy(username, nr_get_uname(buf.st_uid));		strcpy(groupname, nr_get_gname(buf.st_gid));#else		p = getpwuid(buf.st_uid);		if (p != NULL) {			strncpy(username, p->pw_name, 16);			username[16] = 0;		} else {			snprintf(username, 16, "%u", buf.st_uid);		}		g = getgrgid(buf.st_gid);		if (g != NULL) {			strncpy(groupname, g->gr_name, 16);			groupname[16] = 0;		} else {			snprintf(groupname, 16, "%u", buf.st_gid);		}#endif	}	/*	 * This POSIX approximation is based on GNU ls code (and obfuscated	 * a bit...), to be compatible with `real' ls implementations.	 */	t = localtime(&(buf.st_mtime));	strftime(newd, 512, ((now > buf.st_mtime + 6L * 30L * 24L * 60L * 60L) ||			     (now < buf.st_mtime - 60L * 60L))			? "%b %e  %Y" : "%b %e %H:%M", t);	{#if WANT_NONROOT		char rights[16];		if (nr_check_permission(0, pathname, 0, (S_ISDIR(buf.st_mode)), rights) == -1) {			/* no permission to even see this file */			return 0;		}		snprintf(temp, 1024, "%c%s %3u %-8s %-8s %8lu %12s %s\r\n",#else		snprintf(temp, 1024, "%c%c%c%c%c%c%c%c%c%c %3u %-8s %-8s %8lu %12s %s",#endif			decode_mode(buf.st_mode),#if WANT_NONROOT			rights,#else			(buf.st_mode & S_IRUSR) ? 'r' : '-', 			(buf.st_mode & S_IWUSR) ? 'w' : '-',			(buf.st_mode & S_IXUSR) ? ((buf.st_mode & S_ISUID) ? 's' : 'x') : '-',			(buf.st_mode & S_IRGRP) ? 'r' : '-',			(buf.st_mode & S_IWGRP) ? 'w' : '-',			(buf.st_mode & S_IXGRP) ? ((buf.st_mode & S_ISGID) ? 's' : 'x') : '-',			(buf.st_mode & S_IROTH) ? 'r' : '-',			(buf.st_mode & S_IWOTH) ? 'w' : '-',			(buf.st_mode & S_IXOTH) ? ((buf.st_mode & S_ISVTX) ? 't' : 'x') : '-',#endif			buf.st_nlink, username, groupname,			(unsigned long)(buf.st_size), newd, pathname);		i = strlen(temp);	#if 0		/*		 * vim needs this extra character for some reason... It's too 		 * bad I'll have to do it this way, but syntax colouring		 * that works properly is almost a `must' for me :-)		 */		)#endif 	        /* add an extra classification `sign' if we got -F */	        if (do_classify) {			int len = strlen(temp);	                temp[len] = classify(buf.st_mode);	                temp[len + 1] = '\0';	        }	}	strcpy(retbuf, temp);	return 1;}/* * cmd_list():	Handles the LIST command (directory listing). Does a *		long listing (of type `ls -l'). The listing work is *		done by do_listing(), below. */int cmd_list(struct conn * const c){	struct list_options lo;	lo.recursive = 0;	lo.long_listing = 1;	lo.classify = 0;	do_listing(c, &lo);	return 1;}/* * cmd_nlst():	Handles the NLST command (plain directory listing). *		Does a plain listing (no dates etc.), unless overridden *		by the `-l' or `-L' flag (case insensitivity because most *		FTP clients don't have a clue about what they send out).  *		The listing work is done by do_listing(), below. */	int cmd_nlst(struct conn * const c){	struct list_options lo; 	lo.recursive = 0;	lo.long_listing = 0;	lo.classify = 0;	do_listing(c, &lo);	return 1;}/* * do_listing(): *		Prepares any listing buffers, temp files, etc., before *		pushing the work one step further :-) * *		If the directory listing cache is enabled, the cache *		is checked first, to see if we still have a valid entry. */void do_listing(struct conn * const c, struct list_options * const lo){	int i;	char *ptr;#if HAVE_MMAP	int size;#endif	struct ftran * const f = c->transfer;#if WANT_DCACHE	char cwd[256];#endif#if WANT_NONROOT#warning No nonroot checking for list_core() yet#endif	i = prepare_for_listing(c, &ptr, lo);	if (i == -1) {		destroy_ftran(c->transfer);		return;	}#if WANT_DCACHE	getcwd(cwd, 256);#endif#if HAVE_MMAP	strcpy(f->filename, "(directory listing)");#endif#if WANT_DCACHE	{		struct dcache *d = find_dcache(cwd, ptr, lo);		if (d != NULL) {			d->use_count++;			f->dir_cache = d;			f->file_data = d->dir_data;			f->size = d->dir_size;			f->dir_listing = 1;			f->pos = 0;			prepare_for_transfer(f);			return;		}	}#endif#if HAVE_MMAP	{		int num_files = get_num_files(c, ptr, lo);		if (num_files == -1) return;		size = num_files * 160;		f->file_data = malloc(size + 1);		TRAP_ERROR(f->file_data == NULL, 550, return);		list_core(c, ptr, "", lo, size, 0);	}#else	list_core(c, ptr, "", lo);#endif#if WANT_DCACHE	populate_dcache(f, cwd, ptr, lo);#endif#if HAVE_MMAP	f->pos = 0;#endif	prepare_for_transfer(f);}/* * get_num_files(): *		Get the number of files in PATHNAME (optionally matching *		a pattern). Note that c is needed for TRAP_ERROR. */int get_num_files(struct conn * const c, const char * const pathname,	       	   struct list_options * const lo){	int num_files;	glob_t pglob;	/*	 * glob() fails to set errno correctly, so we simply guess on	 * `permission denied'... The others are far less likely to happen.	 */	switch (glob(pathname, 0, NULL, &pglob)) {#ifdef GLOB_NOMATCH	case GLOB_NOMATCH:		return 0;#endif	case 0:		num_files = pglob.gl_pathc;		break;	default:		numeric(c, 550, strerror(EACCES));		return -1;	}	if (lo->recursive) {		int i;       		for (i = 0; i < pglob.gl_pathc; i++) {		        char *temp = pglob.gl_pathv[i];			struct stat buf;			lstat(temp, &buf);			if (S_ISDIR(buf.st_mode)) {				chdir(temp);				num_files += get_num_files(c, "*", lo);				chdir("..");			}		}	}	globfree(&pglob);	return num_files;}/* * list_core():	Enumerate all the files in PATHNAME, and formats them *		according to list_options (calling format functions if *		required). * *		Note that we don't do any realloc() yet, so if your *		_average_ file name length is over a certain size (a little *		under 80 for long listings, and a little under 160 for *		short listings), the list will be truncated. Fix... * *		The return value only makes sense if mmap()'ing, since it *		returns the number of bytes written into the buffer. * *		This function is rather long. */int list_core(struct conn * const c, const char * const pathname,	      char * const disp_pathname, struct list_options * const lo#if HAVE_MMAP		, const int size, int pos#endif		){	int i;	glob_t pglob;	struct ftran * const f = c->transfer;        /*         * glob() fails to set errno correctly, so we simply guess on         * `permission denied'... The others are far less likely to happen.         */        switch (glob(pathname, GLOB_MARK, NULL, &pglob)) {        case 0:#ifdef GLOB_NOMATCH	case GLOB_NOMATCH:#endif                break;		/* note: break, not return */        default:                numeric(c, 550, strerror(EACCES));#if HAVE_MMAP		return pos;#else                return 0;#endif        }	if (lo->recursive) {		if (disp_pathname[0] == '\0') {			mwrite(".:\r\n", 4);		} else {			char temp[1024];			int i;			snprintf(temp, 1024, "%s:\r\n", disp_pathname);			i = strlen(temp);			mwrite(temp, i);		}	}	if (lo->long_listing) {		/* FIX: we may get too high total number if we are running nonroot! */		struct stat buf;		long unsigned int total = 0;		char temp[1024];		for (i = 0; i < pglob.gl_pathc; i++) {	        	if (lstat(pglob.gl_pathv[i], &buf) != -1) {	        		total += buf.st_blocks;			}		}		snprintf(temp, 1024, "total %lu\r\n", total >> 1);		i = strlen(temp);		mwrite(temp, i);	}	for (i = 0; i < pglob.gl_pathc; i++) {		char * const temp = pglob.gl_pathv[i];		char buf[2048];		/* strip `/' away from the pathname -- add it later if -F */		{			int len = strlen(temp);			if (temp[len - 1] == '/') {				temp[len - 1] = '\0';			}		}		if (lo->long_listing) {			if (long_listing(buf, temp, lo->classify) == 0) continue;		} else {			strcpy(buf, temp);			if (lo->classify) {				struct stat statbuf;				if (lstat(buf, &statbuf) != -1) {					const int len = strlen(buf);					buf[len] = classify(statbuf.st_mode);					buf[len + 1] = 0;				}			}		}		mwrite(buf, strlen(buf));		mwrite("\r\n", 2);	}	/*	 * If recursion is on, dive into any subdirectories now -- note	 * that each entry is stat()'ed twice, hopefully the OS will manage,	 * and we've got our own dcache anyways -- this could be fixed at	 * the expense of some memory, consider for later inclusion. 	 */	if (lo->recursive) {		for (i = 0; i < pglob.gl_pathc; i++) {                	struct stat buf;			const char * const temp = pglob.gl_pathv[i];			/* don't dive into `.' or `..' */                        if (lstat(temp, &buf) != -1 && S_ISDIR(buf.st_mode) &&				(temp[0] != '.' || (temp[1] != '.' && temp[1] != '\0'))) {				char tmp2[1024];				mwrite("\r\n", 2);				/* attach the pathname to the end of the displayed path */				if (disp_pathname[0] == '\0') {					snprintf(tmp2, 1024, "%s", temp);				} else {					snprintf(tmp2, 1024, "%s/%s", disp_pathname, temp);				}				chdir(temp);				pos = list_core(c, "*", tmp2, lo, #if HAVE_MMAP					size, pos);#endif				chdir("..");			}		}	}#if HAVE_MMAP	f->size = pos;#else	lseek(f->local_file, 0, SEEK_SET);#endif	globfree(&pglob);#if HAVE_MMAP	return pos;#else	return 0;#endif}/* * cmd_noop():	Handles the NOOP command. Does nothing, doesn't even *		reset the timeout. */int cmd_noop(struct conn * const c){	numeric(c, 200, "NOOP command successful.");	return 1;}/* * cmd_syst():	Handles the SYST command. Returns the system identification. */int cmd_syst(struct conn * const c){	numeric(c, 215, "UNIX Type: L%u", NBBY);	return 1;}/* * cmd_type():	Handles the TYPE command. */int cmd_type(struct conn * const c){#if WANT_ASCII	c->recv_buf[0] &= (255-32);	/* convert to upper case */

⌨️ 快捷键说明

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