日常工作开发中遇到的问题,将每一个问题写成一个通用函数,方便后续开发复用
#include
char hash_str[33] = {0};
int status = file_md5("tmp.txt",hash_str);
int file_md5(const char *file_name,uint8_t *mds)
{
if(file_name == NULL ){
LOG_ERROR(c,"Error:file_name is null");
return -2;
}
if(mds == NULL){
LOG_ERROR(c,"Error:file_name is null");
return -2;
}
FILE *fp = fopen(file_name, "rb");
if (!fp) {
LOG_ERROR(c,"Error: Failed to open file");
return -1;
}
uint8_t buf[BUFFER_SIZE];
uint8_t md[16];
MD5_CTX ctx;
MD5_Init(&ctx);
size_t n;
while ((n = fread(buf, 1, BUFFER_SIZE, fp)) > 0) {
MD5_Update(&ctx, buf, n);
}
MD5_Final(md, &ctx);
fclose(fp);
// for (int i = 0; i < 16; i++) {
// printf("%02x", md[i]);
// }
// printf("\n");
size_t i, pos = 0;
for (int i = 0; i < 16 && pos < 33 - 1; i++)
{
pos += sprintf(mds + pos, "%02x", md[i]);
}
if (pos < 33) {
mds[pos] = '\0';
}
return 0;
}
加密
#include "gmssl/sm4.h"
/*
input_file:需要加密文件
output_file:加密后的文件
key:密钥
*/
int encrypt_file(const char *input_file, const char *output_file, const unsigned char *key)
{
FILE *in, *out;
SM4_KEY sm4_key;
unsigned char buffer[16], out_buffer[16];
size_t read_len;
//printf("input_file:%s\n",input_file);
if ((in = fopen(input_file, "rb")) == NULL) {
printf("Cannot open input file: %s\n", input_file);
return 1;
}
if ((out = fopen(output_file, "wb")) == NULL) {
printf("Cannot open output file: %s\n", output_file);
fclose(in);
return 1;
}
sm4_set_encrypt_key(&sm4_key, key);
unsigned char size_data;
while ((read_len = fread(buffer, 1, sizeof(buffer), in)) > 0) {
if (read_len < sizeof(buffer))
{
memset(buffer + read_len, 0, sizeof(buffer) - read_len);
sm4_encrypt(&sm4_key, buffer, out_buffer);
fwrite(out_buffer, 1, sizeof(out_buffer), out);
// 记录插入值
size_data = (sizeof(buffer) - read_len) & 0xff;
fwrite(&size_data,1,1,out);
}
else
{
sm4_encrypt(&sm4_key, buffer, out_buffer);
fwrite(out_buffer, 1, sizeof(out_buffer), out);
}
}
fclose(in);
fclose(out);
return 0;
}
解密:
/*
input_file:需要解密文件
output_file:解密后的文件
key:密钥
*/
int decrypt_file(const char *input_file, const char *output_file, const unsigned char *key)
{
m_assert(input_file,"input_file is null",-1);
m_assert(input_file,"output_file is null",-1);
m_assert(key,"key is null",-1);
FILE *in, *out;
SM4_KEY sm4_key;
unsigned char buffer[16], out_buffer[16];
size_t read_len;
uint8_t last_data[BLOCK_SIZE];
size_t last_data_len = 0;
size_t data_len = 0;
if ((in = fopen(input_file, "rb")) == NULL) {
LOG_ERROR(c,"Cannot open input file: %s", input_file);
return -1;
}
if ((out = fopen(output_file, "wb")) == NULL) {
LOG_ERROR(c,"Cannot open output file: %s", output_file);
fclose(in);
return -1;
}
sm4_set_decrypt_key(&sm4_key, key);
// 获取文件大小
fseek(in,0,SEEK_END);
data_len = ftell(in);
char size_data;
int data_size;
if(data_len % 16)
{
fseek(in, -1, SEEK_END);
fread(&size_data, 1, 1, in);
data_size = size_data;
}
fseek(in, 0, SEEK_SET);
data_len -= 1;
while ((read_len = fread(buffer, 1, sizeof(buffer), in)) > 0)
{
if(data_len == 16)
{
sm4_decrypt(&sm4_key, buffer, out_buffer);
fwrite(out_buffer, 1, sizeof(out_buffer)-data_size, out);
break;
}
else
{
sm4_decrypt(&sm4_key, buffer, out_buffer);
fwrite(out_buffer, 1, sizeof(out_buffer), out);
}
data_len -= 16;
}
fclose(in);
fclose(out);
return 0;
}
编译
GMSSL = -lgmssl -lcrypto
GMSSL_LIB = -L/usr/local/gmssl/lib
GMSSL_INCLUDE = -I/usr/local/gmssl/include
压缩
#include
/*
output_filename:压缩包名
input_filenames:需要压缩文件的结构体数组
num_files:有几个文件
*/
typedef struct _encry_file
{
char server_path[MAX_LINE_LENGTH];
char server_encry_file[MAX_LINE_LENGTH];
int status;
}encry_file;
int compress_files(const char* output_filename, encry_file** input_filenames, int num_files)
{
gzFile fout = gzopen(output_filename, "wb");
if (fout == NULL) {
printf("Failed to create output file: %s\n", strerror(errno));
return -1;
}
int ret = Z_OK;
uint8_t buf[BUFFER_SIZE];
int i;
for (i = 0; i < num_files; i++)
{
//printf("%d\n",num_files);
FILE* fin = fopen(input_filenames[i]->server_encry_file, "rb");
if (fin == NULL) {
printf("Failed to open input file: %s\n", strerror(errno));
gzclose(fout);
return -1;
}
// 写入文件名
struct stat st;
if (stat(input_filenames[i]->server_encry_file, &st) != 0)
{
printf("Failed to write filename to output file: %s\n", gzerror(fout, &ret));
gzclose(fout);
fclose(fin);
return -1;
}
printf("File size: %s\t%ld bytes\n",input_filenames[i]->server_encry_file, st.st_size);
ret = gzprintf(fout, "%s^%d\n", input_filenames[i]->server_encry_file,st.st_size);
if (ret <= 0) {
printf("Failed to write filename to output file: %s\n", gzerror(fout, &ret));
gzclose(fout);
fclose(fin);
return -1;
}
// 压缩文件内容
int flush = Z_NO_FLUSH;
size_t size_read = 0;
while ((size_read = fread(buf, 1, BUFFER_SIZE, fin)) > 0) {
ret = gzwrite(fout, buf, size_read);
if (ret < 0) {
printf("Failed to write to output file: %s\n", gzerror(fout, &ret));
gzclose(fout);
fclose(fin);
return -1;
}
}
fclose(fin);
}
gzclose(fout);
return 0;
}
解压:
int decompress_file(const char* input_filename)
{
m_assert(input_filename,"input_filename is null",-1);
gzFile fin = gzopen(input_filename, "rb");
if (fin == NULL) {
LOG_ERROR(c,"Failed to open input file: %s\n", strerror(errno));
return -1;
}
int ret = Z_OK;
uint8_t buf[BUFFER_SIZE];
while (1)
{
char filename_inzip[256] = {0};
int file_size = 0;
if (gzgets(fin, filename_inzip, sizeof(filename_inzip)) == NULL) {
if (gzeof(fin)) {
break;
} else {
LOG_ERROR(c,"Failed to read filename from input file: %s\n", gzerror(fin, &ret));
gzclose(fin);
return -1;
}
}
char* p = strchr(filename_inzip, '\n');
if (p != NULL) {
*p = '\0';
}
char *p1 = strchr(filename_inzip,'^');
if(p1 != NULL){
*p1 = '\0';
}
file_size = atoi(p1+1);
FILE* fout = fopen(filename_inzip, "wb");
if (fout == NULL) {
LOG_ERROR(c,"Failed to create output file: %s\n", strerror(errno));
gzclose(fin);
return -1;
}
size_t size_read = 0;
if(file_size < BUFFER_SIZE)
{
size_read = gzread(fin, buf, file_size);
if (fwrite(buf, 1, size_read, fout) != size_read) {
LOG_ERROR(c,"Failed to write to output file: %s\n", strerror(errno));
fclose(fout);
gzclose(fin);
return -1;
}
fclose(fout);
continue;
}
size_t size_write = BUFFER_SIZE;
while (file_size!=0)
{
if(file_size < BUFFER_SIZE)
{
size_write = file_size;
}
if((size_read = gzread(fin, buf, size_write)) > 0)
{
if (fwrite(buf, 1, size_read, fout) != size_read) {
LOG_ERROR(c,"Failed to write to output file: %s\n", strerror(errno));
fclose(fout);
gzclose(fin);
return -1;
}
}
file_size -= size_write;
}
fclose(fout);
}
gzclose(fin);
return 0;
}
编译:
-lz
unsigned long long get_milliseconds()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (unsigned long long)(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
}
typedef struct _CConfItem
{
char ItemName[50];
char ItemContent[500];
}CConfItem;
int load_config(const char *path_name)
{
FILE *fp;
fp = fopen(path_name,"r");
if(fp == NULL)
return -1;
char linebuf[501];
while(!feof(fp))
{
if(fgets(linebuf,500,fp) == NULL)
continue;
if(linebuf[0] == 0)
continue;
if(*linebuf==';' || *linebuf==' ' || *linebuf=='#' || *linebuf=='\t'|| *linebuf=='\n')
continue;
lblprocstring:
if(strlen(linebuf) > 0)
{
if(linebuf[strlen(linebuf)-1] == 10 || linebuf[strlen(linebuf)-1] == 13 || linebuf[strlen(linebuf)-1] == 32)
{
linebuf[strlen(linebuf)-1] = 0;
goto lblprocstring;
}
}
if(linebuf[0] == 0)
continue;
if(*linebuf=='[')
continue;
char *ptmp = strchr(linebuf,'=');
if(ptmp != NULL)
{
if(i_conf_row < MAX_ROWS)
{
strncpy(config_items[i_conf_row]->ItemName,linebuf,(int)(ptmp-linebuf));
strcpy(config_items[i_conf_row]->ItemContent,ptmp+1);
Rtrim(config_items[i_conf_row]->ItemName);
Ltrim(config_items[i_conf_row]->ItemName);
Rtrim(config_items[i_conf_row]->ItemContent);
Ltrim(config_items[i_conf_row]->ItemContent);
config_items[i_conf_row] = config_items[i_conf_row];
i_conf_row++;
}
else
{
fclose(fp);
return 0;
}
}
}
fclose(fp);
return 0;
}
去除左右空格
void Rtrim(char *string)
{
size_t len = 0;
if(string == NULL)
return;
len = strlen(string);
while(len > 0 && string[len-1] == ' ')
string[--len] = 0;
return;
}
void Ltrim(char *string)
{
size_t len = 0;
len = strlen(string);
char *p_tmp = string;
if( (*p_tmp) != ' ')
return;
while((*p_tmp) != '\0')
{
if( (*p_tmp) == ' ')
p_tmp++;
else
break;
}
if((*p_tmp) == '\0')
{
*string = '\0';
return;
}
char *p_tmp2 = string;
while((*p_tmp) != '\0')
{
(*p_tmp2) = (*p_tmp);
p_tmp++;
p_tmp2++;
}
(*p_tmp2) = '\0';
return;
}
通过name获取value
const char *getstring(const char *p_itemname)
{
for(int i = 0; i<i_conf_row; ++i)
{
if(strcasecmp(config_items[i]->ItemName,p_itemname) == 0)
return config_items[i]->ItemContent;
}
return NULL;
}
int getintDefault(const char *p_itemname,const int def)
{
for(int i = 0; i<i_conf_row; ++i)
{
if(strcasecmp(config_items[i]->ItemName,p_itemname) == 0)
return atoi(config_items[i]->ItemContent);
}
return def;
}
#!/bin/sh
var_name="MASTER_UPD_REQ"
var_value="0"
master_upd_name="/tmp/master_upd.ini"
# 要监控的C语言程序名称
program_name="terminal_pro"
program_name_path="/home/upd_framework"
# 用于存储程序运行状态的文件
status_file="/tmp/program_status.txt"
# 用于记录程序是否正常运行的变量
is_running=0
function set_param
{
# 返回升级结果
gflag=$1
if [ ! -f "$master_upd_name" ]; then
echo "文件 $master_upd_name 不存在"
return 2
fi
# 备份文件
cp "$master_upd_name" "${master_upd_name}.bak"
# 修改配置项
sed -i "s/^MASTER_UPD_STATUS=0$/MASTER_UPD_STATUS=$gflag/" "${master_upd_name}.bak"
mv "${master_upd_name}.bak" $master_upd_name
if [ $? -ne 0 ]; then
return 3
fi
return 0
}
# 检查程序是否在运行
check_program_running() {
#pgrep -x "$program_name" > /dev/null
if ps aux | grep "$program_name" | grep -v grep > /dev/null ; then
is_running=1
else
#echo "程序 $program_name 没有运行。"
is_running=0
fi
}
# 检查程序是否正常执行的函数
monitor_program()
{
if [ -f $master_upd_name ]
then
# 判断是否重启程序
while true; do
sleep 1
#echo "正在主程序升级更新程序完成"
var_line=$(grep -E "^$var_name[[:space:]]*=" "$master_upd_name")
var_values=$(echo "$var_line" | cut -d= -f2 | tr -d '[:space:]')
if [ "$var_value" = "$var_values" ]; then
#echo "主程序更新程序完成"
break
fi
done
fi
check_program_running
if [ $is_running -eq 1 ]; then
echo "The program $program_name is running normally." > $status_file
else
cd $program_name_path
./$program_name &
check_program_running
if [ $is_running -eq 1 ]; then
if [ -f $master_upd_name ]
then
echo "重启新的主程序成功"
set_param 1
fi
else
if [ -f $master_upd_name ]
then
echo "重启新的主程序失败"
set_param 0
fi
fi
fi
}
# 每隔10秒检查一次程序状态
while true; do
monitor_program
sleep 10
done
将zlog的功能进行了裁剪,使用功能整合到了两个文件中
#include "log.h"
int main()
{
int rc = log_init("main.conf");
if (rc) {
printf("init failed\n");
return -1;
}
// 创建分类
log_category_t *c = log_get_category("my_stdout");
log_category_t *c1 = log_get_category("my_aa");
log_category_t *c2 = log_get_category("my_time");
log_category_t *c3 = log_get_category("my_cat");
if (!c) {
printf("get cat fail\n");
log_fini();
return -2;
}
// 按照my_stdout规则进行打印
LOG_DEBUG(c,"hello world");
LOG_INFO(c, "hello world");
LOG_NOTICE(c, "hello world");
LOG_WARN(c, "hello world");
LOG_ERROR(c, "hello world");
LOG_FATAL(c, "hello world");
// 说明只能用来答应16进制字符串
LOG_HEX(c,"71B");
// 按照my_cat规则进行打印
LOG_DEBUG(c3,"hello world");
LOG_INFO(c3, "hello world");
LOG_NOTICE(c3, "hello world");
LOG_WARN(c3, "hello world");
LOG_ERROR(c3, "hello world");
LOG_FATAL(c3, "hello world");
// 说明只能用来答应16进制字符串
LOG_HEX(c3,"71B");
// 释放内存
log_fini();
return 0;
}
[formats]
# %d打日志的时间
# %-8us 右补充空格,如果微秒小于8个字符长
# %-5V 日志级别大写,右补充空格,如果日志级别小于5个字符长
# %-8p 进程ID 右补充空格,如果进程ID小于8个字符长
# %T 线程ID长整型
# %F 源代码文件名
# %L 源代码行数
# %m 用户输出信息
# %n 回车
simple = "%d %-8us %-5V[%-6p %T %F %L] %m%n"
# 表示只输出用户输出信息和日志其他什么都不输出
c1 = "%m%n"
# 多打印一个日志等级 小于5个字符右边补空格
c2 = "%-5V %m%n"
[rules]
# my_stdout[分类名] info[类型日志] >stdout[输出到控制台] ;simple[日志输出格式]
# my_stdout大于info类型的日志都会按照simple格式输出到控制台
my_stdout.debug >stdout;simple
# my_aa分类大于info日志等级的输出到日志文件中
my_aa.info "./aa.log";c1
my_time.* "./bb.log";c2
# my_cat下所有类型日志输出到 aa.加当前时间.log日志中
# 每个日志文件大小不能超过20MB,
# 超过创建新文件放在当前目录下aa.当前时间.log.(序号)
# 归档文件保存最多5个
# #s序号会混动一直递增(归档文件后面的序号)
# #r序号不会动
my_cat.* "aa.%d(%F).log",20MB*5~"aa.%d(%F).#r.log";simple
my_thread.* "./aa.log";simple
#!/bin/bash
args=("$@")
zip_name="${args[4]}.bak"
# 定义一个空数组来保存所需信息
declare -a local_oper_type
declare -a loacl_path
declare -a terminal_path
del_dir="del"
exec_file="exec"
config_file_name="pack.ini"
root_dir="/root/test-2023-05-08/ini_parse/pack_c++/"
terminal_dir="/root/test-2023-05-08/ini_parse/pack_c++/sh_test"
make_="/root/build.sh"
make_pack="/root/build.sh pack"
function read_config_file
{
read_flag=0
while IFS= read -r line || [[ -n "$line" ]]; do
if [[ $line == *"[loacl_path]"* ]]; then
read_flag=1
elif [[ $line == *"[terminal_path]"* ]]; then
read_flag=2
fi
if [[ $line != *"="* ]]; then
continue
fi
if [ $read_flag -eq 1 ]; then
if [[ ${line:0:1} != "#" ]]; then
key=$(echo $line | awk -F '=' '{print $1}' | tr -d ' ')
local_oper_type+=("$key")
else
value=$(echo $line | cut -d'=' -f2 | tr -d ' ')
loacl_path+=("$root_dir$value")
fi
elif [ $read_flag -eq 2 ]; then
terminal_value=$(echo $line | cut -d'=' -f2 | tr -d ' ')
terminal_path+=("$terminal_dir$terminal_value")
fi
done < $config_file_name
return 0
}
function copy_upd_pack
{
# 检查两个数组的长度是否相同
if [ ${#loacl_path[@]} -ne ${#terminal_path[@]} ]; then
return 7
fi
# 循环拷贝数组1中的数据到数组2的目录下
for ((i=0; i<${#loacl_path[@]}; i++)); do
if [ "${local_oper_type[i]}" == "$del_dir" ]; then
rm -rf "${terminal_path[i]}"
continue
fi
prefix=$(echo "${terminal_path[i]}" | sed "s|/[^/]*$||")
if [ ! -d "$prefix" ]
then
mkdir -p "$prefix"
fi
# 拷贝到临时目录下
cp "${loacl_path[i]}" "${terminal_path[i]}.tmp"
if [ $? -ne 0 ]; then
echo "拷贝失败:${loacl_path[i]} ${terminal_path[i]}.tmp"
return 8
fi
done
# 移动目录 原子操作
for ((i=0; i<${#loacl_path[@]}; i++)); do
if [ "${local_oper_type[i]}" == "$del_dir" ]; then
continue
fi
mv "${terminal_path[i]}.tmp" "${terminal_path[i]}"
if [ $? -ne 0 ]; then
echo "移动失败:${terminal_path[i]}"
return 9
fi
if [ "${local_oper_type[i]}" == "$exec_file" ]; then
chmod a+x "${terminal_path[i]}"
fi
done
return 0
}
read_config_file
if [ $? -ne 0 ]; then
echo "读取配置文件失败"
exit 1
fi
copy_upd_pack
if [ $? -ne 0 ]; then
echo "拷贝出错了"
exit 2
fi
# 执行./build
# $make_
# $make_pack
echo "local_oper_type: ${local_oper_type[@]}"
echo "loacl_path: ${loacl_path[@]}"
echo "terminal_path: ${terminal_path[@]}"
[loacl_path]
del = #1
add = #2
add = #3
exec = #4
#1 = 1.log
#2 = yaml
#3 = yaml.c
#4 = main
[terminal_path]
#1 = /1.log
#2 = /test-2/yaml
#3 = /test-3/yaml.c
#4 = /main