xref: /plan9/sys/src/cmd/mk/archive.c (revision 7f49a7ff54b1fd29a638d67350c7ceb952fbe2d6)
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