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