http://http://diytec.web.fc2.com/mark2r2/

Dependencies:   EthernetNetIf NTPClient_NetServices mbed ConfigFile

Committer:
mark2r2
Date:
Tue Sep 20 12:46:26 2011 +0000
Revision:
0:08a4d61cd84c
V1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mark2r2 0:08a4d61cd84c 1 /*******************************************************************************
mark2r2 0:08a4d61cd84c 2 modify
mark2r2 0:08a4d61cd84c 3 2011/08
mark2r2 0:08a4d61cd84c 4 - Create version text file when read error.
mark2r2 0:08a4d61cd84c 5 - Use commonClient.
mark2r2 0:08a4d61cd84c 6 - Reset HTTP request headers whe GET.
mark2r2 0:08a4d61cd84c 7 - Delete LOG when over 100KB.
mark2r2 0:08a4d61cd84c 8 2011/07
mark2r2 0:08a4d61cd84c 9 - '\n' -> '\r\n' (when write to LOG)
mark2r2 0:08a4d61cd84c 10 - Add MD5 checksum.
mark2r2 0:08a4d61cd84c 11 - Add fclose(fp) when error & return
mark2r2 0:08a4d61cd84c 12
mark2r2 0:08a4d61cd84c 13 *******************************************************************************/
mark2r2 0:08a4d61cd84c 14
mark2r2 0:08a4d61cd84c 15 /**
mark2r2 0:08a4d61cd84c 16 * =============================================================================
mark2r2 0:08a4d61cd84c 17 * Firmware updater (Version 0.0.2)
mark2r2 0:08a4d61cd84c 18 * =============================================================================
mark2r2 0:08a4d61cd84c 19 * Copyright (c) 2010 Shinichiro Nakamura (CuBeatSystems)
mark2r2 0:08a4d61cd84c 20 *
mark2r2 0:08a4d61cd84c 21 * Permission is hereby granted, free of charge, to any person obtaining a copy
mark2r2 0:08a4d61cd84c 22 * of this software and associated documentation files (the "Software"), to deal
mark2r2 0:08a4d61cd84c 23 * in the Software without restriction, including without limitation the rights
mark2r2 0:08a4d61cd84c 24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
mark2r2 0:08a4d61cd84c 25 * copies of the Software, and to permit persons to whom the Software is
mark2r2 0:08a4d61cd84c 26 * furnished to do so, subject to the following conditions:
mark2r2 0:08a4d61cd84c 27 *
mark2r2 0:08a4d61cd84c 28 * The above copyright notice and this permission notice shall be included in
mark2r2 0:08a4d61cd84c 29 * all copies or substantial portions of the Software.
mark2r2 0:08a4d61cd84c 30 *
mark2r2 0:08a4d61cd84c 31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
mark2r2 0:08a4d61cd84c 32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
mark2r2 0:08a4d61cd84c 33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
mark2r2 0:08a4d61cd84c 34 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
mark2r2 0:08a4d61cd84c 35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
mark2r2 0:08a4d61cd84c 36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
mark2r2 0:08a4d61cd84c 37 * THE SOFTWARE.
mark2r2 0:08a4d61cd84c 38 * =============================================================================
mark2r2 0:08a4d61cd84c 39 */
mark2r2 0:08a4d61cd84c 40
mark2r2 0:08a4d61cd84c 41 #include "FirmwareUpdater.h"
mark2r2 0:08a4d61cd84c 42 #include "md5.h" // 2011/07
mark2r2 0:08a4d61cd84c 43
mark2r2 0:08a4d61cd84c 44 #include <stdio.h>
mark2r2 0:08a4d61cd84c 45 #include <stdarg.h>
mark2r2 0:08a4d61cd84c 46
mark2r2 0:08a4d61cd84c 47 extern "C" void mbed_reset();
mark2r2 0:08a4d61cd84c 48
mark2r2 0:08a4d61cd84c 49 const std::string FirmwareUpdater::EXT_BIN = ".bin";
mark2r2 0:08a4d61cd84c 50 const std::string FirmwareUpdater::EXT_BINTMP = ".b__";
mark2r2 0:08a4d61cd84c 51 const std::string FirmwareUpdater::EXT_TXT = ".txt";
mark2r2 0:08a4d61cd84c 52 const std::string FirmwareUpdater::EXT_TXTTMP = ".t__";
mark2r2 0:08a4d61cd84c 53 const std::string FirmwareUpdater::EXT_MD5 = ".md5"; // 2011/07
mark2r2 0:08a4d61cd84c 54 const std::string FirmwareUpdater::EXT_MD5TMP = ".m__"; // 2011/07
mark2r2 0:08a4d61cd84c 55
mark2r2 0:08a4d61cd84c 56 /**
mark2r2 0:08a4d61cd84c 57 * Create.
mark2r2 0:08a4d61cd84c 58 *
mark2r2 0:08a4d61cd84c 59 * @param url URL for firmware. Do not include a target file name.
mark2r2 0:08a4d61cd84c 60 * @param name An application name. Do not include a extention.
mark2r2 0:08a4d61cd84c 61 * @param log True if logging.
mark2r2 0:08a4d61cd84c 62 */
mark2r2 0:08a4d61cd84c 63 //FirmwareUpdater::FirmwareUpdater(std::string url, std::string name, bool log)
mark2r2 0:08a4d61cd84c 64 FirmwareUpdater::FirmwareUpdater(std::string url, std::string name, HTTPClient *pclient, bool log) // 2011/08
mark2r2 0:08a4d61cd84c 65 : url(url), name(name), log(log), local("local") {
mark2r2 0:08a4d61cd84c 66 client = pclient; // 2011/08
mark2r2 0:08a4d61cd84c 67 client->setTimeout(10000); // 2011/08
mark2r2 0:08a4d61cd84c 68
mark2r2 0:08a4d61cd84c 69 /*
mark2r2 0:08a4d61cd84c 70 * A file name on the mbed local file system should keep '8 + 3' types of name.
mark2r2 0:08a4d61cd84c 71 */
mark2r2 0:08a4d61cd84c 72 if (MAXNAMELEN < name.length()) {
mark2r2 0:08a4d61cd84c 73 LOG("ERR : Invalid firmware name '%s' found. The maximum length is %d.\r\n", name.c_str(), MAXNAMELEN);
mark2r2 0:08a4d61cd84c 74 error("ERR : Invalid firmware name '%s' found. The maximum length is %d.\r\n", name.c_str(), MAXNAMELEN);
mark2r2 0:08a4d61cd84c 75 }
mark2r2 0:08a4d61cd84c 76 }
mark2r2 0:08a4d61cd84c 77
mark2r2 0:08a4d61cd84c 78 /**
mark2r2 0:08a4d61cd84c 79 * Dispose.
mark2r2 0:08a4d61cd84c 80 */
mark2r2 0:08a4d61cd84c 81 FirmwareUpdater::~FirmwareUpdater() {
mark2r2 0:08a4d61cd84c 82 }
mark2r2 0:08a4d61cd84c 83
mark2r2 0:08a4d61cd84c 84 /**
mark2r2 0:08a4d61cd84c 85 * Get a URL.
mark2r2 0:08a4d61cd84c 86 *
mark2r2 0:08a4d61cd84c 87 * @return URL.
mark2r2 0:08a4d61cd84c 88 */
mark2r2 0:08a4d61cd84c 89 const std::string FirmwareUpdater:: getURL() const {
mark2r2 0:08a4d61cd84c 90 return url;
mark2r2 0:08a4d61cd84c 91 }
mark2r2 0:08a4d61cd84c 92
mark2r2 0:08a4d61cd84c 93 /**
mark2r2 0:08a4d61cd84c 94 * Get a name.
mark2r2 0:08a4d61cd84c 95 *
mark2r2 0:08a4d61cd84c 96 * @return name.
mark2r2 0:08a4d61cd84c 97 */
mark2r2 0:08a4d61cd84c 98 const std::string FirmwareUpdater:: getName() const {
mark2r2 0:08a4d61cd84c 99 return name;
mark2r2 0:08a4d61cd84c 100 }
mark2r2 0:08a4d61cd84c 101
mark2r2 0:08a4d61cd84c 102 /**
mark2r2 0:08a4d61cd84c 103 * Checking a new firmware.
mark2r2 0:08a4d61cd84c 104 * Compare versions of the software between local storage on mbed and on webserver.
mark2r2 0:08a4d61cd84c 105 *
mark2r2 0:08a4d61cd84c 106 * @return Return 0 if a new firmware exists.
mark2r2 0:08a4d61cd84c 107 */
mark2r2 0:08a4d61cd84c 108 int FirmwareUpdater::exist() {
mark2r2 0:08a4d61cd84c 109 int ver_local, ver_server;
mark2r2 0:08a4d61cd84c 110
mark2r2 0:08a4d61cd84c 111 /*
mark2r2 0:08a4d61cd84c 112 * Fetch the version from a local.
mark2r2 0:08a4d61cd84c 113 */
mark2r2 0:08a4d61cd84c 114 std::string file_local = "/local/" + name + EXT_TXT;
mark2r2 0:08a4d61cd84c 115 ver_local = readVersionFromFile(file_local.c_str());
mark2r2 0:08a4d61cd84c 116 if (ver_local < 0) {
mark2r2 0:08a4d61cd84c 117 return -1;
mark2r2 0:08a4d61cd84c 118 }
mark2r2 0:08a4d61cd84c 119
mark2r2 0:08a4d61cd84c 120 /*
mark2r2 0:08a4d61cd84c 121 * Fetch the version from a server.
mark2r2 0:08a4d61cd84c 122 */
mark2r2 0:08a4d61cd84c 123 std::string file_server = url + "/" + name + EXT_TXT;
mark2r2 0:08a4d61cd84c 124 ver_server = readVersionFromURL(file_server.c_str());
mark2r2 0:08a4d61cd84c 125 if (ver_server < 0) {
mark2r2 0:08a4d61cd84c 126 return -2;
mark2r2 0:08a4d61cd84c 127 }
mark2r2 0:08a4d61cd84c 128
mark2r2 0:08a4d61cd84c 129 return (ver_local < ver_server) ? 0 : 1;
mark2r2 0:08a4d61cd84c 130 }
mark2r2 0:08a4d61cd84c 131
mark2r2 0:08a4d61cd84c 132 /**
mark2r2 0:08a4d61cd84c 133 * Execute update.
mark2r2 0:08a4d61cd84c 134 *
mark2r2 0:08a4d61cd84c 135 * @return Return 0 if it succeed.
mark2r2 0:08a4d61cd84c 136 */
mark2r2 0:08a4d61cd84c 137 int FirmwareUpdater::execute() {
mark2r2 0:08a4d61cd84c 138 /*
mark2r2 0:08a4d61cd84c 139 * Fetch the files.
mark2r2 0:08a4d61cd84c 140 */
mark2r2 0:08a4d61cd84c 141 std::string serv_txt = url + "/" + name + EXT_TXT;
mark2r2 0:08a4d61cd84c 142 std::string file_txttmp = "/local/" + name + EXT_TXTTMP;
mark2r2 0:08a4d61cd84c 143 if (fetch(serv_txt, file_txttmp) != 0) {
mark2r2 0:08a4d61cd84c 144 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 145 return -1;
mark2r2 0:08a4d61cd84c 146 }
mark2r2 0:08a4d61cd84c 147 std::string serv_bin = url + "/" + name + EXT_BIN;
mark2r2 0:08a4d61cd84c 148 std::string file_bintmp = "/local/" + name + EXT_BINTMP;
mark2r2 0:08a4d61cd84c 149 if (fetch(serv_bin, file_bintmp) != 0) {
mark2r2 0:08a4d61cd84c 150 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 151 return -2;
mark2r2 0:08a4d61cd84c 152 }
mark2r2 0:08a4d61cd84c 153 std::string serv_md5 = url + "/" + name + EXT_MD5;
mark2r2 0:08a4d61cd84c 154 std::string file_md5tmp = "/local/" + name + EXT_MD5TMP;
mark2r2 0:08a4d61cd84c 155 if (fetch(serv_md5, file_md5tmp) != 0) {
mark2r2 0:08a4d61cd84c 156 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 157 return -8;
mark2r2 0:08a4d61cd84c 158 }
mark2r2 0:08a4d61cd84c 159
mark2r2 0:08a4d61cd84c 160 /*
mark2r2 0:08a4d61cd84c 161 * Check the firmware versions.
mark2r2 0:08a4d61cd84c 162 */
mark2r2 0:08a4d61cd84c 163 std::string file_txt = "/local/" + name + EXT_TXT;
mark2r2 0:08a4d61cd84c 164 int ver_old = readVersionFromFile(file_txt.c_str());
mark2r2 0:08a4d61cd84c 165 int ver_new = readVersionFromFile(file_txttmp.c_str());
mark2r2 0:08a4d61cd84c 166 if (ver_old < 0) {
mark2r2 0:08a4d61cd84c 167 LOG("ERR : Could not read the previous firmware version.\r\n");
mark2r2 0:08a4d61cd84c 168 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 169 return -3;
mark2r2 0:08a4d61cd84c 170 }
mark2r2 0:08a4d61cd84c 171 if (ver_new < 0) {
mark2r2 0:08a4d61cd84c 172 LOG("ERR : Could not read the new firmware version.\r\n");
mark2r2 0:08a4d61cd84c 173 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 174 return -4;
mark2r2 0:08a4d61cd84c 175 }
mark2r2 0:08a4d61cd84c 176 if (ver_new < ver_old) {
mark2r2 0:08a4d61cd84c 177 LOG("ERR : Ignore the new firmware. (old=%d, new=%d)\r\n", ver_old, ver_new);
mark2r2 0:08a4d61cd84c 178 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 179 return -5;
mark2r2 0:08a4d61cd84c 180 }
mark2r2 0:08a4d61cd84c 181 /*
mark2r2 0:08a4d61cd84c 182 * MD5 check sum
mark2r2 0:08a4d61cd84c 183 * 2011/07
mark2r2 0:08a4d61cd84c 184 *
mark2r2 0:08a4d61cd84c 185 */
mark2r2 0:08a4d61cd84c 186 char md5str[33];
mark2r2 0:08a4d61cd84c 187 int readret = readMd5FromFile(file_md5tmp.c_str(), md5str);
mark2r2 0:08a4d61cd84c 188 if (readret < 0) {
mark2r2 0:08a4d61cd84c 189 LOG("ERR : Could not read the new firmware MD5.\r\n");
mark2r2 0:08a4d61cd84c 190 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 191 return -9;
mark2r2 0:08a4d61cd84c 192 }
mark2r2 0:08a4d61cd84c 193
mark2r2 0:08a4d61cd84c 194 #define BUFF_SIZE 1024
mark2r2 0:08a4d61cd84c 195
mark2r2 0:08a4d61cd84c 196 MD5 md5;
mark2r2 0:08a4d61cd84c 197 FILE *fp;
mark2r2 0:08a4d61cd84c 198 size_t len;
mark2r2 0:08a4d61cd84c 199 unsigned char buff[BUFF_SIZE];
mark2r2 0:08a4d61cd84c 200
mark2r2 0:08a4d61cd84c 201 fp = fopen(file_bintmp.c_str(),"rb");
mark2r2 0:08a4d61cd84c 202 if ( fp == NULL ) {
mark2r2 0:08a4d61cd84c 203 LOG("ERR : Could not read the new firmware bin.\r\n");
mark2r2 0:08a4d61cd84c 204 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 205 return -10;
mark2r2 0:08a4d61cd84c 206 }
mark2r2 0:08a4d61cd84c 207 while (len = fread(buff, 1, BUFF_SIZE, fp)) {
mark2r2 0:08a4d61cd84c 208 md5.update( buff, len);
mark2r2 0:08a4d61cd84c 209 }
mark2r2 0:08a4d61cd84c 210 fclose( fp );
mark2r2 0:08a4d61cd84c 211 md5.finalize();
mark2r2 0:08a4d61cd84c 212
mark2r2 0:08a4d61cd84c 213 string hash;
mark2r2 0:08a4d61cd84c 214 hash = md5.hexdigest();
mark2r2 0:08a4d61cd84c 215 if (strncmp(md5str, hash.c_str(), 32) != 0) {
mark2r2 0:08a4d61cd84c 216 LOG("ERR : MD5 checksum error. Server MD5=%s, calc MD5 from binary=%s\r\n", md5str, hash.c_str() );
mark2r2 0:08a4d61cd84c 217 LOG("ERR : Aborted...\r\n");
mark2r2 0:08a4d61cd84c 218 return -11;
mark2r2 0:08a4d61cd84c 219 }
mark2r2 0:08a4d61cd84c 220
mark2r2 0:08a4d61cd84c 221
mark2r2 0:08a4d61cd84c 222
mark2r2 0:08a4d61cd84c 223 LOG("INFO: Firmware updating... (%d -> %d)\r\n", ver_old, ver_new);
mark2r2 0:08a4d61cd84c 224
mark2r2 0:08a4d61cd84c 225 /*
mark2r2 0:08a4d61cd84c 226 * Cleanup the previous versions.
mark2r2 0:08a4d61cd84c 227 *
mark2r2 0:08a4d61cd84c 228 * Note:
mark2r2 0:08a4d61cd84c 229 * A file time stamp on mbed is always '12:00 01/01/2008'.
mark2r2 0:08a4d61cd84c 230 * mbed can't sense updated firmware when the file name is same as previous version.
mark2r2 0:08a4d61cd84c 231 *
mark2r2 0:08a4d61cd84c 232 * So I decided to cleanup all bin files.
mark2r2 0:08a4d61cd84c 233 * And the new firmware name is 'name-VERSION.bin'.
mark2r2 0:08a4d61cd84c 234 * To remove previous versions at first means 'start critical section on the system'.
mark2r2 0:08a4d61cd84c 235 */
mark2r2 0:08a4d61cd84c 236 //cleanupAllBinFiles();
mark2r2 0:08a4d61cd84c 237 cleanupAllBbkFiles(); // 2011/07
mark2r2 0:08a4d61cd84c 238 BackupBinFiles(); // 2011/07
mark2r2 0:08a4d61cd84c 239
mark2r2 0:08a4d61cd84c 240 /*
mark2r2 0:08a4d61cd84c 241 * Copy it.
mark2r2 0:08a4d61cd84c 242 */
mark2r2 0:08a4d61cd84c 243 char nn[32];
mark2r2 0:08a4d61cd84c 244 createNewBinName(ver_new, nn, sizeof(nn));
mark2r2 0:08a4d61cd84c 245 std::string file_bin = "/local/" + std::string(nn) + EXT_BIN;
mark2r2 0:08a4d61cd84c 246 if (copy(file_bintmp, file_bin) != 0) {
mark2r2 0:08a4d61cd84c 247 return -7;
mark2r2 0:08a4d61cd84c 248 }
mark2r2 0:08a4d61cd84c 249 if (copy(file_txttmp, file_txt) != 0) {
mark2r2 0:08a4d61cd84c 250 return -6;
mark2r2 0:08a4d61cd84c 251 }
mark2r2 0:08a4d61cd84c 252 /*
mark2r2 0:08a4d61cd84c 253 * Delete the temporary files.
mark2r2 0:08a4d61cd84c 254 */
mark2r2 0:08a4d61cd84c 255 remove(file_txttmp.c_str());
mark2r2 0:08a4d61cd84c 256 remove(file_bintmp.c_str());
mark2r2 0:08a4d61cd84c 257 remove(file_md5tmp.c_str()); // 2011/07
mark2r2 0:08a4d61cd84c 258 return 0;
mark2r2 0:08a4d61cd84c 259 }
mark2r2 0:08a4d61cd84c 260
mark2r2 0:08a4d61cd84c 261 /**
mark2r2 0:08a4d61cd84c 262 * Reset system.
mark2r2 0:08a4d61cd84c 263 */
mark2r2 0:08a4d61cd84c 264 void FirmwareUpdater::reset() {
mark2r2 0:08a4d61cd84c 265 mbed_reset();
mark2r2 0:08a4d61cd84c 266 }
mark2r2 0:08a4d61cd84c 267
mark2r2 0:08a4d61cd84c 268 /**
mark2r2 0:08a4d61cd84c 269 * Fetch a file.
mark2r2 0:08a4d61cd84c 270 *
mark2r2 0:08a4d61cd84c 271 * @param src_url URL of a source file.
mark2r2 0:08a4d61cd84c 272 * @param local_file Local file name.
mark2r2 0:08a4d61cd84c 273 *
mark2r2 0:08a4d61cd84c 274 * @return Return 0 if it succeed.
mark2r2 0:08a4d61cd84c 275 */
mark2r2 0:08a4d61cd84c 276 int FirmwareUpdater::fetch(std::string src_url, std::string local_file) {
mark2r2 0:08a4d61cd84c 277 /*
mark2r2 0:08a4d61cd84c 278 * Fetch the source file from URL to a temporary file on local.
mark2r2 0:08a4d61cd84c 279 */
mark2r2 0:08a4d61cd84c 280 HTTPFile file(local_file.c_str());
mark2r2 0:08a4d61cd84c 281 client->resetRequestHeaders(); // 2011/08
mark2r2 0:08a4d61cd84c 282 int r = client->get(src_url.c_str(), &file); // 2011/08
mark2r2 0:08a4d61cd84c 283 if (r != HTTP_OK) {
mark2r2 0:08a4d61cd84c 284 LOG("ERR : Fetch '%s' to '%s'.\r\n", src_url.c_str(), local_file.c_str());
mark2r2 0:08a4d61cd84c 285 return -1;
mark2r2 0:08a4d61cd84c 286 }
mark2r2 0:08a4d61cd84c 287 LOG("INFO: Fetched '%s' to '%s'.\r\n", src_url.c_str(), local_file.c_str());
mark2r2 0:08a4d61cd84c 288 return 0;
mark2r2 0:08a4d61cd84c 289 }
mark2r2 0:08a4d61cd84c 290
mark2r2 0:08a4d61cd84c 291 /**
mark2r2 0:08a4d61cd84c 292 * Copy a file.
mark2r2 0:08a4d61cd84c 293 *
mark2r2 0:08a4d61cd84c 294 * @param local_file1 Source file.
mark2r2 0:08a4d61cd84c 295 * @param local_file2 Destination file.
mark2r2 0:08a4d61cd84c 296 *
mark2r2 0:08a4d61cd84c 297 * @return Return 0 if it succeed.
mark2r2 0:08a4d61cd84c 298 */
mark2r2 0:08a4d61cd84c 299 int FirmwareUpdater::copy(std::string local_file1, std::string local_file2) {
mark2r2 0:08a4d61cd84c 300 LOG("INFO: File copying... (%s->%s)\r\n", local_file1.c_str(), local_file2.c_str());
mark2r2 0:08a4d61cd84c 301 FILE *rp = fopen(local_file1.c_str(), "rb");
mark2r2 0:08a4d61cd84c 302 if (rp == NULL) {
mark2r2 0:08a4d61cd84c 303 LOG("ERR : File '%s' open failed.\r\n", local_file1.c_str());
mark2r2 0:08a4d61cd84c 304 return -1;
mark2r2 0:08a4d61cd84c 305 }
mark2r2 0:08a4d61cd84c 306 remove(local_file2.c_str());
mark2r2 0:08a4d61cd84c 307 FILE *wp = fopen(local_file2.c_str(), "wb");
mark2r2 0:08a4d61cd84c 308 if (wp == NULL) {
mark2r2 0:08a4d61cd84c 309 LOG("ERR : File '%s' open failed.\r\n", local_file2.c_str());
mark2r2 0:08a4d61cd84c 310 fclose(rp);
mark2r2 0:08a4d61cd84c 311 return -2;
mark2r2 0:08a4d61cd84c 312 }
mark2r2 0:08a4d61cd84c 313 int c;
mark2r2 0:08a4d61cd84c 314 while ((c = fgetc(rp)) != EOF) {
mark2r2 0:08a4d61cd84c 315 fputc(c, wp);
mark2r2 0:08a4d61cd84c 316 }
mark2r2 0:08a4d61cd84c 317
mark2r2 0:08a4d61cd84c 318 fclose(rp);
mark2r2 0:08a4d61cd84c 319 fclose(wp);
mark2r2 0:08a4d61cd84c 320 LOG("INFO: File copied. (%s->%s)\r\n", local_file1.c_str(), local_file2.c_str());
mark2r2 0:08a4d61cd84c 321 return 0;
mark2r2 0:08a4d61cd84c 322 }
mark2r2 0:08a4d61cd84c 323
mark2r2 0:08a4d61cd84c 324 /**
mark2r2 0:08a4d61cd84c 325 * Output a message to a log file.
mark2r2 0:08a4d61cd84c 326 *
mark2r2 0:08a4d61cd84c 327 * @param format ...
mark2r2 0:08a4d61cd84c 328 */
mark2r2 0:08a4d61cd84c 329 void FirmwareUpdater::LOG(const char* format, ...) {
mark2r2 0:08a4d61cd84c 330 if (log) {
mark2r2 0:08a4d61cd84c 331 FILE *fplog = fopen("/local/update.log", "a");
mark2r2 0:08a4d61cd84c 332
mark2r2 0:08a4d61cd84c 333 if (fplog != NULL) {
mark2r2 0:08a4d61cd84c 334 char buf[BUFSIZ];
mark2r2 0:08a4d61cd84c 335 va_list p;
mark2r2 0:08a4d61cd84c 336 va_start(p, format);
mark2r2 0:08a4d61cd84c 337 vsnprintf(buf, sizeof(buf) - 1, format, p);
mark2r2 0:08a4d61cd84c 338 fprintf(fplog, "%s", buf);
mark2r2 0:08a4d61cd84c 339 // printf("%s", buf); /* If you want to check a message from a console. */
mark2r2 0:08a4d61cd84c 340 va_end(p);
mark2r2 0:08a4d61cd84c 341 fclose(fplog);
mark2r2 0:08a4d61cd84c 342 }
mark2r2 0:08a4d61cd84c 343 }
mark2r2 0:08a4d61cd84c 344 }
mark2r2 0:08a4d61cd84c 345
mark2r2 0:08a4d61cd84c 346 /**
mark2r2 0:08a4d61cd84c 347 * Cleanup all bin files.
mark2r2 0:08a4d61cd84c 348 */
mark2r2 0:08a4d61cd84c 349 int FirmwareUpdater::cleanupAllBinFiles(void) {
mark2r2 0:08a4d61cd84c 350 struct dirent *p;
mark2r2 0:08a4d61cd84c 351 DIR *dir = opendir("/local");
mark2r2 0:08a4d61cd84c 352 if (dir == NULL) {
mark2r2 0:08a4d61cd84c 353 return -1;
mark2r2 0:08a4d61cd84c 354 }
mark2r2 0:08a4d61cd84c 355 while ((p = readdir(dir)) != NULL) {
mark2r2 0:08a4d61cd84c 356 char *str = p->d_name;
mark2r2 0:08a4d61cd84c 357 if ((strstr(str, ".bin") != NULL) || (strstr(str, ".BIN") != NULL)) {
mark2r2 0:08a4d61cd84c 358 char buf[BUFSIZ];
mark2r2 0:08a4d61cd84c 359 snprintf(buf, sizeof(buf) - 1, "/local/%s", str);
mark2r2 0:08a4d61cd84c 360 if (remove(buf) == 0) {
mark2r2 0:08a4d61cd84c 361 LOG("INFO: Deleted '%s'.\r\n", buf);
mark2r2 0:08a4d61cd84c 362 } else {
mark2r2 0:08a4d61cd84c 363 LOG("ERR : Delete '%s' failed.\r\n", buf);
mark2r2 0:08a4d61cd84c 364 }
mark2r2 0:08a4d61cd84c 365 }
mark2r2 0:08a4d61cd84c 366 }
mark2r2 0:08a4d61cd84c 367 closedir(dir);
mark2r2 0:08a4d61cd84c 368 return 0;
mark2r2 0:08a4d61cd84c 369 }
mark2r2 0:08a4d61cd84c 370
mark2r2 0:08a4d61cd84c 371 /**
mark2r2 0:08a4d61cd84c 372 * Cleanup all bbk(binary backup) files.
mark2r2 0:08a4d61cd84c 373 * 2011/07
mark2r2 0:08a4d61cd84c 374 */
mark2r2 0:08a4d61cd84c 375 int FirmwareUpdater::cleanupAllBbkFiles(void) {
mark2r2 0:08a4d61cd84c 376 struct dirent *p;
mark2r2 0:08a4d61cd84c 377 DIR *dir = opendir("/local");
mark2r2 0:08a4d61cd84c 378 if (dir == NULL) {
mark2r2 0:08a4d61cd84c 379 return -1;
mark2r2 0:08a4d61cd84c 380 }
mark2r2 0:08a4d61cd84c 381 while ((p = readdir(dir)) != NULL) {
mark2r2 0:08a4d61cd84c 382 char *str = p->d_name;
mark2r2 0:08a4d61cd84c 383 if ((strstr(str, ".bbk") != NULL) || (strstr(str, ".BBK") != NULL)) {
mark2r2 0:08a4d61cd84c 384 char buf[BUFSIZ];
mark2r2 0:08a4d61cd84c 385 snprintf(buf, sizeof(buf) - 1, "/local/%s", str);
mark2r2 0:08a4d61cd84c 386 if (remove(buf) == 0) {
mark2r2 0:08a4d61cd84c 387 LOG("INFO: Deleted '%s'.\r\n", buf);
mark2r2 0:08a4d61cd84c 388 } else {
mark2r2 0:08a4d61cd84c 389 LOG("ERR : Delete '%s' failed.\r\n", buf);
mark2r2 0:08a4d61cd84c 390 }
mark2r2 0:08a4d61cd84c 391 }
mark2r2 0:08a4d61cd84c 392 }
mark2r2 0:08a4d61cd84c 393 closedir(dir);
mark2r2 0:08a4d61cd84c 394 return 0;
mark2r2 0:08a4d61cd84c 395 }
mark2r2 0:08a4d61cd84c 396
mark2r2 0:08a4d61cd84c 397 /**
mark2r2 0:08a4d61cd84c 398 * Backup BIN files.
mark2r2 0:08a4d61cd84c 399 * 2011/07
mark2r2 0:08a4d61cd84c 400 */
mark2r2 0:08a4d61cd84c 401 int FirmwareUpdater::BackupBinFiles() {
mark2r2 0:08a4d61cd84c 402 struct dirent *p;
mark2r2 0:08a4d61cd84c 403 DIR *dir = opendir("/local");
mark2r2 0:08a4d61cd84c 404 if (dir == NULL) {
mark2r2 0:08a4d61cd84c 405 return -1;
mark2r2 0:08a4d61cd84c 406 }
mark2r2 0:08a4d61cd84c 407 while ((p = readdir(dir)) != NULL) {
mark2r2 0:08a4d61cd84c 408 char *str = p->d_name;
mark2r2 0:08a4d61cd84c 409 if ((strstr(str, ".bin") != NULL) || (strstr(str, ".BIN") != NULL)) {
mark2r2 0:08a4d61cd84c 410 char buf[BUFSIZ], bakname[BUFSIZ];
mark2r2 0:08a4d61cd84c 411 int len;
mark2r2 0:08a4d61cd84c 412 snprintf(buf, sizeof(buf) - 1, "/local/%s", str);
mark2r2 0:08a4d61cd84c 413 len = strlen(buf);
mark2r2 0:08a4d61cd84c 414 #if 0
mark2r2 0:08a4d61cd84c 415 int dotpos=0;
mark2r2 0:08a4d61cd84c 416 for (int i=len-1; i>=0; i--) {
mark2r2 0:08a4d61cd84c 417 if (buf[i]=='.') {
mark2r2 0:08a4d61cd84c 418 dotpos = i;
mark2r2 0:08a4d61cd84c 419 break;
mark2r2 0:08a4d61cd84c 420 }
mark2r2 0:08a4d61cd84c 421 }
mark2r2 0:08a4d61cd84c 422 strncpy(bakname,buf, dotpos); bakname[dotpos]='\0'; strcat(bakname,".BBK");
mark2r2 0:08a4d61cd84c 423 #endif
mark2r2 0:08a4d61cd84c 424 for (int i=0; i<len; i++) {
mark2r2 0:08a4d61cd84c 425 bakname[i] = buf[i];
mark2r2 0:08a4d61cd84c 426 if (bakname[i]=='.') {
mark2r2 0:08a4d61cd84c 427 bakname[i+1] = '\0';
mark2r2 0:08a4d61cd84c 428 strcat(bakname, "BBK");
mark2r2 0:08a4d61cd84c 429 break;
mark2r2 0:08a4d61cd84c 430 }
mark2r2 0:08a4d61cd84c 431 }
mark2r2 0:08a4d61cd84c 432
mark2r2 0:08a4d61cd84c 433 LOG("INFO: Copy '%s'->'%s'.\r\n", buf,bakname);
mark2r2 0:08a4d61cd84c 434 if (copy(buf,bakname) == 0) {
mark2r2 0:08a4d61cd84c 435 remove(buf);
mark2r2 0:08a4d61cd84c 436 LOG("INFO: Remove '%s'.\r\n", buf);
mark2r2 0:08a4d61cd84c 437 } else {
mark2r2 0:08a4d61cd84c 438 LOG("ERR : Copy '%s'->'%s' failed.\r\n", buf,bakname);
mark2r2 0:08a4d61cd84c 439 }
mark2r2 0:08a4d61cd84c 440 }
mark2r2 0:08a4d61cd84c 441 }
mark2r2 0:08a4d61cd84c 442 closedir(dir);
mark2r2 0:08a4d61cd84c 443 return 0;
mark2r2 0:08a4d61cd84c 444 }
mark2r2 0:08a4d61cd84c 445
mark2r2 0:08a4d61cd84c 446 /**
mark2r2 0:08a4d61cd84c 447 * Create a new binary file name.
mark2r2 0:08a4d61cd84c 448 *
mark2r2 0:08a4d61cd84c 449 * @param ver Version.
mark2r2 0:08a4d61cd84c 450 * @param buf A pointer to a buffer.
mark2r2 0:08a4d61cd84c 451 * @param siz A size of the buffer.
mark2r2 0:08a4d61cd84c 452 *
mark2r2 0:08a4d61cd84c 453 * @return Return 0 if it succeed.
mark2r2 0:08a4d61cd84c 454 */
mark2r2 0:08a4d61cd84c 455 int FirmwareUpdater::createNewBinName(const int ver, char *buf, size_t siz) {
mark2r2 0:08a4d61cd84c 456 if (siz <= name.length()) {
mark2r2 0:08a4d61cd84c 457 return -1;
mark2r2 0:08a4d61cd84c 458 }
mark2r2 0:08a4d61cd84c 459 snprintf(buf, siz - 1, "%s", name.c_str());
mark2r2 0:08a4d61cd84c 460 char nb[32];
mark2r2 0:08a4d61cd84c 461 snprintf(nb, sizeof(nb) - 1, "-%d", ver);
mark2r2 0:08a4d61cd84c 462 if (strlen(buf) + strlen(nb) <= MAXNAMELEN) {
mark2r2 0:08a4d61cd84c 463 strcat(buf, nb);
mark2r2 0:08a4d61cd84c 464 return 0;
mark2r2 0:08a4d61cd84c 465 } else {
mark2r2 0:08a4d61cd84c 466 strcpy(buf + (MAXNAMELEN - strlen(nb)), nb);
mark2r2 0:08a4d61cd84c 467 return 0;
mark2r2 0:08a4d61cd84c 468 }
mark2r2 0:08a4d61cd84c 469 }
mark2r2 0:08a4d61cd84c 470
mark2r2 0:08a4d61cd84c 471 /**
mark2r2 0:08a4d61cd84c 472 * Read a version from a file.
mark2r2 0:08a4d61cd84c 473 *
mark2r2 0:08a4d61cd84c 474 * @param filename file name.
mark2r2 0:08a4d61cd84c 475 * @return A version.
mark2r2 0:08a4d61cd84c 476 */
mark2r2 0:08a4d61cd84c 477 int FirmwareUpdater::readVersionFromFile(const char *filename) {
mark2r2 0:08a4d61cd84c 478 int ver;
mark2r2 0:08a4d61cd84c 479
mark2r2 0:08a4d61cd84c 480 remove("/local/update.log"); // 2011/08
mark2r2 0:08a4d61cd84c 481
mark2r2 0:08a4d61cd84c 482 FILE *fp = fopen(filename, "rb");
mark2r2 0:08a4d61cd84c 483 if (fp == NULL) {
mark2r2 0:08a4d61cd84c 484 fp = fopen(filename, "wt"); // 2011/08
mark2r2 0:08a4d61cd84c 485 if (fp == NULL) { // 2011/08
mark2r2 0:08a4d61cd84c 486 LOG("ERR : Version file '%s' write open failed.\r\n", filename);
mark2r2 0:08a4d61cd84c 487 return -1;
mark2r2 0:08a4d61cd84c 488 }
mark2r2 0:08a4d61cd84c 489 fprintf(fp, "1\r\n"); // 2011/08
mark2r2 0:08a4d61cd84c 490 fclose(fp); // 2011/08
mark2r2 0:08a4d61cd84c 491 return 1; // 2011/08
mark2r2 0:08a4d61cd84c 492 }
mark2r2 0:08a4d61cd84c 493 if (fscanf(fp, "%d", &ver) != 1) {
mark2r2 0:08a4d61cd84c 494 fclose(fp); // 2011/07
mark2r2 0:08a4d61cd84c 495 LOG("ERR : Version file '%s' is invalid.\r\n", filename);
mark2r2 0:08a4d61cd84c 496 return -2;
mark2r2 0:08a4d61cd84c 497 }
mark2r2 0:08a4d61cd84c 498 fclose(fp);
mark2r2 0:08a4d61cd84c 499 LOG("INFO: Version file '%s': Version %d.\r\n", filename, ver);
mark2r2 0:08a4d61cd84c 500 return ver;
mark2r2 0:08a4d61cd84c 501 }
mark2r2 0:08a4d61cd84c 502
mark2r2 0:08a4d61cd84c 503 /**
mark2r2 0:08a4d61cd84c 504 * Read a version from a URL.
mark2r2 0:08a4d61cd84c 505 *
mark2r2 0:08a4d61cd84c 506 * @param url URL.
mark2r2 0:08a4d61cd84c 507 * @return A version.
mark2r2 0:08a4d61cd84c 508 */
mark2r2 0:08a4d61cd84c 509 int FirmwareUpdater::readVersionFromURL(const char *url) {
mark2r2 0:08a4d61cd84c 510 int ver;
mark2r2 0:08a4d61cd84c 511 HTTPText text;
mark2r2 0:08a4d61cd84c 512 client->resetRequestHeaders(); // 2011/08
mark2r2 0:08a4d61cd84c 513 HTTPResult r = client->get(url, &text); // 2011/08
mark2r2 0:08a4d61cd84c 514 if (r != HTTP_OK) {
mark2r2 0:08a4d61cd84c 515 LOG("ERR : Version file '%s' open failed.\r\n", url);
mark2r2 0:08a4d61cd84c 516 return -1;
mark2r2 0:08a4d61cd84c 517 }
mark2r2 0:08a4d61cd84c 518 if (sscanf(text.gets(), "%d", &ver) != 1) {
mark2r2 0:08a4d61cd84c 519 LOG("ERR : Version file '%s' is invalid.\r\n", url);
mark2r2 0:08a4d61cd84c 520 return -2;
mark2r2 0:08a4d61cd84c 521 }
mark2r2 0:08a4d61cd84c 522 LOG("INFO: Version file '%s': Version %d.\r\n", url, ver);
mark2r2 0:08a4d61cd84c 523 return ver;
mark2r2 0:08a4d61cd84c 524 }
mark2r2 0:08a4d61cd84c 525
mark2r2 0:08a4d61cd84c 526 /**
mark2r2 0:08a4d61cd84c 527 * Read a MD5 from a file.
mark2r2 0:08a4d61cd84c 528 * 2011/07
mark2r2 0:08a4d61cd84c 529 * @param filename file name.
mark2r2 0:08a4d61cd84c 530 * @param md5str MD5 string.
mark2r2 0:08a4d61cd84c 531 * @return Error code.
mark2r2 0:08a4d61cd84c 532 */
mark2r2 0:08a4d61cd84c 533 int FirmwareUpdater::readMd5FromFile(const char *filename, char *md5str) {
mark2r2 0:08a4d61cd84c 534 int ret=0;
mark2r2 0:08a4d61cd84c 535 FILE *fp = fopen(filename, "rb");
mark2r2 0:08a4d61cd84c 536 if (fp == NULL) {
mark2r2 0:08a4d61cd84c 537 LOG("ERR : MD5 file '%s' open failed.\r\n", filename);
mark2r2 0:08a4d61cd84c 538 return -1;
mark2r2 0:08a4d61cd84c 539 }
mark2r2 0:08a4d61cd84c 540 if (fscanf(fp, "%32s", md5str) != 1) {
mark2r2 0:08a4d61cd84c 541 fclose(fp);
mark2r2 0:08a4d61cd84c 542 LOG("ERR : MD5 file '%s' is invalid.\r\n", filename);
mark2r2 0:08a4d61cd84c 543 return -2;
mark2r2 0:08a4d61cd84c 544 }
mark2r2 0:08a4d61cd84c 545 fclose(fp);
mark2r2 0:08a4d61cd84c 546 LOG("INFO: MD5 file '%s': Checksum %s.\r\n", filename, md5str);
mark2r2 0:08a4d61cd84c 547 return ret;
mark2r2 0:08a4d61cd84c 548 }