memfs - directory_rw.go
1 package memfs
2
3 import (
4 "io/fs"
5 "sync"
6 "time"
7 )
8
9 type dnodeRW struct {
10 dnode
11 mu sync.RWMutex
12 }
13
14 func (d *dnodeRW) open(name string, _ opMode) (fs.File, error) {
15 if d.mode&0o444 == 0 {
16 return nil, fs.ErrPermission
17 }
18
19 return &directoryRW{
20 mu: &d.mu,
21 directory: directory{
22 dnode: &d.dnode,
23 name: name,
24 },
25 }, nil
26 }
27
28 func (d *dnodeRW) getEntry(name string) (*dirEnt, error) {
29 d.mu.RLock()
30 defer d.mu.RUnlock()
31
32 return d.dnode.getEntry(name)
33 }
34
35 func (d *dnodeRW) setEntry(de *dirEnt) error {
36 d.mu.Lock()
37 defer d.mu.Unlock()
38
39 return d.dnode.setEntry(de)
40 }
41
42 func (d *dnodeRW) hasEntries() bool {
43 d.mu.RLock()
44 defer d.mu.RUnlock()
45
46 return d.dnode.hasEntries()
47 }
48
49 func (d *dnodeRW) getEntries() ([]fs.DirEntry, error) {
50 d.mu.RLock()
51 defer d.mu.RUnlock()
52
53 return d.dnode.getEntries()
54 }
55
56 func (d *dnodeRW) removeEntry(name string) error {
57 d.mu.Lock()
58 defer d.mu.Unlock()
59
60 if d.mode&0o222 == 0 {
61 return fs.ErrPermission
62 }
63
64 for n, de := range d.entries {
65 if de.name == name {
66 d.entries = append(d.entries[:n], d.entries[n+1:]...)
67 d.modtime = time.Now()
68
69 return nil
70 }
71 }
72
73 return fs.ErrNotExist
74 }
75
76 func (d *dnodeRW) setMode(mode fs.FileMode) {
77 d.mu.Lock()
78 defer d.mu.Unlock()
79
80 d.mode = fs.ModeDir | mode
81 }
82
83 func (d *dnodeRW) setTimes(_, mtime time.Time) {
84 d.mu.Lock()
85 defer d.mu.Unlock()
86
87 d.modtime = mtime
88 }
89
90 func (d *dnodeRW) seal() directoryEntry {
91 d.mu.Lock()
92 defer d.mu.Unlock()
93
94 de := d.dnode
95
96 for n, e := range de.entries {
97 de.entries[n].directoryEntry = e.seal()
98 }
99
100 d.dnode = dnode{}
101
102 return &de
103 }
104
105 func (d *dnodeRW) Type() fs.FileMode {
106 d.mu.RLock()
107 defer d.mu.RUnlock()
108
109 return d.mode
110 }
111
112 func (d *dnodeRW) Mode() fs.FileMode {
113 d.mu.RLock()
114 defer d.mu.RUnlock()
115
116 return d.mode
117 }
118
119 func (d *dnodeRW) ModTime() time.Time {
120 d.mu.RLock()
121 defer d.mu.RUnlock()
122
123 return d.modtime
124 }
125
126 type directoryRW struct {
127 directory
128 mu *sync.RWMutex
129 }
130
131 func (d *directoryRW) ReadDir(n int) ([]fs.DirEntry, error) {
132 d.mu.Lock()
133 defer d.mu.Unlock()
134
135 return d.directory.ReadDir(n)
136 }
137
138 func (d *directoryRW) Sys() any {
139 return d
140 }
141