Skip to content

Instantly share code, notes, and snippets.

@tuxillo
Created May 22, 2013 16:09
Show Gist options
  • Select an option

  • Save tuxillo/5628817 to your computer and use it in GitHub Desktop.

Select an option

Save tuxillo/5628817 to your computer and use it in GitHub Desktop.
#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