#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
typedef struct FileList FileList;
struct FileList {
char *name;
char *path;
FileList *next;
};
void test_stat(FileList *files);
void test_open_fstat(FileList *files);
void test_open_stat(FileList *files);
void test_fstatat(int dirfd, FileList *files);
int main(int argc, char** argv) {
if(argc < 2) {
fprintf(stderr, "Usage: %s <dir>\n", argv[0]);
return EXIT_FAILURE;
}
char *path = argv[1];
size_t pathlen = strlen(path);
DIR *dir = opendir(path);
if(!dir) {
fprintf(stderr, "Cannot open directory: %s\n", path);
return EXIT_FAILURE;
}
FileList *files = NULL;
FileList *last = NULL;
size_t count = 0;
struct dirent *entry;
while((entry = readdir(dir)) != NULL) {
if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
continue;
}
FileList *file = calloc(1, sizeof(FileList));
file->name = strdup(entry->d_name);
if(path[pathlen - 1] == '/') {
asprintf(&file->path, "%s%s", path, entry->d_name);
} else {
asprintf(&file->path, "%s/%s", path, entry->d_name);
}
if(!files) {
files = file;
} else {
last->next = file;
}
last = file;
count++;
}
if(files) {
printf("test %zu files:\n\n", count);
test_stat(files);
test_fstatat(dirfd(dir), files);
printf("----------------------------------------\n\n");
test_open_stat(files);
test_open_fstat(files);
} else {
fprintf(stderr, "No files in %s\n", path);
}
FileList *elm = files;
while(elm) {
free(elm->name);
free(elm->path);
FileList *next = elm->next;
free(elm);
elm = next;
}
closedir(dir);
return EXIT_SUCCESS;
}
void test_stat(FileList *files) {
printf("test_stat\n");
struct timespec begin;
clock_gettime(CLOCK_REALTIME, &begin);
FileList *elm = files;
while(elm) {
struct stat s;
if(stat(elm->path, &s)) {
perror("stat");
fprintf(stderr, "file: %s\n", elm->path);
}
elm = elm->next;
}
struct timespec end;
clock_gettime(CLOCK_REALTIME, &end);
printf("time: %ld ns\n\n", end.tv_nsec - begin.tv_nsec);
}
void test_fstatat(int dirfd, FileList *files) {
printf("test_fstatat\n");
struct timespec begin;
clock_gettime(CLOCK_REALTIME, &begin);
FileList *elm = files;
while(elm) {
struct stat s;
if(fstatat(dirfd, elm->name, &s, 0)) {
perror("stat");
fprintf(stderr, "file: %s\n", elm->path);
}
elm = elm->next;
}
struct timespec end;
clock_gettime(CLOCK_REALTIME, &end);
printf("time: %ld ns\n\n", end.tv_nsec - begin.tv_nsec);
}
void test_open_fstat(FileList *files) {
printf("test_open_fstat\n");
struct timespec begin;
clock_gettime(CLOCK_REALTIME, &begin);
FileList *elm = files;
while(elm) {
int fd = open(elm->path, O_RDONLY);
if(fd == -1) {
perror("open");
fprintf(stderr, "file: %s\n", elm->path);
elm = elm->next;
continue;
}
struct stat s;
if(fstat(fd, &s)) {
perror("fstat");
fprintf(stderr, "file: %s\n", elm->path);
}
close(fd);
elm = elm->next;
}
struct timespec end;
clock_gettime(CLOCK_REALTIME, &end);
printf("time: %ld ns\n\n", end.tv_nsec - begin.tv_nsec);
}
void test_open_stat(FileList *files) {
printf("test_open_stat\n");
struct timespec begin;
clock_gettime(CLOCK_REALTIME, &begin);
FileList *elm = files;
while(elm) {
int fd = open(elm->path, O_RDONLY);
if(fd == -1) {
perror("open");
fprintf(stderr, "file: %s\n", elm->path);
elm = elm->next;
continue;
}
struct stat s;
if(stat(elm->path, &s)) {
perror("stat");
fprintf(stderr, "file: %s\n", elm->path);
}
close(fd);
elm = elm->next;
}
struct timespec end;
clock_gettime(CLOCK_REALTIME, &end);
printf("time: %ld ns\n\n", end.tv_nsec - begin.tv_nsec);
}