nosymlink_test.go (4257B)
1 // Copyright 2019 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package hugofs 15 16 import ( 17 "os" 18 "path/filepath" 19 "testing" 20 21 "github.com/gohugoio/hugo/common/loggers" 22 23 "github.com/gohugoio/hugo/htesting" 24 25 "github.com/spf13/afero" 26 27 qt "github.com/frankban/quicktest" 28 ) 29 30 func prepareSymlinks(t *testing.T) (string, func()) { 31 c := qt.New(t) 32 33 workDir, clean, err := htesting.CreateTempDir(Os, "hugo-symlink-test") 34 c.Assert(err, qt.IsNil) 35 wd, _ := os.Getwd() 36 37 blogDir := filepath.Join(workDir, "blog") 38 blogSubDir := filepath.Join(blogDir, "sub") 39 c.Assert(os.MkdirAll(blogSubDir, 0777), qt.IsNil) 40 blogFile1 := filepath.Join(blogDir, "a.txt") 41 blogFile2 := filepath.Join(blogSubDir, "b.txt") 42 afero.WriteFile(Os, filepath.Join(blogFile1), []byte("content1"), 0777) 43 afero.WriteFile(Os, filepath.Join(blogFile2), []byte("content2"), 0777) 44 os.Chdir(workDir) 45 c.Assert(os.Symlink("blog", "symlinkdedir"), qt.IsNil) 46 os.Chdir(blogDir) 47 c.Assert(os.Symlink("sub", "symsub"), qt.IsNil) 48 c.Assert(os.Symlink("a.txt", "symlinkdedfile.txt"), qt.IsNil) 49 50 return workDir, func() { 51 clean() 52 os.Chdir(wd) 53 } 54 } 55 56 func TestNoSymlinkFs(t *testing.T) { 57 if skipSymlink() { 58 t.Skip("Skip; os.Symlink needs administrator rights on Windows") 59 } 60 c := qt.New(t) 61 workDir, clean := prepareSymlinks(t) 62 defer clean() 63 64 blogDir := filepath.Join(workDir, "blog") 65 blogFile1 := filepath.Join(blogDir, "a.txt") 66 67 logger := loggers.NewWarningLogger() 68 69 for _, bfs := range []afero.Fs{NewBaseFileDecorator(Os), Os} { 70 for _, allowFiles := range []bool{false, true} { 71 logger.LogCounters().WarnCounter.Reset() 72 fs := NewNoSymlinkFs(bfs, logger, allowFiles) 73 ls := fs.(afero.Lstater) 74 symlinkedDir := filepath.Join(workDir, "symlinkdedir") 75 symlinkedFilename := "symlinkdedfile.txt" 76 symlinkedFile := filepath.Join(blogDir, symlinkedFilename) 77 78 assertFileErr := func(err error) { 79 if allowFiles { 80 c.Assert(err, qt.IsNil) 81 } else { 82 c.Assert(err, qt.Equals, ErrPermissionSymlink) 83 } 84 } 85 86 assertFileStat := func(name string, fi os.FileInfo, err error) { 87 t.Helper() 88 assertFileErr(err) 89 if err == nil { 90 c.Assert(fi, qt.Not(qt.IsNil)) 91 c.Assert(fi.Name(), qt.Equals, name) 92 } 93 } 94 95 // Check Stat and Lstat 96 for _, stat := range []func(name string) (os.FileInfo, error){ 97 func(name string) (os.FileInfo, error) { 98 return fs.Stat(name) 99 }, 100 func(name string) (os.FileInfo, error) { 101 fi, _, err := ls.LstatIfPossible(name) 102 return fi, err 103 }, 104 } { 105 _, err := stat(symlinkedDir) 106 c.Assert(err, qt.Equals, ErrPermissionSymlink) 107 fi, err := stat(symlinkedFile) 108 assertFileStat(symlinkedFilename, fi, err) 109 110 fi, err = stat(filepath.Join(workDir, "blog")) 111 c.Assert(err, qt.IsNil) 112 c.Assert(fi, qt.Not(qt.IsNil)) 113 114 fi, err = stat(blogFile1) 115 c.Assert(err, qt.IsNil) 116 c.Assert(fi, qt.Not(qt.IsNil)) 117 } 118 119 // Check Open 120 _, err := fs.Open(symlinkedDir) 121 c.Assert(err, qt.Equals, ErrPermissionSymlink) 122 _, err = fs.OpenFile(symlinkedDir, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) 123 c.Assert(err, qt.Equals, ErrPermissionSymlink) 124 _, err = fs.OpenFile(symlinkedFile, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) 125 assertFileErr(err) 126 _, err = fs.Open(symlinkedFile) 127 assertFileErr(err) 128 f, err := fs.Open(blogDir) 129 c.Assert(err, qt.IsNil) 130 f.Close() 131 f, err = fs.Open(blogFile1) 132 c.Assert(err, qt.IsNil) 133 f.Close() 134 135 // Check readdir 136 f, err = fs.Open(workDir) 137 c.Assert(err, qt.IsNil) 138 // There is at least one unsupported symlink inside workDir 139 _, err = f.Readdir(-1) 140 c.Assert(err, qt.IsNil) 141 f.Close() 142 c.Assert(logger.LogCounters().WarnCounter.Count(), qt.Equals, uint64(1)) 143 144 } 145 } 146 }