Sfoglia il codice sorgente

use epoch timestamp instead of current timestamp for unknown modification times

Signed-off-by: Nicola Murino <[email protected]>
Nicola Murino 3 anni fa
parent
commit
2b463d61e3

+ 3 - 3
go.mod

@@ -21,7 +21,7 @@ require (
 	github.com/coreos/go-oidc/v3 v3.2.0
 	github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
 	github.com/fclairamb/ftpserverlib v0.19.0
-	github.com/fclairamb/go-log v0.3.0
+	github.com/fclairamb/go-log v0.4.0
 	github.com/go-acme/lego/v4 v4.8.0
 	github.com/go-chi/chi/v5 v5.0.8-0.20220512131524-9e71a0d4b3d6
 	github.com/go-chi/jwtauth/v5 v5.0.2
@@ -39,7 +39,7 @@ require (
 	github.com/lestrrat-go/jwx v1.2.25
 	github.com/lib/pq v1.10.6
 	github.com/lithammer/shortuuid/v3 v3.0.7
-	github.com/mattn/go-sqlite3 v1.14.14
+	github.com/mattn/go-sqlite3 v1.14.15
 	github.com/mhale/smtpd v0.8.0
 	github.com/minio/sio v0.3.0
 	github.com/otiai10/copy v1.7.0
@@ -133,7 +133,7 @@ require (
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/oklog/run v1.1.0 // indirect
 	github.com/pelletier/go-toml v1.9.5 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect

+ 6 - 6
go.sum

@@ -286,8 +286,8 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/fclairamb/ftpserverlib v0.19.0 h1:5QcSQ0OIJBlezIqmGehiL/AVsRb6dIkMxbkuhyPkESM=
 github.com/fclairamb/ftpserverlib v0.19.0/go.mod h1:pmukdVOFKKUY9zjWRoxFW8JAljyulC/uK5FfusJzK2E=
-github.com/fclairamb/go-log v0.3.0 h1:oSC7Zjt0FZIYC5xXahUUycKGkypSdr2srFPLsp7CLd0=
-github.com/fclairamb/go-log v0.3.0/go.mod h1:XG61EiPlAXnPDN8SA4N3zeA+GyBJmVOCCo12WORx/gA=
+github.com/fclairamb/go-log v0.4.0 h1:HLm0yU9IzNCqayuTqtLyWUy/Bjud7+DZWTSg0lAC5pQ=
+github.com/fclairamb/go-log v0.4.0/go.mod h1:sw1KvnkZ4wKCYkvy4SL3qVZcJSWFP8Ure4pM3z+KNn4=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
@@ -613,8 +613,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
 github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
-github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
+github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0=
@@ -652,8 +652,8 @@ github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI=
 github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
 github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
-github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
+github.com/pelletier/go-toml/v2 v2.0.3 h1:h9JoA60e1dVEOpp0PFwJSmt1Htu057NUq9/bUwaO61s=
+github.com/pelletier/go-toml/v2 v2.0.3/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
 github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
 github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
 github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=

+ 1 - 1
internal/common/connection.go

@@ -600,7 +600,7 @@ func (c *BaseConnection) DoStat(virtualPath string, mode int, checkFilePatterns
 	// if virtualPath is a virtual folder
 	vfolders := c.User.GetVirtualFoldersInPath(path.Dir(virtualPath))
 	if _, ok := vfolders[virtualPath]; ok {
-		return vfs.NewFileInfo(virtualPath, true, 0, time.Now(), false), nil
+		return vfs.NewFileInfo(virtualPath, true, 0, time.Unix(0, 0), false), nil
 	}
 	if checkFilePatterns {
 		ok, policy := c.User.IsFileAllowed(virtualPath)

+ 3 - 3
internal/dataprovider/bolt.go

@@ -1104,7 +1104,7 @@ func (p *BoltProvider) deleteFolderMappings(folder vfs.BaseVirtualFolder, usersB
 	return nil
 }
 
-func (p *BoltProvider) deleteFolder(folder vfs.BaseVirtualFolder) error {
+func (p *BoltProvider) deleteFolder(baseFolder vfs.BaseVirtualFolder) error {
 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 		bucket, err := p.getFoldersBucket(tx)
 		if err != nil {
@@ -1120,8 +1120,8 @@ func (p *BoltProvider) deleteFolder(folder vfs.BaseVirtualFolder) error {
 		}
 
 		var f []byte
-		if f = bucket.Get([]byte(folder.Name)); f == nil {
-			return util.NewRecordNotFoundError(fmt.Sprintf("folder %v does not exist", folder.Name))
+		if f = bucket.Get([]byte(baseFolder.Name)); f == nil {
+			return util.NewRecordNotFoundError(fmt.Sprintf("folder %v does not exist", baseFolder.Name))
 		}
 		var folder vfs.BaseVirtualFolder
 		err = json.Unmarshal(f, &folder)

+ 2 - 2
internal/dataprovider/memory.go

@@ -1322,14 +1322,14 @@ func (p *MemoryProvider) updateFolder(folder *vfs.BaseVirtualFolder) error {
 	return nil
 }
 
-func (p *MemoryProvider) deleteFolder(folder vfs.BaseVirtualFolder) error {
+func (p *MemoryProvider) deleteFolder(f vfs.BaseVirtualFolder) error {
 	p.dbHandle.Lock()
 	defer p.dbHandle.Unlock()
 	if p.dbHandle.isClosed {
 		return errMemoryProviderClosed
 	}
 
-	_, err := p.folderExistsInternal(folder.Name)
+	folder, err := p.folderExistsInternal(f.Name)
 	if err != nil {
 		return err
 	}

+ 2 - 2
internal/dataprovider/user.go

@@ -722,7 +722,7 @@ func (u *User) FilterListDir(dirContents []os.FileInfo, virtualPath string) []os
 		for dir := range vdirs {
 			if fi.Name() == dir {
 				if !fi.IsDir() {
-					fi = vfs.NewFileInfo(dir, true, 0, time.Now(), false)
+					fi = vfs.NewFileInfo(dir, true, 0, time.Unix(0, 0), false)
 					dirContents[index] = fi
 				}
 				delete(vdirs, dir)
@@ -744,7 +744,7 @@ func (u *User) FilterListDir(dirContents []os.FileInfo, virtualPath string) []os
 	}
 
 	for dir := range vdirs {
-		fi := vfs.NewFileInfo(dir, true, 0, time.Now(), false)
+		fi := vfs.NewFileInfo(dir, true, 0, time.Unix(0, 0), false)
 		dirContents = append(dirContents, fi)
 	}
 	return dirContents

+ 1 - 1
internal/ftpd/handler.go

@@ -165,7 +165,7 @@ func (c *Connection) Stat(name string) (os.FileInfo, error) {
 	if err != nil {
 		if c.isListDirWithWildcards(path.Base(name)) {
 			c.doWildcardListDir = true
-			return vfs.NewFileInfo(name, true, 0, time.Now(), false), nil
+			return vfs.NewFileInfo(name, true, 0, time.Unix(0, 0), false), nil
 		}
 		return nil, err
 	}

+ 2 - 2
internal/httpd/webclient.go

@@ -745,7 +745,7 @@ func (s *httpdServer) handleShareGetFiles(w http.ResponseWriter, r *http.Request
 
 	var info os.FileInfo
 	if name == "/" {
-		info = vfs.NewFileInfo(name, true, 0, time.Now(), false)
+		info = vfs.NewFileInfo(name, true, 0, time.Unix(0, 0), false)
 	} else {
 		info, err = connection.Stat(name, 1)
 	}
@@ -879,7 +879,7 @@ func (s *httpdServer) handleClientGetFiles(w http.ResponseWriter, r *http.Reques
 	name := connection.User.GetCleanedPath(r.URL.Query().Get("path"))
 	var info os.FileInfo
 	if name == "/" {
-		info = vfs.NewFileInfo(name, true, 0, time.Now(), false)
+		info = vfs.NewFileInfo(name, true, 0, time.Unix(0, 0), false)
 	} else {
 		info, err = connection.Stat(name, 0)
 	}

+ 4 - 4
internal/sftpd/handler.go

@@ -223,11 +223,11 @@ func (c *Connection) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
 		if err != nil {
 			return nil, err
 		}
-		now := time.Now()
+		modTime := time.Unix(0, 0)
 		if request.Filepath != "/" || c.folderPrefix != "" {
-			files = util.PrependFileInfo(files, vfs.NewFileInfo("..", true, 0, now, false))
+			files = util.PrependFileInfo(files, vfs.NewFileInfo("..", true, 0, modTime, false))
 		}
-		files = util.PrependFileInfo(files, vfs.NewFileInfo(".", true, 0, now, false))
+		files = util.PrependFileInfo(files, vfs.NewFileInfo(".", true, 0, modTime, false))
 		return listerAt(files), nil
 	case "Stat":
 		if !c.User.HasPerm(dataprovider.PermListItems, path.Dir(request.Filepath)) {
@@ -260,7 +260,7 @@ func (c *Connection) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
 			return nil, err
 		}
 
-		return listerAt([]os.FileInfo{vfs.NewFileInfo(s, false, 0, time.Now(), true)}), nil
+		return listerAt([]os.FileInfo{vfs.NewFileInfo(s, false, 0, time.Unix(0, 0), true)}), nil
 	default:
 		return nil, sftp.ErrSSHFxOpUnsupported
 	}

+ 6 - 6
internal/sftpd/middleware.go

@@ -67,7 +67,7 @@ func (p *prefixMiddleware) Lstat(request *sftp.Request) (sftp.ListerAt, error) {
 		return p.next.Lstat(request)
 	case pathIsPrefixParent:
 		return listerAt([]os.FileInfo{
-			vfs.NewFileInfo(request.Filepath, true, 0, time.Now(), false),
+			vfs.NewFileInfo(request.Filepath, true, 0, time.Unix(0, 0), false),
 		}), nil
 	default:
 		return nil, sftp.ErrSSHFxPermissionDenied
@@ -92,18 +92,18 @@ func (p *prefixMiddleware) Filelist(request *sftp.Request) (sftp.ListerAt, error
 	case pathIsPrefixParent:
 		switch request.Method {
 		case methodList:
-			now := time.Now()
+			modTime := time.Unix(0, 0)
 			fileName := p.nextListFolder(request.Filepath)
 			files := make([]os.FileInfo, 0, 3)
-			files = append(files, vfs.NewFileInfo(".", true, 0, now, false))
+			files = append(files, vfs.NewFileInfo(".", true, 0, modTime, false))
 			if request.Filepath != "/" {
-				files = append(files, vfs.NewFileInfo("..", true, 0, now, false))
+				files = append(files, vfs.NewFileInfo("..", true, 0, modTime, false))
 			}
-			files = append(files, vfs.NewFileInfo(fileName, true, 0, now, false))
+			files = append(files, vfs.NewFileInfo(fileName, true, 0, modTime, false))
 			return listerAt(files), nil
 		case methodStat:
 			return listerAt([]os.FileInfo{
-				vfs.NewFileInfo(request.Filepath, true, 0, time.Now(), false),
+				vfs.NewFileInfo(request.Filepath, true, 0, time.Unix(0, 0), false),
 			}), nil
 		default:
 			return nil, sftp.ErrSSHFxOpUnsupported

+ 2 - 3
internal/sftpd/middleware_test.go

@@ -16,7 +16,6 @@ package sftpd
 
 import (
 	"testing"
-	"time"
 
 	"github.com/golang/mock/gomock"
 	"github.com/pkg/sftp"
@@ -209,7 +208,7 @@ func (Suite *PrefixMiddlewareSuite) TestFileList() {
 					Suite.Equal(".", directList[0].Name())
 				}
 				Suite.Equal(test.ExpectedPath, directList[test.ExpectedItems-1].Name())
-				Suite.InDelta(time.Now().Unix(), directList[test.ExpectedItems-1].ModTime().Unix(), 1)
+				Suite.Equal(int64(0), directList[test.ExpectedItems-1].ModTime().Unix())
 				Suite.True(directList[test.ExpectedItems-1].IsDir())
 			}
 		}
@@ -224,7 +223,7 @@ func (Suite *PrefixMiddlewareSuite) TestLstat() {
 	if directList, ok := ListerAt.(listerAt); ok {
 		Suite.Len(directList, 1)
 		Suite.Equal(`/`, directList[0].Name())
-		Suite.InDelta(time.Now().Unix(), directList[0].ModTime().Unix(), 1)
+		Suite.Equal(int64(0), directList[0].ModTime().Unix())
 		Suite.True(directList[0].IsDir())
 	}
 

+ 1 - 1
internal/telemetry/telemetry_test.go

@@ -56,7 +56,7 @@ CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
 func TestInitialization(t *testing.T) {
 	c := Conf{
 		BindPort:       10000,
-		BindAddress:    "invalid",
+		BindAddress:    "invalid address",
 		EnableProfiler: false,
 	}
 	err := c.Initialize(".")

+ 7 - 7
internal/vfs/azblobfs.go

@@ -160,10 +160,10 @@ func (fs *AzureBlobFs) ConnectionID() string {
 // Stat returns a FileInfo describing the named file
 func (fs *AzureBlobFs) Stat(name string) (os.FileInfo, error) {
 	if name == "" || name == "/" || name == "." {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 	if fs.config.KeyPrefix == name+"/" {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 
 	attrs, err := fs.headObject(name)
@@ -184,7 +184,7 @@ func (fs *AzureBlobFs) Stat(name string) (os.FileInfo, error) {
 		return nil, err
 	}
 	if hasContents {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 	return nil, os.ErrNotExist
 }
@@ -455,7 +455,7 @@ func (fs *AzureBlobFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 				if _, ok := prefixes[strings.TrimSuffix(name, "/")]; ok {
 					continue
 				}
-				result = append(result, NewFileInfo(name, true, 0, time.Now(), false))
+				result = append(result, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 				prefixes[strings.TrimSuffix(name, "/")] = true
 			}
 
@@ -464,7 +464,7 @@ func (fs *AzureBlobFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 				name = strings.TrimPrefix(name, prefix)
 				size := int64(0)
 				isDir := false
-				modTime := time.Now()
+				modTime := time.Unix(0, 0)
 				if blobItem.Properties != nil {
 					size = util.GetIntFromPointer(blobItem.Properties.ContentLength)
 					modTime = util.GetTimeFromPointer(blobItem.Properties.LastModified)
@@ -697,7 +697,7 @@ func (fs *AzureBlobFs) Walk(root string, walkFn filepath.WalkFunc) error {
 					continue
 				}
 				blobSize := int64(0)
-				lastModified := time.Now()
+				lastModified := time.Unix(0, 0)
 				isDir := false
 				if blobItem.Properties != nil {
 					contentType := util.GetStringFromPointer(blobItem.Properties.ContentType)
@@ -720,7 +720,7 @@ func (fs *AzureBlobFs) Walk(root string, walkFn filepath.WalkFunc) error {
 	}
 
 	metric.AZListObjectsCompleted(nil)
-	return walkFn(root, NewFileInfo(root, true, 0, time.Now(), false), nil)
+	return walkFn(root, NewFileInfo(root, true, 0, time.Unix(0, 0), false), nil)
 }
 
 // Join joins any number of path elements into a single path

+ 5 - 5
internal/vfs/gcsfs.go

@@ -115,10 +115,10 @@ func (fs *GCSFs) ConnectionID() string {
 // Stat returns a FileInfo describing the named file
 func (fs *GCSFs) Stat(name string) (os.FileInfo, error) {
 	if name == "" || name == "/" || name == "." {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 	if fs.config.KeyPrefix == name+"/" {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 	_, info, err := fs.getObjectStat(name)
 	return info, err
@@ -404,7 +404,7 @@ func (fs *GCSFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 				if _, ok := prefixes[name]; ok {
 					continue
 				}
-				result = append(result, NewFileInfo(name, true, 0, time.Now(), false))
+				result = append(result, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 				prefixes[name] = true
 			} else {
 				name, isDir := fs.resolve(attrs.Name, prefix, attrs.ContentType)
@@ -688,7 +688,7 @@ func (fs *GCSFs) Walk(root string, walkFn filepath.WalkFunc) error {
 		}
 	}
 
-	walkFn(root, NewFileInfo(root, true, 0, time.Now(), false), err) //nolint:errcheck
+	walkFn(root, NewFileInfo(root, true, 0, time.Unix(0, 0), false), err) //nolint:errcheck
 	metric.GCSListObjectsCompleted(err)
 	return err
 }
@@ -746,7 +746,7 @@ func (fs *GCSFs) getObjectStat(name string) (string, os.FileInfo, error) {
 		return "", nil, err
 	}
 	if hasContents {
-		info, err = updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		info, err = updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 		return name, info, err
 	}
 	// finally check if this is an object with a trailing /

+ 1 - 1
internal/vfs/osfs.go

@@ -373,7 +373,7 @@ func (fs *OsFs) RealPath(p string) (string, error) {
 func (fs *OsFs) GetDirSize(dirname string) (int, int64, error) {
 	numFiles := 0
 	size := int64(0)
-	isDir, err := IsDirectory(fs, dirname)
+	isDir, err := isDirectory(fs, dirname)
 	if err == nil && isDir {
 		err = filepath.Walk(dirname, func(_ string, info os.FileInfo, err error) error {
 			if err != nil {

+ 6 - 6
internal/vfs/s3fs.go

@@ -151,10 +151,10 @@ func (fs *S3Fs) ConnectionID() string {
 func (fs *S3Fs) Stat(name string) (os.FileInfo, error) {
 	var result *FileInfo
 	if name == "" || name == "/" || name == "." {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 	if fs.config.KeyPrefix == name+"/" {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	}
 	obj, err := fs.headObject(name)
 	if err == nil {
@@ -168,7 +168,7 @@ func (fs *S3Fs) Stat(name string) (os.FileInfo, error) {
 	// now check if this is a prefix (virtual directory)
 	hasContents, err := fs.hasContents(name)
 	if err == nil && hasContents {
-		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Now(), false))
+		return updateFileInfoModTime(fs.getStorageID(), name, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 	} else if err != nil {
 		return nil, err
 	}
@@ -484,7 +484,7 @@ func (fs *S3Fs) ReadDir(dirname string) ([]os.FileInfo, error) {
 			if _, ok := prefixes[name]; ok {
 				continue
 			}
-			result = append(result, NewFileInfo(name, true, 0, time.Now(), false))
+			result = append(result, NewFileInfo(name, true, 0, time.Unix(0, 0), false))
 			prefixes[name] = true
 		}
 		for _, fileObject := range page.Contents {
@@ -700,7 +700,7 @@ func (fs *S3Fs) Walk(root string, walkFn filepath.WalkFunc) error {
 		page, err := paginator.NextPage(ctx)
 		if err != nil {
 			metric.S3ListObjectsCompleted(err)
-			walkFn(root, NewFileInfo(root, true, 0, time.Now(), false), err) //nolint:errcheck
+			walkFn(root, NewFileInfo(root, true, 0, time.Unix(0, 0), false), err) //nolint:errcheck
 			return err
 		}
 		for _, fileObject := range page.Contents {
@@ -717,7 +717,7 @@ func (fs *S3Fs) Walk(root string, walkFn filepath.WalkFunc) error {
 	}
 
 	metric.S3ListObjectsCompleted(nil)
-	walkFn(root, NewFileInfo(root, true, 0, time.Now(), false), nil) //nolint:errcheck
+	walkFn(root, NewFileInfo(root, true, 0, time.Unix(0, 0), false), nil) //nolint:errcheck
 	return nil
 }
 

+ 1 - 1
internal/vfs/sftpfs.go

@@ -726,7 +726,7 @@ func (fs *SFTPFs) GetDirSize(dirname string) (int, int64, error) {
 	if err := fs.checkConnection(); err != nil {
 		return numFiles, size, err
 	}
-	isDir, err := IsDirectory(fs, dirname)
+	isDir, err := isDirectory(fs, dirname)
 	if err == nil && isDir {
 		walker := fs.sftpClient.Walk(dirname)
 		for walker.Step() {

+ 2 - 2
internal/vfs/vfs.go

@@ -688,8 +688,8 @@ func isEqualityCheckModeValid(mode int) bool {
 	return mode >= 0 || mode <= 1
 }
 
-// IsDirectory checks if a path exists and is a directory
-func IsDirectory(fs Fs, path string) (bool, error) {
+// isDirectory checks if a path exists and is a directory
+func isDirectory(fs Fs, path string) (bool, error) {
 	fileInfo, err := fs.Stat(path)
 	if err != nil {
 		return false, err

+ 1 - 1
internal/webdavd/file.go

@@ -124,7 +124,7 @@ func (f *webDavFile) Stat() (os.FileInfo, error) {
 	f.Unlock()
 	if f.GetType() == common.TransferUpload && errUpload == nil {
 		info := &webDavFileInfo{
-			FileInfo:    vfs.NewFileInfo(f.GetFsPath(), false, atomic.LoadInt64(&f.BytesReceived), time.Now(), false),
+			FileInfo:    vfs.NewFileInfo(f.GetFsPath(), false, atomic.LoadInt64(&f.BytesReceived), time.Unix(0, 0), false),
 			Fs:          f.Fs,
 			virtualPath: f.GetVirtualPath(),
 			fsPath:      f.GetFsPath(),

+ 3 - 3
internal/webdavd/internal_test.go

@@ -637,15 +637,15 @@ func TestFileAccessErrors(t *testing.T) {
 	if assert.Error(t, err) {
 		assert.EqualError(t, err, os.ErrNotExist.Error())
 	}
-	_, err = connection.handleUploadToExistingFile(fs, p, p, 0, path.Join("adir", missingPath))
+	_, err = connection.handleUploadToExistingFile(fs, p, "_"+p, 0, path.Join("adir", missingPath))
 	if assert.Error(t, err) {
-		assert.EqualError(t, err, os.ErrNotExist.Error())
+		assert.ErrorIs(t, err, os.ErrNotExist)
 	}
 
 	fs = newMockOsFs(nil, false, fs.ConnectionID(), user.HomeDir, nil)
 	_, err = connection.handleUploadToExistingFile(fs, p, p, 0, path.Join("adir", missingPath))
 	if assert.Error(t, err) {
-		assert.EqualError(t, err, os.ErrNotExist.Error())
+		assert.ErrorIs(t, err, os.ErrNotExist)
 	}
 
 	f, err := os.CreateTemp("", "temp")