diff --git a/client/config/dfget.go b/client/config/dfget.go index 379a170e20e..a31139019cf 100644 --- a/client/config/dfget.go +++ b/client/config/dfget.go @@ -21,11 +21,13 @@ import ( "encoding/json" "fmt" "os" + "path" "path/filepath" "strings" "syscall" "time" + logger "d7y.io/dragonfly/v2/pkg/dflog" "github.com/pkg/errors" "d7y.io/dragonfly/v2/pkg/basic" @@ -151,6 +153,11 @@ func (cfg *ClientOption) checkOutput() error { cfg.Output = absPath } + dir, _ := path.Split(cfg.Output) + if err := MkdirAll(dir, 0777, basic.UserId, basic.UserGroup); err != nil { + return err + } + if f, err := os.Stat(cfg.Output); err == nil && f.IsDir() { return fmt.Errorf("path[%s] is directory but requires file path", cfg.Output) } @@ -165,3 +172,28 @@ func (cfg *ClientOption) checkOutput() error { } return nil } + +// MkdirAll make directories recursive, and change uid, gid to latest directory. +// For example: the path /data/x exists, uid=1, gid=1 +// when call MkdirAll("/data/x/y/z", 0755, 2, 2) +// MkdirAll creates /data/x/y and change owner to 2:2, creates /data/x/y/z and change owner to 2:2 +func MkdirAll(dir string, perm os.FileMode, uid, gid int) error { + if _, err := os.Stat(strings.TrimRight(dir, "/")); os.IsNotExist(err) { + parent, _ := path.Split(dir) + err = MkdirAll(strings.TrimRight(parent, "/"), perm, uid, gid) + if err != nil && !os.IsExist(err) { + logger.Errorf("mkdirall error: %s", err) + return err + } + err = os.Mkdir(dir, perm) + if err != nil && !os.IsExist(err) { + logger.Errorf("mkdirall error: %s", err) + return err + } + return os.Chown(dir, uid, gid) + } else if err != nil { + logger.Errorf("mkdirall error: %s", err) + return err + } + return nil +} diff --git a/client/daemon/service/manager.go b/client/daemon/service/manager.go index 7280a3fde8f..6e06b8e7167 100644 --- a/client/daemon/service/manager.go +++ b/client/daemon/service/manager.go @@ -192,6 +192,7 @@ func (m *manager) Download(ctx context.Context, p.DoneCallback() logger.Infof("task %s done", p.TaskId) if req.Uid != 0 && req.Gid != 0 { + logger.Infof("change own to uid %d gid %d", req.Uid, req.Gid) if err = os.Chown(req.Output, int(req.Uid), int(req.Gid)); err != nil { logger.Errorf("change own failed: %s", err) return err diff --git a/cmd/dfget/cmd/root.go b/cmd/dfget/cmd/root.go index b7fd412b085..7cb513111a8 100644 --- a/cmd/dfget/cmd/root.go +++ b/cmd/dfget/cmd/root.go @@ -387,6 +387,12 @@ func downloadFromSource(hdr map[string]string, dferr error) (err error) { logger.Infof("copied %d bytes to %s", written, dfgetConfig.Output) end = time.Now() fmt.Printf("Download from source success, time cost: %dms\n", end.Sub(start).Milliseconds()) + // change permission + logger.Infof("change own to uid %d gid %d", basic.UserId, basic.UserGroup) + if err = os.Chown(dfgetConfig.Output, basic.UserId, basic.UserGroup); err != nil { + logger.Errorf("change own failed: %s", err) + return err + } return nil } logger.Errorf("copied %d bytes to %s, with error: %s",