Files
C-exp-collection/exp0.5/task53.c

198 lines
4.4 KiB
C
Raw Normal View History

2026-05-15 21:25:01 +08:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define INTERVAL_SEC 10
#define LOG_FILE "log"
static unsigned int compute_hash(const char *data, size_t len)
{
unsigned int hash =0;
const unsigned char *p = (const unsigned char *)data;
size_t i,n = len /4;
for ( i = 0; i < n; i++)
{
unsigned int val = (unsigned int)p[i * 4] | ((unsigned int)p[i * 4 + 1] << 8)
| ((unsigned int)p[i * 4 + 2] << 16) | ((unsigned int)p[i * 4 + 3] << 24);
hash += val;
}
size_t rem = len % 4,base = n*4;
for ( i = 0; i < rem; i++)
{
hash += (unsigned int)p[base + i];
}
return hash;
}
static char *read_file(const char *path,size_t *out_len)
{
int fd = open(path,O_RDONLY);
if (fd < 0)
{
return NULL;
}
off_t size = lseek(fd,0,SEEK_END);
if (size < 0)
{
close(fd);
return NULL;
}
lseek(fd,0,SEEK_SET);
char *buf = malloc((size_t)size + 1);
if (!buf)
{
close(fd);
return NULL;
}
ssize_t n = read(fd,buf,(size_t)size);
if (n < 0)
{
free(buf);
close(fd);
return NULL;
}
buf[n] = '\0';
*out_len = (size_t)n;
close(fd);
return buf;
}
static void write_log(unsigned int hash)
{
FILE *fp = fopen(LOG_FILE,"a");
if (!fp)
{
return;
}
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
char time_str[20];
strftime(time_str,sizeof(time_str),"%Y-%m-%d %H:%M:%S",tm_info);
fprintf(fp,"%s hash=%u\n",time_str,hash);
fclose(fp);
}
static void daemonize(void)
{
pid_t pid = fork();
if (pid < 0)
{
exit(1);
}
if (pid > 0)
{
exit(0);
}
setsid();
umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
int main(int argc,char *argv[])
{
//自检模式
if (argc > 1 && strcmp(argv[1],"test") == 0)
{
/* 测试1: 不同内容应产生不同hash值 */
printf("自检模式\n");
const char *test_str = "Hello, World!";
unsigned int h1 = compute_hash(test_str,strlen(test_str));
const char *test_str2 = "Hello, world!"; // 注意 'W' 和 'w'
unsigned int h2 = compute_hash(test_str2,strlen(test_str2));
printf("测试1: hash1=%u, hash2=%u\n",h1,h2);
if (h1 != h2)
printf("通过: 不同内容 -> 不同hash值\n");
else
printf("失败: 不同内容应产生不同的hash值\n");
/* 测试2: 相同内容应产生相同hash值 */
unsigned int h3 = compute_hash(test_str,strlen(test_str));
printf("测试2: hash3=%u\n",h3);
if (h1 == h3)
printf("通过: 相同内容 -> 相同hash值\n");
else
printf("失败: 相同内容应产生相同的hash值\n");
/* 测试3: 读取自身并计算hash */
size_t len;
char *self = read_file("task53.c",&len);
if (self)
{
unsigned int hself = compute_hash(self,len);
printf("测试3: 自身hash=%u, 文件大小=%zu字节\n",hself,len);
free(self);
}
return 0;
}
/*
*
* -f (daemonize), 便
*
*/
int foreground = (argc > 1 && strcmp(argv[1],"-f") == 0);
int interval = INTERVAL_SEC;
if (argc > 2) interval = atoi(argv[2]);
if (interval <= 0) interval = INTERVAL_SEC;
if (!foreground)
{
daemonize();
}
size_t len;
char *prev_data = read_file("test.log",&len);
if (!prev_data) return 1;
unsigned int prev_hash = compute_hash(prev_data,len);
while (1)
{
sleep(interval);
size_t cur_len;
char *cur_data = read_file("test.log",&cur_len);
if (!cur_data)
{
continue;
}
unsigned int cur_hash = compute_hash(cur_data,cur_len);
if (cur_hash != prev_hash)
{
write_log(cur_hash);
free(prev_data);
prev_data = cur_data;
prev_hash = cur_hash;
}
else
{
free(cur_data);
}
}
free(prev_data);
return 0;
}