libisofs-legacy/libisofs/tree.c

224 lines
4.5 KiB
C
Raw Normal View History

2006-08-15 20:37:04 +00:00
/* vim: set noet ts=8 sts=8 sw=8 : */
2006-08-24 19:23:37 +00:00
/**
* \file tree.c
*
* Implement filesystem trees.
*/
#include <assert.h>
2006-08-15 20:37:04 +00:00
#include <stdlib.h>
#include <string.h>
#include <time.h>
2006-08-24 19:23:37 +00:00
#include <dirent.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
2006-08-15 20:37:04 +00:00
#include <errno.h>
2006-08-24 19:23:37 +00:00
#include <err.h>
#include <stdio.h>
2006-08-15 20:37:04 +00:00
#include "tree.h"
#include "util.h"
#include "volume.h"
#include "exclude.h"
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
static void
set_default_stat(struct stat *s)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
time_t now = time(NULL);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
memset(s, 0, sizeof(struct stat));
s->st_mode = 0777 | S_IFREG;
s->st_atime = s->st_mtime = s->st_ctime = now;
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
static struct stat
get_attrib(const struct iso_tree_node *node)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
struct stat st;
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
if (node) {
return node->attrib;
}
set_default_stat(&st);
return st;
}
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
static void
append_node(struct iso_tree_node *parent,
struct iso_tree_node *child)
{
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && child);
if (!parent)
return;
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
parent->nchildren++;
parent->children =
realloc(parent->children, parent->nchildren * sizeof(void*));
parent->children[parent->nchildren-1] = child;
}
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
struct iso_tree_node*
iso_tree_new_root(struct iso_volume *vol)
{
assert(vol);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
if (vol->root) {
iso_tree_free(vol->root);
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
vol->root = calloc(1, sizeof(struct iso_tree_node));
vol->root->volume = vol;
set_default_stat(&vol->root->attrib);
vol->root->attrib.st_mode = S_IFDIR | 0777;
vol->root->loc.type = LIBISO_NONE;
return vol->root;
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
struct iso_tree_node*
iso_tree_add_new_file(struct iso_tree_node *parent, const char *name)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
struct iso_tree_node *f = calloc(1, sizeof(struct iso_tree_node));
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && name);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
f->volume = parent ? parent->volume : NULL;
f->parent = parent;
2006-09-19 17:06:40 +00:00
f->name = parent ? strdup(name) : NULL;
2006-08-24 19:23:37 +00:00
f->attrib = get_attrib(parent);
f->attrib.st_mode = 0777 | S_IFREG;
f->loc.type = LIBISO_NONE;
append_node(parent, f);
return f;
}
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
struct iso_tree_node*
iso_tree_add_new_dir(struct iso_tree_node *parent, const char *name)
{
struct iso_tree_node *d = iso_tree_add_new_file(parent, name);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && name);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
d->attrib.st_mode = (d->attrib.st_mode & ~S_IFMT) | S_IFDIR;
return d;
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
struct iso_tree_node*
iso_tree_add_node(struct iso_tree_node *parent, const char *path)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
char *p;
2006-08-15 20:37:04 +00:00
struct stat st;
2006-08-24 19:23:37 +00:00
struct iso_tree_node *ret;
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && path);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
if (lstat(path, &st) == -1)
return NULL;
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
p = strdup(path); /* because basename() might modify its arg */
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
/* it doesn't matter if we add a file or directory since we modify
* attrib anyway. */
ret = iso_tree_add_new_file(parent, basename(p));
ret->attrib = st;
ret->loc.type = LIBISO_FILESYS;
ret->loc.path = strdup(path);
free(p);
return ret;
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
struct iso_tree_node*
iso_tree_radd_dir (struct iso_tree_node *parent, const char *path)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
struct iso_tree_node *new;
2006-08-15 20:37:04 +00:00
DIR *dir;
struct dirent *ent;
2006-08-24 19:23:37 +00:00
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && path);
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
new = iso_tree_add_node(parent, path);
if (!new || !S_ISDIR(new->attrib.st_mode)) {
return new;
}
2006-08-15 20:37:04 +00:00
dir = opendir(path);
if (!dir) {
2006-08-24 19:23:37 +00:00
warn("couldn't open directory %s: %s\n", path, strerror(errno));
return new;
2006-08-15 20:37:04 +00:00
}
while ((ent = readdir(dir))) {
2006-08-24 19:23:37 +00:00
char child[strlen(ent->d_name) + strlen(path) + 2];
2006-08-15 20:37:04 +00:00
if (strcmp(ent->d_name, ".") == 0 ||
2006-08-24 19:23:37 +00:00
strcmp(ent->d_name, "..") == 0)
2006-08-15 20:37:04 +00:00
continue;
2006-08-24 19:23:37 +00:00
sprintf(child, "%s/%s", path, ent->d_name);
/* see if this child is excluded. */
if (iso_exclude_lookup(child))
continue;
2006-08-24 19:23:37 +00:00
iso_tree_radd_dir(new, child);
2006-08-15 20:37:04 +00:00
}
closedir(dir);
2006-08-24 19:23:37 +00:00
return new;
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
void
iso_tree_free(struct iso_tree_node *root)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
size_t i;
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
for (i=0; i < root->nchildren; i++) {
iso_tree_free(root->children[i]);
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
free(root->name);
free(root->children);
free(root);
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
void
iso_tree_print(const struct iso_tree_node *root, int spaces)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
size_t i;
char sp[spaces+1];
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
memset(sp, ' ', spaces);
sp[spaces] = '\0';
2006-08-15 20:37:04 +00:00
2006-09-19 17:06:40 +00:00
printf("%s%sn", sp, root->name);
2006-08-24 19:23:37 +00:00
for (i=0; i < root->nchildren; i++) {
iso_tree_print(root->children[i], spaces+2);
}
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
void
iso_tree_print_verbose(const struct iso_tree_node *root,
print_dir_callback dir,
print_file_callback file,
void *callback_data,
int spaces)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
size_t i;
2006-08-15 20:37:04 +00:00
2006-08-24 19:23:37 +00:00
(S_ISDIR(root->attrib.st_mode) ? dir : file)
(root, callback_data, spaces);
for (i=0; i < root->nchildren; i++) {
iso_tree_print_verbose(root->children[i], dir,
file, callback_data, spaces+2);
}
2006-08-15 20:37:04 +00:00
}
2006-08-24 19:23:37 +00:00
void
iso_tree_node_set_name(struct iso_tree_node *file, const char *name)
2006-08-15 20:37:04 +00:00
{
2006-08-24 19:23:37 +00:00
free(file->name);
2006-09-19 17:06:40 +00:00
file->name = strdup(name);
2006-08-15 20:37:04 +00:00
}