aboutsummaryrefslogtreecommitdiff
path: root/networking/ftpd.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-03-18 00:45:00 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-03-18 00:45:00 +0000
commit1432cb4bd9daf304111dd19e0011f8756c32e327 (patch)
tree89accfc8fd6cef0d885cbb890e5b484a29fcfaf0 /networking/ftpd.c
parent3a7a1eba2e2b3cc05f000fc739d3548dd0a0872d (diff)
downloadbusybox-w32-1432cb4bd9daf304111dd19e0011f8756c32e327.tar.gz
busybox-w32-1432cb4bd9daf304111dd19e0011f8756c32e327.tar.bz2
busybox-w32-1432cb4bd9daf304111dd19e0011f8756c32e327.zip
ftpd: add support for MDTM, I see clients often use it,
it may allow client-side caching. function old new delta ftpd_main 2232 2306 +74 gmtime_r - 19 +19 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 93/0) Total: 93 bytes
Diffstat (limited to 'networking/ftpd.c')
-rw-r--r--networking/ftpd.c80
1 files changed, 69 insertions, 11 deletions
diff --git a/networking/ftpd.c b/networking/ftpd.c
index f005d129c..b295ddf4f 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -7,7 +7,9 @@
7 * Licensed under GPLv2, see file LICENSE in this tarball for details. 7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 * 8 *
9 * Only subset of FTP protocol is implemented but vast majority of clients 9 * Only subset of FTP protocol is implemented but vast majority of clients
10 * should not have any problem. You have to run this daemon via inetd. 10 * should not have any problem.
11 *
12 * You have to run this daemon via inetd.
11 */ 13 */
12 14
13#include "libbb.h" 15#include "libbb.h"
@@ -172,11 +174,11 @@ cmdio_write(uint32_t status_str, const char *str)
172 char *response; 174 char *response;
173 int len; 175 int len;
174 176
175 /* FTP allegedly uses telnet protocol for command link. 177 /* FTP uses telnet protocol for command link.
176 * In telnet, 0xff is an escape char, and needs to be escaped: */ 178 * In telnet, 0xff is an escape char, and needs to be escaped: */
177 response = escape_text((char *) &status_str, str, (0xff << 8) + '\r'); 179 response = escape_text((char *) &status_str, str, (0xff << 8) + '\r');
178 180
179 /* ?! does FTP send embedded LFs as NULs? wow */ 181 /* FTP sends embedded LFs as NULs */
180 len = replace_char(response, '\n', '\0'); 182 len = replace_char(response, '\n', '\0');
181 183
182 response[len++] = '\n'; /* tack on trailing '\n' */ 184 response[len++] = '\n'; /* tack on trailing '\n' */
@@ -315,6 +317,7 @@ handle_feat(unsigned status)
315 cmdio_write_raw(" EPSV\r\n" 317 cmdio_write_raw(" EPSV\r\n"
316 " PASV\r\n" 318 " PASV\r\n"
317 " REST STREAM\r\n" 319 " REST STREAM\r\n"
320 " MDTM\r\n"
318 " SIZE\r\n"); 321 " SIZE\r\n");
319 cmdio_write(status, " Ok"); 322 cmdio_write(status, " Ok");
320} 323}
@@ -726,11 +729,43 @@ handle_stat_file(void)
726 handle_dir_common(LONG_LISTING + USE_CTRL_CONN); 729 handle_dir_common(LONG_LISTING + USE_CTRL_CONN);
727} 730}
728 731
732/* This can be extended to handle MLST, as all info is available
733 * in struct stat for that:
734 * MLST file_name
735 * 250-Listing file_name
736 * type=file;size=4161;modify=19970214165800; /dir/dir/file_name
737 * 250 End
738 * Nano-doc:
739 * MLST [<file or dir name, "." assumed if not given>]
740 * Returned name should be either the same as requested, or fully qualified.
741 * If there was no parameter, return "" or (preferred) fully-qualified name.
742 * Returned "facts" (case is not important):
743 * size - size in octets
744 * modify - last modification time
745 * type - entry type (file,dir,OS.unix=block)
746 * (+ cdir and pdir types for MLSD)
747 * unique - unique id of file/directory (inode#)
748 * perm -
749 * a: can be appended to (APPE)
750 * d: can be deleted (RMD/DELE)
751 * f: can be renamed (RNFR)
752 * r: can be read (RETR)
753 * w: can be written (STOR)
754 * e: can CWD into this dir
755 * l: this dir can be listed (dir only!)
756 * c: can create files in this dir
757 * m: can create dirs in this dir (MKD)
758 * p: can delete files in this dir
759 * UNIX.mode - unix file mode
760 */
729static void 761static void
730handle_size(void) 762handle_size_or_mdtm(int need_size)
731{ 763{
732 struct stat statbuf; 764 struct stat statbuf;
733 char buf[sizeof(STR(FTP_STATFILE_OK)" %"OFF_FMT"u\r\n") + sizeof(off_t)*3]; 765 struct tm broken_out;
766 char buf[(sizeof("NNN %"OFF_FMT"u\r\n") + sizeof(off_t) * 3)
767 | sizeof("NNN YYYYMMDDhhmmss\r\n")
768 ];
734 769
735 if (!G.ftp_arg 770 if (!G.ftp_arg
736 || stat(G.ftp_arg, &statbuf) != 0 771 || stat(G.ftp_arg, &statbuf) != 0
@@ -739,7 +774,18 @@ handle_size(void)
739 WRITE_ERR(FTP_FILEFAIL); 774 WRITE_ERR(FTP_FILEFAIL);
740 return; 775 return;
741 } 776 }
742 sprintf(buf, STR(FTP_STATFILE_OK)" %"OFF_FMT"u\r\n", statbuf.st_size); 777 if (need_size) {
778 sprintf(buf, STR(FTP_STATFILE_OK)" %"OFF_FMT"u\r\n", statbuf.st_size);
779 } else {
780 gmtime_r(&statbuf.st_mtime, &broken_out);
781 sprintf(buf, STR(FTP_STATFILE_OK)" %04u%02u%02u%02u%02u%02u\r\n",
782 broken_out.tm_year + 1900,
783 broken_out.tm_mon,
784 broken_out.tm_mday,
785 broken_out.tm_hour,
786 broken_out.tm_min,
787 broken_out.tm_sec);
788 }
743 cmdio_write_raw(buf); 789 cmdio_write_raw(buf);
744} 790}
745 791
@@ -936,6 +982,7 @@ enum {
936 const_FEAT = mk_const4('F', 'E', 'A', 'T'), 982 const_FEAT = mk_const4('F', 'E', 'A', 'T'),
937 const_HELP = mk_const4('H', 'E', 'L', 'P'), 983 const_HELP = mk_const4('H', 'E', 'L', 'P'),
938 const_LIST = mk_const4('L', 'I', 'S', 'T'), 984 const_LIST = mk_const4('L', 'I', 'S', 'T'),
985 const_MDTM = mk_const4('M', 'D', 'T', 'M'),
939 const_MKD = mk_const3('M', 'K', 'D'), 986 const_MKD = mk_const3('M', 'K', 'D'),
940 const_MODE = mk_const4('M', 'O', 'D', 'E'), 987 const_MODE = mk_const4('M', 'O', 'D', 'E'),
941 const_NLST = mk_const4('N', 'L', 'S', 'T'), 988 const_NLST = mk_const4('N', 'L', 'S', 'T'),
@@ -1112,7 +1159,12 @@ int ftpd_main(int argc, char **argv)
1112 return 0; 1159 return 0;
1113 } 1160 }
1114 else if (cmdval == const_USER) 1161 else if (cmdval == const_USER)
1115 WRITE_OK(FTP_GIVEPWORD); 1162 /* This would mean "ok, now give me PASS". */
1163 /*WRITE_OK(FTP_GIVEPWORD);*/
1164 /* vsftpd can be configured to not require that,
1165 * and this also saves one roundtrip:
1166 */
1167 WRITE_OK(FTP_LOGINOK);
1116 else if (cmdval == const_PASS) 1168 else if (cmdval == const_PASS)
1117 WRITE_OK(FTP_LOGINOK); 1169 WRITE_OK(FTP_LOGINOK);
1118 else if (cmdval == const_NOOP) 1170 else if (cmdval == const_NOOP)
@@ -1134,14 +1186,20 @@ int ftpd_main(int argc, char **argv)
1134 else if (cmdval == const_CDUP) /* cd .. */ 1186 else if (cmdval == const_CDUP) /* cd .. */
1135 handle_cdup(); 1187 handle_cdup();
1136 /* HELP is nearly useless, but we can reuse FEAT for it */ 1188 /* HELP is nearly useless, but we can reuse FEAT for it */
1189 /* lftp uses FEAT */
1137 else if (cmdval == const_HELP || cmdval == const_FEAT) 1190 else if (cmdval == const_HELP || cmdval == const_FEAT)
1138 handle_feat(cmdval == const_HELP ? STRNUM32(FTP_HELP) : STRNUM32(FTP_STATOK)); 1191 handle_feat(cmdval == const_HELP
1192 ? STRNUM32(FTP_HELP)
1193 : STRNUM32(FTP_STATOK)
1194 );
1139 else if (cmdval == const_LIST) /* ls -l */ 1195 else if (cmdval == const_LIST) /* ls -l */
1140 handle_list(); 1196 handle_list();
1141 else if (cmdval == const_NLST) /* "name list", bare ls */ 1197 else if (cmdval == const_NLST) /* "name list", bare ls */
1142 handle_nlst(); 1198 handle_nlst();
1143 else if (cmdval == const_SIZE) 1199 /* SIZE is crucial for wget's download indicator etc */
1144 handle_size(); 1200 /* Mozilla, lftp use MDTM (presumably for caching) */
1201 else if (cmdval == const_SIZE || cmdval == const_MDTM)
1202 handle_size_or_mdtm(cmdval == const_SIZE);
1145 else if (cmdval == const_STAT) { 1203 else if (cmdval == const_STAT) {
1146 if (G.ftp_arg == NULL) 1204 if (G.ftp_arg == NULL)
1147 handle_stat(); 1205 handle_stat();
@@ -1194,7 +1252,7 @@ int ftpd_main(int argc, char **argv)
1194 else { 1252 else {
1195 /* Which unsupported commands were seen in the wild? 1253 /* Which unsupported commands were seen in the wild?
1196 * (doesn't necessarily mean "we must support them") 1254 * (doesn't necessarily mean "we must support them")
1197 * lftp 3.6.3: MDTM - works fine without it anyway 1255 * foo 1.2.3: XXXX - comment
1198 */ 1256 */
1199 cmdio_write_raw(STR(FTP_BADCMD)" Unknown command\r\n"); 1257 cmdio_write_raw(STR(FTP_BADCMD)" Unknown command\r\n");
1200 } 1258 }