1 package writefs
2
3 import (
4 "errors"
5 "fmt"
6 "io/fs"
7 "log"
8 "os"
9 "path"
10 "syscall"
11 "time"
12 )
13
14 func Main() {
15
16 dir := path.Join(os.TempDir(), "dir")
17 dir1 := path.Join(os.TempDir(), "dir1")
18 if err := os.Mkdir(dir, 0o700); err != nil {
19 log.Panicln(err)
20 return
21 }
22 defer os.Remove(dir)
23
24
25 file := path.Join(dir, "file")
26 file1 := path.Join(os.TempDir(), "file1")
27
28 if err := os.WriteFile(file, []byte{}, 0o600); err != nil {
29 log.Panicln(err)
30 return
31 }
32 defer os.Remove(file)
33
34
35 for _, path := range []string{dir, file} {
36 if stat, err := os.Stat(path); err != nil {
37 log.Panicln(err)
38 } else {
39 fmt.Println(path, "mode", stat.Mode())
40 }
41 }
42
43
44 f, err := os.OpenFile(file1, os.O_RDWR|os.O_CREATE, 0o600)
45 if err != nil {
46 log.Panicln(err)
47 }
48 defer f.Close()
49
50
51 bytes := []byte("wazero")
52 for o, b := range map[int][]byte{3: bytes[3:], 0: bytes[:3]} {
53 n, err := f.WriteAt(b, int64(o))
54 if err != nil {
55 log.Panicln(err)
56 } else if n != 3 {
57 log.Panicln("expected 3, but wrote", n)
58 }
59 }
60
61
62 if _, err = f.ReadAt(bytes, 0); err != nil {
63 log.Panicln(err)
64 } else if string(bytes) != "wazero" {
65 log.Panicln("unexpected contents:", string(bytes))
66 }
67
68
69 if err = f.Truncate(2); err != nil {
70 log.Panicln(err)
71 }
72
73 if err = f.Sync(); err != nil {
74 log.Panicln(err)
75 }
76
77 if stat, err := f.Stat(); err != nil {
78 log.Panicln(err)
79 } else if mode := stat.Mode() & fs.ModePerm; mode != 0o600 {
80 log.Panicln("expected mode = 0o600", mode)
81 }
82
83
84 if err = f.Close(); err != nil {
85 log.Panicln(err)
86 }
87
88
89 if err = syscall.Chmod(file1, 0o400); err != nil {
90 log.Panicln(err)
91 }
92
93
94 stat, err := os.Stat(file1)
95 if err != nil {
96 log.Panicln(err)
97 }
98
99 if stat.Mode().Type() != 0 {
100 log.Panicln("expected type = 0", stat.Mode().Type())
101 }
102 if stat.Mode().Perm() != 0o400 {
103 log.Panicln("expected perm = 0o400", stat.Mode().Perm())
104 }
105
106
107 if bytes, err := os.ReadFile(file1); err != nil {
108 log.Panicln(err)
109 } else if string(bytes) != "wa" {
110 log.Panicln("unexpected contents:", string(bytes))
111 }
112
113
114 link := file1 + "-link"
115 if err = os.Link(file1, link); err != nil {
116 log.Panicln(err)
117 }
118
119
120 file1Stat, err := os.Lstat(file1)
121 if err != nil {
122 log.Panicln(err)
123 }
124 linkStat, err := os.Lstat(link)
125 if err != nil {
126 log.Panicln(err)
127 }
128 if !os.SameFile(file1Stat, linkStat) {
129 log.Panicln("expected file == link stat", file1Stat, linkStat)
130 }
131
132
133 symlink := file1 + "-symlink"
134 if err = os.Symlink(file1, symlink); err != nil {
135 log.Panicln(err)
136 }
137
138
139 if dst, err := os.Readlink(symlink); err != nil {
140 log.Panicln(err)
141 } else if dst != dst {
142 log.Panicln("expected link dst = old value", dst, dst)
143 }
144
145
146 symlinkStat, err := os.Lstat(symlink)
147 if err != nil {
148 log.Panicln(err)
149 }
150
151 if symlinkStat.Mode().Type() != fs.ModeSymlink {
152 log.Panicln("expected type = symlink", symlinkStat.Mode().Type())
153 }
154 if size := int64(len(file1)); symlinkStat.Size() != size {
155 log.Panicln("unexpected symlink size", symlinkStat.Size(), size)
156 }
157
158 if os.SameFile(file1Stat, symlinkStat) {
159 log.Panicln("expected file != link stat", file1Stat, symlinkStat)
160 }
161
162
163 if err = syscall.Rmdir(dir); err != syscall.ENOTEMPTY {
164 log.Panicln("unexpected error", err)
165 }
166
167
168 atime := time.Unix(123, 4*1e6)
169 mtime := time.Unix(567, 8*1e6)
170
171
172 if err = os.Chtimes("noexist", atime, mtime); !errors.Is(err, syscall.ENOENT) {
173 log.Panicln("unexpected error", err)
174 }
175
176
177 if err = os.Chtimes(dir, atime, mtime); err != nil {
178 log.Panicln("unexpected error", err)
179 }
180
181
182 dirAtimeNsec, dirMtimeNsec, dirDev, dirInode := statFields(dir)
183 fmt.Println("dir times:", dirAtimeNsec, dirMtimeNsec)
184
185
186
187
188
189 if dirDev == 0 {
190 log.Panicln("expected dir dev != 0", dirDev)
191 }
192 if dirInode == 0 {
193 log.Panicln("expected dir inode != 0", dirInode)
194 }
195
196
197
198 if err = syscall.Rename(file, dir); err == nil {
199 log.Panicln("expected error")
200 }
201 if err = syscall.Rename(file, file1); err != nil {
202 log.Panicln("unexpected error", err)
203 }
204
205
206 if err = syscall.Rename(dir, file1); err == nil {
207 log.Panicln("expected error")
208 }
209 if err = syscall.Rename(dir, dir1); err != nil {
210 log.Panicln("unexpected error", err)
211 }
212
213
214 atimeNsec, mtimeNsec, dev, inode := statFields(dir1)
215
216 if atimeNsec != dirAtimeNsec {
217 log.Panicln("expected dir atimeNsec = previous value", atimeNsec, dirAtimeNsec)
218 }
219
220 if mtimeNsec <= dirMtimeNsec {
221 log.Panicln("expected dir mtimeNsec > previous value", mtimeNsec, dirMtimeNsec)
222 }
223
224 if dev != dirDev {
225 log.Panicln("expected dir dev = previous value", dev, dirDev)
226 }
227 if inode != dirInode {
228 log.Panicln("expected dir inode = previous value", dev, dirInode)
229 }
230
231
232 if err = syscall.Rmdir(file1); err != syscall.ENOTDIR {
233 log.Panicln("unexpected error", err)
234 }
235 if err = syscall.Unlink(file1); err != nil {
236 log.Panicln("unexpected error", err)
237 }
238
239
240 if err = syscall.Unlink(dir1); err != syscall.EISDIR {
241 log.Panicln("unexpected error", err)
242 }
243 if err = syscall.Rmdir(dir1); err != nil {
244 log.Panicln("unexpected error", err)
245 }
246
247
248 if err = os.RemoveAll(dir1); err != nil {
249 log.Panicln(err)
250 return
251 }
252
253
254 if err = os.Mkdir(dir1, 0); err != nil {
255 log.Panicln(err)
256 return
257 }
258 defer os.Remove(dir)
259
260
261 s := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
262 from := "/symlink.txt"
263 err = os.Symlink(s, from)
264 if err != nil {
265 log.Panicln(err)
266 }
267
268 r, err := os.Readlink(from)
269 if err != nil {
270 log.Fatalf("readlink %q failed: %v", from, err)
271 }
272 if r != s {
273 log.Fatalf("after symlink %q != %q", r, s)
274 }
275 }
276
View as plain text