Blame


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>
4 fee1a463 2012-08-05 rsc
5 fee1a463 2012-08-05 rsc #define mkdir plan9mkdir
6 d2173bb5 2012-07-17 rsc
7 d2173bb5 2012-07-17 rsc enum{
8 d2173bb5 2012-07-17 rsc LEN = 8*1024,
9 d2173bb5 2012-07-17 rsc NFLDS = 6, /* filename, modes, uid, gid, mtime, bytes */
10 d2173bb5 2012-07-17 rsc };
11 d2173bb5 2012-07-17 rsc
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
22 d2173bb5 2012-07-17 rsc
23 d2173bb5 2012-07-17 rsc Biobuf bin;
24 d2173bb5 2012-07-17 rsc uchar binbuf[2*LEN];
25 d2173bb5 2012-07-17 rsc char linebuf[LEN];
26 d2173bb5 2012-07-17 rsc int uflag;
27 d2173bb5 2012-07-17 rsc int hflag;
28 d2173bb5 2012-07-17 rsc int vflag;
29 d2173bb5 2012-07-17 rsc int Tflag;
30 d2173bb5 2012-07-17 rsc
31 d2173bb5 2012-07-17 rsc void
32 d2173bb5 2012-07-17 rsc main(int argc, char **argv)
33 d2173bb5 2012-07-17 rsc {
34 d2173bb5 2012-07-17 rsc Biobuf bout;
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;
39 d2173bb5 2012-07-17 rsc
40 d2173bb5 2012-07-17 rsc quotefmtinstall();
41 d2173bb5 2012-07-17 rsc namep = name;
42 d2173bb5 2012-07-17 rsc ARGBEGIN{
43 d2173bb5 2012-07-17 rsc case 'd':
44 d2173bb5 2012-07-17 rsc p = ARGF();
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);
49 d2173bb5 2012-07-17 rsc break;
50 d2173bb5 2012-07-17 rsc case 'h':
51 d2173bb5 2012-07-17 rsc hflag = 1;
52 d2173bb5 2012-07-17 rsc Binit(&bout, 1, OWRITE);
53 d2173bb5 2012-07-17 rsc break;
54 d2173bb5 2012-07-17 rsc case 'u':
55 d2173bb5 2012-07-17 rsc uflag = 1;
56 d2173bb5 2012-07-17 rsc Tflag = 1;
57 d2173bb5 2012-07-17 rsc break;
58 d2173bb5 2012-07-17 rsc case 'T':
59 d2173bb5 2012-07-17 rsc Tflag = 1;
60 d2173bb5 2012-07-17 rsc break;
61 d2173bb5 2012-07-17 rsc case 'v':
62 d2173bb5 2012-07-17 rsc vflag = 1;
63 d2173bb5 2012-07-17 rsc break;
64 d2173bb5 2012-07-17 rsc default:
65 d2173bb5 2012-07-17 rsc usage();
66 d2173bb5 2012-07-17 rsc }ARGEND
67 fa325e9b 2020-01-10 cross
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);
72 d2173bb5 2012-07-17 rsc p = linebuf;
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");
76 d2173bb5 2012-07-17 rsc exits(0);
77 d2173bb5 2012-07-17 rsc }
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");
80 d2173bb5 2012-07-17 rsc continue;
81 d2173bb5 2012-07-17 rsc }
82 d2173bb5 2012-07-17 rsc p = unquotestrdup(fields[0]);
83 d2173bb5 2012-07-17 rsc strcpy(namep, p);
84 d2173bb5 2012-07-17 rsc free(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);
90 d2173bb5 2012-07-17 rsc if(argc){
91 d2173bb5 2012-07-17 rsc if(!selected(namep, argc, argv)){
92 d2173bb5 2012-07-17 rsc if(bytes)
93 d2173bb5 2012-07-17 rsc seekpast(bytes);
94 d2173bb5 2012-07-17 rsc continue;
95 d2173bb5 2012-07-17 rsc }
96 d2173bb5 2012-07-17 rsc mkdirs(name, namep);
97 d2173bb5 2012-07-17 rsc }
98 d2173bb5 2012-07-17 rsc if(hflag){
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);
101 d2173bb5 2012-07-17 rsc if(bytes)
102 d2173bb5 2012-07-17 rsc seekpast(bytes);
103 d2173bb5 2012-07-17 rsc continue;
104 d2173bb5 2012-07-17 rsc }
105 d2173bb5 2012-07-17 rsc if(mode & DMDIR)
106 d2173bb5 2012-07-17 rsc mkdir(name, mode, mtime, uid, gid);
107 d2173bb5 2012-07-17 rsc else
108 d2173bb5 2012-07-17 rsc extract(name, mode, mtime, uid, gid, bytes);
109 d2173bb5 2012-07-17 rsc }
110 d2173bb5 2012-07-17 rsc fprint(2, "premature end of archive\n");
111 d2173bb5 2012-07-17 rsc exits("premature end of archive");
112 d2173bb5 2012-07-17 rsc }
113 d2173bb5 2012-07-17 rsc
114 d2173bb5 2012-07-17 rsc int
115 d2173bb5 2012-07-17 rsc fileprefix(char *prefix, char *s)
116 d2173bb5 2012-07-17 rsc {
117 d2173bb5 2012-07-17 rsc while(*prefix)
118 d2173bb5 2012-07-17 rsc if(*prefix++ != *s++)
119 d2173bb5 2012-07-17 rsc return 0;
120 d2173bb5 2012-07-17 rsc if(*s && *s != '/')
121 d2173bb5 2012-07-17 rsc return 0;
122 d2173bb5 2012-07-17 rsc return 1;
123 d2173bb5 2012-07-17 rsc }
124 d2173bb5 2012-07-17 rsc
125 d2173bb5 2012-07-17 rsc int
126 d2173bb5 2012-07-17 rsc selected(char *s, int argc, char *argv[])
127 d2173bb5 2012-07-17 rsc {
128 d2173bb5 2012-07-17 rsc int i;
129 d2173bb5 2012-07-17 rsc
130 d2173bb5 2012-07-17 rsc for(i=0; i<argc; i++)
131 d2173bb5 2012-07-17 rsc if(fileprefix(argv[i], s))
132 d2173bb5 2012-07-17 rsc return 1;
133 d2173bb5 2012-07-17 rsc return 0;
134 d2173bb5 2012-07-17 rsc }
135 d2173bb5 2012-07-17 rsc
136 d2173bb5 2012-07-17 rsc void
137 d2173bb5 2012-07-17 rsc mkdirs(char *name, char *namep)
138 d2173bb5 2012-07-17 rsc {
139 d2173bb5 2012-07-17 rsc char buf[2*LEN], *p;
140 d2173bb5 2012-07-17 rsc int fd;
141 d2173bb5 2012-07-17 rsc
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')
145 d2173bb5 2012-07-17 rsc return;
146 d2173bb5 2012-07-17 rsc *p = 0;
147 d2173bb5 2012-07-17 rsc fd = create(buf, OREAD, 0775|DMDIR);
148 d2173bb5 2012-07-17 rsc close(fd);
149 d2173bb5 2012-07-17 rsc *p = '/';
150 d2173bb5 2012-07-17 rsc }
151 d2173bb5 2012-07-17 rsc }
152 d2173bb5 2012-07-17 rsc
153 d2173bb5 2012-07-17 rsc void
154 d2173bb5 2012-07-17 rsc mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
155 d2173bb5 2012-07-17 rsc {
156 d2173bb5 2012-07-17 rsc Dir *d, xd;
157 d2173bb5 2012-07-17 rsc int fd;
158 d2173bb5 2012-07-17 rsc char *p;
159 d2173bb5 2012-07-17 rsc char olderr[256];
160 d2173bb5 2012-07-17 rsc
161 d2173bb5 2012-07-17 rsc fd = create(name, OREAD, mode);
162 d2173bb5 2012-07-17 rsc if(fd < 0){
163 d2173bb5 2012-07-17 rsc rerrstr(olderr, sizeof(olderr));
164 d2173bb5 2012-07-17 rsc if((d = dirstat(name)) == nil || !(d->mode & DMDIR)){
165 d2173bb5 2012-07-17 rsc free(d);
166 d2173bb5 2012-07-17 rsc warn("can't make directory %q, mode %luo: %s", name, mode, olderr);
167 d2173bb5 2012-07-17 rsc return;
168 d2173bb5 2012-07-17 rsc }
169 d2173bb5 2012-07-17 rsc free(d);
170 d2173bb5 2012-07-17 rsc }
171 d2173bb5 2012-07-17 rsc close(fd);
172 d2173bb5 2012-07-17 rsc
173 d2173bb5 2012-07-17 rsc d = &xd;
174 d2173bb5 2012-07-17 rsc nulldir(d);
175 d2173bb5 2012-07-17 rsc p = utfrrune(name, L'/');
176 d2173bb5 2012-07-17 rsc if(p)
177 d2173bb5 2012-07-17 rsc p++;
178 d2173bb5 2012-07-17 rsc else
179 d2173bb5 2012-07-17 rsc p = name;
180 d2173bb5 2012-07-17 rsc d->name = p;
181 d2173bb5 2012-07-17 rsc if(uflag){
182 d2173bb5 2012-07-17 rsc d->uid = uid;
183 d2173bb5 2012-07-17 rsc d->gid = gid;
184 d2173bb5 2012-07-17 rsc }
185 d2173bb5 2012-07-17 rsc if(Tflag)
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);
190 d2173bb5 2012-07-17 rsc
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);
194 d2173bb5 2012-07-17 rsc return;
195 d2173bb5 2012-07-17 rsc }
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);
202 d2173bb5 2012-07-17 rsc }
203 d2173bb5 2012-07-17 rsc }
204 d2173bb5 2012-07-17 rsc
205 d2173bb5 2012-07-17 rsc void
206 d2173bb5 2012-07-17 rsc extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, uvlong bytes)
207 d2173bb5 2012-07-17 rsc {
208 d2173bb5 2012-07-17 rsc Dir d, *nd;
209 d2173bb5 2012-07-17 rsc Biobuf *b;
210 d2173bb5 2012-07-17 rsc char buf[LEN];
211 d2173bb5 2012-07-17 rsc char *p;
212 d2173bb5 2012-07-17 rsc ulong n;
213 d2173bb5 2012-07-17 rsc uvlong tot;
214 d2173bb5 2012-07-17 rsc
215 d2173bb5 2012-07-17 rsc if(vflag)
216 d2173bb5 2012-07-17 rsc print("x %q %llud bytes\n", name, bytes);
217 d2173bb5 2012-07-17 rsc
218 d2173bb5 2012-07-17 rsc b = Bopen(name, OWRITE);
219 d2173bb5 2012-07-17 rsc if(!b){
220 d2173bb5 2012-07-17 rsc warn("can't make file %q: %r", name);
221 d2173bb5 2012-07-17 rsc seekpast(bytes);
222 d2173bb5 2012-07-17 rsc return;
223 d2173bb5 2012-07-17 rsc }
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);
229 d2173bb5 2012-07-17 rsc if(n <= 0)
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);
233 d2173bb5 2012-07-17 rsc }
234 d2173bb5 2012-07-17 rsc
235 d2173bb5 2012-07-17 rsc nulldir(&d);
236 d2173bb5 2012-07-17 rsc p = utfrrune(name, '/');
237 d2173bb5 2012-07-17 rsc if(p)
238 d2173bb5 2012-07-17 rsc p++;
239 d2173bb5 2012-07-17 rsc else
240 d2173bb5 2012-07-17 rsc p = name;
241 d2173bb5 2012-07-17 rsc d.name = p;
242 d2173bb5 2012-07-17 rsc if(uflag){
243 d2173bb5 2012-07-17 rsc d.uid = uid;
244 d2173bb5 2012-07-17 rsc d.gid = gid;
245 d2173bb5 2012-07-17 rsc }
246 d2173bb5 2012-07-17 rsc if(Tflag)
247 d2173bb5 2012-07-17 rsc d.mtime = mtime;
248 d2173bb5 2012-07-17 rsc d.mode = mode;
249 d2173bb5 2012-07-17 rsc Bflush(b);
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);
255 d2173bb5 2012-07-17 rsc else{
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);
265 d2173bb5 2012-07-17 rsc free(nd);
266 d2173bb5 2012-07-17 rsc }
267 d2173bb5 2012-07-17 rsc }
268 d2173bb5 2012-07-17 rsc Bterm(b);
269 d2173bb5 2012-07-17 rsc }
270 d2173bb5 2012-07-17 rsc
271 d2173bb5 2012-07-17 rsc void
272 d2173bb5 2012-07-17 rsc seekpast(uvlong bytes)
273 d2173bb5 2012-07-17 rsc {
274 d2173bb5 2012-07-17 rsc char buf[LEN];
275 d2173bb5 2012-07-17 rsc long n;
276 d2173bb5 2012-07-17 rsc uvlong tot;
277 d2173bb5 2012-07-17 rsc
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);
283 d2173bb5 2012-07-17 rsc if(n < 0)
284 d2173bb5 2012-07-17 rsc error("premature eof");
285 d2173bb5 2012-07-17 rsc }
286 d2173bb5 2012-07-17 rsc }
287 d2173bb5 2012-07-17 rsc
288 d2173bb5 2012-07-17 rsc void
289 d2173bb5 2012-07-17 rsc error(char *fmt, ...)
290 d2173bb5 2012-07-17 rsc {
291 d2173bb5 2012-07-17 rsc char buf[1024];
292 d2173bb5 2012-07-17 rsc va_list arg;
293 d2173bb5 2012-07-17 rsc
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);
299 d2173bb5 2012-07-17 rsc exits(0);
300 d2173bb5 2012-07-17 rsc }
301 d2173bb5 2012-07-17 rsc
302 d2173bb5 2012-07-17 rsc void
303 d2173bb5 2012-07-17 rsc warn(char *fmt, ...)
304 d2173bb5 2012-07-17 rsc {
305 d2173bb5 2012-07-17 rsc char buf[1024];
306 d2173bb5 2012-07-17 rsc va_list arg;
307 d2173bb5 2012-07-17 rsc
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);
313 d2173bb5 2012-07-17 rsc }
314 d2173bb5 2012-07-17 rsc
315 d2173bb5 2012-07-17 rsc void
316 d2173bb5 2012-07-17 rsc usage(void)
317 d2173bb5 2012-07-17 rsc {
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");
320 d2173bb5 2012-07-17 rsc }