U盘单独线程实现升级文件和转储文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <dirent.h>
#include <time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/inotify.h>
#include <errno.h>
#include <sys/inotify.h>
#include <limits.h>

#include "LedManage.h"
#include "MD5.h"
#include "USBUnloadData.h"
#include "Errorlog.h"

// 全局标志位,默认未插入
volatile int usb_inserted = 0;
volatile int upgrade_done = 0;

#define USB_DIR_LEN 256
char USB_DIR[USB_DIR_LEN];

uint8_t IsConfig=0;
uint8_t log_day = 0;  // 用于存储200Clog参数
uint32_t sam_DL_day, mid_DL_day, dtl_DL_day,btm_DL_day;


//16byte二进制数据转换为32bit十六进制字符串
void HexToStr(char *pbDest, unsigned char *pbSrc, int nLen)
{
    char ddl, ddh;
    int i;

    for (i = 0; i < nLen; i++)
    {
        ddh = 48 + pbSrc[i] / 16;    //48->0ascii
        ddl = 48 + pbSrc[i] % 16;
        if (ddh > 57) ddh = ddh + 7;  //57->9ascii      +7 ->A-F
        if (ddl > 57) ddl = ddl + 7;
        pbDest[i * 2] = ddh;
        pbDest[i * 2 + 1] = ddl;
    }
     pbDest[nLen*2] = '\0';
}

//0成功 1失败 2 U盘容量不足
int USB_FileDLoad_Init(void) {
    FILE *file;
    char buf[256];
    char second_line[256];
    uint64_t freebyte, needbyte;
    MD5_CTX md5;
    unsigned char decrypt[16];
    char md5str[32 + 1];
    char filepath[100]; // 确保字符串足够长以容纳整个路径

    snprintf(filepath, sizeof(filepath), "%s/DRU_200C_USBCONFIG.cfg",USB_DIR);


    // 获取设备序列号字符串长度
    char *deviceSerialNumString = get_usb_serial();
    uint8_t tarstrlen = strlen(deviceSerialNumString);
    printf("number serial:%s\n",deviceSerialNumString);

    // 计算MD5
    MD5Init(&md5);
    MD5Update(&md5, deviceSerialNumString, tarstrlen);
    MD5Final(&md5,decrypt);
    HexToStr(md5str, decrypt, 16);
    printf("md5str: %s\n", md5str);
    // 打开配置文件
    file = fopen(filepath, "r");
    IsConfig=1;
    if (!file) {
        perror("Don't Find File");
        IsConfig=0;
        log_error_to_file(303);
        return 1;
    }


    // 读取第一行并丢弃
    if (fgets(buf, sizeof(buf), file) == NULL) {
        printf("Failed to read the first line\n");
        fclose(file);
        return 1;
    }

    // 读取第二行
    if (fgets(second_line, sizeof(second_line), file) == NULL) {
        printf("Failed to read the second line\n");
        fclose(file);
        return 1;
    }


    // 去掉末尾的换行符
    second_line[strcspn(second_line, "\r\n")] = '\0';
    printf("Second line: %s\n", second_line);

    // 校验第二行的MD5字符串
    if (strncmp(second_line, md5str,32) != 0) {
        printf("Serial failed\n");
        fclose(file);
        log_error_to_file(302);
        IsConfig=0;
        return 1;
    }



    // 读取文件内容并提取参数值
    while (fgets(buf, sizeof(buf), file) != NULL) {
        if (sscanf(buf, "SAM_DL_DAY:%u", &sam_DL_day) == 1) {
            printf("SAM_DL_DAY: %u\n", sam_DL_day);
        } else if (sscanf(buf, "MID_DL_DAY:%u", &mid_DL_day) == 1) {
            printf("MID_DL_DAY: %u\n", mid_DL_day);
        } else if (sscanf(buf, "DTL_DL_DAY:%u", &dtl_DL_day) == 1) {
            printf("DTL_DL_DAY: %u\n", dtl_DL_day);
        } else if (sscanf(buf, "BTM_DL_DAY:%u", &btm_DL_day) == 1) {
            printf("BTM_DL_DAY: %u\n", btm_DL_day);
        } else if (sscanf(buf, "200C_LOG_DAY:%hhu", &log_day ) == 1) {
            printf("200C_LOG_DAY: %u\n", log_day );
        }
    }

    // 获取U盘可用空间
    printf("\nDevice path: %s\n", USB_DIR);
    DiskCapacityInfo capacity = get_disk_capacity(USB_DIR);
    freebyte = capacity.free_space;
    printf("\nFree byte: %llu\n", freebyte);

    // 计算所需空间
    needbyte = ((dtl_DL_day+1) * DTL_MSG_SIZE) +((mid_DL_day+1) * MID_MSG_SIZE) +((sam_DL_day+1) * SAM_MSG_SIZE)+
    		((btm_DL_day+1)*BTM_MSG_SIZE)+((log_day+1) *LOG_200C_SIZE);
    printf("\nNeed byte: %llu\n", needbyte);
    if (needbyte >= freebyte) {
        printf("\n not enough");
        log_error_to_file(304);
        IsConfig=0;
        fclose(file);
        return 2;
    }

    // 关闭文件
    fclose(file);

    return 0;
}


