feature (plg_backend_nfs): add option to calculate uid/gid

This commit is contained in:
MickaelK
2024-01-10 18:32:37 +11:00
parent 005cdddfc7
commit 0c2e5f1351
+78 -21
View File
@@ -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
}