2014-12-27 48 views
1

我試着在ç程序使用md5sum命令,現在即時通訊使用dirent.h得到一個文件夾中的所有文件,現在,我想所有這些文件的全部MD5 ,我這樣做:在C上創建的md5sum

#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 

能否請你解釋一下我爲什麼會這樣呢?謝謝 !

+3

我強烈建議閱讀的['system']文檔(http://pubs.opengroup.org/onlinepubs/9699919799/functions全部解釋/system.html)函數。 – 2014-12-27 16:10:31

+3

你是否意識到系統不會返回'md5'的值,而是命令的退出碼? – 2014-12-27 16:10:53

+3

我是唯一一個在''md5sum dir-> d_name「''上說'wat'的人嗎? – 2014-12-27 16:19:20

回答

3

system功能不返回你你在想什麼。 system用於啓動一個命令,當該命令完成時,它(通常)以退出代碼退出。這是你所追求的價值。

你需要的是命令的輸出,而不是它的返回值。所以你需要的是popen,它允許你啓動一些外部命令並通過管道讀/寫它。例如,請參閱http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html

+0

嘿謝謝,不知道,系統的東西,我在論壇上讀到它,我認爲它會工作,我做了與popen,謝謝:) – Hook 2014-12-27 16:32:33

3

system不返回命令的輸出。要獲得命令的輸出,您需要創建一個進程並將標準輸出流綁定到文件描述符,您可以在另一個進程中讀取數據。有關如何執行此操作的示例,請參閱pipe手冊頁(第2節)。

另一種選擇是使用,提供了一個實施MD5(例如OpenSSL的)的文庫。 EVP_DigestInit(第3節)的手冊頁爲此提供了一個示例。

另一個問題是,你的代碼試圖計算d->d_name摘要,而不是文件哪個名字是d->d_name。您可以使用sprintfstrncat以及適當大小的緩衝區(即靜態字符串部分的長度md5sum加上文件名的最大大小(通常爲256字節,可能在庫實現和文件系統之間有所不同)加上另一個字節以安全終止該字符串(因爲某些實現可能會報告d->d_name中未終止的字符串))。請注意,如果您使用庫進行摘要計算,則這不適用,因爲該庫使用文件名或者需要將文件內容傳遞給庫函數(例如,EVP_DigestUpdate)。

2

第一個問題是,你推出執行"md5sum dir->d_name"一個新的shell進程,這意味着它在「文件」名爲dir->d_name做了md5,而不是使用您的readdir獲得的價值。

因此,您可以添加一個臨時變量,並在運行系統之前準備好該命令。

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 stri ng),這將在目錄中顯示文件的md5。你可以只取出的printf ...

0

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