void copy_200C_log_to_usb(const char *emmc_dir, const char *usb_dir) {
    char src_path[512], dst_path[512];
    snprintf(src_path, sizeof(src_path), "%s/200Clog.txt", emmc_dir);
    snprintf(dst_path, sizeof(dst_path), "%s/200Clog.txt", usb_dir);

    printf("Copying %s to %s\n", src_path, dst_path);
    copy_file(src_path, dst_path);
}

char* get_usb_serial() {
    static char serial[256];
    FILE *file = fopen(USB_DEVICE_PATH, "r");
    if (file == NULL) {
        perror("Failed to open serial file");
        return NULL;
    }

    if (fgets(serial, sizeof(serial), file) != NULL) {
        // Remove newline character if present
        size_t len = strlen(serial);
        if (len > 0 && serial[len-1] == '\n') {
            serial[len-1] = '\0';
        }
        fclose(file);
        return serial;
    }

    fclose(file);
    return NULL;
}


DiskCapacityInfo get_disk_capacity(char *device_path) {
    struct statvfs fs_info;
    DiskCapacityInfo capacity_info = {0, 0}; // 初始化为0

    if (statvfs(device_path, &fs_info) == 0) {
        capacity_info.total_space = (uint64_t)fs_info.f_blocks * fs_info.f_bsize;
        capacity_info.free_space = (uint64_t)fs_info.f_bfree * fs_info.f_bsize;
    } else {
        perror("Statvfs error");
    }

    return capacity_info;
}



// 得到USB_DIR
void find_usb_mount() {
    FILE *file;
    char line[256];
    char device[256];
    char mount_point[256];
    const char *file_path = "/proc/mounts";

    file = fopen(file_path, "r");
    if (file == NULL) {
        perror("Failed to open /proc/mounts");
        return;
    }

    while (fgets(line, sizeof(line), file)) {
        if (sscanf(line, "%s %s", device, mount_point) == 2) {
            if (strstr(device, "/dev/sd") == device && strstr(mount_point, "/media") == mount_point) {
                // Ensure the mount_point ends with a slash
                size_t len = strlen(mount_point);
                if (mount_point[len - 1] != '/') {
                    strncat(mount_point, "/", sizeof(mount_point) - len - 1);
                }
                snprintf(USB_DIR, USB_DIR_LEN, "%s", mount_point);
//                printf("Device: %s is mounted on: %s\n", device, mount_point);
                fclose(file);
                return;
            }
        }
    }

    // If no USB device found, clear the USB_DIR
    USB_DIR[0] = '\0';
    fclose(file);
}




void get_date_string(char *buffer, size_t size, int offset_days) {
    time_t rawtime;
    struct tm *timeinfo;

    // 获取当前时间
    time(&rawtime);

    // 根据 offset_days 调整时间
    rawtime += offset_days * 24 * 60 * 60;

    // 转换为本地时间
    timeinfo = localtime(&rawtime);

    // 格式化日期字符串
    strftime(buffer, size, "%Y-%m-%d", timeinfo);
}

void copy_file(const char *src, const char *dst) {
    FILE *src_file = fopen(src, "rb");
    FILE *dst_file = fopen(dst, "wb");
    char buffer[8192];
    size_t bytes;

    if (!src_file || !dst_file) {
        perror("File open error");
        return;
    }

    while ((bytes = fread(buffer, 1, sizeof(buffer), src_file)) > 0) {
        fwrite(buffer, 1, bytes, dst_file);
    }

    fclose(src_file);
    fclose(dst_file);
}

void process_files(const char *dir, const char *usb_dir, uint32_t days, const char *suffix) {
    char date_str[11];
    char src_path[512], dst_path[512];
    struct dirent *entry;//用于存储目录信息
    DIR *dp;
    char *filename_start;
    int i;
    for (i = 0; i <= days; i++) {
        get_date_string(date_str, sizeof(date_str), -i);//负数代表过去天数
        printf("Processing date: %s\n", date_str);

        dp = opendir(dir);
        if (dp == NULL) {
            perror("opendir error");
            return;
        }

        while ((entry = readdir(dp)) != NULL) {
            // 仅处理带有指定后缀的小写文件
            if (strstr(entry->d_name, date_str) != NULL && strstr(entry->d_name, suffix) != NULL) {
                snprintf(src_path, sizeof(src_path), "%s%s", dir, entry->d_name);
                filename_start = strstr(entry->d_name, date_str); // 从文件名截取日期后的部分
                if (filename_start) {
                    snprintf(dst_path, sizeof(dst_path), "%s%s", usb_dir, filename_start);
                }

                printf("Copying %s to %s\n", src_path, dst_path);
                copy_file(src_path, dst_path);
            }
        }

        closedir(dp);
    }
}

