xref: /inferno-os/libinterp/readmod.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "isa.h"
3*37da2899SCharles.Forsyth #include "interp.h"
4*37da2899SCharles.Forsyth #include "kernel.h"
5*37da2899SCharles.Forsyth #include "dynld.h"
6*37da2899SCharles.Forsyth 
7*37da2899SCharles.Forsyth Module*
readmod(char * path,Module * m,int sync)8*37da2899SCharles.Forsyth readmod(char *path, Module *m, int sync)
9*37da2899SCharles.Forsyth {
10*37da2899SCharles.Forsyth 	Dir *d;
11*37da2899SCharles.Forsyth 	int fd, n, dynld;
12*37da2899SCharles.Forsyth 	uchar *code;
13*37da2899SCharles.Forsyth 	Module *ans;
14*37da2899SCharles.Forsyth 	ulong length;
15*37da2899SCharles.Forsyth 
16*37da2899SCharles.Forsyth 	if(path[0] == '$') {
17*37da2899SCharles.Forsyth 		if(m == nil)
18*37da2899SCharles.Forsyth 			kwerrstr("module not built-in");
19*37da2899SCharles.Forsyth 		return m;
20*37da2899SCharles.Forsyth 	}
21*37da2899SCharles.Forsyth 
22*37da2899SCharles.Forsyth 	ans = nil;
23*37da2899SCharles.Forsyth 	code = nil;
24*37da2899SCharles.Forsyth 	length = 0;
25*37da2899SCharles.Forsyth 	dynld = 0;
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth 	if(sync)
28*37da2899SCharles.Forsyth 		release();
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth 	d = nil;
31*37da2899SCharles.Forsyth 	fd = kopen(path, OREAD);
32*37da2899SCharles.Forsyth 	if(fd < 0)
33*37da2899SCharles.Forsyth 		goto done;
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth 	if((d = kdirfstat(fd)) == nil)
36*37da2899SCharles.Forsyth 		goto done;
37*37da2899SCharles.Forsyth 
38*37da2899SCharles.Forsyth 	if(m != nil) {
39*37da2899SCharles.Forsyth 		if(d->dev == m->dev && d->type == m->dtype &&
40*37da2899SCharles.Forsyth 		   d->mtime == m->mtime &&
41*37da2899SCharles.Forsyth 		   d->qid.type == m->qid.type && d->qid.path == m->qid.path && d->qid.vers == m->qid.vers) {
42*37da2899SCharles.Forsyth 			ans = m;
43*37da2899SCharles.Forsyth 			goto done;
44*37da2899SCharles.Forsyth 		}
45*37da2899SCharles.Forsyth 	}
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth 	if(d->length < 0 || d->length >= 8*1024*1024){
48*37da2899SCharles.Forsyth 		kwerrstr("implausible length");
49*37da2899SCharles.Forsyth 		goto done;
50*37da2899SCharles.Forsyth 	}
51*37da2899SCharles.Forsyth 	if((d->mode&0111) && dynldable(fd)){
52*37da2899SCharles.Forsyth 		dynld = 1;
53*37da2899SCharles.Forsyth 		goto done1;
54*37da2899SCharles.Forsyth 	}
55*37da2899SCharles.Forsyth 	length = d->length;
56*37da2899SCharles.Forsyth 	code = mallocz(length, 0);
57*37da2899SCharles.Forsyth 	if(code == nil)
58*37da2899SCharles.Forsyth 		goto done;
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth 	n = kread(fd, code, length);
61*37da2899SCharles.Forsyth 	if(n != length) {
62*37da2899SCharles.Forsyth 		free(code);
63*37da2899SCharles.Forsyth 		code = nil;
64*37da2899SCharles.Forsyth 	}
65*37da2899SCharles.Forsyth done:
66*37da2899SCharles.Forsyth 	if(fd >= 0)
67*37da2899SCharles.Forsyth 		kclose(fd);
68*37da2899SCharles.Forsyth done1:
69*37da2899SCharles.Forsyth 	if(sync)
70*37da2899SCharles.Forsyth 		acquire();
71*37da2899SCharles.Forsyth 	if(m != nil && ans == nil)
72*37da2899SCharles.Forsyth 		unload(m);
73*37da2899SCharles.Forsyth 	if(code != nil) {
74*37da2899SCharles.Forsyth 		ans = parsemod(path, code, length, d);
75*37da2899SCharles.Forsyth 		free(code);
76*37da2899SCharles.Forsyth 	}
77*37da2899SCharles.Forsyth 	else if(dynld){
78*37da2899SCharles.Forsyth 		kseek(fd, 0, 0);
79*37da2899SCharles.Forsyth 		ans = newdyncode(fd, path, d);
80*37da2899SCharles.Forsyth 		kclose(fd);
81*37da2899SCharles.Forsyth 	}
82*37da2899SCharles.Forsyth 	free(d);
83*37da2899SCharles.Forsyth 	return ans;
84*37da2899SCharles.Forsyth }
85