-
-
Save laamalif/4389a22afd5b5ceca08f93da9067ad2b to your computer and use it in GitHub Desktop.
List directories using getdents()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * List directories using getdents() because ls, find and Python libraries | |
| * use readdir() which is slower (but uses getdents() underneath. | |
| * | |
| * $ gcc gs.c -o gs | |
| */ | |
| #define _GNU_SOURCE | |
| #include <fcntl.h> | |
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <sys/stat.h> | |
| #include <sys/syscall.h> | |
| #include <string.h> | |
| #include <limits.h> | |
| #define handle_error(msg) \ | |
| do { perror(msg); exit(EXIT_FAILURE); } while (0) | |
| struct linux_dirent { | |
| long d_ino; | |
| off_t d_off; | |
| unsigned short d_reclen; | |
| char d_name[]; | |
| }; | |
| #define BUF_SIZE 1024*1024*5 | |
| void apply_color(mode_t mode, char *name) { | |
| if (S_ISDIR(mode)) { | |
| printf("\033[1;34m%s\033[0m", name); // Blue for directories | |
| } else if (S_ISLNK(mode)) { | |
| printf("\033[1;36m%s\033[0m", name); // Cyan for symlinks | |
| } else if (mode & S_IXUSR) { | |
| printf("\033[1;32m%s\033[0m", name); // Green for executables | |
| } else { | |
| printf("%s", name); // Default color | |
| } | |
| } | |
| void list_directory(const char *path, int show_hidden) { | |
| int fd, nread; | |
| char buf[BUF_SIZE]; | |
| struct linux_dirent *d; | |
| int bpos; | |
| char d_type; | |
| struct stat st; | |
| char fullpath[PATH_MAX]; | |
| fd = open(path, O_RDONLY | O_DIRECTORY); | |
| if (fd == -1) | |
| handle_error("open"); | |
| for (;;) { | |
| nread = syscall(SYS_getdents, fd, buf, BUF_SIZE); | |
| if (nread == -1) | |
| handle_error("getdents"); | |
| if (nread == 0) | |
| break; | |
| for (bpos = 0; bpos < nread;) { | |
| d = (struct linux_dirent *) (buf + bpos); | |
| d_type = *(buf + bpos + d->d_reclen - 1); | |
| // Skip "." and ".." | |
| if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) { | |
| bpos += d->d_reclen; | |
| continue; | |
| } | |
| // Skip hidden files unless `-a` is provided | |
| if (!show_hidden && d->d_name[0] == '.') { | |
| bpos += d->d_reclen; | |
| continue; | |
| } | |
| snprintf(fullpath, sizeof(fullpath), "%s/%s", path, d->d_name); | |
| if (stat(fullpath, &st) == -1) { | |
| perror("stat"); | |
| bpos += d->d_reclen; | |
| continue; | |
| } | |
| apply_color(st.st_mode, d->d_name); | |
| printf("\n"); | |
| bpos += d->d_reclen; | |
| } | |
| } | |
| close(fd); | |
| } | |
| int main(int argc, char *argv[]) { | |
| int show_hidden = 0; | |
| char *path = "."; | |
| for (int i = 1; i < argc; i++) { | |
| if (strcmp(argv[i], "-a") == 0) { | |
| show_hidden = 1; | |
| } else { | |
| path = argv[i]; | |
| } | |
| } | |
| list_directory(path, show_hidden); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment