aboutsummaryrefslogtreecommitdiff
path: root/repo
diff options
context:
space:
mode:
authorGravatar Anshul Gupta <ansg191@anshulg.com> 2025-02-18 14:06:53 -0800
committerGravatar Anshul Gupta <ansg191@anshulg.com> 2025-02-18 14:06:53 -0800
commitcd36c3e2aadd71fecdb04eba0ddf1e9bd7a1ca4f (patch)
tree4a4a38cb18d43808112620a88bc469c7ccc81cd6 /repo
parent6fc5e736a9225b7cac250833cdd8fd64446fb740 (diff)
parentf053e334865c5ec402c75d55bdf09b745342080d (diff)
downloadrest-server-master.tar.gz
rest-server-master.tar.zst
rest-server-master.zip
Merge remote-tracking branch 'upstream/master'HEADmaster
Diffstat (limited to 'repo')
-rw-r--r--repo/repo.go81
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
}