#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "upgrade.h" #include "md5.h" #if 0 #define LOGD log_print #define LOGE log_print #else #define LOGD printf #define LOGE printf #endif typedef struct { char *pbuf; int dlen; int blen; }node_t; typedef struct { uint32_t src; // uint8_t obj; //升级对象,解压后扫描文件,赋值到该变量 uint8_t stat; //当前升级所处状态 uint8_t step; //当前升级所处阶段 pthread_t tid; FILE* log; }upg_handle_t; static upg_handle_t upgHandle; static int log_print(const char *fmt, ...); static int node_free(node_t *nd) { if(!nd) { return -1; } free(nd->pbuf); nd->pbuf = NULL; nd->dlen = 0; nd->blen = 0; return 0; } static int exe_cmd(char *cmd, node_t *nd) { int r=0; FILE *fp=NULL; char *pbuf=NULL; int onelen=1000; int dlen=0,blen=onelen; pbuf = malloc(onelen); if(!pbuf) { return -1; } fp = popen(cmd, "r"); if (fp == NULL) { return -1; } while(1) { r = fread(pbuf+dlen, sizeof(char), onelen, fp); if(r<=0) { LOGE("upgrade relloac %d failed\n", dlen+onelen); break; } dlen += r; if(dlen+onelen>blen) { char* p = realloc(pbuf, dlen+onelen); if(!p) { LOGE("upgrade relloac %d failed\n", dlen+onelen); free(pbuf); pclose(fp); return -1; } pbuf = p; blen = dlen+onelen; } } pclose(fp); nd->pbuf = pbuf; nd->dlen = dlen; nd->blen = blen; return 0; } static int exe_cmd2(char *cmd) { return system(cmd); } //https://blog.csdn.net/qq_38650447/article/details/136284071 static int log_init(void) { char *path=UPG_LOG_PATH; char tmp[200]; if (upgHandle.log) { return -1; } snprintf(tmp, sizeof(tmp), "mkdir -p %s", path); system(tmp); upgHandle.log = fopen(path, "wt"); if (!upgHandle.log) { LOGE("%s open failed\n", path); return -1; } return 0; } static int log_print(const char *fmt, ...) { int r; va_list va; char buf[1000]; va_start(va, fmt); r = vsprintf(buf, fmt, va); va_end(va); if (upgHandle.log) { fprintf(upgHandle.log, "%s", buf); } else { printf("%s", buf); } return 0; } static int log_flush(void) { if (upgHandle.log) { return -1; } fflush(upgHandle.log); return 0; } static int file_exist(char* path) { int r; struct stat st; r = stat(path, &st); if (r == 0) { return 1; } else { return 0; } } static int file_length(char* path) { int r; struct stat st; r = stat(path, &st); if (r) { return -1; } return st.st_size; } static int file_touch(int id) { int r; char tmp[200]; snprintf(tmp, sizeof(tmp), "touch %s/s%d", UPG_FOLDER, id); return system(tmp); // 使用写入模式创建一个新文件 } static int file_untouch(int id) { int r; char tmp[200]; snprintf(tmp, sizeof(tmp), "rm %s/s%d", UPG_FOLDER, id); return system(tmp); // 使用写入模式创建一个新文件 } static int folder_init(void) { char tmp[200]; snprintf(tmp, sizeof(tmp), "mkdir -p %s", RUN_FOLDER); system(tmp); snprintf(tmp, sizeof(tmp), "mkdir -p %s", BAK_FOLDER); system(tmp); snprintf(tmp, sizeof(tmp), "mkdir -p %s", UPG_FOLDER); system(tmp); snprintf(tmp, sizeof(tmp), "mkdir -p %s", DOWN_FOLDER); system(tmp); return 0; } static int file_save(char *path, void *buf, int len) { int r; FILE *fp; fp = fopen(path, "wb"); if(!fp) { LOGE("file_save, fopen %s failed\n", path); return -1; } r = fwrite(buf, 1, len, fp); if(r!=len) { LOGE("file_save %s failed\n", path); r = -1; } else { r = 0; } fclose(fp); return r; } static int file_load(char* path, void* buf, int len) { int r; FILE* fp; fp = fopen(path, "rb"); if (!fp) { LOGE("file_load, fopen %s failed\n", path); return -1; } r = fread(buf, 1, len, fp); if (r != len) { LOGE("file_load %s failed\n", path); r = -1; } else { r = 0; } fclose(fp); return r; } static int file_remove(char *path) { return remove(path); } /* tar pdutar to run/ */ static int file_cover(char *path) { int r; char cmd[200]; snprintf(cmd, sizeof(cmd), "tar -xpf %s -C / > /dev/null 2>&1", path); r = system(cmd); if(r) { LOGE("%s failed\n", cmd); return -1; } return 0; } static int dir_is_empty(char *path) { struct dirent *entry; int is_empty = 1; DIR *dir = opendir(path); if (dir == NULL) { perror("opendir failed\n"); return -1; // 错误处理 } while ((entry = readdir(dir)) != NULL) { // 忽略'.'和'..' if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { is_empty = 0; break; } } closedir(dir); return is_empty; } //when app run success, copy run/* to bak/ static int file_backup(void) { int r; char tmp[100]; char cmd[200]; //dl目录有tar压缩包,则拷贝到bak目录 snprintf(tmp, sizeof(tmp), "%s/%s", DOWN_FOLDER, UPG_TAR_NAME); if(file_exist(tmp)) { LOGD("%s exist\n", tmp); snprintf(cmd, sizeof(cmd), "cp -f %s %s/", tmp, BAK_FOLDER); r = system(cmd); if(r==0) { return 0; } LOGD("cp %s to %s failed\n", tmp, BAK_FOLDER); } else { LOGD("%s not exist\n", tmp); } //bak目录有tar压缩包,则退出 snprintf(tmp, sizeof(tmp), "%s/%s", BAK_FOLDER, UPG_TAR_NAME); if(file_exist(tmp)) { LOGD("%s exist\n", tmp); return 0; } else { LOGD("%s not exist\n", tmp); } //bak目录没有tar压缩包,则将run目录打包存进bak目录 LOGD("tar %s to %s/%s\n", RUN_FOLDER, BAK_FOLDER, UPG_TAR_NAME); snprintf(cmd, sizeof(cmd), "tar -czpPf %s/%s %s > /dev/null 2>&1", BAK_FOLDER, UPG_TAR_NAME, RUN_FOLDER); r = system(cmd); if(r) { LOGE("%s failed, %d\n", cmd, r); return -1; } return 0; } /* when app run failed, copy to bak/ run/ */ static int file_restore(void) { int r; char cmd[200]; snprintf(cmd, sizeof(cmd), "tar -xpf %s/%s -C / > /dev/null 2>&1", DOWN_FOLDER, UPG_TAR_NAME); r = system(cmd); if(r) { LOGE("%s failed, %d\n", cmd, r); return -1; } return 0; } #define CHAR(b) (((b)<=9)?((b)+0x30):((b)-10+0x61)); static void byte2char(char *chr, uint8_t b) { chr[0] = CHAR(b>>4); chr[1] = CHAR(b&0x0f); } static void print_md5(char *s, md5_t *m) { int i; LOGD("__%s", s); for(i=0; i<32; i++) { LOGD("%c", m->data[i]); } LOGD("\n"); } //md5相同返回0,否则返回1 static int md5_check(upgrade_file_t *h) { md5_ctx_t ctx; uint8_t i,tmp[16]; md5_t m1,m2; md5_init(&ctx); md5_update(&ctx, (uint8_t*)h, h->dlen+sizeof(upgrade_file_t)); md5_final(&ctx, tmp); for (i=0; i<16; i++) { byte2char(&m2.data[i*2], tmp[i]); } memcpy(&m1, h->data+h->dlen, sizeof(md5_t)); print_md5("ori md5: ", &m1); print_md5("cal md5: ", &m2); if(memcmp(&m1, &m2, sizeof(md5_t))) { return -1; } return 0; } static int file_split(void) { int r=0,flen; char *fbuf=NULL; char path[200]; snprintf(path, sizeof(path), "%s/%s", DOWN_FOLDER, UPG_PKG_NAME); flen = file_length(path); if(flen<=0) { LOGE("file_length %s failed\n", path); return -1; } fbuf = (char*)malloc(flen); if(!fbuf) { LOGE("malloc %d failed\n", flen); return -1; } r = file_load(path, fbuf, flen); if(r) { LOGE("%s load failed\n", path); return -1; } upgrade_file_t *hfile = (upgrade_file_t*)fbuf; snprintf(path, sizeof(path), "%s/%s", DOWN_FOLDER, UPG_HDR_NAME); r = file_save(path, hfile, sizeof(upgrade_file_t)); if(r) { LOGE("file_save %s failed\n", path); return -1; } snprintf(path, sizeof(path), "%s/%s", DOWN_FOLDER, UPG_TAR_NAME); r = file_save(path, hfile->data, hfile->dlen); if(r) { LOGE("file_save %s failed\n", path); return -1; } snprintf(path, sizeof(path), "%s/%s", DOWN_FOLDER, UPG_PKG_NAME); r = file_remove(path); if(r) { LOGE("file_remove %s failed\n", path); return -1; } return 0; } static int file_check(char *path) { int r=0,flen; char *fbuf=NULL; upgrade_file_t *hfile=NULL; flen = file_length(path); if(flen<=0) { LOGE("file_length %s failed\n", path); return -1; } fbuf = (char*)malloc(flen); if(!fbuf) { LOGE("malloc %d failed\n", flen); return -1; } r = file_load(path, fbuf, flen); if(r) { LOGE("%s load failed\n", path); return -1; } hfile = (upgrade_file_t*)fbuf; if(hfile->magic!=UPG_FILE_MAGIC || hfile->dlen!=flen-sizeof(upgrade_file_t)-sizeof(md5_t)) { r = -1; LOGE("magic: 0x%08x, should be: 0x%08x\n", hfile->magic, UPG_FILE_MAGIC); LOGE("num: %d, should < %d\n", hfile->obj.num, UPGRADE_NUM_MAX); LOGE("stra: %d, should < %d\n", hfile->obj.stra, UPGRADE_STRA_MAX); LOGE("file hdr check failed\n"); goto fail; } r = md5_check(hfile); if(r) { LOGE("md5 check failed\n"); goto fail; } fail: free(fbuf); return r; } static int file_scan(upg_handle_t *h) { //检查DOWN目录,如有升级文件 //udisk检查,如有升级文件,拷贝到DOWN_FOLDER目录,并设置step为UPGRADE_STEP_DOWN //tcard检查,如有升级文件,拷贝到DOWN_FOLDER目录,并设置step为UPGRADE_STEP_DOWN return 0; } static int file_clear(void) { char tmp[200]; snprintf(tmp, sizeof(tmp), "rm -r %s/* %s/*", DOWN_FOLDER, UPG_FOLDER); return system(tmp); } ////////////////////////////////////////////////// static int is_running(char *prog) { FILE *fp; int pid=0; char buf[20]={0}; char command[200]; snprintf(command, sizeof(command), "ps -ef | grep -v grep | grep -w -c %s", prog); fp = popen(command, "r"); if (fp == NULL) { LOGE("execute %s failed: %s", command, strerror(errno)); return 0; } if (fgets(buf, sizeof(buf), fp)) { pid = atoi(buf); } pclose(fp); return (pid)?1:0; } static int app_start(void) { LOGD("____ app_start\n"); if(is_running("smartMonitor.sh")) { return -1; } return system("/usr/sbin/smartMonitor.sh &"); } static int app_stop(void) { LOGD("____ app_stop\n"); return system("killall smartMonitor.sh; /etc/init.d/S90PDUApp stop"); } static int sys_reboot(void) { return system("reboot"); } ////////////////////////////////////////////////// static void* upg_thread(void *arg) { int r=0; int msgid; key_t key; msgbuf_t mb; upg_handle_t *h=(upg_handle_t*)arg; LOGD("upg_thread running\n"); key = ftok(UPG_KEY_PATH, UPG_KEY_SN); if(key<0) { LOGE("ftok %s failed, errno: %d\n", UPG_KEY_PATH, errno); pthread_exit(NULL); } msgid = msgget(key, 0666|IPC_CREAT); LOGD("___ key: %d, msgid: %d\n", key, msgid); //msgctl(msgid, IPC_RMID, NULL); while(1) { r = msgrcv(msgid, &mb, sizeof(mb.evt), 0, 0); if(r<0) { LOGE("___msgrcv failed, %d\n", errno); continue; } LOGD("___ msgrcv evt: 0x%02x\n", mb.evt); switch(mb.evt) { case UPGRADE_EVT_APP_RUNNING: { LOGD("___ smartPDU running!\n"); h->step = UPGRADE_STEP_SUCCESS; } break; case UPGRADE_EVT_UPLOAD_FINISH: { LOGD("___ upgrade package upload finished!\n"); h->step = UPGRADE_STEP_DOWN; file_touch(UPGRADE_STEP_DOWN); } break; } } pthread_exit(NULL); } static int upg_init(upg_handle_t *h) { int r; folder_init(); h->src = UPGRADE_SRC_NONE; h->stat = UPGRADE_STAT_NONE; return pthread_create(&h->tid, NULL, upg_thread, h); } static int upg_check(upg_handle_t *h) { int i,r; char tmp[200]; for(i=1; istep = i+1; break; } LOGD("%s not exist\n", tmp); } return r; } static int upg_handle(upg_handle_t *h) { int r=-1; char tmp[200]; //LOGD("___h->step: %d\n", h->step); while(h->step!=UPGRADE_STEP_NONE) { switch(h->step) { case UPGRADE_STEP_DOWN: { LOGD("___ UPGRADE_STEP_DOWN\n"); //先检查下载目录是否存在pdupkg文件 snprintf(tmp, sizeof(tmp), "%s/%s", DOWN_FOLDER, UPG_PKG_NAME); if(file_exist(tmp)) { file_touch(UPGRADE_STEP_DOWN); h->step = UPGRADE_STEP_SPLIT; } else { LOGD("___ %s not exist, ", tmp); //下载目录不存在pdupkg文件,则继续检查是否存在pdutar文件 snprintf(tmp, sizeof(tmp), "%s/%s", DOWN_FOLDER, UPG_TAR_NAME); LOGD("read %s\n", tmp); if(file_exist(tmp)) { file_touch(UPGRADE_STEP_DOWN); h->step = UPGRADE_STEP_COVER; } else { file_untouch(UPGRADE_STEP_DOWN); h->step = UPGRADE_STEP_NONE; } } } break; case UPGRADE_STEP_SPLIT: { LOGD("___ UPGRADE_STEP_SPLIT\n"); snprintf(tmp, sizeof(tmp), "%s/%s", DOWN_FOLDER, UPG_PKG_NAME); r = file_check(tmp); if(r==0) { r = file_split(); if(r==0) { file_touch(UPGRADE_STEP_SPLIT); h->step = UPGRADE_STEP_COVER; } else { file_untouch(UPGRADE_STEP_SPLIT); h->step = UPGRADE_STEP_NONE; } } else { file_remove(tmp); h->step = UPGRADE_STEP_NONE; } file_untouch(UPGRADE_STEP_DOWN); } break; case UPGRADE_STEP_COVER: { LOGD("___ UPGRADE_STEP_COVER\n"); app_stop(); snprintf(tmp, sizeof(tmp), "%s/%s", DOWN_FOLDER, UPG_TAR_NAME); r = file_cover(tmp); if(r==0) { file_touch(UPGRADE_STEP_COVER); h->step = UPGRADE_STEP_FINISH; sys_reboot(); } else { LOGD("file_cover, delete %s!\n", tmp); file_remove(tmp); snprintf(tmp, sizeof(tmp), "%s/%s", DOWN_FOLDER, UPG_HDR_NAME); file_remove(tmp); h->step = UPGRADE_STEP_NONE; file_untouch(UPGRADE_STEP_COVER); file_restore(); app_start(); } file_untouch(UPGRADE_STEP_DOWN); file_untouch(UPGRADE_STEP_SPLIT); } break; case UPGRADE_STEP_FINISH: { LOGD("___ UPGRADE_STEP_FINISH\n"); h->step = UPGRADE_STEP_NONE; } break; case UPGRADE_STEP_SUCCESS: { LOGD("___ UPGRADE_STEP_SUCCESS\n"); h->step = UPGRADE_STEP_NONE; file_backup(); //启动成功才证明程序有效,可进行备份, 备份成功,删除下载目录中的文件以节省空间 file_clear(); //app_start(); } break; default: LOGD("___ wrong step: %d\n", h->step); r = 1; break; } } return r; } ///////////////////////////////////////////////////////////////////////// int main(void) { int id,r=0; upg_handle_t *h=&upgHandle; LOGD("___upgrade running ...\n"); upg_init(h); upg_check(h); while(1) { upg_handle(h); sleep(1); } return 0; }