From 6ec5eabc93611ff2163fd48abf5752d3b0396d2c Mon Sep 17 00:00:00 2001 From: Unbewohnte Date: Wed, 10 Nov 2021 19:53:19 +0300 Subject: [PATCH] [fsys] fixed relative path finding; [node] fixed recursive transfer of a directory --- src/fsys/dir.go | 31 +++-- src/fsys/dir_test.go | 36 ++++-- src/fsys/file.go | 19 +++- src/node/node.go | 107 +++++++++++------- src/protocol/packetConstruct.go | 2 +- src/protocol/send.go | 7 +- .../testdir3/nested1/nested2/testfilen.txt | 1 + 7 files changed, 141 insertions(+), 62 deletions(-) create mode 100644 src/testfiles/testdir3/nested1/nested2/testfilen.txt diff --git a/src/fsys/dir.go b/src/fsys/dir.go index 78e7549..5484817 100644 --- a/src/fsys/dir.go +++ b/src/fsys/dir.go @@ -65,10 +65,6 @@ func GetDir(path string, recursive bool) (*Directory, error) { return nil, err } - for _, file := range innerDir.Files { - file.RelativeParentPath = filepath.Join(directory.Name, innerDir.Name, file.Name) - } - directory.Size += innerDir.Size innerDirs = append(innerDirs, innerDir) @@ -83,8 +79,6 @@ func GetDir(path string, recursive bool) (*Directory, error) { return nil, err } - innerFile.RelativeParentPath = filepath.Join(directory.Name, innerFile.Name) - directory.Size += innerFile.Size innerFiles = append(innerFiles, innerFile) @@ -98,16 +92,16 @@ func GetDir(path string, recursive bool) (*Directory, error) { } // Returns every file in that directory -func (dir *Directory) GetAllFiles(recursively bool) []*File { +func (dir *Directory) GetAllFiles(recursive bool) []*File { var files []*File = dir.Files - if recursively { + if recursive { if len(dir.Directories) == 0 { return files } for _, innerDir := range dir.Directories { - innerFiles := innerDir.GetAllFiles(recursively) + innerFiles := innerDir.GetAllFiles(recursive) files = append(files, innerFiles...) } @@ -117,3 +111,22 @@ func (dir *Directory) GetAllFiles(recursively bool) []*File { return files } + +// Sets `RelativeParentPath` relative to the given base path. +// file with such path: +// /home/user/directory/somefile.txt +// had a relative path like that: +// /directory/somefile.txt +// (where base path is /home/user/directory) +func (dir *Directory) SetRelativePaths(base string, recursive bool) error { + for _, file := range dir.GetAllFiles(recursive) { + relPath, err := filepath.Rel(base, file.Path) + if err != nil { + return err + } + + file.RelativeParentPath = relPath + + } + return nil +} diff --git a/src/fsys/dir_test.go b/src/fsys/dir_test.go index 7e41155..ea856a1 100644 --- a/src/fsys/dir_test.go +++ b/src/fsys/dir_test.go @@ -1,6 +1,8 @@ package fsys -import "testing" +import ( + "testing" +) func Test_GetDir(t *testing.T) { dirpath := "../testfiles/" @@ -30,13 +32,6 @@ func Test_GetDirRecursive(t *testing.T) { } } - // t.Errorf("[initialdir] %+v", dir.Files[0]) - // for _, dir := range dir.Directories { - // for countf, file := range dir.Files { - // t.Errorf("[%d] %+v\n", countf, file) - // } - // } - } func Test_GetFiles(t *testing.T) { @@ -50,7 +45,7 @@ func Test_GetFiles(t *testing.T) { // recursive files := dir.GetAllFiles(true) - fileCount := 5 + fileCount := 6 if len(files) != fileCount { t.Fatalf("expected to get %d files; got %d\n", fileCount, len(files)) } @@ -63,3 +58,26 @@ func Test_GetFiles(t *testing.T) { } } + +// func Test_SetRelativePaths(t *testing.T) { +// dirpath := "../testfiles/" + +// dir, err := GetDir(dirpath, true) +// if err != nil { +// t.Fatalf("%s", err) +// } + +// absDirPath, err := filepath.Abs(dirpath) +// if err != nil { +// t.Fatalf("%s", err) +// } + +// err = dir.SetRelativePaths(absDirPath, true) +// if err != nil { +// t.Fatalf("%s", err) +// } + +// for count, file := range dir.GetAllFiles(true) { +// t.Errorf("[%d] %v\n", count, file.RelativeParentPath) +// } +// } diff --git a/src/fsys/file.go b/src/fsys/file.go index d2ab02c..b15180c 100644 --- a/src/fsys/file.go +++ b/src/fsys/file.go @@ -54,7 +54,7 @@ func GetFile(path string) (*File, error) { if err != nil { return nil, err } - defer file.Handler.Close() + defer file.Close() checksum, err := checksum.GetPartialCheckSum(file.Handler) if err != nil { @@ -68,6 +68,10 @@ func GetFile(path string) (*File, error) { // Opens file for read/write operations func (file *File) Open() error { + if file.Handler != nil { + file.Close() + } + handler, err := os.OpenFile(file.Path, os.O_CREATE|os.O_RDWR, os.ModePerm) if err != nil { return err @@ -76,3 +80,16 @@ func (file *File) Open() error { return nil } + +// file.Handler.Close wrapper +func (file *File) Close() error { + if file.Handler != nil { + err := file.Handler.Close() + if err != nil { + return err + } + + file.Handler = nil + } + return nil +} diff --git a/src/node/node.go b/src/node/node.go index 013e4fa..b7fd1db 100644 --- a/src/node/node.go +++ b/src/node/node.go @@ -84,10 +84,17 @@ func NewNode(options *NodeOptions) (*Node, error) { } } else { // receiving node preparation - err := os.MkdirAll(options.ClientSide.DownloadsFolderPath, os.ModePerm) + var err error + options.ClientSide.DownloadsFolderPath, err = filepath.Abs(options.ClientSide.DownloadsFolderPath) if err != nil { return nil, err } + + err = os.MkdirAll(options.ClientSide.DownloadsFolderPath, os.ModePerm) + if err != nil { + return nil, err + } + } node := Node{ @@ -219,7 +226,7 @@ func (node *Node) Start() { fmt.Printf("Sending \"%s\" (%.3f %s) locally on %s:%d\n", dirToSend.Name, size, sizeLevel, localIP, node.netInfo.Port) } else { - size := float32(dirToSend.Size) / 1024 / 1024 + size := float32(fileToSend.Size) / 1024 / 1024 sizeLevel := "MiB" if size >= 1024 { // GiB @@ -292,12 +299,11 @@ func (node *Node) Start() { case true: // send file packets for the files in the directory - var filesToSend []*fsys.File - if node.transferInfo.Sending.Recursive { - filesToSend = dirToSend.GetAllFiles(true) - } else { - filesToSend = dirToSend.GetAllFiles(false) + err = dirToSend.SetRelativePaths(dirToSend.Path, node.transferInfo.Sending.Recursive) + if err != nil { + panic(err) } + filesToSend := dirToSend.GetAllFiles(node.transferInfo.Sending.Recursive) // notify the other node about all the files that are going to be sent for counter, file := range filesToSend { @@ -309,6 +315,8 @@ func (node *Node) Start() { // set current file id to the first file node.transferInfo.Sending.CurrentFileIndex = 0 + // fmt.Printf("[%d] rel path: %s\n", file.ID, file.RelativeParentPath) + filePacket, err := protocol.CreateFilePacket(file) if err != nil { panic(err) @@ -327,6 +335,7 @@ func (node *Node) Start() { if err != nil { panic(err) } + } case false: @@ -370,24 +379,24 @@ func (node *Node) Start() { // Transfer section + if len(node.transferInfo.Sending.FilesToSend) == 0 { + // if there`s nothing else to send - create and send DONE packet + protocol.SendPacket(node.netInfo.Conn, protocol.Packet{ + Header: protocol.HeaderDone, + }) + + fmt.Printf("Transfer ended successfully\n") + + node.state.Stopped = true + } + // if allowed to transfer and the other node is ready to receive packets - send one piece // and wait for it to be ready again if node.state.AllowedToTransfer && node.transferInfo.Sending.CanSendBytes { - if len(node.transferInfo.Sending.FilesToSend) == 0 { - // if there`s nothing else to send - create and send DONE packet - protocol.SendPacket(node.netInfo.Conn, protocol.Packet{ - Header: protocol.HeaderDone, - }) - - fmt.Printf("Transfer ended successfully\n") - - node.state.Stopped = true - } // sending a piece of a single file currentFileIndex := node.transferInfo.Sending.CurrentFileIndex - err = protocol.SendPiece(node.transferInfo.Sending.FilesToSend[currentFileIndex], node.netInfo.Conn, node.netInfo.EncryptionKey) switch err { case protocol.ErrorSentAll: @@ -520,18 +529,18 @@ func (node *Node) Start() { if strings.EqualFold(answer, "y") || answer == "" { // yes - // // in case it`s a directory - create it now - // if dir != nil { - // err = os.MkdirAll(filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name), os.ModePerm) - // if err != nil { - // // well, just download all files in the default downloads folder then - // fmt.Printf("[ERROR] could not create a directory\n") - // } else { - // // also download everything in a newly created directory - // node.transferInfo.Receiving.DownloadsPath = filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name) - // } + // in case it`s a directory - create it now + if dir != nil { + err = os.MkdirAll(filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name), os.ModePerm) + if err != nil { + // well, just download all files in the default downloads folder then + fmt.Printf("[ERROR] could not create a directory\n") + } else { + // also download everything in a newly created directory + node.transferInfo.Receiving.DownloadsPath = filepath.Join(node.transferInfo.Receiving.DownloadsPath, dir.Name) + } - // } + } // send aceptance packet acceptancePacket := protocol.Packet{ @@ -578,10 +587,7 @@ func (node *Node) Start() { panic(err) } - file.Path, err = filepath.Abs(filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.RelativeParentPath)) - if err != nil { - panic(err) - } + file.Path = filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.RelativeParentPath) // create all underlying directories right ahead err = os.MkdirAll(filepath.Dir(file.Path), os.ModePerm) @@ -597,8 +603,6 @@ func (node *Node) Start() { os.Remove(file.Path) } - file.Open() - node.mutex.Lock() node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles, file) node.mutex.Unlock() @@ -620,8 +624,31 @@ func (node *Node) Start() { // append provided bytes to the file + err = acceptedFile.Open() + if err != nil { + panic(err) + } + fileBytes := fileBytesBuffer.Bytes() - _, err = acceptedFile.Handler.Write(fileBytes) + + wrote, err := acceptedFile.Handler.WriteAt(fileBytes, int64(acceptedFile.SentBytes)) + if err != nil { + panic(err) + // // fmt.Printf("[Debug] %+v\n", acceptedFile) + + // // this file won`t be completed, so it`ll be ignored + + // // remove this file from the pool + // node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles[:index], node.transferInfo.Receiving.AcceptedFiles[index+1:]...) + + // fmt.Printf("[ERROR] an error occured when receiving a file \"%s\": %s. This file will not be completed", acceptedFile.Name, err) + + // // remove it from the filesystem + // os.Remove(acceptedFile.Path) + } + acceptedFile.SentBytes += uint64(wrote) + + err = acceptedFile.Close() if err != nil { panic(err) } @@ -652,8 +679,10 @@ func (node *Node) Start() { if acceptedFile.ID == fileID { // accepted - // close the handler afterwards - defer acceptedFile.Handler.Close() + err = acceptedFile.Open() + if err != nil { + panic(err) + } // remove this file from the pool node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles[:index], node.transferInfo.Receiving.AcceptedFiles[index+1:]...) @@ -667,9 +696,11 @@ func (node *Node) Start() { fmt.Printf("\n| Checking hashes for file \"%s\"\n", acceptedFile.Name) if realChecksum != acceptedFile.Checksum { fmt.Printf("| %s --- %s file is corrupted\n", realChecksum, acceptedFile.Checksum) + acceptedFile.Close() break } else { fmt.Printf("| %s --- %s\n", realChecksum, acceptedFile.Checksum) + acceptedFile.Close() break } } diff --git a/src/protocol/packetConstruct.go b/src/protocol/packetConstruct.go index e1f0406..36975d5 100644 --- a/src/protocol/packetConstruct.go +++ b/src/protocol/packetConstruct.go @@ -14,7 +14,7 @@ func CreateFilePacket(file *fsys.File) (*Packet, error) { if err != nil { return nil, err } - defer file.Handler.Close() + defer file.Close() //(id in binary)(filename length in binary)(filename)(filesize)(checksum length in binary)(checksum)(relative path to the upper directory size in binary if present)(relative path) diff --git a/src/protocol/send.go b/src/protocol/send.go index c4d90f2..60f41d9 100644 --- a/src/protocol/send.go +++ b/src/protocol/send.go @@ -125,7 +125,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error { if err != nil { return err } - defer file.Handler.Close() + defer file.Close() if file.SentBytes == 0 { file.Handler.Seek(0, io.SeekStart) @@ -142,7 +142,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error { packetBodyBuff := new(bytes.Buffer) // write file ID first - err = binary.Write(packetBodyBuff, binary.BigEndian, &file.ID) + err = binary.Write(packetBodyBuff, binary.BigEndian, file.ID) if err != nil { return err } @@ -165,6 +165,7 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error { if err != nil { return err } + file.SentBytes += uint64(read) packetBodyBuff.Write(fileBytes) @@ -183,7 +184,5 @@ func SendPiece(file *fsys.File, connection net.Conn, encrKey []byte) error { return err } - file.SentBytes += uint64(read) - return nil } diff --git a/src/testfiles/testdir3/nested1/nested2/testfilen.txt b/src/testfiles/testdir3/nested1/nested2/testfilen.txt new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/src/testfiles/testdir3/nested1/nested2/testfilen.txt @@ -0,0 +1 @@ +test \ No newline at end of file