]> Cypherpunks repositories - gostls13.git/commitdiff
os: check permissions of CopyFS copied files
authorxieyuschen <xieyuschen@gmail.com>
Mon, 30 Sep 2024 05:53:09 +0000 (13:53 +0800)
committerGopher Robot <gobot@golang.org>
Fri, 4 Oct 2024 14:46:36 +0000 (14:46 +0000)
CopyFS stipulates the permissions of the created files,
we should test them in the unit test.

* chmod x for testdata/x to test CopyFS for executable

* check the files permissions to ensure CopyFS follows the stipulated
  convention

Change-Id: Id13a8ad920ad0c1ff4b801dec3bfa6869cb3101f
Reviewed-on: https://go-review.googlesource.com/c/go/+/616615
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/os/os_test.go
src/os/testdata/dirfs/dir/x [changed mode: 0644->0755]

index ad024b6fd04ce92138966e6747479b29a6b77e78..122dfb5a66884fccb88b50fd5d7afa84cc619cf9 100644 (file)
@@ -3317,24 +3317,7 @@ func TestCopyFS(t *testing.T) {
        if err := fstest.TestFS(tmpFsys, "a", "b", "dir/x"); err != nil {
                t.Fatal("TestFS:", err)
        }
-       if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
-               if d.IsDir() {
-                       return nil
-               }
-
-               data, err := fs.ReadFile(fsys, path)
-               if err != nil {
-                       return err
-               }
-               newData, err := fs.ReadFile(tmpFsys, path)
-               if err != nil {
-                       return err
-               }
-               if !bytes.Equal(data, newData) {
-                       return errors.New("file " + path + " contents differ")
-               }
-               return nil
-       }); err != nil {
+       if err := verifyCopyFS(t, fsys, tmpFsys); err != nil {
                t.Fatal("comparing two directories:", err)
        }
 
@@ -3363,34 +3346,109 @@ func TestCopyFS(t *testing.T) {
        if err := fstest.TestFS(tmpFsys, "william", "carl", "daVinci", "einstein", "dir/newton"); err != nil {
                t.Fatal("TestFS:", err)
        }
-       if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
+       if err := verifyCopyFS(t, fsys, tmpFsys); err != nil {
+               t.Fatal("comparing two directories:", err)
+       }
+
+       // Test whether CopyFS disallows copying for memory filesystem when there is any
+       // existing file in the destination directory.
+       if err := CopyFS(tmpDir, fsys); !errors.Is(err, fs.ErrExist) {
+               t.Errorf("CopyFS should have failed and returned error when there is"+
+                       "any existing file in the destination directory (in memory filesystem), "+
+                       "got: %v, expected any error that indicates <file exists>", err)
+       }
+}
+
+// verifyCopyFS checks the content and permission of each file inside copied FS to ensure
+// the copied files satisfy the convention stipulated in CopyFS.
+func verifyCopyFS(t *testing.T, originFS, copiedFS fs.FS) error {
+       testDir := filepath.Join(t.TempDir(), "test")
+       // umask doesn't apply to the wasip and windows and there is no general way to get masked perm,
+       // so create a dir and a file to compare the permission after umask if any
+       if err := Mkdir(testDir, ModePerm); err != nil {
+               return fmt.Errorf("mkdir %q failed: %v", testDir, err)
+       }
+       dirStat, err := Stat(testDir)
+       if err != nil {
+               return fmt.Errorf("stat dir %q failed: %v", testDir, err)
+       }
+       wantDirMode := dirStat.Mode()
+
+       f, err := Create(filepath.Join(testDir, "tmp"))
+       if err != nil {
+               return fmt.Errorf("open %q failed: %v", filepath.Join(testDir, "tmp"), err)
+       }
+       defer f.Close()
+       wantFileRWStat, err := f.Stat()
+       if err != nil {
+               return fmt.Errorf("stat file %q failed: %v", f.Name(), err)
+       }
+
+       return fs.WalkDir(originFS, ".", func(path string, d fs.DirEntry, err error) error {
                if d.IsDir() {
+                       // the dir . is not the dir created by CopyFS so skip checking its permission
+                       if d.Name() == "." {
+                               return nil
+                       }
+
+                       dinfo, err := fs.Stat(copiedFS, path)
+                       if err != nil {
+                               return err
+                       }
+
+                       if dinfo.Mode() != wantDirMode {
+                               return fmt.Errorf("dir %q mode is %v, want %v",
+                                       d.Name(), dinfo.Mode(), wantDirMode)
+                       }
                        return nil
                }
 
-               data, err := fs.ReadFile(fsys, path)
+               fInfo, err := originFS.Open(path)
                if err != nil {
                        return err
                }
-               newData, err := fs.ReadFile(tmpFsys, path)
+               defer fInfo.Close()
+               copiedInfo, err := copiedFS.Open(path)
+               if err != nil {
+                       return err
+               }
+               defer copiedInfo.Close()
+
+               // verify the file contents are the same
+               data, err := io.ReadAll(fInfo)
+               if err != nil {
+                       return err
+               }
+               newData, err := io.ReadAll(copiedInfo)
                if err != nil {
                        return err
                }
                if !bytes.Equal(data, newData) {
-                       return errors.New("file " + path + " contents differ")
+                       return fmt.Errorf("file %q content is %s, want %s", path, newData, data)
                }
-               return nil
-       }); err != nil {
-               t.Fatal("comparing two directories:", err)
-       }
 
-       // Test whether CopyFS disallows copying for memory filesystem when there is any
-       // existing file in the destination directory.
-       if err := CopyFS(tmpDir, fsys); !errors.Is(err, fs.ErrExist) {
-               t.Errorf("CopyFS should have failed and returned error when there is"+
-                       "any existing file in the destination directory (in memory filesystem), "+
-                       "got: %v, expected any error that indicates <file exists>", err)
-       }
+               fStat, err := fInfo.Stat()
+               if err != nil {
+                       return err
+               }
+               copiedStat, err := copiedInfo.Stat()
+               if err != nil {
+                       return err
+               }
+
+               // check whether the execute permission is inherited from original FS
+               if copiedStat.Mode()&0111 != fStat.Mode()&0111 {
+                       return fmt.Errorf("file %q execute mode is %v, want %v",
+                               path, copiedStat.Mode()&0111, fStat.Mode()&0111)
+               }
+
+               rwMode := copiedStat.Mode() &^ 0111 // unset the executable permission from file mode
+               if rwMode != wantFileRWStat.Mode() {
+                       return fmt.Errorf("file %q rw mode is %v, want %v",
+                               path, rwMode, wantFileRWStat.Mode())
+               }
+               return nil
+       })
 }
 
 func TestCopyFSWithSymlinks(t *testing.T) {
old mode 100644 (file)
new mode 100755 (executable)