📄 ftpcmd.c
字号:
getsockname(datalistenfd,(struct sockaddr *)&pasv_addr,&len);
char temp[80]={0};
int port=ntohs(pasv_addr.sin_port);
int arr_port[2]={0};
arr_port[0] = port/256;
arr_port[1] = port%256;
sprintf(temp,"Entering Passive Mode (%s.%d.%d)",localip,arr_port[0],arr_port[1]);
int i=0;
for(;i<strlen(temp);i++)
{
if (temp[i]=='.')
{
temp[i]=',';
}
}
// 227 后面的参数要时合理的 给出服务器IP地址 和端口号 供客户端连接
ftp_global_var.IsPasv =1; // 保存被动模式
ftp_global_var.pasv_mode_sockfd=datalistenfd;
Tcp_listen(datalistenfd,5); // 开监听
ServiceEcho(227,temp);
return 0;
}
int do_rnfr(char * param)
{
// 先做绝对路径 ,相对路径先放着
// ????????????????
//strcpy(ftp_global_var.oldpathname,ftp_global_var.currpath);
//strcat(ftp_global_var.oldpathname,"/");
strcpy(ftp_global_var.oldpathname,param);
ServiceEcho(350,"Ready for RNTO");
//ServiceEcho(350,ftp_global_var.oldpathname);
/*
if (rename())
{
}
*/
return 0;
}
int do_rnto(char * param)
{
//chdir(ftp_global_var.currpath);
if (rename(ftp_global_var.oldpathname,param)==-1)
{
perror("rename error.");
}
ServiceEcho(250,"Rename successful");
return 0;
}
int do_size(char * param)
{
// 文件状态结构
struct stat filestat;
if (stat(param,&filestat)!=-1 && filestat.st_size != 4096)
{
char temp[80]={0};
sprintf(temp,"%s size = %d",param,filestat.st_size);
ServiceEcho(213,temp);
}
else
{
ServiceEcho(550,"Could not get file size.");
}
return 0;
}
int do_noop(char * param)
{
ServiceEcho(200,"NOOP ok.");
return 0;
}
void userhandler(int sig)
{
ftp_global_var.endseek=0;
}
// 上传文件
int do_stor(char * param)
{
int fd=0;
if (ftp_global_var.isappe== 1)
{
fd=open(param,O_CREAT | O_WRONLY |O_APPEND,0644); // 文件权限
}
else
{
fd=open(param,O_CREAT | O_WRONLY,0644); // 文件权限
}
if (fd<0)
{
if (ftp_global_var.isappe== 1)
{
ServiceEcho(553,"Appe fail.");
}
else
{
ServiceEcho(553,"Create file fail.");
}
return -1;
}
if(ftp_global_var.endseek>0)
{
lseek(fd,ftp_global_var.endseek,SEEK_SET);
//lseek(fd,100000,SEEK_SET);
}
int sendsockfd;
// 父亲进程
if (ftp_global_var.IsPasv)
{
signal(SIGUSR1,userhandler);
if (fork()==0)
{
// 子进程
int sendsockfd = Tcp_accept(ftp_global_var.pasv_mode_sockfd,NULL,NULL);
upload_file(fd,sendsockfd);
shutdown(sendsockfd,0);
Tcp_close(sendsockfd);
close(fd);
kill(getppid(),SIGUSR1);
ServiceEcho(226,"File receive Ok");
exit(0);
}
// 被动连接
//ServiceEcho(150,"Here comes the directory listing"); // 说明已经连接上了。
//ftp_global_var.endseek=0;
ServiceEcho(150,"Ok to send data");
//Tcp_close(ftp_global_var.pasv_mode_sockfd); // 关闭监听
/*
int clisockfd = Tcp_accept(ftp_global_var.pasv_mode_sockfd,NULL,NULL);
Tcp_close(ftp_global_var.pasv_mode_sockfd); // 关闭监听
download_file(fd,clisockfd);
Tcp_close(clisockfd);
*/
}else
{
// 主动连接
struct sockaddr_in servaddr,cliaddr;
int servfd;
int clifd;
memset(&servaddr,0,sizeof(servaddr));
memset(&cliaddr,0,sizeof(cliaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(20);
//servaddr.sin_addr.s_addr = inet_addr();
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_family =AF_INET;
cliaddr.sin_port = htons(ftp_global_var.port_port);
cliaddr.sin_addr.s_addr = inet_addr(ftp_global_var.port_ip);
int len=sizeof(cliaddr);
ftp_global_var.uid = geteuid();
ftp_global_var.gid = getegid();
seteuid(0);
setegid(0);
// 只有ROOT 用户才有权限绑定20端口
// ????????????? 调用语义是有问题的 借用一个函数
sendsockfd = Tcp_service(ftp_global_var.port_ip,20);
//servfd = socket(AF_INET,SOCK_DGRAM,0);
seteuid(ftp_global_var.uid);
setegid(ftp_global_var.gid);
if (fork()==0)
{
connect(sendsockfd,(struct sockaddr *)&cliaddr,len);
upload_file(fd,sendsockfd);
shutdown(sendsockfd,0);
Tcp_close(sendsockfd);
close(fd);
ServiceEcho(226,"File receive Ok");
exit(0);
}
//download_file(fd,servfd);
//shutdown(servfd,0);
//Tcp_close(servfd);
// 主动模式 服务器20 端口去。链接客户端
ServiceEcho(150,"Ok to send data");
}
// 发送文件
return 0;
}
/************************
获得文件
*************************/
int do_retr(char * param)
{
// 检查文件的存在性
if (access(param,0)!=0)
{
//文件不存在
ServiceEcho(550,"fail dot exist.");
return 0;
}else
{
//int
}
// 应该对param 做个判断
char temp[512]={0};
// 文件状态结构
struct stat filestat;
if (stat(param,&filestat)!=-1)
{
// 正确调用
}else
{
// 错误调用
}
if ('A'==ftp_global_var.transmode)
{
sprintf(temp,"Opening ASCII mode data connection for %s (%d bytes).",param,filestat.st_size);
ServiceEcho(150,temp);
}else if('I'==ftp_global_var.transmode)
{
sprintf(temp,"Opening BINARY mode data connection for %s (%d bytes).",param,filestat.st_size );
ServiceEcho(150,temp);
}
int fd=open(param,O_RDONLY);
if (fd<0)
{
ServiceEcho(553,"download file fail.");
return -1;
}
if (ftp_global_var.IsPasv)
{
// 被动链接
int clisockfd = Tcp_accept(ftp_global_var.pasv_mode_sockfd,NULL,NULL);
Tcp_close(ftp_global_var.pasv_mode_sockfd); // 关闭监听
download_file(fd,clisockfd);
Tcp_close(clisockfd);
}
else
{
// 主动连接
struct sockaddr_in servaddr,cliaddr;
int servfd;
int clifd;
memset(&servaddr,0,sizeof(servaddr));
memset(&cliaddr,0,sizeof(cliaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(20);
//servaddr.sin_addr.s_addr = inet_addr();
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_family =AF_INET;
cliaddr.sin_port = htons(ftp_global_var.port_port);
cliaddr.sin_addr.s_addr = inet_addr(ftp_global_var.port_ip);
int len=sizeof(cliaddr);
ftp_global_var.uid = geteuid();
ftp_global_var.gid = getegid();
seteuid(0);
setegid(0);
// 只有ROOT 用户才有权限绑定20端口
// ????????????? 调用语义是有问题的 借用一个函数
servfd = Tcp_service(ftp_global_var.port_ip,20);
//servfd = socket(AF_INET,SOCK_DGRAM,0);
seteuid(ftp_global_var.uid);
setegid(ftp_global_var.gid);
connect(servfd,(struct sockaddr *)&cliaddr,len);
// ServiceEcho(150,"Here comes the directory listing");
download_file(fd,servfd);
shutdown(servfd,0);
Tcp_close(servfd);
//Tcp_close(clifd);
//ServiceEcho(226,"Directory send Ok");
// 主动模式 服务器20 端口去。链接客户端
}
ServiceEcho(226,"File send Ok");
//2. sendfile
//3. 关闭连接
//4. 信息提示
// sendfile
return 0;
}
int do_appe(char * param)
{
ftp_global_var.isappe=1;
do_stor(param);
return 0;
}
int do_abor(char * param)
{
ServiceEcho(226,"Directory send Ok");
return 0;
}
int do_mode(char * param)
{
ServiceEcho(500,"Unknown command");
return 0;
}
// stat 监控状态
int do_stat(char * param)
{
//int up_count=0;
//int down_count=0;
//int up_bytes=0;
//int down_bytes=0;
//struct shared_count readshm;
// 没有上传,下载就 的状态
//Create_shm((key_t)1234,sizeof(struct shared_count),0666 | IPC_CREAT);
//Read_download_shm(&readshm);
char temp[1024]={0};
//printf("%ld %ld %ld %ld ",pshm->upload_count,pshm->download_count,pshm->upload_bytes,pshm->download_bytes);
sprintf(temp,"upload_file=%ld,download_file=%ld,upload_bytes=%ld,download_bytes=%ld",
pshm->upload_count,pshm->download_count,pshm->upload_bytes,pshm->download_bytes);
ServiceEcho(211,temp);
}
/*
发送列表函数
*/
int send_list(int sockfd)
{
struct stat sbuf;
mode_t mode;
char buf[1024];
DIR *dp;
struct dirent *link;
dp=opendir(".");
if (dp==NULL)
{
return -1;
}
while ((link=readdir(dp))!=0)
{
if (lstat(link->d_name, &sbuf)==-1)
{
perror("lstat");
continue;
}
if (strcmp(link->d_name, ".") == 0 || strcmp(link->d_name, "..") == 0)
{
continue;
}
mode=sbuf.st_mode;
char perms[] = "----------";
perms[0]='?';
switch (mode & S_IFMT)
{
case S_IFREG:
perms[0] = '-';
break;
case S_IFDIR:
perms[0] = 'd';
break;
case S_IFLNK:
perms[0] = 'l';
break;
case S_IFIFO:
perms[0] = 'p';
break;
case S_IFSOCK:
perms[0] = 's';
break;
case S_IFCHR:
perms[0] = 'c';
break;
case S_IFBLK:
perms[0] = 'b';
break;
}
if (mode & S_IRUSR)
perms[1] = 'r';
if (mode & S_IWUSR)
perms[2] = 'w';
if (mode & S_IXUSR)
perms[3] = 'x';
if (mode & S_IRGRP)
perms[4] = 'r';
if (mode & S_IWGRP)
perms[5] = 'w';
if (mode & S_IXGRP)
perms[6] = 'x';
if (mode & S_IROTH)
perms[7] = 'r';
if (mode & S_IWOTH)
perms[8] = 'w';
if (mode & S_IXOTH)
perms[9] = 'x';
perms[10] = '\0';
int off=0;
memset(buf,0,sizeof(buf));
off += sprintf(buf+off, "%s ",perms);
off += sprintf (buf + off, " %3d %-8d %-8d ",sbuf.st_nlink, sbuf.st_uid, sbuf.st_gid);
off+=sprintf(buf + off, "%8lu ", (unsigned long)sbuf.st_size);
char* p_date_format = "%b %e %H:%M";
char datebuf[13]={0};
struct tm* p_tm;
struct timeval tv;
long local_time;
gettimeofday(&tv,NULL);
local_time = tv.tv_sec;
p_tm = localtime(&sbuf.st_mtime);
if (sbuf.st_mtime > local_time ||
(local_time - sbuf.st_mtime) > 60*60*24*182)
{
p_date_format = "%b %e %Y";
}
strftime(datebuf, sizeof(datebuf), p_date_format, p_tm);
off += sprintf (buf + off, "%s ", datebuf);
if (S_ISLNK(sbuf.st_mode))
{
char tmp[1024]={0};
readlink(link->d_name,tmp,sizeof(tmp));
off += sprintf (buf + off, "%s -> %s", link->d_name,tmp);
}
else
{
off += sprintf (buf + off, "%s", link->d_name);
}
off += sprintf (buf + off, "%s", "\r\n");
write_loop(sockfd,buf,strlen(buf));
}
closedir(dp);
}
FTPCMD cmd_list[] = {
{"USER", do_user, CHECK_NOLOGIN | NEED_PARAM },
{"PASS", do_pass, CHECK_NOLOGIN },
{"CWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"XCWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"CDUP", do_cdup, CHECK_LOGIN | NO_PARAM },
{"XCUP", do_cdup, CHECK_LOGIN | NO_PARAM },
{"SYST", do_syst, CHECK_LOGIN },
{"PWD", do_pwd, CHECK_LOGIN | NO_PARAM },
{"XPWD", do_pwd, CHECK_LOGIN | NO_PARAM },
{"TYPE", do_type, CHECK_LOGIN | NEED_PARAM },
{"PORT", do_port, CHECK_LOGIN | NEED_PARAM },
{"LIST", do_list, CHECK_LOGIN },
{"NLST", do_nlst, CHECK_LOGIN },
{"CWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"XCWD", do_cwd, CHECK_LOGIN | NEED_PARAM },
{"CDUP", do_cdup, CHECK_LOGIN | NO_PARAM },
{"RMD", do_rmd, CHECK_LOGIN | NEED_PARAM },
{"XRMD", do_rmd, CHECK_LOGIN | NEED_PARAM },
{"MKD", do_mkd, CHECK_LOGIN | NEED_PARAM },
{"XMKD", do_mkd, CHECK_LOGIN | NEED_PARAM },
{"DELE", do_dele, CHECK_LOGIN | NEED_PARAM },
{"REIN", do_rein, CHECK_LOGIN },
{"HELP", do_help, CHECK_LOGIN },
{"QUIT", do_quit, NO_CHECK },
{"REST", do_rest, CHECK_LOGIN | NEED_PARAM },
{"PASV", do_pasv, CHECK_LOGIN | NO_PARAM },
{"RNFR", do_rnfr, CHECK_LOGIN | NEED_PARAM },
{"RNTO", do_rnto, CHECK_LOGIN | NEED_PARAM },
{"SIZE", do_size, CHECK_LOGIN | NEED_PARAM },
{"NOOP", do_noop, NO_CHECK },
{"STOR", do_stor, CHECK_LOGIN | NEED_PARAM },
{"RETR", do_retr, CHECK_LOGIN | NEED_PARAM },
{"APPE", do_appe, CHECK_LOGIN | NEED_PARAM },
{"ABOR", do_abor, CHECK_LOGIN | NO_PARAM },
{"ACCT", NULL,0 },
{"SMNT", NULL,0 },
{"STRU", NULL,0 },
{"MODE", NULL,0 },
{"STOU", NULL,0 },
{"ALLO", NULL,0 },
{"MDTM", NULL, CHECK_LOGIN | NEED_PARAM },
{"SITE", NULL, CHECK_LOGIN | NEED_PARAM },
{"STAT", do_stat, CHECK_LOGIN | NEED_PARAM },
{"MODE", do_mode,CHECK_LOGIN},
{NULL, NULL, 0}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -