tuyau

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

commit b6966e8560b0fc0e9fa3d74832e1010c73d8bff9
parent 7b369dafb749ba6bf6442e7440146b834a8b9600
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sat, 13 Aug 2022 17:04:31 -0400

add receive recursive and globbing in server

NOTES.md  |   6 +--
sclient.c |  23 ++++++--
sserver.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 171 insertions(+), 39 deletions(-)

Diffstat:
MNOTES.md | 6+++---
Msclient.c | 23+++++++++++++++++++----
Msserver.c | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 171 insertions(+), 39 deletions(-)

diff --git a/NOTES.md b/NOTES.md @@ -11,7 +11,7 @@ x./sclient.c dev:NOTES.md x./sclient.c dev:NOTES.md ../ x./sclient.c dev:NOTES.md test.txt -cp file tuyau://ip/path +//cp file tuyau://ip/path 0 frame send file: 1 byte command @@ -49,8 +49,8 @@ port 1032 ..- mkdir ..- send files with glob ..- send files recursive -- receive files, glob -- receive files recursive +..- receive files, glob +..- receive files recursive //- list files in path ..- token, home directory ..- server name ip port in config diff --git a/sclient.c b/sclient.c @@ -358,10 +358,15 @@ bool saveReceivedData(void *receiveB, size_t sz, void *context) { if (not root) { // save file in current directory - path = strdup(filename); + if (not destPath) { + path = strdup(filename); + } + else { + path = catS(destPath, "/", filename); + } } elif (isDir(root)) { - path = catS(root, "/", filename); + path = catS(root, "/", nS(destPath), "/", filename); } else { // root has a filename @@ -393,13 +398,23 @@ bool saveReceivedData(void *receiveB, size_t sz, void *context) { } elif (*command == 1) { // mkdir - TODO("mkdir"); + if (root and not isDir(root)) { + logE("Cant create directory if root is not a directory %s", root); + ret yes; + } + logD("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); + cleanCharP(path) = null; + if (not root) { + path = strdup(destPath); + } + else { + path = catS(root, "/", destPath); + } pErrorNULL(normalizePathG(&path)); pErrorNULL(trimG(&path)); logD(BLD GRN"mkdir" RST); diff --git a/sserver.c b/sserver.c @@ -13,6 +13,8 @@ #include <sys/stat.h> #include <fcntl.h> +#include <glob.h> + #include "netFrame.h" #include "shpPackages/short/short.h" #include "makeHeader.h" @@ -188,7 +190,7 @@ void saveReceivedData(void *receiveB, size_t sz) { cleanCharP(destPath) = malloc(*pathLength + 1); memcpy(destPath, receiveB + 13, *pathLength); destPath[*pathLength] = 0; - char *path = catS(root, "/", destPath); + cleanCharP(path) = catS(root, "/", destPath); pErrorNULL(normalizePathG(&path)); pErrorNULL(trimG(&path)); logD(BLD GRN"mkdir" RST); @@ -197,11 +199,12 @@ void saveReceivedData(void *receiveB, size_t sz) { pError0(fileChmod(path, *filemode)); } elif (*command == 2) { - TODO("send files to client, send back sendFile basename"); + logD("send files to client"); u16 *sendFileLength = (u16*)(receiveB + 9); cleanCharP(sendFile) = malloc(*sendFileLength + 1); memcpy(sendFile, receiveB + 11, *sendFileLength); sendFile[*sendFileLength] = 0; + pErrorNULL(prependG(&sendFile, '/')); pErrorNULL(prependG(&sendFile, root)); pErrorNULL(normalizePathG(&sendFile)); @@ -212,50 +215,164 @@ void saveReceivedData(void *receiveB, size_t sz) { logE("Incorrect path, outside home directory: "BLD YLW"%s"RST,sendFile); ret; } - if (not isPath(sendFile)) { - logE("Incorrect path: "BLD YLW"%s"RST,sendFile); - ret; + + cleanAllocateSmallArray(pathToSend); + + if (isPath(sendFile)) { + pushG(pathToSend, sendFile); + } + else { + // check if sendFile is a glob + glob_t globbuf = init0Var; + glob(sendFile, 0, NULL, &globbuf); + if (!globbuf.gl_pathv) { + logE("Incorrect path: "BLD YLW"%s"RST,sendFile); + ret; + } + forEachS(globbuf.gl_pathv, s) { + pushG(pathToSend, s); + } + globfree(&globbuf); } cleanAllocateNetFrame(netframe); u8 buf[1024*1024] = init0Var; - // send - u32 bufi = 0; - u64 *filesize = null; - makeHeader(buf, &bufi, 0 /* command */, null/*svrInfo no need to authenticate the client*/, sendFile, null/*destPath is already selected in client*/, &filesize); + cleanAllocateSmallDict(recusive); - if (*filesize < (sizeof(buf) - bufi)) { - pError0(bReadFile(sendFile, buf + bufi)); - o(netframe,send , mysock, 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 , mysock, b, szToSend); - szToSend = 0; + iter(pathToSend, P) { + castS(p, P); + char *sendFile = ssGet(P); + + if (isDirG(p)) { + logD("mkdir in client"); + + char *dirname = basename(ssGet(p)); + + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 1 /* command */, null/*svrInfo no need to authenticate the client*/, ssGet(P), dirname/*dest*/, &filesize); + + o(netframe,send , mysock, 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 , mysock, buf, bufi + bSz); + lv(recusive); + continue; + } + + // send + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 0 /* command */, null/*svrInfo no need to authenticate the client*/, sendFile, null/*destPath is already selected in client*/, &filesize); + + if (*filesize < (sizeof(buf) - bufi)) { + pError0(bReadFile(sendFile, buf + bufi)); + o(netframe,send , mysock, 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 , mysock, b, szToSend); + szToSend = 0; } else { - o(netframe,send , mysock, b, bSz); + read(fd, b, bSz); + if (szToSend == *filesize) { + o(netframe,send , mysock, buf, bufi + bSz); + } + else { + o(netframe,send , mysock, b, bSz); + } + szToSend -= bSz; + } + } while(szToSend); + close(fd); + } + } // sendFile or globbing + + // 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 client"); + cleanCharP(dirname) = catS(iK(recusive), "/", ssGet(p)); + + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 1 /* command */, null/*svrInfo no need to authenticate the client*/, localp, dirname, &filesize); + + o(netframe,send , mysock, buf, bufi); + + var dir = readDirAllG(rtSmallArrayt, localp); + lv(dir); + if (not isEmptyG(dir)) { + pushG(dir, localp); + setNFreeG(recusive, dirname, dir); } - szToSend -= bSz; + //lv(recusive); + continue; } - } while(szToSend); - close(fd); + + logD("Send localp file to iK(recusive) client directory"); + // send + u32 bufi = 0; + u64 *filesize = null; + makeHeader(buf, &bufi, 0 /* command */, null/*svrInfo no need to authenticate the client*/, localp, (char*)iK(recusive) /*dest*/, &filesize); + + if (*filesize < (sizeof(buf) - bufi)) { + pError0(bReadFile(localp, buf + bufi)); + o(netframe,send , mysock, buf, bufi + *filesize); + } + 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 , mysock, b, szToSend); + szToSend = 0; + } + else { + read(fd, b, bSz); + if (szToSend == *filesize) { + o(netframe,send , mysock, buf, bufi + bSz); + } + else { + o(netframe,send , mysock, b, bSz); + } + szToSend -= bSz; + } + } while(szToSend); + close(fd); + } + } } + lv(recusive); + // last frame size 0 // close connection o(netframe,end, mysock);