1 #include "mk.h"
2 #include <ar.h>
3
4 static void atimes(char *);
5 static char *split(char*, char**);
6
7 ulong
atimeof(int force,char * name)8 atimeof(int force, char *name)
9 {
10 Symtab *sym;
11 ulong t;
12 char *archive, *member, buf[512];
13
14 archive = split(name, &member);
15 if(archive == 0)
16 Exit();
17
18 t = mtime(archive);
19 sym = symlook(archive, S_AGG, 0);
20 if(sym){
21 if(force || t > sym->u.value){
22 atimes(archive);
23 sym->u.value = t;
24 }
25 }
26 else{
27 atimes(archive);
28 /* mark the aggegate as having been done */
29 symlook(strdup(archive), S_AGG, "")->u.value = t;
30 }
31 /* truncate long member name to sizeof of name field in archive header */
32 snprint(buf, sizeof(buf), "%s(%.*s)", archive, utfnlen(member, SARNAME), member);
33 sym = symlook(buf, S_TIME, 0);
34 if (sym)
35 return sym->u.value;
36 return 0;
37 }
38
39 void
atouch(char * name)40 atouch(char *name)
41 {
42 char *archive, *member;
43 int fd, i;
44 struct ar_hdr h;
45 long t;
46
47 archive = split(name, &member);
48 if(archive == 0)
49 Exit();
50
51 fd = open(archive, ORDWR);
52 if(fd < 0){
53 fd = create(archive, OWRITE, 0666);
54 if(fd < 0){
55 perror(archive);
56 Exit();
57 }
58 write(fd, ARMAG, SARMAG);
59 }
60 if(symlook(name, S_TIME, 0)){
61 /* hoon off and change it in situ */
62 LSEEK(fd, SARMAG, 0);
63 while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){
64 for(i = SARNAME-1; i > 0 && h.name[i] == ' '; i--)
65 ;
66 h.name[i+1]=0;
67 if(strcmp(member, h.name) == 0){
68 t = SARNAME-sizeof(h); /* ughgghh */
69 LSEEK(fd, t, 1);
70 fprint(fd, "%-12ld", time(0));
71 break;
72 }
73 t = atol(h.size);
74 if(t&01) t++;
75 LSEEK(fd, t, 1);
76 }
77 }
78 close(fd);
79 }
80
81 static void
atimes(char * ar)82 atimes(char *ar)
83 {
84 struct ar_hdr h;
85 ulong at, t;
86 int fd, i;
87 char buf[BIGBLOCK];
88 Dir *d;
89
90 fd = open(ar, OREAD);
91 if(fd < 0)
92 return;
93
94 if(read(fd, buf, SARMAG) != SARMAG){
95 close(fd);
96 return;
97 }
98 if((d = dirfstat(fd)) == nil){
99 close(fd);
100 return;
101 }
102 at = d->mtime;
103 free(d);
104 while(read(fd, (char *)&h, SAR_HDR) == SAR_HDR){
105 t = strtoul(h.date, nil, 0);
106 if(t >= at) /* new things in old archives confuses mk */
107 t = at-1;
108 if(t == 0) /* as it sometimes happens; thanks ken */
109 t = 1;
110 for(i = sizeof(h.name)-1; i > 0 && h.name[i] == ' '; i--)
111 ;
112 if(h.name[i] == '/') /* system V bug */
113 i--;
114 h.name[i+1]=0; /* can stomp on date field */
115 snprint(buf, sizeof buf, "%s(%s)", ar, h.name);
116 symlook(strdup(buf), S_TIME, (void*)t)->u.value = t;
117 t = atol(h.size);
118 if(t&01) t++;
119 LSEEK(fd, t, 1);
120 }
121 close(fd);
122 }
123
124 static int
type(char * file)125 type(char *file)
126 {
127 int fd;
128 char buf[SARMAG];
129
130 fd = open(file, OREAD);
131 if(fd < 0){
132 if(symlook(file, S_BITCH, 0) == 0){
133 Bprint(&bout, "%s doesn't exist: assuming it will be an archive\n", file);
134 symlook(file, S_BITCH, (void *)file);
135 }
136 return 1;
137 }
138 if(read(fd, buf, SARMAG) != SARMAG){
139 close(fd);
140 return 0;
141 }
142 close(fd);
143 return strncmp(ARMAG, buf, SARMAG) == 0;
144 }
145
146 static char*
split(char * name,char ** member)147 split(char *name, char **member)
148 {
149 char *p, *q;
150
151 p = strdup(name);
152 q = utfrune(p, '(');
153 if(q){
154 *q++ = 0;
155 if(member)
156 *member = q;
157 q = utfrune(q, ')');
158 if (q)
159 *q = 0;
160 if(type(p))
161 return p;
162 free(p);
163 fprint(2, "mk: '%s' is not an archive\n", name);
164 }
165 return 0;
166 }
167