[英]Create md5sum in C
我正在尝试在C程序中使用md5sum
命令,现在我正在使用dirent.h
获取文件夹中的所有文件,现在,我想获取所有这些文件的所有md5 ,我正在这样做:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <dirent.h>
int main(void){
char *word = ".gz";
int i=0;
char *word2 = ".";
char *word3 = "..";
unsigned int md5;
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d) {
while ((dir = readdir(d)) != NULL)
{
if((strstr(dir->d_name, word) == NULL) && (strcmp(dir->d_name, word2) != 0) && (strcmp(dir->d_name, word3)!= 0)) {
md5 = system("md5sum dir->d_name");
printf("The md5 of %s is %d\n", dir->d_name, md5);
}
}
}
return(0);
}
但是当我运行它时,它说,例如:
md5sum: dir-: No such file or directory
The md5 of ej1_signal.c is 256
md5sum: dir-: No such file or directory
The md5 of pipeL.c is 256
您能解释一下为什么会这样吗? 谢谢 !
system
不返回命令的输出。 要获取命令的输出,您需要创建一个进程并将标准输出流绑定到文件描述符,您可以在另一个进程中读取数据。 有关如何执行此操作的示例,请参考pipe
手册页(第2节)。
另一种选择是使用提供MD5实现的库(例如OpenSSL)。 EVP_DigestInit
的手册页(第3节)提供了一个示例。
另一个问题是您的代码尝试计算d->d_name
的摘要,而不是名称在d->d_name
的文件的摘要。 您可以将sprintf
或strncat
与适当大小的缓冲区一起使用(即,静态字符串部分md5sum
的长度加上文件名的最大大小(通常为256个字节,可能在库实现和文件系统之间有所不同),再加上另一个字节用于安全终止字符串(某些实现可能会在d->d_name
报告未终止的字符串)。 请注意,如果您使用库进行摘要计算,则此方法不适用,因为该库使用文件名,或者您需要将文件内容传递给库函数(例如EVP_DigestUpdate
)。
system
功能不会返回您的想法。 system
用于启动命令,并在该命令完成后(通常)以退出代码退出。 这就是您捕获的价值。
您需要的是命令的输出而不是其返回值。 因此,您需要的是popen
,它使您可以启动一些外部命令并通过管道对其进行读写。 例如,请参见http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html 。
第一个问题是您启动一个新的Shell进程,执行"md5sum dir->d_name"
,这意味着它将在名为dir->d_name
的“文件”上执行md5
,而不是使用从readdir获得的值。
因此,您可以添加一个temp变量,并在运行system之前在其中准备命令。
limits.h
适用于Linux,必要时进行调整以获取路径的最大长度
...
#include <linux/limits.h>
char temp[PATH_MAX];
然后代替
md5 = system("md5sum dir->d_name");
加
strcpy(temp, "md5sum ");
strcat(temp, dir->d_name);
system(temp);
至于另一个问题( 系统不会返回md5字符串),这将在目录中显示文件的md5。 而且您可以删除printf ...
C语言中没有命令可以返回外部命令的输出,但是存在popen
您可以将命令作为FILE *
打开并从中读取输出。 这就是您可以做到的方式,并且代码中均已对此进行了说明
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int main(void)
{
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d == NULL)
return -1;
while ((dir = readdir(d)) != NULL)
{
char command[sizeof dir->d_name + 10];
struct stat st;
FILE *pipe;
if (stat(dir->d_name, &st) == -1)
continue;
/* check if the entry is a directory, md5sum does not work with them */
if (S_ISDIR(st.st_mode) != 0)
continue;
/*
* md5sum dir->d_name will pass `dir->d_name` as the argument to the md5sum command,
* we need to build the command string, I like snprintf in this case
*/
snprintf(command, sizeof command, "md5sum \"%s\"", dir->d_name);
/*
* Open the pipe, it will execute the new command in a new process (fork)
* and create a pipe for communication with the current porcess
*/
pipe = popen(command, "r");
if (pipe != NULL)
{
char md5[33];
/* read the md5 digest string from the command output */
fread(md5, 1, sizeof md5 - 1, pipe);
/* append a null terminator */
md5[sizeof md5 - 1] = '\0';
printf("The md5 of %s is %s\n", dir->d_name, md5);
}
/* close the pipe */
pclose(pipe);
}
/* you should always call closedir() if opendir() succeded */
closedir(d);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.