Implemented safety cap and did merge with vreixo branch
This commit is contained in:
commit
7e617733b1
@ -38,3 +38,4 @@ demo/isogrow
|
||||
doc/html
|
||||
doc/doxygen.conf
|
||||
libisofs-1.pc
|
||||
demo/find
|
||||
|
@ -16,6 +16,7 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/node.c \
|
||||
libisofs/tree.h \
|
||||
libisofs/tree.c \
|
||||
libisofs/find.c \
|
||||
libisofs/image.h \
|
||||
libisofs/image.c \
|
||||
libisofs/fsource.h \
|
||||
@ -54,6 +55,8 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/iso1999.h \
|
||||
libisofs/iso1999.c \
|
||||
libisofs/data_source.c
|
||||
libisofs_libisofs_la_LIBADD= \
|
||||
$(THREAD_LIBS)
|
||||
libinclude_HEADERS = \
|
||||
libisofs/libisofs.h
|
||||
|
||||
@ -65,6 +68,7 @@ noinst_PROGRAMS = \
|
||||
demo/cat \
|
||||
demo/catbuffer \
|
||||
demo/tree \
|
||||
demo/find \
|
||||
demo/ecma119tree \
|
||||
demo/iso \
|
||||
demo/isoread \
|
||||
@ -89,6 +93,10 @@ demo_tree_CPPFLAGS = -Ilibisofs
|
||||
demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
demo_tree_SOURCES = demo/tree.c
|
||||
|
||||
demo_find_CPPFLAGS = -Ilibisofs
|
||||
demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
demo_find_SOURCES = demo/find.c
|
||||
|
||||
demo_ecma119tree_CPPFLAGS = -Ilibisofs
|
||||
demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
demo_ecma119tree_SOURCES = demo/ecma119_tree.c
|
||||
|
1
TODO
1
TODO
@ -9,7 +9,6 @@ TODO
|
||||
#00004 (libisofs.h) -> Add a get_mime_type() function.
|
||||
#00005 (node.c) -> optimize iso_dir_iter_take.
|
||||
#00006 (libisofs.h) -> define more replace values when adding a node to a dir
|
||||
#00007 (libisofs.h) -> expose iso_tree_add_new_file
|
||||
#00008 (data_dource.c) -> guard against partial reads
|
||||
#00009 (ecma119_tree.c/h) -> add true support for harlinks and inode numbers
|
||||
#00010 (buffer.c) -> optimize ring buffer
|
||||
|
63
demo/find.c
Normal file
63
demo/find.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Little program that import a directory, find matching nodes and prints the
|
||||
* resulting iso tree.
|
||||
*/
|
||||
|
||||
#include "libisofs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
print_dir(IsoDir *dir)
|
||||
{
|
||||
IsoDirIter *iter;
|
||||
IsoNode *node;
|
||||
IsoFindCondition *cond, *c1, *c2;
|
||||
|
||||
c1 = iso_new_find_conditions_name("*a*");
|
||||
c2 = iso_new_find_conditions_mode(S_IFREG);
|
||||
cond = iso_new_find_conditions_and(c1, c2);
|
||||
iso_dir_find_children(dir, cond, &iter);
|
||||
while (iso_dir_iter_next(iter, &node) == 1) {
|
||||
char *path = iso_tree_get_node_path(node);
|
||||
printf(" %s\n", path);
|
||||
free(path);
|
||||
}
|
||||
iso_dir_iter_free(iter);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
|
||||
if (argc != 2) {
|
||||
printf ("You need to specify a valid path\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iso_init();
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_dir(iso_image_get_root(image));
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
@ -52,12 +52,13 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* take a ref to the src, as stream has taken our ref */
|
||||
iso_file_source_ref(src);
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
ret = iso_node_new_file(name, stream, &node);
|
||||
if (ret < 0) {
|
||||
/* the stream has taken our ref to src, so we need to add one */
|
||||
iso_file_source_ref(src);
|
||||
iso_stream_unref(stream);
|
||||
free(name);
|
||||
return ret;
|
||||
|
@ -34,8 +34,7 @@ struct Iso_Node_Builder
|
||||
* In that case, if the implementation can't do the conversion, it
|
||||
* should fail propertly.
|
||||
*
|
||||
* On sucess, the ref. to src will be owned by file, so you musn't
|
||||
* unref it.
|
||||
* Note that the src is never unref, so you need to free it.
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
|
@ -57,7 +57,7 @@ int ds_open(IsoDataSource *src)
|
||||
|
||||
data = (struct file_data_src*) src->data;
|
||||
if (data->fd != -1) {
|
||||
return ISO_FILE_ALREADY_OPENNED;
|
||||
return ISO_FILE_ALREADY_OPENED;
|
||||
}
|
||||
|
||||
fd = open(data->path, O_RDONLY);
|
||||
@ -81,7 +81,7 @@ int ds_close(IsoDataSource *src)
|
||||
|
||||
data = (struct file_data_src*) src->data;
|
||||
if (data->fd == -1) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
|
||||
/* close can fail if fd is not valid, but that should never happen */
|
||||
@ -102,7 +102,7 @@ static int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
|
||||
|
||||
data = (struct file_data_src*) src->data;
|
||||
if (data->fd == -1) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
|
||||
/* goes to requested block */
|
||||
|
@ -538,7 +538,7 @@ int catalog_open(IsoStream *stream)
|
||||
data = stream->data;
|
||||
|
||||
if (data->offset != -1) {
|
||||
return ISO_FILE_ALREADY_OPENNED;
|
||||
return ISO_FILE_ALREADY_OPENED;
|
||||
}
|
||||
|
||||
memset(data->buffer, 0, BLOCK_SIZE);
|
||||
@ -563,7 +563,7 @@ int catalog_close(IsoStream *stream)
|
||||
data = stream->data;
|
||||
|
||||
if (data->offset == -1) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
data->offset = -1;
|
||||
return ISO_SUCCESS;
|
||||
@ -589,7 +589,7 @@ int catalog_read(IsoStream *stream, void *buf, size_t count)
|
||||
data = stream->data;
|
||||
|
||||
if (data->offset == -1) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
|
||||
len = MIN(count, BLOCK_SIZE - data->offset);
|
||||
|
@ -33,6 +33,12 @@ int iso_file_add_filter(IsoFile *file, FilterContext *filter, int flag)
|
||||
}
|
||||
|
||||
original = file->stream;
|
||||
|
||||
if (!iso_stream_is_repeatable(original)) {
|
||||
/* TODO use custom error */
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
ret = filter->get_filter(filter, original, &filtered);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
761
libisofs/find.c
Normal file
761
libisofs/find.c
Normal file
@ -0,0 +1,761 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Vreixo Formoso
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*/
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include <string.h>
|
||||
|
||||
struct iso_find_condition
|
||||
{
|
||||
/*
|
||||
* Check whether the given node matches this condition.
|
||||
*
|
||||
* @param cond
|
||||
* The condition to check
|
||||
* @param node
|
||||
* The node that should be checked
|
||||
* @return
|
||||
* 1 if the node matches the condition, 0 if not
|
||||
*/
|
||||
int (*matches)(IsoFindCondition *cond, IsoNode *node);
|
||||
|
||||
/**
|
||||
* Free condition specific data
|
||||
*/
|
||||
void (*free)(IsoFindCondition*);
|
||||
|
||||
/** condition specific data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct find_iter_data
|
||||
{
|
||||
IsoDir *dir; /**< original dir of the iterator */
|
||||
IsoDirIter *iter;
|
||||
IsoDirIter *itersec; /**< iterator to deal with child dirs */
|
||||
IsoFindCondition *cond;
|
||||
int err; /**< error? */
|
||||
IsoNode *current; /**< node to be returned next */
|
||||
IsoNode *prev; /**< last returned node, needed for removal */
|
||||
int free_cond; /**< whether to free cond on iter_free */
|
||||
};
|
||||
|
||||
static
|
||||
int get_next(struct find_iter_data *iter, IsoNode **n)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (iter->itersec != NULL) {
|
||||
ret = iso_dir_iter_next(iter->itersec, n);
|
||||
if (ret <= 0) {
|
||||
/* secondary item no more needed */
|
||||
iso_dir_iter_free(iter->itersec);
|
||||
iter->itersec = NULL;
|
||||
}
|
||||
if (ret != 0) {
|
||||
/* succes or error */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we reach here if:
|
||||
* - no secondary item is present
|
||||
* - secondary item has no more items
|
||||
*/
|
||||
|
||||
while ((ret = iso_dir_iter_next(iter->iter, n)) == 1) {
|
||||
if (iter->cond->matches(iter->cond, *n)) {
|
||||
return ISO_SUCCESS;
|
||||
} else if (ISO_NODE_IS_DIR(*n)) {
|
||||
/* recurse on child dir */
|
||||
struct find_iter_data *data;
|
||||
ret = iso_dir_find_children((IsoDir*)*n, iter->cond,
|
||||
&iter->itersec);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
data = iter->itersec->data;
|
||||
data->free_cond = 0; /* we don't need sec iter to free cond */
|
||||
return get_next(iter, n);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void update_next(IsoDirIter *iter)
|
||||
{
|
||||
int ret;
|
||||
IsoNode *n;
|
||||
struct find_iter_data *data = iter->data;
|
||||
|
||||
if (data->prev) {
|
||||
iso_node_unref(data->prev);
|
||||
}
|
||||
data->prev = data->current;
|
||||
|
||||
if (data->itersec == NULL && data->current != NULL
|
||||
&& ISO_NODE_IS_DIR(data->current)) {
|
||||
|
||||
/* we need to recurse on child dir */
|
||||
struct find_iter_data *data2;
|
||||
ret = iso_dir_find_children((IsoDir*)data->current, data->cond,
|
||||
&data->itersec);
|
||||
if (ret < 0) {
|
||||
data->current = NULL;
|
||||
data->err = ret;
|
||||
return;
|
||||
}
|
||||
data2 = data->itersec->data;
|
||||
data2->free_cond = 0; /* we don't need sec iter to free cond */
|
||||
}
|
||||
|
||||
ret = get_next(data, &n);
|
||||
iso_node_unref((IsoNode*)iter->dir);
|
||||
if (ret == 1) {
|
||||
data->current = n;
|
||||
iso_node_ref(n);
|
||||
data->err = 0;
|
||||
iter->dir = n->parent;
|
||||
} else {
|
||||
data->current = NULL;
|
||||
data->err = ret;
|
||||
iter->dir = data->dir;
|
||||
}
|
||||
iso_node_ref((IsoNode*)iter->dir);
|
||||
}
|
||||
|
||||
static
|
||||
int find_iter_next(IsoDirIter *iter, IsoNode **node)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
|
||||
if (iter == NULL || node == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (data->err < 0) {
|
||||
return data->err;
|
||||
}
|
||||
*node = data->current;
|
||||
update_next(iter);
|
||||
return (*node == NULL) ? 0 : ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int find_iter_has_next(IsoDirIter *iter)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
|
||||
return (data->current != NULL);
|
||||
}
|
||||
|
||||
static
|
||||
void find_iter_free(IsoDirIter *iter)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
if (data->free_cond) {
|
||||
data->cond->free(data->cond);
|
||||
free(data->cond);
|
||||
}
|
||||
|
||||
iso_node_unref((IsoNode*)data->dir);
|
||||
|
||||
/* free refs to nodes */
|
||||
if (data->prev) {
|
||||
iso_node_unref(data->prev);
|
||||
}
|
||||
if (data->current) {
|
||||
iso_node_unref(data->current);
|
||||
}
|
||||
|
||||
/* free underlying iter */
|
||||
iso_dir_iter_free(data->iter);
|
||||
free(iter->data);
|
||||
}
|
||||
|
||||
static
|
||||
int find_iter_take(IsoDirIter *iter)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
|
||||
if (data->prev == NULL) {
|
||||
return ISO_ERROR; /* next not called or end of dir */
|
||||
}
|
||||
return iso_node_take(data->prev);
|
||||
}
|
||||
|
||||
static
|
||||
int find_iter_remove(IsoDirIter *iter)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
|
||||
if (data->prev == NULL) {
|
||||
return ISO_ERROR; /* next not called or end of dir */
|
||||
}
|
||||
return iso_node_remove(data->prev);
|
||||
}
|
||||
|
||||
void find_notify_child_taken(IsoDirIter *iter, IsoNode *node)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
|
||||
if (data->prev == node) {
|
||||
/* free our ref */
|
||||
iso_node_unref(node);
|
||||
data->prev = NULL;
|
||||
} else if (data->current == node) {
|
||||
iso_node_unref(node);
|
||||
data->current = NULL;
|
||||
update_next(iter);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
struct iso_dir_iter_iface find_iter_class = {
|
||||
find_iter_next,
|
||||
find_iter_has_next,
|
||||
find_iter_free,
|
||||
find_iter_take,
|
||||
find_iter_remove,
|
||||
find_notify_child_taken
|
||||
};
|
||||
|
||||
int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond,
|
||||
IsoDirIter **iter)
|
||||
{
|
||||
int ret;
|
||||
IsoDirIter *children;
|
||||
IsoDirIter *it;
|
||||
struct find_iter_data *data;
|
||||
|
||||
if (dir == NULL || cond == NULL || iter == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
it = malloc(sizeof(IsoDirIter));
|
||||
if (it == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
data = malloc(sizeof(struct find_iter_data));
|
||||
if (data == NULL) {
|
||||
free(it);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
ret = iso_dir_get_children(dir, &children);
|
||||
if (ret < 0) {
|
||||
free(it);
|
||||
free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
it->class = &find_iter_class;
|
||||
it->dir = (IsoDir*)dir;
|
||||
data->iter = children;
|
||||
data->itersec = NULL;
|
||||
data->cond = cond;
|
||||
data->free_cond = 1;
|
||||
data->err = 0;
|
||||
data->prev = data->current = NULL;
|
||||
it->data = data;
|
||||
|
||||
if (iso_dir_iter_register(it) < 0) {
|
||||
free(it);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
iso_node_ref((IsoNode*)dir);
|
||||
|
||||
/* take another ref to the original dir */
|
||||
data->dir = (IsoDir*)dir;
|
||||
iso_node_ref((IsoNode*)dir);
|
||||
|
||||
update_next(it);
|
||||
|
||||
*iter = it;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/*************** find by name wildcard condition *****************/
|
||||
|
||||
static
|
||||
int cond_name_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
char *pattern = (char*) cond->data;
|
||||
int ret = fnmatch(pattern, node->name, 0);
|
||||
return ret == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cond_name_free(IsoFindCondition *cond)
|
||||
{
|
||||
free(cond->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks if the node name matches the given
|
||||
* wildcard.
|
||||
*
|
||||
* @param wildcard
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_name(const char *wildcard)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
if (wildcard == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cond->data = strdup(wildcard);
|
||||
cond->free = cond_name_free;
|
||||
cond->matches = cond_name_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/*************** find by mode condition *****************/
|
||||
|
||||
static
|
||||
int cond_mode_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
mode_t *mask = (mode_t*) cond->data;
|
||||
return node->mode & *mask ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cond_mode_free(IsoFindCondition *cond)
|
||||
{
|
||||
free(cond->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks the node mode against a mode mask. It
|
||||
* can be used to check both file type and permissions.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* iso_new_find_conditions_mode(S_IFREG) : search for regular files
|
||||
* iso_new_find_conditions_mode(S_IFCHR | S_IWUSR) : search for character
|
||||
* devices where owner has write permissions.
|
||||
*
|
||||
* @param mask
|
||||
* Mode mask to AND against node mode.
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_mode(mode_t mask)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
mode_t *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(mode_t));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
*data = mask;
|
||||
cond->data = data;
|
||||
cond->free = cond_mode_free;
|
||||
cond->matches = cond_mode_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/*************** find by gid condition *****************/
|
||||
|
||||
static
|
||||
int cond_gid_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
gid_t *gid = (gid_t*) cond->data;
|
||||
return node->gid == *gid ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cond_gid_free(IsoFindCondition *cond)
|
||||
{
|
||||
free(cond->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks the node gid.
|
||||
*
|
||||
* @param gid
|
||||
* Desired Group Id.
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_gid(gid_t gid)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
gid_t *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(gid_t));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
*data = gid;
|
||||
cond->data = data;
|
||||
cond->free = cond_gid_free;
|
||||
cond->matches = cond_gid_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/*************** find by uid condition *****************/
|
||||
|
||||
static
|
||||
int cond_uid_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
uid_t *uid = (uid_t*) cond->data;
|
||||
return node->uid == *uid ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cond_uid_free(IsoFindCondition *cond)
|
||||
{
|
||||
free(cond->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks the node uid.
|
||||
*
|
||||
* @param uid
|
||||
* Desired User Id.
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_uid(uid_t uid)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
uid_t *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(uid_t));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
*data = uid;
|
||||
cond->data = data;
|
||||
cond->free = cond_uid_free;
|
||||
cond->matches = cond_uid_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/*************** find by timestamps condition *****************/
|
||||
|
||||
struct cond_times
|
||||
{
|
||||
time_t time;
|
||||
int what_time; /* 0 atime, 1 mtime, 2 ctime */
|
||||
enum iso_find_comparisons comparison;
|
||||
};
|
||||
|
||||
static
|
||||
int cond_time_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
time_t node_time;
|
||||
struct cond_times *data = cond->data;
|
||||
|
||||
switch (data->what_time) {
|
||||
case 0: node_time = node->atime; break;
|
||||
case 1: node_time = node->mtime; break;
|
||||
default: node_time = node->ctime; break;
|
||||
}
|
||||
|
||||
switch (data->comparison) {
|
||||
case ISO_FIND_COND_GREATER:
|
||||
return node_time > data->time ? 1 : 0;
|
||||
case ISO_FIND_COND_GREATER_OR_EQUAL:
|
||||
return node_time >= data->time ? 1 : 0;
|
||||
case ISO_FIND_COND_EQUAL:
|
||||
return node_time == data->time ? 1 : 0;
|
||||
case ISO_FIND_COND_LESS:
|
||||
return node_time < data->time ? 1 : 0;
|
||||
case ISO_FIND_COND_LESS_OR_EQUAL:
|
||||
return node_time <= data->time ? 1 : 0;
|
||||
}
|
||||
/* should never happen */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cond_time_free(IsoFindCondition *cond)
|
||||
{
|
||||
free(cond->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks the time of last access.
|
||||
*
|
||||
* @param time
|
||||
* Time to compare against IsoNode atime.
|
||||
* @param comparison
|
||||
* Comparison to be done between IsoNode atime and submitted time.
|
||||
* Note that ISO_FIND_COND_GREATER, for example, is true if the node
|
||||
* time is greater than the submitted time.
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_atime(time_t time,
|
||||
enum iso_find_comparisons comparison)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
struct cond_times *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(struct cond_times));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
data->time = time;
|
||||
data->comparison = comparison;
|
||||
data->what_time = 0; /* atime */
|
||||
cond->data = data;
|
||||
cond->free = cond_time_free;
|
||||
cond->matches = cond_time_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks the time of last modification.
|
||||
*
|
||||
* @param time
|
||||
* Time to compare against IsoNode mtime.
|
||||
* @param comparison
|
||||
* Comparison to be done between IsoNode mtime and submitted time.
|
||||
* Note that ISO_FIND_COND_GREATER, for example, is true if the node
|
||||
* time is greater than the submitted time.
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_mtime(time_t time,
|
||||
enum iso_find_comparisons comparison)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
struct cond_times *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(struct cond_times));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
data->time = time;
|
||||
data->comparison = comparison;
|
||||
data->what_time = 1; /* mtime */
|
||||
cond->data = data;
|
||||
cond->free = cond_time_free;
|
||||
cond->matches = cond_time_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that checks the time of last status change.
|
||||
*
|
||||
* @param time
|
||||
* Time to compare against IsoNode ctime.
|
||||
* @param comparison
|
||||
* Comparison to be done between IsoNode ctime and submitted time.
|
||||
* Note that ISO_FIND_COND_GREATER, for example, is true if the node
|
||||
* time is greater than the submitted time.
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_ctime(time_t time,
|
||||
enum iso_find_comparisons comparison)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
struct cond_times *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(struct cond_times));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
data->time = time;
|
||||
data->comparison = comparison;
|
||||
data->what_time = 2; /* ctime */
|
||||
cond->data = data;
|
||||
cond->free = cond_time_free;
|
||||
cond->matches = cond_time_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
/*************** logical operations on conditions *****************/
|
||||
|
||||
struct logical_binary_conditions {
|
||||
IsoFindCondition *a;
|
||||
IsoFindCondition *b;
|
||||
};
|
||||
|
||||
static
|
||||
void cond_logical_binary_free(IsoFindCondition *cond)
|
||||
{
|
||||
struct logical_binary_conditions *data;
|
||||
data = cond->data;
|
||||
data->a->free(data->a);
|
||||
free(data->a);
|
||||
data->b->free(data->b);
|
||||
free(data->b);
|
||||
free(cond->data);
|
||||
}
|
||||
|
||||
static
|
||||
int cond_logical_and_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
struct logical_binary_conditions *data = cond->data;
|
||||
return data->a->matches(data->a, node) && data->b->matches(data->b, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that check if the two given conditions are
|
||||
* valid.
|
||||
*
|
||||
* @param a
|
||||
* @param b
|
||||
* IsoFindCondition to compare
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_and(IsoFindCondition *a,
|
||||
IsoFindCondition *b)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
struct logical_binary_conditions *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(struct logical_binary_conditions));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
data->a = a;
|
||||
data->b = b;
|
||||
cond->data = data;
|
||||
cond->free = cond_logical_binary_free;
|
||||
cond->matches = cond_logical_and_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
static
|
||||
int cond_logical_or_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
struct logical_binary_conditions *data = cond->data;
|
||||
return data->a->matches(data->a, node) || data->b->matches(data->b, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that check if at least one the two given conditions
|
||||
* is valid.
|
||||
*
|
||||
* @param a
|
||||
* @param b
|
||||
* IsoFindCondition to compare
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_or(IsoFindCondition *a,
|
||||
IsoFindCondition *b)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
struct logical_binary_conditions *data;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
data = malloc(sizeof(struct logical_binary_conditions));
|
||||
if (data == NULL) {
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
data->a = a;
|
||||
data->b = b;
|
||||
cond->data = data;
|
||||
cond->free = cond_logical_binary_free;
|
||||
cond->matches = cond_logical_or_matches;
|
||||
return cond;
|
||||
}
|
||||
|
||||
static
|
||||
void cond_not_free(IsoFindCondition *cond)
|
||||
{
|
||||
IsoFindCondition *negate = cond->data;
|
||||
negate->free(negate);
|
||||
free(negate);
|
||||
}
|
||||
|
||||
static
|
||||
int cond_not_matches(IsoFindCondition *cond, IsoNode *node)
|
||||
{
|
||||
IsoFindCondition *negate = cond->data;
|
||||
return !(negate->matches(negate, node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new condition that check if the given conditions is false.
|
||||
*
|
||||
* @param negate
|
||||
* @result
|
||||
* The created IsoFindCondition, NULL on error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
IsoFindCondition *iso_new_find_conditions_not(IsoFindCondition *negate)
|
||||
{
|
||||
IsoFindCondition *cond;
|
||||
cond = malloc(sizeof(IsoFindCondition));
|
||||
if (cond == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cond->data = negate;
|
||||
cond->free = cond_not_free;
|
||||
cond->matches = cond_not_matches;
|
||||
return cond;
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ int ifs_open(IsoFileSource *src)
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
|
||||
if (data->opened) {
|
||||
return ISO_FILE_ALREADY_OPENNED;
|
||||
return ISO_FILE_ALREADY_OPENED;
|
||||
}
|
||||
|
||||
if (S_ISDIR(data->info.st_mode)) {
|
||||
@ -530,7 +530,7 @@ int ifs_close(IsoFileSource *src)
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
|
||||
if (!data->opened) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (data->opened == 2) {
|
||||
@ -569,7 +569,7 @@ int ifs_close(IsoFileSource *src)
|
||||
* Error codes:
|
||||
* ISO_FILE_ERROR
|
||||
* ISO_NULL_POINTER
|
||||
* ISO_FILE_NOT_OPENNED
|
||||
* ISO_FILE_NOT_OPENED
|
||||
* ISO_FILE_IS_DIR
|
||||
* ISO_OUT_OF_MEM
|
||||
* ISO_INTERRUPTED
|
||||
@ -590,7 +590,7 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count)
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
|
||||
if (!data->opened) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
} else if (data->opened != 1) {
|
||||
return ISO_FILE_IS_DIR;
|
||||
}
|
||||
@ -632,6 +632,60 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count)
|
||||
return read;
|
||||
}
|
||||
|
||||
static
|
||||
off_t ifs_lseek(IsoFileSource *src, off_t offset, int flag)
|
||||
{
|
||||
ImageFileSourceData *data;
|
||||
|
||||
if (src == NULL) {
|
||||
return (off_t)ISO_NULL_POINTER;
|
||||
}
|
||||
if (offset < (off_t)0) {
|
||||
return (off_t)ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
data = src->data;
|
||||
|
||||
if (!data->opened) {
|
||||
return (off_t)ISO_FILE_NOT_OPENED;
|
||||
} else if (data->opened != 1) {
|
||||
return (off_t)ISO_FILE_IS_DIR;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case 0: /* SEEK_SET */
|
||||
data->data.offset = offset;
|
||||
break;
|
||||
case 1: /* SEEK_CUR */
|
||||
data->data.offset += offset;
|
||||
break;
|
||||
case 2: /* SEEK_END */
|
||||
/* do this make sense? */
|
||||
data->data.offset = data->info.st_size + offset;
|
||||
break;
|
||||
default:
|
||||
return (off_t)ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
if (data->data.offset % BLOCK_SIZE != 0) {
|
||||
/* we need to buffer the block */
|
||||
uint32_t block;
|
||||
_ImageFsData *fsdata;
|
||||
|
||||
if (data->data.offset < data->info.st_size) {
|
||||
int ret;
|
||||
fsdata = data->fs->data;
|
||||
block = data->block + (data->data.offset / BLOCK_SIZE);
|
||||
ret = fsdata->src->read_block(fsdata->src, block,
|
||||
data->data.content);
|
||||
if (ret < 0) {
|
||||
return (off_t)ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data->data.offset;
|
||||
}
|
||||
|
||||
static
|
||||
int ifs_readdir(IsoFileSource *src, IsoFileSource **child)
|
||||
{
|
||||
@ -644,7 +698,7 @@ int ifs_readdir(IsoFileSource *src, IsoFileSource **child)
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
|
||||
if (!data->opened) {
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
} else if (data->opened != 2) {
|
||||
return ISO_FILE_IS_NOT_DIR;
|
||||
}
|
||||
@ -774,7 +828,8 @@ IsoFileSourceIface ifs_class = {
|
||||
ifs_readdir,
|
||||
ifs_readlink,
|
||||
ifs_get_filesystem,
|
||||
ifs_free
|
||||
ifs_free,
|
||||
ifs_lseek
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2081,7 +2136,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
free(name);
|
||||
return ret;
|
||||
}
|
||||
link = malloc(sizeof(IsoSymlink));
|
||||
link = calloc(1, sizeof(IsoSymlink));
|
||||
if (link == NULL) {
|
||||
free(name);
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -2099,7 +2154,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
{
|
||||
/* source is an special file */
|
||||
IsoSpecial *special;
|
||||
special = malloc(sizeof(IsoSpecial));
|
||||
special = calloc(1, sizeof(IsoSpecial));
|
||||
if (special == NULL) {
|
||||
free(name);
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
@ -190,7 +190,7 @@ int lfs_open(IsoFileSource *src)
|
||||
|
||||
data = src->data;
|
||||
if (data->openned) {
|
||||
return ISO_FILE_ALREADY_OPENNED;
|
||||
return ISO_FILE_ALREADY_OPENED;
|
||||
}
|
||||
|
||||
/* is a file or a dir ? */
|
||||
@ -251,7 +251,7 @@ int lfs_close(IsoFileSource *src)
|
||||
ret = closedir(data->info.dir) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR;
|
||||
break;
|
||||
default:
|
||||
ret = ISO_FILE_NOT_OPENNED;
|
||||
ret = ISO_FILE_NOT_OPENED;
|
||||
break;
|
||||
}
|
||||
if (ret == ISO_SUCCESS) {
|
||||
@ -300,7 +300,53 @@ int lfs_read(IsoFileSource *src, void *buf, size_t count)
|
||||
case 2: /* directory */
|
||||
return ISO_FILE_IS_DIR;
|
||||
default:
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag)
|
||||
{
|
||||
_LocalFsFileSource *data;
|
||||
int whence;
|
||||
|
||||
if (src == NULL) {
|
||||
return (off_t)ISO_NULL_POINTER;
|
||||
}
|
||||
switch (flag) {
|
||||
case 0:
|
||||
whence = SEEK_SET; break;
|
||||
case 1:
|
||||
whence = SEEK_CUR; break;
|
||||
case 2:
|
||||
whence = SEEK_END; break;
|
||||
default:
|
||||
return (off_t)ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
data = src->data;
|
||||
switch (data->openned) {
|
||||
case 1: /* not dir */
|
||||
{
|
||||
off_t ret;
|
||||
ret = lseek(data->info.fd, offset, whence);
|
||||
if (ret < 0) {
|
||||
/* error on read */
|
||||
switch (errno) {
|
||||
case ESPIPE:
|
||||
ret = (off_t)ISO_FILE_ERROR;
|
||||
break;
|
||||
default:
|
||||
ret = (off_t)ISO_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case 2: /* directory */
|
||||
return (off_t)ISO_FILE_IS_DIR;
|
||||
default:
|
||||
return (off_t)ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +387,7 @@ int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
return ISO_FILE_NOT_OPENNED;
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,7 +479,8 @@ IsoFileSourceIface lfs_class = {
|
||||
lfs_readdir,
|
||||
lfs_readlink,
|
||||
lfs_get_filesystem,
|
||||
lfs_free
|
||||
lfs_free,
|
||||
lfs_lseek
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -92,6 +92,12 @@ int iso_file_source_read(IsoFileSource *src, void *buf, size_t count)
|
||||
return src->class->read(src, buf, count);
|
||||
}
|
||||
|
||||
inline
|
||||
off_t iso_file_source_lseek(IsoFileSource *src, off_t offset, int flag)
|
||||
{
|
||||
return src->class->lseek(src, offset, flag);
|
||||
}
|
||||
|
||||
inline
|
||||
int iso_file_source_readdir(IsoFileSource *src, IsoFileSource **child)
|
||||
{
|
||||
|
@ -519,7 +519,7 @@ struct IsoFileSource_Iface
|
||||
* Opens the source.
|
||||
* @return 1 on success, < 0 on error
|
||||
* Error codes:
|
||||
* ISO_FILE_ALREADY_OPENNED
|
||||
* ISO_FILE_ALREADY_OPENED
|
||||
* ISO_FILE_ACCESS_DENIED
|
||||
* ISO_FILE_BAD_PATH
|
||||
* ISO_FILE_DOESNT_EXIST
|
||||
@ -535,7 +535,7 @@ struct IsoFileSource_Iface
|
||||
* Error codes:
|
||||
* ISO_FILE_ERROR
|
||||
* ISO_NULL_POINTER
|
||||
* ISO_FILE_NOT_OPENNED
|
||||
* ISO_FILE_NOT_OPENED
|
||||
*/
|
||||
int (*close)(IsoFileSource *src);
|
||||
|
||||
@ -552,7 +552,7 @@ struct IsoFileSource_Iface
|
||||
* Error codes:
|
||||
* ISO_FILE_ERROR
|
||||
* ISO_NULL_POINTER
|
||||
* ISO_FILE_NOT_OPENNED
|
||||
* ISO_FILE_NOT_OPENED
|
||||
* ISO_WRONG_ARG_VALUE -> if count == 0
|
||||
* ISO_FILE_IS_DIR
|
||||
* ISO_OUT_OF_MEM
|
||||
@ -578,7 +578,7 @@ struct IsoFileSource_Iface
|
||||
* Error codes:
|
||||
* ISO_FILE_ERROR
|
||||
* ISO_NULL_POINTER
|
||||
* ISO_FILE_NOT_OPENNED
|
||||
* ISO_FILE_NOT_OPENED
|
||||
* ISO_FILE_IS_NOT_DIR
|
||||
* ISO_OUT_OF_MEM
|
||||
*/
|
||||
@ -622,6 +622,26 @@ struct IsoFileSource_Iface
|
||||
* Use iso_file_source_unref() instead.
|
||||
*/
|
||||
void (*free)(IsoFileSource *src);
|
||||
|
||||
/**
|
||||
* Repositions the offset of the IsoFileSource (must be opened) to the
|
||||
* given offset according to the value of flag.
|
||||
*
|
||||
* @param offset
|
||||
* in bytes
|
||||
* @param flag
|
||||
* 0 The offset is set to offset bytes (SEEK_SET)
|
||||
* 1 The offset is set to its current location plus offset bytes
|
||||
* (SEEK_CUR)
|
||||
* 2 The offset is set to the size of the file plus offset bytes
|
||||
* (SEEK_END).
|
||||
* @return
|
||||
* Absolute offset posistion on the file, or < 0 on error. Cast the
|
||||
* returning value to int to get a valid libisofs error.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
off_t (*lseek)(IsoFileSource *src, off_t offset, int flag);
|
||||
|
||||
/*
|
||||
* TODO #00004 Add a get_mime_type() function.
|
||||
@ -1800,6 +1820,78 @@ void iso_node_unref(IsoNode *node);
|
||||
*/
|
||||
enum IsoNodeType iso_node_get_type(IsoNode *node);
|
||||
|
||||
/**
|
||||
* Function to handle particular extended information. The function
|
||||
* pointer acts as an identifier for the type of the information. Structs
|
||||
* with same information type must use the same function.
|
||||
*
|
||||
* @param data
|
||||
* Attached data
|
||||
* @param flag
|
||||
* What to do with the data. At this time the following values are
|
||||
* defined:
|
||||
* -> 1 the data must be freed
|
||||
* @return
|
||||
* 1 in any case.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
typedef int (*iso_node_xinfo_func)(void *data, int flag);
|
||||
|
||||
/**
|
||||
* Add extended information to the given node. Extended info allows
|
||||
* applications (and libisofs itself) to add more information to an IsoNode.
|
||||
* You can use this facilities to associate new information with a given
|
||||
* node.
|
||||
*
|
||||
* Each node keeps a list of added extended info, meaning you can add several
|
||||
* extended info data to each node. Each extended info you add is identified
|
||||
* by the proc parameter, a pointer to a function that knows how to manage
|
||||
* the external info data. Thus, in order to add several types of extended
|
||||
* info, you need to define a "proc" function for each type.
|
||||
*
|
||||
* @param node
|
||||
* The node where to add the extended info
|
||||
* @param proc
|
||||
* A function pointer used to identify the type of the data, and that
|
||||
* knows how to manage it
|
||||
* @param data
|
||||
* Extended info to add.
|
||||
* @return
|
||||
* 1 if success, 0 if the given node already has extended info of the
|
||||
* type defined by the "proc" function, < 0 on error
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data);
|
||||
|
||||
/**
|
||||
* Remove the given extended info (defined by the proc function) from the
|
||||
* given node.
|
||||
*
|
||||
* @return
|
||||
* 1 on success, 0 if node does not have extended info of the requested
|
||||
* type, < 0 on error
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc);
|
||||
|
||||
/**
|
||||
* Get the given extended info (defined by the proc function) from the
|
||||
* given node.
|
||||
*
|
||||
* @param data
|
||||
* Will be filled with the extended info corresponding to the given proc
|
||||
* function
|
||||
* @return
|
||||
* 1 on success, 0 if node does not have extended info of the requested
|
||||
* type, < 0 on error
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data);
|
||||
|
||||
/**
|
||||
* Set the name of a node. Note that if the node is already added to a dir
|
||||
* this can fail if dir already contains a node with the new name.
|
||||
@ -2062,7 +2154,7 @@ IsoDir *iso_node_get_parent(IsoNode *node);
|
||||
* you should free the iterator with iso_dir_iter_free.
|
||||
* You musn't delete a child of the same dir, using iso_node_take() or
|
||||
* iso_node_remove(), while you're using the iterator. You can use
|
||||
* iso_node_take_iter() or iso_node_remove_iter() instead.
|
||||
* iso_dir_iter_take() or iso_dir_iter_remove() instead.
|
||||
*
|
||||
* You can use the iterator in the way like this
|
||||
*
|
||||
@ -2131,8 +2223,8 @@ void iso_dir_iter_free(IsoDirIter *iter);
|
||||
* It's like iso_node_take(), but to be used during a directory iteration.
|
||||
* The node removed will be the last returned by the iteration.
|
||||
*
|
||||
* The behavior on two call to this function without calling iso_dir_iter_next
|
||||
* between then is undefined, and should never occur. (TODO protect against this?)
|
||||
* If you call this function twice without calling iso_dir_iter_next between
|
||||
* them is not allowed and you will get an ISO_ERROR in second call.
|
||||
*
|
||||
* @return
|
||||
* 1 on succes, < 0 error
|
||||
@ -2150,8 +2242,8 @@ int iso_dir_iter_take(IsoDirIter *iter);
|
||||
* It's like iso_node_remove(), but to be used during a directory iteration.
|
||||
* The node removed will be the last returned by the iteration.
|
||||
*
|
||||
* The behavior on two call to this function without calling iso_tree_iter_next
|
||||
* between then is undefined, and should never occur. (TODO protect against this?)
|
||||
* If you call this function twice without calling iso_dir_iter_next between
|
||||
* them is not allowed and you will get an ISO_ERROR in second call.
|
||||
*
|
||||
* @return
|
||||
* 1 on succes, < 0 error
|
||||
@ -2164,6 +2256,191 @@ int iso_dir_iter_take(IsoDirIter *iter);
|
||||
*/
|
||||
int iso_dir_iter_remove(IsoDirIter *iter);
|
||||
|
||||
|
||||
/**
|
||||
* @since 0.6.4
|
||||
*/
|
||||
typedef struct iso_find_condition IsoFindCondition;
|
||||
|
||||
/**
|
||||
* Create a new condition that checks if the node name matches the given
|
||||
* wildcard.
|
||||