2010-04-27 122 views
2

給定一個C文件名,我想確定這個文件是否存在並且對它有執行權限。所有我現在得到的是:檢查文件是否存在,包括路徑上

if(access(filename, X_OK) != 0) { 

但是這不會搜索文件的路徑,也將匹配目錄(我不希望)。任何人都可以請幫忙?

編輯:

作爲替代,看到我在一個子進程運行execvp(),有沒有辦法來檢查execvp(返回值)和信號父進程與死錯誤信息?

+0

@diciu我知道這一點。這就是爲什麼我正在尋找一種方法讓C在這些路徑中以與bash相同的方式搜索文件名。 – Gary 2010-04-27 05:44:30

回答

0

最後不得不設置FD_CLOEXEC標誌上一個新的管道,如果它的EXEC後通過它寫一個錯誤信息失敗了。然後,我可以從父級讀取錯誤消息,並確定exec是否成功。

感謝您的努力,雖然傢伙,upvoted的幫助

2

這段代碼並不完全是你想要的,因爲它只是盲目地執行它的第一件事。但是,您可以修改搜索代碼,以便不要調用execve,而是調用access,然後stat以查明它是否不是目錄。我認爲只有最後一個功能execvepath必須被替換。

在最好的Unix傳統中,代碼是「自我記錄」(即無證)。

#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 

#include "shellpath.h" 

static void *malloc_check(const char *what, size_t n) { 
    void *p = malloc(n); 
    if (p == NULL) { 
    fprintf(stderr, "Cannot allocate %zu bytes to %s\n", n, what); 
    exit(2); 
    } 
    return p; 
} 

static char *strsave(const char *s, const char *lim) { 
    if (lim == NULL) 
    lim = s + strlen(s); 
    char *p = malloc_check("save string", lim - s + 1); 
    strncpy(p, s, lim-s); 
    p[lim-s] = '\0'; 
    return p; 
} 

char ** shellpath(void) { 
    const char *path = getenv("PATH"); 
    if (!path) 
    path = "/bin:/usr/bin:/usr/local/bin"; 

    char **vector = // size is overkill 
    malloc_check("hold path elements", strlen(path) * sizeof(*vector)); 
    const char *p = path; 
    int next = 0; 
    while (p) { 
    char *q = strchr(p, ':'); 
    vector[next++] = strsave(p, q); 
    p = q ? q + 1 : NULL; 
    } 
    vector[next] = NULL; 
    return vector; 
} 

void freeshellpath (char *shellpath[]) { 
    for (int i = 0; shellpath[i]; i++) 
    free(shellpath[i]); 
    free(shellpath); 
} 
unsigned maxpathlen(char *path[], const char *base) { 
    unsigned blen = strlen(base); 
    unsigned n = 0; 
    for (int i = 0; path[i]; i++) { 
    unsigned pn = strlen(path[i]); 
    if (pn > n) n = pn; 
    } 
    return blen+n+1; 
} 



void execvepath(char *path[], const char *base, char *const argv[], 
       char *const envp[]) 
{ 
    if (strchr(base, '/')) 
    execve(base, argv, envp); 
    else { 
    size_t maxlen = maxpathlen(path, base)+1; 
    char *buf = malloc_check("hold path", maxlen); 
    for (int i = 0; path[i]; i++) { 
     snprintf(buf, maxlen, "%s/%s", path[i], base); 
     execve(buf, argv, envp); 
    } 
    } 
} 
+0

嘿 - 感謝您的幫助。這似乎比我想象的要複雜得多。如果文件不存在,是否沒有辦法運行exec函數並讓它返回? – Gary 2010-04-27 05:52:43

1

您可以使用以下功能。 如.. 以下代碼包含一些僞代碼,但應該是很容易實現

if the given path contains the current directory path, 
like /root/a or ./abc, then 
     return access(filename, X_OK) == 0; 

Else - if the given path only contains the filename, 
{ 
     getenv("PATH"); 
     while(iterate the directories in PATH) 
     { 
       if(search(PATH_directory, filename)) 
       { 
         // create the full path string with strcat, strcpy, and/or etc. 
         full_path = blabla 

         if(!is_directory(full_path) && access(filename, X_OK) == 0) 
           return 1; // Yeah~~ We got it!!! 
       } 
     } 

     return 0; // Nah, I don't think there is any of such a file. 
} 
int is_directory(const char* path) 
{ 
     struct stat file_info; 
     return (stat(path, &file_info) == 0) ? S_ISDIR(file_info.st_mode) : 0; 
} 


int search(const char* file_name, const char* path) 
{ 
     struct dirent* dptr; 
     DIR* dirp; 

     if((dirp = opendir(path)) == NULL) 
       return 0; 

     while(dptr = readdir(dirp)) 
     { 
       if(strcmp(file_name, dptr->d_name) == 0) 
       { 
         closedir(dirp); 
         return 1; 
       } 
     } 

     closedir(dirp);  
     return 0; 
} 
相關問題