Source file
src/os/root_noopenat.go
1
2
3
4
5
6
7 package os
8
9 import (
10 "errors"
11 "sync/atomic"
12 "time"
13 )
14
15
16
17 type root struct {
18 name string
19 closed atomic.Bool
20 }
21
22
23 func openRootNolog(name string) (*Root, error) {
24 r, err := newRoot(name)
25 if err != nil {
26 return nil, &PathError{Op: "open", Path: name, Err: err}
27 }
28 return r, nil
29 }
30
31
32 func openRootInRoot(r *Root, name string) (*Root, error) {
33 if err := checkPathEscapes(r, name); err != nil {
34 return nil, &PathError{Op: "openat", Path: name, Err: err}
35 }
36 r, err := newRoot(joinPath(r.root.name, name))
37 if err != nil {
38 return nil, &PathError{Op: "openat", Path: name, Err: err}
39 }
40 return r, nil
41 }
42
43
44
45 func newRoot(name string) (*Root, error) {
46 fi, err := Stat(name)
47 if err != nil {
48 return nil, err.(*PathError).Err
49 }
50 if !fi.IsDir() {
51 return nil, errors.New("not a directory")
52 }
53 return &Root{&root{name: name}}, nil
54 }
55
56 func (r *root) Close() error {
57
58
59 r.closed.Store(true)
60 return nil
61 }
62
63 func (r *root) Name() string {
64 return r.name
65 }
66
67
68 func rootOpenFileNolog(r *Root, name string, flag int, perm FileMode) (*File, error) {
69 if err := checkPathEscapes(r, name); err != nil {
70 return nil, &PathError{Op: "openat", Path: name, Err: err}
71 }
72 f, err := openFileNolog(joinPath(r.root.name, name), flag, perm)
73 if err != nil {
74 return nil, &PathError{Op: "openat", Path: name, Err: underlyingError(err)}
75 }
76 return f, nil
77 }
78
79 func rootStat(r *Root, name string, lstat bool) (FileInfo, error) {
80 var fi FileInfo
81 var err error
82 if lstat {
83 err = checkPathEscapesLstat(r, name)
84 if err == nil {
85 fi, err = Lstat(joinPath(r.root.name, name))
86 }
87 } else {
88 err = checkPathEscapes(r, name)
89 if err == nil {
90 fi, err = Stat(joinPath(r.root.name, name))
91 }
92 }
93 if err != nil {
94 return nil, &PathError{Op: "statat", Path: name, Err: underlyingError(err)}
95 }
96 return fi, nil
97 }
98
99 func rootChmod(r *Root, name string, mode FileMode) error {
100 if err := checkPathEscapes(r, name); err != nil {
101 return &PathError{Op: "chmodat", Path: name, Err: err}
102 }
103 if err := Chmod(joinPath(r.root.name, name), mode); err != nil {
104 return &PathError{Op: "chmodat", Path: name, Err: underlyingError(err)}
105 }
106 return nil
107 }
108
109 func rootChown(r *Root, name string, uid, gid int) error {
110 if err := checkPathEscapes(r, name); err != nil {
111 return &PathError{Op: "chownat", Path: name, Err: err}
112 }
113 if err := Chown(joinPath(r.root.name, name), uid, gid); err != nil {
114 return &PathError{Op: "chownat", Path: name, Err: underlyingError(err)}
115 }
116 return nil
117 }
118
119 func rootLchown(r *Root, name string, uid, gid int) error {
120 if err := checkPathEscapesLstat(r, name); err != nil {
121 return &PathError{Op: "lchownat", Path: name, Err: err}
122 }
123 if err := Lchown(joinPath(r.root.name, name), uid, gid); err != nil {
124 return &PathError{Op: "lchownat", Path: name, Err: underlyingError(err)}
125 }
126 return nil
127 }
128
129 func rootChtimes(r *Root, name string, atime time.Time, mtime time.Time) error {
130 if err := checkPathEscapes(r, name); err != nil {
131 return &PathError{Op: "chtimesat", Path: name, Err: err}
132 }
133 if err := Chtimes(joinPath(r.root.name, name), atime, mtime); err != nil {
134 return &PathError{Op: "chtimesat", Path: name, Err: underlyingError(err)}
135 }
136 return nil
137 }
138
139 func rootMkdir(r *Root, name string, perm FileMode) error {
140 if err := checkPathEscapes(r, name); err != nil {
141 return &PathError{Op: "mkdirat", Path: name, Err: err}
142 }
143 if err := Mkdir(joinPath(r.root.name, name), perm); err != nil {
144 return &PathError{Op: "mkdirat", Path: name, Err: underlyingError(err)}
145 }
146 return nil
147 }
148
149 func rootRemove(r *Root, name string) error {
150 if err := checkPathEscapesLstat(r, name); err != nil {
151 return &PathError{Op: "removeat", Path: name, Err: err}
152 }
153 if err := Remove(joinPath(r.root.name, name)); err != nil {
154 return &PathError{Op: "removeat", Path: name, Err: underlyingError(err)}
155 }
156 return nil
157 }
158
159 func rootReadlink(r *Root, name string) (string, error) {
160 if err := checkPathEscapesLstat(r, name); err != nil {
161 return "", &PathError{Op: "readlinkat", Path: name, Err: err}
162 }
163 name, err := Readlink(joinPath(r.root.name, name))
164 if err != nil {
165 return "", &PathError{Op: "readlinkat", Path: name, Err: underlyingError(err)}
166 }
167 return name, nil
168 }
169
170 func rootRename(r *Root, oldname, newname string) error {
171 if err := checkPathEscapesLstat(r, oldname); err != nil {
172 return &PathError{Op: "renameat", Path: oldname, Err: err}
173 }
174 if err := checkPathEscapesLstat(r, newname); err != nil {
175 return &PathError{Op: "renameat", Path: newname, Err: err}
176 }
177 err := Rename(joinPath(r.root.name, oldname), joinPath(r.root.name, newname))
178 if err != nil {
179 return &LinkError{"renameat", oldname, newname, underlyingError(err)}
180 }
181 return nil
182 }
183
184 func rootLink(r *Root, oldname, newname string) error {
185 if err := checkPathEscapesLstat(r, oldname); err != nil {
186 return &PathError{Op: "linkat", Path: oldname, Err: err}
187 }
188 fullOldName := joinPath(r.root.name, oldname)
189 if fs, err := Lstat(fullOldName); err == nil && fs.Mode()&ModeSymlink != 0 {
190 return &PathError{Op: "linkat", Path: oldname, Err: errors.New("cannot create a hard link to a symlink")}
191 }
192 if err := checkPathEscapesLstat(r, newname); err != nil {
193 return &PathError{Op: "linkat", Path: newname, Err: err}
194 }
195 err := Link(fullOldName, joinPath(r.root.name, newname))
196 if err != nil {
197 return &LinkError{"linkat", oldname, newname, underlyingError(err)}
198 }
199 return nil
200 }
201
202 func rootSymlink(r *Root, oldname, newname string) error {
203 if err := checkPathEscapesLstat(r, newname); err != nil {
204 return &PathError{Op: "symlinkat", Path: newname, Err: err}
205 }
206 err := Symlink(oldname, joinPath(r.root.name, newname))
207 if err != nil {
208 return &LinkError{"symlinkat", oldname, newname, underlyingError(err)}
209 }
210 return nil
211 }
212
View as plain text