Blame


1 be36ff68 2004-04-29 devnull #define _GNU_SOURCE /* for Linux O_DIRECT */
2 b3994ec5 2003-12-11 devnull #include <u.h>
3 8cb7308f 2020-05-18 rsc #include <dirent.h>
4 8cb7308f 2020-05-18 rsc #include <errno.h>
5 e7504005 2004-06-11 devnull #include <sys/file.h>
6 58fdc083 2020-05-18 rsc #include <sys/stat.h>
7 8cb7308f 2020-05-18 rsc #define NOPLAN9DEFINES
8 8cb7308f 2020-05-18 rsc #include <libc.h>
9 b3994ec5 2003-12-11 devnull
10 8cb7308f 2020-05-18 rsc static struct {
11 8cb7308f 2020-05-18 rsc Lock lk;
12 8cb7308f 2020-05-18 rsc DIR **d;
13 8cb7308f 2020-05-18 rsc int nd;
14 8cb7308f 2020-05-18 rsc } dirs;
15 8cb7308f 2020-05-18 rsc
16 8cb7308f 2020-05-18 rsc static int
17 8cb7308f 2020-05-18 rsc dirput(int fd, DIR *d)
18 8cb7308f 2020-05-18 rsc {
19 8cb7308f 2020-05-18 rsc int i, nd;
20 8cb7308f 2020-05-18 rsc DIR **dp;
21 8cb7308f 2020-05-18 rsc
22 8cb7308f 2020-05-18 rsc if(fd < 0) {
23 8cb7308f 2020-05-18 rsc werrstr("invalid fd");
24 8cb7308f 2020-05-18 rsc return -1;
25 8cb7308f 2020-05-18 rsc }
26 8cb7308f 2020-05-18 rsc lock(&dirs.lk);
27 8cb7308f 2020-05-18 rsc if(fd >= dirs.nd) {
28 8cb7308f 2020-05-18 rsc nd = dirs.nd*2;
29 8cb7308f 2020-05-18 rsc if(nd <= fd)
30 8cb7308f 2020-05-18 rsc nd = fd+1;
31 8cb7308f 2020-05-18 rsc dp = realloc(dirs.d, nd*sizeof dirs.d[0]);
32 8cb7308f 2020-05-18 rsc if(dp == nil) {
33 8cb7308f 2020-05-18 rsc werrstr("out of memory");
34 8cb7308f 2020-05-18 rsc unlock(&dirs.lk);
35 8cb7308f 2020-05-18 rsc return -1;
36 8cb7308f 2020-05-18 rsc }
37 8cb7308f 2020-05-18 rsc for(i=dirs.nd; i<nd; i++)
38 8cb7308f 2020-05-18 rsc dp[i] = nil;
39 8cb7308f 2020-05-18 rsc dirs.d = dp;
40 8cb7308f 2020-05-18 rsc dirs.nd = nd;
41 8cb7308f 2020-05-18 rsc }
42 8cb7308f 2020-05-18 rsc dirs.d[fd] = d;
43 8cb7308f 2020-05-18 rsc unlock(&dirs.lk);
44 8cb7308f 2020-05-18 rsc return 0;
45 8cb7308f 2020-05-18 rsc }
46 8cb7308f 2020-05-18 rsc
47 8cb7308f 2020-05-18 rsc static DIR*
48 8cb7308f 2020-05-18 rsc dirget(int fd)
49 8cb7308f 2020-05-18 rsc {
50 8cb7308f 2020-05-18 rsc DIR *d;
51 8cb7308f 2020-05-18 rsc
52 8cb7308f 2020-05-18 rsc lock(&dirs.lk);
53 8cb7308f 2020-05-18 rsc d = nil;
54 8cb7308f 2020-05-18 rsc if(0 <= fd && fd < dirs.nd)
55 8cb7308f 2020-05-18 rsc d = dirs.d[fd];
56 8cb7308f 2020-05-18 rsc unlock(&dirs.lk);
57 8cb7308f 2020-05-18 rsc return d;
58 8cb7308f 2020-05-18 rsc }
59 8cb7308f 2020-05-18 rsc
60 8cb7308f 2020-05-18 rsc static DIR*
61 8cb7308f 2020-05-18 rsc dirdel(int fd)
62 8cb7308f 2020-05-18 rsc {
63 8cb7308f 2020-05-18 rsc DIR *d;
64 8cb7308f 2020-05-18 rsc
65 8cb7308f 2020-05-18 rsc lock(&dirs.lk);
66 8cb7308f 2020-05-18 rsc d = nil;
67 8cb7308f 2020-05-18 rsc if(0 <= fd && fd < dirs.nd) {
68 8cb7308f 2020-05-18 rsc d = dirs.d[fd];
69 8cb7308f 2020-05-18 rsc dirs.d[fd] = nil;
70 8cb7308f 2020-05-18 rsc }
71 8cb7308f 2020-05-18 rsc unlock(&dirs.lk);
72 8cb7308f 2020-05-18 rsc return d;
73 8cb7308f 2020-05-18 rsc }
74 8cb7308f 2020-05-18 rsc
75 b3994ec5 2003-12-11 devnull int
76 58fdc083 2020-05-18 rsc p9create(char *path, int mode, ulong perm)
77 58fdc083 2020-05-18 rsc {
78 58fdc083 2020-05-18 rsc int fd, cexec, umode, rclose, lock, rdwr;
79 58fdc083 2020-05-18 rsc struct flock fl;
80 58fdc083 2020-05-18 rsc
81 58fdc083 2020-05-18 rsc rdwr = mode&3;
82 58fdc083 2020-05-18 rsc lock = mode&OLOCK;
83 58fdc083 2020-05-18 rsc cexec = mode&OCEXEC;
84 58fdc083 2020-05-18 rsc rclose = mode&ORCLOSE;
85 58fdc083 2020-05-18 rsc mode &= ~(ORCLOSE|OCEXEC|OLOCK);
86 58fdc083 2020-05-18 rsc
87 58fdc083 2020-05-18 rsc /* XXX should get mode mask right? */
88 58fdc083 2020-05-18 rsc fd = -1;
89 58fdc083 2020-05-18 rsc if(perm&DMDIR){
90 58fdc083 2020-05-18 rsc if(mode != OREAD){
91 58fdc083 2020-05-18 rsc werrstr("bad mode in directory create");
92 58fdc083 2020-05-18 rsc goto out;
93 58fdc083 2020-05-18 rsc }
94 58fdc083 2020-05-18 rsc if(mkdir(path, perm&0777) < 0)
95 58fdc083 2020-05-18 rsc goto out;
96 58fdc083 2020-05-18 rsc fd = open(path, O_RDONLY);
97 58fdc083 2020-05-18 rsc }else{
98 58fdc083 2020-05-18 rsc umode = (mode&3)|O_CREAT|O_TRUNC;
99 58fdc083 2020-05-18 rsc mode &= ~(3|OTRUNC);
100 58fdc083 2020-05-18 rsc if(mode&ODIRECT){
101 58fdc083 2020-05-18 rsc umode |= O_DIRECT;
102 58fdc083 2020-05-18 rsc mode &= ~ODIRECT;
103 58fdc083 2020-05-18 rsc }
104 58fdc083 2020-05-18 rsc if(mode&OEXCL){
105 58fdc083 2020-05-18 rsc umode |= O_EXCL;
106 58fdc083 2020-05-18 rsc mode &= ~OEXCL;
107 58fdc083 2020-05-18 rsc }
108 58fdc083 2020-05-18 rsc if(mode&OAPPEND){
109 58fdc083 2020-05-18 rsc umode |= O_APPEND;
110 58fdc083 2020-05-18 rsc mode &= ~OAPPEND;
111 58fdc083 2020-05-18 rsc }
112 58fdc083 2020-05-18 rsc if(mode){
113 58fdc083 2020-05-18 rsc werrstr("unsupported mode in create");
114 58fdc083 2020-05-18 rsc goto out;
115 58fdc083 2020-05-18 rsc }
116 58fdc083 2020-05-18 rsc fd = open(path, umode, perm);
117 58fdc083 2020-05-18 rsc }
118 58fdc083 2020-05-18 rsc out:
119 58fdc083 2020-05-18 rsc if(fd >= 0){
120 58fdc083 2020-05-18 rsc if(lock){
121 58fdc083 2020-05-18 rsc fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
122 58fdc083 2020-05-18 rsc fl.l_whence = SEEK_SET;
123 58fdc083 2020-05-18 rsc fl.l_start = 0;
124 58fdc083 2020-05-18 rsc fl.l_len = 0;
125 58fdc083 2020-05-18 rsc if(fcntl(fd, F_SETLK, &fl) < 0){
126 58fdc083 2020-05-18 rsc close(fd);
127 58fdc083 2020-05-18 rsc werrstr("lock: %r");
128 58fdc083 2020-05-18 rsc return -1;
129 58fdc083 2020-05-18 rsc }
130 58fdc083 2020-05-18 rsc }
131 58fdc083 2020-05-18 rsc if(cexec)
132 58fdc083 2020-05-18 rsc fcntl(fd, F_SETFL, FD_CLOEXEC);
133 58fdc083 2020-05-18 rsc if(rclose)
134 58fdc083 2020-05-18 rsc remove(path);
135 58fdc083 2020-05-18 rsc }
136 58fdc083 2020-05-18 rsc return fd;
137 58fdc083 2020-05-18 rsc }
138 58fdc083 2020-05-18 rsc
139 58fdc083 2020-05-18 rsc int
140 8ad51794 2004-03-25 devnull p9open(char *name, int mode)
141 b3994ec5 2003-12-11 devnull {
142 b3994ec5 2003-12-11 devnull int cexec, rclose;
143 d9e16d25 2004-06-11 devnull int fd, umode, lock, rdwr;
144 c71af67a 2005-01-07 devnull struct flock fl;
145 8cb7308f 2020-05-18 rsc struct stat st;
146 8cb7308f 2020-05-18 rsc DIR *d;
147 b3994ec5 2003-12-11 devnull
148 d9e16d25 2004-06-11 devnull rdwr = mode&3;
149 d9e16d25 2004-06-11 devnull umode = rdwr;
150 b3994ec5 2003-12-11 devnull cexec = mode&OCEXEC;
151 b3994ec5 2003-12-11 devnull rclose = mode&ORCLOSE;
152 e7504005 2004-06-11 devnull lock = mode&OLOCK;
153 e7504005 2004-06-11 devnull mode &= ~(3|OCEXEC|ORCLOSE|OLOCK);
154 b3994ec5 2003-12-11 devnull if(mode&OTRUNC){
155 b3994ec5 2003-12-11 devnull umode |= O_TRUNC;
156 b3994ec5 2003-12-11 devnull mode ^= OTRUNC;
157 b3994ec5 2003-12-11 devnull }
158 be36ff68 2004-04-29 devnull if(mode&ODIRECT){
159 be36ff68 2004-04-29 devnull umode |= O_DIRECT;
160 be36ff68 2004-04-29 devnull mode ^= ODIRECT;
161 be36ff68 2004-04-29 devnull }
162 a19ff5b2 2005-01-07 devnull if(mode&ONONBLOCK){
163 a19ff5b2 2005-01-07 devnull umode |= O_NONBLOCK;
164 a19ff5b2 2005-01-07 devnull mode ^= ONONBLOCK;
165 a19ff5b2 2005-01-07 devnull }
166 b589fce2 2005-02-11 devnull if(mode&OAPPEND){
167 b589fce2 2005-02-11 devnull umode |= O_APPEND;
168 b589fce2 2005-02-11 devnull mode ^= OAPPEND;
169 b589fce2 2005-02-11 devnull }
170 b3994ec5 2003-12-11 devnull if(mode){
171 debcecb5 2004-05-14 devnull werrstr("mode 0x%x not supported", mode);
172 b3994ec5 2003-12-11 devnull return -1;
173 b3994ec5 2003-12-11 devnull }
174 b3994ec5 2003-12-11 devnull fd = open(name, umode);
175 b3994ec5 2003-12-11 devnull if(fd >= 0){
176 e7504005 2004-06-11 devnull if(lock){
177 c71af67a 2005-01-07 devnull fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
178 c71af67a 2005-01-07 devnull fl.l_whence = SEEK_SET;
179 c71af67a 2005-01-07 devnull fl.l_start = 0;
180 c71af67a 2005-01-07 devnull fl.l_len = 0;
181 c71af67a 2005-01-07 devnull if(fcntl(fd, F_SETLK, &fl) < 0){
182 e7504005 2004-06-11 devnull close(fd);
183 915734a7 2005-03-18 devnull werrstr("lock: %r");
184 e7504005 2004-06-11 devnull return -1;
185 e7504005 2004-06-11 devnull }
186 e7504005 2004-06-11 devnull }
187 b3994ec5 2003-12-11 devnull if(cexec)
188 b3994ec5 2003-12-11 devnull fcntl(fd, F_SETFL, FD_CLOEXEC);
189 8cb7308f 2020-05-18 rsc if(fstat(fd, &st) >= 0 && S_ISDIR(st.st_mode)) {
190 8cb7308f 2020-05-18 rsc d = fdopendir(fd);
191 8cb7308f 2020-05-18 rsc if(d == nil) {
192 8cb7308f 2020-05-18 rsc close(fd);
193 8cb7308f 2020-05-18 rsc return -1;
194 8cb7308f 2020-05-18 rsc }
195 8cb7308f 2020-05-18 rsc if(dirput(fd, d) < 0) {
196 8cb7308f 2020-05-18 rsc closedir(d);
197 8cb7308f 2020-05-18 rsc return -1;
198 8cb7308f 2020-05-18 rsc }
199 8cb7308f 2020-05-18 rsc }
200 b3994ec5 2003-12-11 devnull if(rclose)
201 b3994ec5 2003-12-11 devnull remove(name);
202 b3994ec5 2003-12-11 devnull }
203 b3994ec5 2003-12-11 devnull return fd;
204 b3994ec5 2003-12-11 devnull }
205 58fdc083 2020-05-18 rsc
206 16f60479 2020-05-18 rsc vlong
207 16f60479 2020-05-18 rsc p9seek(int fd, vlong offset, int whence)
208 16f60479 2020-05-18 rsc {
209 8cb7308f 2020-05-18 rsc DIR *d;
210 8cb7308f 2020-05-18 rsc
211 8cb7308f 2020-05-18 rsc if((d = dirget(fd)) != nil) {
212 8cb7308f 2020-05-18 rsc if(whence == 1 && offset == 0)
213 8cb7308f 2020-05-18 rsc return telldir(d);
214 8cb7308f 2020-05-18 rsc if(whence == 0) {
215 8cb7308f 2020-05-18 rsc seekdir(d, offset);
216 8cb7308f 2020-05-18 rsc return 0;
217 8cb7308f 2020-05-18 rsc }
218 8cb7308f 2020-05-18 rsc werrstr("bad seek in directory");
219 8cb7308f 2020-05-18 rsc return -1;
220 8cb7308f 2020-05-18 rsc }
221 8cb7308f 2020-05-18 rsc
222 16f60479 2020-05-18 rsc return lseek(fd, offset, whence);
223 16f60479 2020-05-18 rsc }
224 16f60479 2020-05-18 rsc
225 6fd4e901 2020-05-18 rsc int
226 6fd4e901 2020-05-18 rsc p9close(int fd)
227 6fd4e901 2020-05-18 rsc {
228 8cb7308f 2020-05-18 rsc DIR *d;
229 8cb7308f 2020-05-18 rsc
230 8cb7308f 2020-05-18 rsc if((d = dirdel(fd)) != nil)
231 8cb7308f 2020-05-18 rsc return closedir(d);
232 6fd4e901 2020-05-18 rsc return close(fd);
233 6fd4e901 2020-05-18 rsc }
234 6fd4e901 2020-05-18 rsc
235 8cb7308f 2020-05-18 rsc typedef struct DirBuild DirBuild;
236 8cb7308f 2020-05-18 rsc struct DirBuild {
237 8cb7308f 2020-05-18 rsc Dir *d;
238 8cb7308f 2020-05-18 rsc int nd;
239 8cb7308f 2020-05-18 rsc int md;
240 8cb7308f 2020-05-18 rsc char *str;
241 8cb7308f 2020-05-18 rsc char *estr;
242 8cb7308f 2020-05-18 rsc };
243 8cb7308f 2020-05-18 rsc
244 58fdc083 2020-05-18 rsc extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);
245 58fdc083 2020-05-18 rsc
246 58fdc083 2020-05-18 rsc static int
247 8cb7308f 2020-05-18 rsc dirbuild1(DirBuild *b, struct stat *lst, struct stat *st, char *name)
248 58fdc083 2020-05-18 rsc {
249 8cb7308f 2020-05-18 rsc int i, nstr;
250 8cb7308f 2020-05-18 rsc Dir *d;
251 8cb7308f 2020-05-18 rsc int md, mstr;
252 8cb7308f 2020-05-18 rsc char *lo, *hi, *newlo;
253 58fdc083 2020-05-18 rsc
254 8cb7308f 2020-05-18 rsc nstr = _p9dir(lst, st, name, nil, nil, nil);
255 8cb7308f 2020-05-18 rsc if(b->md-b->nd < 1 || b->estr-b->str < nstr) {
256 8cb7308f 2020-05-18 rsc // expand either d space or str space or both.
257 8cb7308f 2020-05-18 rsc md = b->md;
258 8cb7308f 2020-05-18 rsc if(b->md-b->nd < 1) {
259 8cb7308f 2020-05-18 rsc md *= 2;
260 8cb7308f 2020-05-18 rsc if(md < 16)
261 8cb7308f 2020-05-18 rsc md = 16;
262 8cb7308f 2020-05-18 rsc }
263 8cb7308f 2020-05-18 rsc mstr = b->estr-(char*)&b->d[b->md];
264 8cb7308f 2020-05-18 rsc if(b->estr-b->str < nstr) {
265 8cb7308f 2020-05-18 rsc mstr += nstr;
266 8cb7308f 2020-05-18 rsc mstr += mstr/2;
267 8cb7308f 2020-05-18 rsc }
268 8cb7308f 2020-05-18 rsc if(mstr < 512)
269 8cb7308f 2020-05-18 rsc mstr = 512;
270 8cb7308f 2020-05-18 rsc d = realloc(b->d, md*sizeof d[0] + mstr);
271 8cb7308f 2020-05-18 rsc if(d == nil)
272 8cb7308f 2020-05-18 rsc return -1;
273 8cb7308f 2020-05-18 rsc // move strings and update pointers in Dirs
274 8cb7308f 2020-05-18 rsc lo = (char*)&b->d[b->md];
275 8cb7308f 2020-05-18 rsc newlo = (char*)&d[md];
276 8cb7308f 2020-05-18 rsc hi = b->str;
277 8cb7308f 2020-05-18 rsc memmove(newlo, lo+((char*)d-(char*)b->d), hi-lo);
278 8cb7308f 2020-05-18 rsc for(i=0; i<b->nd; i++) {
279 8cb7308f 2020-05-18 rsc if(lo <= d[i].name && d[i].name < hi)
280 8cb7308f 2020-05-18 rsc d[i].name += newlo - lo;
281 8cb7308f 2020-05-18 rsc if(lo <= d[i].uid && d[i].uid < hi)
282 8cb7308f 2020-05-18 rsc d[i].uid += newlo - lo;
283 8cb7308f 2020-05-18 rsc if(lo <= d[i].gid && d[i].gid < hi)
284 8cb7308f 2020-05-18 rsc d[i].gid += newlo - lo;
285 8cb7308f 2020-05-18 rsc if(lo <= d[i].muid && d[i].muid < hi)
286 8cb7308f 2020-05-18 rsc d[i].muid += newlo - lo;
287 8cb7308f 2020-05-18 rsc }
288 8cb7308f 2020-05-18 rsc b->d = d;
289 8cb7308f 2020-05-18 rsc b->md = md;
290 8cb7308f 2020-05-18 rsc b->str += newlo - lo;
291 8cb7308f 2020-05-18 rsc b->estr = newlo + mstr;
292 58fdc083 2020-05-18 rsc }
293 8cb7308f 2020-05-18 rsc _p9dir(lst, st, name, &b->d[b->nd], &b->str, b->estr);
294 8cb7308f 2020-05-18 rsc b->nd++;
295 8cb7308f 2020-05-18 rsc return 0;
296 58fdc083 2020-05-18 rsc }
297 58fdc083 2020-05-18 rsc
298 8cb7308f 2020-05-18 rsc static long
299 8cb7308f 2020-05-18 rsc dirreadmax(int fd, Dir **dp, int max)
300 58fdc083 2020-05-18 rsc {
301 8cb7308f 2020-05-18 rsc int i;
302 8cb7308f 2020-05-18 rsc DIR *dir;
303 8cb7308f 2020-05-18 rsc DirBuild b;
304 58fdc083 2020-05-18 rsc struct dirent *de;
305 58fdc083 2020-05-18 rsc struct stat st, lst;
306 58fdc083 2020-05-18 rsc
307 8cb7308f 2020-05-18 rsc if((dir = dirget(fd)) == nil) {
308 8cb7308f 2020-05-18 rsc werrstr("not a directory");
309 58fdc083 2020-05-18 rsc return -1;
310 58fdc083 2020-05-18 rsc }
311 58fdc083 2020-05-18 rsc
312 8cb7308f 2020-05-18 rsc memset(&b, 0, sizeof b);
313 8cb7308f 2020-05-18 rsc for(i=0; max == -1 || i<max; i++) { // max = not too many, not too few
314 8cb7308f 2020-05-18 rsc errno = 0;
315 8cb7308f 2020-05-18 rsc de = readdir(dir);
316 8cb7308f 2020-05-18 rsc if(de == nil) {
317 8cb7308f 2020-05-18 rsc if(b.nd == 0 && errno != 0)
318 8cb7308f 2020-05-18 rsc return -1;
319 8cb7308f 2020-05-18 rsc break;
320 58fdc083 2020-05-18 rsc }
321 c53ad837 2020-05-18 rsc // Note: not all systems have d_namlen. Assume NUL-terminated.
322 8cb7308f 2020-05-18 rsc if(de->d_name[0]=='.' && de->d_name[1]==0)
323 8cb7308f 2020-05-18 rsc continue;
324 8cb7308f 2020-05-18 rsc if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)
325 8cb7308f 2020-05-18 rsc continue;
326 8cb7308f 2020-05-18 rsc if(fstatat(fd, de->d_name, &lst, AT_SYMLINK_NOFOLLOW) < 0)
327 8cb7308f 2020-05-18 rsc continue;
328 8cb7308f 2020-05-18 rsc st = lst;
329 8cb7308f 2020-05-18 rsc if(S_ISLNK(lst.st_mode))
330 8cb7308f 2020-05-18 rsc fstatat(fd, de->d_name, &st, 0);
331 8cb7308f 2020-05-18 rsc dirbuild1(&b, &lst, &st, de->d_name);
332 58fdc083 2020-05-18 rsc }
333 8cb7308f 2020-05-18 rsc *dp = b.d;
334 8cb7308f 2020-05-18 rsc return b.nd;
335 58fdc083 2020-05-18 rsc }
336 58fdc083 2020-05-18 rsc
337 58fdc083 2020-05-18 rsc long
338 58fdc083 2020-05-18 rsc dirread(int fd, Dir **dp)
339 58fdc083 2020-05-18 rsc {
340 8cb7308f 2020-05-18 rsc return dirreadmax(fd, dp, 10);
341 58fdc083 2020-05-18 rsc }
342 58fdc083 2020-05-18 rsc
343 58fdc083 2020-05-18 rsc long
344 8cb7308f 2020-05-18 rsc dirreadall(int fd, Dir **dp)
345 58fdc083 2020-05-18 rsc {
346 8cb7308f 2020-05-18 rsc return dirreadmax(fd, dp, -1);
347 58fdc083 2020-05-18 rsc }