简体   繁体   English

在C中创建md5sum

[英]Create md5sum in C

Im trying to use the md5sum command in a C program, right now im using dirent.h to get all the files in a folder, now, I want to get all the md5 of all those files, I am doing this: 我正在尝试在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);
}

but when I run it, it says, for example: 但是当我运行它时,它说,例如:

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

Could you please explain me why is this happening? 您能解释一下为什么会这样吗? Thanks ! 谢谢 !

system does not return the output of a command. system不返回命令的输出。 To get the output of a command, you need to create a process and tie the standard output stream to a file descriptor you can read data off in the other process. 要获取命令的输出,您需要创建一个进程并将标准输出流绑定到文件描述符,您可以在另一个进程中读取数据。 For an example on how to do that, you can refer to the pipe man page (section 2). 有关如何执行此操作的示例,请参考pipe手册页(第2节)。

Another option is to use a library that provides an MD5 implementation (eg. OpenSSL). 另一种选择是使用提供MD5实现的库(例如OpenSSL)。 The man page of EVP_DigestInit (section 3) provides an example for that. EVP_DigestInit的手册页(第3节)提供了一个示例。

Another problem is that your code tries to calculate the digest of d->d_name , not the file which name is in d->d_name . 另一个问题是您的代码尝试计算d->d_name的摘要,而不是名称在d->d_name的文件的摘要。 You could use sprintf or strncat with a suitably sized buffer (ie. the length of the static string part md5sum plus the maximum size of the file name (usually 256 bytes, may vary between library implementations and file systems) plus another byte for safely terminating the string (as some implementations may report an unterminated string in d->d_name )). 您可以将sprintfstrncat与适当大小的缓冲区一起使用(即,静态字符串部分md5sum的长度加上文件名的最大大小(通常为256个字节,可能在库实现和文件系统之间有所不同),再加上另一个字节用于安全终止字符串(某些实现可能会在d->d_name报告未终止的字符串)。 Please note that this does not apply if you use a library for digest calculation, as the library uses either the file name or you need to pass the file contents to a library function (eg. EVP_DigestUpdate ). 请注意,如果您使用库进行摘要计算,则此方法不适用,因为该库使用文件名,或者您需要将文件内容传递给库函数(例如EVP_DigestUpdate )。

The system function doesn't returns you what you think. system功能不会返回您的想法。 system is used to launch a command and when that command finished, it (generally) exits with an exit code. system用于启动命令,并在该命令完成后(通常)以退出代码退出。 This is the value you catched. 这就是您捕获的价值。

What you need is the output of the command not its return value. 您需要的是命令的输出而不是其返回值。 So what you need is popen which lets you launch some external command and read/write to it through a pipe. 因此,您需要的是popen ,它使您可以启动一些外部命令并通过管道对其进行读写。 See http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html for example. 例如,请参见http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html

The first problem is that you launch a new shell process executing "md5sum dir->d_name" , meaning it does a md5 on the "file" named dir->d_name , instead of using the value you get from readdir. 第一个问题是您启动一个新的Shell进程,执行"md5sum dir->d_name" ,这意味着它将在名为dir->d_name的“文件”上执行md5 ,而不是使用从readdir获得的值。

So you could add a temp variable, and prepare the command in it prior to running system . 因此,您可以添加一个temp变量,并在运行system之前在其中准备命令。

limits.h is for Linux, adjust it if necessary to get the max length of a path limits.h适用于Linux,必要时进行调整以获取路径的最大长度

...
#include <linux/limits.h>

char temp[PATH_MAX];

then instead of 然后代替

md5 = system("md5sum dir->d_name");

add

strcpy(temp, "md5sum ");
strcat(temp, dir->d_name);
system(temp);

as for the other problem ( system will not return the md5 string), this will display the md5 of the file in the directory. 至于另一个问题( 系统不会返回md5字符串),这将在目录中显示文件的md5。 And you can just remove the printf ... 而且您可以删除printf ...

There is no command in C to return the output of an external command, but there exists popen you can just open a command as a FILE * and read the output from it. C语言中没有命令可以返回外部命令的输出,但是存在popen您可以将命令作为FILE *打开并从中读取输出。 This is how you can do it, and it's all explained within the code 这就是您可以做到的方式,并且代码中均已对此进行了说明

#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