Switch to Vreixo development branch 386
This commit is contained in:
parent
e50b3b6492
commit
dd10efd80c
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
@ -774,7 +828,8 @@ IsoFileSourceIface ifs_class = {
|
||||
ifs_readdir,
|
||||
ifs_readlink,
|
||||
ifs_get_filesystem,
|
||||
ifs_free
|
||||
ifs_free,
|
||||
ifs_lseek
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -304,6 +304,52 @@ int lfs_read(IsoFileSource *src, void *buf, size_t count)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
@ -2131,8 +2151,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 +2170,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
|
||||
@ -2469,10 +2489,36 @@ int iso_node_get_old_image_lba(IsoNode *node, uint32_t *lba, int flag);
|
||||
*/
|
||||
int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir);
|
||||
|
||||
/*
|
||||
TODO #00007 expose Stream and this function:
|
||||
int iso_tree_add_new_file(IsoDir *parent, const char *name, stream, file)
|
||||
/**
|
||||
* Add a new regular file to the iso tree. Permissions are set to 0444,
|
||||
* owner and hidden atts are taken from parent. You can modify any of them
|
||||
* later.
|
||||
*
|
||||
* @param parent
|
||||
* the dir where the new file will be created
|
||||
* @param name
|
||||
* name for the new file. If a node with same name already exists on
|
||||
* parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE.
|
||||
* @param stream
|
||||
* IsoStream for the contents of the file. The reference will be taken
|
||||
* by the newly created file, you will need to take an extra ref to it
|
||||
* if you need it.
|
||||
* @param file
|
||||
* place where to store a pointer to the newly created file. No extra
|
||||
* ref is addded, so you will need to call iso_node_ref() if you really
|
||||
* need it. You can pass NULL in this parameter if you don't need the
|
||||
* pointer
|
||||
* @return
|
||||
* number of nodes in parent if success, < 0 otherwise
|
||||
* Possible errors:
|
||||
* ISO_NULL_POINTER, if parent, name or dest are NULL
|
||||
* ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists
|
||||
* ISO_OUT_OF_MEM
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream,
|
||||
IsoFile **file);
|
||||
|
||||
/**
|
||||
* Add a new symlink to the directory tree. Permissions are set to 0777,
|
||||
@ -2760,6 +2806,44 @@ int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path,
|
||||
int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
||||
const char *path, IsoNode **node);
|
||||
|
||||
/**
|
||||
* Add a new node to the image tree, from an existing file, and with the
|
||||
* given name, that must not exist on dir. The node will be cut-out to the
|
||||
* submitted size, and its contents will be read from the given offset. This
|
||||
* function is thus suitable for adding only a piece of a file to the image.
|
||||
*
|
||||
* @param image
|
||||
* The image
|
||||
* @param parent
|
||||
* The directory in the image tree where the node will be added.
|
||||
* @param name
|
||||
* The name that the node will have on image.
|
||||
* @param path
|
||||
* The path of the file to add in the filesystem. For now only regular
|
||||
* files and symlinks to regular files are supported.
|
||||
* @param offset
|
||||
* Offset on the given file from where to start reading data.
|
||||
* @param size
|
||||
* Max size of the file.
|
||||
* @param node
|
||||
* place where to store a pointer to the newly added file. No
|
||||
* extra ref is addded, so you will need to call iso_node_ref() if you
|
||||
* really need it. You can pass NULL in this parameter if you don't need
|
||||
* the pointer.
|
||||
* @return
|
||||
* number of nodes in parent if success, < 0 otherwise
|
||||
* Possible errors:
|
||||
* ISO_NULL_POINTER, if image, parent or path are NULL
|
||||
* ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists
|
||||
* ISO_OUT_OF_MEM
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
|
||||
const char *name, const char *path,
|
||||
off_t offset, off_t size,
|
||||
IsoNode **node);
|
||||
|
||||
/**
|
||||
* Add the contents of a dir to a given directory of the iso tree.
|
||||
*
|
||||
@ -3190,6 +3274,25 @@ int iso_file_source_close(IsoFileSource *src);
|
||||
*/
|
||||
int iso_file_source_read(IsoFileSource *src, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* Repositions the offset of the given 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 iso_file_source_lseek(IsoFileSource *src, off_t offset, int flag);
|
||||
|
||||
/**
|
||||
* Read a directory.
|
||||
*
|
||||
@ -3575,10 +3678,16 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
|
||||
/**
|
||||
* File path break specification constraints and will be ignored
|
||||
* (HINT,MEDIUM, -141)
|
||||
* (HINT,MEDIUM, -144)
|
||||
*/
|
||||
#define ISO_FILE_IMGPATH_WRONG 0xC020FF70
|
||||
|
||||
/**
|
||||
* Offset greater than file size (FAILURE,HIGH, -145)
|
||||
* @since 0.6.4
|
||||
*/
|
||||
#define ISO_FILE_OFFSET_TOO_BIG 0xE830FF6A
|
||||
|
||||
/** Charset conversion error (FAILURE,HIGH, -256) */
|
||||
#define ISO_CHARSET_CONV_ERROR 0xE830FF00
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
ino_t serial_id = (ino_t)1;
|
||||
ino_t mem_serial_id = (ino_t)1;
|
||||
ino_t cut_out_serial_id = (ino_t)1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -175,7 +176,7 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
data = malloc(sizeof(FSrcStreamData));
|
||||
if (str == NULL) {
|
||||
if (data == NULL) {
|
||||
free(str);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
@ -212,6 +213,193 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
struct cut_out_stream
|
||||
{
|
||||
IsoFileSource *src;
|
||||
|
||||
/* key for file identification inside filesystem */
|
||||
dev_t dev_id;
|
||||
ino_t ino_id;
|
||||
off_t offset; /**< offset where read begins */
|
||||
off_t size; /**< size of this file */
|
||||
off_t pos; /* position on the file for read */
|
||||
};
|
||||
|
||||
static
|
||||
int cut_out_open(IsoStream *stream)
|
||||
{
|
||||
int ret;
|
||||
struct stat info;
|
||||
IsoFileSource *src;
|
||||
struct cut_out_stream *data;
|
||||
|
||||
if (stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
data = stream->data;
|
||||
src = data->src;
|
||||
ret = iso_file_source_stat(data->src, &info);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = iso_file_source_open(src);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
{
|
||||
off_t ret;
|
||||
if (data->offset > info.st_size) {
|
||||
/* file is smaller than expected */
|
||||
ret = iso_file_source_lseek(src, info.st_size, 0);
|
||||
} else {
|
||||
ret = iso_file_source_lseek(src, data->offset, 0);
|
||||
}
|
||||
if (ret < 0) {
|
||||
return (int) ret;
|
||||
}
|
||||
}
|
||||
data->pos = 0;
|
||||
if (data->offset + data->size > info.st_size) {
|
||||
return 3; /* file smaller than expected */
|
||||
} else {
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_close(IsoStream *stream)
|
||||
{
|
||||
IsoFileSource *src;
|
||||
if (stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
src = ((struct cut_out_stream*)stream->data)->src;
|
||||
return iso_file_source_close(src);
|
||||
}
|
||||
|
||||
static
|
||||
off_t cut_out_get_size(IsoStream *stream)
|
||||
{
|
||||
struct cut_out_stream *data = stream->data;
|
||||
return data->size;
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_read(IsoStream *stream, void *buf, size_t count)
|
||||
{
|
||||
struct cut_out_stream *data = stream->data;
|
||||
count = (size_t)MIN(data->size - data->pos, count);
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
return iso_file_source_read(data->src, buf, count);
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_is_repeatable(IsoStream *stream)
|
||||
{
|
||||
/* reg files are always repeatable */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void cut_out_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
ino_t *ino_id)
|
||||
{
|
||||
FSrcStreamData *data;
|
||||
IsoFilesystem *fs;
|
||||
|
||||
data = (FSrcStreamData*)stream->data;
|
||||
fs = iso_file_source_get_filesystem(data->src);
|
||||
|
||||
*fs_id = fs->get_id(fs);
|
||||
*dev_id = data->dev_id;
|
||||
*ino_id = data->ino_id;
|
||||
}
|
||||
|
||||
static
|
||||
void cut_out_free(IsoStream *stream)
|
||||
{
|
||||
struct cut_out_stream *data = stream->data;
|
||||
iso_file_source_unref(data->src);
|
||||
free(data);
|
||||
}
|
||||
|
||||
IsoStreamIface cut_out_stream_class = {
|
||||
0,
|
||||
"cout",
|
||||
cut_out_open,
|
||||
cut_out_close,
|
||||
cut_out_get_size,
|
||||
cut_out_read,
|
||||
cut_out_is_repeatable,
|
||||
cut_out_get_id,
|
||||
cut_out_free
|
||||
};
|
||||
|
||||
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
||||
IsoStream **stream)
|
||||
{
|
||||
int r;
|
||||
struct stat info;
|
||||
IsoStream *str;
|
||||
struct cut_out_stream *data;
|
||||
|
||||
if (src == NULL || stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (size == 0) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
r = iso_file_source_stat(src, &info);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (offset > info.st_size) {
|
||||
return ISO_FILE_OFFSET_TOO_BIG;
|
||||
}
|
||||
|
||||
/* check for read access to contents */
|
||||
r = iso_file_source_access(src);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
str = malloc(sizeof(IsoStream));
|
||||
if (str == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
data = malloc(sizeof(struct cut_out_stream));
|
||||
if (data == NULL) {
|
||||
free(str);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
/* take a new ref to IsoFileSource */
|
||||
data->src = src;
|
||||
iso_file_source_ref(src);
|
||||
|
||||
data->offset = offset;
|
||||
data->size = MIN(info.st_size - offset, size);
|
||||
|
||||
/* get the id numbers */
|
||||
data->dev_id = (dev_t) 0;
|
||||
data->ino_id = cut_out_serial_id++;
|
||||
|
||||
str->refcount = 1;
|
||||
str->data = data;
|
||||
str->class = &cut_out_stream_class;
|
||||
|
||||
*stream = str;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
|
@ -33,6 +33,16 @@ void iso_stream_get_file_name(IsoStream *stream, char *name);
|
||||
*/
|
||||
int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream);
|
||||
|
||||
/**
|
||||
* Create a new stream to read a chunk of an IsoFileSource..
|
||||
* The stream will add a ref. to the IsoFileSource.
|
||||
*
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
*/
|
||||
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
||||
IsoStream **stream);
|
||||
|
||||
/**
|
||||
* Create a stream for reading from a arbitrary memory buffer.
|
||||
* When the Stream refcount reach 0, the buffer is free(3).
|
||||
|
161
libisofs/tree.c
161
libisofs/tree.c
@ -256,6 +256,81 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode,
|
||||
return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new regular file to the iso tree. Permissions are set to 0444,
|
||||
* owner and hidden atts are taken from parent. You can modify any of them
|
||||
* later.
|
||||
*
|
||||
* @param parent
|
||||
* the dir where the new file will be created
|
||||
* @param name
|
||||
* name for the new file. If a node with same name already exists on
|
||||
* parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE.
|
||||
* @param stream
|
||||
* IsoStream for the contents of the file
|
||||
* @param file
|
||||
* place where to store a pointer to the newly created file. No extra
|
||||
* ref is addded, so you will need to call iso_node_ref() if you really
|
||||
* need it. You can pass NULL in this parameter if you don't need the
|
||||
* pointer
|
||||
* @return
|
||||
* number of nodes in parent if success, < 0 otherwise
|
||||
* Possible errors:
|
||||
* ISO_NULL_POINTER, if parent, name or dest are NULL
|
||||
* ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists
|
||||
* ISO_OUT_OF_MEM
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream,
|
||||
IsoFile **file)
|
||||
{
|
||||
int ret;
|
||||
char *n;
|
||||
IsoFile *node;
|
||||
IsoNode **pos;
|
||||
time_t now;
|
||||
|
||||
if (parent == NULL || name == NULL || stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (file) {
|
||||
*file = NULL;
|
||||
}
|
||||
|
||||
/* find place where to insert */
|
||||
if (iso_dir_exists(parent, name, &pos)) {
|
||||
/* a node with same name already exists */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
}
|
||||
|
||||
n = strdup(name);
|
||||
ret = iso_node_new_file(n, stream, &node);
|
||||
if (ret < 0) {
|
||||
free(n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* permissions from parent */
|
||||
iso_node_set_permissions((IsoNode*)node, 0444);
|
||||
iso_node_set_uid((IsoNode*)node, parent->node.uid);
|
||||
iso_node_set_gid((IsoNode*)node, parent->node.gid);
|
||||
iso_node_set_hidden((IsoNode*)node, parent->node.hidden);
|
||||
|
||||
/* current time */
|
||||
now = time(NULL);
|
||||
iso_node_set_atime((IsoNode*)node, now);
|
||||
iso_node_set_ctime((IsoNode*)node, now);
|
||||
iso_node_set_mtime((IsoNode*)node, now);
|
||||
|
||||
if (file) {
|
||||
*file = node;
|
||||
}
|
||||
|
||||
/* add to dir */
|
||||
return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to follow or not symbolic links when added a file from a source
|
||||
* to IsoImage.
|
||||
@ -507,13 +582,14 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
||||
}
|
||||
|
||||
result = image->builder->create_node(image->builder, image, file, &new);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* free the file */
|
||||
iso_file_source_unref(file);
|
||||
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = iso_node_set_name(new, name);
|
||||
if (result < 0) {
|
||||
iso_node_unref(new);
|
||||
@ -528,6 +604,85 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
||||
return iso_dir_insert(parent, new, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
|
||||
const char *name, const char *path,
|
||||
off_t offset, off_t size,
|
||||
IsoNode **node)
|
||||
{
|
||||
int result;
|
||||
struct stat info;
|
||||
IsoFilesystem *fs;
|
||||
IsoFileSource *src;
|
||||
IsoFile *new;
|
||||
IsoNode **pos;
|
||||
IsoStream *stream;
|
||||
|
||||
if (image == NULL || parent == NULL || name == NULL || path == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
*node = NULL;
|
||||
}
|
||||
|
||||
/* find place where to insert */
|
||||
result = iso_dir_exists(parent, name, &pos);
|
||||
if (result) {
|
||||
/* a node with same name already exists */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
}
|
||||
|
||||
fs = image->fs;
|
||||
result = fs->get_by_path(fs, path, &src);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = iso_file_source_stat(src, &info);
|
||||
if (result < 0) {
|
||||
iso_file_source_unref(src);
|
||||
return result;
|
||||
}
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (offset >= info.st_size) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
/* force regular file */
|
||||
result = image->builder->create_file(image->builder, image, src, &new);
|
||||
|
||||
/* free the file */
|
||||
iso_file_source_unref(src);
|
||||
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* replace file iso stream with a cut-out-stream */
|
||||
result = iso_cut_out_stream_new(src, offset, size, &stream);
|
||||
if (result < 0) {
|
||||
iso_node_unref((IsoNode*)new);
|
||||
return result;
|
||||
}
|
||||
iso_stream_unref(new->stream);
|
||||
new->stream = stream;
|
||||
|
||||
result = iso_node_set_name((IsoNode*)new, name);
|
||||
if (result < 0) {
|
||||
iso_node_unref((IsoNode*)new);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
*node = (IsoNode*)new;
|
||||
}
|
||||
|
||||
/* finally, add node to parent */
|
||||
return iso_dir_insert(parent, (IsoNode*)new, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
static
|
||||
int check_excludes(IsoImage *image, const char *path)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user