@@ -5,16 +5,64 @@ package os
55import (
66 "io"
77 "io/fs"
8+ "runtime"
89)
910
1011type (
1112 FileMode = fs.FileMode
1213 FileInfo = fs.FileInfo
1314)
1415
15- // The followings are copied from Go 1.16 official implementation:
16+ // The followings are copied from Go 1.16 or 1.17 official implementation:
1617// https://github.com/golang/go/blob/go1.16/src/os/file.go
1718
19+ // DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir.
20+ //
21+ // Note that DirFS("/prefix") only guarantees that the Open calls it makes to the
22+ // operating system will begin with "/prefix": DirFS("/prefix").Open("file") is the
23+ // same as os.Open("/prefix/file"). So if /prefix/file is a symbolic link pointing outside
24+ // the /prefix tree, then using DirFS does not stop the access any more than using
25+ // os.Open does. DirFS is therefore not a general substitute for a chroot-style security
26+ // mechanism when the directory tree contains arbitrary content.
27+ func DirFS (dir string ) fs.FS {
28+ return dirFS (dir )
29+ }
30+
31+ func containsAny (s , chars string ) bool {
32+ for i := 0 ; i < len (s ); i ++ {
33+ for j := 0 ; j < len (chars ); j ++ {
34+ if s [i ] == chars [j ] {
35+ return true
36+ }
37+ }
38+ }
39+ return false
40+ }
41+
42+ type dirFS string
43+
44+ func (dir dirFS ) Open (name string ) (fs.File , error ) {
45+ if ! fs .ValidPath (name ) || runtime .GOOS == "windows" && containsAny (name , `\:` ) {
46+ return nil , & PathError {Op : "open" , Path : name , Err : ErrInvalid }
47+ }
48+ f , err := Open (string (dir ) + "/" + name )
49+ if err != nil {
50+ return nil , err // nil fs.File
51+ }
52+ return f , nil
53+ }
54+
55+ func (dir dirFS ) Stat (name string ) (fs.FileInfo , error ) {
56+ if ! fs .ValidPath (name ) || runtime .GOOS == "windows" && containsAny (name , `\:` ) {
57+ return nil , & PathError {Op : "stat" , Path : name , Err : ErrInvalid }
58+ }
59+ f , err := Stat (string (dir ) + "/" + name )
60+ if err != nil {
61+ return nil , err
62+ }
63+ return f , nil
64+ }
65+
1866// ReadFile reads the named file and returns the contents.
1967// A successful call returns err == nil, not err == EOF.
2068// Because ReadFile reads the whole file, it does not treat an EOF from Read
0 commit comments