minit-update.c (5575B) download
1#include <errno.h>
2#include <dirent.h>
3#include <fcntl.h>
4#include <sys/file.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <libowfat/str.h>
12#include <libowfat/buffer.h>
13
14#include "minit.h"
15
16#define USAGE "Usage: minit-update [ -v [ -u ] ]\n"
17#define BUFLEN 1500
18
19/*
20 increases file size by almost 4k
21#define WITH_STRERROR */
22
23static char buf[BUFLEN+1];
24
25static unsigned int verbose;
26static int do_update;
27
28void feed_struct_to_minit(struct process *data);
29
30ssize_t read_outfd(void *buf, size_t count);
31
32void addprocess(struct process *p);
33
34
35void die(const char *msg) {
36 buffer_putsflush(buffer_2, msg);
37 _exit(111);
38}
39
40
41void buffer_putsnlflush(buffer *b, const char *msg) {
42 buffer_puts(b, msg);
43 buffer_putflush(b, "\n",1);
44}
45
46
47#ifdef WITH_STRERROR
48void buffer_puts_strerror(const char *msg) {
49 buffer_puts(buffer_2, "minit-update: ");
50 buffer_puts(buffer_2, msg);
51 buffer_putsnlflush(buffer_2, strerror(errno));
52}
53#else
54#define buffer_puts_strerror(a) buffer_putsflush(buffer_2, a)
55#endif
56
57
58void *xmalloc(size_t size) {
59 void *ptr=malloc(size);
60 if (!ptr) die("malloc() failed\n");
61 return ptr;
62}
63
64
65void copywrite (const char *service) {
66 strncpy(buf+1,service,BUFLEN);
67 buf[BUFLEN]=0;
68 write(infd,buf,str_len(buf));
69}
70
71
72int read_reply_from_minit(void) {
73 if (read_outfd(buf,BUFLEN)==1) {
74 if (buf[0]=='1') return 1;
75 if (buf[0]=='0') buffer_puts(buffer_2,"expected '1' from minit, got '0' - minit too old?\n");
76 }
77 /* XXX: Uuuh. Should this be checked?
78 else buffer_putsflush(buffer_2, "minit response not understood\n");
79 */
80return 0;
81}
82
83
84void find_service(int subdir, char *name, char *parent) {
85 struct stat statbuf;
86 char *service=0;
87 DIR *dirstream=0;
88 struct dirent *dir;
89
90 if (chdir(name)) return;
91
92 if (parent) {
93 service=xmalloc(str_len(parent) + str_len(name) + 2 );
94 strcpy(service, parent);
95 strcat(service, "/");
96 strcat(service, name);
97 } else {
98 if (subdir) {
99 service=xmalloc(str_len(name)+1);
100 strcpy(service, name);
101 }
102 }
103#if 0
104 buffer_putsnlflush(buffer_1,service);
105#endif
106
107 if (service) { /* request and read a "struct process" from minit */
108 struct process tmp;
109#if 0
110 int j;
111 for (j=0; j<=maxprocess; ++j) { /* skip duplicates */
112 if(!strcmp(root[j].name,service)) return 0;
113 }
114#endif
115
116 if (verbose) {
117 buffer_puts(buffer_1, "minit-update: status for ");
118 buffer_puts(buffer_1, service);
119 }
120
121 buf[0]='D';
122 copywrite(service);
123
124 switch (read_outfd(&tmp,sizeof(tmp))) {
125 case sizeof(tmp):
126 tmp.name=strdup(service);
127 addprocess(&tmp);
128 if (verbose) buffer_puts(buffer_1, " saved.\n");
129 break;
130 case 1:
131 if (verbose) buffer_puts(buffer_1, " failed - minit has no information on this service\n");
132 #if 0
133 break;
134 default:
135 buffer_puts(buffer_1, " failed - read incomplete structure!\n");
136 #endif
137 }
138 }
139
140dirstream=opendir(".");
141if (!dirstream) goto ret;
142
143while ( (dir=readdir(dirstream))){
144 if (dir->d_name[0]!='.') {
145 if(!lstat(dir->d_name, &statbuf)) {
146 if (S_ISDIR(statbuf.st_mode)) {
147 find_service(1, dir->d_name, service);
148#if 0
149 } else {
150 buffer_putsnlflush(buffer_1,dir->d_name);
151#endif
152 }
153 } else {
154 buffer_puts(buffer_2, dir->d_name);
155 buffer_puts(buffer_2, ": cannot stat\n");
156 buffer_puts_strerror("lstat() failed: ");
157 }
158 }
159} /* while */
160
161closedir(dirstream);
162
163ret:
164if (service) free(service);
165chdir(MINITROOT);
166if (parent) chdir(parent);
167buffer_flush(buffer_1);
168}
169
170
171int main(int argc, char **argv) {
172 int i;
173
174 if (argc < 2) die(USAGE);
175
176 while (argc>1) {
177 argc--;
178 if (argv[argc][0]=='-') {
179 switch(argv[argc][1]) {
180 case 'v': verbose++; break;
181 case 'u': do_update=1; break;
182 default:
183 buffer_puts(buffer_2,"minit-update: Unknown Option: ");
184 buffer_putsnlflush(buffer_2,argv[argc]);
185 }
186 } else die(USAGE);
187 }
188
189 infd=open(MINITROOT "/in",O_WRONLY);
190 outfd=open(MINITROOT "/out",O_RDONLY);
191
192 if (infd<0 || outfd<0) die("could not open " MINITROOT "/in or " MINITROOT "/out\n");
193
194 while (lockf(infd,F_TLOCK,1)) {
195 buffer_puts_strerror("could not acquire lock: ");
196 sleep(1);
197 }
198
199 find_service(0,MINITROOT,0);
200
201 if (maxprocess == -1)
202 die("Could not extract running services from minit\n");
203
204 if (verbose) buffer_putsflush(buffer_1, "minit-update: telling minit to execve itself\n");
205
206 if (!do_update) {
207 buffer_putsflush(buffer_2, "Test mode: No update done.\n");
208 return 0;
209 }
210
211 write(infd,"update",6);
212 sleep(1);
213
214 for (i=0; i<=maxprocess; i++) {
215 if (verbose) {
216 buffer_puts(buffer_1, "minit-update: restoring status for ");
217 buffer_putsnlflush(buffer_1, root[i].name);
218 }
219
220 buf[0]='U';
221 copywrite(root[i].name);
222
223 read_reply_from_minit();
224
225 write(infd,&root[i],sizeof (struct process));
226
227 if (read_reply_from_minit() && verbose) {
228 buffer_puts(buffer_1, "minit-update: restored service ");
229 buffer_putsnlflush(buffer_1, root[i].name);
230 }
231
232 } /* for() */
233
234return 0;
235}
236
237
238ssize_t read_outfd(void *buf, size_t count) {
239 ssize_t br=read(outfd,buf,count);
240
241 if (br<0) buffer_puts_strerror("Error reading from outfd: ");
242return br;
243}
244
245
246void addprocess(struct process *p) {
247 if (maxprocess+1>=processalloc) {
248 struct process *fump;
249 processalloc+=8;
250 if ((fump=(struct process *)realloc(root,processalloc*sizeof(struct process)))==0) die("realloc() failed\n ");
251 root=fump;
252 }
253 memmove(&root[++maxprocess],p,sizeof(struct process));
254}