X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=cmd%2Fsafcm%2Fconfig%2Fpermissions.go;fp=cmd%2Fsafcm%2Fconfig%2Fpermissions.go;h=b84b521d1c615289aeaf17e704bd2ec1dbe79927;hb=f2f2bc47e8729548f3c10117f7f008b547c4afc5;hp=0000000000000000000000000000000000000000;hpb=dc0d431a778a50e6732b9eb91384a07a207b772d;p=safcm%2Fsafcm.git diff --git a/cmd/safcm/config/permissions.go b/cmd/safcm/config/permissions.go new file mode 100644 index 0000000..b84b521 --- /dev/null +++ b/cmd/safcm/config/permissions.go @@ -0,0 +1,118 @@ +// Config: parse permissions.yaml + +// Copyright (C) 2021 Simon Ruderich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package config + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "strconv" + "strings" + + "gopkg.in/yaml.v2" + + "ruderich.org/simon/safcm" +) + +func LoadPermissions(group string, files map[string]*safcm.File) error { + path := filepath.Join(group, "permissions.yaml") + + var cfg map[string]string + x, err := os.ReadFile(path) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + err = yaml.UnmarshalStrict(x, &cfg) + if err != nil { + return fmt.Errorf("%s: failed to load: %v", path, err) + } + + for p, x := range cfg { + _, ok := files[p] + if !ok { + return fmt.Errorf("%s: %q does not exist in files/", + path, p) + } + + xs := strings.Fields(x) + if len(xs) != 1 && len(xs) != 3 { + return fmt.Errorf("%s: invalid line %q "+ + "(expected [ ])", + path, x) + } + perm, err := strconv.ParseInt(xs[0], 8, 32) + if err != nil { + return fmt.Errorf("%s: invalid permission %q "+ + "(expected e.g. %q or %q)", + path, xs[0], "0644", "01777") + } + if perm > 07777 { + return fmt.Errorf("%s: invalid permission %#o "+ + "(expected e.g. %#o or %#o)", + path, perm, 0644, 01777) + } + + file := files[p] + // Sanity check + if file.Mode.Perm()&0111 != 0 && perm&0111 == 0 { + return fmt.Errorf( + "%s: %q: trying to remove +x from file, "+ + "manually chmod -x in files/", + path, p) + } + file.Mode = file.Mode.Type() | FullPermToFileMode(int(perm)) + if len(xs) == 3 { + file.User = xs[1] + file.Group = xs[2] + } + } + + return nil +} + +func FileModeToFullPerm(mode fs.FileMode) int { + perm := mode.Perm() + if mode&fs.ModeSticky != 0 { + perm |= 01000 + } + if mode&fs.ModeSetgid != 0 { + perm |= 02000 + } + if mode&fs.ModeSetuid != 0 { + perm |= 04000 + } + return int(perm) +} + +func FullPermToFileMode(perm int) fs.FileMode { + mode := fs.FileMode(perm & 0777) + if perm&01000 != 0 { + mode |= fs.ModeSticky + } + if perm&02000 != 0 { + mode |= fs.ModeSetgid + } + if perm&04000 != 0 { + mode |= fs.ModeSetuid + } + return mode +}