void USB_Download(void){



//    // 确认各个参数值在循环外部也正确
//    printf("After file read, SAM_DL_DAY: %u\n", sam_DL_day);
//    printf("After file read, MID_DL_DAY: %u\n", mid_DL_day);
//    printf("After file read, DTL_DL_DAY: %u\n", dtl_DL_day);
//    printf("After file read, BTM_DL_DAY: %u\n", btm_DL_day);

    if (IsConfig) {
    // 处理不同类型的数据
    process_files(SAM_DIR, USB_DIR, sam_DL_day, "_sam");
    process_files(MID_DIR, USB_DIR, mid_DL_day, "_mid");
    process_files(DTL_DIR, USB_DIR, dtl_DL_day, "_dtl");
    process_files(BTM_DIR, USB_DIR, btm_DL_day, "_btm");
    process_files(LOG_DIR, USB_DIR, log_day , "_200Clog");
    }


    return ;
}



// 检测 U 盘是否插入的函数
int detect_usb_insertion() {
    struct stat sb;
    // 检查 /media/sda1 目录是否存在
    if (stat(USB_DIR, &sb) == 0 && S_ISDIR(sb.st_mode)) {
        return 1;
    }
    return 0;
}

// U盘检测线程函数
void* usb_monitor_thread(void* arg) {

    while (1) {
    	find_usb_mount();
        if (detect_usb_insertion()) {
            if (usb_inserted == 0 && upgrade_done == 0) {
                usb_inserted = 1;
                log_error_to_file(301);
                printf("U盘插入,开始升级...\n");

                int ret = system("/opt/update.sh");
                if (WIFEXITED(ret) && WEXITSTATUS(ret) == 1) {
                    printf("升级成功,开始转储...\n");
                    log_error_to_file(305);
                    USB_FileDLoad_Init();
                    USB_Download();
                    printf("转储完成,等待U盘移除...\n");
                } else {
                    printf("升级失败,返回值: %d\n", WEXITSTATUS(ret));
                    log_error_to_file(306);
                }

                // 设置升级完成标志
                upgrade_done = 1;
            }
        } else {
            if (usb_inserted == 1) {
                usb_inserted = 0;
                upgrade_done = 0;
                printf("U盘已移除。\n");
                log_error_to_file(309);
            }
        }
        sleep(5); // 每5秒检测一次
    }
    return NULL;
}


int main() {
	 pthread_t thread_id;
	 LED1_Init();//LED初始化
	    // 创建U盘检测线程
	    if (pthread_create(&thread_id, NULL, usb_monitor_thread, NULL) != 0) {
	        perror("Failed to create thread");
	        return 1;
	    }

    // 主函数继续执行其他工作
    while (1) {
        // 主函数的其他工作
    	LedOnOff(J1_LED,LED_ON_YELLOW,0);
    	LedOnOff(MMC_LED,LED_ON_GREEN,0);
    	log_run_status(3000);

    }

    return 0;
}



#ifndef APP_SOURCE_USBUNLOADDATA_H_
#define APP_SOURCE_USBUNLOADDATA_H_

#define SAM_DIR "/Data/SAM/"
#define MID_DIR "/Data/MID/"
#define DTL_DIR "/Data/DTL/"
#define BTM_DIR "/Data/BTM/"


typedef uint8_t UINT;

#define MID_MSG_SIZE (49.913*1024)
#define SAM_MSG_SIZE (60.81*1024)
#define DTL_MSG_SIZE (150*1024)
#define BTM_MSG_SIZE (150*1024)
#define LOG_200C_SIZE (1024*1024)



#define USB_DEVICE_PATH "/sys/bus/usb/devices/1-1/serial"
#define LOG_DIR "/media/mmc/"

typedef struct {
    uint64_t total_space;
    uint64_t free_space;
} DiskCapacityInfo;

void copy_file(const char *src, const char *dst);
DiskCapacityInfo get_disk_capacity(char *device_path);
char* get_usb_serial(void);
int32_t USB_FileDLoad_Init(void);







#endif /* APP_SOURCE_USBUNLOADDATA_H_ */

先放这,过两天空了来分析一下。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值