Introduction
Introduction Statistics Contact Development Disclaimer Help
archive.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
archive.c (4689B)
---
1 #include "mk.h"
2 #define ARMAG "!<arch>\n"
3 #define SARMAG 8
4
5 #define ARFMAG "`\n"
6 #define SARNAME 16
7
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)
19
20 static int dolong = 1;
21
22 static void atimes(char *);
23 static char *split(char*, char**);
24
25 long
26 readn(int f, void *av, long n)
27 {
28 char *a;
29 long m, t;
30
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];
50
51 archive = split(name, &member);
52 if(archive == 0)
53 Exit();
54
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 …
69 if(dolong)
70 snprint(buf, sizeof(buf), "%s(%s)", archive, member);
71 else
72 snprint(buf, sizeof(buf), "%s(%.*s)", archive, SARNAME, …
73 sym = symlook(buf, S_TIME, 0);
74 if (sym)
75 return sym->u.value;
76 return 0;
77 }
78
79 void
80 atouch(char *name)
81 {
82 char *archive, *member;
83 int fd, i;
84 struct ar_hdr h;
85 long t;
86
87 archive = split(name, &member);
88 if(archive == 0)
89 Exit();
90
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-…
105 ;
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;
112 }
113 t = atol(h.size);
114 if(t&01) t++;
115 LSEEK(fd, t, 1);
116 }
117 }
118 close(fd);
119 }
120
121 static void
122 atimes(char *ar)
123 {
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;
130
131 strings = nil;
132 fd = open(ar, OREAD);
133 if(fd < 0)
134 return;
135
136 if(read(fd, buf, SARMAG) != SARMAG){
137 close(fd);
138 return;
139 }
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;
150 }
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;
169 }
170 strings[t] = 0;
171 continue;
172 }
173 goto skip;
174 }else if(strings && h.name[0]=='/' && isdigit((uchar)h.n…
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++)
180 ;
181 namelen = p-(strings+i);
182 if(namelen >= sizeof name){
183 namelen = 0;
184 goto skip;
185 }
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] == ' …
192 ;
193 if(name[i] == '/') /* system V bu…
194 i--;
195 name[i+1]=0;
196 }
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);
205 }
206 close(fd);
207 free(strings);
208 }
209
210 static int
211 type(char *file)
212 {
213 int fd;
214 char buf[SARMAG];
215
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)-…
220 Bprint(&bout, "%s doesn't exist: assumin…
221 symlook(file, S_BITCH, (void *)file);
222 }
223 return 1;
224 }
225 if(read(fd, buf, SARMAG) != SARMAG){
226 close(fd);
227 return 0;
228 }
229 close(fd);
230 return !strncmp(ARMAG, buf, SARMAG);
231 }
232
233 static char*
234 split(char *name, char **member)
235 {
236 char *p, *q;
237
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);
251 }
252 return 0;
253 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.