📄 file.c
字号:
/* file.c * * This file is part of ftpd. * * This file handles: * * ALLO APPE CDUP CWD DELE LIST MDTM MODE MKD NLST PWD REST RETR * RMD RNFR RNTO SITE SIZE STAT STOR STOU STRU SYST TYPE * * 01/25/96 Initial Release Michael Temari, <temari@ix.netcom.com> */#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <string.h>#include <time.h>#include <net/hton.h>#include <net/gen/in.h>#include <net/gen/inet.h>#include <net/gen/tcp.h>#include "ftpd.h"#include "access.h"#include "file.h"#include "net.h"_PROTOTYPE(static int fdxcmd, (char *xcmd, char *args));_PROTOTYPE(static int endfdxcmd, (int fd));_PROTOTYPE(static int asciisize, (char *filename, unsigned long *filesize));_PROTOTYPE(static int cnvtfile, (char *name, char **name2));_PROTOTYPE(static int procfile, (char *name));_PROTOTYPE(static int sendfile, (char *name, int xmode));_PROTOTYPE(static int recvfile, (char *name, int xmode));_PROTOTYPE(static char *uniqname, (void));_PROTOTYPE(static int docrc, (char *buff, int xmode));_PROTOTYPE(static char *path, (char *fname));#define SEND_FILE 0#define SEND_NLST 1#define SEND_LIST 2#define RECV_FILE 0#define RECV_APND 1#define RECV_UNIQ 2#define CNVT_ERROR 0#define CNVT_NONE 1#define CNVT_TAR 2#define CNVT_TAR_Z 3#define CNVT_COMP 4#define CNVT_TAR_GZ 5#define CNVT_GZIP 6#define CNVT_UNCOMP 7#define CMD_SH "/bin/sh"#define CMD_NLST "ls"#define CMD_LIST "ls -lA"#define CMD_CRC "crc"static char *msg550 = "550 %s %s.\r\n";static unsigned long file_restart = 0;static char rnfr[256];static char buffer[8192];static char bufout[8192];static cmdpid = -1;/* allocate, we don't need no stink'n allocate */int doALLO(buff)char *buff;{ printf("202 ALLO command not needed at this site.\r\n"); return(GOOD);}/* append to a file if it exists */int doAPPE(buff)char *buff;{ return(recvfile(buff, RECV_APND));}/* change to parent directory */int doCDUP(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); return(doCWD(".."));}/* change directory */int doCWD(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); if(chdir(buff)) printf(msg550, buff, strerror(errno)); else printf("250 %s command okay.\r\n", line); return(GOOD);}/* remove a file */int doDELE(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); if(unlink(buff)) printf(msg550, buff, strerror(errno)); else { printf("250 File \"%s\" deleted.\r\n", buff); logit("DELE", path(buff)); } return(GOOD);}/* directory listing */int doLIST(buff)char *buff;{ file_restart = 0; return(sendfile(buff, SEND_LIST));}/* file modification time, btw when will this be put into an RFC */int doMDTM(buff)char *buff;{struct stat st;struct tm *t; if(ChkLoggedIn()) return(GOOD); if(stat(buff, &st)) { printf(msg550, buff, strerror(errno)); return(GOOD); } if((st.st_mode & S_IFMT) != S_IFREG) { printf("550 Not a regular file.\r\n"); return(GOOD); } t = gmtime(&st.st_mtime); printf("215 %04d%02d%02d%02d%02d%02d\r\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); return(GOOD);}/* mode */int doMODE(buff)char *buff;{ switch(*buff) { case 's': case 'S': printf("200 Mode set to %c.\r\n", *buff); break; default: printf("501 Unknown mode %c.\r\n", *buff); } return(GOOD);}/* make a directory */int doMKD(buff)char *buff;{ mode_t mask; if(ChkLoggedIn()) return(GOOD); if(anonymous) mask = umask(0000); if(mkdir(buff, 0777)) printf(msg550, buff, strerror(errno)); else { printf("257 \"%s\" directory created.\r\n", buff); logit("MKD ", path(buff)); } if(anonymous) (void) umask(mask); return(GOOD);}/* name listing */int doNLST(buff)char *buff;{ file_restart = 0; return(sendfile(buff, SEND_NLST));}/* where are we */int doPWD(buff)char *buff;{char dir[128]; if(ChkLoggedIn()) return(GOOD); if(getcwd(dir, sizeof(dir)) == (char *)NULL) printf(msg550, buff, strerror(errno)); else printf("251 \"%s\" is current directory.\r\n", dir); return(GOOD);}/* restart command */int doREST(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); file_restart = atol(buff); printf("350 Next file transfer will restart at %lu.\r\n", file_restart); return(GOOD);}/* they want a file */int doRETR(buff)char *buff;{ return(sendfile(buff, SEND_FILE));}/* remove a directory */int doRMD(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); if(rmdir(buff)) printf(msg550, buff, strerror(errno)); else { printf("250 Directory \"%s\" deleted.\r\n", buff); logit("RMD ", path(buff)); } return(GOOD);}/* rename from */int doRNFR(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); strncpy(rnfr, buff, sizeof(rnfr)); rnfr[sizeof(rnfr)-1] = '\0'; printf("350 Got RNFR waiting for RNTO.\r\n"); return(GOOD);}/* rename to */int doRNTO(buff)char *buff;{ if(ChkLoggedIn()) return(GOOD); if(rnfr[0] == '\0') { printf("550 Rename failed.\r\n"); return(GOOD); } if(rename(rnfr, buff) < 0) printf("550 Rename failed. Error %s\r\n", strerror(errno)); else { printf("250 Renamed %s to %s.\r\n", rnfr, buff); logit("RNFR", path(rnfr)); logit("RNTO", path(buff)); } rnfr[0] = '\0'; return(GOOD);}static int docrc(buff, xmode)char *buff;int xmode;{unsigned short cs;long fs;int fd;int s;char *p; if((fd = fdxcmd(CMD_CRC, buff)) < 0) { printf("501 Could not obtain CRC.\r\n"); return(GOOD); } if(xmode == 0) printf("201-SITE CRC \"%s\"\r\n", buff); while(1) { p = buffer; while(1) { if((s = read(fd, p, 1)) != 1) { if(xmode == 0) printf("201 SITE CRC DONE.\r\n"); else printf("501 Could not obtain CRC.\r\n"); endfdxcmd(fd); return(GOOD); } if(*p == '\n') { *p++ = '\r'; *p++ = '\n'; *p = '\0'; break; } p++; } if(xmode != 0) break; printf(" %s", buffer); } cs = atoi(buffer); fs = atol(buffer+6); printf("201 CRC %05u %ld.\r\n", cs, fs); endfdxcmd(fd); return(GOOD);}/* site specific */int doSITE(buff)char *buff;{char *args; strncpy(line, buff, sizeof(line)); cvtline(&args); if(!strcmp(line, "CRC") || !strcmp(line, "CCRC")) return(docrc(args, strcmp(line, "CRC"))); printf("501 Unknown SITE command %s.\r\n", line); return(GOOD);}/* file size, btw when will this be put into an RFC */int doSIZE(buff)char *buff;{struct stat st;unsigned long filesize; if(ChkLoggedIn()) return(GOOD); if(stat(buff, &st)) { printf(msg550, buff, strerror(errno)); return(GOOD); } if((st.st_mode & S_IFMT) != S_IFREG) { printf("550 Not a regular file.\r\n"); return(GOOD); } filesize = st.st_size; if(type == TYPE_A) if(asciisize(buff, &filesize)) return(GOOD); printf("215 %lu\r\n", filesize); return(GOOD);}/* server status, or file status */int doSTAT(buff)char *buff;{time_t now;struct tm *tm;int fd;int s; if(!*buff) { (void) time(&now); tm = localtime(&now); printf("211-%s(%s:%u) FTP server status:\r\n", myhostname, inet_ntoa(myipaddr), ntohs(myport)); printf(" Version %s ", FtpdVersion); printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec, tzname[tm->tm_isdst]); printf(" Connected to %s:%u\r\n", inet_ntoa(rmtipaddr), ntohs(rmtport)); if(!loggedin) printf(" Not logged in\r\n"); else printf(" Logged in %s\r\n", username); printf(" TYPE: %s\r\n",(type == TYPE_A) ? "Ascii" : "Binary"); printf("211 End of status\r\n"); return(GOOD); } if(ChkLoggedIn()) return(GOOD); printf("211-Status of %s:\r\n", buff); if((fd = fdxcmd(CMD_LIST, buff)) < 0) printf(" Could not retrieve status"); else { while((s = read(fd, buffer, 1)) == 1) { if(*buffer == '\n') printf("\r\n"); else printf("%c", *buffer); } endfdxcmd(fd); } printf("211 End of status\r\n"); return(GOOD);}/* hey look, we're getting a file */int doSTOR(buff)char *buff;{ return(recvfile(buff, RECV_FILE));}/* hey, get a file unique */int doSTOU(buff)char *buff;{ return(recvfile(buff, RECV_UNIQ));}/* structure */int doSTRU(buff)char *buff;{ switch(*buff) { case 'f': case 'F': printf("200 Structure set to %c.\r\n", *buff); break; default: printf("501 Unknown structure %c.\r\n", *buff); } return(GOOD);}/* we're UNIX and proud of it! */int doSYST(buff)char *buff;{ printf("215 UNIX Type: L8\r\n"); return(GOOD);}/* change transfer type */int doTYPE(buff)char *buff;{ if(*(buff+1) != '\0') { printf("501 Syntax error in parameters.\r\n"); return(GOOD); } switch(*buff) { case 'A': case 'a': type = TYPE_A; printf("200 Type set to A.\r\n"); break; case 'I': case 'i': type = TYPE_I; printf("200 Type set to I.\r\n"); break; default: printf("501 Invalid type %c.\r\n", *buff); } return(GOOD);}static int fdxcmd(xcmd, args)char *xcmd;char *args;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -