Linux C语言工具函数

阅读: 评论:0

Linux C语言工具函数

Linux C语言工具函数

文章目录

  • 1、概述
  • 2、计算文件md5值
  • 3、gmssl国密sm4加解密
  • 4、使用zlib库压缩解压
  • 5、获取毫秒时间
  • 6、ini类型配置文件读取
  • 7、守护脚本
  • 8、log日志使用
  • 9、拷贝脚本

1、概述

日常工作开发中遇到的问题,将每一个问题写成一个通用函数,方便后续开发复用

2、计算文件md5值

#include <openssl/md5.h>
char hash_str[33] = {0};
int status = file_md5(&#",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] = '';}return 0;
}

3、gmssl国密sm4加解密

加密

#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:%sn",input_file);if ((in = fopen(input_file, "rb")) == NULL) {printf("Cannot open input file: %sn", input_file);return 1;}if ((out = fopen(output_file, "wb")) == NULL) {printf("Cannot open output file: %sn", 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

4、使用zlib库压缩解压

压缩

#include <zlib.h>
/*
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: %sn", strerror(errno));return -1;}int ret = Z_OK;uint8_t buf[BUFFER_SIZE];int i;for (i = 0; i < num_files; i++) {//printf("%dn",num_files);FILE* fin = fopen(input_filenames[i]->server_encry_file, "rb");if (fin == NULL) {printf("Failed to open input file: %sn", 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: %sn", gzerror(fout, &ret));gzclose(fout);fclose(fin);return -1;}printf("File size: %st%ld bytesn",input_filenames[i]->server_encry_file, st.st_size);ret = gzprintf(fout, "%s^%dn", input_filenames[i]->server_encry_file,st.st_size);if (ret <= 0) {printf("Failed to write filename to output file: %sn", 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: %sn", 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: %sn", 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: %sn", gzerror(fin, &ret));gzclose(fin);return -1;}}char* p = strchr(filename_inzip, 'n');if (p != NULL) {*p = '';}char *p1 = strchr(filename_inzip,'^');if(p1 != NULL){*p1 = '';}file_size = atoi(p1+1);FILE* fout = fopen(filename_inzip, "wb");if (fout == NULL) {LOG_ERROR(c,"Failed to create output file: %sn", 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: %sn", 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: %sn", strerror(errno));fclose(fout);gzclose(fin);return -1;}}file_size -= size_write;}fclose(fout);}gzclose(fin);return 0;
}

编译:

-lz

5、获取毫秒时间

unsigned long long get_milliseconds()
{struct timeval tv;gettimeofday(&tv, NULL);return (unsigned long long)(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
}

6、ini类型配置文件读取

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) != ''){if( (*p_tmp) == ' ')p_tmp++;elsebreak;}if((*p_tmp) == ''){*string = '';return;}char *p_tmp2 = string; while((*p_tmp) != ''){(*p_tmp2) = (*p_tmp);p_tmp++;p_tmp2++;}(*p_tmp2) = '';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;
}

7、守护脚本

#!/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/"# 用于记录程序是否正常运行的变量
is_running=0function set_param
{# 返回升级结果gflag=$1if [ ! -f "$master_upd_name" ]; thenecho "文件 $master_upd_name 不存在"return 2fi# 备份文件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_nameif [ $? -ne 0 ]; thenreturn 3fireturn 0    
}# 检查程序是否在运行
check_program_running() {#pgrep -x "$program_name" > /dev/nullif ps aux | grep "$program_name" | grep -v grep > /dev/null ; thenis_running=1else#echo "程序 $program_name 没有运行。"is_running=0fi
}# 检查程序是否正常执行的函数
monitor_program() 
{if [ -f $master_upd_name ]then# 判断是否重启程序while true; dosleep 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 "主程序更新程序完成"breakfidoneficheck_program_runningif [ $is_running -eq 1 ]; thenecho "The program $program_name is running normally." > $status_fileelsecd $program_name_path./$program_name &check_program_runningif [ $is_running -eq 1 ]; thenif [ -f $master_upd_name ]thenecho "重启新的主程序成功"set_param 1fielseif [ -f $master_upd_name ]thenecho "重启新的主程序失败"set_param 0fififi
}# 每隔10秒检查一次程序状态
while true; domonitor_programsleep 10
done

8、log日志使用

将zlog的功能进行了裁剪,使用功能整合到了两个文件中

#include "log.h"int main()
{int rc = log_init(&#f");if (rc) {printf("init failedn");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 failn");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";c1my_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";simplemy_thread.* "./aa.log";simple

9、拷贝脚本

#!/bin/bash
args=("$@")
zip_name="${args[4]}.bak"# 定义一个空数组来保存所需信息
declare -a local_oper_type
declare -a loacl_path
declare -a terminal_pathdel_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=0while IFS= read -r line || [[ -n "$line" ]]; doif [[ $line == *"[loacl_path]"* ]]; thenread_flag=1elif [[ $line == *"[terminal_path]"* ]]; thenread_flag=2fiif [[ $line != *"="* ]]; thencontinuefiif [ $read_flag -eq 1 ]; thenif [[ ${line:0:1} != "#" ]]; thenkey=$(echo $line | awk -F '=' '{print $1}' | tr -d ' ')local_oper_type+=("$key")elsevalue=$(echo $line | cut -d'=' -f2 | tr -d ' ')loacl_path+=("$root_dir$value")fielif [ $read_flag -eq 2 ]; thenterminal_value=$(echo $line | cut -d'=' -f2 | tr -d ' ')terminal_path+=("$terminal_dir$terminal_value")fidone < $config_file_namereturn 0
}function copy_upd_pack
{# 检查两个数组的长度是否相同if [ ${#loacl_path[@]} -ne ${#terminal_path[@]} ]; thenreturn 7  fi# 循环拷贝数组1中的数据到数组2的目录下for ((i=0; i<${#loacl_path[@]}; i++)); doif [ "${local_oper_type[i]}" == "$del_dir" ]; thenrm -rf "${terminal_path[i]}"continuefiprefix=$(echo "${terminal_path[i]}" | sed "s|/[^/]*$||")if [ ! -d "$prefix" ]thenmkdir -p "$prefix"fi# 拷贝到临时目录下cp "${loacl_path[i]}" "${terminal_path[i]}.tmp"if [ $? -ne 0 ]; thenecho "拷贝失败:${loacl_path[i]}  ${terminal_path[i]}.tmp"return 8fidone# 移动目录 原子操作for ((i=0; i<${#loacl_path[@]}; i++)); doif [ "${local_oper_type[i]}" == "$del_dir" ]; thencontinuefimv "${terminal_path[i]}.tmp" "${terminal_path[i]}"if [ $? -ne 0 ]; thenecho "移动失败:${terminal_path[i]}"return 9fiif [ "${local_oper_type[i]}" == "$exec_file" ]; thenchmod a+x "${terminal_path[i]}"fidonereturn 0
}read_config_file
if [ $? -ne 0 ]; thenecho "读取配置文件失败"exit 1
ficopy_upd_pack
if [ $? -ne 0 ]; thenecho "拷贝出错了"exit 2
fi# 执行./build
# $make_
# $make_packecho "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

本文发布于:2024-02-04 22:56:06,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170718270560490.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:函数   语言   工具   Linux
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23