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 atimeof(int force, char *name)
27 {
28 Symtab *sym;
29 long t;
30 char *archive, *member, buf[512];
32 archive = split(name, &member);
33 if(archive == 0)
34 Exit();
36 t = mtime(archive);
37 sym = symlook(archive, S_AGG, 0);
38 if(sym){
39 if(force || (t > (long)sym->value)){
40 atimes(archive);
41 sym->value = (void *)t;
42 }
43 }
44 else{
45 atimes(archive);
46 /* mark the aggegate as having been done */
47 symlook(strdup(archive), S_AGG, "")->value = (void *)t;
48 }
49 /* truncate long member name to sizeof of name field in archive header */
50 if(dolong)
51 snprint(buf, sizeof(buf), "%s(%s)", archive, member);
52 else
53 snprint(buf, sizeof(buf), "%s(%.*s)", archive, SARNAME, member);
54 sym = symlook(buf, S_TIME, 0);
55 if (sym)
56 return (long)sym->value; /* uggh */
57 return 0;
58 }
60 void
61 atouch(char *name)
62 {
63 char *archive, *member;
64 int fd, i;
65 struct ar_hdr h;
66 long t;
68 archive = split(name, &member);
69 if(archive == 0)
70 Exit();
72 fd = open(archive, ORDWR);
73 if(fd < 0){
74 fd = create(archive, OWRITE, 0666);
75 if(fd < 0){
76 fprint(2, "create %s: %r\n", archive);
77 Exit();
78 }
79 write(fd, ARMAG, SARMAG);
80 }
81 if(symlook(name, S_TIME, 0)){
82 /* hoon off and change it in situ */
83 LSEEK(fd, SARMAG, 0);
84 while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){
85 for(i = SARNAME-1; i > 0 && h.name[i] == ' '; i--)
86 ;
87 h.name[i+1]=0;
88 if(strcmp(member, h.name) == 0){
89 t = SARNAME-sizeof(h); /* ughgghh */
90 LSEEK(fd, t, 1);
91 fprint(fd, "%-12ld", time(0));
92 break;
93 }
94 t = atol(h.size);
95 if(t&01) t++;
96 LSEEK(fd, t, 1);
97 }
98 }
99 close(fd);
102 static void
103 atimes(char *ar)
105 struct ar_hdr h;
106 long t;
107 int fd, i, namelen;
108 char buf[2048], *p, *strings;
109 char name[1024];
110 Symtab *sym;
112 strings = nil;
113 fd = open(ar, OREAD);
114 if(fd < 0)
115 return;
117 if(read(fd, buf, SARMAG) != SARMAG){
118 close(fd);
119 return;
121 while(readn(fd, (char *)&h, sizeof(h)) == sizeof(h)){
122 t = atol(h.date);
123 if(t == 0) /* as it sometimes happens; thanks ken */
124 t = 1;
125 namelen = 0;
126 if(memcmp(h.name, "#1/", 3) == 0){ /* BSD */
127 namelen = atoi(h.name+3);
128 if(namelen >= sizeof name){
129 namelen = 0;
130 goto skip;
132 if(readn(fd, name, namelen) != namelen)
133 break;
134 name[namelen] = 0;
135 }else if(memcmp(h.name, "// ", 2) == 0){ /* GNU */
136 /* date, uid, gid, mode all ' ' */
137 for(i=2; i<16+12+6+6+8; i++)
138 if(h.name[i] != ' ')
139 goto skip;
140 t = atol(h.size);
141 if(t&01)
142 t++;
143 free(strings);
144 strings = malloc(t+1);
145 if(strings){
146 if(readn(fd, strings, t) != t){
147 free(strings);
148 strings = nil;
149 break;
151 strings[t] = 0;
152 continue;
154 goto skip;
155 }else if(strings && h.name[0]=='/' && isdigit(h.name[1])){
156 i = strtol(h.name+1, &p, 10);
157 if(*p != ' ' || i >= strlen(strings))
158 goto skip;
159 p = strings+i;
160 for(; *p && *p != '/'; p++)
162 namelen = p-(strings+i);
163 if(namelen >= sizeof name){
164 namelen = 0;
165 goto skip;
167 memmove(name, strings+i, namelen);
168 name[namelen] = 0;
169 namelen = 0;
170 }else{
171 strncpy(name, h.name, sizeof(h.name));
172 for(i = sizeof(h.name)-1; i > 0 && name[i] == ' '; i--)
174 if(name[i] == '/') /* system V bug */
175 i--;
176 name[i+1]=0;
178 snprint(buf, sizeof buf, "%s(%s)", ar, name);
179 sym = symlook(strdup(buf), S_TIME, (void *)t);
180 sym->value = (void *)t;
181 skip:
182 t = atol(h.size);
183 if(t&01) t++;
184 t -= namelen;
185 LSEEK(fd, t, 1);
187 close(fd);
188 free(strings);
191 static int
192 type(char *file)
194 int fd;
195 char buf[SARMAG];
197 fd = open(file, OREAD);
198 if(fd < 0){
199 if(symlook(file, S_BITCH, 0) == 0){
200 Bprint(&bout, "%s doesn't exist: assuming it will be an archive\n", file);
201 symlook(file, S_BITCH, (void *)file);
203 return 1;
205 if(read(fd, buf, SARMAG) != SARMAG){
206 close(fd);
207 return 0;
209 close(fd);
210 return !strncmp(ARMAG, buf, SARMAG);
213 static char*
214 split(char *name, char **member)
216 char *p, *q;
218 p = strdup(name);
219 q = utfrune(p, '(');
220 if(q){
221 *q++ = 0;
222 if(member)
223 *member = q;
224 q = utfrune(q, ')');
225 if (q)
226 *q = 0;
227 if(type(p))
228 return p;
229 free(p);
230 fprint(2, "mk: '%s' is not an archive\n", name);
232 return 0;