diff --git a/cmd/stfs/cmd/inventory_stat.go b/cmd/stfs/cmd/inventory_stat.go index 22b8cad..1ddd9ab 100644 --- a/cmd/stfs/cmd/inventory_stat.go +++ b/cmd/stfs/cmd/inventory_stat.go @@ -9,6 +9,10 @@ import ( "github.com/spf13/viper" ) +const ( + linkFlag = "link" +) + var inventoryStatCmd = &cobra.Command{ Use: "stat", Aliases: []string{"sta", "s"}, @@ -29,6 +33,7 @@ var inventoryStatCmd = &cobra.Command{ }, viper.GetString(nameFlag), + viper.GetBool(linkFlag), logging.NewCSVLogger().PrintHeader, ); err != nil { @@ -41,6 +46,7 @@ var inventoryStatCmd = &cobra.Command{ func init() { inventoryStatCmd.PersistentFlags().StringP(nameFlag, "n", "", "File or directory to get info for") + inventoryStatCmd.PersistentFlags().BoolP(linkFlag, "l", false, "Resolve as symlink") viper.AutomaticEnv() diff --git a/internal/fs/file.go b/internal/fs/file.go index 4b10b0d..539cdff 100644 --- a/internal/fs/file.go +++ b/internal/fs/file.go @@ -207,6 +207,7 @@ func (f *File) enterWriteMode() error { f.metadata, f.path, + false, f.onHeader, ) diff --git a/pkg/fs/filesystem.go b/pkg/fs/filesystem.go index 8c56ef3..f9dde9e 100644 --- a/pkg/fs/filesystem.go +++ b/pkg/fs/filesystem.go @@ -264,6 +264,7 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er f.metadata, name, + false, f.onHeader, ) @@ -278,6 +279,7 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er f.metadata, name, + false, f.onHeader, ) @@ -361,6 +363,7 @@ func (f *STFS) Stat(name string) (os.FileInfo, error) { f.metadata, name, + false, f.onHeader, ) @@ -414,6 +417,7 @@ func (f *STFS) Chmod(name string, mode os.FileMode) error { f.metadata, name, + false, f.onHeader, ) @@ -444,6 +448,7 @@ func (f *STFS) Chown(name string, uid, gid int) error { f.metadata, name, + false, f.onHeader, ) @@ -475,6 +480,7 @@ func (f *STFS) Chtimes(name string, atime time.Time, mtime time.Time) error { f.metadata, name, + false, f.onHeader, ) @@ -500,7 +506,23 @@ func (f *STFS) LstatIfPossible(name string) (os.FileInfo, bool, error) { f.ioLock.Lock() defer f.ioLock.Unlock() - return nil, false, config.ErrNotImplemented + hdr, err := inventory.Stat( + f.metadata, + + name, + true, + + f.onHeader, + ) + if err != nil { + if err == sql.ErrNoRows { + return nil, true, os.ErrNotExist + } + + return nil, true, err + } + + return ifs.NewFileInfoFromTarHeader(hdr, f.log), true, nil } func (f *STFS) SymlinkIfPossible(oldname, newname string) error { diff --git a/pkg/inventory/stat.go b/pkg/inventory/stat.go index 1cf8f61..b85814e 100644 --- a/pkg/inventory/stat.go +++ b/pkg/inventory/stat.go @@ -15,11 +15,29 @@ func Stat( metadata config.MetadataConfig, name string, + symlink bool, onHeader func(hdr *config.Header), ) (*tar.Header, error) { name = filepath.ToSlash(name) + if symlink { + // Resolve symlink + link, err := metadata.Metadata.GetHeader(context.Background(), name) + if err != nil { + if err == sql.ErrNoRows { + link, err = metadata.Metadata.GetHeader(context.Background(), strings.TrimSuffix(name, "/")+"/") + if err != nil { + return nil, err + } + } else { + return nil, err + } + } + + name = link.Linkname + } + dbhdr, err := metadata.Metadata.GetHeader(context.Background(), name) if err != nil { if err == sql.ErrNoRows {