cae36a52 |
1 | #include <u.h> |
2 | #include <libc.h> |
3 | #include <ureg.h> |
4 | #include "dat.h" |
5 | #include "fns.h" |
6 | #include "linux.h" |
7 | |
8 | int |
9 | ufstat(int fd, Ustat *ps) |
10 | { |
11 | Ufile *f; |
12 | int err; |
13 | |
14 | err = -EBADF; |
15 | if((f = fdgetfile(fd)) == nil) |
16 | goto out; |
17 | err = -EPERM; |
18 | if(devtab[f->dev]->fstat == nil) |
19 | goto out; |
20 | memset(ps, 0, sizeof(Ustat)); |
21 | err = devtab[f->dev]->fstat(f, ps); |
22 | out: |
23 | putfile(f); |
24 | return err; |
25 | } |
26 | |
27 | struct linux_stat { |
28 | ushort st_dev; |
29 | ushort __pad1; |
30 | ulong st_ino; |
31 | ushort st_mode; |
32 | ushort st_nlink; |
33 | ushort st_uid; |
34 | ushort st_gid; |
35 | ushort st_rdev; |
36 | ushort __pad2; |
37 | ulong st_size; |
38 | ulong st_blksize; |
39 | ulong st_blocks; |
40 | ulong st_atime; |
41 | ulong __unused1; |
42 | ulong st_mtime; |
43 | ulong __unused2; |
44 | ulong st_ctime; |
45 | ulong __unused3; |
46 | ulong __unused4; |
47 | ulong __unused5; |
48 | }; |
49 | |
50 | static void |
51 | ustat2linuxstat(Ustat *x, struct linux_stat *s) |
52 | { |
53 | memset(s, 0, sizeof(*s)); |
54 | s->st_dev = x->dev; |
55 | s->st_ino = x->ino; |
56 | s->st_mode = x->mode; |
57 | s->st_nlink = 1; |
58 | s->st_uid = x->uid; |
59 | s->st_gid = x->gid; |
60 | s->st_size = x->size; |
61 | s->st_rdev = x->rdev; |
62 | s->st_blksize = 4096; |
63 | s->st_blocks = (x->size+s->st_blksize-1) / s->st_blksize; |
64 | s->st_atime = x->atime; |
65 | s->st_mtime = x->mtime; |
66 | s->st_ctime = x->ctime; |
67 | } |
68 | |
69 | |
70 | struct linux_stat64 { |
71 | uvlong lst_dev; |
72 | uint __pad1; |
73 | uint __lst_ino; |
74 | uint lst_mode; |
75 | uint lst_nlink; |
76 | uint lst_uid; |
77 | uint lst_gid; |
78 | uvlong lst_rdev; |
79 | uint __pad2; |
80 | vlong lst_size; |
81 | uint lst_blksize; |
82 | uvlong lst_blocks; |
83 | uint lst_atime; |
84 | uint lst_atime_nsec; |
85 | uint lst_mtime; |
86 | uint lst_mtime_nsec; |
87 | uint lst_ctime; |
88 | uint lst_ctime_nsec; |
89 | uvlong lst_ino; |
90 | }; |
91 | |
92 | static void |
93 | ustat2linuxstat64(Ustat *x, struct linux_stat64 *s) |
94 | { |
95 | memset(s, 0, sizeof(*s)); |
96 | s->lst_dev = x->dev; |
97 | s->lst_ino = x->ino; |
98 | s->__lst_ino = x->ino & 0xFFFFFFFF; |
99 | s->lst_mode = x->mode; |
100 | s->lst_nlink = 1; |
101 | s->lst_uid = x->uid; |
102 | s->lst_gid = x->gid; |
103 | s->lst_size = x->size; |
104 | s->lst_rdev = x->rdev; |
105 | s->lst_blksize = 4096; // good as any |
106 | s->lst_blocks = (x->size+s->lst_blksize-1) / s->lst_blksize; |
107 | s->lst_atime = x->atime; |
108 | s->lst_mtime = x->mtime; |
109 | s->lst_ctime = x->ctime; |
110 | } |
111 | |
112 | int sys_linux_stat(char *path, void *st) |
113 | { |
114 | int err; |
115 | Ustat x; |
116 | |
117 | trace("sys_linux_stat(%s, %p)", path, st); |
118 | err = fsstat(path, 0, &x); |
119 | if(err < 0) |
120 | return err; |
121 | ustat2linuxstat(&x, (struct linux_stat*)st); |
122 | return err; |
123 | } |
124 | |
125 | int sys_linux_lstat(char *path, void *st) |
126 | { |
127 | int err; |
128 | Ustat x; |
129 | |
130 | trace("sys_linux_lstat(%s, %p)", path, st); |
131 | |
132 | if((path = fsfullpath(path)) == nil) |
133 | return -EFAULT; |
134 | err = fsstat(path, 1, &x); |
135 | free(path); |
136 | |
137 | if(err < 0) |
138 | return err; |
139 | ustat2linuxstat(&x, (struct linux_stat*)st); |
140 | return err; |
141 | } |
142 | |
143 | int sys_linux_stat64(char *path, void *st) |
144 | { |
145 | int err; |
146 | Ustat x; |
147 | |
148 | trace("sys_linux_stat64(%s, %p)", path, st); |
149 | |
150 | if((path = fsfullpath(path)) == nil) |
151 | return -EFAULT; |
152 | err = fsstat(path, 0, &x); |
153 | free(path); |
154 | |
155 | if(err < 0) |
156 | return err; |
157 | ustat2linuxstat64(&x, (struct linux_stat64*)st); |
158 | return err; |
159 | } |
160 | |
161 | int sys_linux_lstat64(char *path, void *st) |
162 | { |
163 | int err; |
164 | Ustat x; |
165 | |
166 | trace("sys_linux_lstat64(%s, %p)", path, st); |
167 | |
168 | if((path = fsfullpath(path)) == nil) |
169 | return -EFAULT; |
170 | err = fsstat(path, 1, &x); |
171 | free(path); |
172 | |
173 | if(err < 0) |
174 | return err; |
175 | ustat2linuxstat64(&x, (struct linux_stat64*)st); |
176 | return err; |
177 | } |
178 | |
179 | int sys_linux_fstat(int fd, void *st) |
180 | { |
181 | int err; |
182 | Ustat x; |
183 | |
184 | trace("sys_linux_fstat(%d, %p)", fd, st); |
185 | |
186 | err = ufstat(fd, &x); |
187 | if(err < 0) |
188 | return err; |
189 | ustat2linuxstat(&x, (struct linux_stat*)st); |
190 | return err; |
191 | } |
192 | |
193 | int sys_linux_fstat64(int fd, void *st) |
194 | { |
195 | int err; |
196 | Ustat x; |
197 | |
198 | trace("sys_linux_fstat64(%d, %p)", fd, st); |
199 | |
200 | err = ufstat(fd, &x); |
201 | if(err < 0) |
202 | return err; |
203 | ustat2linuxstat64(&x, (struct linux_stat64*)st); |
204 | return err; |
205 | } |
206 | |
207 | static int |
208 | getdents(int fd, void *buf, int len, int (*fconv)(Udirent *, void *, int, int)) |
209 | { |
210 | Ufile *f; |
211 | Udirent *t, *x; |
212 | uchar *p, *e; |
213 | int o, r, err; |
214 | |
215 | if((f = fdgetfile(fd)) == nil) |
216 | return -EBADF; |
217 | o = 0; |
218 | p = buf; |
219 | e = p + len; |
220 | t = f->rdaux; |
221 | if(t == nil || f->off == 0){ |
222 | f->rdaux = nil; |
223 | while(x = t){ |
224 | t = t->next; |
225 | free(x); |
226 | } |
227 | if((err = devtab[f->dev]->readdir(f, &t)) <= 0){ |
228 | putfile(f); |
229 | return err; |
230 | } |
231 | f->rdaux = t; |
232 | } |
233 | for(; t; t=t->next){ |
234 | /* just calculate size */ |
235 | r = fconv(t, nil, 0, e - p); |
236 | if(r <= 0) |
237 | break; |
238 | if(o >= f->off){ |
239 | /* convert */ |
240 | f->off = o + r; |
241 | r = fconv(t, p, t->next ? f->off : 0, e - p); |
242 | p += r; |
243 | } |
244 | o += r; |
245 | } |
246 | putfile(f); |
247 | return p - (uchar*)buf; |
248 | } |
249 | |
250 | Udirent* |
251 | newdirent(char *path, char *name, int mode) |
252 | { |
253 | Udirent *d; |
254 | int nlen; |
255 | char *s; |
256 | |
257 | nlen = strlen(name); |
258 | d = kmallocz(sizeof(*d) + nlen + 1, 1); |
259 | d->mode = mode; |
260 | strcpy(d->name, name); |
261 | s = allocpath(path, nil, d->name); |
262 | d->ino = hashpath(s); |
263 | free(s); |
264 | |
265 | return d; |
266 | } |
267 | |
268 | struct linux_dirent { |
269 | long d_ino; |
270 | long d_off; |
271 | ushort d_reclen; |
272 | char d_name[]; |
273 | }; |
274 | |
275 | static int |
276 | udirent2linux(Udirent *u, void *d, int off, int left) |
277 | { |
278 | int n; |
279 | struct linux_dirent *e = d; |
280 | |
281 | n = sizeof(*e) + strlen(u->name) + 1; |
282 | if(n > left) |
283 | return 0; |
284 | if(e){ |
285 | e->d_ino = u->ino & 0xFFFFFFFF; |
286 | e->d_off = off; |
287 | e->d_reclen = n; |
288 | strcpy(e->d_name, u->name); |
289 | } |
290 | return n; |
291 | } |
292 | |
293 | struct linux_dirent64 { |
294 | uvlong d_ino; |
295 | vlong d_off; |
296 | ushort d_reclen; |
297 | uchar d_type; |
298 | char d_name[]; |
299 | }; |
300 | |
301 | static int |
302 | udirent2linux64(Udirent *u, void *d, int off, int left) |
303 | { |
304 | int n; |
305 | struct linux_dirent64 *e = d; |
306 | |
307 | n = sizeof(*e) + strlen(u->name) + 1; |
308 | if(n > left) |
309 | return 0; |
310 | if(e){ |
311 | e->d_ino = u->ino; |
312 | e->d_off = off; |
313 | e->d_reclen = n; |
314 | e->d_type = (u->mode>>12)&15; |
315 | strcpy(e->d_name, u->name); |
316 | } |
317 | return n; |
318 | } |
319 | |
320 | int sys_linux_getdents(int fd, void *buf, int nbuf) |
321 | { |
322 | trace("sys_linux_getdents(%d, %p, %x)", fd, buf, nbuf); |
323 | |
324 | return getdents(fd, buf, nbuf, udirent2linux); |
325 | } |
326 | |
327 | int sys_linux_getdents64(int fd, void *buf, int nbuf) |
328 | { |
329 | trace("sys_linux_getdents64(%d, %p, %x)", fd, buf, nbuf); |
330 | |
331 | return getdents(fd, buf, nbuf, udirent2linux64); |
332 | } |
333 | |
334 | struct linux_statfs { |
335 | long f_type; |
336 | long f_bsize; |
337 | long f_blocks; |
338 | long f_bfree; |
339 | long f_bavail; |
340 | long f_files; |
341 | long f_ffree; |
342 | long f_fsid[2]; |
343 | long f_namelen; |
344 | long f_frsize; |
345 | long f_spare[5]; |
346 | }; |
347 | |
348 | int sys_statfs(char *name, void *pstatfs) |
349 | { |
350 | struct linux_statfs *s = pstatfs; |
351 | |
352 | trace("sys_statfs(%s, %p)", name, s); |
353 | |
354 | if((s == nil) || (name == nil)) |
355 | return -EINVAL; |
356 | |
357 | memset(s, 0, sizeof(*s)); |
358 | |
359 | s->f_namelen = 256; |
360 | s->f_bsize = 4096; |
361 | s->f_blocks = 0x80000000; |
362 | s->f_bavail = s->f_bfree = 0x80000000; |
363 | s->f_files = s->f_ffree = 0x40000000; |
364 | |
365 | if(strncmp(name, "/dev/pts", 8) == 0){ |
366 | s->f_type = 0x1cd1; |
367 | return 0; |
368 | } |
369 | |
370 | memmove(&s->f_type, "PLN9", 4); |
371 | memmove(s->f_fsid, "PLAN9_FS", 8); |
372 | |
373 | return 0; |
374 | } |
375 | |
376 | int |
377 | sys_getxattr(char *path, char *name, void *value, int size) |
378 | { |
379 | trace("sys_getxattr(%s, %s, %p, %x)", path, name, value, size); |
380 | |
381 | return -EOPNOTSUPP; |
382 | } |
383 | |
384 | int |
385 | sys_lgetxattr(char *path, char *name, void *value, int size) |
386 | { |
387 | trace("sys_lgetxattr(%s, %s, %p, %x)", path, name, value, size); |
388 | |
389 | return -EOPNOTSUPP; |
390 | } |
391 | |
392 | int |
393 | sys_fgetxattr(int fd, char *name, void *value, int size) |
394 | { |
395 | Ufile *f; |
396 | int err; |
397 | |
398 | trace("sys_fgetxattr(%d, %s, %p, %x)", fd, name, value, size); |
399 | |
400 | if((f = fdgetfile(fd)) == nil) |
401 | return -EBADF; |
402 | err = -EOPNOTSUPP; |
403 | putfile(f); |
404 | |
405 | return err; |
406 | } |
407 | |
408 | int |
409 | sys_setxattr(char *path, char *name, void *value, int flags, int size) |
410 | { |
411 | trace("sys_setxattr(%s, %s, %p, %x, %x)", path, name, value, flags, size); |
412 | |
413 | return -EOPNOTSUPP; |
414 | } |
415 | |
416 | int |
417 | sys_lsetxattr(char *path, char *name, void *value, int flags, int size) |
418 | { |
419 | trace("sys_lsetxattr(%s, %s, %p, %x, %x)", path, name, value, flags, size); |
420 | |
421 | return -EOPNOTSUPP; |
422 | } |
423 | |
424 | int |
425 | sys_fsetxattr(int fd, char *name, void *value, int size, int flags) |
426 | { |
427 | Ufile *f; |
428 | int err; |
429 | |
430 | trace("sys_fsetxattr(%d, %s, %p, %x, %x)", fd, name, value, flags, size); |
431 | |
432 | if((f = fdgetfile(fd)) == nil) |
433 | return -EBADF; |
434 | err = -EOPNOTSUPP; |
435 | putfile(f); |
436 | return err; |
437 | } |