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:
215
src/tree.c
215
src/tree.c
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user