7 NFLDS = 6, /* filename, modes, uid, gid, mtime, bytes */
10 int selected(char*, int, char*[]);
11 void mkdirs(char*, char*);
12 void mkdir(char*, ulong, ulong, char*, char*);
13 void extract(char*, ulong, ulong, char*, char*, uvlong);
14 void seekpast(uvlong);
15 void error(char*, ...);
16 void warn(char*, ...);
18 #pragma varargck argpos warn 1
19 #pragma varargck argpos error 1
30 main(int argc, char **argv)
33 char *fields[NFLDS], name[2*LEN], *p, *namep;
44 error("destination fs name too long\n");
46 namep = name + strlen(name);
50 Binit(&bout, 1, OWRITE);
66 Binits(&bin, 0, OREAD, binbuf, sizeof binbuf);
67 while(p = Brdline(&bin, '\n')){
68 p[Blinelen(&bin)-1] = '\0';
71 if(strcmp(p, "end of archive") == 0){
76 if (gettokens(p, fields, NFLDS, " \t") != NFLDS){
77 warn("too few fields in file header");
80 p = unquotestrdup(fields[0]);
83 mode = strtoul(fields[1], 0, 8);
86 mtime = strtoul(fields[4], 0, 10);
87 bytes = strtoull(fields[5], 0, 10);
89 if(!selected(namep, argc, argv)){
97 Bprint(&bout, "%q %luo %q %q %lud %llud\n",
98 name, mode, uid, gid, mtime, bytes);
104 mkdir(name, mode, mtime, uid, gid);
106 extract(name, mode, mtime, uid, gid, bytes);
108 fprint(2, "premature end of archive\n");
109 exits("premature end of archive");
113 fileprefix(char *prefix, char *s)
116 if(*prefix++ != *s++)
124 selected(char *s, int argc, char *argv[])
128 for(i=0; i<argc; i++)
129 if(fileprefix(argv[i], s))
135 mkdirs(char *name, char *namep)
141 for(p = &buf[namep - name]; p = utfrune(p, '/'); p++){
145 fd = create(buf, OREAD, 0775|DMDIR);
152 mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
159 fd = create(name, OREAD, mode);
161 rerrstr(olderr, sizeof(olderr));
162 if((d = dirstat(name)) == nil || !(d->mode & DMDIR)){
164 warn("can't make directory %q, mode %luo: %s", name, mode, olderr);
173 p = utfrrune(name, L'/');
186 if(dirwstat(name, d) < 0)
187 warn("can't set modes for %q: %r", name);
190 if((d = dirstat(name)) == nil){
191 warn("can't reread modes for %q: %r", name);
194 if(Tflag && d->mtime != mtime)
195 warn("%q: time mismatch %lud %lud\n", name, mtime, d->mtime);
196 if(uflag && strcmp(uid, d->uid))
197 warn("%q: uid mismatch %q %q", name, uid, d->uid);
198 if(uflag && strcmp(gid, d->gid))
199 warn("%q: gid mismatch %q %q", name, gid, d->gid);
204 extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, uvlong bytes)
214 print("x %q %llud bytes\n", name, bytes);
216 b = Bopen(name, OWRITE);
218 warn("can't make file %q: %r", name);
222 for(tot = 0; tot < bytes; tot += n){
226 n = Bread(&bin, buf, n);
228 error("premature eof reading %q", name);
229 if(Bwrite(b, buf, n) != n)
230 warn("error writing %q: %r", name);
234 p = utfrrune(name, '/');
248 if(dirfwstat(Bfildes(b), &d) < 0)
249 warn("can't set modes for %q: %r", name);
251 if((nd = dirfstat(Bfildes(b))) == nil)
252 warn("can't reread modes for %q: %r", name);
254 if(Tflag && nd->mtime != mtime)
255 warn("%q: time mismatch %lud %lud\n",
256 name, mtime, nd->mtime);
257 if(uflag && strcmp(uid, nd->uid))
258 warn("%q: uid mismatch %q %q",
260 if(uflag && strcmp(gid, nd->gid))
261 warn("%q: gid mismatch %q %q",
270 seekpast(uvlong bytes)
276 for(tot = 0; tot < bytes; tot += n){
280 n = Bread(&bin, buf, n);
282 error("premature eof");
287 error(char *fmt, ...)
292 sprint(buf, "%q: ", argv0);
294 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
296 fprint(2, "%s\n", buf);
306 sprint(buf, "%q: ", argv0);
308 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
310 fprint(2, "%s\n", buf);
316 fprint(2, "usage: mkext [-h] [-u] [-v] [-d dest-fs] [file ...]\n");