124 lines
2.6 KiB
Go
124 lines
2.6 KiB
Go
package conf
|
|
|
|
import (
|
|
`errors`
|
|
`io/fs`
|
|
`os`
|
|
`os/user`
|
|
`strconv`
|
|
)
|
|
|
|
// chmod applies the PermSpec.Mode to path.
|
|
func (p *PermSpec) chmod(path string, isNew bool) (err error) {
|
|
|
|
if p.Mode == nil || (!isNew && p.explicitMode == false) {
|
|
return
|
|
}
|
|
|
|
if err = os.Chmod(path, *p.Mode); err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// chown applies the Permspec.User and PermSpec.Group to path.
|
|
func (p *PermSpec) chown(path string) (err error) {
|
|
|
|
/*
|
|
ORIGINALLY, I thought I'd have to fetch the original UID/GID from fs.FileInfo.Sys().
|
|
Linux uses https://pkg.go.dev/syscall?GOOS=linux#Stat_t
|
|
macOS uses a https://pkg.go.dev/syscall?GOOS=darwin#Stat_t
|
|
Windows uses a https://pkg.go.dev/syscall?GOOS=windows#Win32FileAttributeData which is completely useless.
|
|
(And AIX, Plan9, JS don't have a Stat_t.)
|
|
But per os.Chown, a -1 means "do not change", which is what we want.
|
|
*/
|
|
|
|
if (p.realUid == -1) || (p.realGid == -1) {
|
|
// This evaluates as a no-op.
|
|
return
|
|
}
|
|
|
|
if err = os.Chown(path, p.realUid, p.realGid); err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// setMissing populates missing information from a PermSpec. It should only be invoked by the parent Perms.SetMissing.
|
|
func (p *PermSpec) setMissing(isDir bool) (err error) {
|
|
|
|
var tmpUser *user.User
|
|
var tmpGroup *user.Group
|
|
var unameUnknown user.UnknownUserError
|
|
// var uidUnknown user.UnknownUserIdError
|
|
var gnameUnknown user.UnknownGroupError
|
|
// var gidUnknown user.UnknownGroupIdError
|
|
|
|
if p.idsSet {
|
|
return
|
|
}
|
|
|
|
// MODE
|
|
if p.Mode == nil {
|
|
p.Mode = new(fs.FileMode)
|
|
if isDir {
|
|
*p.Mode = fs.FileMode(0o0700)
|
|
} else {
|
|
*p.Mode = fs.FileMode(0o0600)
|
|
}
|
|
} else {
|
|
p.explicitMode = true
|
|
}
|
|
|
|
// OWNER/GROUP
|
|
// If nil, no change from current on-disk.
|
|
switch p.User {
|
|
case "":
|
|
p.realUid = p.parent.curUid
|
|
case "-1":
|
|
p.realUid = -1
|
|
default:
|
|
// Lookup, try username first then uid.
|
|
if tmpUser, err = user.Lookup(p.User); err != nil {
|
|
if errors.As(err, &unameUnknown) {
|
|
err = nil
|
|
if tmpUser, err = user.LookupId(p.User); err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
if p.realUid, err = strconv.Atoi(tmpUser.Uid); err != nil {
|
|
return
|
|
}
|
|
}
|
|
switch p.Group {
|
|
case "":
|
|
p.realGid = p.parent.curGid
|
|
case "-1":
|
|
p.realGid = -1
|
|
default:
|
|
// Lookup, try groupname first then gid.
|
|
if tmpGroup, err = user.LookupGroup(p.Group); err != nil {
|
|
if errors.As(err, &gnameUnknown) {
|
|
err = nil
|
|
if tmpGroup, err = user.LookupGroupId(p.Group); err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
if p.realGid, err = strconv.Atoi(tmpGroup.Gid); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
p.idsSet = true
|
|
|
|
return
|
|
}
|