Repository: spf13/afero
Pull request #378 (2022-08-30 21:19:42)

Add sftpfs files ReadAt method
This method is still a TODO after 6 years despite being a simple delegate, i don't think i missed any real reason why it wasn't implemented but i could be wrong.


Patch:
diff --git a/afero.go b/afero.go
index 199480c..39f6585 100644
--- a/afero.go
+++ b/afero.go
@@ -97,7 +97,7 @@ type Fs interface {
 	// Chown changes the uid and gid of the named file.
 	Chown(name string, uid, gid int) error
 
-	//Chtimes changes the access and modification times of the named file
+	// Chtimes changes the access and modification times of the named file
 	Chtimes(name string, atime time.Time, mtime time.Time) error
 }
 
diff --git a/basepath.go b/basepath.go
index 70a1d91..2e72793 100644
--- a/basepath.go
+++ b/basepath.go
@@ -40,7 +40,6 @@ func (f *BasePathFile) Name() string {
 func (f *BasePathFile) ReadDir(n int) ([]fs.DirEntry, error) {
 	if rdf, ok := f.File.(fs.ReadDirFile); ok {
 		return rdf.ReadDir(n)
-
 	}
 	return readDirFile{f.File}.ReadDir(n)
 }
diff --git a/copyOnWriteFs.go b/copyOnWriteFs.go
index 6ff8f30..184d6dd 100644
--- a/copyOnWriteFs.go
+++ b/copyOnWriteFs.go
@@ -223,7 +223,7 @@ func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File,
 			return nil, err
 		}
 		if isaDir {
-			if err = u.layer.MkdirAll(dir, 0777); err != nil {
+			if err = u.layer.MkdirAll(dir, 0o777); err != nil {
 				return nil, err
 			}
 			return u.layer.OpenFile(name, flag, perm)
@@ -247,8 +247,9 @@ func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File,
 
 // This function handles the 9 different possibilities caused
 // by the union which are the intersection of the following...
-//  layer: doesn't exist, exists as a file, and exists as a directory
-//  base:  doesn't exist, exists as a file, and exists as a directory
+//
+//	layer: doesn't exist, exists as a file, and exists as a directory
+//	base:  doesn't exist, exists as a file, and exists as a directory
 func (u *CopyOnWriteFs) Open(name string) (File, error) {
 	// Since the overlay overrides the base we check that first
 	b, err := u.isBaseFile(name)
@@ -322,5 +323,5 @@ func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error {
 }
 
 func (u *CopyOnWriteFs) Create(name string) (File, error) {
-	return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
+	return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0o666)
 }
diff --git a/gcsfs/file.go b/gcsfs/file.go
index f916bd2..671c046 100644
--- a/gcsfs/file.go
+++ b/gcsfs/file.go
@@ -36,7 +36,7 @@ import (
 // GcsFs is the Afero version adapted for GCS
 type GcsFile struct {
 	openFlags int
-	fhOffset  int64 //File handle specific offset
+	fhOffset  int64 // File handle specific offset
 	closed    bool
 	ReadDirIt stiface.ObjectIterator
 	resource  *gcsFileResource
@@ -105,13 +105,13 @@ func (o *GcsFile) Seek(newOffset int64, whence int) (int64, error) {
 		return 0, ErrFileClosed
 	}
 
-	//Since this is an expensive operation; let's make sure we need it
+	// Since this is an expensive operation; let's make sure we need it
 	if (whence == 0 && newOffset == o.fhOffset) || (whence == 1 && newOffset == 0) {
 		return o.fhOffset, nil
 	}
 	log.Printf("WARNING: Seek behavior triggered, highly inefficent. Offset before seek is at %d\n", o.fhOffset)
 
-	//Fore the reader/writers to be reopened (at correct offset)
+	// Fore the reader/writers to be reopened (at correct offset)
 	err := o.Sync()
 	if err != nil {
 		return 0, err
@@ -197,7 +197,7 @@ func (o *GcsFile) readdirImpl(count int) ([]*FileInfo, error) {
 
 	path := o.resource.fs.ensureTrailingSeparator(o.resource.name)
 	if o.ReadDirIt == nil {
-		//log.Printf("Querying path : %s\n", path)
+		// log.Printf("Querying path : %s\n", path)
 		bucketName, bucketPath := o.resource.fs.splitName(path)
 
 		o.ReadDirIt = o.resource.fs.client.Bucket(bucketName).Objects(
@@ -246,7 +246,7 @@ func (o *GcsFile) readdirImpl(count int) ([]*FileInfo, error) {
 		//	break
 		//}
 	}
-	//return res, nil
+	// return res, nil
 }
 
 func (o *GcsFile) Readdir(count int) ([]os.FileInfo, error) {
diff --git a/gcsfs/file_info.go b/gcsfs/file_info.go
index 0a42d38..92e3046 100644
--- a/gcsfs/file_info.go
+++ b/gcsfs/file_info.go
@@ -110,6 +110,7 @@ func (fi *FileInfo) Name() string {
 func (fi *FileInfo) Size() int64 {
 	return fi.size
 }
+
 func (fi *FileInfo) Mode() os.FileMode {
 	if fi.IsDir() {
 		return os.ModeDir | fi.fileMode
diff --git a/gcsfs/file_resource.go b/gcsfs/file_resource.go
index c25ad51..06d5c54 100644
--- a/gcsfs/file_resource.go
+++ b/gcsfs/file_resource.go
@@ -146,7 +146,7 @@ func (o *gcsFileResource) ReadAt(p []byte, off int64) (n int, err error) {
 		return 0, err
 	}
 
-	//Then read at the correct offset.
+	// Then read at the correct offset.
 	r, err := o.obj.NewRangeReader(o.ctx, off, -1)
 	if err != nil {
 		return 0, err
@@ -160,7 +160,7 @@ func (o *gcsFileResource) ReadAt(p []byte, off int64) (n int, err error) {
 }
 
 func (o *gcsFileResource) WriteAt(b []byte, off int64) (n int, err error) {
-	//If the writer is opened and at the correct offset we're good!
+	// If the writer is opened and at the correct offset we're good!
 	if off == o.offset && o.writer != nil {
 		n, err = o.writer.Write(b)
 		o.offset += int64(n)
@@ -251,7 +251,7 @@ func (o *gcsFileResource) Truncate(wantedSize int64) error {
 	}
 
 	for written < wantedSize {
-		//Bulk up padding writes
+		// Bulk up padding writes
 		paddingBytes := bytes.Repeat([]byte(" "), min(maxWriteSize, int(wantedSize-written)))
 
 		n := 0
diff --git a/gcsfs/fs.go b/gcsfs/fs.go
index 9b0dde4..b2a78fc 100644
--- a/gcsfs/fs.go
+++ b/gcsfs/fs.go
@@ -29,7 +29,7 @@ import (
 )
 
 const (
-	defaultFileMode = 0755
+	defaultFileMode = 0o755
 	gsPrefix        = "gs://"
 )
 
@@ -42,7 +42,7 @@ type Fs struct {
 	buckets       map[string]stiface.BucketHandle
 	rawGcsObjects map[string]*GcsFile
 
-	autoRemoveEmptyFolders bool //trigger for creating "virtual folders" (not required by GCSs)
+	autoRemoveEmptyFolders bool // trigger for creating "virtual folders" (not required by GCSs)
 }
 
 func NewGcsFs(ctx context.Context, client stiface.Client) *Fs {
@@ -71,6 +71,7 @@ func (fs *Fs) ensureTrailingSeparator(s string) string {
 	}
 	return s
 }
+
 func (fs *Fs) ensureNoLeadingSeparator(s string) string {
 	if len(s) > 0 && strings.HasPrefix(s, fs.separator) {
 		s = s[len(fs.separator):]
@@ -200,7 +201,7 @@ func (fs *Fs) MkdirAll(path string, perm os.FileMode) error {
 		if f == "" && i != 0 {
 			continue // it's the last item - it should be empty
 		}
-		//Don't force a delimiter prefix
+		// Don't force a delimiter prefix
 		if root != "" {
 			root = root + fs.separator + f
 		} else {
diff --git a/gcsfs/gcs.go b/gcsfs/gcs.go
index 78cc924..c94b142 100644
--- a/gcsfs/gcs.go
+++ b/gcsfs/gcs.go
@@ -76,39 +76,51 @@ func NewGcsFSFromClientWithSeparator(ctx context.Context, client *storage.Client
 func (fs *GcsFs) Name() string {
 	return fs.source.Name()
 }
+
 func (fs *GcsFs) Create(name string) (afero.File, error) {
 	return fs.source.Create(name)
 }
+
 func (fs *GcsFs) Mkdir(name string, perm os.FileMode) error {
 	return fs.source.Mkdir(name, perm)
 }
+
 func (fs *GcsFs) MkdirAll(path string, perm os.FileMode) error {
 	return fs.source.MkdirAll(path, perm)
 }
+
 func (fs *GcsFs) Open(name string) (afero.File, error) {
 	return fs.source.Open(name)
 }
+
 func (fs *GcsFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
 	return fs.source.OpenFile(name, flag, perm)
 }
+
 func (fs *GcsFs) Remove(name string) error {
 	return fs.source.Remove(name)
 }
+
 func (fs *GcsFs) RemoveAll(path string) error {
 	return fs.source.RemoveAll(path)
 }
+
 func (fs *GcsFs) Rename(oldname, newname string) error {
 	return fs.source.Rename(oldname, newname)
 }
+
 func (fs *GcsFs) Stat(name string) (os.FileInfo, error) {
 	return fs.source.Stat(name)
 }
+
 func (fs *GcsFs) Chmod(name string, mode os.FileMode) error {
 	return fs.source.Chmod(name, mode)
 }
+
 func (fs *GcsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 	return fs.source.Chtimes(name, atime, mtime)
 }
+
 func (fs *GcsFs) Chown(name string, uid, gid int) error {
 	return fs.source.Chown(name, uid, gid)
 }
diff --git a/gcsfs/gcs_mocks.go b/gcsfs/gcs_mocks.go
index 272eb9f..b71b292 100644
--- a/gcsfs/gcs_mocks.go
+++ b/gcsfs/gcs_mocks.go
@@ -166,7 +166,7 @@ func (w *writerMock) Close() error {
 	if w.file == nil {
 		var err error
 		if strings.HasSuffix(w.name, "/") {
-			err = w.fs.Mkdir(w.name, 0755)
+			err = w.fs.Mkdir(w.name, 0o755)
 			if err != nil {
 				return err
 			}
diff --git a/go.mod b/go.mod
index a301a4e..d6b1962 100644
--- a/go.mod
+++ b/go.mod
@@ -4,9 +4,9 @@ require (
 	cloud.google.com/go/storage v1.14.0
 	github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8
 	github.com/pkg/sftp v1.13.1
-	golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
+	golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
 	golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99
-	golang.org/x/text v0.3.4
+	golang.org/x/text v0.3.7
 	google.golang.org/api v0.40.0
 )
 
diff --git a/go.sum b/go.sum
index 3b9968a..e0228c2 100644
--- a/go.sum
+++ b/go.sum
@@ -163,8 +163,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -230,8 +230,9 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -284,6 +285,7 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -294,8 +296,10 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
diff --git a/ioutil.go b/ioutil.go
index 386c9cd..fa6abe1 100644
--- a/ioutil.go
+++ b/ioutil.go
@@ -141,8 +141,10 @@ func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error {
 // We generate random temporary file names so that there's a good
 // chance the file doesn't exist yet - keeps the number of tries in
 // TempFile to a minimum.
-var randNum uint32
-var randmu sync.Mutex
+var (
+	randNum uint32
+	randmu  sync.Mutex
+)
 
 func reseed() uint32 {
 	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
@@ -190,7 +192,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
 	nconflict := 0
 	for i := 0; i < 10000; i++ {
 		name := filepath.Join(dir, prefix+nextRandom()+suffix)
-		f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+		f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600)
 		if os.IsExist(err) {
 			if nconflict++; nconflict > 10 {
 				randmu.Lock()
@@ -214,6 +216,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
 func (a Afero) TempDir(dir, prefix string) (name string, err error) {
 	return TempDir(a.Fs, dir, prefix)
 }
+
 func TempDir(fs Fs, dir, prefix string) (name string, err error) {
 	if dir == "" {
 		dir = os.TempDir()
@@ -222,7 +225,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {
 	nconflict := 0
 	for i := 0; i < 10000; i++ {
 		try := filepath.Join(dir, prefix+nextRandom())
-		err = fs.Mkdir(try, 0700)
+		err = fs.Mkdir(try, 0o700)
 		if os.IsExist(err) {
 			if nconflict++; nconflict > 10 {
 				randmu.Lock()
diff --git a/mem/file.go b/mem/file.go
index 3cf4693..62fe449 100644
--- a/mem/file.go
+++ b/mem/file.go
@@ -245,7 +245,7 @@ func (f *File) Truncate(size int64) error {
 	defer f.fileData.Unlock()
 	if size > int64(len(f.fileData.data)) {
 		diff := size - int64(len(f.fileData.data))
-		f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...)
+		f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{0o0}, int(diff))...)
 	} else {
 		f.fileData.data = f.fileData.data[0:size]
 	}
@@ -285,7 +285,7 @@ func (f *File) Write(b []byte) (n int, err error) {
 		tail = f.fileData.data[n+int(cur):]
 	}
 	if diff > 0 {
-		f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{00}, int(diff)), b...)...)
+		f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{0o0}, int(diff)), b...)...)
 		f.fileData.data = append(f.fileData.data, tail...)
 	} else {
 		f.fileData.data = append(f.fileData.data[:cur], b...)
@@ -321,16 +321,19 @@ func (s *FileInfo) Name() string {
 	s.Unlock()
 	return name
 }
+
 func (s *FileInfo) Mode() os.FileMode {
 	s.Lock()
 	defer s.Unlock()
 	return s.mode
 }
+
 func (s *FileInfo) ModTime() time.Time {
 	s.Lock()
 	defer s.Unlock()
 	return s.modtime
 }
+
 func (s *FileInfo) IsDir() bool {
 	s.Lock()
 	defer s.Unlock()
diff --git a/memmap.go b/memmap.go
index ea0798d..e6b7d70 100644
--- a/memmap.go
+++ b/memmap.go
@@ -15,6 +15,7 @@ package afero
 
 import (
 	"fmt"
+	"io"
 	"log"
 	"os"
 	"path/filepath"
@@ -43,7 +44,7 @@ func (m *MemMapFs) getData() map[string]*mem.FileData {
 		// Root should always exist, right?
 		// TODO: what about windows?
 		root := mem.CreateDir(FilePathSeparator)
-		mem.SetMode(root, os.ModeDir|0755)
+		mem.SetMode(root, os.ModeDir|0o755)
 		m.data[FilePathSeparator] = root
 	})
 	return m.data
@@ -96,12 +97,12 @@ func (m *MemMapFs) registerWithParent(f *mem.FileData, perm os.FileMode) {
 		pdir := filepath.Dir(filepath.Clean(f.Name()))
 		err := m.lockfreeMkdir(pdir, perm)
 		if err != nil {
-			//log.Println("Mkdir error:", err)
+			// log.Println("Mkdir error:", err)
 			return
 		}
 		parent, err = m.lockfreeOpen(pdir)
 		if err != nil {
-			//log.Println("Open after Mkdir error:", err)
+			// log.Println("Open after Mkdir error:", err)
 			return
 		}
 	}
@@ -142,6 +143,11 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
 	}
 
 	m.mu.Lock()
+	// Dobule check that it doesn't exist.
+	if _, ok := m.getData()[name]; ok {
+		m.mu.Unlock()
+		return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
+	}
 	item := mem.CreateDir(name)
 	mem.SetMode(item, os.ModeDir|perm)
 	m.getData()[name] = item
@@ -232,7 +238,7 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro
 		file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
 	}
 	if flag&os.O_APPEND > 0 {
-		_, err = file.Seek(0, os.SEEK_END)
+		_, err = file.Seek(0, io.SeekEnd)
 		if err != nil {
 			file.Close()
 			return nil, err
@@ -314,6 +320,18 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
 	} else {
 		return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
 	}
+
+	for p, fileData := range m.getData() {
+		if strings.HasPrefix(p, oldname+FilePathSeparator) {
+			m.mu.RUnlock()
+			m.mu.Lock()
+			delete(m.getData(), p)
+			p := strings.Replace(p, oldname, newname, 1)
+			m.getData()[p] = fileData
+			m.mu.Unlock()
+			m.mu.RLock()
+		}
+	}
 	return nil
 }
 
diff --git a/regexpfs.go b/regexpfs.go
index ac359c6..218f3b2 100644
--- a/regexpfs.go
+++ b/regexpfs.go
@@ -10,7 +10,6 @@ import (
 // The RegexpFs filters files (not directories) by regular expression. Only
 // files matching the given regexp will be allowed, all others get a ENOENT error (
 // "No such file or directory").
-//
 type RegexpFs struct {
 	re     *regexp.Regexp
 	source Fs
diff --git a/sftpfs/file.go b/sftpfs/file.go
index eef14e3..324282f 100644
--- a/sftpfs/file.go
+++ b/sftpfs/file.go
@@ -64,9 +64,8 @@ func (f *File) Read(b []byte) (n int, err error) {
 	return f.fd.Read(b)
 }
 
-// TODO
 func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
-	return 0, nil
+	return f.fd.ReadAt(b, off)
 }
 
 func (f *File) Readdir(count int) (res []os.FileInfo, err error) {
diff --git a/symlink.go b/symlink.go
index d1c6ea5..aa6ae12 100644
--- a/symlink.go
+++ b/symlink.go
@@ -21,9 +21,9 @@ import (
 // filesystems saying so.
 // It indicates support for 3 symlink related interfaces that implement the
 // behaviors of the os methods:
-//    - Lstat
-//    - Symlink, and
-//    - Readlink
+//   - Lstat
+//   - Symlink, and
+//   - Readlink
 type Symlinker interface {
 	Lstater
 	Linker
diff --git a/unionFile.go b/unionFile.go
index 333d367..62dd6c9 100644
--- a/unionFile.go
+++ b/unionFile.go
@@ -47,7 +47,7 @@ func (f *UnionFile) Read(s []byte) (int, error) {
 		if (err == nil || err == io.EOF) && f.Base != nil {
 			// advance the file position also in the base file, the next
 			// call may be a write at this position (or a seek with SEEK_CUR)
-			if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil {
+			if _, seekErr := f.Base.Seek(int64(n), io.SeekCurrent); seekErr != nil {
 				// only overwrite err in case the seek fails: we need to
 				// report an eventual io.EOF to the caller
 				err = seekErr
@@ -130,7 +130,7 @@ func (f *UnionFile) Name() string {
 type DirsMerger func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error)
 
 var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) {
-	var files = make(map[string]os.FileInfo)
+	files := make(map[string]os.FileInfo)
 
 	for _, fi := range lofi {
 		files[fi.Name()] = fi
@@ -151,7 +151,6 @@ var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, err
 	}
 
 	return rfi, nil
-
 }
 
 // Readdir will weave the two directories together and
@@ -275,7 +274,7 @@ func copyFile(base Fs, layer Fs, name string, bfh File) error {
 		return err
 	}
 	if !exists {
-		err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME?
+		err = layer.MkdirAll(filepath.Dir(name), 0o777) // FIXME?
 		if err != nil {
 			return err
 		}
diff --git a/util.go b/util.go
index cb7de23..9e4cba2 100644
--- a/util.go
+++ b/util.go
@@ -43,7 +43,7 @@ func WriteReader(fs Fs, path string, r io.Reader) (err error) {
 	ospath := filepath.FromSlash(dir)
 
 	if ospath != "" {
-		err = fs.MkdirAll(ospath, 0777) // rwx, rw, r
+		err = fs.MkdirAll(ospath, 0o777) // rwx, rw, r
 		if err != nil {
 			if err != os.ErrExist {
 				return err
@@ -71,7 +71,7 @@ func SafeWriteReader(fs Fs, path string, r io.Reader) (err error) {
 	ospath := filepath.FromSlash(dir)
 
 	if ospath != "" {
-		err = fs.MkdirAll(ospath, 0777) // rwx, rw, r
+		err = fs.MkdirAll(ospath, 0o777) // rwx, rw, r
 		if err != nil {
 			return
 		}
@@ -124,7 +124,7 @@ func GetTempDir(fs Fs, subPath string) string {
 			return addSlash(dir)
 		}
 
-		err := fs.MkdirAll(dir, 0777)
+		err := fs.MkdirAll(dir, 0o777)
 		if err != nil {
 			panic(err)
 		}
@@ -197,7 +197,6 @@ func FileContainsAnyBytes(fs Fs, filename string, subslices [][]byte) (bool, err
 
 // readerContains reports whether any of the subslices is within r.
 func readerContainsAny(r io.Reader, subslices ...[]byte) bool {
-
 	if r == nil || len(subslices) == 0 {
 		return false
 	}


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 1f3b02d..011f9e5 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -7,7 +7,7 @@ jobs:
   test:
     strategy:
       matrix:
-        go-version: [1.16.x,1.17.x,1.18.x]
+        go-version: [1.18.x,1.19.x,1.20.x]
         platform: [ubuntu-latest, macos-latest, windows-latest]
     runs-on: ${{ matrix.platform }}
     steps:
@@ -16,7 +16,7 @@ jobs:
       with:
         go-version: ${{ matrix.go-version }}
     - name: Install staticcheck
-      if: matrix.go-version != '1.16.x'
+      if: matrix.go-version == '1.20.x'
       run: go install honnef.co/go/tools/cmd/staticcheck@latest
       shell: bash
     - name: Update PATH
@@ -31,7 +31,7 @@ jobs:
     - name: Vet
       run: go vet ./...
     - name: Staticcheck
-      if: matrix.go-version != '1.16.x'
+      if: matrix.go-version == '1.20.x'
       run: staticcheck ./...
     - name: Test
       run: go test -race ./...
\ No newline at end of file
diff --git a/afero_test.go b/afero_test.go
index f875ae1..9a1d84f 100644
--- a/afero_test.go
+++ b/afero_test.go
@@ -28,8 +28,10 @@ import (
 	"testing"
 )
 
-var testName = "test.txt"
-var Fss = []Fs{&MemMapFs{}, &OsFs{}}
+var (
+	testName = "test.txt"
+	Fss      = []Fs{&MemMapFs{}, &OsFs{}}
+)
 
 var testRegistry map[Fs][]string = make(map[Fs][]string)
 
@@ -45,7 +47,6 @@ func testDir(fs Fs) string {
 
 func tmpFile(fs Fs) File {
 	x, err := TempFile(fs, "", "afero")
-
 	if err != nil {
 		panic(fmt.Sprint("unable to work with temp file", err))
 	}
@@ -55,7 +56,7 @@ func tmpFile(fs Fs) File {
 	return x
 }
 
-//Read with length 0 should not return EOF.
+// Read with length 0 should not return EOF.
 func TestRead0(t *testing.T) {
 	for _, fs := range Fss {
 		f := tmpFile(fs)
@@ -83,7 +84,7 @@ func TestOpenFile(t *testing.T) {
 		tmp := testDir(fs)
 		path := filepath.Join(tmp, testName)
 
-		f, err := fs.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600)
+		f, err := fs.OpenFile(path, os.O_RDWR|os.O_CREATE, 0o600)
 		if err != nil {
 			t.Error(fs.Name(), "OpenFile (O_CREATE) failed:", err)
 			continue
@@ -91,7 +92,7 @@ func TestOpenFile(t *testing.T) {
 		io.WriteString(f, "initial")
 		f.Close()
 
-		f, err = fs.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0600)
+		f, err = fs.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0o600)
 		if err != nil {
 			t.Error(fs.Name(), "OpenFile (O_APPEND) failed:", err)
 			continue
@@ -99,7 +100,7 @@ func TestOpenFile(t *testing.T) {
 		io.WriteString(f, "|append")
 		f.Close()
 
-		f, _ = fs.OpenFile(path, os.O_RDONLY, 0600)
+		f, _ = fs.OpenFile(path, os.O_RDONLY, 0o600)
 		contents, _ := ioutil.ReadAll(f)
 		expectedContents := "initial|append"
 		if string(contents) != expectedContents {
@@ -107,7 +108,7 @@ func TestOpenFile(t *testing.T) {
 		}
 		f.Close()
 
-		f, err = fs.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0600)
+		f, err = fs.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0o600)
 		if err != nil {
 			t.Error(fs.Name(), "OpenFile (O_TRUNC) failed:", err)
 			continue
@@ -333,7 +334,7 @@ func TestSeek(t *testing.T) {
 			whence int
 			out    int64
 		}
-		var tests = []test{
+		tests := []test{
 			{0, 1, int64(len(data))},
 			{0, 0, 0},
 			{5, 0, 5},
@@ -424,7 +425,7 @@ func setupTestDirReusePath(t *testing.T, fs Fs, path string) string {
 
 func setupTestFiles(t *testing.T, fs Fs, path string) string {
 	testSubDir := filepath.Join(path, "more", "subdirectories", "for", "testing", "we")
-	err := fs.MkdirAll(testSubDir, 0700)
+	err := fs.MkdirAll(testSubDir, 0o700)
 	if err != nil && !os.IsExist(err) {
 		t.Fatal(err)
 	}
@@ -637,7 +638,7 @@ func TestReaddirAll(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		var namesRoot = []string{}
+		namesRoot := []string{}
 		for _, e := range rootInfo {
 			namesRoot = append(namesRoot, e.Name())
 		}
@@ -652,7 +653,7 @@ func TestReaddirAll(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		var namesSub = []string{}
+		namesSub := []string{}
 		for _, e := range subInfo {
 			namesSub = append(namesSub, e.Name())
 		}
diff --git a/basepath_test.go b/basepath_test.go
index e314c05..1c46abd 100644
--- a/basepath_test.go
+++ b/basepath_test.go
@@ -9,7 +9,7 @@ import (
 
 func TestBasePath(t *testing.T) {
 	baseFs := &MemMapFs{}
-	baseFs.MkdirAll("/base/path/tmp", 0777)
+	baseFs.MkdirAll("/base/path/tmp", 0o777)
 	bp := NewBasePathFs(baseFs, "/base/path")
 
 	if _, err := bp.Create("/tmp/foo"); err != nil {
@@ -23,8 +23,8 @@ func TestBasePath(t *testing.T) {
 
 func TestBasePathRoot(t *testing.T) {
 	baseFs := &MemMapFs{}
-	baseFs.MkdirAll("/base/path/foo/baz", 0777)
-	baseFs.MkdirAll("/base/path/boo/", 0777)
+	baseFs.MkdirAll("/base/path/foo/baz", 0o777)
+	baseFs.MkdirAll("/base/path/boo/", 0o777)
 	bp := NewBasePathFs(baseFs, "/base/path")
 
 	rd, err := ReadDir(bp, string(os.PathSeparator))
@@ -56,7 +56,6 @@ func TestRealPath(t *testing.T) {
 	subDir := filepath.Join(baseDir, "s1")
 
 	realPath, err := bp.RealPath("/s1")
-
 	if err != nil {
 		t.Errorf("Got error %s", err)
 	}
@@ -77,7 +76,6 @@ func TestRealPath(t *testing.T) {
 		// is not inside the base file system.
 		// The user will receive an os.ErrNotExist later.
 		surrealPath, err := bp.RealPath(anotherDir)
-
 		if err != nil {
 			t.Errorf("Got error %s", err)
 		}
@@ -88,7 +86,6 @@ func TestRealPath(t *testing.T) {
 			t.Errorf("Expected \n%s got \n%s", excpected, surrealPath)
 		}
 	}
-
 }
 
 func TestNestedBasePaths(t *testing.T) {
@@ -119,7 +116,7 @@ func TestNestedBasePaths(t *testing.T) {
 		}
 
 		for _, s := range specs {
-			if err := s.BaseFs.MkdirAll(s.FileName, 0755); err != nil {
+			if err := s.BaseFs.MkdirAll(s.FileName, 0o755); err != nil {
 				t.Errorf("Got error %s", err.Error())
 			}
 			if _, err := s.BaseFs.Stat(s.FileName); err != nil {
@@ -143,9 +140,9 @@ func TestNestedBasePaths(t *testing.T) {
 
 func TestBasePathOpenFile(t *testing.T) {
 	baseFs := &MemMapFs{}
-	baseFs.MkdirAll("/base/path/tmp", 0777)
+	baseFs.MkdirAll("/base/path/tmp", 0o777)
 	bp := NewBasePathFs(baseFs, "/base/path")
-	f, err := bp.OpenFile("/tmp/file.txt", os.O_CREATE, 0600)
+	f, err := bp.OpenFile("/tmp/file.txt", os.O_CREATE, 0o600)
 	if err != nil {
 		t.Fatalf("failed to open file: %v", err)
 	}
@@ -156,7 +153,7 @@ func TestBasePathOpenFile(t *testing.T) {
 
 func TestBasePathCreate(t *testing.T) {
 	baseFs := &MemMapFs{}
-	baseFs.MkdirAll("/base/path/tmp", 0777)
+	baseFs.MkdirAll("/base/path/tmp", 0o777)
 	bp := NewBasePathFs(baseFs, "/base/path")
 	f, err := bp.Create("/tmp/file.txt")
 	if err != nil {
@@ -169,7 +166,7 @@ func TestBasePathCreate(t *testing.T) {
 
 func TestBasePathTempFile(t *testing.T) {
 	baseFs := &MemMapFs{}
-	baseFs.MkdirAll("/base/path/tmp", 0777)
+	baseFs.MkdirAll("/base/path/tmp", 0o777)
 	bp := NewBasePathFs(baseFs, "/base/path")
 
 	tDir, err := TempDir(bp, "/tmp", "")
diff --git a/composite_test.go b/composite_test.go
index 05605fb..88fd49b 100644
--- a/composite_test.go
+++ b/composite_test.go
@@ -54,12 +54,12 @@ func TestUnionCreateExisting(t *testing.T) {
 	roBase := &ReadOnlyFs{source: base}
 	ufs := NewCopyOnWriteFs(roBase, &MemMapFs{})
 
-	base.MkdirAll("/home/test", 0777)
+	base.MkdirAll("/home/test", 0o777)
 	fh, _ := base.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
 
-	fh, err := ufs.OpenFile("/home/test/file.txt", os.O_RDWR, 0666)
+	fh, err := ufs.OpenFile("/home/test/file.txt", os.O_RDWR, 0o666)
 	if err != nil {
 		t.Errorf("Failed to open file r/w: %s", err)
 	}
@@ -95,7 +95,6 @@ func TestUnionCreateExisting(t *testing.T) {
 	default:
 		t.Errorf("Create failed on existing file")
 	}
-
 }
 
 func TestUnionMergeReaddir(t *testing.T) {
@@ -104,7 +103,7 @@ func TestUnionMergeReaddir(t *testing.T) {
 
 	ufs := &CopyOnWriteFs{base: roBase, layer: &MemMapFs{}}
 
-	base.MkdirAll("/home/test", 0777)
+	base.MkdirAll("/home/test", 0o777)
 	fh, _ := base.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
@@ -130,12 +129,12 @@ func TestExistingDirectoryCollisionReaddir(t *testing.T) {
 
 	ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
 
-	base.MkdirAll("/home/test", 0777)
+	base.MkdirAll("/home/test", 0o777)
 	fh, _ := base.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
 
-	overlay.MkdirAll("home/test", 0777)
+	overlay.MkdirAll("home/test", 0o777)
 	fh, _ = overlay.Create("/home/test/file2.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
@@ -170,7 +169,7 @@ func TestNestedDirBaseReaddir(t *testing.T) {
 
 	ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
 
-	base.MkdirAll("/home/test/foo/bar", 0777)
+	base.MkdirAll("/home/test/foo/bar", 0o777)
 	fh, _ := base.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
@@ -182,7 +181,7 @@ func TestNestedDirBaseReaddir(t *testing.T) {
 	fh.WriteString("This is a test")
 	fh.Close()
 
-	overlay.MkdirAll("/", 0777)
+	overlay.MkdirAll("/", 0o777)
 
 	// Opening something only in the base
 	fh, _ = ufs.Open("/home/test/foo")
@@ -205,8 +204,8 @@ func TestNestedDirOverlayReaddir(t *testing.T) {
 
 	ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
 
-	base.MkdirAll("/", 0777)
-	overlay.MkdirAll("/home/test/foo/bar", 0777)
+	base.MkdirAll("/", 0o777)
+	overlay.MkdirAll("/home/test/foo/bar", 0o777)
 	fh, _ := overlay.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
@@ -239,8 +238,8 @@ func TestNestedDirOverlayOsFsReaddir(t *testing.T) {
 
 	ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
 
-	base.MkdirAll("/", 0777)
-	overlay.MkdirAll("/home/test/foo/bar", 0777)
+	base.MkdirAll("/", 0o777)
+	overlay.MkdirAll("/home/test/foo/bar", 0o777)
 	fh, _ := overlay.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
@@ -274,12 +273,12 @@ func TestCopyOnWriteFsWithOsFs(t *testing.T) {
 
 	ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
 
-	base.MkdirAll("/home/test", 0777)
+	base.MkdirAll("/home/test", 0o777)
 	fh, _ := base.Create("/home/test/file.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
 
-	overlay.MkdirAll("home/test", 0777)
+	overlay.MkdirAll("home/test", 0o777)
 	fh, _ = overlay.Create("/home/test/file2.txt")
 	fh.WriteString("This is a test")
 	fh.Close()
@@ -315,7 +314,7 @@ func TestUnionCacheWrite(t *testing.T) {
 
 	ufs := NewCacheOnReadFs(base, layer, 0)
 
-	base.Mkdir("/data", 0777)
+	base.Mkdir("/data", 0o777)
 
 	fh, err := ufs.Create("/data/file.txt")
 	if err != nil {
@@ -344,7 +343,7 @@ func TestUnionCacheExpire(t *testing.T) {
 	layer := &MemMapFs{}
 	ufs := &CacheOnReadFs{base: base, layer: layer, cacheTime: 1 * time.Second}
 
-	base.Mkdir("/data", 0777)
+	base.Mkdir("/data", 0o777)
 
 	fh, err := ufs.Create("/data/file.txt")
 	if err != nil {
@@ -449,7 +448,7 @@ func TestUnionFileReaddirDuplicateEmpty(t *testing.T) {
 
 	// Overlay shares same empty directory as base
 	overlay := NewMemMapFs()
-	err = overlay.Mkdir(dir, 0700)
+	err = overlay.Mkdir(dir, 0o700)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -479,7 +478,7 @@ func TestUnionFileReaddirAskForTooMany(t *testing.T) {
 
 	const testFiles = 5
 	for i := 0; i < testFiles; i++ {
-		WriteFile(base, fmt.Sprintf("file%d.txt", i), []byte("afero"), 0777)
+		WriteFile(base, fmt.Sprintf("file%d.txt", i), []byte("afero"), 0o777)
 	}
 
 	ufs := &CopyOnWriteFs{base: base, layer: overlay}
diff --git a/copyOnWriteFs_test.go b/copyOnWriteFs_test.go
index 94ba725..c94ff1e 100644
--- a/copyOnWriteFs_test.go
+++ b/copyOnWriteFs_test.go
@@ -16,9 +16,9 @@ func TestCopyOnWrite(t *testing.T) {
 
 	compositeFs := NewCopyOnWriteFs(NewReadOnlyFs(NewOsFs()), osFs)
 
-	var dir = filepath.Join(writeDir, "some/path")
+	dir := filepath.Join(writeDir, "some/path")
 
-	err = compositeFs.MkdirAll(dir, 0744)
+	err = compositeFs.MkdirAll(dir, 0o744)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -31,13 +31,13 @@ func TestCopyOnWrite(t *testing.T) {
 	// We want the composite file system to behave like the OS file system
 	// on Mkdir and MkdirAll
 	for _, fs := range []Fs{osFs, compositeFs} {
-		err = fs.Mkdir(dir, 0744)
+		err = fs.Mkdir(dir, 0o744)
 		if err == nil || !os.IsExist(err) {
 			t.Errorf("Mkdir: Got %q for %T", err, fs)
 		}
 
 		// MkdirAll does not return an error when the directory already exists
-		err = fs.MkdirAll(dir, 0744)
+		err = fs.MkdirAll(dir, 0o744)
 		if err != nil {
 			t.Errorf("MkdirAll:  Got %q for %T", err, fs)
 		}
@@ -49,7 +49,7 @@ func TestCopyOnWriteFileInMemMapBase(t *testing.T) {
 	base := &MemMapFs{}
 	layer := &MemMapFs{}
 
-	if err := WriteFile(base, "base.txt", []byte("base"), 0755); err != nil {
+	if err := WriteFile(base, "base.txt", []byte("base"), 0o755); err != nil {
 		t.Fatalf("Failed to write file: %s", err)
 	}
 
diff --git a/gcsfs/gcs_test.go b/gcsfs/gcs_test.go
index feedfb0..67794be 100644
--- a/gcsfs/gcs_test.go
+++ b/gcsfs/gcs_test.go
@@ -122,7 +122,7 @@ func TestMain(m *testing.M) {
 	gcsAfs = &afero.Afero{Fs: &GcsFs{NewGcsFs(ctx, mockClient)}}
 
 	// Uncomment to use the real, not mocked, client
-	//gcsAfs = &Afero{Fs: &GcsFs{gcsfs.NewGcsFs(ctx, client)}}
+	// gcsAfs = &Afero{Fs: &GcsFs{gcsfs.NewGcsFs(ctx, client)}}
 
 	exitCode = m.Run()
 }
@@ -341,7 +341,7 @@ func TestGcsSeek(t *testing.T) {
 				t.Fatalf("opening %v: %v", name, err)
 			}
 
-			var tests = []struct {
+			tests := []struct {
 				offIn  int64
 				whence int
 				offOut int64
@@ -477,7 +477,7 @@ func TestGcsOpenFile(t *testing.T) {
 		}
 
 		for _, name := range names {
-			file, err := gcsAfs.OpenFile(name, os.O_RDONLY, 0400)
+			file, err := gcsAfs.OpenFile(name, os.O_RDONLY, 0o400)
 			if !f.exists {
 				if (f.name != "" && !errors.Is(err, syscall.ENOENT)) ||
 					(f.name == "" && !errors.Is(err, ErrNoBucketInName)) {
@@ -496,7 +496,7 @@ func TestGcsOpenFile(t *testing.T) {
 				t.Fatalf("failed to close a file \"%s\": %s", name, err)
 			}
 
-			_, err = gcsAfs.OpenFile(name, os.O_CREATE, 0600)
+			_, err = gcsAfs.OpenFile(name, os.O_CREATE, 0o600)
 			if !errors.Is(err, syscall.EPERM) {
 				t.Errorf("%v: open for write: got %v, expected %v", name, err, syscall.EPERM)
 			}
@@ -714,7 +714,7 @@ func TestGcsMkdir(t *testing.T) {
 	t.Run("empty", func(t *testing.T) {
 		emptyDirName := bucketName
 
-		err := gcsAfs.Mkdir(emptyDirName, 0755)
+		err := gcsAfs.Mkdir(emptyDirName, 0o755)
 		if err == nil {
 			t.Fatal("did not fail upon creation of an empty folder")
 		}
@@ -723,7 +723,7 @@ func TestGcsMkdir(t *testing.T) {
 		dirName := filepath.Join(bucketName, "a-test-dir")
 		var err error
 
-		err = gcsAfs.Mkdir(dirName, 0755)
+		err = gcsAfs.Mkdir(dirName, 0o755)
 		if err != nil {
 			t.Fatal("failed to create a folder with error", err)
 		}
@@ -739,7 +739,7 @@ func TestGcsMkdir(t *testing.T) {
 			t.Errorf("%s: mode is not directory", dirName)
 		}
 
-		if info.Mode() != os.ModeDir|0755 {
+		if info.Mode() != os.ModeDir|0o755 {
 			t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", dirName, info.Mode())
 		}
 
@@ -754,7 +754,7 @@ func TestGcsMkdirAll(t *testing.T) {
 	t.Run("empty", func(t *testing.T) {
 		emptyDirName := bucketName
 
-		err := gcsAfs.MkdirAll(emptyDirName, 0755)
+		err := gcsAfs.MkdirAll(emptyDirName, 0o755)
 		if err == nil {
 			t.Fatal("did not fail upon creation of an empty folder")
 		}
@@ -762,7 +762,7 @@ func TestGcsMkdirAll(t *testing.T) {
 	t.Run("success", func(t *testing.T) {
 		dirName := filepath.Join(bucketName, "a/b/c")
 
-		err := gcsAfs.MkdirAll(dirName, 0755)
+		err := gcsAfs.MkdirAll(dirName, 0o755)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -774,7 +774,7 @@ func TestGcsMkdirAll(t *testing.T) {
 		if !info.Mode().IsDir() {
 			t.Errorf("%s: mode is not directory", filepath.Join(bucketName, "a"))
 		}
-		if info.Mode() != os.ModeDir|0755 {
+		if info.Mode() != os.ModeDir|0o755 {
 			t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", filepath.Join(bucketName, "a"), info.Mode())
 		}
 		info, err = gcsAfs.Stat(filepath.Join(bucketName, "a/b"))
@@ -784,7 +784,7 @@ func TestGcsMkdirAll(t *testing.T) {
 		if !info.Mode().IsDir() {
 			t.Errorf("%s: mode is not directory", filepath.Join(bucketName, "a/b"))
 		}
-		if info.Mode() != os.ModeDir|0755 {
+		if info.Mode() != os.ModeDir|0o755 {
 			t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", filepath.Join(bucketName, "a/b"), info.Mode())
 		}
 		info, err = gcsAfs.Stat(dirName)
@@ -794,7 +794,7 @@ func TestGcsMkdirAll(t *testing.T) {
 		if !info.Mode().IsDir() {
 			t.Errorf("%s: mode is not directory", dirName)
 		}
-		if info.Mode() != os.ModeDir|0755 {
+		if info.Mode() != os.ModeDir|0o755 {
 			t.Errorf("%s: wrong permissions, expected drwxr-xr-x, got %s", dirName, info.Mode())
 		}
 
@@ -816,7 +816,7 @@ func TestGcsRemoveAll(t *testing.T) {
 		aDir := filepath.Join(bucketName, "a")
 		bDir := filepath.Join(aDir, "b")
 
-		err := gcsAfs.MkdirAll(bDir, 0755)
+		err := gcsAfs.MkdirAll(bDir, 0o755)
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/iofs_test.go b/iofs_test.go
index 579345e..829e919 100644
--- a/iofs_test.go
+++ b/iofs_test.go
@@ -66,7 +66,6 @@ func TestIOFS(t *testing.T) {
 			t.Error(err)
 		}
 	})
-
 }
 
 func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
@@ -101,6 +100,7 @@ func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
+	defer dir2.Close()
 
 	assertDirEntries := func(entries []fs.DirEntry, ordered bool) {
 		if len(entries) != numFiles {
@@ -145,7 +145,6 @@ func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
 		}
 
 		return nil
-
 	})
 
 	if err != nil {
@@ -155,7 +154,6 @@ func TestIOFSNativeDirEntryWhenPossible(t *testing.T) {
 	if fileCount != numFiles {
 		t.Fatalf("expected %d, got %d", numFiles, fileCount)
 	}
-
 }
 
 func TestFromIOFS(t *testing.T) {
@@ -360,7 +358,6 @@ func TestFromIOFS_File(t *testing.T) {
 		// MapFS files implements io.ReaderAt
 		b := make([]byte, 2)
 		_, err := file.ReadAt(b, 2)
-
 		if err != nil {
 			t.Errorf("ReadAt failed: %v", err)
 			return
@@ -420,7 +417,7 @@ func TestFromIOFS_File(t *testing.T) {
 				return
 			}
 
-			var expectedItems = []struct {
+			expectedItems := []struct {
 				Name  string
 				IsDir bool
 				Size  int64
@@ -472,7 +469,7 @@ func TestFromIOFS_File(t *testing.T) {
 				return
 			}
 
-			var expectedItems = []string{"dir1", "dir2", "test.txt"}
+			expectedItems := []string{"dir1", "dir2", "test.txt"}
 
 			if len(expectedItems) != len(items) {
 				t.Errorf("Items count mismatch, expected %d, got %d", len(expectedItems), len(items))
@@ -530,7 +527,7 @@ func BenchmarkWalkDir(b *testing.B) {
 		dirname := ""
 		for i := 0; i < level; i++ {
 			dirname = filepath.Join(dirname, fmt.Sprintf("dir%d", i))
-			err := osfs.MkdirAll(dirname, 0755)
+			err := osfs.MkdirAll(dirname, 0o755)
 			if err != nil && !os.IsExist(err) {
 				b.Fatal(err)
 			}
@@ -547,12 +544,9 @@ func BenchmarkWalkDir(b *testing.B) {
 				return err
 			}
 			return nil
-
 		})
-
 		if err != nil {
 			b.Fatal(err)
 		}
 	}
-
 }
diff --git a/ioutil_test.go b/ioutil_test.go
index 540bf56..004c66b 100644
--- a/ioutil_test.go
+++ b/ioutil_test.go
@@ -63,7 +63,7 @@ func TestWriteFile(t *testing.T) {
 		"build bigger and better idiot-proof programs, and the Universe trying " +
 		"to produce bigger and better idiots. So far, the Universe is winning."
 
-	if err := fsutil.WriteFile(filename, []byte(data), 0644); err != nil {
+	if err := fsutil.WriteFile(filename, []byte(data), 0o644); err != nil {
 		t.Fatalf("WriteFile %s: %v", filename, err)
 	}
 
@@ -83,7 +83,7 @@ func TestWriteFile(t *testing.T) {
 
 func TestReadDir(t *testing.T) {
 	testFS = &MemMapFs{}
-	testFS.Mkdir("/i-am-a-dir", 0777)
+	testFS.Mkdir("/i-am-a-dir", 0o777)
 	testFS.Create("/this_exists.go")
 	dirname := "rumpelstilzchen"
 	_, err := ReadDir(testFS, dirname)
diff --git a/lstater_test.go b/lstater_test.go
index 477924f..cb5585f 100644
--- a/lstater_test.go
+++ b/lstater_test.go
@@ -50,8 +50,8 @@ func TestLstatIfPossible(t *testing.T) {
 
 	pathFileMem := filepath.Join(memWorkDir, "aferom.txt")
 
-	WriteFile(osFs, filepath.Join(workDir, "afero.txt"), []byte("Hi, Afero!"), 0777)
-	WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0777)
+	WriteFile(osFs, filepath.Join(workDir, "afero.txt"), []byte("Hi, Afero!"), 0o777)
+	WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0o777)
 
 	os.Chdir(workDir)
 	if err := os.Symlink("afero.txt", "symafero.txt"); err != nil {
diff --git a/match_test.go b/match_test.go
index fa2c17b..3f24b58 100644
--- a/match_test.go
+++ b/match_test.go
@@ -44,7 +44,7 @@ func setupGlobDirReusePath(t *testing.T, fs Fs, path string) string {
 
 func setupGlobFiles(t *testing.T, fs Fs, path string) string {
 	testSubDir := filepath.Join(path, "globs", "bobs")
-	err := fs.MkdirAll(testSubDir, 0700)
+	err := fs.MkdirAll(testSubDir, 0o700)
 	if err != nil && !os.IsExist(err) {
 		t.Fatal(err)
 	}
@@ -84,7 +84,7 @@ func TestGlob(t *testing.T) {
 		}
 	}
 
-	var globTests = []struct {
+	globTests := []struct {
 		pattern, result string
 	}{
 		{testDir + "/globs/bobs/matcher", testDir + "/globs/bobs/matcher"},
@@ -136,7 +136,7 @@ func TestGlobSymlink(t *testing.T) {
 		t.Skipf("skipping on %s", runtime.GOOS)
 	}
 
-	var globSymlinkTests = []struct {
+	globSymlinkTests := []struct {
 		path, dest string
 		brokenLink bool
 	}{
diff --git a/mem/file_test.go b/mem/file_test.go
index 998a5d0..2b123f3 100644
--- a/mem/file_test.go
+++ b/mem/file_test.go
@@ -66,8 +66,8 @@ func TestFileDataModTimeRace(t *testing.T) {
 
 func TestFileDataModeRace(t *testing.T) {
 	t.Parallel()
-	const someMode = 0777
-	const someOtherMode = 0660
+	const someMode = 0o777
+	const someOtherMode = 0o660
 
 	d := FileData{
 		mode: someMode,
@@ -167,7 +167,7 @@ func TestFileDataIsDirRace(t *testing.T) {
 		s.Unlock()
 	}()
 
-	//just logging the value to trigger a read:
+	// just logging the value to trigger a read:
 	t.Logf("Value is %v", s.IsDir())
 }
 
@@ -196,10 +196,10 @@ func TestFileDataSizeRace(t *testing.T) {
 		s.Unlock()
 	}()
 
-	//just logging the value to trigger a read:
+	// just logging the value to trigger a read:
 	t.Logf("Value is %v", s.Size())
 
-	//Testing the Dir size case
+	// Testing the Dir size case
 	d.dir = true
 	if s.Size() != int64(42) {
 		t.Errorf("Failed to read correct value for dir, was %v", s.Size())
diff --git a/memmap_test.go b/memmap_test.go
index 94f70b2..52a492e 100644
--- a/memmap_test.go
+++ b/memmap_test.go
@@ -3,9 +3,12 @@ package afero
 import (
 	"fmt"
 	"io"
+	"io/fs"
 	"os"
 	"path/filepath"
 	"runtime"
+	"strings"
+	"sync"
 	"testing"
 	"time"
 )
@@ -37,7 +40,7 @@ func TestPathErrors(t *testing.T) {
 	path := filepath.Join(".", "some", "path")
 	path2 := filepath.Join(".", "different", "path")
 	fs := NewMemMapFs()
-	perm := os.FileMode(0755)
+	perm := os.FileMode(0o755)
 	uid := 1000
 	gid := 1000
 
@@ -112,7 +115,7 @@ func checkPathError(t *testing.T, err error, op string) {
 // Ensure os.O_EXCL is correctly handled.
 func TestOpenFileExcl(t *testing.T) {
 	const fileName = "/myFileTest"
-	const fileMode = os.FileMode(0765)
+	const fileMode = os.FileMode(0o765)
 
 	fs := NewMemMapFs()
 
@@ -138,7 +141,7 @@ func TestPermSet(t *testing.T) {
 	const dirPath = "/myDirTest"
 	const dirPathAll = "/my/path/to/dir"
 
-	const fileMode = os.FileMode(0765)
+	const fileMode = os.FileMode(0o765)
 	// directories will also have the directory bit set
 	const dirMode = fileMode | os.ModeDir
 
@@ -201,7 +204,7 @@ func TestMultipleOpenFiles(t *testing.T) {
 	defer removeAllTestFiles(t)
 	const fileName = "afero-demo2.txt"
 
-	var data = make([][]byte, len(Fss))
+	data := make([][]byte, len(Fss))
 
 	for i, fs := range Fss {
 		dir := testDir(fs)
@@ -219,11 +222,11 @@ func TestMultipleOpenFiles(t *testing.T) {
 			t.Error(err)
 		}
 
-		fh2, err := fs.OpenFile(path, os.O_RDWR, 0777)
+		fh2, err := fs.OpenFile(path, os.O_RDWR, 0o777)
 		if err != nil {
 			t.Error("fs.OpenFile failed: " + err.Error())
 		}
-		_, err = fh2.Seek(0, os.SEEK_END)
+		_, err = fh2.Seek(0, io.SeekEnd)
 		if err != nil {
 			t.Error(err)
 		}
@@ -292,7 +295,7 @@ func TestReadOnly(t *testing.T) {
 		}
 		f.Close()
 
-		f, err = fs.OpenFile(path, os.O_RDONLY, 0644)
+		f, err = fs.OpenFile(path, os.O_RDONLY, 0o644)
 		if err != nil {
 			t.Error("fs.Open failed: " + err.Error())
 		}
@@ -383,7 +386,7 @@ func TestMemFsDataRace(t *testing.T) {
 	const dir = "test_dir"
 	fs := NewMemMapFs()
 
-	if err := fs.MkdirAll(dir, 0777); err != nil {
+	if err := fs.MkdirAll(dir, 0o777); err != nil {
 		t.Fatal(err)
 	}
 
@@ -394,7 +397,7 @@ func TestMemFsDataRace(t *testing.T) {
 		defer close(done)
 		for i := 0; i < n; i++ {
 			fname := filepath.Join(dir, fmt.Sprintf("%d.txt", i))
-			if err := WriteFile(fs, fname, []byte(""), 0777); err != nil {
+			if err := WriteFile(fs, fname, []byte(""), 0o777); err != nil {
 				panic(err)
 			}
 			if err := fs.Remove(fname); err != nil {
@@ -439,7 +442,7 @@ func TestMemFsMkdirAllMode(t *testing.T) {
 	t.Parallel()
 
 	fs := NewMemMapFs()
-	err := fs.MkdirAll("/a/b/c", 0755)
+	err := fs.MkdirAll("/a/b/c", 0o755)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -453,7 +456,7 @@ func TestMemFsMkdirAllMode(t *testing.T) {
 	if !info.ModTime().After(time.Now().Add(-1 * time.Hour)) {
 		t.Errorf("/a: mod time not set, got %s", info.ModTime())
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0755) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o755) {
 		t.Errorf("/a: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
 	}
 	info, err = fs.Stat("/a/b")
@@ -463,7 +466,7 @@ func TestMemFsMkdirAllMode(t *testing.T) {
 	if !info.Mode().IsDir() {
 		t.Error("/a/b: mode is not directory")
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0755) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o755) {
 		t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
 	}
 	if !info.ModTime().After(time.Now().Add(-1 * time.Hour)) {
@@ -476,7 +479,7 @@ func TestMemFsMkdirAllMode(t *testing.T) {
 	if !info.Mode().IsDir() {
 		t.Error("/a/b/c: mode is not directory")
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0755) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o755) {
 		t.Errorf("/a/b/c: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
 	}
 	if !info.ModTime().After(time.Now().Add(-1 * time.Hour)) {
@@ -489,7 +492,7 @@ func TestMemFsMkdirAllNoClobber(t *testing.T) {
 	t.Parallel()
 
 	fs := NewMemMapFs()
-	err := fs.MkdirAll("/a/b/c", 0755)
+	err := fs.MkdirAll("/a/b/c", 0o755)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -497,10 +500,10 @@ func TestMemFsMkdirAllNoClobber(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0755) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o755) {
 		t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
 	}
-	err = fs.MkdirAll("/a/b/c/d/e/f", 0710)
+	err = fs.MkdirAll("/a/b/c/d/e/f", 0o710)
 	// '/a/b' is unchanged
 	if err != nil {
 		t.Fatal(err)
@@ -509,7 +512,7 @@ func TestMemFsMkdirAllNoClobber(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0755) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o755) {
 		t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode())
 	}
 	// new directories created with proper permissions
@@ -517,32 +520,32 @@ func TestMemFsMkdirAllNoClobber(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0710) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o710) {
 		t.Errorf("/a/b/c/d: wrong permissions, expected drwx--x---, got %s", info.Mode())
 	}
 	info, err = fs.Stat("/a/b/c/d/e")
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0710) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o710) {
 		t.Errorf("/a/b/c/d/e: wrong permissions, expected drwx--x---, got %s", info.Mode())
 	}
 	info, err = fs.Stat("/a/b/c/d/e/f")
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0710) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o710) {
 		t.Errorf("/a/b/c/d/e/f: wrong permissions, expected drwx--x---, got %s", info.Mode())
 	}
 }
 
 func TestMemFsDirMode(t *testing.T) {
 	fs := NewMemMapFs()
-	err := fs.Mkdir("/testDir1", 0644)
+	err := fs.Mkdir("/testDir1", 0o644)
 	if err != nil {
 		t.Error(err)
 	}
-	err = fs.MkdirAll("/sub/testDir2", 0644)
+	err = fs.MkdirAll("/sub/testDir2", 0o644)
 	if err != nil {
 		t.Error(err)
 	}
@@ -573,7 +576,7 @@ func TestMemFsUnexpectedEOF(t *testing.T) {
 
 	fs := NewMemMapFs()
 
-	if err := WriteFile(fs, "file.txt", []byte("abc"), 0777); err != nil {
+	if err := WriteFile(fs, "file.txt", []byte("abc"), 0o777); err != nil {
 		t.Fatal(err)
 	}
 
@@ -602,7 +605,7 @@ func TestMemFsChmod(t *testing.T) {
 
 	fs := NewMemMapFs()
 	const file = "hello"
-	if err := fs.Mkdir(file, 0700); err != nil {
+	if err := fs.Mkdir(file, 0o700); err != nil {
 		t.Fatal(err)
 	}
 
@@ -633,7 +636,7 @@ func TestMemFsMkdirModeIllegal(t *testing.T) {
 	t.Parallel()
 
 	fs := NewMemMapFs()
-	err := fs.Mkdir("/a", os.ModeSocket|0755)
+	err := fs.Mkdir("/a", os.ModeSocket|0o755)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -641,7 +644,7 @@ func TestMemFsMkdirModeIllegal(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(os.ModeDir|0755) {
+	if info.Mode() != os.FileMode(os.ModeDir|0o755) {
 		t.Fatalf("should not be able to use Mkdir to set illegal mode: %s", info.Mode().String())
 	}
 }
@@ -651,7 +654,7 @@ func TestMemFsOpenFileModeIllegal(t *testing.T) {
 	t.Parallel()
 
 	fs := NewMemMapFs()
-	file, err := fs.OpenFile("/a", os.O_CREATE, os.ModeSymlink|0644)
+	file, err := fs.OpenFile("/a", os.O_CREATE, os.ModeSymlink|0o644)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -660,7 +663,7 @@ func TestMemFsOpenFileModeIllegal(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if info.Mode() != os.FileMode(0644) {
+	if info.Mode() != os.FileMode(0o644) {
 		t.Fatalf("should not be able to use OpenFile to set illegal mode: %s", info.Mode().String())
 	}
 }
@@ -692,3 +695,141 @@ func TestMemFsLstatIfPossible(t *testing.T) {
 		t.Fatalf("Function indicated lstat was called. This should never be true.")
 	}
 }
+
+func TestMemMapFsConfurrentMkdir(t *testing.T) {
+	const dir = "test_dir"
+	const n = 1000
+	mfs := NewMemMapFs().(*MemMapFs)
+
+	allFilePaths := make([]string, 0, n)
+
+	// run concurrency test
+	var wg sync.WaitGroup
+	for i := 0; i < n; i++ {
+		fp := filepath.Join(
+			dir,
+			fmt.Sprintf("%02d", n%10),
+			fmt.Sprintf("%d.txt", i),
+		)
+		allFilePaths = append(allFilePaths, fp)
+
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+
+			if err := mfs.MkdirAll(filepath.Dir(fp), 0o755); err != nil {
+				t.Error(err)
+			}
+
+			wt, err := mfs.Create(fp)
+			if err != nil {
+				t.Error(err)
+			}
+			defer func() {
+				if err := wt.Close(); err != nil {
+					t.Error(err)
+				}
+			}()
+
+			// write 30 bytes
+			for j := 0; j < 10; j++ {
+				_, err := wt.Write([]byte("000"))
+				if err != nil {
+					t.Error(err)
+				}
+			}
+		}()
+	}
+	wg.Wait()
+
+	// Test1: find all files by full path access
+	for _, fp := range allFilePaths {
+		info, err := mfs.Stat(fp)
+		if err != nil {
+			t.Error(err)
+		}
+
+		if info.Size() != 30 {
+			t.Errorf("file size should be 30, but got %d", info.Size())
+		}
+
+	}
+
+	// Test2: find all files by walk
+	foundFiles := make([]string, 0, n)
+	wErr := Walk(mfs, dir, func(path string, info fs.FileInfo, err error) error {
+		if err != nil {
+			t.Error(err)
+		}
+		if info.IsDir() {
+			return nil // skip dir
+		}
+		if strings.HasSuffix(info.Name(), ".txt") {
+			foundFiles = append(foundFiles, path)
+		}
+		return nil
+	})
+	if wErr != nil {
+		t.Error(wErr)
+	}
+	if len(foundFiles) != n {
+		t.Errorf("found %d files, but expect %d", len(foundFiles), n)
+	}
+}
+
+func TestMemFsRenameDir(t *testing.T) {
+	const srcPath = "/src"
+	const dstPath = "/dst"
+	const subDir = "dir"
+	const subFile = "file.txt"
+
+	fs := NewMemMapFs()
+
+	err := fs.MkdirAll(srcPath+FilePathSeparator+subDir, 0o777)
+	if err != nil {
+		t.Fatalf("MkDirAll failed: %s", err)
+	}
+
+	f, err := fs.Create(srcPath + FilePathSeparator + subFile)
+	if err != nil {
+		t.Fatalf("Create failed: %s", err)
+	}
+	if err = f.Close(); err != nil {
+		t.Fatalf("Close failed: %s", err)
+	}
+
+	err = fs.Rename(srcPath, dstPath)
+	if err != nil {
+		t.Fatalf("Rename failed: %s", err)
+	}
+
+	_, err = fs.Stat(srcPath + FilePathSeparator + subDir)
+	if err == nil {
+		t.Fatalf("SubDir still exists in the source dir")
+	}
+
+	_, err = fs.Stat(srcPath + FilePathSeparator + subFile)
+	if err == nil {
+		t.Fatalf("SubFile still exists in the source dir")
+	}
+
+	_, err = fs.Stat(dstPath + FilePathSeparator + subDir)
+	if err != nil {
+		t.Fatalf("SubDir stat in the destination dir: %s", err)
+	}
+
+	_, err = fs.Stat(dstPath + FilePathSeparator + subFile)
+	if err != nil {
+		t.Fatalf("SubFile stat in the destination dir: %s", err)
+	}
+
+	err = fs.Mkdir(srcPath, 0o777)
+	if err != nil {
+		t.Fatalf("Cannot recreate the source dir: %s", err)
+	}
+
+	err = fs.Mkdir(srcPath+FilePathSeparator+subDir, 0o777)
+	if err != nil {
+		t.Errorf("Cannot recreate the subdir in the source dir: %s", err)
+	}
+}
diff --git a/ro_regexp_test.go b/ro_regexp_test.go
index ef3a14f..3dc8930 100644
--- a/ro_regexp_test.go
+++ b/ro_regexp_test.go
@@ -54,7 +54,6 @@ func TestFilterRegexp(t *testing.T) {
 	fs := NewRegexpFs(&MemMapFs{}, regexp.MustCompile(`\.txt$`))
 	_, err := fs.Create("/file.html")
 	if err == nil {
-
 		t.Errorf("Did not fail to create file")
 	}
 	// t.Logf("ERR=%s", err)
@@ -75,7 +74,7 @@ func TestFilterRegexReadDir(t *testing.T) {
 	fs1 := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: mfs}
 	fs := &RegexpFs{re: regexp.MustCompile(`^a`), source: fs1}
 
-	mfs.MkdirAll("/dir/sub", 0777)
+	mfs.MkdirAll("/dir/sub", 0o777)
 	for _, name := range []string{"afile.txt", "afile.html", "bfile.txt"} {
 		for _, dir := range []string{"/dir/", "/dir/sub/"} {
 			fh, _ := mfs.Create(dir + name)
diff --git a/sftpfs/sftp_test.go b/sftpfs/sftp_test.go
index a865139..bba2f36 100644
--- a/sftpfs/sftp_test.go
+++ b/sftpfs/sftp_test.go
@@ -234,11 +234,11 @@ func MakeSSHKeyPair(bits int, pubKeyPath, privateKeyPath string) error {
 		return err
 	}
 
-	return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655)
+	return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0o655)
 }
 
 func TestSftpCreate(t *testing.T) {
-	os.Mkdir("./test", 0777)
+	os.Mkdir("./test", 0o777)
 	MakeSSHKeyPair(1024, "./test/id_rsa.pub", "./test/id_rsa")
 
 	go RunSftpServer("./test/")
@@ -250,12 +250,12 @@ func TestSftpCreate(t *testing.T) {
 	}
 	defer ctx.Disconnect()
 
-	var fs = New(ctx.sftpc)
+	fs := New(ctx.sftpc)
 
-	fs.MkdirAll("test/dir1/dir2/dir3", os.FileMode(0777))
-	fs.Mkdir("test/foo", os.FileMode(0000))
-	fs.Chmod("test/foo", os.FileMode(0700))
-	fs.Mkdir("test/bar", os.FileMode(0777))
+	fs.MkdirAll("test/dir1/dir2/dir3", os.FileMode(0o777))
+	fs.Mkdir("test/foo", os.FileMode(0o000))
+	fs.Chmod("test/foo", os.FileMode(0o700))
+	fs.Mkdir("test/bar", os.FileMode(0o777))
 
 	file, err := fs.Create("file1")
 	if err != nil {
diff --git a/symlink_test.go b/symlink_test.go
index 5a9e5db..77dd742 100644
--- a/symlink_test.go
+++ b/symlink_test.go
@@ -38,14 +38,14 @@ func TestSymlinkIfPossible(t *testing.T) {
 	pathFileMem := filepath.Join(memWorkDir, "aferom.txt")
 	osPath := filepath.Join(workDir, "afero.txt")
 
-	WriteFile(osFs, osPath, []byte("Hi, Afero!"), 0777)
-	WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0777)
+	WriteFile(osFs, osPath, []byte("Hi, Afero!"), 0o777)
+	WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0o777)
 
 	testLink := func(l Linker, source, destination string, output *string) {
 		if fs, ok := l.(Fs); ok {
 			dir := filepath.Dir(destination)
 			if dir != "" {
-				fs.MkdirAll(dir, 0777)
+				fs.MkdirAll(dir, 0o777)
 			}
 		}
 
@@ -117,14 +117,14 @@ func TestReadlinkIfPossible(t *testing.T) {
 	pathFileMem := filepath.Join(memWorkDir, "aferom.txt")
 	osPath := filepath.Join(workDir, "afero.txt")
 
-	WriteFile(osFs, osPath, []byte("Hi, Afero!"), 0777)
-	WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0777)
+	WriteFile(osFs, osPath, []byte("Hi, Afero!"), 0o777)
+	WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0o777)
 
 	createLink := func(l Linker, source, destination string) error {
 		if fs, ok := l.(Fs); ok {
 			dir := filepath.Dir(destination)
 			if dir != "" {
-				fs.MkdirAll(dir, 0777)
+				fs.MkdirAll(dir, 0o777)
 			}
 		}
 
diff --git a/tarfs/tarfs_test.go b/tarfs/tarfs_test.go
index aa2d6a4..228ed9b 100644
--- a/tarfs/tarfs_test.go
+++ b/tarfs/tarfs_test.go
@@ -161,7 +161,7 @@ func TestSeek(t *testing.T) {
 			t.Fatalf("opening %v: %v", f.name, err)
 		}
 
-		var tests = []struct {
+		tests := []struct {
 			offin  int64
 			whence int
 			offout int64
@@ -252,7 +252,7 @@ func TestClose(t *testing.T) {
 
 func TestOpenFile(t *testing.T) {
 	for _, f := range files {
-		file, err := afs.OpenFile(f.name, os.O_RDONLY, 0400)
+		file, err := afs.OpenFile(f.name, os.O_RDONLY, 0o400)
 		if !f.exists {
 			if !errors.Is(err, syscall.ENOENT) {
 				t.Errorf("%v: got %v, expected%v", f.name, err, syscall.ENOENT)
@@ -266,7 +266,7 @@ func TestOpenFile(t *testing.T) {
 		}
 		file.Close()
 
-		_, err = afs.OpenFile(f.name, os.O_CREATE, 0600)
+		_, err = afs.OpenFile(f.name, os.O_CREATE, 0o600)
 		if !errors.Is(err, syscall.EPERM) {
 			t.Errorf("%v: open for write: got %v, expected %v", f.name, err, syscall.EPERM)
 		}
diff --git a/util_test.go b/util_test.go
index 985b7a1..13ec23b 100644
--- a/util_test.go
+++ b/util_test.go
@@ -36,8 +36,8 @@ func TestDirExists(t *testing.T) {
 	}
 
 	// First create a couple directories so there is something in the filesystem
-	//testFS := new(MemMapFs)
-	testFS.MkdirAll("/foo/bar", 0777)
+	// testFS := new(MemMapFs)
+	testFS.MkdirAll("/foo/bar", 0o777)
 
 	data := []test{
 		{".", true},
@@ -155,7 +155,8 @@ func TestReaderContains(t *testing.T) {
 		{"", nil, false},
 		{"", [][]byte{[]byte("a")}, false},
 		{"a", [][]byte{[]byte("")}, false},
-		{"", [][]byte{[]byte("")}, false}} {
+		{"", [][]byte{[]byte("")}, false},
+	} {
 		result := readerContainsAny(strings.NewReader(this.v1), this.v2...)
 		if result != this.expect {
 			t.Errorf("[%d] readerContains: got %t but expected %t", i, result, this.expect)
@@ -188,7 +189,7 @@ func createNonZeroSizedFileInTempDir() (File, error) {
 		return nil, err
 	}
 	byteString := []byte("byteString")
-	err = WriteFile(testFS, f.Name(), byteString, 0644)
+	err = WriteFile(testFS, f.Name(), byteString, 0o644)
 	if err != nil {
 		// delete the file
 		deleteFileInTempDir(f)
@@ -229,7 +230,6 @@ func createTempDirWithZeroLengthFiles() (string, error) {
 	}
 	// the dir now has one, zero length file in it
 	return d, nil
-
 }
 
 func createTempDirWithNonZeroLengthFiles() (string, error) {
@@ -246,7 +246,7 @@ func createTempDirWithNonZeroLengthFiles() (string, error) {
 		return "", fileErr
 	}
 	byteString := []byte("byteString")
-	fileErr = WriteFile(testFS, f.Name(), byteString, 0644)
+	fileErr = WriteFile(testFS, f.Name(), byteString, 0o644)
 	if fileErr != nil {
 		// delete the file
 		deleteFileInTempDir(f)
@@ -257,7 +257,6 @@ func createTempDirWithNonZeroLengthFiles() (string, error) {
 
 	// the dir now has one, zero length file in it
 	return d, nil
-
 }
 
 func TestExists(t *testing.T) {
@@ -292,7 +291,6 @@ func TestExists(t *testing.T) {
 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expectedErr, err)
 		}
 	}
-
 }
 
 func TestSafeWriteToDisk(t *testing.T) {
diff --git a/zipfs/zipfs_test.go b/zipfs/zipfs_test.go
index bf781cc..6fb9743 100644
--- a/zipfs/zipfs_test.go
+++ b/zipfs/zipfs_test.go
@@ -1,12 +1,12 @@
 package zipfs
 
 import (
-	"github.com/spf13/afero"
-
 	"archive/zip"
 	"path/filepath"
 	"reflect"
 	"testing"
+
+	"github.com/spf13/afero"
 )
 
 func TestZipFS(t *testing.T) {