Я думаю, что решение может быть полезно для тех, кто все еще может столкнуться с проблемой.
Вот функция, написанная для имитации программы linux du
. Он рекурсивно просматривает все каталоги и добавляет размеры файлов.
Обратите внимание , что эта функция все еще не завершена, поскольку она ведет себя некорректно на жестких ссылках. Нужно добавить контейнер для хранения файловых дескрипторов, которые указывают на одну и ту же сущность inode, и использовать это, чтобы избавиться от нескольких подсчетов одного и того же файла. lstat()
используется для обработки символических ссылок (также называемых мягкими ссылками), жесткие ссылки - это проблема здесь .
size_t countDiskUsage(const char* pathname)
{
if (pathname == NULL) {
printf("Erorr: pathname is NULL\n");
}
struct stat stats;
if (lstat(pathname, &stats) == 0) {
if (S_ISREG(stats.st_mode)){
return stats.st_size;
}
} else {
perror("lstat\n");
}
DIR* dir = opendir(pathname);
if (dir == NULL) {
perror("Error");
return 0;
}
struct dirent *dirEntry;
size_t totalSize = 4096;
for (dirEntry = readdir(dir); dirEntry != NULL; dirEntry = readdir(dir)) {
long pathLength = sizeof(char) * (strlen(pathname) + strlen(dirEntry->d_name) + 2);
char* name = (char*)malloc(pathLength);
strcpy(name, pathname);
strcpy(name + strlen(pathname), "/");
strcpy(name + strlen(pathname) + 1, dirEntry->d_name);
if (dirEntry->d_type == DT_DIR) {
if (strcmp(dirEntry->d_name, ".") != 0 && strcmp(dirEntry->d_name, "..") != 0) {
totalSize += countDiskUsage(name);
}
} else {
int status = lstat(name, &stats);
if (status == 0) {
totalSize += stats.st_size;
} else {
perror("lstat\n");
}
}
free(name);
}
closedir(dir);
return totalSize;
}