Merge branch 'exp-hash'
[eleutheria.git] / fileops / listdir_recursive.c
blob6c7ac91cbbda416ddcbb29cb1c8d495e3560a169
1 /* compile with:
2 gcc listdir_recursive.c -o listdir_recursive -Wall -W -Wextra -ansi -pedantic */
4 #include <dirent.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
11 /* Since listdir() uses a static variable to keep track of the call depth,
12 it is not safe to use it in a multi threading environment. If this is the
13 case, then you need to pass 'dirdepth' as an argument to listdir().
15 int listdir(const char *path)
17 struct dirent *pdent;
18 DIR *pdir;
19 char *newpath = NULL;
20 static unsigned int dirdepth = 0;
21 unsigned int i;
23 /* open directory named by path, associate a directory stream
24 with it and return a pointer to it
26 if ((pdir = opendir(path)) == NULL) {
27 perror("opendir");
28 return -1;
31 /* get all directory entries */
32 while((pdent = readdir(pdir)) != NULL) {
33 /* indent according to the depth we are */
34 for (i = 0; i < dirdepth; i++)
35 printf(" ");
37 /* print current entry, or [entry] if it's a directory */
38 if (pdent->d_type == DT_DIR)
39 printf("[%s]\n", pdent->d_name);
40 else
41 printf("%s\n", pdent->d_name);
43 /* Is it a directory ? If yes, list it */
44 if (pdent->d_type == DT_DIR
45 && strcmp(pdent->d_name, ".")
46 && strcmp(pdent->d_name, "..")) {
47 dirdepth++;
49 /* allocate memory for new path
50 don't forget +1 for the '\0'
52 if ((newpath = malloc(strlen(path) + strlen(pdent->d_name) + 2)) == NULL) {
53 perror("malloc");
54 return -1;
57 /* construct new path */
58 strcpy(newpath, path);
59 strcat(newpath, "/");
60 strcat(newpath, pdent->d_name);
62 /* to iterate is human, to recurse, divine */
63 if (listdir(newpath) == -1) {
64 closedir(pdir);
65 free(newpath);
66 return -1;
71 closedir(pdir);
72 if (newpath != NULL)
73 free(newpath);
75 dirdepth--;
76 return 1;
79 int main(int argc, char *argv[])
81 /* check argument count */
82 if (argc != 2) {
83 fprintf(stderr, "Usage: %s directory\n", argv[0]);
84 exit(EXIT_FAILURE);
87 (void)listdir(argv[1]);
89 return EXIT_SUCCESS;