diff --git a/warehouse/Store.go b/warehouse/Store.go index 33187e2..16fe03d 100644 --- a/warehouse/Store.go +++ b/warehouse/Store.go @@ -7,9 +7,9 @@ Author: Peter Kleissner package warehouse import ( - "encoding/hex" "io" "os" + "path/filepath" "strings" "time" @@ -34,7 +34,7 @@ const ( // CreateFile creates a new file in the warehouse func (wh *Warehouse) CreateFile(data io.Reader) (hash []byte, status int, err error) { // create a temporary file to hold the body content - tmpFile, err := wh.TempFile() + tmpFile, err := wh.tempFile() if err != nil { return nil, StatusErrorCreateTempFile, err } @@ -60,10 +60,9 @@ func (wh *Warehouse) CreateFile(data io.Reader) (hash []byte, status int, err er } hash = hashWriter.Sum(nil) - hashA := hex.EncodeToString(hash) // Check if the file exists - if _, _, valid := wh.FileExists(hashA); valid { + if _, _, status, _ := wh.FileExists(hash); status == StatusOK { // file exists already, temp file not needed os.Remove(tmpFileName) @@ -72,7 +71,7 @@ func (wh *Warehouse) CreateFile(data io.Reader) (hash []byte, status int, err er } // Destination - pathFull, err := wh.createFilePath(hashA) + pathFull, err := wh.createFilePath(hash) if err != nil { os.Remove(tmpFileName) return nil, StatusErrorCreatePath, err @@ -117,20 +116,13 @@ func (wh *Warehouse) CreateFileFromPath(file string) (hash []byte, status int, e // ReadFile reads a file from the warehouse and outputs it to the writer // Offset is the position in the file to start reading. Limit (0 = not used) defines how many bytes to read starting at the offset. func (wh *Warehouse) ReadFile(hash []byte, offset, limit int64, writer io.Writer) (status int, err error) { - hashA, err := ValidateHash(hash) - if err != nil { - return StatusInvalidHash, err + path, _, status, err := wh.FileExists(hash) + if status != StatusOK { // file does not exist or invalid hash + return status, err } + // read the file from disk var reader io.ReadSeeker - - path, _, valid := wh.FileExists(hashA) - if !valid { - // file does not exist - return StatusFileNotFound, os.ErrNotExist - } - - // read from drive retryCount := 0 retryOpenFile: @@ -174,14 +166,9 @@ retryOpenFile: // DeleteFile deletes a file from the warehouse func (wh *Warehouse) DeleteFile(hash []byte) (status int, err error) { - hashA, err := ValidateHash(hash) - if err != nil { - return StatusInvalidHash, err - } - - path, _, valid := wh.FileExists(hashA) - if !valid { - return StatusFileNotFound, os.ErrNotExist + path, _, status, err := wh.FileExists(hash) + if status != StatusOK { + return status, err } if err := os.Remove(path); err != nil { @@ -190,3 +177,30 @@ func (wh *Warehouse) DeleteFile(hash []byte) (status int, err error) { return StatusOK, nil } + +// FileExists checks if the file exists +func (wh *Warehouse) FileExists(hash []byte) (path string, fileInfo os.FileInfo, status int, err error) { + hashA, err := ValidateHash(hash) + if err != nil { + return "", nil, StatusInvalidHash, err + } + + a, b := buildPath(wh.Directory, hashA) + path = filepath.Join(a, b) + + if fileInfo, err := os.Stat(path); err == nil { + // file exists + return path, fileInfo, StatusOK, nil + } + + return "", nil, StatusFileNotFound, os.ErrNotExist +} + +// DeleteWarehouse deletes all files in the warehouse +func (wh *Warehouse) DeleteWarehouse() (err error) { + return wh.IterateFiles(func(Hash []byte, Size int64) (Continue bool) { + wh.DeleteFile(Hash) + + return true + }) +} diff --git a/warehouse/Warehouse.go b/warehouse/Warehouse.go index 5de5d5f..6020b5d 100644 --- a/warehouse/Warehouse.go +++ b/warehouse/Warehouse.go @@ -24,9 +24,6 @@ type Warehouse struct { Temp string // Temporary folder } -// LogError is called for any error. The caller can use it to capture any errors. -//var LogError func(function, format string, v ...interface{}) = func(function, format string, v ...interface{}) {} - // Init initializes the warehouse func Init(Directory string) (wh *Warehouse, err error) { // The temp folder will always be a sub-folder named "_Temp" @@ -42,41 +39,6 @@ func Init(Directory string) (wh *Warehouse, err error) { return } -// TempFile creates a temporary file in the Warehouse. Do not forget to delete. -func (wh *Warehouse) TempFile() (file *os.File, err error) { - file, err = ioutil.TempFile(wh.Temp, "wh") - - return -} - -// createFilePath creates the file path for the specified hash and returns the full file path -func (wh *Warehouse) createFilePath(hash string) (pathFull string, err error) { - path, filename := buildPath(wh.Directory, hash) - return filepath.Join(path, filename), createDirectory(path) -} - -// FileExists checks if the file exists -func (wh *Warehouse) FileExists(hash string) (path string, fileInfo os.FileInfo, valid bool) { - a, b := buildPath(wh.Directory, hash) - path = filepath.Join(a, b) - - if fileInfo, err := os.Stat(path); err == nil { - // file exists - return path, fileInfo, true - } - - return "", nil, false -} - -// DeleteWarehouse deletes all files in the warehouse -func (wh *Warehouse) DeleteWarehouse() (err error) { - return wh.IterateFiles(func(Hash []byte, Size int64) (Continue bool) { - wh.DeleteFile(Hash) - - return true - }) -} - // ---- hash functions ---- func ValidateHash(hash []byte) (hashA string, err error) { @@ -106,6 +68,19 @@ func buildPath(storagePath, hash string) (directory string, filename string) { return newPath, filename } +// tempFile creates a temporary file in the Warehouse. Do not forget to delete. +func (wh *Warehouse) tempFile() (file *os.File, err error) { + file, err = ioutil.TempFile(wh.Temp, "wh") + + return +} + +// createFilePath creates the file path for the specified hash and returns the full file path +func (wh *Warehouse) createFilePath(hash []byte) (pathFull string, err error) { + path, filename := buildPath(wh.Directory, hex.EncodeToString(hash)) + return filepath.Join(path, filename), createDirectory(path) +} + // IterateFiles iterates through all the files and calls the callback func (wh *Warehouse) IterateFiles(Callback func(Hash []byte, Size int64) (Continue bool)) (err error) { // list all directories in the local Storage folder. We have to walk 2 levels down to see the actual files. diff --git a/webapi/File.go b/webapi/File.go index 3258b29..25527b2 100644 --- a/webapi/File.go +++ b/webapi/File.go @@ -145,10 +145,10 @@ func apiBlockchainFileAdd(w http.ResponseWriter, r *http.Request) { // Verify that the file exists in the warehouse. Folders are exempt from this check as they are only virtual. if !file.IsVirtualFolder() { - if hashA, err := warehouse.ValidateHash(file.Hash); err != nil { + if _, err := warehouse.ValidateHash(file.Hash); err != nil { http.Error(w, "", http.StatusBadRequest) return - } else if _, _, valid := core.UserWarehouse.FileExists(hashA); !valid { + } else if _, _, status, _ := core.UserWarehouse.FileExists(file.Hash); status != warehouse.StatusOK { EncodeJSON(w, r, apiBlockchainBlockStatus{Status: blockchain.StatusNotInWarehouse}) return } @@ -233,10 +233,10 @@ func apiBlockchainFileUpdate(w http.ResponseWriter, r *http.Request) { for _, file := range input.Files { // Verify that the file exists in the warehouse. Folders are exempt from this check as they are only virtual. if !file.IsVirtualFolder() { - if hashA, err := warehouse.ValidateHash(file.Hash); err != nil { + if _, err := warehouse.ValidateHash(file.Hash); err != nil { http.Error(w, "", http.StatusBadRequest) return - } else if _, _, valid := core.UserWarehouse.FileExists(hashA); !valid { + } else if _, _, status, _ := core.UserWarehouse.FileExists(file.Hash); status != warehouse.StatusOK { EncodeJSON(w, r, apiBlockchainBlockStatus{Status: blockchain.StatusNotInWarehouse}) return }