tuyau

Client/server for transfering files (like cp)
git clone https://noulin.net/git/tuyau.git
Log | Files | Refs

commit 3f5d85a450d7748e9ad5d3b165db9c10e8f8750c
parent 664248a9da8c2e92a073b561c7310798a5f4fb5f
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sat, 13 Aug 2022 00:55:33 -0400

send glob and recursive to server

NOTES.md  |  28 +++++--
sclient.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++---------------
sserver.c | 150 +++++++++++++++++++---------------
3 files changed, 311 insertions(+), 138 deletions(-)

Diffstat:
MNOTES.md | 28++++++++++++++++++++--------
Msclient.c | 271++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msserver.c | 150+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
3 files changed, 311 insertions(+), 138 deletions(-)

diff --git a/NOTES.md b/NOTES.md @@ -6,23 +6,32 @@ x./sclient.c NOTES.md dev:tuyauTest/ # new name x./sclient.c NOTES.md dev:tuyauTest/ger.md +## receive ./sclient.c dev:NOTES.md ./sclient.c dev:NOTES.md ../ cp file tuyau://ip/path ->> ADD FILE MODE -frame: +frame send file: 1 byte command 8 bytes token 2 bytes file name length <filename> +2 bytes file mode/permissions 2 bytes path length <path> - optional 8 bytes data size <data> +frame mkdir +1 byte command +8 bytes token +2 bytes file mode/permissions +2 bytes path length +<path> + + > client/server requests client > command reponse < server 1 byte - 0 ok/1 error @@ -30,7 +39,15 @@ client > command port 1032 -- config home ~/.tuyau/config.yml +..- mkdir +..- send files with glob +..- send files recursive +- receive files, glob +- receive files recursive +//- list files in path +..- token, home directory +..- server name ip port in config +..- config home ~/.tuyau/config.yml --- alias: hostname: ip @@ -43,8 +60,3 @@ serverConfig.yml user: token: QE123123 root: /home/rlp/tmp/ -- send files with glob, recursive -- received files, glob, recursive -- list files in path -- token, home directory -- server name ip port in config diff --git a/sclient.c b/sclient.c @@ -19,6 +19,72 @@ #define CONFIG "~/.tuyau/config.yml" +void makeHeader(u8 *buf, u32 *bufip, u8 command, smallDictt *svrInfo, char *sendFile, char *destPath, u64 **filesize) { + + // command + // token + // file name max 8k + // file mode + // dest path + + lv(sendFile); + lv(destPath); + + // command + buf[0] = command; + // token + memcpy(buf + 1, $(svrInfo, "token"), 8); + + u32 bufi = 0; + if (command == 0) { + // send file + // file name max 8k + u16 *filenameLength = (u16*)(buf + 9); + char *filename = basename(sendFile); + *filenameLength = lenG(filename); + memcpy(buf + 11, filename, lenG(filename)); + bufi = 11 + lenG(filename); + // file mode + u16 *filemode = (u16*)(buf + bufi); + struct stat st; + if(stat(sendFile, &st) != 0){ + logE("Can't access %s", sendFile); + XFailure; + } + *filemode = st.st_mode & 0xFFF; + bufi += 2; + // dest path + u16 *pathLength = (u16*)(buf + bufi); + *pathLength = lenG(destPath); + bufi += 2; + if (destPath) { + memcpy(buf + bufi, destPath, *pathLength); + bufi += *pathLength; + } + // file size + *filesize = (u64*)(buf + bufi); + **filesize = fileSizeG(sendFile); + bufi += 8; + } + elif (command == 1) { + // mkdir + u16 *filemode = (u16*)(buf + 9); + struct stat st; + if(stat(sendFile, &st) != 0){ + logE("Can't access %s", sendFile); + XFailure; + } + *filemode = st.st_mode & 0xFFF; + // dest path + u16 *pathLength = (u16*)(buf + 11); + *pathLength = lenG(destPath); + memcpy(buf + 13, destPath, *pathLength); + bufi = 13 + lenG(destPath); + } + + *bufip = bufi; +} + int main(int ARGC, char** ARGV) { initLibsheepy(ARGV[0]); @@ -35,7 +101,7 @@ int main(int ARGC, char** ARGV) { // check args if (ARGC == 2) { - TODO("check that a server is selected"); + TODO("check that a server is selected and store files in current path"); } if (ARGC < 3) { @@ -54,17 +120,10 @@ int main(int ARGC, char** ARGV) { } } - char *sendFile = null; const char *serverName = null; char *destPath = null; if (not isReceive) { logD("path in client"); - if (not isPath(ARGV[1])) { - logE("Incorrect path: "BLD YLW"%s"RST,ARGV[1]); - ret 1; - } - sendFile = ARGV[1]; - // check last arg bool foundDest = no; iter(cfg, D) { @@ -103,6 +162,8 @@ int main(int ARGC, char** ARGV) { int mysock; int rval; + cleanAllocateNetFrame(netframe); + sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0){ @@ -127,75 +188,155 @@ int main(int ARGC, char** ARGV) { XFailure; } - // send - // command 0 - // token - // file name max 8k - // dest path 0 - u8 buf[1024*1024] = init0Var; - // command - buf[0] = 0; - // token - memcpy(buf + 1, $(svrInfo, "token"), 8); - u16 *filenameLength = (u16*)(buf + 9); - char *filename = basename(sendFile); - *filenameLength = lenG(filename); - memcpy(buf + 11, filename, lenG(filename)); - u32 bufi = 11 + lenG(filename); - u16 *filemode = (u16*)(buf + bufi); - struct stat st; - if(stat(sendFile, &st) != 0){ - logE("Can't access %s", sendFile); - ret 1; - } - *filemode = st.st_mode & 0xFFF; - bufi += 2; - u16 *pathLength = (u16*)(buf + bufi); - *pathLength = lenG(destPath); - bufi += 2; - if (destPath) { - memcpy(buf + bufi, destPath, *pathLength); - bufi += *pathLength; + cleanAllocateSmallArray(pathToSend); + + rangeFrom(i, 1, ARGC-1) { + if (not isPath(ARGV[i])) { + logE("Incorrect path: "BLD YLW"%s"RST,ARGV[i]); + continue; + } + pushG(pathToSend, ARGV[i]); } - // file size - u64 *filesize = (u64*)(buf + bufi); - *filesize = fileSizeG(sendFile); - bufi += 8; - cleanAllocateNetFrame(netframe); + cleanAllocateSmallDict(recusive); - if (*filesize < (sizeof(buf) - bufi)) { - pError0(bReadFile(sendFile, buf + bufi)); - o(netframe,send , sock, buf, bufi + *filesize); - } - else { - logD("big file"); - u64 szToSend = *filesize; - u8 *b = buf + bufi; - u64 bSz = sizeof(buf) - bufi; - int fd = open(sendFile, O_RDONLY); - do { - if (szToSend <= bSz) { - read(fd, b, szToSend); - o(netframe,send , sock, b, szToSend); - szToSend = 0; + iter(pathToSend, P) { + castS(p, P); + char *sendFile = ssGet(P); + + if (isDirG(p)) { + logD("mkdir in server"); + + char *dirname = basename(ssGet(p)); + cleanCharP(dest) = catS(destPath, "/", dirname); + + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 1 /* command */, svrInfo, ssGet(p), dest, &filesize); + + o(netframe,send , sock, buf, bufi); + + var dir = readDirAllG(rtSmallArrayt, p); + //lv(dir); + if (not isEmptyG(dir)) { + pushG(dir, ssGet(p)); + setNFreeG(recusive, dirname, dir); } - else { - read(fd, b, bSz); - if (szToSend == *filesize) { - o(netframe,send , sock, buf, bufi + bSz); + lv(recusive); + continue; + } + + // send + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 0 /* command */, svrInfo, sendFile, destPath, &filesize); + + if (*filesize < (sizeof(buf) - bufi)) { + pError0(bReadFile(sendFile, buf + bufi)); + o(netframe,send , sock, buf, bufi + *filesize); + } + else { + logD("big file"); + u64 szToSend = *filesize; + u8 *b = buf + bufi; + u64 bSz = sizeof(buf) - bufi; + int fd = open(sendFile, O_RDONLY); + do { + if (szToSend <= bSz) { + read(fd, b, szToSend); + o(netframe,send , sock, b, szToSend); + szToSend = 0; } else { - o(netframe,send , sock, b, bSz); + read(fd, b, bSz); + if (szToSend == *filesize) { + o(netframe,send , sock, buf, bufi + bSz); + } + else { + o(netframe,send , sock, b, bSz); + } + szToSend -= bSz; } - szToSend -= bSz; + } while(szToSend); + close(fd); + } + } // loop on arguments + + + // Send files recursively + + iter(recusive, A) { + cast(smallArrayt*,a,A); + cleanCharP(localPath) = cropElemG(a, rtChar, -1); + lv(localPath); + iter(a, P) { + castS(p, P); + char *sendFile = ssGet(P); + + cleanCharP(localp) = catS(localPath, "/", ssGet(p)); + if (isDirG(localp)) { + logD("mkdir in server"); + cleanCharP(dirname) = catS(iK(recusive), "/", ssGet(p)); + cleanCharP(dest) = catS(destPath, "/", dirname); + + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 1 /* command */, svrInfo, localp, dest, &filesize); + + o(netframe,send , sock, buf, bufi); + + var dir = readDirAllG(rtSmallArrayt, localp); + lv(dir); + if (not isEmptyG(dir)) { + pushG(dir, localp); + setNFreeG(recusive, dirname, dir); + } + //lv(recusive); + continue; + } + + logD("Send files from localPath/p to destPath/iK(recusive)/"); + // send + cleanCharP(dest) = catS(destPath, "/", iK(recusive)); + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 0 /* command */, svrInfo, localp, dest, &filesize); + + if (*filesize < (sizeof(buf) - bufi)) { + pError0(bReadFile(localp, buf + bufi)); + o(netframe,send , sock, buf, bufi + *filesize); } - } while(szToSend); - close(fd); + else { + logD("big file"); + u64 szToSend = *filesize; + u8 *b = buf + bufi; + u64 bSz = sizeof(buf) - bufi; + int fd = open(localp, O_RDONLY); + do { + if (szToSend <= bSz) { + read(fd, b, szToSend); + o(netframe,send , sock, b, szToSend); + szToSend = 0; + } + else { + read(fd, b, bSz); + if (szToSend == *filesize) { + o(netframe,send , sock, buf, bufi + bSz); + } + else { + o(netframe,send , sock, b, bSz); + } + szToSend -= bSz; + } + } while(szToSend); + close(fd); + } + } } + lv(recusive); // last frame size 0 o(netframe,end, sock); diff --git a/sserver.c b/sserver.c @@ -103,80 +103,100 @@ void saveReceivedData(void *receiveB, size_t sz) { char *root = $(tokens, tk); - u16 *filenameLength = (u16*)(receiveB + 9); - // receiveB + 11 = filename - cleanCharP(filename) = malloc(*filenameLength + 1); - filename[*filenameLength] = 0; - memcpy(filename, receiveB + 11, *filenameLength); - u32 bufi = 11 + *filenameLength; - u16 *filemode = (u16*)(receiveB + bufi); - bufi += 2; - u16 *pathLength = (u16*)(receiveB + bufi); - bufi += 2; - cleanCharP(destPath) = null; - if (*pathLength) { - destPath = malloc(*pathLength + 1); - memcpy(destPath, receiveB + bufi, *pathLength); - destPath[*pathLength] = 0; - bufi += *pathLength; - } - // file size - u64 *filesize = (u64*)(receiveB + bufi); - bufi += 8; - - logD("bufi %d fsz %d + %d, filename %s, destPath %s",bufi, *filesize, bufi + *filesize, filename, destPath); - - char *path = catS(root, "/", nS(destPath)); - pErrorNULL(normalizePathG(&path)); - pErrorNULL(trimG(&path)); - cleanCharP(nroot) = normalizePathG(root); - //lv(path); - if (not startsWithG(path, nroot)) { - logE("Incorrect path"); - ret; - } - - // check isdir or if there is a filename - bool filenameInDestPath = no; - if (destPath and not isPath(path)) { - if (endsWithG(destPath,'/')) { - logE("Directory doesn't exist %s", path); - ret; + if (*command == 0) { + // receive file + + u16 *filenameLength = (u16*)(receiveB + 9); + // receiveB + 11 = filename + cleanCharP(filename) = malloc(*filenameLength + 1); + filename[*filenameLength] = 0; + memcpy(filename, receiveB + 11, *filenameLength); + u32 bufi = 11 + *filenameLength; + u16 *filemode = (u16*)(receiveB + bufi); + bufi += 2; + u16 *pathLength = (u16*)(receiveB + bufi); + bufi += 2; + cleanCharP(destPath) = null; + if (*pathLength) { + destPath = malloc(*pathLength + 1); + memcpy(destPath, receiveB + bufi, *pathLength); + destPath[*pathLength] = 0; + bufi += *pathLength; } - cleanCharP(dir) = shDirname(path); - if (not isPath(dir)) { - logE("Directory doesn't exist %s", dir); + // file size + u64 *filesize = (u64*)(receiveB + bufi); + bufi += 8; + + logD("bufi %d fsz %d + %d, filename %s, destPath %s",bufi, *filesize, bufi + *filesize, filename, destPath); + + char *path = catS(root, "/", nS(destPath)); + pErrorNULL(normalizePathG(&path)); + pErrorNULL(trimG(&path)); + cleanCharP(nroot) = normalizePathG(root); + //lv(path); + if (not startsWithG(path, nroot)) { + logE("Incorrect path"); ret; } - filenameInDestPath = yes; - } - //lv(filenameInDestPath); - if (not filenameInDestPath) { - pErrorNULL(iAppendManyS(&path, "/", filename)); - } - lv(path); - if (*filesize <= sz - bufi) { - pError0(writeFile(path, receiveB + bufi, *filesize)); - pError0(fileChmod(path, *filemode)); - } - else { - logD("open fd"); - inc packetCount; - fd = open(path, O_WRONLY | O_CREAT, *filemode); - if (fd == -1) { - logE("cant open %s", path); - ret; + // check isdir or if there is a filename + bool filenameInDestPath = no; + if (destPath and not isPath(path)) { + if (endsWithG(destPath,'/')) { + logE("Directory doesn't exist %s", path); + ret; + } + cleanCharP(dir) = shDirname(path); + if (not isPath(dir)) { + logE("Directory doesn't exist %s", dir); + ret; + } + filenameInDestPath = yes; } - int r = write(fd, receiveB + bufi, sz - bufi); - if (r == -1) { - logE("cant write %s", path); - ret; + //lv(filenameInDestPath); + if (not filenameInDestPath) { + pErrorNULL(iAppendManyS(&path, "/", filename)); + } + lv(path); + + if (*filesize <= sz - bufi) { + pError0(writeFile(path, receiveB + bufi, *filesize)); + pError0(fileChmod(path, *filemode)); } - transferSz = *filesize - (sz - bufi); + else { + logD("open fd"); + inc packetCount; + fd = open(path, O_WRONLY | O_CREAT, *filemode); + if (fd == -1) { + logE("cant open %s", path); + ret; + } + int r = write(fd, receiveB + bufi, sz - bufi); + if (r == -1) { + logE("cant write %s", path); + ret; + } + transferSz = *filesize - (sz - bufi); + } + } + elif (*command == 1) { + // mkdir + u16 *filemode = (u16*)(receiveB + 9); + u16 *pathLength = (u16*)(receiveB + 11); + cleanCharP(destPath) = malloc(*pathLength + 1); + memcpy(destPath, receiveB + 13, *pathLength); + destPath[*pathLength] = 0; + char *path = catS(root, "/", destPath); + pErrorNULL(normalizePathG(&path)); + pErrorNULL(trimG(&path)); + logD(BLD GRN"mkdir" RST); + lv(path); + pError0(mkdirParents(path)); + pError0(fileChmod(path, *filemode)); } } else { + // receive large files packetCount > 0 if (fd == -1) ret; // big file int r = write(fd, receiveB, sz);