Improved handling of unconvertable file names and name collsions during iso_image_import()
This commit is contained in:
parent
60eb7e883c
commit
44f475a4ef
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -96,7 +96,7 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
|
||||
|
||||
static
|
||||
int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoFileSource *src, IsoNode **node)
|
||||
IsoFileSource *src, char *in_name, IsoNode **node)
|
||||
{
|
||||
int ret;
|
||||
struct stat info;
|
||||
@ -122,7 +122,15 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
goto ex;
|
||||
}
|
||||
|
||||
if (in_name == NULL) {
|
||||
name = iso_file_source_get_name(src);
|
||||
} else {
|
||||
name = strdup(in_name);
|
||||
if (name == NULL) {
|
||||
ret = ISO_OUT_OF_MEM; goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||
name[LIBISOFS_NODE_NAME_MAX] = 0;
|
||||
fs = iso_file_source_get_filesystem(src);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -47,6 +48,7 @@ struct Iso_Node_Builder
|
||||
* Create a new IsoNode from a IsoFileSource. The type of the node to be
|
||||
* created is determined from the type of the file source. Name,
|
||||
* permissions and other attributes are taken from source file.
|
||||
* But name may be overridden by parameter name if it is not NULL.
|
||||
*
|
||||
* Note that the src is never unref, so you need to free it.
|
||||
*
|
||||
@ -54,7 +56,7 @@ struct Iso_Node_Builder
|
||||
* 1 on success, < 0 on error
|
||||
*/
|
||||
int (*create_node)(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoFileSource *src, IsoNode **node);
|
||||
IsoFileSource *src, char *name, IsoNode **node);
|
||||
|
||||
/**
|
||||
* Free implementation specific data. Should never be called by user.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -1237,15 +1237,67 @@ int iso_ifs_source_get_zf(IsoFileSource *src, int *header_size_div4,
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int make_hopefully_unique_name(_ImageFsData *fsdata,
|
||||
char *str, size_t len, char **name)
|
||||
{
|
||||
int ret, name_len, i;
|
||||
char c, *smashed = NULL, md5[16];
|
||||
void *md5_context = NULL;
|
||||
|
||||
/* Shorten so that 32 characters of MD5 fit.
|
||||
If shorter than 8, pad up to 8 by '_'.
|
||||
Smash characters to [0-9A-Za-z_.].
|
||||
Append MD5 of original str as hex digits.
|
||||
*/
|
||||
name_len = len > 223 ? 223 : len;
|
||||
LIBISO_ALLOC_MEM(smashed, char, (name_len >= 8 ? name_len : 8) + 32 + 1);
|
||||
memcpy(smashed, str, name_len);
|
||||
for (; name_len < 8; name_len++)
|
||||
smashed[name_len] = '_';
|
||||
smashed[name_len] = 0;
|
||||
for (i = 0; i < name_len; i++) {
|
||||
c = smashed[i];
|
||||
if (c == '.' || (c >= '0' && c <= '9') ||
|
||||
c == '_' || (c >= 'a' && c <= 'z'))
|
||||
continue;
|
||||
smashed[i] = '_';
|
||||
}
|
||||
ret = iso_md5_start(&md5_context);
|
||||
if (ret != 1)
|
||||
goto ex;
|
||||
ret = iso_md5_compute(md5_context, str, len);
|
||||
if (ret != 1)
|
||||
goto ex;
|
||||
ret = iso_md5_end(&md5_context, md5);
|
||||
if (ret != 1)
|
||||
goto ex;
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(smashed + i * 2 + name_len, "%2.2x",
|
||||
((unsigned char *) md5)[i]);
|
||||
name_len += 32;
|
||||
smashed[name_len] = 0;
|
||||
*name = smashed; smashed = NULL;
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:
|
||||
LIBISO_FREE_MEM(smashed);
|
||||
if (md5_context != NULL)
|
||||
iso_md5_end(&md5_context, md5);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read a file name from a directory record, doing the needed charset
|
||||
* conversion
|
||||
*/
|
||||
static
|
||||
char *get_name(_ImageFsData *fsdata, const char *str, size_t len)
|
||||
char *get_name(_ImageFsData *fsdata, char *str, size_t len)
|
||||
{
|
||||
int ret;
|
||||
char *name = NULL, *from_ucs = NULL;
|
||||
|
||||
if (strcmp(fsdata->local_charset, fsdata->input_charset)) {
|
||||
/* charset conversion needed */
|
||||
ret = strnconv(str, fsdata->input_charset, fsdata->local_charset, len,
|
||||
@ -1278,13 +1330,14 @@ char *get_name(_ImageFsData *fsdata, const char *str, size_t len)
|
||||
return NULL; /* aborted */
|
||||
}
|
||||
/* fallback */
|
||||
|
||||
/* >>> create a hopefully unique name */;
|
||||
|
||||
ret = make_hopefully_unique_name(fsdata, str, len, &name);
|
||||
if (ret == ISO_SUCCESS)
|
||||
return name;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* we reach here when the charset conversion is not needed or has failed */
|
||||
/* we reach here when the charset conversion is not needed */
|
||||
|
||||
name = malloc(len + 1);
|
||||
if (name == NULL) {
|
||||
@ -3029,7 +3082,8 @@ int src_aa_to_node(IsoFileSource *src, IsoNode *node, int flag)
|
||||
|
||||
static
|
||||
int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoFileSource *src, IsoNode **node)
|
||||
IsoFileSource *src, char *in_name,
|
||||
IsoNode **node)
|
||||
{
|
||||
int ret, idx, to_copy;
|
||||
struct stat info;
|
||||
@ -3055,7 +3109,14 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
fsdata = data->fs->data;
|
||||
|
||||
if (in_name == NULL) {
|
||||
name = iso_file_source_get_name(src);
|
||||
} else {
|
||||
name = strdup(in_name);
|
||||
if (name == NULL) {
|
||||
ret = ISO_OUT_OF_MEM; goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
/* get info about source */
|
||||
ret = iso_file_source_lstat(src, &info);
|
||||
@ -3518,6 +3579,22 @@ ex:;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void issue_collision_warning_summary(size_t failures)
|
||||
{
|
||||
if (failures > ISO_IMPORT_COLL_WARN_MAX) {
|
||||
iso_msg_submit(-1, ISO_IMPORT_COLLISION, 0,
|
||||
"More file name collisions had to be resolved");
|
||||
}
|
||||
if (failures > 0) {
|
||||
iso_msg_submit(-1, ISO_IMPORT_COLLISION, 0,
|
||||
"Sum of resolved file name collisions: %.f",
|
||||
(double) failures);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
struct iso_read_opts *opts,
|
||||
IsoReadImageFeatures **features)
|
||||
@ -3667,6 +3744,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
goto import_revert;
|
||||
}
|
||||
issue_ucs2_warning_summary(data->joliet_ucs2_failures);
|
||||
issue_collision_warning_summary(image->collision_warnings);
|
||||
|
||||
/* Take over inode management from IsoImageFilesystem.
|
||||
data->inode_counter is supposed to hold the maximum PX inode number.
|
||||
@ -3700,7 +3778,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
goto import_revert;
|
||||
}
|
||||
ret = image_builder_create_node(image->builder, image, boot_src,
|
||||
&node);
|
||||
NULL, &node);
|
||||
if (ret < 0) {
|
||||
iso_node_builder_unref(image->builder);
|
||||
goto import_revert;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2013 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -97,6 +97,7 @@ int iso_image_new(const char *name, IsoImage **image)
|
||||
img->generator_is_running = 0;
|
||||
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
|
||||
img->hfsplus_blessed[i] = NULL;
|
||||
img->collision_warnings = 0;
|
||||
|
||||
*image = img;
|
||||
return ISO_SUCCESS;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2012 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -22,6 +22,9 @@
|
||||
*/
|
||||
#define ISO_USED_INODE_RANGE (1 << 18)
|
||||
|
||||
/* How many warnings to issue about name collisions during iso_image_import()
|
||||
*/
|
||||
#define ISO_IMPORT_COLL_WARN_MAX 10
|
||||
|
||||
/*
|
||||
* Image is a context for image manipulation.
|
||||
@ -196,6 +199,9 @@ struct Iso_Image
|
||||
*/
|
||||
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
|
||||
|
||||
/* Counts the name collisions while iso_image_import() */
|
||||
size_t collision_warnings;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
|
||||
* Copyright (c) 2009-2013 Thomas Schmitt
|
||||
* Copyright (c) 2009-2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -328,7 +328,7 @@ enum eltorito_boot_media_type {
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace mode used when addding a node to a file.
|
||||
* Replace mode used when addding a node to a directory.
|
||||
* This controls how libisofs will act when you tried to add to a dir a file
|
||||
* with the same name that an existing file.
|
||||
*
|
||||
@ -7605,6 +7605,9 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len,
|
||||
/** Filename not suitable for character set UCS-2 (WARNING, HIGH, -397) */
|
||||
#define ISO_NAME_NOT_UCS2 0xD030FE73
|
||||
|
||||
/** File name collision during ISO image import (WARNING, HIGH, -398) */
|
||||
#define ISO_IMPORT_COLLISION 0xD030FE72
|
||||
|
||||
|
||||
/* Internal developer note:
|
||||
Place new error codes directly above this comment.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -505,6 +505,8 @@ const char *iso_error_to_msg(int errcode)
|
||||
return "Unrecognized file type in ISO image";
|
||||
case ISO_NAME_NOT_UCS2:
|
||||
return "Filename not suitable for character set UCS-2";
|
||||
case ISO_IMPORT_COLLISION:
|
||||
return "File name collision during ISO image import";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
156
libisofs/tree.c
156
libisofs/tree.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2011 Thomas Schmitt
|
||||
* Copyright (c) 2011 - 2014 Thomas Schmitt
|
||||
*
|
||||
* 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
|
||||
@ -23,6 +23,7 @@
|
||||
#include "builder.h"
|
||||
#include "messages.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -521,7 +522,7 @@ int iso_tree_add_node_builder(IsoImage *image, IsoDir *parent,
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
}
|
||||
|
||||
result = builder->create_node(builder, image, src, &new);
|
||||
result = builder->create_node(builder, image, src, name, &new);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
@ -587,7 +588,8 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
||||
return result;
|
||||
}
|
||||
|
||||
result = image->builder->create_node(image->builder, image, file, &new);
|
||||
result = image->builder->create_node(image->builder, image, file,
|
||||
(char *) name, &new);
|
||||
|
||||
/* free the file */
|
||||
iso_file_source_unref(file);
|
||||
@ -596,12 +598,6 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
||||
return result;
|
||||
}
|
||||
|
||||
result = iso_node_set_name(new, name);
|
||||
if (result < 0) {
|
||||
iso_node_unref(new);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
*node = new;
|
||||
}
|
||||
@ -742,6 +738,97 @@ int check_special(IsoImage *image, mode_t mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void ascii_increment(char *name, int pos)
|
||||
{
|
||||
int c, len;
|
||||
|
||||
len = strlen(name);
|
||||
if (pos < 0 || pos >= len)
|
||||
pos = len - 1;
|
||||
c = name[pos];
|
||||
if (c >= '0' && c < '9') {
|
||||
c++;
|
||||
} else if (c == '9') {
|
||||
c = 'A';
|
||||
} else if (c >= 'A' && c < 'Z') {
|
||||
c++;
|
||||
} else if (c == 'Z') {
|
||||
c = '_';
|
||||
} else if (c == '_') {
|
||||
c = 'a';
|
||||
} else if (c >= 'a' && c < 'z') {
|
||||
c++;
|
||||
} else if (c == 'z') {
|
||||
c = '0';
|
||||
name[pos] = c;
|
||||
ascii_increment(name, pos - 1);
|
||||
return;
|
||||
} else {
|
||||
if (pos == len - 1 || name[pos + 1] == '.')
|
||||
c = '_'; /* Make first change less riddling */
|
||||
else
|
||||
c = '0'; /* But else use the full range of valid characters */
|
||||
}
|
||||
name[pos] = c;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int make_really_unique_name(IsoDir *parent, char **name, char **unique_name,
|
||||
IsoNode ***pos, int flag)
|
||||
{
|
||||
int len, ret, pre_check = 0, ascii_idx = -1, first;
|
||||
char *dpt;
|
||||
|
||||
len = strlen(*name);
|
||||
if (len < 8) {
|
||||
/* Insert underscores before last dot */
|
||||
LIBISO_ALLOC_MEM(*unique_name, char, 8 + 1);
|
||||
first = len;
|
||||
dpt = strrchr(*name, '.');
|
||||
if (dpt != NULL)
|
||||
first = (dpt - *name);
|
||||
if (first > 0)
|
||||
memcpy(*unique_name, *name, first);
|
||||
memset(*unique_name + first, '_', 8 - len);
|
||||
if (len > 0)
|
||||
memcpy(*unique_name + (8 - (len - first)), *name + first,
|
||||
len - first);
|
||||
len = 8;
|
||||
pre_check = 1; /* It might now already be unique */
|
||||
} else {
|
||||
LIBISO_ALLOC_MEM(*unique_name, char, len + 1);
|
||||
memcpy(*unique_name, *name, len);
|
||||
}
|
||||
(*unique_name)[len] = 0;
|
||||
|
||||
dpt = strrchr(*unique_name, '.');
|
||||
if (dpt != NULL)
|
||||
ascii_idx = (dpt - *unique_name) - 1; /* Begin before last dot */
|
||||
while (1) {
|
||||
if (!pre_check)
|
||||
ascii_increment(*unique_name, ascii_idx);
|
||||
else
|
||||
pre_check = 0;
|
||||
ret = iso_dir_exists(parent, *unique_name, pos);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
*name = *unique_name;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ret < 0) {
|
||||
LIBISO_FREE_MEM(*unique_name);
|
||||
*unique_name = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively add a given directory to the image tree.
|
||||
*
|
||||
@ -750,12 +837,12 @@ int check_special(IsoImage *image, mode_t mode)
|
||||
*/
|
||||
int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
||||
{
|
||||
int ret;
|
||||
int ret, dir_is_open = 0;
|
||||
IsoNodeBuilder *builder;
|
||||
IsoFileSource *file;
|
||||
IsoNode **pos;
|
||||
struct stat info;
|
||||
char *name, *path;
|
||||
char *name, *path, *allocated_name = NULL;
|
||||
IsoNode *new;
|
||||
enum iso_replace_mode replace;
|
||||
|
||||
@ -771,8 +858,9 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
||||
ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret,
|
||||
"Can't open dir. NULL pointer caught as dir name");
|
||||
}
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
dir_is_open = 1;
|
||||
|
||||
builder = image->builder;
|
||||
|
||||
@ -785,15 +873,16 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
||||
if (ret < 0) {
|
||||
/* error reading dir */
|
||||
ret = iso_msg_submit(image->id, ret, ret, "Error reading dir");
|
||||
goto ex;
|
||||
}
|
||||
break;
|
||||
break; /* End of directory */
|
||||
}
|
||||
|
||||
path = iso_file_source_get_path(file);
|
||||
if (path == NULL) {
|
||||
ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret,
|
||||
"NULL pointer caught as file path");
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
name = strrchr(path, '/') + 1;
|
||||
|
||||
@ -827,17 +916,23 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
||||
|
||||
/* find place where to insert */
|
||||
ret = iso_dir_exists(parent, name, &pos);
|
||||
/* TODO
|
||||
* if (ret && replace == ISO_REPLACE_ASK) {
|
||||
* replace = /....
|
||||
* }
|
||||
if (ret) {
|
||||
/* Resolve name collision
|
||||
e.g. caused by fs_image.c:make_hopefully_unique_name()
|
||||
*/
|
||||
|
||||
/* chek if we must insert or not */
|
||||
/* TODO check for other replace behavior */
|
||||
if (ret && (replace == ISO_REPLACE_NEVER)) {
|
||||
/* skip file */
|
||||
goto dir_rec_continue;
|
||||
LIBISO_FREE_MEM(allocated_name); allocated_name = NULL;
|
||||
ret = make_really_unique_name(parent, &name, &allocated_name, &pos,
|
||||
0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
image->collision_warnings++;
|
||||
if (image->collision_warnings < ISO_IMPORT_COLL_WARN_MAX) {
|
||||
ret = iso_msg_submit(image->id, ISO_IMPORT_COLLISION, 0,
|
||||
"File name collision resolved with %s . Now: %s",
|
||||
path, name);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we are here we must insert. Give user a chance for cancel */
|
||||
@ -848,7 +943,7 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
||||
goto dir_rec_continue;
|
||||
}
|
||||
}
|
||||
ret = builder->create_node(builder, image, file, &new);
|
||||
ret = builder->create_node(builder, image, file, name, &new);
|
||||
if (ret < 0) {
|
||||
ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret,
|
||||
"Error when adding file %s", path);
|
||||
@ -884,14 +979,17 @@ dir_rec_continue:;
|
||||
/* check for error severity to decide what to do */
|
||||
if (ret < 0) {
|
||||
ret = iso_msg_submit(image->id, ret, 0, NULL);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
} /* while */
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (dir_is_open)
|
||||
iso_file_source_close(dir);
|
||||
return ret < 0 ? ret : ISO_SUCCESS;
|
||||
LIBISO_FREE_MEM(allocated_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir)
|
||||
|
Loading…
Reference in New Issue
Block a user