internal/file/root.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | //nolint:forbidigo // wrappers for os.File functions go here package file import ( "io" "io/fs" "os" "path/filepath" "time" "github.com/Southclaws/fault" "github.com/Southclaws/fault/fmsg" ) type Root struct { *os.Root } func CreateAndOpenRoot(name string) (*Root, error) { exists, err := exists(name) if err != nil { return nil, fault.Wrap(err, fmsg.Withf("failed to check data root existence %s", name)) } if !exists { err := mkdirp(name) if err != nil { return nil, fault.Wrap(err, fmsg.Withf("failed to create data root %s", name)) } } return OpenRoot(name) } func OpenRoot(name string) (*Root, error) { r, err := os.OpenRoot(name) if err != nil { return nil, fault.Wrap(err, fmsg.Withf("failed to open data root directory %s", name)) } return &Root{ Root: r, }, nil } func (r *Root) JoinPath(path string) string { return filepath.Join(r.Name(), path) } func (r *Root) StatIfExists(name string) (fs.FileInfo, error) { stat, err := r.Stat(name) return stat, needNotExist(err) } func (r *Root) Exists(file string) (bool, error) { stat, err := r.StatIfExists(file) return stat != nil, err } func (r *Root) CopyTo(source, target string) error { src, err := os.Open(source) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to open source file %s", source)) } defer src.Close() dst, err := r.OpenFile(target, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o640) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to create target file %s", target)) } defer dst.Close() if _, err := io.Copy(dst, src); err != nil { return fault.Wrap(err, fmsg.Withf("failed to copy file from %s to %s", source, target)) } err = dst.Sync() if err != nil { return fault.Wrap(err, fmsg.Withf("failed to sync target file %s", target)) } return nil } func (r *Root) Chtimes(name string, atime time.Time, mtime time.Time) error { err := os.Chtimes(r.JoinPath(name), atime, mtime) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to change times of %s", name)) } return nil } func (r *Root) MkdirAll(name string) error { err := os.MkdirAll(r.JoinPath(name), 0o750) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to create directory %s", name)) } return nil } func (r *Root) ReadFile(name string) ([]byte, error) { b, err := fs.ReadFile(r.FS(), name) if err != nil { return nil, fault.Wrap(err, fmsg.Withf("failed to read file %s", name)) } return b, nil } func (r *Root) WriteFile(name string, data []byte, perm fs.FileMode) error { f, err := r.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to write file %s", name)) } defer f.Close() _, err = f.Write(data) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to write file %s", name)) } return nil } func (r *Root) RemoveAll(name string) error { err := os.RemoveAll(r.JoinPath(name)) if err != nil { return fault.Wrap(err, fmsg.Withf("failed to remove path %s", r.JoinPath(name))) } return nil } |