diff --git a/os/gfile/gfile.go b/os/gfile/gfile.go index 0dbc9e6cd26..3c9db89e55f 100644 --- a/os/gfile/gfile.go +++ b/os/gfile/gfile.go @@ -30,7 +30,7 @@ const ( DefaultPermOpen = os.FileMode(0666) // DefaultPermCopy is the default perm for file/folder copy. - DefaultPermCopy = os.FileMode(0777) + DefaultPermCopy = os.FileMode(0755) ) var ( diff --git a/os/gfile/gfile_copy.go b/os/gfile/gfile_copy.go index f817afb6936..1a815551646 100644 --- a/os/gfile/gfile_copy.go +++ b/os/gfile/gfile_copy.go @@ -17,8 +17,16 @@ import ( // CopyOption is the option for Copy* functions. type CopyOption struct { - Sync bool // Auto call file sync after source file content copied to target file. - Mode os.FileMode // Destination created file mode. The default file mode is DefaultPermCopy. + // Auto call file sync after source file content copied to target file. + Sync bool + + // Preserve the mode of the original file to the target file. + // If true, the Mode attribute will make no sense. + PreserveMode bool + + // Destination created file mode. + // The default file mode is DefaultPermCopy if PreserveMode is false. + Mode os.FileMode } // Copy file/directory from `src` to `dst`. @@ -162,6 +170,9 @@ func CopyFile(src, dst string, option ...CopyOption) (err error) { return } } + if usedOption.PreserveMode { + usedOption.Mode = srcStat.Mode().Perm() + } if err = Chmod(dst, usedOption.Mode); err != nil { return } @@ -192,6 +203,9 @@ func CopyDir(src string, dst string, option ...CopyOption) (err error) { if !si.IsDir() { return gerror.NewCode(gcode.CodeInvalidParameter, "source is not a directory") } + if usedOption.PreserveMode { + usedOption.Mode = si.Mode().Perm() + } if !Exists(dst) { if err = os.MkdirAll(dst, usedOption.Mode); err != nil { err = gerror.Wrapf( diff --git a/os/gfile/gfile_z_exmaple_basic_test.go b/os/gfile/gfile_z_exmaple_basic_test.go index dc658f70b61..a592e3cf27d 100644 --- a/os/gfile/gfile_z_exmaple_basic_test.go +++ b/os/gfile/gfile_z_exmaple_basic_test.go @@ -377,7 +377,7 @@ func ExampleChmod() { // Output: // -rw-r--r-- - // -rwxrwxrwx + // -rwxr-xr-x } func ExampleAbs() { diff --git a/os/gfile/gfile_z_unit_copy_test.go b/os/gfile/gfile_z_unit_copy_test.go index 66e23169e2b..b914ca7d4dd 100644 --- a/os/gfile/gfile_z_unit_copy_test.go +++ b/os/gfile/gfile_z_unit_copy_test.go @@ -7,6 +7,7 @@ package gfile_test import ( + "os" "testing" "github.com/gogf/gf/v2/os/gfile" @@ -100,6 +101,41 @@ func Test_CopyFile(t *testing.T) { t.Assert(gfile.GetContents(src), srcContent) t.Assert(gfile.GetContents(dst), srcContent) }) + // Set mode + gtest.C(t, func(t *gtest.T) { + var ( + src = "/testfile_copyfile1.txt" + dst = "/testfile_copyfile2.txt" + dstMode = os.FileMode(0600) + ) + t.AssertNil(createTestFile(src, "")) + defer delTestFiles(src) + + t.Assert(gfile.CopyFile(testpath()+src, testpath()+dst, gfile.CopyOption{Mode: dstMode}), nil) + defer delTestFiles(dst) + + dstStat, err := gfile.Stat(testpath() + dst) + t.AssertNil(err) + t.Assert(dstStat.Mode().Perm(), dstMode) + }) + // Preserve src file's mode + gtest.C(t, func(t *gtest.T) { + var ( + src = "/testfile_copyfile1.txt" + dst = "/testfile_copyfile2.txt" + ) + t.AssertNil(createTestFile(src, "")) + defer delTestFiles(src) + + t.Assert(gfile.CopyFile(testpath()+src, testpath()+dst, gfile.CopyOption{PreserveMode: true}), nil) + defer delTestFiles(dst) + + srcStat, err := gfile.Stat(testpath() + src) + t.AssertNil(err) + dstStat, err := gfile.Stat(testpath() + dst) + t.AssertNil(err) + t.Assert(srcStat.Mode().Perm(), dstStat.Mode().Perm()) + }) } func Test_CopyDir(t *testing.T) {