github.com/andy2046/gopie@v0.7.0/pkg/fileutil/fileutil.go (about) 1 // Package fileutil implements some file utils. 2 package fileutil 3 4 import ( 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "sort" 10 ) 11 12 // ReadDirOperation represents read-directory operation. 13 type ReadDirOperation struct { 14 ext string 15 } 16 17 const ( 18 // PrivateFileMode represents file read/write mode to owner. 19 PrivateFileMode = 0600 20 // PrivateDirMode represents file make/remove mode in the directory to owner. 21 PrivateDirMode = 0700 22 ) 23 24 // WithExt filters file names by extension. 25 func WithExt(ext string) func(*ReadDirOperation) { 26 return func(op *ReadDirOperation) { op.ext = ext } 27 } 28 29 func (op *ReadDirOperation) applyOpts(opts []func(*ReadDirOperation)) { 30 for _, opt := range opts { 31 opt(op) 32 } 33 } 34 35 // ReadDir returns the file names in the provided directory in order. 36 func ReadDir(d string, opts ...func(*ReadDirOperation)) ([]string, error) { 37 var err error 38 op := &ReadDirOperation{} 39 op.applyOpts(opts) 40 41 dir, err := os.Open(d) 42 if err != nil { 43 return nil, err 44 } 45 defer dir.Close() 46 47 names, err := dir.Readdirnames(-1) 48 if err != nil { 49 return nil, err 50 } 51 sort.Strings(names) 52 53 if op.ext != "" { 54 temp := make([]string, 0) 55 for _, v := range names { 56 if filepath.Ext(v) == op.ext { 57 temp = append(temp, v) 58 } 59 } 60 names = temp 61 } 62 return names, nil 63 } 64 65 // IsDirWriteable checks if dir is writable by writing and removing a file to dir. 66 func IsDirWriteable(dir string) error { 67 f := filepath.Join(dir, ".touch") 68 if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil { 69 return err 70 } 71 return os.Remove(f) 72 } 73 74 // TouchDirAll creates directories with 0700 permission if any directory 75 // does not exist and ensures the provided directory is writable. 76 func TouchDirAll(dir string) error { 77 err := os.MkdirAll(dir, PrivateDirMode) 78 if err != nil { 79 return err 80 } 81 return IsDirWriteable(dir) 82 } 83 84 // CreateDirAll wraps TouchDirAll but returns error 85 // if the deepest directory is not empty. 86 func CreateDirAll(dir string) error { 87 err := TouchDirAll(dir) 88 if err == nil { 89 var ns []string 90 if ns, err = ReadDir(dir); err != nil { 91 return err 92 } 93 if len(ns) != 0 { 94 err = fmt.Errorf("expected %q to be empty, got %q", dir, ns) 95 } 96 } 97 return err 98 } 99 100 // Exist returns true if a file or directory exists. 101 func Exist(name string) bool { 102 if _, err := os.Stat(name); os.IsNotExist(err) { 103 return false 104 } 105 return true 106 }