【问题标题】:Create md5sum in C在 C 中创建 md5sum
【发布时间】:2014-12-27 16:06:28
【问题描述】:

我试图在 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函数的文档
  • 您是否意识到系统不会返回md5 值,而是命令的退出代码?
  • 只有我在"md5sum dir-&gt;d_name"上说“wat”吗?
  • 我强烈建议使用shell script 用于这些目的,通过标准 C 解析/执行 shell 命令是....充其量容易出错,您几乎需要成为专家两种语言。始终使用最适合的工具,即使有人帮助您,其他一切都会让人头疼。
  • 尝试使用 snprintf 将 "md5sum %s" 与文件的实际名称结合起来......如果您在 Posix 系统上,您可能需要 popen() 而不是 system()。 ..不确定win32替代品

标签: c md5sum


【解决方案1】:

system 函数不会返回您的想法。 system 用于启动命令,当该命令完成时,它(通常)以退出代码退出。这就是你捕获的值。

你需要的是命令的输出而不是它的返回值。所以你需要的是popen,它可以让你启动一些外部命令并通过管道读/写它。例如,请参阅http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html

【讨论】:

  • 嘿,谢谢,不知道,我在论坛上读到的系统东西,我认为它可以工作,我用 popen 做了,谢谢:)
【解决方案2】:

system 不返回命令的输出。要获得命令的输出,您需要创建一个进程并将标准输出流绑定到一个文件描述符,您可以在另一个进程中读取数据。有关如何执行此操作的示例,您可以参考 pipe 手册页(第 2 节)。

另一种选择是使用提供 MD5 实现的库(例如 OpenSSL)。 EVP_DigestInit 的手册页(第 3 节)提供了一个示例。

另一个问题是您的代码试图计算d-&gt;d_name 的摘要,而不是名称在d-&gt;d_name 中的文件。您可以将sprintfstrncat 与适当大小的缓冲区一起使用(即静态字符串部分的长度md5sum 加上文件名的最大大小(通常为256 字节,可能因库实现和文件系统而异)加上另一个用于安全终止字符串的字节(因为某些实现可能会在d-&gt;d_name 中报告未终止的字符串)。请注意,如果您使用库进行摘要计算,则这不适用,因为库使用文件名或者您需要将文件内容传递给库函数(例如EVP_DigestUpdate)。

【讨论】:

    【解决方案3】:

    第一个问题是您启动了一个执行"md5sum dir-&gt;d_name" 的新shell 进程,这意味着它对名为dir-&gt;d_name 的“文件”执行md5,而不是使用从readdir 获得的值。

    所以你可以添加一个临时变量,并在运行 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);
    

    至于其他问题(system不会返回md5字符串),这会显示目录中文件的md5。你可以删除 printf ...

    【讨论】:

      【解决方案4】:

      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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-21
        • 2011-08-07
        相关资源
        最近更新 更多