]> ruderich.org/simon Gitweb - safcm/safcm.git/blobdiff - cmd/safcm/fixperms.go
remote: guard against symlinks in earlier path components
[safcm/safcm.git] / cmd / safcm / fixperms.go
index 6770934f14d176f7ab15f413ea1d9ce8f0accbd3..af5c65826e3310533c5e4f4748e8bd5a2ae03851 100644 (file)
@@ -25,6 +25,7 @@ import (
        "path/filepath"
 
        "ruderich.org/simon/safcm/cmd/safcm/config"
+       "ruderich.org/simon/safcm/remote/sync"
 )
 
 func MainFixperms() error {
@@ -78,7 +79,7 @@ func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error {
                        // This is safe because perm does not include
                        // setuid/setgid/sticky which use different values in
                        // FileMode.
-                       err := os.Chmod(path, fs.FileMode(perm))
+                       err := chmodNoFollow(path, fs.FileMode(perm))
                        if err != nil {
                                return err
                        }
@@ -87,7 +88,7 @@ func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error {
                if perm != 0755 {
                        perm = 0755
                        log.Printf("chmodding %q to %#o", path, perm)
-                       err := os.Chmod(path, fs.FileMode(perm))
+                       err := chmodNoFollow(path, fs.FileMode(perm))
                        if err != nil {
                                return err
                        }
@@ -97,3 +98,19 @@ func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error {
 
        return nil
 }
+
+// chmodNoFollow works like os.Chmod but doesn't follow symlinks.
+func chmodNoFollow(path string, mode fs.FileMode) error {
+       x, err := sync.OpenFileNoSymlinks(path)
+       if err != nil {
+               return err
+       }
+       defer x.Close()
+
+       err = x.Chmod(mode)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}