繁体   English   中英

在C中创建md5sum

[英]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的文件的摘要。 您可以将sprintfstrncat与适当大小的缓冲区一起使用(即,静态字符串部分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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM