readdir() не работает должным образом для подкаталогов
У меня есть эта функция, которая использует readdir(). Я использую stat(), чтобы получить информацию о файлах, которые находятся в каталоге, который я предоставляю в качестве параметра.
имя_папки [] фактически является абсолютным путем к каталогу, который я хочу прочитать
Функция отлично работает для таких имен, как .
или же ./lfac
но это не работает должным образом для имен, таких как ./lfac/comp
, Я проверяю его, и он читает некоторые файлы из этого каталога, но не все из них. Исполняемый файл помещается в корневой каталог.
У меня есть другая функция (рекурсивная функция), которая также использует readdir () и хранит список с абсолютными путями файлов, которые находятся в каталоге (я даю в качестве параметра) и его подкаталогах. Эта функция имеет ту же проблему.
void content(char folder_name[], char *answer)
{
DIR *diropen;
struct dirent *dirread;
if ((diropen = opendir(folder_name)) == NULL)
{
printf ("Error opening directory %s\n",folder_name);
exit(EXIT_FAILURE);
}
while ((dirread = readdir (diropen)) != NULL)
{
struct stat sb;
memset(&sb, 0, sizeof sb);
char *temp;
temp = (char*) malloc (sizeof(char));
temp[0] = 0;
sprintf(temp,"%s/%s",folder_name,dirread->d_name);
if(strcmp(dirread->d_name,".")==0 || strcmp(dirread->d_name,".")==0)
continue;
if (stat(temp, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
strcat(answer,"File name: ");
strcat(answer,dirread->d_name);
strcat(answer,"\n");
strcat(answer,"File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: strcat(answer,"block device\n"); break;
case S_IFCHR: strcat(answer,"character device\n"); break;
case S_IFDIR: strcat(answer,"directory\n"); break;
case S_IFIFO: strcat(answer,"FIFO/pipe\n"); break;
case S_IFLNK: strcat(answer,"symlink\n"); break;
case S_IFREG: strcat(answer,"regular file\n"); break;
case S_IFSOCK: strcat(answer,"socket\n"); break;
default: strcat(answer,"unknown?\n"); break;
}
sprintf(temp,"I-node number: %ld\n", (long) sb.st_ino); strcat(answer,temp);
.......
}
}
1 ответ
Вы попираете тяжелые ботинки через память вашего компьютера, поэтому вы получаете неопределенное поведение.
Эта часть
char *temp;
temp = (char*) malloc (sizeof(char));
temp[0] = 0;
sprintf(temp,"%s/%s",folder_name,dirread->d_name);
выделяет всего 1 байт памяти, за sizeof(char)
, но следующее, что вы делаете, это пишете в него более длинные строки.
Вам нужно выделить больше, чем это - по крайней мере, столько же, сколько длина пути к вашей папке, плюс разделитель и максимально допустимая длина имени файла. Есть несколько констант, таких как MAX_FILE_PATH
Вы можете использовать, но это зависит от компилятора и системы; Я обычно использую что-то "достаточно большой, кашель", такой как 1024
,
Однако мне не совсем понятно, почему вы выделяете эту память в цикле. (Главным образом потому, что вы нигде не освобождаете его, поэтому я не знаю предполагаемой области видимости.) Вы можете сделать это до цикла, а затем вы можете использовать
char temp[1024];
вместо динамического распределения.
К сожалению, это не решает проблему... Как я уже говорил, у меня есть другая функция, которая имеет ту же проблему, и она не использует динамическое распределение.
void print_files(char folder_name[], char *answer)
{
DIR *diropen;
struct dirent *dirread;
char innerpath[100];
if ((diropen = opendir(folder_name)) == NULL)
{
printf ("Error opening directory %s\n",folder_name);
exit(EXIT_FAILURE);
}
while ((dirread = readdir (diropen)) != NULL)
{
if(strcmp(dirread->d_name,".") != 0 && strcmp(dirread->d_name,"..") != 0)
{
strcat(answer,folder_name);
strcat(answer,"/");
strcat(answer,dirread->d_name);
strcat(answer,"\n");
}
if (dirread->d_type == DT_DIR && strcmp(dirread->d_name,".") != 0 && strcmp(dirread->d_name,"..") != 0)
{
strcpy(innerpath,folder_name);
strcat(innerpath,"/");
strcat(innerpath,dirread->d_name);
print_files(innerpath,answer);
}
}
closedir(diropen);
}