xref: /plan9/sys/src/cmd/mk/archive.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
1 #include	"mk.h"
2 #include	<ar.h>
3 
4 static void atimes(char *);
5 static char *split(char*, char**);
6 
7 long
8 atimeof(int force, char *name)
9 {
10 	Symtab *sym;
11 	long 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 > (long)sym->value)){
22 			atimes(archive);
23 			sym->value = (void *)t;
24 		}
25 	}
26 	else{
27 		atimes(archive);
28 		/* mark the aggegate as having been done */
29 		symlook(strdup(archive), S_AGG, "")->value = (void *)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 (long)sym->value;	/* uggh */
36 	return 0;
37 }
38 
39 void
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
82 atimes(char *ar)
83 {
84 	struct ar_hdr h;
85 	long t;
86 	int fd, i;
87 	char buf[BIGBLOCK];
88 
89 	fd = open(ar, OREAD);
90 	if(fd < 0)
91 		return;
92 
93 	if(read(fd, buf, SARMAG) != SARMAG){
94 		close(fd);
95 		return;
96 	}
97 	while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){
98 		t = atol(h.date);
99 		if(t == 0)	/* as it sometimes happens; thanks ken */
100 			t = 1;
101 		for(i = sizeof(h.name)-1; i > 0 && h.name[i] == ' '; i--)
102 				;
103 		if(h.name[i] == '/')		/* system V bug */
104 			i--;
105 		h.name[i+1]=0;		/* can stomp on date field */
106 		sprint(buf, "%s(%s)", ar, h.name);
107 		symlook(strdup(buf), S_TIME, (void *)t)->value = (void *)t;
108 		t = atol(h.size);
109 		if(t&01) t++;
110 		LSEEK(fd, t, 1);
111 	}
112 	close(fd);
113 }
114 
115 static int
116 type(char *file)
117 {
118 	int fd;
119 	char buf[SARMAG];
120 
121 	fd = open(file, OREAD);
122 	if(fd < 0){
123 		if(symlook(file, S_BITCH, 0) == 0){
124 			Bprint(&bout, "%s doesn't exist: assuming it will be an archive\n", file);
125 			symlook(file, S_BITCH, (void *)file);
126 		}
127 		return 1;
128 	}
129 	if(read(fd, buf, SARMAG) != SARMAG){
130 		close(fd);
131 		return 0;
132 	}
133 	close(fd);
134 	return !strncmp(ARMAG, buf, SARMAG);
135 }
136 
137 static char*
138 split(char *name, char **member)
139 {
140 	char *p, *q;
141 
142 	p = strdup(name);
143 	q = utfrune(p, '(');
144 	if(q){
145 		*q++ = 0;
146 		if(member)
147 			*member = q;
148 		q = utfrune(q, ')');
149 		if (q)
150 			*q = 0;
151 		if(type(p))
152 			return p;
153 		free(p);
154 		fprint(2, "mk: '%s' is not an archive\n", name);
155 	}
156 	return 0;
157 }
158