From 20d80314e785cf00ad66e0e5efb8b207469216ad Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Mon, 13 Aug 2007 20:49:57 +0800 Subject: [PATCH] Add NLST by Liu Yang. --- server/src/do_cmd.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++-- server/src/do_cmd.h | 1 + server/src/parse_cmd.c | 6 ++- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/server/src/do_cmd.c b/server/src/do_cmd.c index cf1027f..d596970 100644 --- a/server/src/do_cmd.c +++ b/server/src/do_cmd.c @@ -11,7 +11,7 @@ * 修 改 者:刘洋 林峰 王聪 聂海海 * 修改日期:2007年6月16日 * 取代版本:1.0 - * 摘 要:原来增加的命令很符合要求,重建此文件。全部根据要求,现将命令单独在test目录中通过的逐条加入。 + * 摘 要:原来增加的命令不很符合要求,重建此文件。全部根据要求,现将命令单独在test目录中通过的逐条加入。 * 今天仅加入STAT。 *14日加入USER。 *6.15: 修正英文语法错误,排版错误。 @@ -40,6 +40,7 @@ static void _stat_fail_550(void); static void _stat_success_150(void); static void _stat_success_226(void); static void _stat_fail_501(void); +static void _path_tail(char *, char *); static int _get_local_ip_address(int sock, char* ip_addr); static int _stat_mkd(const char *path); static int _stat_rmd(const char *path); @@ -1095,7 +1096,7 @@ static int _chdir(const char *cdir) _response("501 Can't change directory.\r\n"); return -1; } - /*检查是否合法,即是否超过跟目录*/ + /*检查是否合法,即是否超过根目录*/ if ((buffer = malloc(size)) == NULL) { _response("550 Can't change directory.\r\n"); LOG_IT("malloc failed"); @@ -1308,7 +1309,7 @@ int do_help(const char *args) const char help[] = "214-The following commands are implemented.\r\n" "214-USER QUIT PASS SYST HELP PORT PASV LIST\r\n" "214-NLST RETR STOR TYPE MKD RMD DELE PWD\r\n" - "214-CWD SITE CDUP RNFR RNTO NOOP\r\n" + "214-CWD SITE CDUP RNFR RNTO NOOP NLST\r\n" "214 End of list.\r\n"; const char helpsite[] = "214-The following SITE commands are implemented.\r\n" "214-CHMOD HELP\r\n" @@ -1339,3 +1340,95 @@ int failed(const char *s) _response(msg500); return 0; } +/*implement of NLST*/ +int do_nlst(const char *path) +{ + int i = 0; + const char finish[] = "226 Transfer complete.\r\n"; + const char success[] = "150 Opening ASCII mode data connection for file list.\r\n"; + const char fail[] = "450 No such file or directory.\r\n"; + struct stat stat_buf; + DIR *target_dir; + struct dirent *direntp; + char buf[BUF_LEN] = {0}; + char **words; + wordexp_t wxp; + + if(path[0]!='/') { + if ((user_env.current_path[strlen(user_env.current_path) - 1]) == '/') { + snprintf(buf, BUF_LEN, "%s%s", user_env.current_path, path); + } else { + snprintf(buf, BUF_LEN, "%s/%s", user_env.current_path, path); + } + } + else { + snprintf(buf, BUF_LEN, "%s", path); + } + + debug_printf("buf=\'%s\'\n", buf); + + wordexp(buf, &wxp, 0); + words = wxp.we_wordv; + + if (wxp.we_wordc < 1) { + _response(fail); + goto end; + } + + _response(success); + + if (wxp.we_wordc == 1) { + if (stat(words[0], &stat_buf) == -1) { + _response(fail); + goto end; + } + else { + if (S_ISDIR(stat_buf.st_mode)) { + _path_tail(buf, words[0]); + if((target_dir = opendir(buf)) == NULL) { + goto end; + } + while ((direntp = readdir(target_dir)) != NULL && direntp->d_name[0] != '.') { + write(user_env.data_fd, direntp->d_name, strlen(direntp->d_name)); + write(user_env.data_fd, "\n", 1); + } + goto suc; + } + } + } + + for (i = 0; i < (int)wxp.we_wordc; i++) { + if (words[i][0] != '.') { + write(user_env.data_fd, words[i], strlen(words[i])); + write(user_env.data_fd, "\n", 1); + } + } + +suc: _response(finish); + +end: close(user_env.data_fd); + wordfree(&wxp); + return 0; +} + +static void _path_tail(char *buf, char *name) +{ + int flag = 1; + int i = 0; + + if ((strlen(buf) + strlen(name)) >= BUF_LEN) { + flag = 0; + } + + for (i = strlen(buf); i >= 0; i--) { + if (buf[i] == '/') { + buf[i] = '\0'; + break; + } + } + + if (flag) { + strcat(buf, name); /*It's safe*/ + } +} +/*end of implement NLST*/ diff --git a/server/src/do_cmd.h b/server/src/do_cmd.h index d93531d..bb33932 100644 --- a/server/src/do_cmd.h +++ b/server/src/do_cmd.h @@ -42,4 +42,5 @@ extern int do_rest(const char *); extern int do_size(const char *); extern int do_site(const char *); extern int do_help(const char *); +extern int do_nlst(const char *); #endif /*end of _DO_CMD_H*/ diff --git a/server/src/parse_cmd.c b/server/src/parse_cmd.c index f555d71..ce4b8e5 100644 --- a/server/src/parse_cmd.c +++ b/server/src/parse_cmd.c @@ -33,7 +33,7 @@ struct parse_cmd{ const char *commands[] = {"USER","PASS","SYST","QUIT","RETR","STOR","RNFR","RNTO","ABOR","DELE", "RMD","MKD","PWD","CWD","CDUP","PORT","NOOP","PASV","TYPE","MODE", - "STAT","STRU","LIST", "REST", "SIZE", "SITE", "HELP"}; /*服务器支持的所有命令*/ + "STAT","STRU","LIST", "REST", "SIZE", "SITE", "HELP", "NLST"}; /*服务器支持的所有命令*/ static int _line_cmd(char *line_buf, struct parse_cmd *user_cmd) { @@ -238,6 +238,10 @@ int parse_cmd(char *p_buf) debug_printf("call do_help()\n"); do_help(user_cmd.arg); break; + case 28: + debug_printf("call do_nlst()\n"); + do_nlst(user_cmd.arg); + break; default: debug_printf("call failed()\n"); failed(user_cmd.cmd); -- 2.11.4.GIT