FileClient文件夹中文件:
FileClient.h:
#ifndef __FILE_CLIENT_H__
#define __FILE_CLIENT_H__
#include
FileClient.cpp:
#include
#include
#include
#include
#include
#include
#include
using std::pair;
#include "../ByteStream/ByteStream.h"
#include "../Head/Command.h"
#include "FileClient.h"
FileClient::FileClient(const char * host, const char * serv)
: TMClient(host, serv)
{
m_cmd.insert(pair("ls", ls));
m_cmd.insert(pair("cd", cd));
m_cmd.insert(pair("mkdir", mk));
m_cmd.insert(pair("touch", touch));
m_cmd.insert(pair("rm", rm));
m_cmd.insert(pair("download", download));
m_cmd.insert(pair("upload", upload));
}
FileClient::~FileClient()
{
}
bool FileClient::handlecmd(char * data)
{
unsigned short uslen = strlen(data);
int fws;
for (fws = 0; fws < uslen; ++fws) {
if (' ' != data[fws]) {
break;
}
}
if (fws >= uslen) {
showusage();
return(true);
}
int fwe;
for (fwe = fws + 1; fwe < uslen; ++fwe) {
if (' ' == data[fwe]) {
break;
}
}
data[fwe] = '\0';
int lws;
for (lws = fwe + 1; lws < uslen; ++lws) {
if (' ' != data[lws]) {
break;
}
}
int lwe;
for (lwe = uslen - 1; lwe > lws; --lwe) {
if (' ' != data[lwe]) {
break;
}
}
data[lwe + 1] = '\0';
map::iterator iter = m_cmd.find(data + fws);
if (m_cmd.end() == iter) {
showusage();
return(true);
}
unsigned char cmd = iter->second;
if (lws > lwe) {
if (ls == cmd) {
data[0] = cmd;
data[1] = '.';
data[2] = '\0';
uslen = 3;
}
else if (cd == cmd) {
data[0] = cmd;
data[1] = '\0';
uslen = 2;
}
else {
showusage();
return(true);
}
}
else {
data += lws - 1;
*data = cmd;
uslen = 1 + (lwe - lws + 1) + 1; /* cmd_sz + str_len + terminator_sz */
}
unsigned short reserved = sizeof(unsigned short);
data -= reserved;
OBStream os(data, reserved);
if (upload == cmd) {
os << (unsigned short)1;
if (!send(data, reserved + 1)) {
return(false);
}
data += reserved + 1;
}
else {
os << uslen;
if (!send(data, reserved + uslen)) {
return(false);
}
}
switch (cmd)
{
case ls:
{
return(handle_ls_res());
}
case cd:
{
return(handle_cd_res());
}
case mk:
{
return(handle_mkdir_res());
}
case touch:
{
return(handle_touch_res());
}
case rm:
{
return(handle_rm_res());
}
case download:
{
return(handle_download_res());
}
case upload:
{
return(handle_upload_res(data));
}
default:
{
return(false);
}
}
}
bool FileClient::send(const char * data, int n)
{
return(TConnection::send(m_connfd, data, n));
}
bool FileClient::recv(char * buff, int n)
{
if (!setrcvlow(m_connfd, n)) {
return(false);
}
return(TConnection::recv(m_connfd, buff, n));
}
void FileClient::showusage()
{
printf("usage:\n"
"\t 1> list directory, Example: ls directory\n"
"\t 2> change directory, Example: cd directory\n"
"\t 3> create empty directory, Example: mkdir directory\n"
"\t 4> create empty file, Example: touch file\n"
"\t 5> remove file or directory, Example: rm file\n"
"\t 6> download file or directory, Example: download file\n"
"\t 7> upload file or directory, Example: upload file\n"
"\t 8> quit\n");
}
bool FileClient::handle_ls_res()
{
char buff[BUFFSIZ] = { 0 };
while (true) {
unsigned short uslen = sizeof(unsigned short);
if (!recv(buff, uslen)) {
return(false);
}
IBStream is(buff, uslen);
is >> uslen;
assert(uslen > 0);
if (!recv(buff, uslen)) {
return(false);
}
printf("%s", buff + sizeof(unsigned char));
if ((unsigned char)1 == buff[0]) {
return(true);
}
}
}
bool FileClient::handle_cd_res()
{
return(handle_normal_res());
}
bool FileClient::handle_mkdir_res()
{
return(handle_normal_res());
}
bool FileClient::handle_touch_res()
{
return(handle_normal_res());
}
bool FileClient::handle_rm_res()
{
return(handle_normal_res());
}
bool FileClient::handle_download_res()
{
char buff[BUFFSIZ] = { 0 };
int fd = -1;
char laststate = done;
while (true) {
unsigned short uslen = sizeof(unsigned short);
if (!recv(buff, uslen)) {
return(false);
}
IBStream is(buff, uslen);
is >> uslen;
assert(uslen > 0);
if (!recv(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);
}
printf("%s", buff + 1);
return(true);
}
default:
{
if (-1 != fd) {
close(fd);
}
printf("error: unknown state (%d)\n", buff[0]);
return(false);
}
}
laststate = buff[0];
}
}
bool FileClient::handle_upload_res(char * data)
{
char buff[BUFFSIZ] = { 0 };
char pathname[PATH_MAX + 1] = { 0 };
struct stat sbuf;
if (-1 == lstat(data, &sbuf)) {
printf("lstat error: %s\n", strerror(errno));
return(true);
}
int index = strlen(data) - 1;
while (index >= 0 && '/' == data[index]) {
--index;
}
while (index >= 0 && '/' != data[index]) {
--index;
}
++index;
strcpy(pathname, data + index);
data[index] = '\0';
if (0 == strlen(data)) {
strcpy(data, ".");
}
if (-1 == chdir(data)) {
printf("chdir error: %s\n", strerror(errno));
return(true);
}
if (S_ISDIR(sbuf.st_mode)) {
int len = strlen(pathname);
if ('/' != pathname[len - 1]) {
strcat(pathname, "/");
}
if (-1 == updir(pathname, buff, BUFFSIZ - 1)) {
return(false);
}
}
else {
if (-1 == upfile(pathname, buff, BUFFSIZ - 1)) {
return(false);
}
}
return(upsend(done, buff, 0));
}
bool FileClient::handle_normal_res()
{
char buff[BUFFSIZ] = { 0 };
unsigned short uslen = sizeof(unsigned short);
if (!recv(buff, uslen)) {
return(false);
}
IBStream is(buff, uslen);
is >> uslen;
if (0 == uslen) {
return(true);
}
if (!recv(buff, uslen)) {
return(false);
}
printf("%s", buff);
return(true);
}
bool FileClient::upsend(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(buff, uslen));
}
int FileClient::upfile(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(sndfile, buff, filelen + 1)) {
return(-1);
}
int fd;
if (-1 == (fd = open(filename, O_RDONLY))) {
printf("open error: %s\n", strerror(errno));
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(sndtxt, buff, size)) {
ret = -1;
break;
}
ptr = buff + reserved;
left = uslen - reserved;
size = 0;
}
}
do {
if (size > 0) {
if (!upsend(sndtxt, buff, size)) {
ret = -1;
}
}
if (1 != ret) {
break;
}
if (-1 == n) {
printf("read error: %s\n", strerror(errno));
ret = 0;
break;
}
} while (false);
if (-1 == ::close(fd)) {
printf("close error: %s\n", strerror(errno));
if (1 == ret) {
ret = 0;
}
}
return(ret);
}
int FileClient::updir(char * pathname, char * buff, unsigned short uslen)
{
struct dirent * dirp;
DIR * dp;
struct stat sbuf;
int ret = 1;
unsigned short pathlen = strlen(pathname);
const int reserved = sizeof(unsigned short) + sizeof(unsigned char);
strcpy(buff + reserved, pathname);
if (!upsend(snddir, buff, pathlen + 1)) {
return(-1);
}
if (NULL == (dp = opendir(pathname))) {
printf("opendir error: %s\n", strerror(errno));
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(pathname, buff, uslen))) {
break;
}
}
else {
if (1 != (ret = upfile(pathname, buff, uslen))) {
break;
}
}
pathname[pathlen] = '\0';
}
pathname[pathlen] = '\0';
if (-1 == closedir(dp)) {
printf("closedir error: %s\n", strerror(errno));
if (1 == ret) {
ret = 0;
}
}
return(ret);
}
Client.cpp:
#include
#include
#include "FileClient.h"
int main(int argc, char ** argv)
{
if (3 != argc) {
printf("usage: %s \n", argv[0]);
exit(1);
}
FileClient client(argv[1], argv[2]);
client.mainloop();
return(0);
}
makefile:
objects=Client.o FileClient.o TMClient.o TConnection.o ByteStream.o
client:$(objects)
g++ -o client $(objects)
Client.o:Client.cpp
g++ -c Client.cpp
FileClient.o:FileClient.cpp FileClient.h ../Head/Command.h
g++ -c FileClient.cpp
TMClient.o:../TMClient/TMClient.cpp ../TMClient/TMClient.h ../Head/Uncopy.h
g++ -c ../TMClient/TMClient.cpp
TConnection.o:../TConnection/TConnection.cpp ../TConnection/TConnection.h
g++ -c ../TConnection/TConnection.cpp
ByteStream.o:../ByteStream/ByteStream.cpp ../ByteStream/ByteStream.h
g++ -c ../ByteStream/ByteStream.cpp
rebuild:clean client
clean:
-rm client $(objects)