xref: /inferno-os/emu/port/dynldc.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include	"dat.h"
2 #include	"fns.h"
3 #include	"error.h"
4 #include	<a.out.h>
5 #include	<dynld.h>
6 
7 /*
8  * channel-based kernel interface to dynld, for use by devdynld.c,
9  * libinterp/dlm.c, and possibly others
10  */
11 
12 static long
13 readfc(void *a, void *buf, long nbytes)
14 {
15 	Chan *c = a;
16 
17 	if(waserror())
18 		return -1;
19 	nbytes = devtab[c->type]->read(c, buf, nbytes, c->offset);
20 	poperror();
21 	return nbytes;
22 }
23 
24 static vlong
25 seekfc(void *a, vlong off, int t)
26 {
27 	Chan *c = a;
28 
29 	if(c->qid.type & QTDIR || off < 0)
30 		return -1;	/* won't happen */
31 	switch(t){
32 	case 0:
33 		lock(c);
34 		c->offset = off;
35 		unlock(c);
36 		break;
37 	case 1:
38 		lock(c);
39 		off += c->offset;
40 		c->offset = off;
41 		unlock(c);
42 		break;
43 	case 2:
44 		return -1;	/* not needed */
45 	}
46 	return off;
47 }
48 
49 static void
50 errfc(char *s)
51 {
52 	kstrcpy(up->env->errstr, s, ERRMAX);
53 }
54 
55 Dynobj*
56 kdynloadchan(Chan *c, Dynsym *tab, int ntab)
57 {
58 	return dynloadgen(c, readfc, seekfc, errfc, tab, ntab, 0);
59 }
60 
61 int
62 kdynloadable(Chan *c)
63 {
64 	return dynloadable(c, readfc, seekfc);
65 }
66