Implement function to recursively add a dir to an iso tree.

This commit also to the following changes:
- create_node() on builder never frees the IsoFileSource, it is responsability 
  of the caller to free it.
- Recursive addition options added to IsoImage (not exposed to public API yet)
- create_node() takes care about follow_symlinks
- Added little demo program to test it.
This commit is contained in:
Vreixo Formoso
2007-12-11 22:47:04 +01:00
parent 0306bb5daf
commit d10ed353e2
9 changed files with 426 additions and 7 deletions

View File

@ -16,10 +16,13 @@
#include "image.h"
#include "fsource.h"
#include "builder.h"
#include "messages.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include <stdio.h>
/**
* Add a new directory to the iso tree.
@ -356,6 +359,218 @@ int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path,
}
result = iso_tree_add_node_builder(image, parent, file, image->builder,
node);
/* free the file */
iso_file_source_unref(file);
return result;
}
static
int check_excludes(IsoImage *image, const char *path)
{
char **exclude;
if (image->recOpts->excludes == NULL) {
return 0;
}
exclude = image->recOpts->excludes;
while (*exclude) {
if (strcmp(*exclude, path) == 0) {
return 1;
}
++exclude;
}
return 0;
}
static
int check_hidden(IsoImage *image, const char *name)
{
return (image->recOpts->ignore_hidden && name[0] == '.');
}
/**
* @return
* 1 continue, 0 stop, < 0 error
*/
static
int iso_add_dir_aux(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
{
int result;
int action; /* 1 add, 2 skip, 3 stop, < 0 error */
IsoNodeBuilder *builder;
IsoFileSource *file;
IsoNode **pos;
result = dir->open(dir);
if (result < 0) {
return result;
}
builder = image->builder;
action = 1;
while ( (result = dir->readdir(dir, &file)) == 1) {
int flag;
char *name;
IsoNode *new;
{
char msg[PATH_MAX];
sprintf(msg, "Adding file %s\n", file->get_path(file));
iso_msg_debug(image, msg);
}
name = file->get_name(file);
if (check_excludes(image, file->get_path(file))) {
action = 2;
} else if (check_hidden(image, name)) {
action = 2;
} else {
action = 1;
}
/* find place where to insert */
flag = 0;
pos = &(parent->children);
while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
pos = &((*pos)->next);
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
flag = 1;
if (action == 1 && image->recOpts->replace == 0) {
action = 2;
}
}
/* ask user if callback has been set */
if (image->recOpts->report) {
action = image->recOpts->report(file, action, flag);
}
if (action == 2) {
/* skip file */
iso_file_source_unref(file);
continue;
} else if (action == 3) {
/* stop */
iso_file_source_unref(file);
break;
}
/* ok, file will be added */
result = builder->create_node(builder, image, file, &new);
if (result < 0) {
{
char msg[PATH_MAX];
sprintf(msg, "Error %d when adding file %s\n", result,
file->get_path(file));
iso_msg_debug(image, msg);
}
if (image->recOpts->report) {
action = image->recOpts->report(file, result, flag);
} else {
action = image->recOpts->stop_on_error ? 3 : 1;
}
/* free file */
iso_file_source_unref(file);
if (action == 3) {
result = 1; /* prevent error to be passing up */
break;
} else {
/* TODO check that action is 1!!! */
continue;
}
}
/* ok, node has correctly created, we need to add it */
if (flag) {
/* replace node */
new->next = (*pos)->next;
(*pos)->parent = NULL;
(*pos)->next = NULL;
iso_node_unref(*pos);
*pos = new;
new->parent = parent;
} else {
/* just add */
new->next = *pos;
*pos = new;
new->parent = parent;
++parent->nchildren;
}
/* finally, if the node is a directory we need to recurse */
if (new->type == LIBISO_DIR) {
result = iso_add_dir_aux(image, (IsoDir*)new, file);
iso_file_source_unref(file);
if (result < 0) {
/* error */
if (image->recOpts->stop_on_error) {
action = 3; /* stop */
result = 1; /* prevent error to be passing up */
break;
}
} else if (result == 0) {
/* stop */
action = 3;
break;
}
} else {
iso_file_source_unref(file);
}
}
if (result < 0) {
// TODO printf message
action = result;
}
result = dir->close(dir);
if (result < 0) {
return result;
}
if (action < 0) {
return action; /* error */
} else if (action == 3) {
return 0; /* stop */
} else {
return 1; /* continue */
}
}
int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir)
{
int result;
struct stat info;
IsoFilesystem *fs;
IsoFileSource *file;
if (image == NULL || parent == NULL || dir == NULL) {
return ISO_NULL_POINTER;
}
fs = image->fs;
result = fs->get_by_path(fs, dir, &file);
if (result < 0) {
return result;
}
/* we also allow dir path to be a symlink to a dir */
result = file->stat(file, &info);
if (result < 0) {
iso_file_source_unref(file);
return result;
}
if (!S_ISDIR(info.st_mode)) {
iso_file_source_unref(file);
return ISO_FILE_IS_NOT_DIR;
}
result = iso_add_dir_aux(image, parent, file);
iso_file_source_unref(file);
return result;
}