// http://www.olark.com/spw/2011/08/you-can-list-a-directory-with-8-million-files-but-not-with-ls/ #define _GNU_SOURCE #include /* Defines DT_* constants */ #include #include #include #include #include #include #include #define handle_error(msg) perror(msg) struct linux_dirent { long d_ino; off_t d_off; unsigned short d_reclen; char d_name[]; }; #define BUF_SIZE (1024 * 1024 * 128) void listdir(const char * dirname, size_t * ntotal) { int fd, nread; struct linux_dirent *d; int bpos; char d_type; char * buf = malloc(BUF_SIZE); fd = open(dirname, O_RDONLY | O_DIRECTORY); if (fd == -1) return handle_error(dirname); for ( ; ; ) { nread = syscall(SYS_getdents, fd, buf, BUF_SIZE); if (nread == -1) return handle_error(dirname); if (nread == 0) break; for (bpos = 0; bpos < nread;) { d = (struct linux_dirent *) (buf + bpos); d_type = *(buf + bpos + d->d_reclen - 1); bpos += d->d_reclen; if(d->d_ino && strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { (*ntotal)++; if(d_type == DT_DIR) { int dirname_len = strlen(dirname); char * subdir = calloc(1, PATH_MAX + 1); strcat(subdir, dirname); strcat(subdir + dirname_len, "/"); strcat(subdir + dirname_len + 1, d->d_name); listdir(subdir, ntotal); free(subdir); } } } } close(fd); free(buf); } int main(int argc, char *argv[]) { size_t ntotal = 0; listdir(argc > 1 ? argv[1] : ".", &ntotal); printf("%d\n", ntotal); exit(EXIT_SUCCESS); }