Skip to content

Commit

Permalink
Merge pull request #1181 from mattjoyce/bugfix/1169-symlinks
Browse files Browse the repository at this point in the history
Bugfix/1169 symlinks
  • Loading branch information
eugeis authored Dec 7, 2024
2 parents 43ca0dc + 0320e17 commit fbd6083
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 28 deletions.
74 changes: 74 additions & 0 deletions common/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package common

import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
)

// GetAbsolutePath resolves a given path to its absolute form, handling ~, ./, ../, UNC paths, and symlinks.
func GetAbsolutePath(path string) (string, error) {
if path == "" {
return "", errors.New("path is empty")
}

// Handle UNC paths on Windows
if runtime.GOOS == "windows" && strings.HasPrefix(path, `\\`) {
return path, nil
}

// Handle ~ for home directory expansion
if strings.HasPrefix(path, "~") {
home, err := os.UserHomeDir()
if err != nil {
return "", errors.New("could not resolve home directory")
}
path = filepath.Join(home, path[1:])
}

// Convert to absolute path
absPath, err := filepath.Abs(path)
if err != nil {
return "", errors.New("could not get absolute path")
}

// Resolve symlinks, but allow non-existent paths
resolvedPath, err := filepath.EvalSymlinks(absPath)
if err == nil {
return resolvedPath, nil
}
if os.IsNotExist(err) {
// Return the absolute path for non-existent paths
return absPath, nil
}

return "", fmt.Errorf("could not resolve symlinks: %w", err)
}


// Helper function to check if a symlink points to a directory
func IsSymlinkToDir(path string) bool {
fileInfo, err := os.Lstat(path)
if err != nil {
return false
}

if fileInfo.Mode()&os.ModeSymlink != 0 {
resolvedPath, err := filepath.EvalSymlinks(path)
if err != nil {
return false
}

fileInfo, err = os.Stat(resolvedPath)
if err != nil {
return false
}

return fileInfo.IsDir()
}

return false // Regular directories should not be treated as symlinks
}
13 changes: 12 additions & 1 deletion plugins/db/fsdb/patterns.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"
"strings"

"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/plugins/template"
)

Expand Down Expand Up @@ -33,19 +34,29 @@ func (o *PatternsEntity) GetApplyVariables(
strings.HasPrefix(source, ".")

if isFilePath {
pattern, err = o.getFromFile(source)
// Resolve the file path using GetAbsolutePath
absPath, err := common.GetAbsolutePath(source)
if err != nil {
return nil, fmt.Errorf("could not resolve file path: %v", err)
}

// Use the resolved absolute path to get the pattern
pattern, err = o.getFromFile(absPath)
} else {
// Otherwise, get the pattern from the database
pattern, err = o.getFromDB(source)
}

if err != nil {
return
}

// Apply variables to the pattern
err = o.applyVariables(pattern, variables, input)
return
}


func (o *PatternsEntity) applyVariables(
pattern *Pattern, variables map[string]string, input string) (err error) {

Expand Down
63 changes: 36 additions & 27 deletions plugins/db/fsdb/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"path/filepath"
"strings"

"github.com/samber/lo"
"github.com/danielmiessler/fabric/common"
)

type StorageEntity struct {
Expand All @@ -26,39 +26,48 @@ func (o *StorageEntity) Configure() (err error) {

// GetNames finds all patterns in the patterns directory and enters the id, name, and pattern into a slice of Entry structs. it returns these entries or an error
func (o *StorageEntity) GetNames() (ret []string, err error) {
// Resolve the directory path to an absolute path
absDir, err := common.GetAbsolutePath(o.Dir)
if err != nil {
return nil, fmt.Errorf("could not resolve directory path: %v", err)
}

// Read the directory entries
var entries []os.DirEntry
if entries, err = os.ReadDir(o.Dir); err != nil {
err = fmt.Errorf("could not read items from directory: %v", err)
return
if entries, err = os.ReadDir(absDir); err != nil {
return nil, fmt.Errorf("could not read items from directory: %v", err)
}

if o.ItemIsDir {
ret = lo.FilterMap(entries, func(item os.DirEntry, index int) (ret string, ok bool) {
if ok = item.IsDir(); ok {
ret = item.Name()
for _, entry := range entries {
entryPath := filepath.Join(absDir, entry.Name())

// Get metadata for the entry, including symlink info
fileInfo, err := os.Lstat(entryPath)
if err != nil {
return nil, fmt.Errorf("could not stat entry %s: %v", entryPath, err)
}

// Determine if the entry should be included
if o.ItemIsDir {
// Include directories or symlinks to directories
if fileInfo.IsDir() || (fileInfo.Mode()&os.ModeSymlink != 0 && common.IsSymlinkToDir(entryPath)) {
ret = append(ret, entry.Name())
}
} else {
// Include files, optionally filtering by extension
if !fileInfo.IsDir() {
if o.FileExtension == "" || filepath.Ext(entry.Name()) == o.FileExtension {
ret = append(ret, strings.TrimSuffix(entry.Name(), o.FileExtension))
}
}
}
return
})
} else {
if o.FileExtension == "" {
ret = lo.FilterMap(entries, func(item os.DirEntry, index int) (ret string, ok bool) {
if ok = !item.IsDir(); ok {
ret = item.Name()
}
return
})
} else {
ret = lo.FilterMap(entries, func(item os.DirEntry, index int) (ret string, ok bool) {
if ok = !item.IsDir() && filepath.Ext(item.Name()) == o.FileExtension; ok {
ret = strings.TrimSuffix(item.Name(), o.FileExtension)
}
return
})
}
}
return

return ret, nil
}



func (o *StorageEntity) Delete(name string) (err error) {
if err = os.Remove(o.BuildFilePathByName(name)); err != nil {
err = fmt.Errorf("could not delete %s: %v", name, err)
Expand Down

0 comments on commit fbd6083

Please sign in to comment.