add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / stat.c
CommitLineData
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
8int
9ufstat(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);
22out:
23 putfile(f);
24 return err;
25}
26
27struct 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
50static void
51ustat2linuxstat(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
70struct 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
92static void
93ustat2linuxstat64(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
112int 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
125int 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
143int 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
161int 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
179int 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
193int 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
207static int
208getdents(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
250Udirent*
251newdirent(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
268struct linux_dirent {
269 long d_ino;
270 long d_off;
271 ushort d_reclen;
272 char d_name[];
273};
274
275static int
276udirent2linux(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
293struct linux_dirent64 {
294 uvlong d_ino;
295 vlong d_off;
296 ushort d_reclen;
297 uchar d_type;
298 char d_name[];
299};
300
301static int
302udirent2linux64(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
320int 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
327int 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
334struct 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
348int 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
376int
377sys_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
384int
385sys_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
392int
393sys_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
408int
409sys_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
416int
417sys_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
424int
425sys_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}