1 /* casper-md5check - a tool to check md5sums and talk to usplash
3 Written by Tollef Fog Heen <tfheen@ubuntu.com>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
28 #include <sys/types.h>
35 #define USPLASH_FIFO "/dev/.initramfs/usplash_fifo"
40 int write_and_retry(int fd, char *s) {
45 fprintf(stderr, "-> %s\n", s);
48 end = s + strlen(s)+1;
50 ret = write(fd, s, end - s);
51 while (s + ret < end && try < MAXTRIES) {
54 ret = write(fd, s, strlen(s)+1);
57 return (s+ret == end ? 0 : 1);
60 void usplash_timeout(int fd, int timeout) {
63 asprintf(&s, "TIMEOUT %d", timeout);
65 write_and_retry(fd, s);
71 void usplash_failure(int fd, char *format, ...) {
75 va_start(argp, format);
76 vasprintf(&s, format, argp);
79 asprintf(&s1, "FAILURE %s", s);
81 write_and_retry(fd, s1);
87 void usplash_text(int fd, char *format, ...) {
91 va_start(argp, format);
92 vasprintf(&s, format, argp);
95 asprintf(&s1, "TEXT %s", s);
97 write_and_retry(fd, s1);
103 void usplash_urgent(int fd, char *format, ...) {
107 va_start(argp, format);
108 vasprintf(&s, format, argp);
111 asprintf(&s1, "TEXT-URGENT %s", s);
113 write_and_retry(fd, s1);
120 void usplash_success(int fd, char *format, ...) {
124 va_start(argp, format);
125 vasprintf(&s, format, argp);
128 asprintf(&s1, "SUCCESS %s", s);
130 write_and_retry(fd, s1);
136 void usplash_progress(int fd, int progress) {
137 static int prevprogress = -1;
140 if (progress == prevprogress)
142 prevprogress = progress;
144 asprintf(&s, "PROGRESS %d", progress);
146 write_and_retry(fd, s);
151 int set_nocanonical_tty(int fd) {
154 if (tcgetattr(fd, &t) == -1) {
157 t.c_lflag &= ~ICANON;
160 return tcsetattr(fd, TCSANOW, &t);
163 int main(int argc, char **argv) {
165 int pipe_fd, check_fd;
170 md5_byte_t digest[16];
171 char hex_output[16*2 + 1];
172 char *checksum, *checkfile;
173 ssize_t tsize, csize;
179 fprintf(stderr,"Wrong number of arguments\n");
180 fprintf(stderr,"%s <root directory> <md5sum file>\n", argv[0]);
184 if (chdir(argv[1]) != 0) {
189 pipe_fd = open(USPLASH_FIFO, O_WRONLY|O_NONBLOCK);
192 /* We can't really do anything useful here */
193 perror("Opening pipe");
198 usplash_progress(pipe_fd, 0);
199 usplash_urgent(pipe_fd, "Checking integrity, this may take some time");
200 md5_file = fopen(argv[2], "r");
202 perror("fopen md5_file");
205 while (fscanf(md5_file, "%as %as", &checksum, &checkfile) == 2) {
208 if (stat(checkfile, &statbuf) == 0) {
209 tsize += statbuf.st_size;
217 while (fscanf(md5_file, "%as %as", &checksum, &checkfile) == 2) {
224 usplash_text(pipe_fd, "Checking %s", checkfile);
226 check_fd = open(checkfile, O_RDONLY);
228 usplash_timeout(pipe_fd, 300);
229 usplash_failure(pipe_fd, "%s", strerror(errno));
233 rsize = read(check_fd, buf, sizeof(buf));
237 usplash_progress(pipe_fd, floorl(100*((long double)csize)/tsize));
239 md5_append(&state, (const md5_byte_t *)buf, rsize);
240 rsize = read(check_fd, buf, sizeof(buf));
244 md5_finish(&state, digest);
246 for (i = 0; i < 16; i++)
247 sprintf(hex_output + i * 2, "%02x", digest[i]);
249 if (strncmp(hex_output, checksum, strlen(hex_output)) == 0) {
250 usplash_success(pipe_fd, "OK");
252 usplash_failure(pipe_fd, "mismatch");
259 usplash_urgent(pipe_fd, "Check finished: errors found in %d files!", failed);
261 usplash_urgent(pipe_fd, "Check finished: no errors found");
263 usplash_urgent(pipe_fd, "Press any key to reboot your system");
264 usplash_timeout(pipe_fd, 86400);
265 set_nocanonical_tty(0);
267 reboot(LINUX_REBOOT_CMD_RESTART);