一个简单的文件共享工程 -- FileServer
来源:互联网 发布:淘宝天猫网店交易平台 编辑:程序博客网 时间:2024/05/17 07:54
FileServer文件夹中文件:
FileServer.h:
#ifndef __FILE_SERVER_H__#define __FILE_SERVER_H__#include "../TMServer/TMServer.h"class FileServer : public TMServer{public: FileServer(const char * host, const char * serv); ~FileServer();protected: virtual bool handle(ConnNode & conn, unsigned char cmd, char * data, unsigned short uslen);private: bool handle_ls_req(ConnNode & conn, char * data, unsigned short uslen); bool handle_cd_req(ConnNode & conn, char * data, unsigned short uslen); bool handle_mkdir_req(ConnNode & conn, char * data, unsigned short uslen); bool handle_touch_req(ConnNode & conn, char * data, unsigned short uslen); bool handle_rm_req(ConnNode & conn, char * data, unsigned short uslen); bool handle_download_req(ConnNode & conn, char * data, unsigned short uslen); bool handle_upload_req(ConnNode & conn, char * data, unsigned short uslen);private: void writelength(char * buff, unsigned short & uslen); int checkdir(char * cwd, char * data, char * buff, unsigned short uslen); int checkall(char * cwd, char *& data, bool & dir, char * buff, unsigned short uslen); bool mkdir(char *& data, char * buff, unsigned short uslen); bool rmcwd(char * buff, unsigned short uslen); bool upsend(int sockfd, unsigned char state, char * buff, unsigned short uslen); int upfile(int sockfd, char * filename, char * buff, unsigned short uslen); int updir(int sockfd, char * pathname, char * buff, unsigned short uslen);};#endifFileServer.cpp:
#include <errno.h>#include <fcntl.h>#include <sys/stat.h>#include <cstdio>#include <cstring>#include <cassert>#include "../ByteStream/ByteStream.h"#include "../Head/Command.h"#include "FileServer.h"FileServer::FileServer(const char * host, const char * serv) : TMServer(host, serv){ }FileServer::~FileServer(){ }bool FileServer::handle(ConnNode & conn, unsigned char cmd, char * data, unsigned short uslen){ switch (cmd) { case ls: { return(handle_ls_req(conn, data, uslen)); } case cd: { return(handle_cd_req(conn, data, uslen)); } case mk: { return(handle_mkdir_req(conn, data, uslen)); } case touch: { return(handle_touch_req(conn, data, uslen)); } case rm: { return(handle_rm_req(conn, data, uslen)); } case download: { return(handle_download_req(conn, data, uslen)); } case upload: { return(handle_upload_req(conn, data, uslen)); } default: { return(false); } }}bool FileServer::handle_ls_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; const int reserved = sizeof(unsigned short) + sizeof(unsigned char); char * ptr = buff + reserved; unsigned short left = BUFFSIZ - 1 - reserved; int n; if (-1 == (n = checkdir(conn.cwd, data, ptr, left))) { return(false); } else if (1 == n) { *ptr = '\0'; struct dirent * dirp; DIR * dp; if (NULL == (dp = opendir("."))) { snprintf(ptr, left, "%s\n", strerror(errno)); } else { bool fine = true; while (NULL != (dirp = readdir(dp))) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } int len = strlen(dirp->d_name); if (left <= len + 1) { buff[sizeof(unsigned short)] = (unsigned char)' '; writelength(buff, uslen); buff[sizeof(unsigned short)] = (unsigned char)0; if (!send(conn.sockfd, buff, uslen)) { fine = false; break; } ptr = buff + reserved; left = BUFFSIZ - 1 - reserved; } snprintf(ptr, left, "%s\n", dirp->d_name); ptr += len + 1; left -= len + 1; } if (-1 == closedir(dp)) { printf("closedir error: %s\n", strerror(errno)); } if (!fine) { return(false); } } } buff[sizeof(unsigned short)] = (unsigned char)' '; writelength(buff, uslen); buff[sizeof(unsigned short)] = (unsigned char)1; return(send(conn.sockfd, buff, uslen));}bool FileServer::handle_cd_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; const int reserved = sizeof(unsigned short); char * ptr = buff + reserved; unsigned short left = BUFFSIZ - 1 - reserved; if (0 == strlen(data)) { strcpy(conn.cwd, TMServer::ConnNode::root); *ptr = '\0'; } else { int n; if (-1 == (n = checkdir(conn.cwd, data, ptr, left))) { return(false); } else if (1 == n) { strcpy(conn.cwd, ptr); *ptr = '\0'; } } writelength(buff, uslen); return(send(conn.sockfd, buff, uslen));}bool FileServer::handle_mkdir_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; const int reserved = sizeof(unsigned short); char * ptr = buff + reserved; unsigned short left = BUFFSIZ - 1 - reserved; if (-1 == chdir(conn.cwd)) { printf("chdir to %s error: %s\n", conn.cwd, strerror(errno)); return(false); } if (!mkdir(data, ptr, left)) { writelength(buff, uslen); return(send(conn.sockfd, buff, uslen)); } int len = strlen(data); if ('/' != data[len - 1] && -1 == ::mkdir(data, DIR_MODE) && EEXIST != errno) { snprintf(ptr, left, "%s\n", strerror(errno)); } else { *ptr = '\0'; } writelength(buff, uslen); return(send(conn.sockfd, buff, uslen));}bool FileServer::handle_touch_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; const int reserved = sizeof(unsigned short); char * ptr = buff + reserved; unsigned short left = BUFFSIZ - 1 - reserved; if (-1 == chdir(conn.cwd)) { printf("chdir to %s error: %s\n", conn.cwd, strerror(errno)); return(false); } if (!mkdir(data, ptr, left)) { writelength(buff, uslen); return(send(conn.sockfd, buff, uslen)); } int len = strlen(data); if ('/' != data[len - 1]) { int fd; if (-1 == (fd = open(data, O_WRONLY | O_CREAT | O_EXCL, FILE_MODE))) { snprintf(ptr, left, "%s\n", strerror(errno)); } else { if (-1 == ::close(fd)) { printf("close error: %s\n", strerror(errno)); } *ptr = '\0'; } } else { snprintf(ptr, left, "Invalid filename\n"); } writelength(buff, uslen); return(send(conn.sockfd, buff, uslen));}bool FileServer::handle_rm_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; const int reserved = sizeof(unsigned short); char * ptr = buff + reserved; unsigned short left = BUFFSIZ - 1 - reserved; bool dir; int n; if (-1 == (n = checkall(conn.cwd, data, dir, ptr, left))) { return(false); } else if (1 == n) { if (dir) { bool root = (0 == strcmp(TMServer::ConnNode::root, ptr)); if (rmcwd(ptr, left)) { if (!root && -1 == rmdir(ptr)) { snprintf(ptr, left, "%s\n", strerror(errno)); } else { *ptr = '\0'; } } adjustcwd(); } else { if (-1 == unlink(data)) { snprintf(ptr, left, "%s\n", strerror(errno)); } else { *ptr = '\0'; } } } writelength(buff, uslen); return(send(conn.sockfd, buff, uslen));}bool FileServer::handle_download_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; const int reserved = sizeof(unsigned short) + sizeof(unsigned char); char * ptr = buff + reserved; unsigned short left = BUFFSIZ - 1 - reserved; bool dir; int n; if (-1 == (n = checkall(conn.cwd, data, dir, ptr, left))) { return(false); } else if (1 == n) { if (dir) { if (-1 == chdir("..")) { snprintf(ptr, left, "Failed when chdir\n"); } else { char pathname[PATH_MAX + 1] = { 0 }; int index = strlen(ptr) - 2; while (index >= 0) { if ('/' == ptr[index]) { break; } --index; } ++index; strcpy(pathname, ptr + index); if (1 == (n = updir(conn.sockfd, pathname, ptr, left))) { *ptr = '\0'; } } } else { if (1 == (n = upfile(conn.sockfd, data, ptr, left))) { *ptr = '\0'; } } } if (-1 == n) { return(false); } return(upsend(conn.sockfd, done, buff, strlen(ptr) + 1));}bool FileServer::handle_upload_req(ConnNode & conn, char * data, unsigned short uslen){ char buff[BUFFSIZ] = { 0 }; int fd = -1; char laststate = done; if (-1 == chdir(conn.cwd)) { printf("chdir to %s error: %s\n", conn.cwd, strerror(errno)); return(false); } while (true) { unsigned short uslen = sizeof(unsigned short); if (!setrcvlow(conn.sockfd, uslen)) { return(false); } if (!recv(conn.sockfd, buff, uslen)) { return(false); } IBStream is(buff, uslen); is >> uslen; assert(uslen > 0); if (!setrcvlow(conn.sockfd, uslen)) { return(false); } if (!recv(conn.sockfd, buff, uslen)) { return(false); } switch (buff[0]) { case snddir: { if (-1 == ::mkdir(buff + 1, DIR_MODE) && EEXIST != errno) { printf("mkdir error: %s\n", strerror(errno)); } break; } case sndfile: { if (-1 != fd) { ::close(fd); } int index = 0; while (++index > 0 && -1 != access(buff + 1, F_OK)) { snprintf(buff + 1 + (uslen - 2), BUFFSIZ - 1 - uslen, "(%d)", index); } if (-1 == (fd = open(buff + 1, O_WRONLY | O_CREAT, FILE_MODE))) { printf("open error: %s\n", strerror(errno)); } break; } case sndtxt: { if (sndfile != laststate && sndtxt != laststate) { if (-1 != fd) { ::close(fd); } printf("error: state from (%d) to (%d)\n", laststate, buff[0]); return(false); } uslen -= 1; if (-1 != fd) { if (uslen != write(fd, buff + 1, uslen)) { printf("write error: %s\n", strerror(errno)); } } break; } case done: { if (-1 != fd) { ::close(fd); } return(true); } default: { if (-1 != fd) { ::close(fd); } printf("error: unknown state (%d)\n", buff[0]); return(false); } } laststate = buff[0]; }}void FileServer::writelength(char * buff, unsigned short & uslen){ const int reserved = sizeof(unsigned short); OBStream os(buff, reserved); uslen = strlen(buff + reserved); if (uslen > 0) { uslen += 1; } os << uslen; uslen += reserved;}int FileServer::checkdir(char * cwd, char * data, char * buff, unsigned short uslen){ if (-1 == chdir(cwd)) { printf("chdir to %s error: %s\n", cwd, strerror(errno)); return(-1); } if (-1 == chdir(data)) { snprintf(buff, uslen, "%s\n", strerror(errno)); return(0); } if (NULL == getcwd(buff, uslen)) { snprintf(buff, uslen, "%s\n", strerror(errno)); return(0); } int len = strlen(buff); if ('/' != buff[len - 1]) { buff[len] = '/'; buff[len + 1] = '\0'; } if (0 != strncmp(TMServer::ConnNode::root, buff, strlen(TMServer::ConnNode::root))) { snprintf(buff, uslen, "Do not have permission" " to access the directory\n"); return(0); } return(1);}int FileServer::checkall(char * cwd, char *& data, bool & dir, char * buff, unsigned short uslen){ if (-1 == chdir(cwd)) { printf("chdir to %s error: %s\n", cwd, strerror(errno)); return(-1); } struct stat sbuf; if (-1 == lstat(data, &sbuf)) { snprintf(buff, uslen, "%s\n", strerror(errno)); return(0); } if (S_ISDIR(sbuf.st_mode)) { dir = true; return(checkdir(cwd, data, buff, uslen)); } else { dir = false; int n = 1; char * slash = strrchr(data, '/'); if (NULL != slash) { *slash = '\0'; if (1 == (n = checkdir(cwd, data, buff, uslen))) { data = slash + 1; } } return(n); }}bool FileServer::mkdir(char *& data, char * buff, unsigned short uslen){ int len = strlen(data); int index = 0; while (index < len) { if (' ' != data[index] && '/' != data[index] && '.' != data[index]) { break; } ++index; } if (index >= len) { snprintf(buff, uslen, "Invalid filename\n"); return(false); } data += index; len -= index; index = 0; while (index < len) { if ('/' == data[index]) { data[index] = '\0'; if (-1 == ::mkdir(data, DIR_MODE) && EEXIST != errno) { snprintf(buff, uslen, "%s\n", strerror(errno)); return(false); } data[index] = '/'; } ++index; } return(true);}bool FileServer::rmcwd(char * buff, unsigned short uslen){ struct dirent * dirp; DIR * dp; struct stat sbuf; char cwd[PATH_MAX + 1]; bool fine = true; if (NULL == getcwd(cwd, PATH_MAX + 1)) { snprintf(buff, uslen, "Failed when getcwd\n"); return(false); } if (NULL == (dp = opendir("."))) { snprintf(buff, uslen, "Failed when opendir\n"); return(false); } while (NULL != (dirp = readdir(dp))) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } if (-1 == lstat(dirp->d_name, &sbuf)) { continue; } if (S_ISDIR(sbuf.st_mode)) { if (-1 == chdir(dirp->d_name)) { snprintf(buff, uslen, "Failed when chdir\n"); fine = false; break; } if (!rmcwd(buff, uslen)) { fine = false; break; } if (-1 == chdir(cwd)) { snprintf(buff, uslen, "Failed when chdir\n"); fine = false; break; } if (-1 == rmdir(dirp->d_name)) { snprintf(buff, uslen, "Failed when rmdir\n"); fine = false; break; } } else { if (-1 == unlink(dirp->d_name)) { snprintf(buff, uslen, "Failed when unlink\n"); fine = false; break; } } } if (-1 == closedir(dp) && fine) { snprintf(buff, uslen, "Failed when closedir\n"); fine = false; } return(fine);}bool FileServer::upsend(int sockfd, unsigned char state, char * buff, unsigned short uslen){ uslen += sizeof(unsigned char); OBStream os(buff, sizeof(unsigned short) + sizeof(unsigned char)); os << uslen << state; uslen += sizeof(unsigned short); return(send(sockfd, buff, uslen));}int FileServer::upfile(int sockfd, char * filename, char * buff, unsigned short uslen){ const int reserved = sizeof(unsigned short) + sizeof(unsigned char); unsigned short filelen = strlen(filename); strcpy(buff + reserved, filename); if (!upsend(sockfd, sndfile, buff, filelen + 1)) { return(-1); } int fd; if (-1 == (fd = open(filename, O_RDONLY))) { snprintf(buff, uslen, "Failed when open\n"); return(0); } char * ptr = buff + reserved; unsigned short left = uslen - reserved; unsigned short size = 0; int n = 0; int ret = 1; while ((n = read(fd, ptr, left)) > 0) { ptr += n; left -= n; size += n; if (0 == left || size >= 4096 - reserved) { if (!upsend(sockfd, sndtxt, buff, size)) { ret = -1; break; } ptr = buff + reserved; left = uslen - reserved; size = 0; } } do { if (size > 0) { if (!upsend(sockfd, sndtxt, buff, size)) { ret = -1; } } if (1 != ret) { break; } if (-1 == n) { snprintf(buff, uslen, "Failed when read\n"); ret = 0; break; } } while (false); if (-1 == ::close(fd) && 1 == ret) { snprintf(buff, uslen, "Failed when close\n"); ret = 0; } return(ret);}int FileServer::updir(int sockfd, char * pathname, char * buff, unsigned short uslen){ struct dirent * dirp; DIR * dp; struct stat sbuf; int ret = 1; int pathlen = strlen(pathname); const int reserved = sizeof(unsigned short) + sizeof(unsigned char); strcpy(buff + reserved, pathname); if (!upsend(sockfd, snddir, buff, pathlen + 1)) { return(-1); } if (NULL == (dp = opendir(pathname))) { snprintf(buff, uslen, "Failed when opendir\n"); return(0); } while (NULL != (dirp = readdir(dp))) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } strcat(pathname, dirp->d_name); if (-1 == lstat(pathname, &sbuf)) { pathname[pathlen] = '\0'; continue; } if (S_ISDIR(sbuf.st_mode)) { strcat(pathname, "/"); if (1 != (ret = updir(sockfd, pathname, buff, uslen))) { break; } } else { if (1 != (ret = upfile(sockfd, pathname, buff, uslen))) { break; } } pathname[pathlen] = '\0'; } pathname[pathlen] = '\0'; if (-1 == closedir(dp) && 1 == ret) { snprintf(buff, uslen, "Failed when closedir\n"); ret = 0; } return(ret);}Server.cpp:
#include <cstdio>#include <cstdlib>#include "FileServer.h"int main(int argc, char ** argv){ if (3 != argc) { printf("usage: %s <host> <serv>\n", argv[0]); exit(1); } FileServer server(argv[1], argv[2]); server.mainloop(); return(0);}makefile:
objects=Server.o FileServer.o TMServer.o TConnection.o ByteStream.oserver:$(objects)g++ -o server $(objects) Server.o:Server.cppg++ -c Server.cppFileServer.o:FileServer.cpp FileServer.h ../Head/Command.hg++ -c FileServer.cppTMServer.o:../TMServer/TMServer.cpp ../TMServer/TMServer.h ../Head/Command.h ../Head/Uncopy.hg++ -c ../TMServer/TMServer.cppTConnection.o:../TConnection/TConnection.cpp ../TConnection/TConnection.hg++ -c ../TConnection/TConnection.cppByteStream.o:../ByteStream/ByteStream.cpp ../ByteStream/ByteStream.hg++ -c ../ByteStream/ByteStream.cpprebuild:clean serverclean: -rm server $(objects)
- 一个简单的文件共享工程 -- FileServer
- 一个简单的文件共享工程 -- Head
- 一个简单的文件共享工程 -- TConnection
- 一个简单的文件共享工程 -- TMServer
- 一个简单的文件共享工程 -- TMClient
- 一个简单的文件共享工程 -- FileClient
- 一个简单的文件共享工程 -- 总结
- 一个简单的文件共享工程 -- 功能概述
- Puppet的fileserver注意事项
- 一个简单的SpringMVC工程
- ActiveMQ的BlobMessage传输文件示例:完全嵌入式的使用jetty的fileserver
- 创建一个Android程序(简单介绍工程里面各个文件的作用)
- 创建一个Android程序(简单介绍工程里面各个文件的作用)
- 创建一个简单iphone工程的步骤
- 建立一个简单的android涂鸦工程
- 一个简单的JSPweb工程创建过程
- 创建一个简单的maven工程
- 为C6713建立一个简单的工程
- 2012百度之星第二场初始题-1
- 一个简单的文件共享工程 -- TMClient
- 时间复杂度的比较
- 二. Htmlayout之元素value来世今生 select元素封装类
- address
- 一个简单的文件共享工程 -- FileServer
- 分享一下工作以来我看过计算机书籍
- cmd.Parameters.Add()的用法
- 一个简单的文件共享工程 -- FileClient
- 从B树、B+树、B*树谈到R 树
- The Elements of Programming Style
- Linux Shell常用技巧
- Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)
- B树算法应用实例