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 }