GoBroke/conf/funcs_permspec.go

124 lines
2.6 KiB
Go
Raw Normal View History

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
}