/*============================================================================
Name : FtpServer.cbp
Author : Haier
Version : 1.01
Copyright : Copyright (c) 2014
Description : Ftp Server in C, Ansi-style, Compile by Gcc,in Linux
============================================================================*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>//sockaddr_in等结构的定义
#include <netdb.h> //addrinfo等结构的定义
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#define LISTEN_PORT (5500)
#define BUFFER (1024)
#define TRUE (1)
char CurrentDirPath[100];
char CurrentDirName[25];
char help[]=
"get get a file from server\n\
put upload a file to server\n\
pwd display the current directory of server\n\
dir display the files in the current directory of server\n\
cd change the directory of server\n\
? display the whole command which equals 'help'\n\
quit return\n";
char *getDirName(char *dirPathName);
void pwd(int sock);
void dir(int sock);
void cd(int sock,char *DirName);
void cdback(int sock);
void Help(int sock);
void put(int sock,char *FileName);
void get(int sock,char *FileName);
int main(int argc,char *argv[])
{
int sock,sockmsg;
int lengthOfSock,lengthOfSockMsg;
int DataOfsock,DataOfsockmsg;
pid_t Child;
char ClientCmd[10],CmdArg[20];
int LengthOfRead=0;
struct sockaddr_in Server,ServerMsg;
sock=socket(AF_INET,SOCK_STREAM,0);
sockmsg=socket(AF_INET,SOCK_STREAM,0);
if(sock<0 || sockmsg<0)
{
perror("Socket Failed !\n");
exit(1);
}
Server.sin_family=AF_INET;
Server.sin_port =htons(LISTEN_PORT);
Server.sin_addr.s_addr=INADDR_ANY;
ServerMsg.sin_family=AF_INET;
ServerMsg.sin_port =htons(LISTEN_PORT+1);
ServerMsg.sin_addr.s_addr=INADDR_ANY;
if(bind(sock,(struct sockaddr *)&Server,sizeof(Server))<0
|| bind(sockmsg,(struct sockaddr *)&ServerMsg,sizeof(ServerMsg))<0)
{
perror("Bind Failed !\n");
exit(1);
}
lengthOfSock=sizeof(Server);
lengthOfSockMsg=sizeof(ServerMsg);
if(getsockname(sock,(struct sockaddr *)&Server,&lengthOfSock)<0
|| getsockname(sockmsg,(struct sockaddr *)&ServerMsg,&lengthOfSockMsg)<0)
{
perror("GetSockName Fail !\n");
exit(1);
}
printf("Socket port # %d %d\n",ntohs(Server.sin_port),ntohs(ServerMsg.sin_port));
memset(CurrentDirPath,0,sizeof(CurrentDirPath));
getcwd(CurrentDirPath,sizeof(CurrentDirPath));
listen(sock,2);
listen(sockmsg,2);
do
{
DataOfsock=accept(sock,(struct sockaddr *)0,(int *)0);
DataOfsockmsg=accept(sockmsg,(struct sockaddr *)0,(int *)0);
if(DataOfsock==-1 || DataOfsockmsg==-1)
{
perror("Accept Failed !\n");
}
else
{
if((Child=fork())==-1)
{
perror("Fork Failed !\n");
}
//child process
if(Child==0)
{
printf("Connection Succeed ! Client is Coming.\n");
loop: memset(ClientCmd,0,sizeof(ClientCmd));
LengthOfRead=read(DataOfsockmsg,ClientCmd,sizeof(ClientCmd));
if(LengthOfRead<0)
{
perror("Read Failed !\n");
}
else if(LengthOfRead==0)
{
printf("Connection Closed !\n");
close(DataOfsock);
close(DataOfsockmsg);
}
else
{
if(strcmp(ClientCmd,"pwd")==0)
{
pwd(DataOfsock);
goto loop;
}
else if(strcmp(ClientCmd,"dir")==0)
{
dir(DataOfsock);
goto loop;
}
else if(strcmp(ClientCmd,"cd")==0)
{
memset(CmdArg,0,sizeof(CmdArg));
read(DataOfsockmsg,CmdArg,sizeof(CmdArg));
cd(DataOfsock,CmdArg);
goto loop;
}
else if(strcmp(ClientCmd,"cd ..")==0)
{
cdback(DataOfsock);
goto loop;
}
else if(strcmp(ClientCmd,"get")==0)
{
memset(CmdArg,0,sizeof(CmdArg));
read(DataOfsockmsg,CmdArg,sizeof(CmdArg));
get(DataOfsock,CmdArg);
goto loop;
}
else if(strcmp(ClientCmd,"put")==0)
{
memset(CmdArg,0,sizeof(CmdArg));
read(DataOfsockmsg,CmdArg,sizeof(CmdArg));
put(DataOfsock,CmdArg);
goto loop;
}
else if(strcmp(ClientCmd,"?")==0)
{
Help(DataOfsock);
goto loop;
}
else if(strcmp(ClientCmd,"quit")==0)
{
printf("Connection Closed !\n");
close(DataOfsock);
close(DataOfsockmsg);
exit(0);
}
else
{
goto loop;
}
}
}
}
}while(TRUE);
return 0;
}
char *getDirName(char *dirPathName)
{
int i,Length;
int Position;
char *DirName;
if(dirPathName==NULL)
{
printf("Absoultly Path is NULL !\n");
return NULL;
}
Length=strlen(dirPathName);
for(i=Length-1; i>=0; i--)
{
if(dirPathName[i]=='/')
{
Position=i;
break;
}
}
DirName=(char *)malloc(sizeof(char)*(Length-Position+1));
for(i=Position+1; i<Length; i++)
{
DirName[i-Position-1]=dirPathName[i];
}
return DirName;
}
void pwd(int sock)
{
char *PtrToDirName;
memset(CurrentDirPath,0,sizeof(CurrentDirPath));
getcwd(CurrentDirPath,sizeof(CurrentDirPath));
PtrToDirName=getDirName(CurrentDirPath);
strcpy(CurrentDirName,PtrToDirName);
write(sock,CurrentDirName,strlen(CurrentDirName)+1);
}
void dir(int sock)
{
DIR *PtrToDir;
struct dirent *Pent;
int FileCount=0;
int i,fd;
char FileName[30],FileInfo[50],FilePath[100];
struct stat FileStat;
PtrToDir=opendir(CurrentDirPath);
Pent =readdir(PtrToDir);
while(Pent!=NULL)
{
FileCount++;
Pent=readdir(PtrToDir);
}
write(sock,&FileCount,sizeof(int));
closedir(PtrToDir);
if(FileCount<0)
{
return;
}
else
{
PtrToDir=opendir(CurrentDirPath);
for(i=0; i<FileCount; i++)
{
Pent=readdir(PtrToDir);
memset(FileName,0,sizeof(FileName));
memset(FileInfo,0,sizeof(FileInfo));
strcpy(FileName,Pent->d_name);
//check the file is a directory or a file
memset(FilePath,0,sizeof(FilePath));
strcpy(FilePath,CurrentDirPath);
strcat(FilePath,"/");
strcat(FilePath,FileName);
fd=open(FilePath,O_RDONLY,S_IREAD);
fstat(fd,&FileStat);
if(S_ISDIR(FileStat.st_mode))
{
strcat(FileInfo,"dir\t");
strcat(FileInfo,FileName);
}
else
{
strcat(FileInfo,"file\t");
strcat(FileInfo,FileName);
}
write(sock,FileInfo,sizeof(FileInfo));
}
}
closedir(PtrToDir);
}
void cd(int sock,char *DirName)
{
DIR *PtrToDir;
struct dirent *Pent;
int FileCount=0;
int i,Flag=0;
PtrToDir=opendir(CurrentDirPath);
Pent =readdir(PtrToDir);
while(Pent!=NULL)
{
FileCount++;
Pent=readdir(PtrToDir);
}
closedir(PtrToDir);
if(FileCount<=0)
{
return ;
}
else
{
PtrToDir=opendir(CurrentDirPath);
for(i=0; i<FileCount; i++)
{
Pent=readdir(PtrToDir);
if(strcmp(Pent->d_name,DirName)==0)
{
strcat(CurrentDirPath,"/");
strcat(CurrentDirPath,DirName);
Flag=1;
break;
}
}
if(Flag)
{
write(sock,CurrentDirPath,sizeof(CurrentDirPath));
}
closedir(PtrToDir);
}
}
void cdback(int sock)
{
int Length=strlen(CurrentDirPath);
int i;
for(i=Length-1; i>=0; i--)
{
if(CurrentDirPath[i]=='/')
{
CurrentDirPath[i]='\0';
break;
}
CurrentDirPath[i]='\0';
}
// write(sock,CurrentDirPath,sizeof(CurrentDirPath));
}
void Help(int sock)
{
int Length=strlen(help)+1;
write(sock,help,Length);
}
void get(int sock,char *FileName)
{
char FilePath[100];
int fd;
struct stat FileStat;
long FileSize;
char Buffer[BUFFER];
memset(FilePath,0,sizeof(FilePath));
strcpy(FilePath,CurrentDirPath);
strcat(FilePath,"/");
strcat(FilePath,FileName);
fd=open(FilePath,O_RDONLY,S_IREAD);
if(fd>0)
{
fstat(fd,&FileStat);
FileSize=(long)FileStat.st_size;
write(sock,&FileSize,sizeof(long));
memset(Buffer,0,BUFFER);
while(FileSize>BUFFER)
{
read(fd,Buffer,BUFFER);
write(sock,Buffer,sizeof(Buffer));
FileSize -=BUFFER;
}
read(fd,Buffer,FileSize);
write(sock,&Buffer,FileSize);
close(fd);
printf("Transation Finished !");
}
else
{
perror("Open File Failed !\n");
}
}
void put(int sock,char *FileName)
{
char FilePath[100];
int fd;
char Buffer[BUFFER];
long FileSize=0;
memset(FilePath,0,sizeof(FilePath));
strcpy(FilePath,FileName);
strcat(FilePath,"/");
strcat(FilePath,FileName);
fd=open(FilePath,O_RDWR|O_CREAT,S_IREAD|S_IWRITE);
if(fd>0)
{
memset(Buffer,0,BUFFER);
read(sock,&FileSize,sizeof(long));
while(FileSize>BUFFER)
{
read(sock,Buffer,BUFFER);
write(fd,Buffer,BUFFER);
FileSize-=BUFFER;
}
read(sock,Buffer,FileSize);
write(fd,Buffer,FileSize);
close(fd);
printf("Transation complete !\n");
}
else
{
perror("Open File Failed !\n");
}
}