[英]Do I need to Allocate Memory for a Dirent Structure
我目前正在編寫一個程序,它將使用POSIX目錄函數遞歸刪除給定目錄。 但是我遇到了readdir()及其對應的dirent結構的問題。 我在readdir的文檔中讀到,對函數的多次調用將覆蓋函數返回的結構中保存的數據。 所以我認為readdir()必須為結構本身創建memmory,然后簡單地將指針地址重新分配給捕獲它的返回值的結構。 我測試了這個理論,我是正確的readdir()為它的成員d_name分配了memmory。 我遇到的問題是當目錄流為空時readdir返回一個NULL指針,所以我使用帶有條件(dirent_ptr!= NULL)的while循環來迭代整個目錄。 但是因為readdir()將處理結構的memmory分配,所以我只是聲明一個dirent結構,讓readdir()完成它的工作。 由於某種原因unforrtatnly dirent結構初始化為NULL(或者它可能是我的編譯器)所以我的循環永遠不會啟動,因為它的條件語句不是initialy true。 所以我想我的問題是我在這里做錯了什么?
這是重要的變量聲明和包含的庫。 請注意,所有這些變量都是全局聲明的。
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
int recursive_delete(const char *path);
int file_delete(const char *path, int file_size);
struct dirent *direntp;
struct stat *statp;
struct switches
{
int verbose;
int no_prompt;
int continue_if_error;
int files_only;
}; struct switches switches;
我只是cd到作為參數給出的路徑,而不是解析相對路徑,然后我使用。 和..移動的通配符拋出directorys,使相對路徑(d_names)有效。 此外,開關結構只包含命令行開關,應該被忽略,我知道以下代碼中的錯誤,但是我無法解決它們,因為我無法解決上述問題。
int recursive_delete(const char *path)
{
DIR *dirp;
int return_value = 0;
int recursive_return_value = 0;
if((chdir(path)) == -1)
{
perror("ERROR(3)");
return 1;
}
printf("CDED to \"%s\"\n", path);
dirp = opendir(".");
if(dirp == NULL)
{
perror("ERROR(4)");
return 1;
}
printf("OPENED \"%s\"\n", path);
while(direntp != NULL)
{
direntp = readdir(dirp);
if( (direntp == NULL) && (errno != 0) )
{
perror("ERROR(5)");
return 1;
}
printf("READ \"%s\" FROM \"%s\"\n", direntp->d_name, path);
if( (strcmp(direntp->d_name, ".")!=0) && (strcmp(direntp->d_name, "..")!=0) )
{
if((stat(direntp->d_name, statp)) == -1)
{
perror("ERROR(6)");
return 1;
}
printf("STATED \"%s\"\n", direntp->d_name);
if(S_ISREG(statp->st_mode))
{
printf("DELETING \"...\\%s\\%s\"\n", path, direntp->d_name);
return_value += file_delete(direntp->d_name, statp->st_size);
if( (!switches.continue_if_error) && (return_value != 0) )
{
break;
}
}
else if(S_ISDIR(statp->st_mode))
{
printf("\n\n\nCALLING RECURSIVE DELETE with \"%s\"\n", direntp->d_name);
recursive_return_value = recursive_delete(direntp->d_name);
return_value += recursive_return_value;
if( (!switches.continue_if_error) && (recursive_return_value != 0) )
{
break;
}
if( (!switches.files_only) && (recursive_return_value == 0) )
{
if((chdir("..")) == -1)
{
perror("ERROR(6)");
return 1;
}
printf("CDED BACK TO \"%s\" FROM \"%s\"\n", path, direntp->d_name);
if((rmdir(direntp->d_name)) == -1)
{
perror("ERROR(7)");
return 1;
}
if(switches.verbose)
{
printf("DELETED DIRECTORY \"...\\%s\\\"\n\n\n", direntp->d_name);
}
}
}
}
}
return return_value;
}
從附加的代碼中,不清楚direntp的初始化位置(在while
循環之前)。 可能嘗試類似的東西:
direntp = readdir(dirp);
while(direntp != NULL)
{
// all your work here
direntp = readdir(dirp);
}
此模式確保為您的while循環初始化和更新direntp
。 但是,在你的代碼的第二眼看來,我並不完全確定while循環應該首先做什么。 direntp
或dirp
如何在循環中改變?
你可以通過if
測試(而不是while
)來逃避,只需讓遞歸調用處理“循環”效果......
您的代碼結構應該類似於此(為清晰起見,省略了大多數錯誤檢查):
int recursive_delete(const char *path)
{
DIR* dirp = NULL;
int return_value = 0;
char* initial_cur_dir = malloc(1000);
getcwd(initial_cur_dir, 1000);
chdir(path);
dirp = opendir(".");
while (dirp != NULL)
{
struct dirent* direntp;
struct stat stat;
direntp = readdir(dirp);
if (direntp == NULL)
break;
stat(direntp->d_name, &stat);
if (S_ISDIR(statp->st_mode))
{
if (strcmp(direntp->d_name, ".") && strcmp(direntp->d_name, ".."))
{
return_value += recursive_delete(direntp->d_name);
}
}
else if (S_ISREG(statp->st_mode))
{
unlink(direntp->d_name);
}
}
if (initial_cur_dir != NULL)
{
chdir(initial_cur_dir);
rmdir(path);
}
ErrorLabel: // you should goto here when an error is detected
if (dirp != NULL)
{
closedir(dirp);
}
if (initial_cur_dir != NULL)
{
chdir(initial_cur_dir);
free(initial_cur_dir);
}
return return_value;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.