]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/archfs.c
devpccard, pci: fix pccard support and handle pci expansion roms
[plan9front.git] / sys / src / cmd / archfs.c
1 /*
2  * archfs - mount mkfs style archives
3  */
4
5 #include <u.h>
6 #include <libc.h>
7 #include <bio.h>
8 #include <auth.h>
9 #include <fcall.h>
10 #include <thread.h>
11 #include <9p.h>
12
13 Tree *archtree;
14 Biobuf *b;
15 int verbose;
16
17 typedef struct Ahdr Ahdr;
18 struct Ahdr {
19         char *name;
20         Dir;
21 };
22
23 typedef struct Arch Arch;
24 struct Arch {
25         vlong off;
26         vlong length;
27 };
28
29 static void*
30 emalloc(long sz)
31 {
32         void *v;
33
34         v = malloc(sz);
35         if(v == nil)
36                 sysfatal("malloc %lud fails", sz);
37         memset(v, 0, sz);
38         return v;
39 }
40
41 static char*
42 estrdup(char *s)
43 {
44         s = strdup(s);
45         if(s == nil)
46                 sysfatal("strdup (%.10s) fails", s);
47         return s;
48 }
49
50 static char*
51 Bgetline(Biobuf *b)
52 {
53         char *p;
54
55         if(p = Brdline(b, '\n'))
56                 p[Blinelen(b)-1] = '\0';
57         return p;
58 }
59
60 Ahdr*
61 gethdr(Biobuf *b)
62 {
63         Ahdr *a;
64         char *p, *f[10];
65
66         if((p = Bgetline(b)) == nil)
67                 return nil;
68
69         if(strcmp(p, "end of archive") == 0) {
70                 werrstr("");
71                 return nil;
72         }
73
74         if(tokenize(p, f, nelem(f)) != 6) {
75                 werrstr("bad format");
76                 return nil;
77         }
78
79         a = emalloc(sizeof(*a));
80         a->name = estrdup(f[0]);
81         a->mode = strtoul(f[1], 0, 8);
82         a->uid = estrdup(f[2]);
83         a->gid = estrdup(f[3]);
84         a->mtime = strtoll(f[4], 0, 10);
85         a->length = strtoll(f[5], 0, 10);
86         return a;
87 }
88
89 static Arch*
90 newarch(vlong off, vlong length)
91 {
92         static Arch *abuf;
93         static int nabuf;
94
95         if(nabuf == 0) {
96                 nabuf = 256;
97                 abuf = emalloc(sizeof(Arch)*nabuf);
98         }
99
100         nabuf--;
101         abuf->off = off;
102         abuf->length = length;
103         return abuf++;
104 }
105
106 static File*
107 createpath(File *f, char *name, char *u, ulong m)
108 {
109         char *p;
110         File *nf;
111
112         if(verbose)
113                 fprint(2, "createpath %s\n", name);
114         incref(f);
115         while(f && (p = strchr(name, '/'))) {
116                 *p = '\0';
117                 if(strcmp(name, "") != 0 && strcmp(name, ".") != 0){
118                         /* this would be a race if we were multithreaded */
119                         incref(f);      /* so walk doesn't kill it immediately on failure */
120                         if((nf = walkfile(f, name)) == nil)
121                                 nf = createfile(f, name, u, DMDIR|0777, nil);
122                         decref(f);
123                         f = nf;
124                 }
125                 *p = '/';
126                 name = p+1;
127         }
128         if(f == nil)
129                 return nil;
130
131         incref(f);
132         if((nf = walkfile(f, name)) == nil)
133                 nf = createfile(f, name, u, m, nil);
134         decref(f);
135         return nf;
136 }
137
138 static void
139 archcreatefile(char *name, Arch *arch, Dir *d)
140 {
141         File *f;
142         f = createpath(archtree->root, name, d->uid, d->mode);
143         if(f == nil)
144                 sysfatal("creating %s: %r", name);
145         free(f->gid);
146         f->gid = estrdup9p(d->gid);
147         f->aux = arch;
148         f->mtime = d->mtime;
149         f->length = d->length;
150         decref(f);
151 }
152
153 static void
154 fsread(Req *r)
155 {
156         Arch *a;
157         char err[ERRMAX];
158         int n;
159
160         a = r->fid->file->aux;
161         if(a->length <= r->ifcall.offset) 
162                 r->ifcall.count = 0;
163         else if(a->length <= r->ifcall.offset+r->ifcall.count)
164                 r->ifcall.count = a->length - r->ifcall.offset;
165
166         werrstr("unknown error");
167         if(Bseek(b, a->off+r->ifcall.offset, 0) < 0 
168         || (n = Bread(b, r->ofcall.data, r->ifcall.count)) < 0) {
169                 err[0] = '\0';
170                 errstr(err, sizeof err);
171                 respond(r, err);
172         } else {
173                 r->ofcall.count = n;
174                 respond(r, nil);        
175         }
176 }
177
178 Srv fs = {
179         .read=  fsread,
180 };
181
182 static void
183 usage(void)
184 {
185         fprint(2, "usage: archfs [-abcC] [-m mtpt] archfile\n");
186         exits("usage");
187 }
188
189 void
190 main(int argc, char **argv)
191 {
192         Ahdr *a;
193         ulong flag;
194         char *mtpt;
195         char err[ERRMAX];
196
197         flag = 0;
198         mtpt = "/mnt/arch";
199         ARGBEGIN{
200         case 'D':
201                 chatty9p++;
202                 break;
203         case 'a':
204                 flag |= MAFTER;
205                 break;
206         case 'b':
207                 flag |= MBEFORE;
208                 break;
209         case 'c':
210                 flag |= MCREATE;
211                 break;
212         case 'C':
213                 flag |= MCACHE;
214                 break;
215         case 'm':
216                 mtpt = EARGF(usage());
217                 break;
218         default:
219                 usage();
220                 break;
221         }ARGEND;
222
223         if(argc != 1)
224                 usage();
225
226         if((b = Bopen(argv[0], OREAD)) == nil)
227                 sysfatal("open '%s': %r", argv[0]);
228
229         archtree = fs.tree = alloctree("sys", "sys", DMDIR|0775, nil);
230         while(a = gethdr(b)) {
231                 archcreatefile(a->name, newarch(Boffset(b), a->length), a);
232                 Bseek(b, a->length, 1);
233         }
234
235         err[0] = '\0';
236         errstr(err, sizeof err);
237         if(err[0])
238                 sysfatal("reading archive: %s", err);
239
240         postmountsrv(&fs, nil, mtpt, flag);
241         exits(0);
242 }