Blob


1 #include "mk.h"
2 #define ARMAG "!<arch>\n"
3 #define SARMAG 8
5 #define ARFMAG "`\n"
6 #define SARNAME 16
8 struct ar_hdr
9 {
10 char name[SARNAME];
11 char date[12];
12 char uid[6];
13 char gid[6];
14 char mode[8];
15 char size[10];
16 char fmag[2];
17 };
18 #define SAR_HDR (SARNAME+44)
20 static int dolong = 1;
22 static void atimes(char *);
23 static char *split(char*, char**);
25 long
26 readn(int f, void *av, long n)
27 {
28 char *a;
29 long m, t;
31 a = av;
32 t = 0;
33 while(t < n){
34 m = read(f, a+t, n-t);
35 if(m <= 0){
36 if(t == 0)
37 return m;
38 break;
39 }
40 t += m;
41 }
42 return t;
43 }
44 long
45 atimeof(int force, char *name)
46 {
47 Symtab *sym;
48 long t;
49 char *archive, *member, buf[512];
51 archive = split(name, &member);
52 if(archive == 0)
53 Exit();
55 t = mtime(archive);
56 sym = symlook(archive, S_AGG, 0);
57 if(sym){
58 if(force || (t > sym->u.value)){
59 atimes(archive);
60 sym->u.value = t;
61 }
62 }
63 else{
64 atimes(archive);
65 /* mark the aggegate as having been done */
66 symlook(strdup(archive), S_AGG, "")->u.value = t;
67 }
68 /* truncate long member name to sizeof of name field in archive header */
69 if(dolong)
70 snprint(buf, sizeof(buf), "%s(%s)", archive, member);
71 else
72 snprint(buf, sizeof(buf), "%s(%.*s)", archive, SARNAME, member);
73 sym = symlook(buf, S_TIME, 0);
74 if (sym)
75 return sym->u.value;
76 return 0;
77 }
79 void
80 atouch(char *name)
81 {
82 char *archive, *member;
83 int fd, i;
84 struct ar_hdr h;
85 long t;
87 archive = split(name, &member);
88 if(archive == 0)
89 Exit();
91 fd = open(archive, ORDWR);
92 if(fd < 0){
93 fd = create(archive, OWRITE, 0666);
94 if(fd < 0){
95 fprint(2, "create %s: %r\n", archive);
96 Exit();
97 }
98 write(fd, ARMAG, SARMAG);
99 }
100 if(symlook(name, S_TIME, 0)){
101 /* hoon off and change it in situ */
102 LSEEK(fd, SARMAG, 0);
103 while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){
104 for(i = SARNAME-1; i > 0 && h.name[i] == ' '; i--)
106 h.name[i+1]=0;
107 if(strcmp(member, h.name) == 0){
108 t = SARNAME-sizeof(h); /* ughgghh */
109 LSEEK(fd, t, 1);
110 fprint(fd, "%-12ld", time(0));
111 break;
113 t = atol(h.size);
114 if(t&01) t++;
115 LSEEK(fd, t, 1);
118 close(fd);
121 static void
122 atimes(char *ar)
124 struct ar_hdr h;
125 long t;
126 int fd, i, namelen;
127 char buf[2048], *p, *strings;
128 char name[1024];
129 Symtab *sym;
131 strings = nil;
132 fd = open(ar, OREAD);
133 if(fd < 0)
134 return;
136 if(read(fd, buf, SARMAG) != SARMAG){
137 close(fd);
138 return;
140 while(readn(fd, (char *)&h, sizeof(h)) == sizeof(h)){
141 t = atol(h.date);
142 if(t == 0) /* as it sometimes happens; thanks ken */
143 t = 1;
144 namelen = 0;
145 if(memcmp(h.name, "#1/", 3) == 0){ /* BSD */
146 namelen = atoi(h.name+3);
147 if(namelen >= sizeof name){
148 namelen = 0;
149 goto skip;
151 if(readn(fd, name, namelen) != namelen)
152 break;
153 name[namelen] = 0;
154 }else if(memcmp(h.name, "// ", 2) == 0){ /* GNU */
155 /* date, uid, gid, mode all ' ' */
156 for(i=2; i<16+12+6+6+8; i++)
157 if(h.name[i] != ' ')
158 goto skip;
159 t = atol(h.size);
160 if(t&01)
161 t++;
162 free(strings);
163 strings = malloc(t+1);
164 if(strings){
165 if(readn(fd, strings, t) != t){
166 free(strings);
167 strings = nil;
168 break;
170 strings[t] = 0;
171 continue;
173 goto skip;
174 }else if(strings && h.name[0]=='/' && isdigit((uchar)h.name[1])){
175 i = strtol(h.name+1, &p, 10);
176 if(*p != ' ' || i >= strlen(strings))
177 goto skip;
178 p = strings+i;
179 for(; *p && *p != '/'; p++)
181 namelen = p-(strings+i);
182 if(namelen >= sizeof name){
183 namelen = 0;
184 goto skip;
186 memmove(name, strings+i, namelen);
187 name[namelen] = 0;
188 namelen = 0;
189 }else{
190 strncpy(name, h.name, sizeof(h.name));
191 for(i = sizeof(h.name)-1; i > 0 && name[i] == ' '; i--)
193 if(name[i] == '/') /* system V bug */
194 i--;
195 name[i+1]=0;
197 snprint(buf, sizeof buf, "%s(%s)", ar, name);
198 sym = symlook(strdup(buf), S_TIME, (void *)t);
199 sym->u.value = t;
200 skip:
201 t = atol(h.size);
202 if(t&01) t++;
203 t -= namelen;
204 LSEEK(fd, t, 1);
206 close(fd);
207 free(strings);
210 static int
211 type(char *file)
213 int fd;
214 char buf[SARMAG];
216 fd = open(file, OREAD);
217 if(fd < 0){
218 if(symlook(file, S_BITCH, 0) == 0){
219 if(strlen(file) < 2 || strcmp(file+strlen(file)-2, ".a") != 0)
220 Bprint(&bout, "%s doesn't exist: assuming it will be an archive\n", file);
221 symlook(file, S_BITCH, (void *)file);
223 return 1;
225 if(read(fd, buf, SARMAG) != SARMAG){
226 close(fd);
227 return 0;
229 close(fd);
230 return !strncmp(ARMAG, buf, SARMAG);
233 static char*
234 split(char *name, char **member)
236 char *p, *q;
238 p = strdup(name);
239 q = utfrune(p, '(');
240 if(q){
241 *q++ = 0;
242 if(member)
243 *member = q;
244 q = utfrune(q, ')');
245 if (q)
246 *q = 0;
247 if(type(p))
248 return p;
249 free(p);
250 fprint(2, "mk: '%s' is not an archive\n", name);
252 return 0;