1 d2173bb5 2012-07-17 rsc #include <u.h>
2 d2173bb5 2012-07-17 rsc #include <libc.h>
3 d2173bb5 2012-07-17 rsc #include <bio.h>
5 fee1a463 2012-08-05 rsc #define mkdir plan9mkdir
9 d2173bb5 2012-07-17 rsc NFLDS = 6, /* filename, modes, uid, gid, mtime, bytes */
12 d2173bb5 2012-07-17 rsc int selected(char*, int, char*[]);
13 d2173bb5 2012-07-17 rsc void mkdirs(char*, char*);
14 d2173bb5 2012-07-17 rsc void mkdir(char*, ulong, ulong, char*, char*);
15 d2173bb5 2012-07-17 rsc void extract(char*, ulong, ulong, char*, char*, uvlong);
16 d2173bb5 2012-07-17 rsc void seekpast(uvlong);
17 d2173bb5 2012-07-17 rsc void error(char*, ...);
18 d2173bb5 2012-07-17 rsc void warn(char*, ...);
19 d2173bb5 2012-07-17 rsc void usage(void);
20 d2173bb5 2012-07-17 rsc #pragma varargck argpos warn 1
21 d2173bb5 2012-07-17 rsc #pragma varargck argpos error 1
24 d2173bb5 2012-07-17 rsc uchar binbuf[2*LEN];
25 d2173bb5 2012-07-17 rsc char linebuf[LEN];
32 d2173bb5 2012-07-17 rsc main(int argc, char **argv)
35 d2173bb5 2012-07-17 rsc char *fields[NFLDS], name[2*LEN], *p, *namep;
36 d2173bb5 2012-07-17 rsc char *uid, *gid;
37 d2173bb5 2012-07-17 rsc ulong mode, mtime;
38 d2173bb5 2012-07-17 rsc uvlong bytes;
40 d2173bb5 2012-07-17 rsc quotefmtinstall();
41 d2173bb5 2012-07-17 rsc namep = name;
45 d2173bb5 2012-07-17 rsc if(strlen(p) >= LEN)
46 d2173bb5 2012-07-17 rsc error("destination fs name too long\n");
47 d2173bb5 2012-07-17 rsc strcpy(name, p);
48 d2173bb5 2012-07-17 rsc namep = name + strlen(name);
52 d2173bb5 2012-07-17 rsc Binit(&bout, 1, OWRITE);
68 d2173bb5 2012-07-17 rsc Binits(&bin, 0, OREAD, binbuf, sizeof binbuf);
69 d2173bb5 2012-07-17 rsc while(p = Brdline(&bin, '\n')){
70 d2173bb5 2012-07-17 rsc p[Blinelen(&bin)-1] = '\0';
71 d2173bb5 2012-07-17 rsc strcpy(linebuf, p);
73 d2173bb5 2012-07-17 rsc if(strcmp(p, "end of archive") == 0){
74 d2173bb5 2012-07-17 rsc Bterm(&bout);
75 d2173bb5 2012-07-17 rsc fprint(2, "done\n");
78 d2173bb5 2012-07-17 rsc if (gettokens(p, fields, NFLDS, " \t") != NFLDS){
79 d2173bb5 2012-07-17 rsc warn("too few fields in file header");
82 d2173bb5 2012-07-17 rsc p = unquotestrdup(fields[0]);
83 d2173bb5 2012-07-17 rsc strcpy(namep, p);
85 d2173bb5 2012-07-17 rsc mode = strtoul(fields[1], 0, 8);
86 d2173bb5 2012-07-17 rsc uid = fields[2];
87 d2173bb5 2012-07-17 rsc gid = fields[3];
88 d2173bb5 2012-07-17 rsc mtime = strtoul(fields[4], 0, 10);
89 d2173bb5 2012-07-17 rsc bytes = strtoull(fields[5], 0, 10);
91 d2173bb5 2012-07-17 rsc if(!selected(namep, argc, argv)){
93 d2173bb5 2012-07-17 rsc seekpast(bytes);
96 d2173bb5 2012-07-17 rsc mkdirs(name, namep);
99 d2173bb5 2012-07-17 rsc Bprint(&bout, "%q %luo %q %q %lud %llud\n",
100 d2173bb5 2012-07-17 rsc name, mode, uid, gid, mtime, bytes);
102 d2173bb5 2012-07-17 rsc seekpast(bytes);
105 d2173bb5 2012-07-17 rsc if(mode & DMDIR)
106 d2173bb5 2012-07-17 rsc mkdir(name, mode, mtime, uid, gid);
108 d2173bb5 2012-07-17 rsc extract(name, mode, mtime, uid, gid, bytes);
110 d2173bb5 2012-07-17 rsc fprint(2, "premature end of archive\n");
111 d2173bb5 2012-07-17 rsc exits("premature end of archive");
115 d2173bb5 2012-07-17 rsc fileprefix(char *prefix, char *s)
117 d2173bb5 2012-07-17 rsc while(*prefix)
118 d2173bb5 2012-07-17 rsc if(*prefix++ != *s++)
120 d2173bb5 2012-07-17 rsc if(*s && *s != '/')
126 d2173bb5 2012-07-17 rsc selected(char *s, int argc, char *argv[])
130 d2173bb5 2012-07-17 rsc for(i=0; i<argc; i++)
131 d2173bb5 2012-07-17 rsc if(fileprefix(argv[i], s))
137 d2173bb5 2012-07-17 rsc mkdirs(char *name, char *namep)
139 d2173bb5 2012-07-17 rsc char buf[2*LEN], *p;
142 d2173bb5 2012-07-17 rsc strcpy(buf, name);
143 d2173bb5 2012-07-17 rsc for(p = &buf[namep - name]; p = utfrune(p, '/'); p++){
144 d2173bb5 2012-07-17 rsc if(p[1] == '\0')
147 d2173bb5 2012-07-17 rsc fd = create(buf, OREAD, 0775|DMDIR);
154 d2173bb5 2012-07-17 rsc mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
159 d2173bb5 2012-07-17 rsc char olderr[256];
161 d2173bb5 2012-07-17 rsc fd = create(name, OREAD, mode);
163 d2173bb5 2012-07-17 rsc rerrstr(olderr, sizeof(olderr));
164 d2173bb5 2012-07-17 rsc if((d = dirstat(name)) == nil || !(d->mode & DMDIR)){
166 d2173bb5 2012-07-17 rsc warn("can't make directory %q, mode %luo: %s", name, mode, olderr);
175 d2173bb5 2012-07-17 rsc p = utfrrune(name, L'/');
180 d2173bb5 2012-07-17 rsc d->name = p;
182 d2173bb5 2012-07-17 rsc d->uid = uid;
183 d2173bb5 2012-07-17 rsc d->gid = gid;
186 d2173bb5 2012-07-17 rsc d->mtime = mtime;
187 d2173bb5 2012-07-17 rsc d->mode = mode;
188 d2173bb5 2012-07-17 rsc if(dirwstat(name, d) < 0)
189 d2173bb5 2012-07-17 rsc warn("can't set modes for %q: %r", name);
191 d2173bb5 2012-07-17 rsc if(uflag||Tflag){
192 d2173bb5 2012-07-17 rsc if((d = dirstat(name)) == nil){
193 d2173bb5 2012-07-17 rsc warn("can't reread modes for %q: %r", name);
196 d2173bb5 2012-07-17 rsc if(Tflag && d->mtime != mtime)
197 d2173bb5 2012-07-17 rsc warn("%q: time mismatch %lud %lud\n", name, mtime, d->mtime);
198 d2173bb5 2012-07-17 rsc if(uflag && strcmp(uid, d->uid))
199 d2173bb5 2012-07-17 rsc warn("%q: uid mismatch %q %q", name, uid, d->uid);
200 d2173bb5 2012-07-17 rsc if(uflag && strcmp(gid, d->gid))
201 d2173bb5 2012-07-17 rsc warn("%q: gid mismatch %q %q", name, gid, d->gid);
206 d2173bb5 2012-07-17 rsc extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, uvlong bytes)
210 d2173bb5 2012-07-17 rsc char buf[LEN];
216 d2173bb5 2012-07-17 rsc print("x %q %llud bytes\n", name, bytes);
218 d2173bb5 2012-07-17 rsc b = Bopen(name, OWRITE);
220 d2173bb5 2012-07-17 rsc warn("can't make file %q: %r", name);
221 d2173bb5 2012-07-17 rsc seekpast(bytes);
224 d2173bb5 2012-07-17 rsc for(tot = 0; tot < bytes; tot += n){
225 d2173bb5 2012-07-17 rsc n = sizeof buf;
226 d2173bb5 2012-07-17 rsc if(tot + n > bytes)
227 d2173bb5 2012-07-17 rsc n = bytes - tot;
228 d2173bb5 2012-07-17 rsc n = Bread(&bin, buf, n);
230 d2173bb5 2012-07-17 rsc error("premature eof reading %q", name);
231 d2173bb5 2012-07-17 rsc if(Bwrite(b, buf, n) != n)
232 d2173bb5 2012-07-17 rsc warn("error writing %q: %r", name);
235 d2173bb5 2012-07-17 rsc nulldir(&d);
236 d2173bb5 2012-07-17 rsc p = utfrrune(name, '/');
243 d2173bb5 2012-07-17 rsc d.uid = uid;
244 d2173bb5 2012-07-17 rsc d.gid = gid;
247 d2173bb5 2012-07-17 rsc d.mtime = mtime;
248 d2173bb5 2012-07-17 rsc d.mode = mode;
250 d2173bb5 2012-07-17 rsc if(dirfwstat(Bfildes(b), &d) < 0)
251 d2173bb5 2012-07-17 rsc warn("can't set modes for %q: %r", name);
252 d2173bb5 2012-07-17 rsc if(uflag||Tflag){
253 d2173bb5 2012-07-17 rsc if((nd = dirfstat(Bfildes(b))) == nil)
254 d2173bb5 2012-07-17 rsc warn("can't reread modes for %q: %r", name);
256 d2173bb5 2012-07-17 rsc if(Tflag && nd->mtime != mtime)
257 d2173bb5 2012-07-17 rsc warn("%q: time mismatch %lud %lud\n",
258 d2173bb5 2012-07-17 rsc name, mtime, nd->mtime);
259 d2173bb5 2012-07-17 rsc if(uflag && strcmp(uid, nd->uid))
260 d2173bb5 2012-07-17 rsc warn("%q: uid mismatch %q %q",
261 d2173bb5 2012-07-17 rsc name, uid, nd->uid);
262 d2173bb5 2012-07-17 rsc if(uflag && strcmp(gid, nd->gid))
263 d2173bb5 2012-07-17 rsc warn("%q: gid mismatch %q %q",
264 d2173bb5 2012-07-17 rsc name, gid, nd->gid);
272 d2173bb5 2012-07-17 rsc seekpast(uvlong bytes)
274 d2173bb5 2012-07-17 rsc char buf[LEN];
278 d2173bb5 2012-07-17 rsc for(tot = 0; tot < bytes; tot += n){
279 d2173bb5 2012-07-17 rsc n = sizeof buf;
280 d2173bb5 2012-07-17 rsc if(tot + n > bytes)
281 d2173bb5 2012-07-17 rsc n = bytes - tot;
282 d2173bb5 2012-07-17 rsc n = Bread(&bin, buf, n);
284 d2173bb5 2012-07-17 rsc error("premature eof");
289 d2173bb5 2012-07-17 rsc error(char *fmt, ...)
291 d2173bb5 2012-07-17 rsc char buf[1024];
292 d2173bb5 2012-07-17 rsc va_list arg;
294 d2173bb5 2012-07-17 rsc sprint(buf, "%q: ", argv0);
295 d2173bb5 2012-07-17 rsc va_start(arg, fmt);
296 d2173bb5 2012-07-17 rsc vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
297 d2173bb5 2012-07-17 rsc va_end(arg);
298 d2173bb5 2012-07-17 rsc fprint(2, "%s\n", buf);
303 d2173bb5 2012-07-17 rsc warn(char *fmt, ...)
305 d2173bb5 2012-07-17 rsc char buf[1024];
306 d2173bb5 2012-07-17 rsc va_list arg;
308 d2173bb5 2012-07-17 rsc sprint(buf, "%q: ", argv0);
309 d2173bb5 2012-07-17 rsc va_start(arg, fmt);
310 d2173bb5 2012-07-17 rsc vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
311 d2173bb5 2012-07-17 rsc va_end(arg);
312 d2173bb5 2012-07-17 rsc fprint(2, "%s\n", buf);
318 d2173bb5 2012-07-17 rsc fprint(2, "usage: mkext [-h] [-u] [-v] [-d dest-fs] [file ...]\n");
319 d2173bb5 2012-07-17 rsc exits("usage");