Created
May 22, 2013 16:09
-
-
Save tuxillo/5628817 to your computer and use it in GitHub Desktop.
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
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <strings.h> | |
| #include <string.h> | |
| #include <dirent.h> | |
| #include <fcntl.h> | |
| #include <err.h> | |
| #include <sys/types.h> | |
| #include <sys/tree.h> | |
| enum nodetype { | |
| DDIR = 4, | |
| DREG = 8, | |
| DNON | |
| }; | |
| struct dirfs_dent { | |
| RB_ENTRY(dirfs_dent) de_entry; | |
| char de_name[255]; | |
| struct dirfs_node *de_node; | |
| }; | |
| static int dent_compare(struct dirfs_dent *a, struct dirfs_dent *b); | |
| RB_HEAD(dirtree, dirfs_dent); | |
| RB_PROTOTYPE(dirtree, dirfs_dent, de_entry, dent_compare); | |
| RB_GENERATE(dirtree, dirfs_dent, de_entry, dent_compare); | |
| struct dirfs_node { | |
| int dn_type; | |
| struct dirtree dn_tree; | |
| }; | |
| struct dirfs_node dn_root; | |
| size_t totalmem; | |
| static int | |
| dent_compare(struct dirfs_dent *a, struct dirfs_dent *b) | |
| { | |
| size_t alen = strlen(a->de_name); | |
| size_t blen = strlen(a->de_name); | |
| if (alen > blen) | |
| return 1; | |
| else if (alen < blen) | |
| return -1; | |
| else | |
| return strcmp(a->de_name, b->de_name); | |
| } | |
| void | |
| print_node(struct dirfs_dent *de, int *depth) | |
| { | |
| char buf[256] = {0}; | |
| int i; | |
| for (i = 0; i < *depth; i++) | |
| strcat(buf, "\t"); | |
| printf("%s %c %s\n", buf, (de->de_node->dn_type == DDIR) ? 'd' : 'f', de->de_name); | |
| } | |
| void | |
| alloc_dent(struct dirfs_dent *de, const char *name, int type) | |
| { | |
| de->de_node = malloc(sizeof(*de->de_node)); | |
| totalmem += sizeof(*de->de_node); | |
| strcpy(de->de_name, name); | |
| de->de_node->dn_type = type; | |
| switch (type) { | |
| case DDIR: | |
| RB_INIT(&de->de_node->dn_tree); | |
| break; | |
| case DREG: | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| void | |
| free_dent(struct dirfs_node *n) | |
| { | |
| free(n); | |
| } | |
| void | |
| attach_dent(struct dirtree *dt, struct dirfs_dent *entry) | |
| { | |
| struct dirfs_dent *p; | |
| p = RB_INSERT(dirtree, dt, entry); | |
| if (p) | |
| printf("error inserting in the tree %p (%s)\n", p, p->de_name); | |
| } | |
| void | |
| add_dir_totree(const char *path, struct dirtree *dt) | |
| { | |
| struct dirfs_dent *de; | |
| struct dirent *dp, *dpn; | |
| int bytes; | |
| char buf[512], buf2[256]; | |
| long base; | |
| int fd; | |
| if ((fd = open(path, O_RDONLY | O_DIRECTORY)) == -1) | |
| err(1, "open %s", path); | |
| for (;;) { | |
| bytes = getdirentries(fd, buf, 512, &base); | |
| if (bytes <= 0) | |
| break; | |
| dp = (struct dirent *) buf; | |
| while (bytes >= dp->d_namlen && bytes != 0) { | |
| de = malloc(sizeof(*de)); | |
| totalmem += sizeof(*de); | |
| if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { | |
| alloc_dent(de, dp->d_name, dp->d_type); | |
| attach_dent(dt, de); | |
| // printf("Added node %d %s/%s to %p\n", de->de_node->dn_type, path, de->de_name, dt); | |
| if (dp->d_type == DDIR) { | |
| sprintf(buf2, "%s/%s", path, de->de_name); | |
| add_dir_totree(buf2, &de->de_node->dn_tree); | |
| } | |
| } | |
| dpn = _DIRENT_NEXT(dp); | |
| bytes -= _DIRENT_DIRSIZ(dp); | |
| dp = dpn; | |
| } | |
| } | |
| close (fd); | |
| } | |
| void | |
| print_tree(struct dirtree *tree, int *level) | |
| { | |
| struct dirfs_dent *tmp; | |
| RB_FOREACH(tmp, dirtree, tree) { | |
| if (tmp != NULL) { | |
| if ((tmp->de_node->dn_type == DDIR)) { | |
| print_node(tmp, level); | |
| (*level)++; | |
| print_tree(&tmp->de_node->dn_tree, level); | |
| } else { | |
| print_node(tmp, level); | |
| } | |
| } | |
| } | |
| (*level)--; | |
| } | |
| int | |
| main(int argc, char *argv[]) | |
| { | |
| int level; | |
| RB_INIT(&dn_root.dn_tree); | |
| totalmem = 0; | |
| add_dir_totree(argv[1], &dn_root.dn_tree); | |
| print_tree(&dn_root.dn_tree, &level); | |
| printf("%zd bytes used\n", totalmem); | |
| sleep(15); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment