From 0c2e5f13516992e56133647cea4129733eee3fa5 Mon Sep 17 00:00:00 2001 From: MickaelK Date: Wed, 10 Jan 2024 18:32:37 +1100 Subject: [PATCH] feature (plg_backend_nfs): add option to calculate uid/gid --- server/plugin/plg_backend_nfs/index.go | 99 ++++++++++++++++++++------ 1 file changed, 78 insertions(+), 21 deletions(-) diff --git a/server/plugin/plg_backend_nfs/index.go b/server/plugin/plg_backend_nfs/index.go index 700cdbbe..53eb55ba 100644 --- a/server/plugin/plg_backend_nfs/index.go +++ b/server/plugin/plg_backend_nfs/index.go @@ -1,17 +1,25 @@ package plg_backend_nfs import ( + "bufio" "context" - . "github.com/mickael-kerjean/filestash/server/common" - "github.com/vmware/go-nfs-client/nfs" - "github.com/vmware/go-nfs-client/nfs/rpc" - "github.com/vmware/go-nfs-client/nfs/util" - "github.com/vmware/go-nfs-client/nfs/xdr" "io" "os" "path/filepath" "strconv" "strings" + + . "github.com/mickael-kerjean/filestash/server/common" + + "github.com/vmware/go-nfs-client/nfs" + "github.com/vmware/go-nfs-client/nfs/rpc" + "github.com/vmware/go-nfs-client/nfs/util" + "github.com/vmware/go-nfs-client/nfs/xdr" +) + +const ( + DEFAULT_UID = 1000 + DEFAULT_GID = 1000 ) type NfsShare struct { @@ -26,29 +34,20 @@ type NfsShare struct { func init() { Backend.Register("nfs", NfsShare{}) util.DefaultLogger.SetDebug(false) + cacheForEtc = NewAppCache(120, 60) } func (this NfsShare) Init(params map[string]string, app *App) (IBackend, error) { if params["hostname"] == "" { return nil, ErrNotFound } - var ( - uid uint32 = 1000 - gid uint32 = 1000 - ) - if params["uid"] != "" { - if _uid, err := strconv.Atoi(params["uid"]); err == nil { - uid = uint32(_uid) - } - } - if params["gid"] != "" { - if _gid, err := strconv.Atoi(params["gid"]); err == nil { - gid = uint32(_gid) - } - } + if params["machine_name"] == "" { params["machine_name"] = "filestash" } + + uid := getUid(params["uid"]) + gid := getGid(params["gid"]) auth := rpc.NewAuthUnix(params["machine_name"], uid, gid).Auth() mount, err := nfs.DialMount(params["hostname"]) if err != nil { @@ -88,13 +87,13 @@ func (this NfsShare) LoginForm() Form { FormElement{ Id: "nfs_uid", Name: "uid", - Type: "number", + Type: "text", Placeholder: "uid", }, FormElement{ Id: "nfs_gid", Name: "gid", - Type: "number", + Type: "text", Placeholder: "gid", }, FormElement{ @@ -272,3 +271,61 @@ func (this NfsShare) Close() { func (this NfsShare) nfsPath(path string) string { return strings.TrimSuffix(path, "/") } + +func getUid(hint string) uint32 { + if hint == "" { + return DEFAULT_UID + } else if _uid, err := strconv.Atoi(hint); err == nil { + return uint32(_uid) + } else if uid, _, err := extractFromEtcPasswd(hint); err == nil { + return uid + } + return DEFAULT_UID +} +func getGid(hint string) uint32 { + if hint == "" { + return DEFAULT_UID + } else if _gid, err := strconv.Atoi(hint); err == nil { + return uint32(_gid) + } else if _, gid, err := extractFromEtcPasswd(hint); err == nil { + return gid + } + return DEFAULT_GID +} + +var cacheForEtc AppCache + +func extractFromEtcPasswd(username string) (uint32, uint32, error) { + if v := cacheForEtc.Get(map[string]string{"username": username}); v != nil { + inCache := v.([]int) + return uint32(inCache[0]), uint32(inCache[1]), nil + } + f, err := os.OpenFile("/etc/passwd", os.O_RDONLY, os.ModePerm) + if err != nil { + return DEFAULT_UID, DEFAULT_GID, err + } + defer f.Close() + lines := bufio.NewReader(f) + for { + line, _, err := lines.ReadLine() + if err != nil { + break + } + s := strings.Split(string(line), ":") + if len(s) != 7 { + continue + } else if username == s[0] { + u, err := strconv.Atoi(s[2]) + if err != nil { + continue + } + g, err := strconv.Atoi(s[3]) + if err != nil { + continue + } + cacheForEtc.Set(map[string]string{"username": username}, []int{u, g}) + return uint32(u), uint32(g), nil + } + } + return DEFAULT_UID, DEFAULT_GID, ErrNotFound +}