Skip to content

Commit

Permalink
Allow the configuration of filesystem permissions.
Browse files Browse the repository at this point in the history
  • Loading branch information
koenbollen authored and cenkalti committed Jul 13, 2022
1 parent 2da41d4 commit 9e6543a
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 12 deletions.
10 changes: 6 additions & 4 deletions internal/storage/filestorage/filestorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package filestorage

import (
"io/fs"
"os"
"path/filepath"

Expand All @@ -11,16 +12,17 @@ import (
// FileStorage implements Storage interface for saving files on disk.
type FileStorage struct {
dest string
perm fs.FileMode
}

// New returns a new FileStorage at the destination.
func New(dest string) (*FileStorage, error) {
func New(dest string, perm fs.FileMode) (*FileStorage, error) {
var err error
dest, err = filepath.Abs(dest)
if err != nil {
return nil, err
}
return &FileStorage{dest: dest}, nil
return &FileStorage{dest: dest, perm: perm}, nil
}

var _ storage.Storage = (*FileStorage)(nil)
Expand All @@ -33,7 +35,7 @@ func (s *FileStorage) Open(name string, size int64) (f storage.File, exists bool
name = filepath.Join(s.dest, name)

// Create containing dir if not exists.
err = os.MkdirAll(filepath.Dir(name), os.ModeDir|0o750)
err = os.MkdirAll(filepath.Dir(name), os.ModeDir|s.perm)
if err != nil {
return
}
Expand All @@ -52,7 +54,7 @@ func (s *FileStorage) Open(name string, size int64) (f storage.File, exists bool
}()

// Open OS file.
const mode = 0o640
var mode = s.perm &^ 0111
openFlags := os.O_RDWR | os.O_SYNC
openFlags = applyNoAtimeFlag(openFlags)
of, err = os.OpenFile(name, openFlags, mode)
Expand Down
4 changes: 4 additions & 0 deletions torrent/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package torrent

import (
"io/fs"
"time"

"github.com/cenkalti/rain/internal/metainfo"
Expand Down Expand Up @@ -75,6 +76,8 @@ type Config struct {
HealthCheckInterval time.Duration
// If torrent loop is stuck for more than this duration. Program crashes with stacktrace.
HealthCheckTimeout time.Duration
// The unix permission of created files, execute bit is removed for files
FilePermissions fs.FileMode

// Enable RPC server
RPCEnabled bool
Expand Down Expand Up @@ -220,6 +223,7 @@ var DefaultConfig = Config{
ResumeOnStartup: true,
HealthCheckInterval: 10 * time.Second,
HealthCheckTimeout: 60 * time.Second,
FilePermissions: 0o750,

// RPC Server
RPCEnabled: true,
Expand Down
4 changes: 2 additions & 2 deletions torrent/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@ func NewSession(cfg Config) (*Session, error) {
if err != nil {
return nil, err
}
err = os.MkdirAll(filepath.Dir(cfg.Database), 0750)
err = os.MkdirAll(filepath.Dir(cfg.Database), os.ModeDir|cfg.FilePermissions)
if err != nil {
return nil, err
}
l := logger.New("session")
db, err := bbolt.Open(cfg.Database, 0640, &bbolt.Options{Timeout: time.Second})
db, err := bbolt.Open(cfg.Database, cfg.FilePermissions&^0111, &bbolt.Options{Timeout: time.Second})
if err == bbolt.ErrTimeout {
return nil, errors.New("resume database is locked by another process")
} else if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion torrent/session_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ func (s *Session) add(opt *AddTorrentOptions) (id string, port int, sto *filesto
}
id = base64.RawURLEncoding.EncodeToString(u1[:])
}
sto, err = filestorage.New(s.getDataDir(id))
sto, err = filestorage.New(s.getDataDir(id), s.config.FilePermissions)
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion torrent/session_load.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (s *Session) loadExistingTorrent(id string) (tt *Torrent, hasStarted bool,
bf = bf3
}
}
sto, err := filestorage.New(s.getDataDir(id))
sto, err := filestorage.New(s.getDataDir(id), s.config.FilePermissions)
if err != nil {
return
}
Expand Down
7 changes: 4 additions & 3 deletions torrent/session_rpc_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"errors"
"io"
"io/fs"
"io/ioutil"
"net/http"
"os"
Expand Down Expand Up @@ -514,7 +515,7 @@ func (h *rpcHandler) handleMoveTorrent(w http.ResponseWriter, r *http.Request) {
http.Error(w, "data expected in multipart form", http.StatusBadRequest)
return
}
err = readData(p, h.session.getDataDir(id))
err = readData(p, h.session.getDataDir(id), h.session.config.FilePermissions)
if err != nil {
h.session.log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down Expand Up @@ -543,7 +544,7 @@ func (h *rpcHandler) handleMoveTorrent(w http.ResponseWriter, r *http.Request) {
success = true
}

func readData(r io.Reader, dir string) error {
func readData(r io.Reader, dir string, perm fs.FileMode) error {
tr := tar.NewReader(r)
for {
hdr, err := tr.Next()
Expand All @@ -554,7 +555,7 @@ func readData(r io.Reader, dir string) error {
return err
}
name := filepath.Join(dir, hdr.Name)
err = os.MkdirAll(filepath.Dir(name), os.ModeDir|0750)
err = os.MkdirAll(filepath.Dir(name), os.ModeDir|perm)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion torrent/torrent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func seeder(t *testing.T, clearTrackers bool) (addr string, c func()) {
}
src := filepath.Join(torrentDataDir, torrentName)
dst := filepath.Join(s.config.DataDir, tor.ID(), torrentName)
err = os.Mkdir(filepath.Join(s.config.DataDir, tor.ID()), os.ModeDir|0750)
err = os.Mkdir(filepath.Join(s.config.DataDir, tor.ID()), os.ModeDir|s.config.FilePermissions)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit 9e6543a

Please sign in to comment.