From 6c5d6dfed2ad330ce1bff3e2021704d774d2bd33 Mon Sep 17 00:00:00 2001 From: Tarun Koyalwar Date: Mon, 9 Oct 2023 21:27:48 +0530 Subject: [PATCH 1/2] add cache dir --- folder/folderutil.go | 52 ++++++++++++-------------------------------- folder/std_dirs.go | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 38 deletions(-) create mode 100644 folder/std_dirs.go diff --git a/folder/folderutil.go b/folder/folderutil.go index d3ef9d4..eb62cfc 100644 --- a/folder/folderutil.go +++ b/folder/folderutil.go @@ -3,17 +3,23 @@ package folderutil import ( "errors" "os" - "os/user" "path/filepath" "runtime" "strings" fileutil "github.com/projectdiscovery/utils/file" + mapsutil "github.com/projectdiscovery/utils/maps" ) var ( // Separator evaluated at runtime Separator = string(os.PathSeparator) + // Remove source directory after successful sync + RemoveSourceDirAfterSync = true + // writeablePathCache is a cache of writeable paths + writeablePathCache = mapsutil.SyncLockMap[string, struct{}]{ + Map: make(map[string]struct{}), + } ) const ( @@ -145,55 +151,25 @@ func agnosticSplit(path string) (parts []string) { return } -// HomeDirOrDefault tries to obtain the user's home directory and -// returns the default if it cannot be obtained. -func HomeDirOrDefault(defaultDirectory string) string { - if user, err := user.Current(); err == nil && IsWritable(user.HomeDir) { - return user.HomeDir - } - if homeDir, err := os.UserHomeDir(); err == nil && IsWritable(homeDir) { - return homeDir - } - return defaultDirectory -} - // IsWritable checks if a path is writable by attempting to create a temporary file. -// Note: It's recommended to minimize the use of this function because it involves file creation. -// If performance is a concern, consider declaring a global variable in the module using this and initialize it once. +// It caches writable paths to avoid unnecessary file operations. func IsWritable(path string) bool { + if _, ok := writeablePathCache.Get(path); ok { + return true + } if !fileutil.FolderExists(path) { return false } - tmpfile, err := os.CreateTemp(path, "test") if err != nil { return false } - defer os.Remove(tmpfile.Name()) + _ = tmpfile.Close() + _ = os.Remove(tmpfile.Name()) + writeablePathCache.Set(path, struct{}{}) return true } -// UserConfigDirOrDefault returns the user config directory or defaultConfigDir in case of error -func UserConfigDirOrDefault(defaultConfigDir string) string { - userConfigDir, err := os.UserConfigDir() - if err != nil { - return defaultConfigDir - } - return userConfigDir -} - -// AppConfigDirOrDefault returns the app config directory -func AppConfigDirOrDefault(defaultAppConfigDir string, toolName string) string { - userConfigDir := UserConfigDirOrDefault("") - if userConfigDir == "" { - return filepath.Join(defaultAppConfigDir, toolName) - } - return filepath.Join(userConfigDir, toolName) -} - -// Remove source directory after successful sync -var RemoveSourceDirAfterSync = true - // SyncDirectory sync all files and non-empty directories from source to destination folder // optionally removes source directory and removes source func SyncDirectory(source, destination string) error { diff --git a/folder/std_dirs.go b/folder/std_dirs.go new file mode 100644 index 0000000..229c78c --- /dev/null +++ b/folder/std_dirs.go @@ -0,0 +1,50 @@ +package folderutil + +import ( + "os" + "os/user" + "path/filepath" +) + +// Below Contains utils for standard directories +// which should be used by tools to store data +// and configuration files respectively + +// HomeDirOrDefault tries to obtain the user's home directory and +// returns the default if it cannot be obtained. +func HomeDirOrDefault(defaultDirectory string) string { + if homeDir, err := os.UserHomeDir(); err == nil && IsWritable(homeDir) { + return homeDir + } + if user, err := user.Current(); err == nil && IsWritable(user.HomeDir) { + return user.HomeDir + } + return defaultDirectory +} + +// UserConfigDirOrDefault returns the user config directory or defaultConfigDir in case of error +func UserConfigDirOrDefault(defaultConfigDir string) string { + userConfigDir, err := os.UserConfigDir() + if err != nil { + return defaultConfigDir + } + return userConfigDir +} + +// AppConfigDirOrDefault returns the app config directory +func AppConfigDirOrDefault(defaultAppConfigDir string, toolName string) string { + userConfigDir := UserConfigDirOrDefault("") + if userConfigDir == "" { + return filepath.Join(defaultAppConfigDir, toolName) + } + return filepath.Join(userConfigDir, toolName) +} + +// AppCacheDirOrDefault returns the user cache directory or defaultCacheDir in case of error +func AppCacheDirOrDefault(defaultCacheDir string, toolName string) string { + userCacheDir, err := os.UserCacheDir() + if err != nil || userCacheDir == "" { + return filepath.Join(defaultCacheDir, toolName) + } + return filepath.Join(userCacheDir, toolName) +} From 60268dca6e8fd832db12408ec65b7ae631c97cae Mon Sep 17 00:00:00 2001 From: Tarun Koyalwar Date: Mon, 9 Oct 2023 21:41:15 +0530 Subject: [PATCH 2/2] add printStdDirs func + lint error --- folder/folderutil.go | 2 +- folder/std_dirs.go | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/folder/folderutil.go b/folder/folderutil.go index eb62cfc..6201b00 100644 --- a/folder/folderutil.go +++ b/folder/folderutil.go @@ -166,7 +166,7 @@ func IsWritable(path string) bool { } _ = tmpfile.Close() _ = os.Remove(tmpfile.Name()) - writeablePathCache.Set(path, struct{}{}) + _ = writeablePathCache.Set(path, struct{}{}) return true } diff --git a/folder/std_dirs.go b/folder/std_dirs.go index 229c78c..217630d 100644 --- a/folder/std_dirs.go +++ b/folder/std_dirs.go @@ -1,6 +1,7 @@ package folderutil import ( + "fmt" "os" "os/user" "path/filepath" @@ -48,3 +49,11 @@ func AppCacheDirOrDefault(defaultCacheDir string, toolName string) string { } return filepath.Join(userCacheDir, toolName) } + +// Prints the standard directories for a tool +func PrintStdDirs(toolName string) { + appConfigDir := AppConfigDirOrDefault("", toolName) + appCacheDir := AppCacheDirOrDefault("", toolName) + fmt.Printf("[+] %v %-13v: %v\n", toolName, "AppConfigDir", appConfigDir) + fmt.Printf("[+] %v %-13v: %v\n", toolName, "AppCacheDir", appCacheDir) +}