Merge branch 'Toastman-RT' into Toastman-RT-N
[tomato.git] / release / src / router / httpd / upgrade.c
blob2244862f28128a54c12a669691f2e78f80a35aff
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
8 #include "tomato.h"
10 #include <fcntl.h>
11 #include <errno.h>
12 #include <sys/stat.h>
13 #include <sys/statfs.h>
14 #include <sys/wait.h>
15 #include <typedefs.h>
16 #include <sys/reboot.h>
18 #if 1
19 #define MTD_WRITE_CMD "mtd-write"
20 #else
21 #define DEBUG_TEST
22 #define MTD_WRITE_CMD "/tmp/mtd-write"
23 #endif
25 void prepare_upgrade(void)
27 int n;
29 // stop non-essential stuff & free up some memory
30 exec_service("upgrade-start");
31 for (n = 30; n > 0; --n) {
32 sleep(1);
33 if (nvram_match("action_service", "")) break; // this is cleared at the end
35 unlink("/var/log/messages");
36 unlink("/var/log/messages.0");
37 sync();
40 void wi_upgrade(char *url, int len, char *boundary)
42 uint8 buf[1024];
43 const char *error = "Error reading file";
44 int ok = 0;
45 int n;
46 int reset;
48 check_id(url);
49 reset = (strcmp(webcgi_safeget("_reset", "0"), "1") == 0);
51 #ifdef TCONFIG_JFFS2
52 // quickly check if JFFS2 is mounted by checking if /jffs/ is not squashfs
53 struct statfs sf;
54 if ((statfs("/jffs", &sf) != 0) || (sf.f_type != 0x73717368)) {
55 error = "JFFS2 is currently in use. Since an upgrade may overwrite the "
56 "JFFS2 partition, please backup the contents, disable JFFS2, then reboot the router";
57 goto ERROR;
59 #endif
61 // skip the rest of the header
62 if (!skip_header(&len)) goto ERROR;
64 if (len < (1 * 1024 * 1024)) {
65 error = "Invalid file";
66 goto ERROR;
69 // -- anything after here ends in a reboot --
71 rboot = 1;
73 signal(SIGTERM, SIG_IGN);
74 signal(SIGINT, SIG_IGN);
75 signal(SIGHUP, SIG_IGN);
76 signal(SIGQUIT, SIG_IGN);
78 prepare_upgrade();
79 system("cp reboot.asp /tmp"); // copy to memory
81 led(LED_DIAG, 1);
83 char fifo[] = "/tmp/flashXXXXXX";
84 int pid = -1;
85 FILE *f = NULL;
87 if ((mktemp(fifo) == NULL) ||
88 (mkfifo(fifo, S_IRWXU) < 0)) {
89 error = "Unable to create a fifo";
90 goto ERROR2;
93 char *wargv[] = { MTD_WRITE_CMD, "-w", "-i", fifo, "-d", "linux", NULL };
94 if (_eval(wargv, ">/tmp/.mtd-write", 0, &pid) != 0) {
95 error = "Unable to start flash program";
96 goto ERROR2;
99 if ((f = fopen(fifo, "w")) == NULL) {
100 error = "Unable to start pipe for mtd write";
101 goto ERROR2;
104 // !!! This will actually write the boundary. But since mtd-write
105 // uses trx length... -- zzz
107 while (len > 0) {
108 if ((n = web_read(buf, MIN(len, sizeof(buf)))) <= 0) {
109 goto ERROR2;
111 len -= n;
112 if (safe_fwrite(buf, 1, n, f) != n) {
113 error = "Error writing to pipe";
114 goto ERROR2;
118 error = NULL;
119 ok = 1;
121 ERROR2:
122 rboot = 1;
124 if (f) fclose(f);
125 if (pid != -1) waitpid(pid, &n, 0);
127 if (error == NULL && reset) {
128 set_action(ACT_IDLE);
129 eval("mtd-erase", "-d", "nvram");
131 set_action(ACT_REBOOT);
133 if (resmsg_fread("/tmp/.mtd-write"))
134 error = NULL;
135 ERROR:
136 if (error) resmsg_set(error);
137 web_eat(len);
140 void wo_flash(char *url)
142 if (rboot) {
143 parse_asp("/tmp/reboot.asp");
144 web_close();
146 #ifdef DEBUG_TEST
147 printf("\n\n -- reboot -- \n\n");
148 set_action(ACT_IDLE);
149 #else
150 // disconnect ppp - need this for PPTP/L2TP/PPPOE to finish gracefully
151 killall("xl2tpd", SIGTERM);
152 killall("pppd", SIGTERM);
154 sleep(2);
155 // kill(1, SIGTERM);
156 reboot(RB_AUTOBOOT);
157 #endif
158 exit(0);
161 parse_asp("error.asp");