From 146ecadfbf067492d6c665f4c5bcab83ea071aaf Mon Sep 17 00:00:00 2001 From: Michael Gajda Date: Sun, 13 Sep 2020 20:12:08 +0200 Subject: [PATCH] Enable hashing symlinks Example output: ``` INFO[0000] Hashing directory. hashesFile=x/bundleinfo.json pathToHash=x/ uniqueBundleName=x INFO[0000] Hash "x/". WARN[0000] File "x/foo"->"x/x2" is a symlink, will be treated as a regular file/dir. INFO[0000] Finished hasher. `` Symlinks with targets not within the hash directory are not allowed and cause a panic. --- CHANGES.md | 1 + pkg/launcher/hashing/scan.go | 37 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2c3329f0..f8107a5b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ * `hasher` will no longer create a directory if a non-existing one is passed as an argument. * trivrost will no longer attempt to repeat range requests to a host after it has failed to conformly respond while displaying the confusing message `Taking longer than usual: HTTP Status 200` and will now fail immediately in such cases instead. * trivrost will no longer fail to comply with HTTP 2 strictly using lower-case HTTP Header names. This had been caused by methods of `http.Header` still being oriented around HTTP 1 canonical header names due to Go's backwards compatibility promise. +* hasher now supports symlinks within hashed directories. ## 1.4.6 (2021-01-25) ### Fixes diff --git a/pkg/launcher/hashing/scan.go b/pkg/launcher/hashing/scan.go index a2d456fa..64092d91 100644 --- a/pkg/launcher/hashing/scan.go +++ b/pkg/launcher/hashing/scan.go @@ -10,6 +10,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "github.com/setlog/trivrost/pkg/launcher/config" log "github.com/sirupsen/logrus" @@ -61,23 +62,29 @@ func mustHashRelatively(ctx context.Context, readDir readDirFunc, readFile readF } func mustHashDir(ctx context.Context, readDir readDirFunc, readFile readFileFunc, stat statFunc, hashFilePath string) config.FileInfoMap { - fm := make(config.FileInfoMap) - for _, info := range mustReadDir(readDir, hashFilePath) { - if info.IsDir() { - fm.Join(mustHashDir(ctx, readDir, readFile, stat, filepath.Join(hashFilePath, info.Name()))) - } else { - filePath := filepath.Join(hashFilePath, info.Name()) - if isDir(filePath) { - fm.Join(mustHashDir(readDir, readFile, stat, filePath)) + fileMap := make(config.FileInfoMap) + for _, curPathInfo := range mustReadDir(readDir, hashFilePath) { + curPath := filepath.Join(hashFilePath, curPathInfo.Name()) + resolvedPath := evaluateSoftLink(curPath) + if curPath != resolvedPath { + log.Warnf("File \"%s\"->\"%s\" is a symlink, will be treated as a regular file/dir.", curPath, resolvedPath) + curPath = resolvedPath + } + if !strings.HasPrefix(curPath, hashFilePath) { + panic(fmt.Errorf("hashing '%s' outside hash directory is not allowed", curPath)) + } + curPathInfo, _ = stat(curPath) + if curPathInfo.IsDir() { + fileMap.Join(mustHashDir(ctx, readDir, readFile, stat, curPath)) } else { - sha, size, err := calculateSha256(ctx, filePath, readFile) + sha, size, err := calculateSha256(ctx, curPath, readFile) if err != nil { panic(fmt.Errorf("failed hashing file \"%s\": %w", hashFilePath, err)) } - fm[filePath] = &config.FileInfo{SHA256: sha, Size: size} + fileMap[curPath] = &config.FileInfo{SHA256: sha, Size: size} } } - return fm + return fileMap } func evaluateSoftLink(filePath string) string { @@ -88,14 +95,6 @@ func evaluateSoftLink(filePath string) string { return evaluatedName } -func isDir(filePath string) bool { - fi, err := os.Stat(filePath) - if err != nil { - panic(err) - } - return fi.IsDir() -} - func mustReadDir(readDir readDirFunc, directoryPath string) []os.FileInfo { infos, err := readDir(evaluateSoftLink(directoryPath)) if err != nil {