diff options
author | 2025-02-18 14:06:53 -0800 | |
---|---|---|
committer | 2025-02-18 14:06:53 -0800 | |
commit | cd36c3e2aadd71fecdb04eba0ddf1e9bd7a1ca4f (patch) | |
tree | 4a4a38cb18d43808112620a88bc469c7ccc81cd6 /repo | |
parent | 6fc5e736a9225b7cac250833cdd8fd64446fb740 (diff) | |
parent | f053e334865c5ec402c75d55bdf09b745342080d (diff) | |
download | rest-server-master.tar.gz rest-server-master.tar.zst rest-server-master.zip |
Diffstat (limited to 'repo')
-rw-r--r-- | repo/repo.go | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/repo/repo.go b/repo/repo.go index d04879a..0e38bb6 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" "math/rand" "net/http" @@ -29,8 +28,6 @@ import ( type Options struct { AppendOnly bool // if set, delete actions are not allowed Debug bool - DirMode os.FileMode - FileMode os.FileMode NoVerifyUpload bool // If set, we will panic when an internal server error happens. This @@ -40,6 +37,13 @@ type Options struct { BlobMetricFunc BlobMetricFunc QuotaManager *quota.Manager FsyncWarning *sync.Once + + // If set makes files group accessible + GroupAccessible bool + + // Defaults dir and file mode + dirMode os.FileMode + fileMode os.FileMode } // DefaultDirMode is the file mode used for directory creation if not @@ -50,6 +54,14 @@ const DefaultDirMode os.FileMode = 0700 // overridden in the Options const DefaultFileMode os.FileMode = 0600 +// GroupAccessibleDirMode is the file mode used for directory creation when +// group access is enabled +const GroupAccessibleDirMode os.FileMode = 0770 + +// GroupAccessibleFileMode is the file mode used for file creation when +// group access is enabled +const GroupAccessibleFileMode os.FileMode = 0660 + // New creates a new Handler for a single Restic backup repo. // path is the full filesystem path to this repo directory. // opt is a set of options. @@ -57,12 +69,15 @@ func New(path string, opt Options) (*Handler, error) { if path == "" { return nil, fmt.Errorf("path is required") } - if opt.DirMode == 0 { - opt.DirMode = DefaultDirMode - } - if opt.FileMode == 0 { - opt.FileMode = DefaultFileMode + + opt.dirMode = DefaultDirMode + opt.fileMode = DefaultFileMode + + if opt.GroupAccessible { + opt.dirMode = GroupAccessibleDirMode + opt.fileMode = GroupAccessibleFileMode } + h := Handler{ path: path, opt: opt, @@ -251,7 +266,7 @@ func (h *Handler) wrapFileWriter(r *http.Request, w io.Writer) (io.Writer, int, } // checkConfig checks whether a configuration exists. -func (h *Handler) checkConfig(w http.ResponseWriter, r *http.Request) { +func (h *Handler) checkConfig(w http.ResponseWriter, _ *http.Request) { if h.opt.Debug { log.Println("checkConfig()") } @@ -267,13 +282,13 @@ func (h *Handler) checkConfig(w http.ResponseWriter, r *http.Request) { } // getConfig allows for a config to be retrieved. -func (h *Handler) getConfig(w http.ResponseWriter, r *http.Request) { +func (h *Handler) getConfig(w http.ResponseWriter, _ *http.Request) { if h.opt.Debug { log.Println("getConfig()") } cfg := h.getSubPath("config") - bytes, err := ioutil.ReadFile(cfg) + bytes, err := os.ReadFile(cfg) if err != nil { h.fileAccessError(w, err) return @@ -289,7 +304,7 @@ func (h *Handler) saveConfig(w http.ResponseWriter, r *http.Request) { } cfg := h.getSubPath("config") - f, err := os.OpenFile(cfg, os.O_CREATE|os.O_WRONLY|os.O_EXCL, h.opt.FileMode) + f, err := os.OpenFile(cfg, os.O_CREATE|os.O_WRONLY|os.O_EXCL, h.opt.fileMode) if err != nil && os.IsExist(err) { if h.opt.Debug { log.Print(err) @@ -314,7 +329,7 @@ func (h *Handler) saveConfig(w http.ResponseWriter, r *http.Request) { } // deleteConfig removes a config. -func (h *Handler) deleteConfig(w http.ResponseWriter, r *http.Request) { +func (h *Handler) deleteConfig(w http.ResponseWriter, _ *http.Request) { if h.opt.Debug { log.Println("deleteConfig()") } @@ -369,7 +384,7 @@ func (h *Handler) listBlobsV1(w http.ResponseWriter, r *http.Request) { } path := h.getSubPath(objectType) - items, err := ioutil.ReadDir(path) + items, err := os.ReadDir(path) if err != nil { h.fileAccessError(w, err) return @@ -383,8 +398,8 @@ func (h *Handler) listBlobsV1(w http.ResponseWriter, r *http.Request) { continue } subpath := filepath.Join(path, i.Name()) - var subitems []os.FileInfo - subitems, err = ioutil.ReadDir(subpath) + var subitems []os.DirEntry + subitems, err = os.ReadDir(subpath) if err != nil { h.fileAccessError(w, err) return @@ -428,7 +443,7 @@ func (h *Handler) listBlobsV2(w http.ResponseWriter, r *http.Request) { } path := h.getSubPath(objectType) - items, err := ioutil.ReadDir(path) + items, err := os.ReadDir(path) if err != nil { h.fileAccessError(w, err) return @@ -442,17 +457,27 @@ func (h *Handler) listBlobsV2(w http.ResponseWriter, r *http.Request) { continue } subpath := filepath.Join(path, i.Name()) - var subitems []os.FileInfo - subitems, err = ioutil.ReadDir(subpath) + var subitems []os.DirEntry + subitems, err = os.ReadDir(subpath) if err != nil { h.fileAccessError(w, err) return } for _, f := range subitems { - blobs = append(blobs, Blob{Name: f.Name(), Size: f.Size()}) + fi, err := f.Info() + if err != nil { + h.fileAccessError(w, err) + return + } + blobs = append(blobs, Blob{Name: f.Name(), Size: fi.Size()}) } } else { - blobs = append(blobs, Blob{Name: i.Name(), Size: i.Size()}) + fi, err := i.Info() + if err != nil { + h.fileAccessError(w, err) + return + } + blobs = append(blobs, Blob{Name: i.Name(), Size: fi.Size()}) } } @@ -545,15 +570,15 @@ func (h *Handler) saveBlob(w http.ResponseWriter, r *http.Request) { } tmpFn := filepath.Join(filepath.Dir(path), objectID+".rest-server-temp") - tf, err := tempFile(tmpFn, h.opt.FileMode) + tf, err := tempFile(tmpFn, h.opt.fileMode) if os.IsNotExist(err) { // the error is caused by a missing directory, create it and retry - mkdirErr := os.MkdirAll(filepath.Dir(path), h.opt.DirMode) + mkdirErr := os.MkdirAll(filepath.Dir(path), h.opt.dirMode) if mkdirErr != nil { log.Print(mkdirErr) } else { // try again - tf, err = tempFile(tmpFn, h.opt.FileMode) + tf, err = tempFile(tmpFn, h.opt.fileMode) } } if err != nil { @@ -652,7 +677,7 @@ func (h *Handler) saveBlob(w http.ResponseWriter, r *http.Request) { h.sendMetric(objectType, BlobWrite, uint64(written)) } -// tempFile implements a custom version of ioutil.TempFile which allows modifying the file permissions +// tempFile implements a custom version of os.CreateTemp which allows modifying the file permissions func tempFile(fn string, perm os.FileMode) (f *os.File, err error) { for i := 0; i < 10; i++ { name := fn + strconv.FormatInt(rand.Int63(), 10) @@ -750,13 +775,13 @@ func (h *Handler) createRepo(w http.ResponseWriter, r *http.Request) { log.Printf("Creating repository directories in %s\n", h.path) - if err := os.MkdirAll(h.path, h.opt.DirMode); err != nil { + if err := os.MkdirAll(h.path, h.opt.dirMode); err != nil { h.internalServerError(w, err) return } for _, d := range ObjectTypes { - if err := os.Mkdir(filepath.Join(h.path, d), h.opt.DirMode); err != nil && !os.IsExist(err) { + if err := os.Mkdir(filepath.Join(h.path, d), h.opt.dirMode); err != nil && !os.IsExist(err) { h.internalServerError(w, err) return } @@ -764,7 +789,7 @@ func (h *Handler) createRepo(w http.ResponseWriter, r *http.Request) { for i := 0; i < 256; i++ { dirPath := filepath.Join(h.path, "data", fmt.Sprintf("%02x", i)) - if err := os.Mkdir(dirPath, h.opt.DirMode); err != nil && !os.IsExist(err) { + if err := os.Mkdir(dirPath, h.opt.dirMode); err != nil && !os.IsExist(err) { h.internalServerError(w, err) return } |