#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <limits.h>
#define INITSIZE 100
typedef struct entry {
struct stat stat;
char name[NAME_MAX];
} entry_t;
typedef struct dir {
entry_t **entries;
size_t count;
size_t max_name_len;
char *path;
} dir_t;
dir_t *dir = NULL;
dir_t* look_dir(const char* path) {
DIR *dp;
struct dirent *dirent;
dir_t *dir;
entry_t *entry;
size_t n = INITSIZE;
dir = malloc(sizeof(dir_t));
dir->entries = malloc(sizeof(entry_t *) * n);
dir->count = 0;
dir->max_name_len = 0;
dir->path = malloc(strlen(path)+1);
strcpy(dir->path, path);
dp = opendir(path);
if (dp == NULL) {
perror("opendir");
exit(1);
}
while ((dirent = readdir(dp)) != NULL) {
size_t len;
len = strlen(dirent->d_name);
if (len > dir->max_name_len)
dir->max_name_len = len;
if (dir->count >= n) {
n *= 2;
dir->entries = realloc(dir->entries, sizeof(entry_t *) * n);
}
entry = malloc(sizeof(entry_t));
strcpy(entry->name, dirent->d_name);
if (stat(entry->name, &entry->stat) < 0) {
perror("stat");
exit(1);
}
dir->entries[dir->count++] = entry;
}
dir->entries[dir->count] = NULL;
closedir(dp);
return dir;
}
void free_dir(dir_t *dir) {
if (dir == NULL) return;
entry_t **pentry;
for (pentry = dir->entries; *pentry != NULL; pentry++) {
free(*pentry);
}
free(dir->entries);
free(dir->path);
free(dir);
}
int main(int argc, char **argv) {
char *dirpath;
entry_t **pentry;
dirpath = getcwd(NULL, 0);
dir = look_dir(dirpath);
if (dir == NULL) {
exit(1);
}
for (pentry = dir->entries; *pentry != NULL; pentry++) {
entry_t *entry = *pentry;
printf("%d\t%lld\t%s\n", entry->stat.st_mode, entry->stat.st_size, entry->name);
}
free_dir(dir);
free(dirpath);
return 0;
}
メモ
- getcwd()でカレントディレクトリのパスを取得
- バッファにNULLを渡すと、getcwdがメモリを確保して文字列を返す
- 確保されたメモリは呼び出し側の責任でfreeしないと行けない
- readdir()の返り値はfreeしてはいけない
- NAME_MAXはシステムの最大のファイル名の長さ