minit-update.c (5575B)
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 23 static char buf[BUFLEN+1]; 24 25 static unsigned int verbose; 26 static int do_update; 27 28 void feed_struct_to_minit(struct process *data); 29 30 ssize_t read_outfd(void *buf, size_t count); 31 32 void addprocess(struct process *p); 33 34 35 void die(const char *msg) { 36 buffer_putsflush(buffer_2, msg); 37 _exit(111); 38 } 39 40 41 void 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 48 void 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 58 void *xmalloc(size_t size) { 59 void *ptr=malloc(size); 60 if (!ptr) die("malloc() failed\n"); 61 return ptr; 62 } 63 64 65 void copywrite (const char *service) { 66 strncpy(buf+1,service,BUFLEN); 67 buf[BUFLEN]=0; 68 write(infd,buf,str_len(buf)); 69 } 70 71 72 int 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 */ 80 return 0; 81 } 82 83 84 void 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 140 dirstream=opendir("."); 141 if (!dirstream) goto ret; 142 143 while ( (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 161 closedir(dirstream); 162 163 ret: 164 if (service) free(service); 165 chdir(MINITROOT); 166 if (parent) chdir(parent); 167 buffer_flush(buffer_1); 168 } 169 170 171 int 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 234 return 0; 235 } 236 237 238 ssize_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: "); 242 return br; 243 } 244 245 246 void 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 }