tarchive.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tarchive.c (5052B) | |
--- | |
1 #include "mk.h" | |
2 #if defined(__AIX__) | |
3 #define ARMAG "<bigaf>\n" | |
4 #else | |
5 #define ARMAG "!<arch>\n" | |
6 #endif | |
7 #define SARMAG (sizeof(ARMAG) - sizeof("")) | |
8 | |
9 #define ARFMAG "`\n" | |
10 #define SARNAME 16 | |
11 | |
12 struct ar_hdr | |
13 { | |
14 char name[SARNAME]; | |
15 char date[12]; | |
16 char uid[6]; | |
17 char gid[6]; | |
18 char mode[8]; | |
19 char size[10]; | |
20 char fmag[2]; | |
21 }; | |
22 #define SAR_HDR (SARNAME+44) | |
23 | |
24 static int dolong = 1; | |
25 | |
26 static void atimes(char *); | |
27 static char *split(char*, char**); | |
28 | |
29 long | |
30 readn(int f, void *av, long n) | |
31 { | |
32 char *a; | |
33 long m, t; | |
34 | |
35 a = av; | |
36 t = 0; | |
37 while(t < n){ | |
38 m = read(f, a+t, n-t); | |
39 if(m <= 0){ | |
40 if(t == 0) | |
41 return m; | |
42 break; | |
43 } | |
44 t += m; | |
45 } | |
46 return t; | |
47 } | |
48 long | |
49 atimeof(int force, char *name) | |
50 { | |
51 Symtab *sym; | |
52 long t; | |
53 char *archive, *member, buf[512]; | |
54 | |
55 archive = split(name, &member); | |
56 if(archive == 0) | |
57 Exit(); | |
58 | |
59 t = mtime(archive); | |
60 sym = symlook(archive, S_AGG, 0); | |
61 if(sym){ | |
62 if(force || (t > sym->u.value)){ | |
63 atimes(archive); | |
64 sym->u.value = t; | |
65 } | |
66 } | |
67 else{ | |
68 atimes(archive); | |
69 /* mark the aggegate as having been done */ | |
70 symlook(strdup(archive), S_AGG, "")->u.value = t; | |
71 } | |
72 /* truncate long member name to sizeof of name field in … | |
73 if(dolong) | |
74 snprint(buf, sizeof(buf), "%s(%s)", archive, member); | |
75 else | |
76 snprint(buf, sizeof(buf), "%s(%.*s)", archive, SARNAME, … | |
77 sym = symlook(buf, S_TIME, 0); | |
78 if (sym) | |
79 return sym->u.value; | |
80 return 0; | |
81 } | |
82 | |
83 void | |
84 atouch(char *name) | |
85 { | |
86 char *archive, *member; | |
87 int fd, i; | |
88 struct ar_hdr h; | |
89 long t; | |
90 | |
91 archive = split(name, &member); | |
92 if(archive == 0) | |
93 Exit(); | |
94 | |
95 fd = open(archive, ORDWR); | |
96 if(fd < 0){ | |
97 fd = create(archive, OWRITE, 0666); | |
98 if(fd < 0){ | |
99 fprint(2, "create %s: %r\n", archive); | |
100 Exit(); | |
101 } | |
102 write(fd, ARMAG, SARMAG); | |
103 } | |
104 if(symlook(name, S_TIME, 0)){ | |
105 /* hoon off and change it in situ */ | |
106 LSEEK(fd, SARMAG, 0); | |
107 while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){ | |
108 for(i = SARNAME-1; i > 0 && h.name[i] == ' '; i-… | |
109 ; | |
110 h.name[i+1]=0; | |
111 if(strcmp(member, h.name) == 0){ | |
112 t = SARNAME-sizeof(h); /* ughgghh… | |
113 LSEEK(fd, t, 1); | |
114 fprint(fd, "%-12ld", time(0)); | |
115 break; | |
116 } | |
117 t = atol(h.size); | |
118 if(t&01) t++; | |
119 LSEEK(fd, t, 1); | |
120 } | |
121 } | |
122 close(fd); | |
123 } | |
124 | |
125 static int | |
126 allspaces(char *a, int n) | |
127 { | |
128 int i; | |
129 | |
130 for(i=0; i<n; i++) | |
131 if(a[i] != ' ') | |
132 return 0; | |
133 | |
134 return 1; | |
135 } | |
136 | |
137 static void | |
138 atimes(char *ar) | |
139 { | |
140 struct ar_hdr h; | |
141 long t; | |
142 int fd, i, namelen; | |
143 char buf[2048], *p, *strings; | |
144 char name[1024]; | |
145 Symtab *sym; | |
146 | |
147 strings = nil; | |
148 fd = open(ar, OREAD); | |
149 if(fd < 0) | |
150 return; | |
151 | |
152 if(read(fd, buf, SARMAG) != SARMAG){ | |
153 close(fd); | |
154 return; | |
155 } | |
156 while(readn(fd, (char *)&h, sizeof(h)) == sizeof(h)){ | |
157 t = atol(h.date); | |
158 if(t == 0) /* as it sometimes happens; thanks ken… | |
159 t = 1; | |
160 namelen = 0; | |
161 if(memcmp(h.name, "#1/", 3) == 0){ /* BSD */ | |
162 namelen = atoi(h.name+3); | |
163 if(namelen >= sizeof name){ | |
164 namelen = 0; | |
165 goto skip; | |
166 } | |
167 if(readn(fd, name, namelen) != namelen) | |
168 break; | |
169 name[namelen] = 0; | |
170 }else if(memcmp(h.name, "// ", 3) == 0){ /* GNU */ | |
171 /* date, uid, gid, mode all ' ' */ | |
172 if(!allspaces(&h.name[3], sizeof(h.name) - 3) || | |
173 !allspaces(h.date, sizeof(h.date)) || | |
174 !allspaces(h.uid, sizeof(h.uid)) || | |
175 !allspaces(h.gid, sizeof(h.gid)) || | |
176 !allspaces(h.mode, sizeof(h.mode))) | |
177 goto skip; | |
178 t = atol(h.size); | |
179 if(t&01) | |
180 t++; | |
181 free(strings); | |
182 strings = malloc(t+1); | |
183 if(strings){ | |
184 if(readn(fd, strings, t) != t){ | |
185 free(strings); | |
186 strings = nil; | |
187 break; | |
188 } | |
189 strings[t] = 0; | |
190 continue; | |
191 } | |
192 goto skip; | |
193 }else if(strings && h.name[0]=='/' && isdigit((uchar)h.n… | |
194 i = strtol(h.name+1, &p, 10); | |
195 if(*p != ' ' || i >= strlen(strings)) | |
196 goto skip; | |
197 p = strings+i; | |
198 for(; *p && *p != '/'; p++) | |
199 ; | |
200 namelen = p-(strings+i); | |
201 if(namelen >= sizeof name){ | |
202 namelen = 0; | |
203 goto skip; | |
204 } | |
205 memmove(name, strings+i, namelen); | |
206 name[namelen] = 0; | |
207 namelen = 0; | |
208 }else{ | |
209 memmove(name, h.name, sizeof(h.name)); | |
210 for(i = sizeof(h.name)-1; i > 0 && name[i] == ' … | |
211 ; | |
212 if(name[i] == '/') /* system V bu… | |
213 i--; | |
214 name[i+1]=0; | |
215 } | |
216 snprint(buf, sizeof buf, "%s(%s)", ar, name); | |
217 sym = symlook(strdup(buf), S_TIME, (void *)t); | |
218 sym->u.value = t; | |
219 skip: | |
220 t = atol(h.size); | |
221 if(t&01) t++; | |
222 t -= namelen; | |
223 LSEEK(fd, t, 1); | |
224 } | |
225 close(fd); | |
226 free(strings); | |
227 } | |
228 | |
229 static int | |
230 type(char *file) | |
231 { | |
232 int fd; | |
233 char buf[SARMAG]; | |
234 | |
235 fd = open(file, OREAD); | |
236 if(fd < 0){ | |
237 if(symlook(file, S_BITCH, 0) == 0){ | |
238 if(strlen(file) < 2 || strcmp(file+strlen(file)-… | |
239 Bprint(&bout, "%s doesn't exist: assumin… | |
240 symlook(file, S_BITCH, (void *)file); | |
241 } | |
242 return 1; | |
243 } | |
244 if(read(fd, buf, SARMAG) != SARMAG){ | |
245 close(fd); | |
246 return 0; | |
247 } | |
248 close(fd); | |
249 return !strncmp(ARMAG, buf, SARMAG); | |
250 } | |
251 | |
252 static char* | |
253 split(char *name, char **member) | |
254 { | |
255 char *p, *q; | |
256 | |
257 p = strdup(name); | |
258 q = utfrune(p, '('); | |
259 if(q){ | |
260 *q++ = 0; | |
261 if(member) | |
262 *member = q; | |
263 q = utfrune(q, ')'); | |
264 if (q) | |
265 *q = 0; | |
266 if(type(p)) | |
267 return p; | |
268 free(p); | |
269 fprint(2, "mk: '%s' is not an archive\n", name); | |
270 } | |
271 return 0; | |
272 } |