add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / stat.c
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 }