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 }