1 // "fixperms" sub-command: apply proper permissions in files/ directories
3 // SPDX-License-Identifier: GPL-3.0-or-later
4 // Copyright (C) 2021-2024 Simon Ruderich
15 "ruderich.org/simon/safcm/cmd/safcm/config"
16 "ruderich.org/simon/safcm/remote/sync"
19 func MainFixperms() error {
20 _, _, _, err := LoadBaseFiles()
22 return fmt.Errorf("not in a safcm directory: %v", err)
25 xs, err := os.ReadDir(".")
29 for _, x := range xs {
33 path := filepath.Join(x.Name(), "files")
35 err := filepath.WalkDir(path, fixpermsWalkDirFunc)
37 if os.IsNotExist(err) {
40 return fmt.Errorf("%s: %v", path, err)
47 func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error {
56 typ := info.Mode().Type()
57 perm := config.FileModeToFullPerm(info.Mode())
59 if typ == 0 /* regular file */ {
60 if perm != 0644 && perm != 0755 {
61 if perm&0111 != 0 /* executable */ {
66 log.Printf("chmodding %q to %#o", path, perm)
67 // This is safe because perm does not include
68 // setuid/setgid/sticky which use different values in
70 err := chmodNoFollow(path, fs.FileMode(perm))
75 } else if typ == fs.ModeDir {
78 log.Printf("chmodding %q to %#o", path, perm)
79 err := chmodNoFollow(path, fs.FileMode(perm))
85 // Other file types are caught by regular "sync"
90 // chmodNoFollow works like os.Chmod but doesn't follow symlinks.
91 func chmodNoFollow(path string, mode fs.FileMode) error {
92 x, err := sync.OpenFileNoSymlinks(path)