Compare commits
1 Commits
ZeroTwoEig
...
ZeroTwoFou
Author | SHA1 | Date | |
---|---|---|---|
4108ddd995 |
@ -1,4 +1,2 @@
|
||||
Joe Neeman
|
||||
Philippe Rouquier
|
||||
Suriyan Laohaprapanon
|
||||
Vreixo Formoso Lopes
|
||||
|
23
Makefile.am
23
Makefile.am
@ -29,11 +29,7 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/exclude.c \
|
||||
libisofs/exclude.h \
|
||||
libisofs/hash.h \
|
||||
libisofs/hash.c \
|
||||
libisofs/file.h \
|
||||
libisofs/file.c \
|
||||
libisofs/eltorito.h \
|
||||
libisofs/eltorito.c
|
||||
libisofs/hash.c
|
||||
|
||||
libinclude_HEADERS = \
|
||||
libisofs/libisofs.h
|
||||
@ -48,23 +44,6 @@ test_iso_CPPFLAGS = -Ilibisofs
|
||||
test_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_iso_SOURCES = test/iso.c
|
||||
|
||||
## Build unit test
|
||||
|
||||
check_PROGRAMS = \
|
||||
test/test
|
||||
|
||||
test_test_CPPFLAGS = -Ilibisofs
|
||||
test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS) -lcunit
|
||||
test_test_LDFLAGS = -L.. -lm
|
||||
|
||||
test_test_SOURCES = \
|
||||
test/test_exclude.c \
|
||||
test/test_tree.c \
|
||||
test/test_ecma119_tree.c \
|
||||
test/test_file_hashtable.c \
|
||||
test/test_util.c \
|
||||
test/test_volume.c \
|
||||
test/test.c
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
|
53
README
53
README
@ -6,7 +6,7 @@ This all is under GPL.
|
||||
------------------------------------------------------------------------------
|
||||
libburnia.pykix.org
|
||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
|
||||
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||
|
||||
Still containing parts of
|
||||
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
||||
@ -19,7 +19,7 @@ commitment as written at the end of this text.
|
||||
The rights and merits of the Libburn-copyright holders Derek Foreman and
|
||||
Ben Jansens will be duely respected.
|
||||
|
||||
This libburnia.pykix.org toplevel README (C) 2006-2007 Thomas Schmitt
|
||||
This libburnia.pykix.org toplevel README (C) 2006 Thomas Schmitt
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Build and Installation
|
||||
@ -54,8 +54,7 @@ See README file there.
|
||||
Overview of libburnia.pykix.org
|
||||
|
||||
libburnia.pykix.org is an open-source software project for reading, mastering
|
||||
and writing optical discs.
|
||||
For now this means only CD media and all single layer DVD media except DVD+R.
|
||||
and writing optical discs. For now this means only CD-R and CD-RW.
|
||||
|
||||
The project comprises of several more or less interdependent parts which
|
||||
together strive to be a usable foundation for application development.
|
||||
@ -67,10 +66,10 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
|
||||
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
|
||||
volunteers for testing of realistic use cases.
|
||||
|
||||
We have a workable code base for burning CD and most single layer DVD.
|
||||
The burn API is quite comprehensively documented and can be used to build a
|
||||
presentable application.
|
||||
We have a functional binary which emulates parts of cdrecord in order to
|
||||
We do have a workable code base for burning data CDs, though. The burn API is
|
||||
quite comprehensively documented and can be used to build a presentable
|
||||
application.
|
||||
We do have a functional binary which emulates parts of cdrecord in order to
|
||||
prove that usability, and in order to allow you to explore libburnia's scope
|
||||
by help of existing cdrecord frontends.
|
||||
|
||||
@ -79,25 +78,20 @@ The project components (list subject to growth, hopefully):
|
||||
- libburn is the library by which preformatted data get onto optical media.
|
||||
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||
/dev/hdX (e.g. on kernel 2.6).
|
||||
libburn is the foundation of our cdrecord emulation. Its code is
|
||||
independent of cdrecord. Its DVD capabilities are learned from
|
||||
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
|
||||
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
|
||||
libburn is the foundation of our cdrecord emulation.
|
||||
|
||||
- libisofs is the library to pack up hard disk files and directories into a
|
||||
ISO 9660 disk image. This may then be brought to media via libburn.
|
||||
ISO 9660 disk image. This may then be brought to CD via libburn.
|
||||
libisofs is to be the foundation of our upcoming mkisofs emulation.
|
||||
|
||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||
Cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||
Schilling's cdrtools. cdrskin strives to be a second source for
|
||||
the services traditionally provided by cdrecord. Additionally it
|
||||
provides libburn's DVD capabilities, where only -sao is compatible
|
||||
with cdrecord.
|
||||
the services traditionally provided by cdrecord.
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||
Many bytes have been copied from the message output of cdrecord
|
||||
runs, though.
|
||||
See cdrskin/README and man cdrskin/cdrskin.1 for more.
|
||||
See cdrskin/README for more.
|
||||
|
||||
- test is a collection of application gestures and examples given by the
|
||||
authors of the library features. The main API example for libburn
|
||||
@ -127,7 +121,7 @@ Project history as far as known to me:
|
||||
It has meanwhile moved to use vanilla libburn.pykix.org , though.
|
||||
Version 0.1.4 constitutes the first release of this kind.
|
||||
|
||||
- In July 2006 our team mate Mario Danic announced a revival of libburn
|
||||
- In Juli 2006 our team mate Mario Danic announced a revival of libburn
|
||||
which by about nearly everybody else was perceived as unfriendly fork.
|
||||
Derek Foreman four days later posted a message which expressed his
|
||||
discontent.
|
||||
@ -184,32 +178,13 @@ Project history as far as known to me:
|
||||
libburn, is now called libburnia. For the origin of this name, see
|
||||
http://en.wikipedia.org/wiki/Liburnians .
|
||||
|
||||
- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope
|
||||
is widened to a first class of DVD media: overwriteable single layer types
|
||||
DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired
|
||||
by dvd+rw-tools' "poor man" writing facility for this class of media.
|
||||
Taking a bow towards Andy Polyakov.
|
||||
|
||||
- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with
|
||||
multi-session and with DAO.
|
||||
|
||||
- 12th March 2007 version 0.3.4 supports DVD+R and thus covers all single layer
|
||||
DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
|
||||
yet.
|
||||
|
||||
- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel
|
||||
people that one should not use /dev/sg on kernel 2.6.
|
||||
|
||||
- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival.
|
||||
We look back on improved stability, a substantially extended list of media
|
||||
and write modes, and better protection against typical user mishaps.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation. To be exact: version 2 of that License.
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
29
TODO
29
TODO
@ -1,29 +0,0 @@
|
||||
FEATURES
|
||||
========
|
||||
|
||||
El-Torito
|
||||
Support for multiple images
|
||||
HFS/HFS+
|
||||
CD reading
|
||||
Multisession
|
||||
UDF
|
||||
ISO relaxed contraints
|
||||
ISO 9660:1998
|
||||
|
||||
Support for special files (only dirs, reg. files and symlinks are supported).
|
||||
|
||||
TESTS
|
||||
=====
|
||||
|
||||
For all
|
||||
|
||||
IMPLEMENTATION
|
||||
==============
|
||||
|
||||
a way to return NULL sources meaning a failure!!
|
||||
Error message queue
|
||||
Public API for all things already implemented
|
||||
Better charset support
|
||||
default input charset to locale one, no always UTF-8
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT([libisofs], [0.2.8], [http://libburnia-project.org])
|
||||
AC_INIT([libisofs], [0.2.4], [http://libburnia.pykix.org])
|
||||
AC_PREREQ([2.50])
|
||||
dnl AC_CONFIG_HEADER([config.h])
|
||||
|
||||
@ -25,7 +25,7 @@ dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
||||
dnl
|
||||
BURN_MAJOR_VERSION=0
|
||||
BURN_MINOR_VERSION=2
|
||||
BURN_MICRO_VERSION=8
|
||||
BURN_MICRO_VERSION=4
|
||||
BURN_INTERFACE_AGE=0
|
||||
BURN_BINARY_AGE=0
|
||||
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||
@ -39,7 +39,7 @@ AC_SUBST(BURN_VERSION)
|
||||
|
||||
dnl Libtool versioning
|
||||
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION
|
||||
LT_CURRENT=5
|
||||
LT_CURRENT=`expr $BURN_MICRO_VERSION - $BURN_INTERFACE_AGE`
|
||||
LT_REVISION=$BURN_INTERFACE_AGE
|
||||
LT_AGE=`expr $BURN_BINARY_AGE - $BURN_INTERFACE_AGE`
|
||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||
|
@ -16,10 +16,8 @@
|
||||
#include "volume.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
#include "libisofs.h"
|
||||
#include "libburn/libburn.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
/* burn-source compatible stuff */
|
||||
static int
|
||||
@ -79,7 +77,6 @@ static const write_fn writers[] =
|
||||
NULL,
|
||||
wr_system_area,
|
||||
wr_pri_vol_desc,
|
||||
el_torito_wr_boot_vol_desc,
|
||||
joliet_wr_sup_vol_desc,
|
||||
wr_vol_desc_term,
|
||||
wr_l_path_table,
|
||||
@ -88,7 +85,6 @@ static const write_fn writers[] =
|
||||
joliet_wr_m_path_table,
|
||||
wr_dir_records,
|
||||
joliet_wr_dir_records,
|
||||
el_torito_wr_catalog,
|
||||
wr_files
|
||||
};
|
||||
|
||||
@ -105,35 +101,30 @@ add_susp_fields_rec(struct ecma119_write_target *t,
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!node->iso_self)
|
||||
return;
|
||||
|
||||
rrip_add_PX(t, node);
|
||||
rrip_add_NM(t, node);
|
||||
rrip_add_TF(t, node);
|
||||
|
||||
switch (node->type) {
|
||||
case ECMA119_FILE:
|
||||
break;
|
||||
case ECMA119_SYMLINK:
|
||||
rrip_add_SL(t, node);
|
||||
break;
|
||||
case ECMA119_DIR:
|
||||
if (node->info.dir.real_parent != node->parent) {
|
||||
rrip_add_RE(t, node);
|
||||
rrip_add_PL(t, node);
|
||||
}
|
||||
for (i = 0; i < node->info.dir.nchildren; i++) {
|
||||
add_susp_fields_rec(t, node->info.dir.children[i]);
|
||||
}
|
||||
break;
|
||||
case ECMA119_PLACEHOLDER:
|
||||
rrip_add_CL(t, node);
|
||||
break;
|
||||
default:
|
||||
// FIXME support for device blocks by uncommenting this
|
||||
//if (node->iso_self->attrib.st_rdev)
|
||||
// rrip_add_PN(t, node);
|
||||
break;
|
||||
if (node->iso_self->attrib.st_rdev)
|
||||
rrip_add_PN(t, node);
|
||||
if (S_ISLNK(node->iso_self->attrib.st_mode))
|
||||
rrip_add_SL(t, node);
|
||||
if (node->type == ECMA119_FILE && node->file.real_me)
|
||||
rrip_add_CL(t, node);
|
||||
if (node->type == ECMA119_DIR
|
||||
&& node->dir.real_parent != node->parent) {
|
||||
rrip_add_RE(t, node);
|
||||
rrip_add_PL(t, node);
|
||||
}
|
||||
susp_add_CE(t, node);
|
||||
|
||||
if (node->type == ECMA119_DIR) {
|
||||
for (i = 0; i < node->dir.nchildren; i++) {
|
||||
add_susp_fields_rec(t, node->dir.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -155,40 +146,33 @@ calc_dir_size(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *dir)
|
||||
{
|
||||
size_t i;
|
||||
size_t newlen;
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
t->dirlist_len++;
|
||||
dir->info.dir.len = 34 + dir->info.dir.self_susp.non_CE_len
|
||||
+ 34 + dir->info.dir.parent_susp.non_CE_len;
|
||||
dir->info.dir.CE_len = dir->info.dir.self_susp.CE_len
|
||||
+ dir->info.dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->info.dir.nchildren; ++i) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
dir->dir.len = 34 + dir->dir.self_susp.non_CE_len
|
||||
+ 34 + dir->dir.parent_susp.non_CE_len;
|
||||
dir->dir.CE_len = dir->dir.self_susp.CE_len
|
||||
+ dir->dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
|
||||
newlen = dir->info.dir.len + ch->dirent_len + ch->susp.non_CE_len;
|
||||
if ((newlen % 2048) < (dir->info.dir.len % 2048)) {
|
||||
dir->info.dir.len = newlen + (2048 - (dir->info.dir.len % 2048));
|
||||
} else {
|
||||
dir->info.dir.len += ch->dirent_len + ch->susp.non_CE_len;
|
||||
}
|
||||
dir->info.dir.CE_len += ch->susp.CE_len;
|
||||
dir->dir.len += ch->dirent_len + ch->susp.non_CE_len;
|
||||
dir->dir.CE_len += ch->susp.CE_len;
|
||||
}
|
||||
t->total_dir_size += round_up(dir->info.dir.len + dir->info.dir.CE_len,
|
||||
t->total_dir_size += round_up(dir->dir.len + dir->dir.CE_len,
|
||||
t->block_size);
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
//struct iso_tree_node *iso = ch->iso_self;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
struct iso_tree_node *iso = ch->iso_self;
|
||||
if (ch->type == ECMA119_DIR) {
|
||||
calc_dir_size(t, ch);
|
||||
}
|
||||
// else if (iso && iso->attrib.st_size
|
||||
// && iso->loc.type == LIBISO_FILESYS
|
||||
// && iso->loc.path) {
|
||||
// t->filelist_len++;
|
||||
// }
|
||||
} else if (iso && iso->attrib.st_size
|
||||
&& iso->loc.type == LIBISO_FILESYS
|
||||
&& iso->loc.path) {
|
||||
t->filelist_len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,27 +188,26 @@ calc_dir_pos(struct ecma119_write_target *t,
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
dir->info.dir.block = t->curblock;
|
||||
t->curblock += div_up(dir->info.dir.len + dir->info.dir.CE_len, t->block_size);
|
||||
/* we don't need to set iso_self->block since each tree writes
|
||||
* its own directories */
|
||||
dir->block = t->curblock;
|
||||
t->curblock += div_up(dir->dir.len + dir->dir.CE_len, t->block_size);
|
||||
t->dirlist[t->curfile++] = dir;
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
if (ch->type == ECMA119_DIR)
|
||||
calc_dir_pos(t, ch);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cmp_file(const void *f1, const void *f2)
|
||||
{
|
||||
struct iso_file *f = *((struct iso_file**)f1);
|
||||
struct iso_file *g = *((struct iso_file**)f2);
|
||||
/* higher weighted first */
|
||||
return g->sort_weight - f->sort_weight;
|
||||
/* reset curfile when we're finished */
|
||||
if (!dir->parent) {
|
||||
t->curfile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill out the block field for each file and fill out t->filelist.
|
||||
* Fill out the block field for each ecma119_tree_node that is a file and fill
|
||||
* out t->filelist.
|
||||
*/
|
||||
static void
|
||||
calc_file_pos(struct ecma119_write_target *t,
|
||||
@ -233,112 +216,69 @@ calc_file_pos(struct ecma119_write_target *t,
|
||||
size_t i;
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
t->filelist = calloc(1, sizeof(struct iso_file *) * t->file_table->count);
|
||||
|
||||
for (i = 0; i < FILE_HASH_NODES; ++i) {
|
||||
|
||||
struct iso_file_hash_node *node;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
if (ch->type == ECMA119_FILE && ch->iso_self) {
|
||||
struct iso_tree_node *iso = ch->iso_self;
|
||||
off_t size = iso->attrib.st_size;
|
||||
|
||||
node = t->file_table->table[i];
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
do {
|
||||
struct iso_file *file = node->file;
|
||||
if (file->size)
|
||||
t->filelist[t->curfile++] = file;
|
||||
node = node->next;
|
||||
} while (node);
|
||||
iso->block = ch->block = t->curblock;
|
||||
t->curblock += div_up(size, t->block_size);
|
||||
if (size && iso->loc.type == LIBISO_FILESYS
|
||||
&& iso->loc.path)
|
||||
t->filelist[t->curfile++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
t->filelist_len = t->curfile;
|
||||
|
||||
/* sort */
|
||||
if ( t->sort_files )
|
||||
qsort(t->filelist, t->filelist_len, sizeof(void*), cmp_file);
|
||||
|
||||
/* fill block value */
|
||||
for ( i = 0; i < t->filelist_len; ++i) {
|
||||
struct iso_file *file = t->filelist[i];
|
||||
file->block = t->curblock;
|
||||
t->curblock += div_up(file->size, t->block_size);
|
||||
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
if (ch->type == ECMA119_DIR)
|
||||
calc_file_pos(t, ch);
|
||||
}
|
||||
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
t->curfile = 0;
|
||||
if (!dir->parent) {
|
||||
t->curfile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ecma119_write_target from the given volume number of the
|
||||
* given volume set.
|
||||
*
|
||||
* \pre \p volnum is less than \p volset-\>volset_size.
|
||||
* \post For each node in the tree, writer_data has been allocated.
|
||||
* \post The directory heirarchy has been reorganised to be ecma119-compatible.
|
||||
*/
|
||||
static struct ecma119_write_target*
|
||||
struct ecma119_write_target*
|
||||
ecma119_target_new(struct iso_volset *volset,
|
||||
const struct ecma119_source_opts *opts)
|
||||
int volnum,
|
||||
int level,
|
||||
int flags)
|
||||
{
|
||||
struct ecma119_write_target *t =
|
||||
calloc(1, sizeof(struct ecma119_write_target));
|
||||
size_t i, j, cur;
|
||||
struct iso_tree_node *iso_root =
|
||||
(struct iso_tree_node*) volset->volume[opts->volnum]->root;
|
||||
struct iso_tree_node *iso_root = volset->volume[volnum]->root;
|
||||
|
||||
t->cache_inodes = opts->no_cache_inodes ? 0 : 1;
|
||||
t->replace_mode = opts->default_mode ? 0 : 1;
|
||||
if ( opts->replace_dir_mode )
|
||||
t->replace_mode |= 0x02;
|
||||
if ( opts->replace_file_mode )
|
||||
t->replace_mode |= 0x04;
|
||||
if ( opts->replace_gid )
|
||||
t->replace_mode |= 0x08;
|
||||
if ( opts->replace_uid )
|
||||
t->replace_mode |= 0x10;
|
||||
t->dir_mode = opts->dir_mode;
|
||||
t->file_mode = opts->file_mode;
|
||||
t->gid = opts->gid;
|
||||
t->uid = opts->uid;
|
||||
|
||||
//TODO get defailt values for current locale, no UTF-8
|
||||
t->input_charset = opts->input_charset ? opts->input_charset : "UTF-8";
|
||||
t->ouput_charset = opts->ouput_charset ? opts->ouput_charset : "UTF-8";
|
||||
t->sort_files = opts->sort_files;
|
||||
|
||||
t->file_table = iso_file_table_new(t->cache_inodes);
|
||||
volset->refcount++;
|
||||
t->iso_level = opts->level;
|
||||
t->block_size = 2048;
|
||||
t->relaxed_constraints = opts->relaxed_constraints;
|
||||
|
||||
t->rockridge = (opts->flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->joliet = (opts->flags & ECMA119_JOLIET) ? 1 : 0;
|
||||
|
||||
t->catalog = volset->volume[opts->volnum]->bootcat;
|
||||
t->eltorito = t->catalog ? 1 : 0;
|
||||
|
||||
t->root = ecma119_tree_create(t, iso_root);
|
||||
t->joliet = (flags & ECMA119_JOLIET) ? 1 : 0;
|
||||
if (t->joliet)
|
||||
t->joliet_root = joliet_tree_create(t, iso_root);
|
||||
t->volset = volset;
|
||||
t->volnum = opts->volnum;
|
||||
t->volnum = volnum;
|
||||
t->now = time(NULL);
|
||||
|
||||
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->iso_level = level;
|
||||
t->block_size = 2048;
|
||||
|
||||
if (t->rockridge)
|
||||
add_susp_fields(t);
|
||||
|
||||
calc_dir_size(t, t->root);
|
||||
if (t->joliet) {
|
||||
joliet_calc_dir_size(t, t->joliet_root);
|
||||
t->pathlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len_joliet);
|
||||
t->dirlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len_joliet);
|
||||
t->pathlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->dirlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
}
|
||||
|
||||
t->dirlist = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->pathlist = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->filelist = calloc(1, sizeof(void*) * t->filelist_len);
|
||||
|
||||
/* fill out the pathlist */
|
||||
t->pathlist[0] = t->root;
|
||||
@ -346,10 +286,10 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
cur = 1;
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
struct ecma119_tree_node *dir = t->pathlist[i];
|
||||
for (j = 0; j < dir->info.dir.nchildren; j++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[j];
|
||||
for (j = 0; j < dir->dir.nchildren; j++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[j];
|
||||
if (ch->type == ECMA119_DIR) {
|
||||
size_t len = 8 + strlen(ch->iso_name);
|
||||
size_t len = 8 + strlen(ch->name);
|
||||
t->pathlist[cur++] = ch;
|
||||
t->path_table_size += len + len % 2;
|
||||
}
|
||||
@ -360,8 +300,6 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
+ 1 /* volume desc */
|
||||
+ 1; /* volume desc terminator */
|
||||
|
||||
if (t->eltorito)
|
||||
t->curblock += 1; /* boot record volume descriptor */
|
||||
if (t->joliet) /* supplementary vol desc */
|
||||
t->curblock += div_up (2048, t->block_size);
|
||||
|
||||
@ -378,30 +316,11 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
}
|
||||
|
||||
calc_dir_pos(t, t->root);
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
t->curfile = 0;
|
||||
if (t->joliet) {
|
||||
|
||||
if (t->joliet)
|
||||
joliet_calc_dir_pos(t, t->joliet_root);
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
/* el-torito? */
|
||||
if (t->eltorito) {
|
||||
|
||||
/* add catalog block */
|
||||
t->catalog->file->block = t->curblock;
|
||||
t->curblock += div_up(2048, t->block_size);
|
||||
el_torito_get_image_files(t);
|
||||
}
|
||||
|
||||
calc_file_pos(t, t->root);
|
||||
|
||||
if (t->eltorito)
|
||||
el_torito_patch_image_files(t);
|
||||
if (t->joliet)
|
||||
joliet_update_file_pos (t, t->joliet_root);
|
||||
|
||||
if (t->rockridge) {
|
||||
susp_finalize(t, t->root);
|
||||
@ -427,19 +346,11 @@ is_joliet_state(enum ecma119_write_state state)
|
||||
|| state == ECMA119_WRITE_DIR_RECORDS_JOLIET;
|
||||
}
|
||||
|
||||
static int
|
||||
is_eltorito_state(enum ecma119_write_state state)
|
||||
{
|
||||
return state == ECMA119_WRITE_ELTORITO_BOOT_VOL_DESC
|
||||
|| state == ECMA119_WRITE_ELTORITO_CATALOG;
|
||||
}
|
||||
|
||||
static void
|
||||
next_state(struct ecma119_write_target *t)
|
||||
{
|
||||
t->state++;
|
||||
while ( (!t->joliet && is_joliet_state(t->state))
|
||||
||(!t->eltorito && is_eltorito_state(t->state)) )
|
||||
while (!t->joliet && is_joliet_state(t->state))
|
||||
t->state++;
|
||||
|
||||
printf ("now in state %d, curblock=%d\n", (int)t->state, (int)t->curblock);
|
||||
@ -488,13 +399,11 @@ wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct state_files *f_st = &t->state_files;
|
||||
size_t nread;
|
||||
struct iso_file *f = t->filelist[f_st->file];
|
||||
const char *path = f->path;
|
||||
|
||||
struct ecma119_tree_node *f = t->filelist[f_st->file];
|
||||
const char *path = f->iso_self->loc.path;
|
||||
|
||||
if (!f_st->fd) {
|
||||
printf("Writing file %s\n", path);
|
||||
f_st->data_len = f->size;
|
||||
f_st->data_len = f->iso_self->attrib.st_size;
|
||||
f_st->fd = fopen(path, "r");
|
||||
if (!f_st->fd)
|
||||
err(1, "couldn't open %s for reading", path);
|
||||
@ -522,25 +431,15 @@ write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct ecma119_pri_vol_desc *vol = (struct ecma119_pri_vol_desc*)buf;
|
||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||
char *vol_id = str2d_char(volume->volume_id, t->input_charset);
|
||||
char *pub_id = str2a_char(volume->publisher_id, t->input_charset);
|
||||
char *data_id = str2a_char(volume->data_preparer_id, t->input_charset);
|
||||
char *volset_id = str2d_char(t->volset->volset_id, t->input_charset);
|
||||
|
||||
char *system_id = str2a_char(volume->system_id, t->input_charset);
|
||||
char *application_id = str2a_char(volume->application_id, t->input_charset);
|
||||
char *copyright_file_id = str2d_char(volume->copyright_file_id, t->input_charset);
|
||||
char *abstract_file_id = str2d_char(volume->abstract_file_id, t->input_charset);
|
||||
char *biblio_file_id = str2d_char(volume->biblio_file_id, t->input_charset);
|
||||
|
||||
char *vol_id = str2ascii(volume->volume_id);
|
||||
char *pub_id = str2ascii(volume->publisher_id);
|
||||
char *data_id = str2ascii(volume->data_preparer_id);
|
||||
char *volset_id = str2ascii(t->volset->volset_id);
|
||||
|
||||
vol->vol_desc_type[0] = 1;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
if (system_id)
|
||||
strncpy((char*)vol->system_id, system_id, 32);
|
||||
else
|
||||
/* put linux by default? */
|
||||
memcpy(vol->system_id, "LINUX", 5);
|
||||
memcpy(vol->system_id, "SYSID", 5);
|
||||
if (vol_id)
|
||||
strncpy((char*)vol->volume_id, vol_id, 32);
|
||||
iso_bb(vol->vol_space_size, t->vol_space_size, 4);
|
||||
@ -553,19 +452,10 @@ write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
|
||||
write_one_dir_record(t, t->root, 3, vol->root_dir_record);
|
||||
|
||||
/* mmm, why not check for null? */
|
||||
strncpy((char*)vol->vol_set_id, volset_id, 128);
|
||||
strncpy((char*)vol->publisher_id, pub_id, 128);
|
||||
strncpy((char*)vol->data_prep_id, data_id, 128);
|
||||
|
||||
if (application_id)
|
||||
strncpy((char*)vol->application_id, application_id, 128);
|
||||
if (copyright_file_id)
|
||||
strncpy((char*)vol->copyright_file_id, copyright_file_id, 37);
|
||||
if (abstract_file_id)
|
||||
strncpy((char*)vol->abstract_file_id, abstract_file_id, 37);
|
||||
if (biblio_file_id)
|
||||
strncpy((char*)vol->bibliographic_file_id, biblio_file_id, 37);
|
||||
strncpy((char*)vol->application_id, "APPID", 128);
|
||||
|
||||
iso_datetime_17(vol->vol_creation_time, t->now);
|
||||
iso_datetime_17(vol->vol_modification_time, t->now);
|
||||
@ -576,11 +466,6 @@ write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
free(volset_id);
|
||||
free(pub_id);
|
||||
free(data_id);
|
||||
free(system_id);
|
||||
free(application_id);
|
||||
free(copyright_file_id);
|
||||
free(abstract_file_id);
|
||||
free(biblio_file_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -606,18 +491,17 @@ write_path_table(struct ecma119_write_target *t, int l_type, uint8_t *buf)
|
||||
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
dir = t->pathlist[i];
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
while ((i) && t->pathlist[parent] != dir->parent)
|
||||
parent++;
|
||||
assert(parent < i || i == 0);
|
||||
|
||||
rec = (struct ecma119_path_table_record*) buf;
|
||||
rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->iso_name) : 1;
|
||||
rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->name) : 1;
|
||||
rec->len_xa[0] = 0;
|
||||
write_int(rec->block, dir->info.dir.block, 4);
|
||||
write_int(rec->block, dir->block, 4);
|
||||
write_int(rec->parent, parent + 1, 2);
|
||||
if (dir->parent)
|
||||
memcpy(rec->dir_id, dir->iso_name, rec->len_di[0]);
|
||||
memcpy(rec->dir_id, dir->name, rec->len_di[0]);
|
||||
buf += 8 + rec->len_di[0] + (rec->len_di[0] % 2);
|
||||
}
|
||||
}
|
||||
@ -643,36 +527,22 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
int file_id,
|
||||
uint8_t *buf)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t block;
|
||||
uint8_t len_dr = (file_id >= 0) ? 34 : node->dirent_len;
|
||||
uint8_t len_fi = (file_id >= 0) ? 1 : strlen(node->iso_name);
|
||||
uint8_t len_fi = (file_id >= 0) ? 1 : strlen(node->name);
|
||||
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->iso_name;
|
||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
||||
uint32_t len = (node->type == ECMA119_DIR) ? node->dir.len
|
||||
: node->file.real_me ? 0 : node->iso_self->attrib.st_size;
|
||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
||||
|
||||
if (node->type == ECMA119_DIR) {
|
||||
len = node->info.dir.len;
|
||||
block = node->info.dir.block;
|
||||
} else if (node->type == ECMA119_FILE) {
|
||||
len = node->info.file->size;
|
||||
block = node->info.file->block;
|
||||
} else {
|
||||
/* for nodes other than files and dirs, we set both len and block to 0 */
|
||||
len = 0;
|
||||
block = 0;
|
||||
}
|
||||
|
||||
|
||||
/* we don't write out susp fields for the root node */
|
||||
if (t->rockridge) {
|
||||
if (file_id == 0) {
|
||||
assert(node->type == ECMA119_DIR);
|
||||
susp_write(t, &node->info.dir.self_susp, &buf[len_dr]);
|
||||
len_dr += node->info.dir.self_susp.non_CE_len;
|
||||
susp_write(t, &node->dir.self_susp, &buf[len_dr]);
|
||||
len_dr += node->dir.self_susp.non_CE_len;
|
||||
} else if (file_id == 1) {
|
||||
assert(node->type == ECMA119_DIR);
|
||||
susp_write(t, &node->info.dir.parent_susp, &buf[len_dr]);
|
||||
len_dr += node->info.dir.parent_susp.non_CE_len;
|
||||
susp_write(t, &node->dir.parent_susp, &buf[len_dr]);
|
||||
len_dr += node->dir.parent_susp.non_CE_len;
|
||||
} else if (file_id < 0) {
|
||||
susp_write(t, &node->susp, &buf[len_dr]);
|
||||
len_dr += node->susp.non_CE_len;
|
||||
@ -682,7 +552,7 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
node = node->parent;
|
||||
|
||||
rec->len_dr[0] = len_dr;
|
||||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->block, node->block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
iso_datetime_7(rec->recording_time, t->now);
|
||||
rec->flags[0] = (node->type == ECMA119_DIR) ? 2 : 0;
|
||||
@ -697,10 +567,7 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
uint8_t *buf)
|
||||
{
|
||||
size_t i;
|
||||
int j;
|
||||
size_t len;
|
||||
uint8_t *orig_buf = buf;
|
||||
uint8_t *prior_buf = buf;
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
/* write the "." and ".." entries first */
|
||||
@ -710,34 +577,23 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
write_one_dir_record(t, dir, 1, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
write_one_dir_record(t, dir->info.dir.children[i], -1, buf);
|
||||
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
if ((buf + len - prior_buf) >= 2048) {
|
||||
for (j = len - 1; j >= 0; j--) {
|
||||
prior_buf[2048 + j] = buf[j];
|
||||
buf[j] = 0;
|
||||
}
|
||||
prior_buf += 2048;
|
||||
buf = prior_buf + len;
|
||||
}
|
||||
else {
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
}
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
write_one_dir_record(t, dir->dir.children[i], -1, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
}
|
||||
|
||||
/* write the susp continuation areas */
|
||||
if (t->rockridge) {
|
||||
susp_write_CE(t, &dir->info.dir.self_susp, buf);
|
||||
buf += dir->info.dir.self_susp.CE_len;
|
||||
susp_write_CE(t, &dir->info.dir.parent_susp, buf);
|
||||
buf += dir->info.dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
susp_write_CE(t, &dir->info.dir.children[i]->susp, buf);
|
||||
buf += dir->info.dir.children[i]->susp.CE_len;
|
||||
susp_write_CE(t, &dir->dir.self_susp, buf);
|
||||
buf += dir->dir.self_susp.CE_len;
|
||||
susp_write_CE(t, &dir->dir.parent_susp, buf);
|
||||
buf += dir->dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
susp_write_CE(t, &dir->dir.children[i]->susp, buf);
|
||||
buf += dir->dir.children[i]->susp.CE_len;
|
||||
}
|
||||
}
|
||||
assert (buf - orig_buf == dir->info.dir.len + dir->info.dir.CE_len);
|
||||
assert (buf - orig_buf == dir->dir.len + dir->dir.CE_len);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -748,7 +604,7 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
dir = t->dirlist[i];
|
||||
write_one_dir(t, dir, buf);
|
||||
buf += round_up(dir->info.dir.len + dir->info.dir.CE_len, t->block_size);
|
||||
buf += round_up(dir->dir.len + dir->dir.CE_len, t->block_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -813,28 +669,26 @@ bs_free_data(struct burn_source *bs)
|
||||
{
|
||||
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
|
||||
ecma119_tree_free(t->root);
|
||||
iso_file_table_clear(t->file_table);
|
||||
|
||||
free(t->dirlist);
|
||||
free(t->pathlist);
|
||||
free(t->dirlist_joliet);
|
||||
free(t->pathlist_joliet);
|
||||
free(t->filelist);
|
||||
free(t->state_data);
|
||||
if (t->joliet)
|
||||
joliet_tree_free(t->joliet_root);
|
||||
if (t->state_files.fd)
|
||||
fclose(t->state_files.fd);
|
||||
}
|
||||
|
||||
struct burn_source *iso_source_new_ecma119(struct iso_volset *volset,
|
||||
struct ecma119_source_opts *opts)
|
||||
int volnum,
|
||||
int level,
|
||||
int flags)
|
||||
{
|
||||
struct burn_source *ret = calloc(1, sizeof(struct burn_source));
|
||||
ret->refcount = 1;
|
||||
ret->read = bs_read;
|
||||
ret->get_size = bs_get_size;
|
||||
ret->free_data = bs_free_data;
|
||||
ret->data = ecma119_target_new(volset, opts);
|
||||
ret->data = ecma119_target_new(volset, volnum, level, flags);
|
||||
return ret;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ enum ecma119_write_state
|
||||
|
||||
ECMA119_WRITE_SYSTEM_AREA,
|
||||
ECMA119_WRITE_PRI_VOL_DESC,
|
||||
ECMA119_WRITE_ELTORITO_BOOT_VOL_DESC,
|
||||
ECMA119_WRITE_SUP_VOL_DESC_JOLIET,
|
||||
ECMA119_WRITE_VOL_DESC_TERMINATOR,
|
||||
ECMA119_WRITE_L_PATH_TABLE,
|
||||
@ -38,7 +37,6 @@ enum ecma119_write_state
|
||||
ECMA119_WRITE_M_PATH_TABLE_JOLIET,
|
||||
ECMA119_WRITE_DIR_RECORDS,
|
||||
ECMA119_WRITE_DIR_RECORDS_JOLIET,
|
||||
ECMA119_WRITE_ELTORITO_CATALOG,
|
||||
ECMA119_WRITE_FILES,
|
||||
|
||||
ECMA119_WRITE_DONE
|
||||
@ -63,40 +61,6 @@ struct ecma119_write_target
|
||||
unsigned int rockridge:1;
|
||||
unsigned int joliet:1;
|
||||
unsigned int iso_level:2;
|
||||
unsigned int eltorito:1;
|
||||
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
int replace_mode; /**< Replace ownership and modes of files
|
||||
*
|
||||
* 0. filesystem values
|
||||
* 1. useful values
|
||||
* bits 1-4 bitmask:
|
||||
* 2 - replace dir
|
||||
* 3 - replace file
|
||||
* 4 - replace gid
|
||||
* 5 - replace uid
|
||||
*/
|
||||
mode_t dir_mode;
|
||||
mode_t file_mode;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
|
||||
char *input_charset;
|
||||
char *ouput_charset;
|
||||
|
||||
int cache_inodes;
|
||||
|
||||
int sort_files; /**< if sort files or not. Sorting is based of
|
||||
* the weight of each file */
|
||||
|
||||
/**
|
||||
* In the CD, each file must have an unique inode number. So each
|
||||
* time we add a new file, this is incremented.
|
||||
*/
|
||||
ino_t ino;
|
||||
|
||||
int curblock;
|
||||
uint16_t block_size;
|
||||
@ -122,13 +86,10 @@ struct ecma119_write_target
|
||||
size_t dirlist_len; /**< The length of the previous 2 lists.
|
||||
*/
|
||||
|
||||
|
||||
struct iso_file_table *file_table;
|
||||
/**<
|
||||
* A hash table with info about all files
|
||||
struct ecma119_tree_node **filelist;
|
||||
/**< A pre-order list of files with
|
||||
* non-NULL paths and non-zero sizes.
|
||||
*/
|
||||
|
||||
struct iso_file **filelist; /**< A pre-order list of files.*/
|
||||
size_t filelist_len; /* Length of the previous list. */
|
||||
|
||||
int curfile; /**< Used as a helper field for writing
|
||||
@ -140,8 +101,6 @@ struct ecma119_write_target
|
||||
*/
|
||||
struct joliet_tree_node **dirlist_joliet;
|
||||
struct joliet_tree_node **pathlist_joliet;
|
||||
|
||||
size_t dirlist_len_joliet;
|
||||
|
||||
enum ecma119_write_state state; /* The current state of the writer. */
|
||||
|
||||
@ -170,6 +129,19 @@ struct ecma119_write_target
|
||||
} state_files;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new ecma119_write_target from the given volume number of the
|
||||
* given volume set.
|
||||
*
|
||||
* \pre \p volnum is less than \p volset-\>volset_size.
|
||||
* \post For each node in the tree, writer_data has been allocated.
|
||||
* \post The directory heirarchy has been reorganised to be ecma119-compatible.
|
||||
*/
|
||||
struct ecma119_write_target *ecma119_target_new(struct iso_volset *volset,
|
||||
int volnum,
|
||||
int level,
|
||||
int flags);
|
||||
|
||||
#define BP(a,b) [(b) - (a) + 1]
|
||||
|
||||
struct ecma119_pri_vol_desc
|
||||
@ -246,17 +218,6 @@ struct ecma119_sup_vol_desc
|
||||
uint8_t reserved2 BP(1396, 2048);
|
||||
};
|
||||
|
||||
struct ecma119_boot_rec_vol_desc
|
||||
{
|
||||
uint8_t vol_desc_type BP(1, 1);
|
||||
uint8_t std_identifier BP(2, 6);
|
||||
uint8_t vol_desc_version BP(7, 7);
|
||||
uint8_t boot_sys_id BP(8, 39);
|
||||
uint8_t boot_id BP(40, 71);
|
||||
uint8_t boot_catalog BP(72, 75);
|
||||
uint8_t unused BP(76, 2048);
|
||||
};
|
||||
|
||||
struct ecma119_vol_desc_terminator
|
||||
{
|
||||
uint8_t vol_desc_type BP(1, 1);
|
||||
|
@ -9,343 +9,74 @@
|
||||
#include "ecma119_tree.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
static size_t calc_dirent_len(struct ecma119_tree_node *n)
|
||||
{
|
||||
int ret = n->iso_name ? strlen(n->iso_name) + 33 : 34;
|
||||
int ret = n->name ? strlen(n->name) + 33 : 34;
|
||||
if (ret % 2) ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the file permissions and user/group id of an ECMA-119 node.
|
||||
* This is used when a replace mode is selected, i.e., when we want to
|
||||
* create a disc where the mode of each file or directory will be
|
||||
* different than the mode in the original source.
|
||||
*/
|
||||
static void
|
||||
replace_node_mode(struct ecma119_write_target *t, struct stat *st)
|
||||
{
|
||||
if ( S_ISDIR(st->st_mode) ) {
|
||||
if ( t->replace_mode & 0x02 ) {
|
||||
/* replace dir mode with specific */
|
||||
st->st_mode &= S_IFMT;
|
||||
st->st_mode |= t->dir_mode;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
/* replace dir mode with default */
|
||||
/* read perm */
|
||||
mode_t new_mode = (st->st_mode & S_IFMT) | 0444;
|
||||
/* search bit if any */
|
||||
if ( st->st_mode & 0111)
|
||||
new_mode |= 0111;
|
||||
st->st_mode = new_mode;
|
||||
}
|
||||
} else {
|
||||
if ( t->replace_mode & 0x04 ) {
|
||||
/* replace file mode with specific */
|
||||
st->st_mode &= S_IFMT;
|
||||
st->st_mode |= t->file_mode;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
/* replace file mode with default */
|
||||
/* read perm */
|
||||
mode_t new_mode = (st->st_mode & S_IFMT) | 0444;
|
||||
/* execute bit if any */
|
||||
if ( st->st_mode & 0111)
|
||||
new_mode |= 0111;
|
||||
st->st_mode = new_mode;
|
||||
}
|
||||
|
||||
}
|
||||
if ( t->replace_mode & 0x08 ) {
|
||||
/* replace gid mode with specific */
|
||||
st->st_gid = t->gid;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
st->st_gid = 0;
|
||||
}
|
||||
if ( t->replace_mode & 0x10 ) {
|
||||
/* replace gid mode with specific */
|
||||
st->st_uid = t->uid;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
st->st_uid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ECMA-119 node from the given iso tree node, and initializes
|
||||
* the fields that are common to all kind of nodes (dir, reg file, symlink...).
|
||||
*
|
||||
* @param t
|
||||
* The options for the ECMA-119 tree that is being created
|
||||
* @param parent
|
||||
* The parent of the node, or NULL if it's the root.
|
||||
* @param iso
|
||||
* The node from which this function creates a ECMA-119 node
|
||||
* @return
|
||||
* The created node.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_ecma119_node(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
char *(*iso_name)(const char *, const char *) = ISO_ISDIR(iso) ?
|
||||
((t->iso_level == 1) ? iso_1_dirid : iso_2_dirid)
|
||||
: ((t->iso_level == 1) ? iso_1_fileid : iso_2_fileid);
|
||||
char *(*iso_r_name)(const char *, const char *, int) =
|
||||
ISO_ISDIR(iso) ? iso_r_dirid : iso_r_fileid;
|
||||
|
||||
assert(t && (!parent || parent->type == ECMA119_DIR) && iso );
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
|
||||
/*
|
||||
* If selected one ISO relaxed constraints other than NO_DIR_REALOCATION,
|
||||
* we use the function that computes the relaxed name, otherwise normal
|
||||
* function for specified level is used.
|
||||
*/
|
||||
ret->iso_name = iso->name ?
|
||||
( t->relaxed_constraints & ~ECMA119_NO_DIR_REALOCATION ?
|
||||
iso_r_name(iso->name, t->input_charset, t->relaxed_constraints) :
|
||||
iso_name(iso->name, t->input_charset)
|
||||
) : NULL;
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
|
||||
/* iso node keeps the same file attribs as the original file. */
|
||||
ret->attrib = iso->attrib;
|
||||
|
||||
/*
|
||||
* When using RR extension and replace mode, we will replace the
|
||||
* permissions and uid/gid of each file with those previously selected
|
||||
* by the user.
|
||||
*/
|
||||
if ( t->rockridge && t->replace_mode )
|
||||
replace_node_mode(t, &ret->attrib);
|
||||
|
||||
if (!iso->name)
|
||||
ret->full_name = NULL;
|
||||
else if ( strcmp(t->input_charset,t->ouput_charset) )
|
||||
/* convert the file name charset */
|
||||
ret->full_name = convert_str(iso->name, t->input_charset,
|
||||
t->ouput_charset);
|
||||
else
|
||||
ret->full_name = strdup(iso->name);
|
||||
ret->target = t;
|
||||
ret->parent = parent;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a directory from a iso directory
|
||||
* node.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_dir(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_dir *iso)
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
|
||||
assert(t && (!parent || parent->type == ECMA119_DIR)
|
||||
&& iso && S_ISDIR(iso->node.attrib.st_mode));
|
||||
&& iso && S_ISDIR(iso->attrib.st_mode));
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_dirid(iso->name)
|
||||
: iso_2_dirid(iso->name))
|
||||
: NULL;
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
ret->iso_self = iso;
|
||||
ret->target = t;
|
||||
ret->type = ECMA119_DIR;
|
||||
ret->info.dir.real_parent = parent;
|
||||
ret->info.dir.depth = parent ? parent->info.dir.depth + 1 : 1;
|
||||
ret->info.dir.nchildren = 0;
|
||||
ret->info.dir.children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||
ret->parent = ret->dir.real_parent = parent;
|
||||
ret->dir.depth = parent ? parent->dir.depth + 1 : 1;
|
||||
ret->dir.nchildren = iso->nchildren;
|
||||
ret->dir.children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a regular file from a iso file
|
||||
* node.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_file(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_file *iso)
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
struct iso_file *file;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->type = ECMA119_FILE;
|
||||
|
||||
/* get iso_file struct */
|
||||
file = iso_file_table_lookup(t->file_table, iso);
|
||||
if ( file == NULL ) {
|
||||
/*
|
||||
* If the file is not already added to the disc, we add it now
|
||||
* to the file table, and get a new inode number for it.
|
||||
*/
|
||||
file = iso_file_new(iso);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
file->ino = ++t->ino;
|
||||
} else {
|
||||
/* increment number of hard-links */
|
||||
file->nlink++;
|
||||
}
|
||||
|
||||
ret->attrib.st_nlink = file->nlink;
|
||||
ret->attrib.st_ino = file->ino;
|
||||
ret->info.file = file;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a placeholder for a relocated
|
||||
* dir.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.5 for details
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_placeholder(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct ecma119_tree_node *real)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
|
||||
assert(t && real && real->type == ECMA119_DIR
|
||||
&& parent && parent->type == ECMA119_DIR);
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
ret->iso_name = real->iso_name; /* TODO strdup? */
|
||||
/* FIXME
|
||||
* if we strdup above, if name changes in mangle_all,
|
||||
* this probably keeps as original.
|
||||
* if not, both change, but we need to update dirent_len.
|
||||
* I think that attributes of a placeholder must be taken from
|
||||
* real_me, not keept here.
|
||||
* FIXME
|
||||
* Another question is that real is a dir, while placeholder is
|
||||
* a file, and ISO name restricctions are different, what to do?
|
||||
*/
|
||||
ret->dirent_len = real->dirent_len;
|
||||
ret->attrib = real->attrib;
|
||||
ret->full_name = strdup(real->full_name);
|
||||
ret->target = t;
|
||||
ret->parent = parent;
|
||||
ret->type = ECMA119_PLACEHOLDER;
|
||||
ret->info.real_me = real;
|
||||
ret->attrib.st_nlink = 1;
|
||||
ret->attrib.st_ino = ++t->ino;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a symbolic link from a iso symlink
|
||||
* node.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_symlink(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_symlink *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->iso_name = iso->node.name ? ((t->iso_level == 1) ?
|
||||
iso_1_fileid(iso->node.name, t->input_charset)
|
||||
: iso_2_fileid(iso->node.name, t->input_charset))
|
||||
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_fileid(iso->name)
|
||||
: iso_2_fileid(iso->name))
|
||||
: NULL;
|
||||
ret->type = ECMA119_SYMLINK;
|
||||
ret->info.dest = iso->dest; /* TODO strdup? */
|
||||
ret->attrib.st_nlink = 1;
|
||||
ret->attrib.st_ino = ++t->ino;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a boot catalog. This is like a
|
||||
* regular file, but its contents are taken from a El-Torito boot catalog,
|
||||
* and not from a file in the local filesystem.
|
||||
*
|
||||
* See "El Torito" Bootable CD-ROM Format Specification Version 1.0 for
|
||||
* more details.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_boot_catalog(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_boot_catalog *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
struct iso_file *file;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
/*
|
||||
* This will simply create a ECMA119 file, with the only difference
|
||||
* that the iso_file is not taken from table, but from boot catalog
|
||||
*/
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
ret->parent = parent;
|
||||
ret->iso_self = iso;
|
||||
ret->target = t;
|
||||
ret->type = ECMA119_FILE;
|
||||
|
||||
file = iso->catalog->file;
|
||||
file->ino = ++t->ino;
|
||||
|
||||
ret->attrib.st_nlink = file->nlink;
|
||||
ret->attrib.st_ino = file->ino;
|
||||
ret->info.file = file;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node that corresponds to the given iso tree node.
|
||||
* If that node is a dir, this function recurses over all their children,
|
||||
* thus creating a ECMA-119 tree whose root is the given iso dir.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_tree(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret = NULL;
|
||||
struct ecma119_tree_node *ret;
|
||||
size_t i;
|
||||
|
||||
assert(t && iso);
|
||||
|
||||
if ( iso->hide_flags & LIBISO_HIDE_ON_RR )
|
||||
return NULL;
|
||||
|
||||
switch ( iso->type ) {
|
||||
case LIBISO_NODE_FILE:
|
||||
ret = create_file(t, parent, (struct iso_tree_node_file*)iso);
|
||||
break;
|
||||
case LIBISO_NODE_SYMLINK:
|
||||
if ( !t->rockridge )
|
||||
printf("Can't add symlinks to a non ISO tree. Skipping %s \n",
|
||||
iso->name);
|
||||
else
|
||||
ret = create_symlink(t, parent, (struct iso_tree_node_symlink*)iso);
|
||||
break;
|
||||
case LIBISO_NODE_DIR:
|
||||
{
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir = (struct iso_tree_node_dir*)iso;
|
||||
ret = create_dir(t, parent, dir);
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
struct ecma119_tree_node *child;
|
||||
child = create_tree(t, ret, dir->children[i]);
|
||||
if (child)
|
||||
ret->info.dir.children[ret->info.dir.nchildren++] = child;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LIBISO_NODE_BOOTCATALOG:
|
||||
ret = create_boot_catalog(t, parent,
|
||||
(struct iso_tree_node_boot_catalog*)iso);
|
||||
break;
|
||||
default:
|
||||
/* should never happen */
|
||||
assert( 0 );
|
||||
break;
|
||||
|
||||
ret = (S_ISDIR(iso->attrib.st_mode) ? create_dir : create_file)
|
||||
(t, parent, iso);
|
||||
for (i = 0; i < iso->nchildren; i++) {
|
||||
ret->dir.children[i] = create_tree(t, ret, iso->children[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -356,13 +87,12 @@ ecma119_tree_free(struct ecma119_tree_node *root)
|
||||
size_t i;
|
||||
|
||||
if (root->type == ECMA119_DIR) {
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
ecma119_tree_free(root->info.dir.children[i]);
|
||||
for (i=0; i < root->dir.nchildren; i++) {
|
||||
ecma119_tree_free(root->dir.children[i]);
|
||||
}
|
||||
free(root->info.dir.children);
|
||||
free(root->dir.children);
|
||||
}
|
||||
free(root->iso_name);
|
||||
free(root->full_name);
|
||||
free(root->name);
|
||||
free(root);
|
||||
}
|
||||
|
||||
@ -372,19 +102,13 @@ max_child_name_len(struct ecma119_tree_node *root)
|
||||
size_t ret = 0, i;
|
||||
|
||||
assert(root->type == ECMA119_DIR);
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
size_t len = strlen(root->info.dir.children[i]->iso_name);
|
||||
for (i=0; i < root->dir.nchildren; i++) {
|
||||
size_t len = strlen(root->dir.children[i]->name);
|
||||
ret = MAX(ret, len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocates a directory, as specified in Rock Ridge Specification
|
||||
* (see IEEE P1282, section 4.1.5). This is needed when the number of levels
|
||||
* on a directory hierarchy exceeds 8, or the length of a path is higher
|
||||
* than 255 characters, as specified in ECMA-119, section 6.8.2.1
|
||||
*/
|
||||
static void
|
||||
reparent(struct ecma119_tree_node *child,
|
||||
struct ecma119_tree_node *parent)
|
||||
@ -396,11 +120,13 @@ reparent(struct ecma119_tree_node *child,
|
||||
assert(child && parent && parent->type == ECMA119_DIR && child->parent);
|
||||
|
||||
/* replace the child in the original parent with a placeholder */
|
||||
for (i=0; i < child->parent->info.dir.nchildren; i++) {
|
||||
if (child->parent->info.dir.children[i] == child) {
|
||||
placeholder = create_placeholder(child->target,
|
||||
child->parent, child);
|
||||
child->parent->info.dir.children[i] = placeholder;
|
||||
for (i=0; i < child->parent->dir.nchildren; i++) {
|
||||
if (child->parent->dir.children[i] == child) {
|
||||
placeholder = create_file(child->target,
|
||||
child->parent,
|
||||
child->iso_self);
|
||||
placeholder->file.real_me = child;
|
||||
child->parent->dir.children[i] = placeholder;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@ -409,83 +135,52 @@ reparent(struct ecma119_tree_node *child,
|
||||
|
||||
/* add the child to its new parent */
|
||||
child->parent = parent;
|
||||
parent->info.dir.nchildren++;
|
||||
parent->info.dir.children = realloc( parent->info.dir.children,
|
||||
sizeof(void*) * parent->info.dir.nchildren );
|
||||
parent->info.dir.children[parent->info.dir.nchildren-1] = child;
|
||||
parent->dir.nchildren++;
|
||||
parent->dir.children = realloc( parent->dir.children,
|
||||
sizeof(void*) * parent->dir.nchildren );
|
||||
parent->dir.children[parent->dir.nchildren-1] = child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder the tree, if necessary, to ensure that
|
||||
* - the depth is at most 8
|
||||
* - each path length is at most 255 characters
|
||||
* This restriction is imposed by ECMA-119 specification (see ECMA-119,
|
||||
* 6.8.2.1).
|
||||
*/
|
||||
static void
|
||||
reorder_tree(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *root,
|
||||
reorder_tree(struct ecma119_tree_node *root,
|
||||
struct ecma119_tree_node *cur)
|
||||
{
|
||||
size_t max_path;
|
||||
|
||||
assert(root && cur && cur->type == ECMA119_DIR);
|
||||
|
||||
cur->info.dir.depth = cur->parent ? cur->parent->info.dir.depth + 1 : 1;
|
||||
cur->info.dir.path_len = cur->parent ? cur->parent->info.dir.path_len
|
||||
+ strlen(cur->iso_name) : 0;
|
||||
max_path = cur->info.dir.path_len + cur->info.dir.depth
|
||||
+ max_child_name_len(cur);
|
||||
cur->dir.depth = cur->parent ? cur->parent->dir.depth + 1 : 1;
|
||||
cur->dir.path_len = cur->parent ? cur->parent->dir.path_len
|
||||
+ strlen(cur->name) : 0;
|
||||
max_path = cur->dir.path_len + cur->dir.depth + max_child_name_len(cur);
|
||||
|
||||
if (cur->info.dir.depth > 8 || max_path > 255) {
|
||||
|
||||
if (t->rockridge) {
|
||||
reparent(cur, root);
|
||||
/* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again) */
|
||||
} else {
|
||||
/* we need to delete cur */
|
||||
size_t i,j;
|
||||
struct ecma119_tree_node *parent = cur->parent;
|
||||
|
||||
printf("Can't dirs deeper than 8 without RR. Skipping %s\n",
|
||||
cur->full_name);
|
||||
for (i=0; i < parent->info.dir.nchildren; ++i) {
|
||||
if (parent->info.dir.children[i] == cur) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert ( i < parent->info.dir.nchildren);
|
||||
for ( j = i; j < parent->info.dir.nchildren - 1; ++j)
|
||||
parent->info.dir.children[j] = parent->info.dir.children[j+1];
|
||||
parent->info.dir.nchildren--;
|
||||
ecma119_tree_free(cur);
|
||||
}
|
||||
if (cur->dir.depth > 8 || max_path > 255) {
|
||||
reparent(cur, root);
|
||||
/* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again) */
|
||||
} else {
|
||||
size_t i;
|
||||
|
||||
for (i=0; i < cur->info.dir.nchildren; i++) {
|
||||
if (cur->info.dir.children[i]->type == ECMA119_DIR)
|
||||
reorder_tree(t, root, cur->info.dir.children[i]);
|
||||
for (i=0; i < cur->dir.nchildren; i++) {
|
||||
if (cur->dir.children[i]->type == ECMA119_DIR)
|
||||
reorder_tree(root, cur->dir.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the iso name of two ECMA-119 nodes
|
||||
*/
|
||||
static int
|
||||
cmp_node(const void *f1, const void *f2)
|
||||
{
|
||||
struct ecma119_tree_node *f = *((struct ecma119_tree_node**)f1);
|
||||
struct ecma119_tree_node *g = *((struct ecma119_tree_node**)f2);
|
||||
return strcmp(f->iso_name, g->iso_name);
|
||||
return strcmp(f->name, g->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts a the children of each directory in the ECMA-119 tree represented
|
||||
* by \p root, acording to the order specified in ECMA-119, section 9.3.
|
||||
*/
|
||||
static void
|
||||
sort_tree(struct ecma119_tree_node *root)
|
||||
{
|
||||
@ -493,11 +188,10 @@ sort_tree(struct ecma119_tree_node *root)
|
||||
|
||||
assert(root && root->type == ECMA119_DIR);
|
||||
|
||||
qsort(root->info.dir.children, root->info.dir.nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
if (root->info.dir.children[i]->type == ECMA119_DIR)
|
||||
sort_tree(root->info.dir.children[i]);
|
||||
qsort(root->dir.children, root->dir.nchildren, sizeof(void*), cmp_node);
|
||||
for (i=0; i < root->dir.nchildren; i++) {
|
||||
if (root->dir.children[i]->type == ECMA119_DIR)
|
||||
sort_tree(root->dir.children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -548,15 +242,11 @@ mangle_name(char **name, int num_change, int level, int seq_num)
|
||||
sprintf(*name, fmt, base, seq_num, ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the ISO name of each children of the given dir is unique,
|
||||
* changing some of them if needed.
|
||||
*/
|
||||
static void
|
||||
mangle_all(struct ecma119_tree_node *dir)
|
||||
{
|
||||
size_t i, j, k;
|
||||
struct ecma119_dir_info d = dir->info.dir;
|
||||
struct ecma119_dir_info d = dir->dir;
|
||||
size_t n_change;
|
||||
int changed;
|
||||
|
||||
@ -567,8 +257,8 @@ mangle_all(struct ecma119_tree_node *dir)
|
||||
/* find the number of consecutive equal names */
|
||||
j = 1;
|
||||
while ( i+j < d.nchildren &&
|
||||
!strcmp(d.children[i]->iso_name,
|
||||
d.children[i+j]->iso_name) )
|
||||
!strcmp(d.children[i]->name,
|
||||
d.children[i+j]->name) )
|
||||
j++;
|
||||
if (j == 1) continue;
|
||||
|
||||
@ -576,7 +266,7 @@ mangle_all(struct ecma119_tree_node *dir)
|
||||
changed = 1;
|
||||
n_change = j / 10 + 1;
|
||||
for (k=0; k < j; k++) {
|
||||
mangle_name(&(d.children[i+k]->iso_name),
|
||||
mangle_name(&(d.children[i+k]->name),
|
||||
n_change,
|
||||
dir->target->iso_level,
|
||||
k);
|
||||
@ -600,8 +290,7 @@ ecma119_tree_create(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *iso_root)
|
||||
{
|
||||
t->root = create_tree(t, NULL, iso_root);
|
||||
if ( !(t->relaxed_constraints & ECMA119_NO_DIR_REALOCATION) )
|
||||
reorder_tree(t, t->root, t->root);
|
||||
reorder_tree(t->root, t->root);
|
||||
sort_tree(t->root);
|
||||
mangle_all(t->root);
|
||||
return t->root;
|
||||
@ -616,8 +305,8 @@ ecma119_tree_print(struct ecma119_tree_node *root, int spaces)
|
||||
memset(sp, ' ', spaces);
|
||||
sp[spaces] = '\0';
|
||||
|
||||
printf("%s%s\n", sp, root->iso_name);
|
||||
printf("%s%s\n", sp, root->name);
|
||||
if (root->type == ECMA119_DIR)
|
||||
for (i=0; i < root->info.dir.nchildren; i++)
|
||||
ecma119_tree_print(root->info.dir.children[i], spaces+2);
|
||||
for (i=0; i < root->dir.nchildren; i++)
|
||||
ecma119_tree_print(root->dir.children[i], spaces+2);
|
||||
}
|
||||
|
@ -10,18 +10,11 @@
|
||||
#ifndef LIBISO_ECMA119_TREE_H
|
||||
#define LIBISO_ECMA119_TREE_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "file.h"
|
||||
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
|
||||
enum ecma119_node_type {
|
||||
enum {
|
||||
ECMA119_FILE,
|
||||
ECMA119_SYMLINK,
|
||||
ECMA119_DIR,
|
||||
ECMA119_PLACEHOLDER /**< placeholder for a relocated dir. */
|
||||
ECMA119_DIR
|
||||
};
|
||||
|
||||
struct ecma119_dir_info {
|
||||
@ -32,7 +25,6 @@ struct ecma119_dir_info {
|
||||
* Directory Records (including SU) */
|
||||
size_t CE_len; /**< sum of the lengths of children's
|
||||
* SUSP CE areas */
|
||||
size_t block;
|
||||
|
||||
int depth;
|
||||
size_t path_len; /**< The length of a path up to, and
|
||||
@ -45,34 +37,39 @@ struct ecma119_dir_info {
|
||||
/**< The parent before relocation */
|
||||
};
|
||||
|
||||
struct ecma119_file_info
|
||||
{
|
||||
struct ecma119_tree_node *real_me;
|
||||
/**< If this is non-NULL, the file is
|
||||
* a placeholder for a relocated
|
||||
* directory and this field points to
|
||||
* that relocated directory.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* A node for a tree containing all the information necessary for writing
|
||||
* an ISO9660 volume.
|
||||
*/
|
||||
struct ecma119_tree_node
|
||||
{
|
||||
char *iso_name; /**< in ASCII, conforming to the
|
||||
* current ISO level. */
|
||||
char *full_name; /**< full name, in current locale (TODO put this in UTF-8?) */
|
||||
char *name; /**< in ASCII, conforming to the
|
||||
* current ISO level. */
|
||||
size_t dirent_len; /**< Length of the directory record,
|
||||
* not including SU. */
|
||||
* not including SU. */
|
||||
size_t block;
|
||||
|
||||
struct ecma119_tree_node *parent;
|
||||
struct iso_tree_node *iso_self;
|
||||
struct ecma119_write_target *target;
|
||||
|
||||
struct stat attrib;
|
||||
|
||||
struct susp_info susp;
|
||||
|
||||
enum ecma119_node_type type; /**< file, symlink, directory or placeholder */
|
||||
union {
|
||||
struct iso_file *file;
|
||||
char *dest;
|
||||
int type; /**< file or directory */
|
||||
/* union {*/
|
||||
struct ecma119_dir_info dir;
|
||||
struct ecma119_tree_node *real_me; /**< this field points to
|
||||
* the relocated directory.
|
||||
*/
|
||||
} info;
|
||||
struct ecma119_file_info file;
|
||||
/* };*/
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,454 +0,0 @@
|
||||
#include "libisofs.h"
|
||||
|
||||
#include "eltorito.h"
|
||||
#include "volume.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
struct el_torito_validation_entry {
|
||||
uint8_t header_id BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t reserved BP(3, 4);
|
||||
uint8_t id_string BP(5, 28);
|
||||
uint8_t checksum BP(29, 30);
|
||||
uint8_t key_byte1 BP(31, 31);
|
||||
uint8_t key_byte2 BP(32, 32);
|
||||
};
|
||||
|
||||
struct el_torito_default_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t unused2 BP(13, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_header_entry {
|
||||
uint8_t header_indicator BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t number BP(3, 4);
|
||||
uint8_t character BP(5, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t selec_criteria BP(13, 13);
|
||||
uint8_t vendor_sc BP(14, 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* This table should be written with accuracy values at offset
|
||||
* 8 of boot image, when used ISOLINUX boot loader
|
||||
*/
|
||||
struct boot_info_table {
|
||||
uint8_t bi_pvd BP(1, 4); /* LBA of primary volume descriptor */
|
||||
uint8_t bi_file BP(5, 8); /* LBA of boot file */
|
||||
uint8_t bi_length BP(9, 12); /* Length of boot file */
|
||||
uint8_t bi_csum BP(13, 16); /* Checksum of boot file */
|
||||
uint8_t bi_reserved BP(17, 56); /* Reserved */
|
||||
};
|
||||
|
||||
struct partition_desc {
|
||||
uint8_t boot_ind;
|
||||
uint8_t begin_chs[3];
|
||||
uint8_t type;
|
||||
uint8_t end_chs[3];
|
||||
uint8_t start[4];
|
||||
uint8_t size[4];
|
||||
};
|
||||
|
||||
struct hard_disc_mbr {
|
||||
uint8_t code_area[440];
|
||||
uint8_t opt_disk_sg[4];
|
||||
uint8_t pad[2];
|
||||
struct partition_desc partition[4];
|
||||
uint8_t sign1;
|
||||
uint8_t sign2;
|
||||
};
|
||||
|
||||
static struct el_torito_boot_image *
|
||||
create_image(struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type)
|
||||
{
|
||||
struct el_torito_boot_image *boot;
|
||||
int boot_media_type = 0;
|
||||
int load_sectors = 0; /* number of sector to load */
|
||||
unsigned char partition_type = 0;
|
||||
|
||||
switch (type) {
|
||||
case ELTORITO_FLOPPY_EMUL:
|
||||
switch (image->attrib.st_size) {
|
||||
case 1200 * 1024:
|
||||
boot_media_type = 1; /* 1.2 meg diskette */
|
||||
break;
|
||||
case 1440 * 1024:
|
||||
boot_media_type = 2; /* 1.44 meg diskette */
|
||||
break;
|
||||
case 2880 * 1024:
|
||||
boot_media_type = 3; /* 2.88 meg diskette */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid image size %d Kb. Must be one of 1.2, 1.44"
|
||||
"or 2.88 Mb", (int) image->attrib.st_size / 1024);
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE_SIZE;
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
/* it seems that for floppy emulation we need to load
|
||||
* a single sector (512b) */
|
||||
load_sectors = 1;
|
||||
break;
|
||||
case ELTORITO_HARD_DISC_EMUL:
|
||||
{
|
||||
size_t i;
|
||||
int fd;
|
||||
struct hard_disc_mbr mbr;
|
||||
int used_partition;
|
||||
|
||||
/* read the MBR on disc and get the type of the partition */
|
||||
fd = open(((struct iso_tree_node_file*)image)->path, O_RDONLY);
|
||||
if ( fd == -1 ) {
|
||||
fprintf(stderr, "Can't open image file\n");
|
||||
return NULL;
|
||||
}
|
||||
if ( read(fd, &mbr, sizeof(mbr)) ) {
|
||||
fprintf(stderr, "Can't read MBR from image file\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* check valid MBR signature */
|
||||
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
|
||||
fprintf(stderr, "Invalid MBR. Wrong signature.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ensure single partition */
|
||||
used_partition = -1;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (mbr.partition[i].type != 0) {
|
||||
/* it's an used partition */
|
||||
if (used_partition != -1) {
|
||||
fprintf(stderr, "Invalid MBR. At least 2 paritions: %d and "
|
||||
"%d, are being used\n", used_partition, i);
|
||||
return NULL;
|
||||
} else
|
||||
used_partition = i;
|
||||
}
|
||||
}
|
||||
partition_type = mbr.partition[used_partition].type;
|
||||
}
|
||||
boot_media_type = 4;
|
||||
|
||||
/* only load the MBR */
|
||||
load_sectors = 1;
|
||||
break;
|
||||
case ELTORITO_NO_EMUL:
|
||||
boot_media_type = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
boot = calloc(1, sizeof(struct el_torito_boot_image));
|
||||
boot->bootable = 1;
|
||||
boot->image = (struct iso_tree_node_file *) image;
|
||||
boot->type = boot_media_type;
|
||||
boot->load_size = load_sectors;
|
||||
boot->partition_type = partition_type;
|
||||
return boot;
|
||||
}
|
||||
|
||||
static struct iso_tree_node_boot_catalog*
|
||||
create_boot_catalog_node(struct iso_tree_node_dir *parent,
|
||||
const char *name)
|
||||
{
|
||||
struct iso_tree_node_boot_catalog *boot;
|
||||
|
||||
assert( parent && name );
|
||||
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot_catalog));
|
||||
boot->node.attrib.st_mode = S_IFREG | 0444;
|
||||
boot->node.attrib.st_atime =
|
||||
boot->node.attrib.st_mtime =
|
||||
boot->node.attrib.st_ctime = time(NULL);
|
||||
boot->node.type = LIBISO_NODE_BOOTCATALOG;
|
||||
boot->node.name = strdup(name);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) boot);
|
||||
return boot;
|
||||
}
|
||||
|
||||
struct el_torito_boot_image *
|
||||
iso_volume_create_boot_catalog(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name)
|
||||
{
|
||||
struct el_torito_boot_image *boot_image;
|
||||
struct iso_tree_node_boot_catalog *boot_node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
assert( volume && !volume->bootcat);
|
||||
assert( image && ISO_ISREG(image) && dir && name);
|
||||
|
||||
boot_image = create_image(image, type);
|
||||
if ( !boot_image )
|
||||
return NULL;
|
||||
|
||||
/* creates the catalog with the given default image */
|
||||
catalog = malloc(sizeof(struct el_torito_boot_catalog));
|
||||
catalog->nentries = 1;
|
||||
catalog->entries = malloc(sizeof(struct el_torito_boot_image *));
|
||||
catalog->entries[0] = boot_image;
|
||||
catalog->file = malloc(sizeof(struct iso_file));
|
||||
catalog->file->size = 2048;
|
||||
|
||||
/* add catalog file */
|
||||
boot_node = create_boot_catalog_node(dir, name);
|
||||
boot_node->catalog = catalog;
|
||||
|
||||
volume->bootcat = catalog;
|
||||
|
||||
return boot_image;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_load_seg(struct el_torito_boot_image *bootimg, int segment)
|
||||
{
|
||||
if (bootimg->type != ELTORITO_NO_EMUL)
|
||||
return;
|
||||
bootimg->load_seg = segment;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_load_size(struct el_torito_boot_image *bootimg, int sectors)
|
||||
{
|
||||
if (bootimg->type != ELTORITO_NO_EMUL)
|
||||
return;
|
||||
bootimg->load_size = sectors;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_no_bootable(struct el_torito_boot_image *bootimg)
|
||||
{
|
||||
bootimg->bootable = 0;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg)
|
||||
{
|
||||
bootimg->patch_isolinux = 1;
|
||||
}
|
||||
|
||||
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(cat);
|
||||
|
||||
for(i = 0; i < cat->nentries; ++i) {
|
||||
free(cat->entries[i]);
|
||||
}
|
||||
free(cat->entries);
|
||||
free(cat->file);
|
||||
free(cat);
|
||||
}
|
||||
|
||||
void el_torito_get_image_files(struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
|
||||
for(i = 0; i < cat->nentries; ++i) {
|
||||
|
||||
struct iso_tree_node_file *image = cat->entries[i]->image;
|
||||
struct iso_file *file = iso_file_table_lookup(t->file_table, image);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(image);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
}
|
||||
cat->entries[i]->file = file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor
|
||||
*/
|
||||
static void
|
||||
write_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
struct ecma119_boot_rec_vol_desc *vol =
|
||||
(struct ecma119_boot_rec_vol_desc*)buf;
|
||||
|
||||
assert(cat);
|
||||
|
||||
vol->vol_desc_type[0] = 0;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
memcpy(vol->boot_sys_id, "EL TORITO SPECIFICATION", 23);
|
||||
iso_lsb(vol->boot_catalog, cat->file->block, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
write_validation_entry(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
size_t i;
|
||||
int checksum;
|
||||
|
||||
struct el_torito_validation_entry *ve =
|
||||
(struct el_torito_validation_entry*)buf;
|
||||
ve->header_id[0] = 1;
|
||||
ve->platform_id[0] = 0; /* 0: 80x86, 1: PowerPC, 2: Mac */
|
||||
ve->key_byte1[0] = 0x55;
|
||||
ve->key_byte2[0] = 0xAA;
|
||||
|
||||
/* calculate the checksum, to ensure sum of all words is 0 */
|
||||
checksum = 0;
|
||||
for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) {
|
||||
checksum -= buf[i];
|
||||
checksum -= (buf[i] << 8);
|
||||
}
|
||||
iso_lsb(ve->checksum, checksum, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
patch_boot_file(struct el_torito_boot_image *img)
|
||||
{
|
||||
struct boot_info_table info;
|
||||
int fd;
|
||||
uint32_t checksum;
|
||||
ssize_t len;
|
||||
uint8_t buf[4];
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
/* open image */
|
||||
fd = open(img->image->path, O_RDWR);
|
||||
if ( fd == -1 ) {
|
||||
//TODO what do do? exit or just continue?
|
||||
fprintf(stderr, "Can't patch boot image %s\n", img->image->path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute checksum, as the the sum of all 32 bit words in boot image
|
||||
* from offset 64 */
|
||||
checksum = 0;
|
||||
lseek(fd, (off_t) 64, SEEK_SET);
|
||||
|
||||
//TODO this can (must) be optimizied by reading to a longer buffer
|
||||
while ( (len = read(fd, buf, 4) ) == 4 ) {
|
||||
checksum += iso_read_lsb(buf, 4);
|
||||
}
|
||||
if ( len != 0 ) {
|
||||
/* error reading file, or file length not multiple of 4 */
|
||||
//TODO what do do? exit or just continue?
|
||||
fprintf(stderr, "Can't patch boot image %s\n", img->image->path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill boot info table */
|
||||
iso_lsb(info.bi_pvd, 16, 4); //FIXME this should be changed when we implement ms
|
||||
iso_lsb(info.bi_file, img->file->block, 4);
|
||||
iso_lsb(info.bi_length, img->image->node.attrib.st_size, 4);
|
||||
iso_lsb(info.bi_csum, checksum, 4);
|
||||
|
||||
/* patch file */
|
||||
lseek(fd, (off_t) 8, SEEK_SET);
|
||||
write(fd, &info, sizeof(info));
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_patch_image_files(struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
|
||||
for (i = 0; i < cat->nentries; ++i) {
|
||||
struct el_torito_boot_image *img = cat->entries[i];
|
||||
if ( img->patch_isolinux )
|
||||
patch_boot_file(img);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one section entry.
|
||||
* Currently this is used for both default and other entries since we
|
||||
* put selection criteria no 0 (no sel. criteria)
|
||||
*/
|
||||
static void
|
||||
write_section_entry(uint8_t *buf, struct el_torito_boot_image *img)
|
||||
{
|
||||
struct el_torito_section_entry *se =
|
||||
(struct el_torito_section_entry*)buf;
|
||||
|
||||
se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
|
||||
se->boot_media_type[0] = img->type;
|
||||
iso_lsb(se->load_seg, img->load_seg, 2);
|
||||
se->system_type[0] = 0; //TODO need to get the partition type
|
||||
iso_lsb(se->sec_count, img->load_size, 2);
|
||||
iso_lsb(se->block, img->file->block, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write El-Torito Boot Catalog
|
||||
*/
|
||||
static void
|
||||
write_catalog(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
assert(cat->nentries >= 1 && cat->nentries < 63);
|
||||
|
||||
write_validation_entry(t, buf);
|
||||
|
||||
/* write default entry */
|
||||
write_section_entry(buf + 32, cat->entries[0]);
|
||||
|
||||
//TODO write all images
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
assert(t->catalog);
|
||||
ecma119_start_chunking(t,
|
||||
write_boot_vol_desc,
|
||||
2048,
|
||||
buf);
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_wr_catalog(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
assert(t->catalog);
|
||||
ecma119_start_chunking(t,
|
||||
write_catalog,
|
||||
2048,
|
||||
buf);
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
#ifndef ELTORITO_H_
|
||||
#define ELTORITO_H_
|
||||
|
||||
#include "tree.h"
|
||||
#include "file.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
/**
|
||||
* Location of the boot catalog
|
||||
*/
|
||||
struct iso_tree_node_boot_catalog
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
};
|
||||
|
||||
struct el_torito_boot_catalog {
|
||||
int nentries;
|
||||
struct el_torito_boot_image **entries;
|
||||
struct iso_file *file; /**< The catalog file */
|
||||
};
|
||||
|
||||
struct el_torito_boot_image {
|
||||
unsigned char bootable; /**< If the entry is bootable. */
|
||||
unsigned char patch_isolinux; /**< If the image will be patched */
|
||||
unsigned char type; /**< The type of image */
|
||||
unsigned char partition_type; /**< type of partition for HD-emul images */
|
||||
short load_seg; /**< Load segment for the initial boot image. */
|
||||
short load_size; /**< Number of sector to load. */
|
||||
struct iso_tree_node_file *image;
|
||||
struct iso_file *file;
|
||||
};
|
||||
|
||||
/*struct el_torito_boot_entry *
|
||||
el_torito_add_boot_entry(struct el_torito_boot_catalog *cat,
|
||||
struct iso_tree_node_file *image);
|
||||
*/
|
||||
|
||||
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat);
|
||||
|
||||
/**
|
||||
* For each boot image file, this gets the related iso_file object.
|
||||
* In most cases, the file is already in the hash table. However, if the
|
||||
* boot record is hidden in both ISO/RR and joliet trees, this ensures
|
||||
* that boot images will be written to image.
|
||||
*/
|
||||
void el_torito_get_image_files(struct ecma119_write_target *t);
|
||||
|
||||
/**
|
||||
* Patch image files if selected. This is needed for isolinux boot images
|
||||
*/
|
||||
void el_torito_patch_image_files(struct ecma119_write_target *t);
|
||||
|
||||
void
|
||||
el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
void
|
||||
el_torito_wr_catalog(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
#endif /*ELTORITO_H_*/
|
@ -1,38 +1,42 @@
|
||||
#include "hash.h"
|
||||
#include "exclude.h"
|
||||
|
||||
static struct iso_hash_node *table[HASH_NODES]={0,};
|
||||
static int num=0;
|
||||
|
||||
void
|
||||
iso_exclude_add_path(struct iso_hash_table *table, const char *path)
|
||||
iso_exclude_add_path(const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
table->num += iso_hash_insert(table->table, path);
|
||||
num += iso_hash_insert(table, path);
|
||||
}
|
||||
|
||||
/*void
|
||||
iso_exclude_remove_path(struct iso_hash_table *table, const char *path)
|
||||
void
|
||||
iso_exclude_remove_path(const char *path)
|
||||
{
|
||||
if (!table->num || !path)
|
||||
if (!num || !path)
|
||||
return;
|
||||
|
||||
table->num -= iso_hash_remove(table->table, path);
|
||||
}*/
|
||||
num -= iso_hash_remove(table, path);
|
||||
}
|
||||
|
||||
void
|
||||
iso_exclude_empty(struct iso_hash_table *table)
|
||||
iso_exclude_empty(void)
|
||||
{
|
||||
if (!table->num)
|
||||
if (!num)
|
||||
return;
|
||||
|
||||
iso_hash_empty(table->table);
|
||||
table->num=0;
|
||||
iso_hash_empty(table);
|
||||
num=0;
|
||||
}
|
||||
|
||||
int
|
||||
iso_exclude_lookup(struct iso_hash_table *table, const char *path)
|
||||
iso_exclude_lookup(const char *path)
|
||||
{
|
||||
if (!table->num || !path)
|
||||
if (!num || !path)
|
||||
return 0;
|
||||
|
||||
return iso_hash_lookup(table->table, path);
|
||||
return iso_hash_lookup(table, path);
|
||||
}
|
||||
|
@ -1,37 +1,12 @@
|
||||
#ifndef ISO_EXCLUDE_H
|
||||
#define ISO_EXCLUDE_H
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
struct iso_hash_table {
|
||||
struct iso_hash_node *table[HASH_NODES];
|
||||
int num;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a path to ignore when adding a directory recursively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
int iso_exclude_lookup(struct iso_hash_table *table, const char *path);
|
||||
|
||||
/**
|
||||
* Add the path of a file or directory to ignore when adding a directory recursively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
void iso_exclude_add_path(struct iso_hash_table *table, const char *path);
|
||||
|
||||
/**
|
||||
* Remove a path that was set to be ignored when adding a directory recusively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
//void iso_exclude_remove_path(struct iso_hash_table *table, const char *path);
|
||||
|
||||
/**
|
||||
* Remove all paths that were set to be ignored when adding a directory recusively.
|
||||
*/
|
||||
void iso_exclude_empty(struct iso_hash_table *table);
|
||||
int
|
||||
iso_exclude_lookup(const char *path);
|
||||
|
||||
#endif /* ISO_EXCLUDE */
|
||||
|
188
libisofs/file.c
188
libisofs/file.c
@ -1,188 +0,0 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "tree.h"
|
||||
|
||||
//TODO: refactor both hash and this hash table into a single one!!
|
||||
|
||||
struct iso_file *
|
||||
iso_file_new(struct iso_tree_node_file *f)
|
||||
{
|
||||
struct iso_file *file = calloc(1, sizeof(struct iso_file));
|
||||
file->path = f->path; /*TODO strdup? it needs to be free on clear then */
|
||||
file->size = f->node.attrib.st_size;
|
||||
file->nlink = 1;
|
||||
file->real_dev = f->node.attrib.st_dev;
|
||||
file->real_ino = f->node.attrib.st_ino;
|
||||
file->sort_weight = f->sort_weight;
|
||||
return file;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
iso_file_table_hash(const char *path)
|
||||
{
|
||||
unsigned int hash_num=0;
|
||||
const char *c;
|
||||
|
||||
c=path;
|
||||
while(*c)
|
||||
hash_num = (hash_num << 15) + (hash_num << 3) + (hash_num >> 3) + *c++;
|
||||
|
||||
return hash_num % FILE_HASH_NODES;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
iso_file_table_hash_inode(dev_t dev, ino_t ino)
|
||||
{
|
||||
return (dev ^ ino) % FILE_HASH_NODES;
|
||||
}
|
||||
|
||||
struct iso_file_table*
|
||||
iso_file_table_new(int cache_inodes)
|
||||
{
|
||||
struct iso_file_table *table = calloc(1, sizeof(struct iso_file_table));
|
||||
table->cache_inodes = cache_inodes;
|
||||
return table;
|
||||
}
|
||||
|
||||
static struct iso_file_hash_node *
|
||||
iso_file_table_node_new(struct iso_file *file)
|
||||
{
|
||||
struct iso_file_hash_node *node;
|
||||
node = calloc(1, sizeof(struct iso_file_hash_node) );
|
||||
node->file = file;
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
iso_file_table_node_free(struct iso_file_hash_node *node)
|
||||
{
|
||||
free(node->file);
|
||||
free(node);
|
||||
}
|
||||
|
||||
void
|
||||
iso_file_table_clear(struct iso_file_table *ft)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < FILE_HASH_NODES; i++) {
|
||||
struct iso_file_hash_node *node;
|
||||
|
||||
node=ft->table[i];
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
ft->table[i] = NULL;
|
||||
|
||||
do {
|
||||
struct iso_file_hash_node *next;
|
||||
|
||||
next = node->next;
|
||||
iso_file_table_node_free(node);
|
||||
node = next;
|
||||
} while (node);
|
||||
}
|
||||
ft->count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* return 0 if equal, != 0 if not
|
||||
*/
|
||||
static int
|
||||
iso_table_compare_files(struct iso_file_table *ft,
|
||||
struct iso_file *f1, struct iso_file *f2)
|
||||
{
|
||||
if (ft->cache_inodes) {
|
||||
return (f1->real_dev != f2->real_dev) || (f1->real_ino != f2->real_ino);
|
||||
} else {
|
||||
return strcmp(f1->path, f2->path);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f)
|
||||
{
|
||||
struct iso_file_hash_node *node;
|
||||
unsigned int hash_num;
|
||||
|
||||
/* find the hash number */
|
||||
if (ft->cache_inodes)
|
||||
hash_num = iso_file_table_hash_inode(f->real_dev, f->real_ino);
|
||||
else
|
||||
hash_num = iso_file_table_hash(f->path);
|
||||
|
||||
/* insert it */
|
||||
node = ft->table[hash_num];
|
||||
|
||||
/* unfortunately, we can't safely consider that a file
|
||||
* won't be twice in the hash table so make sure it
|
||||
* doesn't already exists */
|
||||
if (!node) {
|
||||
ft->table[hash_num]=iso_file_table_node_new(f);
|
||||
ft->count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if it's already in, we don't do anything */
|
||||
if (!iso_table_compare_files(ft, f, node->file))
|
||||
return 0;
|
||||
|
||||
while (node->next) {
|
||||
node = node->next;
|
||||
|
||||
/* if it's already in, we don't do anything */
|
||||
if (!iso_table_compare_files(ft, f, node->file))
|
||||
return 0;
|
||||
}
|
||||
|
||||
node->next = iso_file_table_node_new(f);
|
||||
ft->count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct iso_file *
|
||||
iso_file_table_lookup(struct iso_file_table *ft, struct iso_tree_node_file *f)
|
||||
{
|
||||
struct iso_file_hash_node *node;
|
||||
unsigned int hash_num;
|
||||
int equal;
|
||||
|
||||
/* find the hash number */
|
||||
if ( ft->cache_inodes )
|
||||
hash_num = iso_file_table_hash_inode(f->node.attrib.st_dev,
|
||||
f->node.attrib.st_ino);
|
||||
else
|
||||
hash_num = iso_file_table_hash(f->path);
|
||||
|
||||
node = ft->table[hash_num];
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
equal = ft->cache_inodes ?
|
||||
((f->node.attrib.st_dev == node->file->real_dev)
|
||||
&& (f->node.attrib.st_ino == node->file->real_ino))
|
||||
: !strcmp(f->path, node->file->path);
|
||||
if (equal)
|
||||
return node->file;
|
||||
|
||||
while (node->next) {
|
||||
node = node->next;
|
||||
|
||||
equal = ft->cache_inodes ?
|
||||
((f->node.attrib.st_dev == node->file->real_dev)
|
||||
&& (f->node.attrib.st_ino == node->file->real_ino))
|
||||
: !strcmp(f->path, node->file->path);
|
||||
if (equal)
|
||||
return node->file;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
/**
|
||||
* \file file.h
|
||||
*
|
||||
* Declare the structs to keep track of the files to be written into image.
|
||||
* These files are stored in a hash table. Two modes of operation are supported:
|
||||
* when cache inodes is enabled, the files are indexed into the table by the
|
||||
* device and inode id in the local filesystem. This way, two different files
|
||||
* with same inode and device id are treated as if they were a single file.
|
||||
* This is usually the correct behavior, as a different file with same inode
|
||||
* and device used to be a hard link.
|
||||
* When cache inode is disabled, indexing is done by path on local filesystem.
|
||||
*/
|
||||
|
||||
#ifndef FILE_H_
|
||||
#define FILE_H_
|
||||
|
||||
#define FILE_HASH_NODES 2048
|
||||
|
||||
struct iso_file {
|
||||
char *path; /**< Path of the file on local filesystem */
|
||||
off_t size; /**< size of this file */
|
||||
ino_t ino; /**< This will be the inode number on CD of the file (RR) */
|
||||
nlink_t nlink; /**< Number of hard links of the file on CD (RR) */
|
||||
size_t block; /**< Block where this file is to be written on image */
|
||||
dev_t real_dev;
|
||||
ino_t real_ino; /**< for lookup by inode caching */
|
||||
int sort_weight;
|
||||
};
|
||||
|
||||
struct iso_file_hash_node {
|
||||
struct iso_file_hash_node *next;
|
||||
struct iso_file *file;
|
||||
};
|
||||
|
||||
struct iso_file_table {
|
||||
struct iso_file_hash_node *table[FILE_HASH_NODES];
|
||||
size_t count;
|
||||
int cache_inodes; /**< 1 to index by inode number */
|
||||
};
|
||||
|
||||
struct iso_tree_node_file;
|
||||
|
||||
/**
|
||||
* Create a struct that represents the specified iso_tree_node_file,
|
||||
* suitable to be stored into the table,
|
||||
*/
|
||||
struct iso_file *iso_file_new(struct iso_tree_node_file*);
|
||||
|
||||
struct iso_file_table *iso_file_table_new(int cache_inodes);
|
||||
|
||||
/**
|
||||
* Clear a hash table. All iso_file structs stored will also be freed,
|
||||
* but not the path of each iso_file
|
||||
*/
|
||||
void iso_file_table_clear(struct iso_file_table *ft);
|
||||
|
||||
/**
|
||||
* Add a new file to the table.
|
||||
* \return 1 if the file is added, 0 if the file already exist on table
|
||||
*/
|
||||
int iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f);
|
||||
|
||||
struct iso_file *iso_file_table_lookup(struct iso_file_table *ft,
|
||||
struct iso_tree_node_file *f);
|
||||
|
||||
#endif /*FILE_H_*/
|
@ -7,7 +7,6 @@
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -20,75 +19,33 @@ create_node(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *ret =
|
||||
calloc(1, sizeof(struct joliet_tree_node));
|
||||
|
||||
ret->name = iso_j_id(iso->name, t->input_charset);
|
||||
ret->name = iso_j_id(iso->name);
|
||||
ret->dirent_len = 34 + (ret->name ? ucslen(ret->name) * 2 : 0);
|
||||
ret->len = iso->attrib.st_size; /* for dirs, we'll change this */
|
||||
ret->block = iso->block; /* only actually for files, not dirs */
|
||||
ret->parent = parent;
|
||||
ret->iso_self = iso;
|
||||
ret->target = t;
|
||||
|
||||
if ( ISO_ISDIR(iso) ) {
|
||||
struct iso_tree_node_dir *dir = (struct iso_tree_node_dir *) iso;
|
||||
ret->info.dir.children = calloc(sizeof(void*), dir->nchildren);
|
||||
ret->type = JOLIET_DIR;
|
||||
} else if (ISO_ISREG(iso)) {
|
||||
/* it's a file */
|
||||
struct iso_tree_node_file *iso_f = (struct iso_tree_node_file *) iso;
|
||||
struct iso_file *file;
|
||||
file = iso_file_table_lookup(t->file_table, iso_f);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(iso_f);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
}
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
} else {
|
||||
/* it's boot catalog info */
|
||||
struct iso_tree_node_boot_catalog *iso_b =
|
||||
(struct iso_tree_node_boot_catalog *) iso;
|
||||
struct iso_file *file;
|
||||
file = iso_b->catalog->file;
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
}
|
||||
|
||||
ret->nchildren = iso->nchildren;
|
||||
if (ret->nchildren)
|
||||
ret->children = calloc(sizeof(void*), ret->nchildren);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct joliet_tree_node*
|
||||
create_tree(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct joliet_tree_node *root;
|
||||
assert(t && iso);
|
||||
|
||||
if ( iso->hide_flags & LIBISO_HIDE_ON_JOLIET )
|
||||
return NULL;
|
||||
|
||||
switch (iso->type) {
|
||||
case LIBISO_NODE_FILE:
|
||||
case LIBISO_NODE_BOOTCATALOG:
|
||||
root = create_node(t, parent, iso);
|
||||
break;
|
||||
case LIBISO_NODE_DIR:
|
||||
{
|
||||
size_t i;
|
||||
struct joliet_tree_node *node;
|
||||
struct iso_tree_node_dir *dir;
|
||||
root = create_node(t, parent, iso);
|
||||
dir = (struct iso_tree_node_dir*)iso;
|
||||
for (i = 0; i < dir->nchildren; ++i) {
|
||||
node = create_tree(t, root, dir->children[i]);
|
||||
if ( node != NULL ) {
|
||||
root->info.dir.children[root->info.dir.nchildren++] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//TODO replace this printf
|
||||
printf("Can't add this kind of node to a Joliet tree");
|
||||
return NULL;
|
||||
break;
|
||||
struct iso_tree_node *iso_root)
|
||||
{
|
||||
struct joliet_tree_node *root = create_node(t, parent, iso_root);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
struct iso_tree_node *iso_ch = iso_root->children[i];
|
||||
if (ISO_ISDIR(iso_ch))
|
||||
root->children[i] = create_tree(t, root, iso_ch);
|
||||
else
|
||||
root->children[i] = create_node(t, root, iso_ch);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
@ -106,15 +63,12 @@ sort_tree(struct joliet_tree_node *root)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(root && (root->type == JOLIET_DIR));
|
||||
assert(root && ISO_ISDIR(root->iso_self));
|
||||
|
||||
qsort(root->info.dir.children, root->info.dir.nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->info.dir.nchildren; i++) {
|
||||
struct joliet_tree_node *child = root->info.dir.children[i];
|
||||
if ( child->type == JOLIET_DIR )
|
||||
sort_tree(child);
|
||||
}
|
||||
qsort(root->children, root->nchildren, sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->nchildren; i++)
|
||||
if (ISO_ISDIR(root->children[i]->iso_self))
|
||||
sort_tree(root->children[i]);
|
||||
}
|
||||
|
||||
void
|
||||
@ -126,11 +80,11 @@ joliet_prepare_path_tables(struct ecma119_write_target *t)
|
||||
t->path_table_size_joliet = 10; /* root directory record */
|
||||
cur = 1;
|
||||
|
||||
for (i = 0; i < t->dirlist_len_joliet; i++) {
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
struct joliet_tree_node *dir = t->pathlist_joliet[i];
|
||||
for (j = 0; j < dir->info.dir.nchildren; j++) {
|
||||
struct joliet_tree_node *ch = dir->info.dir.children[j];
|
||||
if (ch->type == JOLIET_DIR) {
|
||||
for (j = 0; j < dir->nchildren; j++) {
|
||||
struct joliet_tree_node *ch = dir->children[j];
|
||||
if (ISO_ISDIR(ch->iso_self)) {
|
||||
size_t len = 8 + ucslen(ch->name)*2;
|
||||
t->pathlist_joliet[cur++] = ch;
|
||||
t->path_table_size_joliet += len;
|
||||
@ -147,25 +101,18 @@ joliet_calc_dir_size(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *root)
|
||||
{
|
||||
size_t i;
|
||||
size_t newlen;
|
||||
struct joliet_tree_node *ch;
|
||||
|
||||
assert(root && (root->type == JOLIET_DIR) );
|
||||
assert(root && ISO_ISDIR(root->iso_self));
|
||||
|
||||
t->dirlist_len_joliet++;
|
||||
root->info.dir.len = 68; /* for "." and ".." entries */
|
||||
for (i = 0; i < root->info.dir.nchildren; ++i) {
|
||||
ch = root->info.dir.children[i];
|
||||
newlen = root->info.dir.len + ch->dirent_len;
|
||||
if ((newlen % 2048) < (root->info.dir.len % 2048)) {
|
||||
root->info.dir.len = newlen + (2048 - (root->info.dir.len % 2048));
|
||||
} else {
|
||||
root->info.dir.len += ch->dirent_len;
|
||||
}
|
||||
if (ch->type == JOLIET_DIR)
|
||||
root->len = 68; /* for "." and ".." entries */
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
ch = root->children[i];
|
||||
root->len += ch->dirent_len;
|
||||
if (ISO_ISDIR(ch->iso_self))
|
||||
joliet_calc_dir_size(t, ch);
|
||||
}
|
||||
t->total_dir_size_joliet += round_up (root->info.dir.len, t->block_size);
|
||||
t->total_dir_size_joliet += round_up (root->len, t->block_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,17 +125,45 @@ joliet_calc_dir_pos(struct ecma119_write_target *t,
|
||||
size_t i;
|
||||
struct joliet_tree_node *ch;
|
||||
|
||||
assert(root && (root->type == JOLIET_DIR));
|
||||
assert(root && ISO_ISDIR(root->iso_self));
|
||||
|
||||
root->info.dir.block = t->curblock;
|
||||
t->curblock += div_up(root->info.dir.len, t->block_size);
|
||||
root->block = t->curblock;
|
||||
t->curblock += div_up(root->len, t->block_size);
|
||||
|
||||
t->dirlist_joliet[t->curfile++] = root;
|
||||
for (i = 0; i < root->info.dir.nchildren; i++) {
|
||||
ch = root->info.dir.children[i];
|
||||
if (ch->type == JOLIET_DIR)
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
ch = root->children[i];
|
||||
if (ISO_ISDIR(ch->iso_self))
|
||||
joliet_calc_dir_pos(t, ch);
|
||||
}
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
if (!root->parent)
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
void
|
||||
joliet_update_file_pos(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *dir)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(dir && ISO_ISDIR(dir->iso_self));
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
struct joliet_tree_node *ch;
|
||||
ch = dir->children[i];
|
||||
|
||||
if (!ISO_ISDIR (ch->iso_self)) {
|
||||
struct iso_tree_node *iso = ch->iso_self;
|
||||
ch->block = iso->block;
|
||||
}
|
||||
else
|
||||
joliet_update_file_pos(t, ch);
|
||||
}
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
if (!dir->parent)
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
struct joliet_tree_node*
|
||||
@ -201,21 +176,6 @@ joliet_tree_create(struct ecma119_write_target *t,
|
||||
return root;
|
||||
}
|
||||
|
||||
void
|
||||
joliet_tree_free(struct joliet_tree_node *root)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (root->type == JOLIET_DIR) {
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
joliet_tree_free(root->info.dir.children[i]);
|
||||
}
|
||||
free(root->info.dir.children);
|
||||
}
|
||||
free(root->name);
|
||||
free(root);
|
||||
}
|
||||
|
||||
/* ugh. this is mostly C&P */
|
||||
static void
|
||||
write_path_table(struct ecma119_write_target *t,
|
||||
@ -225,7 +185,7 @@ write_path_table(struct ecma119_write_target *t,
|
||||
void (*write_int)(uint8_t*, uint32_t, int) = l_type ?
|
||||
iso_lsb : iso_msb;
|
||||
|
||||
size_t i;
|
||||
size_t i;
|
||||
struct ecma119_path_table_record *rec;
|
||||
struct joliet_tree_node *dir;
|
||||
int parent = 0;
|
||||
@ -242,7 +202,7 @@ write_path_table(struct ecma119_write_target *t,
|
||||
rec->len_di[0] = dir->parent ?
|
||||
(uint8_t) ucslen(dir->name) * 2 : 1;
|
||||
rec->len_xa[0] = 0;
|
||||
write_int(rec->block, dir->info.dir.block, 4);
|
||||
write_int(rec->block, dir->block, 4);
|
||||
write_int(rec->parent, parent + 1, 2);
|
||||
if (dir->parent)
|
||||
memcpy(rec->dir_id, dir->name, rec->len_di[0]);
|
||||
@ -260,31 +220,20 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
int file_id,
|
||||
uint8_t *buf)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t block;
|
||||
uint8_t len_dr = (file_id >= 0) ? 34 : node->dirent_len;
|
||||
uint8_t len_fi = (file_id >= 0) ? 1 : ucslen(node->name) * 2;
|
||||
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
||||
|
||||
if (node->type == JOLIET_DIR) {
|
||||
len = node->info.dir.len;
|
||||
block = node->info.dir.block;
|
||||
} else {
|
||||
/* file */
|
||||
len = node->info.file->size;
|
||||
block = node->info.file->block;
|
||||
}
|
||||
|
||||
if (file_id == 1 && node->parent)
|
||||
node = node->parent;
|
||||
|
||||
rec->len_dr[0] = len_dr;
|
||||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
iso_bb(rec->block, node->block, 4);
|
||||
iso_bb(rec->length, node->len, 4);
|
||||
iso_datetime_7(rec->recording_time, t->now);
|
||||
rec->flags[0] = (node->type == JOLIET_DIR) ? 2 : 0;
|
||||
rec->flags[0] = ISO_ISDIR(node->iso_self) ? 2 : 0;
|
||||
iso_bb(rec->vol_seq_number, t->volnum + 1, 2);
|
||||
rec->len_fi[0] = len_fi;
|
||||
memcpy(rec->file_id, name, len_fi);
|
||||
@ -307,29 +256,19 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct ecma119_sup_vol_desc *vol = (struct ecma119_sup_vol_desc*)buf;
|
||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||
uint16_t *vol_id = str2ucs(volume->volume_id, t->input_charset);
|
||||
uint16_t *pub_id = str2ucs(volume->publisher_id, t->input_charset);
|
||||
uint16_t *data_id = str2ucs(volume->data_preparer_id, t->input_charset);
|
||||
uint16_t *volset_id = str2ucs(t->volset->volset_id, t->input_charset);
|
||||
uint16_t *vol_id = str2ucs(volume->volume_id);
|
||||
uint16_t *pub_id = str2ucs(volume->publisher_id);
|
||||
uint16_t *data_id = str2ucs(volume->data_preparer_id);
|
||||
uint16_t *volset_id = str2ucs(t->volset->volset_id);
|
||||
int vol_id_len = MIN(32, ucslen(vol_id) * 2);
|
||||
int pub_id_len = MIN(128, ucslen(pub_id) * 2);
|
||||
int data_id_len = MIN(128, ucslen(data_id) * 2);
|
||||
int volset_id_len = MIN(128, ucslen(volset_id) * 2);
|
||||
|
||||
uint16_t *system_id = str2ucs(volume->system_id, t->input_charset);
|
||||
uint16_t *application_id = str2ucs(volume->application_id, t->input_charset);
|
||||
uint16_t *copyright_file_id = str2ucs(volume->copyright_file_id, t->input_charset);
|
||||
uint16_t *abstract_file_id = str2ucs(volume->abstract_file_id, t->input_charset);
|
||||
uint16_t *biblio_file_id = str2ucs(volume->biblio_file_id, t->input_charset);
|
||||
int system_id_len = MIN(32, ucslen(system_id) * 2);
|
||||
int application_id_len = MIN(128, ucslen(application_id) * 2);
|
||||
int copyright_file_id_len = MIN(37, ucslen(copyright_file_id) * 2);
|
||||
int abstract_file_id_len = MIN(37, ucslen(abstract_file_id) * 2);
|
||||
int biblio_file_id_len = MIN(37, ucslen(biblio_file_id) * 2);
|
||||
|
||||
vol->vol_desc_type[0] = 2;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
memcpy(vol->system_id, "SYSID", 5);
|
||||
if (vol_id)
|
||||
memcpy(vol->volume_id, vol_id, vol_id_len);
|
||||
memcpy(vol->esc_sequences, "%/E", 3);
|
||||
@ -346,13 +285,8 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
memcpy(vol->vol_set_id, volset_id, volset_id_len);
|
||||
memcpy(vol->publisher_id, pub_id, pub_id_len);
|
||||
memcpy(vol->data_prep_id, data_id, data_id_len);
|
||||
|
||||
memcpy(vol->system_id, system_id, system_id_len);
|
||||
memcpy(vol->application_id, "APPID", application_id_len);
|
||||
memcpy(vol->copyright_file_id, copyright_file_id, copyright_file_id_len);
|
||||
memcpy(vol->abstract_file_id, abstract_file_id, abstract_file_id_len);
|
||||
memcpy(vol->bibliographic_file_id, biblio_file_id, biblio_file_id_len);
|
||||
|
||||
/*memcpy(vol->application_id, "APPID", app_id_len);*/
|
||||
|
||||
iso_datetime_17(vol->vol_creation_time, t->now);
|
||||
iso_datetime_17(vol->vol_modification_time, t->now);
|
||||
iso_datetime_17(vol->vol_effective_time, t->now);
|
||||
@ -362,11 +296,6 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
free(volset_id);
|
||||
free(pub_id);
|
||||
free(data_id);
|
||||
free(system_id);
|
||||
free(application_id);
|
||||
free(copyright_file_id);
|
||||
free(abstract_file_id);
|
||||
free(biblio_file_id);
|
||||
|
||||
}
|
||||
|
||||
@ -376,12 +305,9 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
uint8_t *buf)
|
||||
{
|
||||
size_t i;
|
||||
int j;
|
||||
size_t len;
|
||||
uint8_t *orig_buf = buf;
|
||||
uint8_t *prior_buf = buf;
|
||||
|
||||
assert(dir->type == JOLIET_DIR);
|
||||
assert(ISO_ISDIR (dir->iso_self));
|
||||
/* write the "." and ".." entries first */
|
||||
write_one_dir_record(t, dir, 0, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
@ -389,23 +315,12 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
write_one_dir_record(t, dir, 1, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
write_one_dir_record(t, dir->info.dir.children[i], -1, buf);
|
||||
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
if ((buf + len - prior_buf) >= 2048) {
|
||||
for (j = len - 1; j >= 0; j--) {
|
||||
prior_buf[2048 + j] = buf[j];
|
||||
buf[j] = 0;
|
||||
}
|
||||
prior_buf += 2048;
|
||||
buf = prior_buf + len;
|
||||
}
|
||||
else {
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
}
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
write_one_dir_record(t, dir->children[i], -1, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
}
|
||||
|
||||
assert (buf - orig_buf == dir->info.dir.len);
|
||||
assert (buf - orig_buf == dir->len);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -414,11 +329,11 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
||||
size_t i;
|
||||
struct joliet_tree_node *dir;
|
||||
|
||||
assert (t->curblock == t->dirlist_joliet[0]->info.dir.block);
|
||||
for (i = 0; i < t->dirlist_len_joliet; i++) {
|
||||
assert (t->curblock == t->dirlist_joliet[0]->block);
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
dir = t->dirlist_joliet[i];
|
||||
write_one_dir(t, dir, buf);
|
||||
buf += round_up(dir->info.dir.len, t->block_size);
|
||||
buf += round_up(dir->len, t->block_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,31 +17,19 @@
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
|
||||
enum joliet_node_type {
|
||||
JOLIET_FILE,
|
||||
JOLIET_DIR
|
||||
};
|
||||
|
||||
struct joliet_dir_info {
|
||||
struct joliet_tree_node **children;
|
||||
size_t nchildren;
|
||||
size_t len;
|
||||
size_t block;
|
||||
};
|
||||
|
||||
struct joliet_tree_node
|
||||
{
|
||||
uint16_t *name; /**< In UCS-2BE. */
|
||||
size_t dirent_len;
|
||||
size_t len;
|
||||
size_t block;
|
||||
|
||||
struct joliet_tree_node *parent;
|
||||
struct iso_tree_node *iso_self;
|
||||
struct ecma119_write_target *target;
|
||||
|
||||
enum joliet_node_type type;
|
||||
union {
|
||||
struct iso_file *file;
|
||||
struct joliet_dir_info dir;
|
||||
} info;
|
||||
|
||||
struct joliet_tree_node **children;
|
||||
size_t nchildren;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -64,6 +52,13 @@ joliet_calc_dir_size(struct ecma119_write_target *t, struct joliet_tree_node*);
|
||||
void
|
||||
joliet_calc_dir_pos(struct ecma119_write_target *t, struct joliet_tree_node*);
|
||||
|
||||
/**
|
||||
* Update the position of each file in the joliet hierarchy (to be called
|
||||
* AFTER the file positions in the iso tree have been set).
|
||||
*/
|
||||
void
|
||||
joliet_update_file_pos(struct ecma119_write_target *t, struct joliet_tree_node*);
|
||||
|
||||
/**
|
||||
* Calculate the size of the joliet path table and fill in the list of
|
||||
* directories.
|
||||
|
@ -12,8 +12,6 @@
|
||||
#ifndef LIBISO_LIBISOFS_H
|
||||
#define LIBISO_LIBISOFS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* #include <libburn.h> */
|
||||
struct burn_source;
|
||||
|
||||
@ -35,156 +33,11 @@ struct iso_volset;
|
||||
*/
|
||||
struct iso_tree_node;
|
||||
|
||||
/**
|
||||
* El-Torito boot image
|
||||
* \see eltorito.h
|
||||
*/
|
||||
struct el_torito_boot_image;
|
||||
|
||||
/**
|
||||
* A directory in the filesystem tree.
|
||||
* The first member of this is an iso_tree_node.
|
||||
* \see tree.h
|
||||
*/
|
||||
struct iso_tree_node_dir;
|
||||
|
||||
/**
|
||||
* Extensions addition to ECMA-119 (ISO-9660) image. Usage of at least
|
||||
* one of these flags is highly recommended if the disc will be used on a
|
||||
* modern OS.
|
||||
*/
|
||||
enum ecma119_extension_flag {
|
||||
/**
|
||||
* Add the standard Rock Ridge extensions. This adds POSIX filesystem
|
||||
* features to the ECMA-119 image. Thus, usage of this flag is highly
|
||||
* recommended for images used on GNU/Linux systems. With the usage
|
||||
* of RR extension, the resulting image will have long filenames (up to
|
||||
* 255 characters), deeper directory structure, POSIX permissions and
|
||||
* owner info on files and directories, support for symbolic links or
|
||||
* special files... All that attributes can be modified/setted with the
|
||||
* appropiate function.
|
||||
*/
|
||||
ECMA119_ROCKRIDGE = (1<<0),
|
||||
/**
|
||||
* Add the non-standard Joliet extension to the image. This extension is
|
||||
* heavily used in Microsoft Windows systems, so if you plan to use your
|
||||
* disc on such a system you should add this extension. Usage of Joliet
|
||||
* supplies longer filesystem length (up to 64 unicode characters), and
|
||||
* deeper directory structure.
|
||||
*/
|
||||
ECMA119_JOLIET = (1<<1)
|
||||
};
|
||||
|
||||
/**
|
||||
* Flag used to hide a file in the RR/ISO or Joliet tree.
|
||||
*
|
||||
* \see iso_tree_node_set_hidden
|
||||
*/
|
||||
enum hide_node_flag {
|
||||
LIBISO_HIDE_ON_RR = 1 << 0,
|
||||
LIBISO_HIDE_ON_JOLIET = 1 << 1
|
||||
};
|
||||
|
||||
/**
|
||||
* El-Torito bootable image type.
|
||||
*/
|
||||
enum eltorito_boot_media_type {
|
||||
ELTORITO_FLOPPY_EMUL,
|
||||
ELTORITO_HARD_DISC_EMUL,
|
||||
ELTORITO_NO_EMUL
|
||||
};
|
||||
|
||||
enum ecma119_relaxed_constraints_flag {
|
||||
ECMA119_OMIT_VERSION_NUMBERS = (1<<0),
|
||||
/* 37 char filenames involves no version number */
|
||||
ECMA119_37_CHAR_FILENAMES = (1<<1) | (1<<0),
|
||||
ECMA119_NO_DIR_REALOCATION = (1<<2),
|
||||
ECMA119_RELAXED_FILENAMES = (1<<3)
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds the options for the image generation.
|
||||
*/
|
||||
struct ecma119_source_opts {
|
||||
int volnum; /**< The volume in the set which you want to write (usually 0) */
|
||||
int level; /**< ISO level to write at. */
|
||||
int flags; /**< Which extensions to support. */
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
unsigned int no_cache_inodes:1;
|
||||
/**< If use inode caching or not. Set it to 1 to prevent
|
||||
* inode caching.
|
||||
* Usage of inode caching allows detection of hard-links,
|
||||
* which contents are only written once to disc this way.
|
||||
* Don't use inode caching in systems with non unique inodes
|
||||
* per device.
|
||||
*/
|
||||
unsigned int sort_files:1;
|
||||
/**< If files should be sorted based on their weight. */
|
||||
unsigned int default_mode:1;
|
||||
/**<
|
||||
* The default values for files and directory permissions,
|
||||
* gid and uid. This option can be overwritten when set
|
||||
* one of the following.
|
||||
* 0 to use useful values, 1 to use node modes (this are
|
||||
* the same as filesystem ones if not changed after added
|
||||
* to tree).
|
||||
*/
|
||||
unsigned int replace_dir_mode:1;
|
||||
/**<
|
||||
* When 1, permissions for all dirs will be replaced by the
|
||||
* specified in dir_mode field.
|
||||
*/
|
||||
unsigned int replace_file_mode:1;
|
||||
/**<
|
||||
* When 1, permissions for all files will be replaced by the
|
||||
* specified in file_mode field.
|
||||
*/
|
||||
unsigned int replace_uid:1;
|
||||
/**<
|
||||
* When 1, uid of all nodes (both files and dirs) will be
|
||||
* replaced by the specified in uid field.
|
||||
*/
|
||||
unsigned int replace_gid:1;
|
||||
/**<
|
||||
* When 1, gid of all nodes (both files and dirs) will be
|
||||
* replaced by the specified in gid field.
|
||||
*/
|
||||
mode_t dir_mode; /**< Mode to use on dirs when replace_dir_mode is set. */
|
||||
mode_t file_mode; /**< Mode to use on files when replace_file_mode is set. */
|
||||
gid_t gid; /**< gid to use when replace_gid is set. */
|
||||
uid_t uid; /**< uid to use when replace_uid is set. */
|
||||
char *input_charset; /**< NULL to use default charset */
|
||||
char *ouput_charset; /**< NULL to use default charset */
|
||||
};
|
||||
|
||||
/**
|
||||
* This will hold the error code for some functions, if them fail.
|
||||
*/
|
||||
int libisofs_errno;
|
||||
|
||||
/* an unexpected internal error */
|
||||
#define INTERNAL_ERROR -1
|
||||
/* file don't exists, or can't be stat'ed */
|
||||
#define NO_FILE 1
|
||||
/* user haven't read access to file */
|
||||
#define NO_READ_ACCESS 2
|
||||
/* unexpected file type, eg., passing a dir instead of a regular file */
|
||||
#define UNEXPECTED_FILE_TYPE 3
|
||||
/* invalid boot image size */
|
||||
#define ELTORITO_WRONG_IMAGE_SIZE 4
|
||||
|
||||
/**
|
||||
* Controls the bahavior of iso_tree_radd_dir function
|
||||
*/
|
||||
struct iso_tree_radd_dir_behavior {
|
||||
char** excludes; /**< List of paths (file or directory) to be ignored. */
|
||||
//int follow_sym_link;
|
||||
int stop_on_error; /**< Stop when an error was found?. */
|
||||
int error; /**< set to 1 on error */
|
||||
//int notify_errors;
|
||||
//char** errors;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new volume.
|
||||
* The parameters can be set to NULL if you wish to set them later.
|
||||
@ -196,7 +49,7 @@ struct iso_volume *iso_volume_new(const char *volume_id,
|
||||
struct iso_volume *iso_volume_new_with_root(const char *volume_id,
|
||||
const char *publisher_id,
|
||||
const char *data_preparer_id,
|
||||
struct iso_tree_node_dir *root);
|
||||
struct iso_tree_node *root);
|
||||
|
||||
/**
|
||||
* Free a volume.
|
||||
@ -211,7 +64,7 @@ void iso_volset_free(struct iso_volset *volume);
|
||||
/**
|
||||
* Get the root directory for a volume.
|
||||
*/
|
||||
struct iso_tree_node_dir *iso_volume_get_root(const struct iso_volume *volume);
|
||||
struct iso_tree_node *iso_volume_get_root(const struct iso_volume *volume);
|
||||
|
||||
/**
|
||||
* Fill in the volume identifier for a volume.
|
||||
@ -231,104 +84,6 @@ void iso_volume_set_publisher_id(struct iso_volume *volume,
|
||||
void iso_volume_set_data_preparer_id(struct iso_volume *volume,
|
||||
const char *data_preparer_id);
|
||||
|
||||
/**
|
||||
* Fill in the system id for a volume. Up to 32 characters.
|
||||
*/
|
||||
void iso_volume_set_system_id(struct iso_volume *volume,
|
||||
const char *system_id);
|
||||
|
||||
/**
|
||||
* Fill in the application id for a volume. Up to 128 chars.
|
||||
*/
|
||||
void iso_volume_set_application_id(struct iso_volume *volume,
|
||||
const char *application_id);
|
||||
|
||||
/**
|
||||
* Fill copyright information for the volume. Usually this refers
|
||||
* to a file on disc. Up to 37 characters.
|
||||
*/
|
||||
void iso_volume_set_copyright_file_id(struct iso_volume *volume,
|
||||
const char *copyright_file_id);
|
||||
|
||||
/**
|
||||
* Fill abstract information for the volume. Usually this refers
|
||||
* to a file on disc. Up to 37 characters.
|
||||
*/
|
||||
void iso_volume_set_abstract_file_id(struct iso_volume *volume,
|
||||
const char *abstract_file_id);
|
||||
|
||||
/**
|
||||
* Fill biblio information for the volume. Usually this refers
|
||||
* to a file on disc. Up to 37 characters.
|
||||
*/
|
||||
void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
||||
const char *biblio_file_id);
|
||||
|
||||
/**
|
||||
* Create a bootable volume by adding a El-Torito boot image.
|
||||
*
|
||||
* \param volume The volume to make bootable.
|
||||
* \param image The tree node with the file to use as default boot image.
|
||||
* \param type The boot media type. This can be one of 3 types:
|
||||
* - Floppy emulation: Boot image files must be exactly
|
||||
* 1200 kB, 1440 kB or 2880 kB.
|
||||
* - Hard disc emulation: The image must begin with a master
|
||||
* boot record with a single image.
|
||||
* - No emulation. You should specify load segment and load size
|
||||
* of image.
|
||||
* \param dir The directory node where the boot catalog will be located
|
||||
* in image. Usually both boot catalog and boot image will be
|
||||
* located in the same dir, maybe /boot.
|
||||
* \param name The name of the boot catalog.
|
||||
*
|
||||
* \return The default El-Torito bootable image. If specified image file
|
||||
* seems to be not correct, this returns NULL and libisofs_errno
|
||||
* is set propertly.
|
||||
*
|
||||
* \pre \p volume is a volume without any boot catalog yet
|
||||
* \pre \p image is a file tree node already inserted in the volume tree.
|
||||
* \pre \p dir is a directory node already inserted in the volume tree.
|
||||
* \pre \p name There isn't any dir child with the same name.
|
||||
*
|
||||
*/
|
||||
struct el_torito_boot_image *
|
||||
iso_volume_create_boot_catalog(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name);
|
||||
|
||||
/**
|
||||
* Sets the load segment for the initial boot image. This is only for
|
||||
* no emulation boot images, and is a NOP for other image types.
|
||||
*/
|
||||
void
|
||||
el_torito_set_load_seg(struct el_torito_boot_image *bootimg, int segment);
|
||||
|
||||
/**
|
||||
* Sets the number of sectors (512b) to be load at load segment during
|
||||
* the initial boot procedure. This is only for
|
||||
* no emulation boot images, and is a NOP for other image types.
|
||||
*/
|
||||
void
|
||||
el_torito_set_load_size(struct el_torito_boot_image *bootimg, int sectors);
|
||||
|
||||
/**
|
||||
* Marks the specified boot image as not bootable
|
||||
*/
|
||||
void
|
||||
el_torito_set_no_bootable(struct el_torito_boot_image *bootimg);
|
||||
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writting
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* Be aware that libisofs will modify original boot image file, so do a backup
|
||||
* if needed.
|
||||
* This is needed for isolinux boot images.
|
||||
*/
|
||||
void
|
||||
el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg);
|
||||
|
||||
/**
|
||||
* Locate a node by its path on disc.
|
||||
*
|
||||
@ -337,8 +92,6 @@ el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg);
|
||||
*
|
||||
* \return The node found or NULL.
|
||||
*
|
||||
* TODO we need a way to allow developers know which kind of node is.
|
||||
* Think about this when designing the read api
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path);
|
||||
|
||||
@ -351,9 +104,9 @@ struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, co
|
||||
*
|
||||
* \return The node for the file or NULL if the parent doesn't exists on the disc.
|
||||
*/
|
||||
//struct iso_tree_node *iso_tree_volume_add_path(struct iso_volume *volume,
|
||||
// const char *disc_path,
|
||||
// const char *path);
|
||||
struct iso_tree_node *iso_tree_volume_add_path(struct iso_volume *volume,
|
||||
const char *disc_path,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Creates a new, empty directory on the volume.
|
||||
@ -363,8 +116,8 @@ struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, co
|
||||
*
|
||||
* \return A pointer to the newly created directory.
|
||||
*/
|
||||
//struct iso_tree_node *iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
||||
// const char *disc_path);
|
||||
struct iso_tree_node *iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
||||
const char *disc_path);
|
||||
|
||||
/**
|
||||
* Create a new Volume Set consisting of only one volume.
|
||||
@ -375,47 +128,59 @@ struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, co
|
||||
struct iso_volset *iso_volset_new(struct iso_volume *volume,
|
||||
const char *volset_id);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new root dir for a filesystem tree
|
||||
*/
|
||||
struct iso_tree_node_dir *iso_tree_new_root();
|
||||
|
||||
/**
|
||||
* Add a file to a directory.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*
|
||||
* \pre \p parent is non-NULL.
|
||||
* \pre \p path is non-NULL.
|
||||
* \return An iso_tree_node_file whose path is \p path and whose parent is
|
||||
* \p parent.
|
||||
* On error, returns NULL and libisofs_errno is set appropriately:
|
||||
* NO_FILE if path doesn't point to a valid file.
|
||||
* NO_READ_ACCESS if user haven't read access on file
|
||||
* UNEXPECTED_FILE_TYPE if path doesn't point to a regular file
|
||||
*
|
||||
* \pre \p parent is NULL or is a directory.
|
||||
* \pre \p path is non-NULL and is a valid path to a non-directory on the local
|
||||
* filesystem.
|
||||
* \return An iso_tree_node whose path is \p path and whose parent is \p parent.
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_add_file(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *iso_tree_add_node(struct iso_tree_node *parent,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Add a symbolic link to a directory.
|
||||
*
|
||||
* \param name The name of the symbolic link
|
||||
* \param dest The distination of the link, i.e., the file this link points
|
||||
* to
|
||||
*
|
||||
* \pre \p parent, name and dest are non-NULL.
|
||||
*
|
||||
* \return An iso_tree_node_symlink
|
||||
* Recursively add an existing directory to the tree.
|
||||
* Warning: when using this, you'll lose pointers to files or subdirectories.
|
||||
* If you want to have pointers to all files and directories,
|
||||
* use iso_tree_add_file and iso_tree_add_dir.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the directory to add.
|
||||
*
|
||||
* \pre \p parent is NULL or is a directory.
|
||||
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
||||
* filesystem.
|
||||
* \return a pointer to the newly created directory.
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_add_symlink(struct iso_tree_node_dir *parent,
|
||||
const char *name, const char *dest);
|
||||
struct iso_tree_node *iso_tree_radd_dir(struct iso_tree_node *parent,
|
||||
const char *path);
|
||||
|
||||
|
||||
/**
|
||||
* Add a new, empty directory to the tree.
|
||||
* Add the path of a file or directory to ignore when adding a directory recursively.
|
||||
*
|
||||
* \pre \p parent is non-NULL.
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
void iso_exclude_add_path(const char *path);
|
||||
|
||||
/**
|
||||
* Remove a path that was set to be ignored when adding a directory recusively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
void iso_exclude_remove_path(const char *path);
|
||||
|
||||
/**
|
||||
* Remove all paths that were set to be ignored when adding a directory recusively.
|
||||
*/
|
||||
void iso_exclude_empty(void);
|
||||
|
||||
/**
|
||||
* Creates a new, empty directory on the volume.
|
||||
*
|
||||
* \pre \p parent is NULL or is a directory.
|
||||
* \pre \p name is unique among the children and files belonging to \p parent.
|
||||
* Also, it doesn't contain '/' characters.
|
||||
*
|
||||
@ -423,101 +188,13 @@ struct iso_tree_node *iso_tree_add_symlink(struct iso_tree_node_dir *parent,
|
||||
* POSIX attributes are the same as \p parent's.
|
||||
* \return a pointer to the newly created directory.
|
||||
*/
|
||||
struct iso_tree_node_dir *iso_tree_add_dir(struct iso_tree_node_dir *parent,
|
||||
const char *name);
|
||||
|
||||
/* TODO iso_tree_new_special */
|
||||
struct iso_tree_node *iso_tree_add_new_dir(struct iso_tree_node *parent,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Add a file to a directory.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*
|
||||
* \pre \p parent is non-NULL.
|
||||
* \pre \p path is non-NULL and is a valid path to a file or directory on the local
|
||||
* filesystem.
|
||||
* \return An iso_tree_node whose path is \p path and whose parent is \p parent.
|
||||
* On error, returns NULL and libisofs_errno is set appropriately:
|
||||
* NO_FILE if path doesn't point to a valid file.
|
||||
* NO_READ_ACCESS if user haven't read access on file
|
||||
* UNEXPECTED_FILE_TYPE if path refers to non supported file type
|
||||
* (at the momment, only dirs, symlinks and regular
|
||||
* files are supported).
|
||||
* Set the name of a file (using the current locale).
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_add_node(struct iso_tree_node_dir *parent,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Recursively add an existing directory to the tree.
|
||||
* Warning: when using this, you'll lose pointers to files or subdirectories.
|
||||
* If you want to have pointers to all files and directories,
|
||||
* use iso_tree_add_file, iso_tree_add_node and iso_tree_add_dir.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the directory to add.
|
||||
*
|
||||
* \pre \p parent is non-NULL.
|
||||
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
||||
* filesystem.
|
||||
*/
|
||||
void iso_tree_radd_dir(struct iso_tree_node_dir *parent, const char *path,
|
||||
struct iso_tree_radd_dir_behavior *behavior);
|
||||
|
||||
/**
|
||||
* Set the name of a tree node (using the current locale).
|
||||
*/
|
||||
void iso_tree_node_set_name(struct iso_tree_node *node, const char *name);
|
||||
|
||||
/**
|
||||
* Set if the node will be hidden in RR/ISO tree, Joliet tree or both.
|
||||
*
|
||||
* If the file is setted as hidden in one tree, it won't be included there, so
|
||||
* it won't be visible in a OS accessing CD using that tree. For example,
|
||||
* GNU/Linux systems access to Rock Ridge / ISO9960 tree in order to see
|
||||
* what is recorded on CD, while MS Windows make use of the Joliet tree. If a
|
||||
* file is hidden only in Joliet, it won't be visible in Windows systems,
|
||||
* while still visible in Linux.
|
||||
*
|
||||
* If a file is hidden in both trees, it won't be written to image.
|
||||
*
|
||||
* \param node The node that is to be hidden.
|
||||
* \param hide_attrs hide_node_flag's to set the trees in which file
|
||||
* will be hidden.
|
||||
*/
|
||||
void iso_tree_node_set_hidden(struct iso_tree_node *node, int hide_attrs);
|
||||
|
||||
/**
|
||||
* Set the group id for the node. This attribute is only useful when
|
||||
* Rock Ridge extensions are enabled.
|
||||
*/
|
||||
void iso_tree_node_set_gid(struct iso_tree_node *node, gid_t gid);
|
||||
|
||||
/**
|
||||
* Set the user id for the node. This attribute is only useful when
|
||||
* Rock Ridge extensions are enabled.
|
||||
*/
|
||||
void iso_tree_node_set_uid(struct iso_tree_node *node, uid_t uid);
|
||||
|
||||
/**
|
||||
* Set the permissions for the node. This attribute is only useful when
|
||||
* Rock Ridge extensions are enabled.
|
||||
*
|
||||
* \param mode bitmask with the permissions of the node, as specified
|
||||
* in 'man 2 stat'. The file type bitfields will be ignored,
|
||||
* only file permissions will be modified.
|
||||
*/
|
||||
void iso_tree_node_set_permissions(struct iso_tree_node *node, mode_t mode);
|
||||
|
||||
/**
|
||||
* Sets the order in which a node will be written on image. High weihted files
|
||||
* will be written first, so in a disc them will be written near the center.
|
||||
*
|
||||
* \param node The node which weight will be changed. If it's a dir, this
|
||||
* function will change the weight of all its children. For nodes
|
||||
* other that dirs or regular files, this function has no effect.
|
||||
* \param w The weight as a integer number, the greater this value is, the
|
||||
* closer from the begining of image the file will be written.
|
||||
*/
|
||||
void iso_tree_node_set_sort_weight(struct iso_tree_node *node, int w);
|
||||
void iso_tree_node_set_name(struct iso_tree_node *file, const char *name);
|
||||
|
||||
/**
|
||||
* Recursively print a directory to stdout.
|
||||
@ -532,13 +209,17 @@ void iso_tree_print(const struct iso_tree_node *root, int spaces);
|
||||
* until the libburn_source is freed.
|
||||
*
|
||||
* \param volumeset The volume set from which you want to write
|
||||
* \param opts The options for image generation
|
||||
* \param volnum The volume in the set which you want to write (usually 0)
|
||||
* \param level ISO level to write at.
|
||||
* \param flags Which extensions to support.
|
||||
*
|
||||
* \pre \p volumeset is non-NULL
|
||||
* \pre \p volnum is less than \p volset->volset_size.
|
||||
* \return A burn_source to be used for the data source for a track
|
||||
*/
|
||||
struct burn_source* iso_source_new_ecma119(struct iso_volset *volumeset,
|
||||
struct ecma119_source_opts *opts);
|
||||
struct burn_source* iso_source_new_ecma119 (struct iso_volset *volumeset,
|
||||
int volnum,
|
||||
int level,
|
||||
int flags);
|
||||
|
||||
#endif /* LIBISO_LIBISOFS_H */
|
||||
|
@ -14,30 +14,6 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/** See IEEE P1281 Draft Version 1.12/5.5 FIXME: this is rockridge */
|
||||
void
|
||||
rrip_add_ER(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
{
|
||||
unsigned char *ER = malloc(182);
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
ER[0] = 'E';
|
||||
ER[1] = 'R';
|
||||
ER[2] = 182;
|
||||
ER[3] = 1;
|
||||
ER[4] = 9;
|
||||
ER[5] = 72;
|
||||
ER[6] = 93;
|
||||
ER[7] = 1;
|
||||
memcpy(&ER[8], "IEEE_1282", 9);
|
||||
memcpy(&ER[17], "THE IEEE 1282 PROTOCOL PROVIDES SUPPORT FOR POSIX "
|
||||
"FILE SYSTEM SEMANTICS.", 72);
|
||||
memcpy(&ER[89], "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, "
|
||||
"PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION.", 93);
|
||||
susp_append(t, &dir->info.dir.self_susp, ER);
|
||||
}
|
||||
|
||||
/* create a PX field from the permissions on the current node. */
|
||||
uint8_t *rrip_make_PX(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *node)
|
||||
@ -48,11 +24,11 @@ uint8_t *rrip_make_PX(struct ecma119_write_target *t,
|
||||
PX[1] = 'X';
|
||||
PX[2] = 44;
|
||||
PX[3] = 1;
|
||||
iso_bb(&PX[4], node->attrib.st_mode, 4);
|
||||
iso_bb(&PX[12], node->attrib.st_nlink, 4);
|
||||
iso_bb(&PX[20], node->attrib.st_uid, 4);
|
||||
iso_bb(&PX[28], node->attrib.st_gid, 4);
|
||||
iso_bb(&PX[36], node->attrib.st_ino, 4);
|
||||
iso_bb(&PX[4], node->iso_self->attrib.st_mode, 4);
|
||||
iso_bb(&PX[12], node->iso_self->attrib.st_nlink, 4);
|
||||
iso_bb(&PX[20], node->iso_self->attrib.st_uid, 4);
|
||||
iso_bb(&PX[28], node->iso_self->attrib.st_gid, 4);
|
||||
iso_bb(&PX[36], node->iso_self->attrib.st_ino, 4);
|
||||
return PX;
|
||||
}
|
||||
|
||||
@ -61,8 +37,8 @@ void rrip_add_PX(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
susp_append(t, &node->susp, rrip_make_PX(t, node));
|
||||
if (node->type == ECMA119_DIR) {
|
||||
susp_append(t, &node->info.dir.self_susp, rrip_make_PX(t, node));
|
||||
susp_append(t, &node->info.dir.parent_susp, rrip_make_PX(t, node));
|
||||
susp_append(t, &node->dir.self_susp, rrip_make_PX(t, node));
|
||||
susp_append(t, &node->dir.parent_susp, rrip_make_PX(t, node));
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,8 +50,8 @@ void rrip_add_PN(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
PN[1] = 'N';
|
||||
PN[2] = 20;
|
||||
PN[3] = 1;
|
||||
iso_bb(&PN[4], node->attrib.st_dev >> 32, 4);
|
||||
iso_bb(&PN[12], node->attrib.st_dev & 0xffffffff, 4);
|
||||
iso_bb(&PN[4], node->iso_self->attrib.st_dev >> 32, 4);
|
||||
iso_bb(&PN[12], node->iso_self->attrib.st_dev & 0xffffffff, 4);
|
||||
susp_append(t, &node->susp, PN);
|
||||
}
|
||||
|
||||
@ -126,7 +102,7 @@ static void rrip_SL_add_component(char *prev, char *cur, int *n_comp,
|
||||
|
||||
void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
int path_size;
|
||||
int ret, pathsize = 0;
|
||||
char *path = NULL, *cur, *prev;
|
||||
int i, j;
|
||||
|
||||
@ -137,9 +113,19 @@ void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
|
||||
uint8_t *SL;
|
||||
|
||||
path = node->info.dest;
|
||||
path_size = strlen(path);
|
||||
|
||||
do {
|
||||
pathsize += 128;
|
||||
path = realloc(path, pathsize);
|
||||
/* FIXME: what if the file is not on the local fs? */
|
||||
ret = readlink(node->iso_self->loc.path, path, pathsize);
|
||||
} while (ret == pathsize);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Error: couldn't read symlink: %s\n",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
path[ret] = '\0';
|
||||
|
||||
prev = path;
|
||||
for (cur = strchr(path, '/'); cur && *cur; cur = strchr(cur, '/')) {
|
||||
rrip_SL_add_component(prev, cur, &n_comp, &comp);
|
||||
@ -148,8 +134,8 @@ void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
}
|
||||
|
||||
/* if there was no trailing '/', we need to add the last component. */
|
||||
if (prev == path || prev != &path[path_size - 1]) {
|
||||
rrip_SL_add_component(prev, &path[path_size], &n_comp, &comp);
|
||||
if (prev == path || prev != &path[ret - 1]) {
|
||||
rrip_SL_add_component(prev, &path[ret], &n_comp, &comp);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
@ -186,6 +172,7 @@ void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
}
|
||||
susp_append(t, &node->susp, SL);
|
||||
|
||||
free(path);
|
||||
/* free the components */
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
free(comp[i]);
|
||||
@ -213,7 +200,7 @@ static void rrip_add_NM_single(struct ecma119_write_target *t,
|
||||
void
|
||||
rrip_add_NM(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
char *name = node->full_name;
|
||||
char *name = iso_p_fileid(node->iso_self->name);
|
||||
int len = name ? strlen(name) : 0;
|
||||
char *pos = name;
|
||||
|
||||
@ -221,8 +208,8 @@ rrip_add_NM(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
return;
|
||||
|
||||
if (node->type == ECMA119_DIR) {
|
||||
rrip_add_NM_single(t, &node->info.dir.self_susp, pos, 0, 1 << 1);
|
||||
rrip_add_NM_single(t, &node->info.dir.parent_susp, pos, 0, 1 << 2);
|
||||
rrip_add_NM_single(t, &node->dir.self_susp, pos, 0, 1 << 1);
|
||||
rrip_add_NM_single(t, &node->dir.parent_susp, pos, 0, 1 << 2);
|
||||
}
|
||||
|
||||
while (len > 250) {
|
||||
@ -253,7 +240,7 @@ rrip_add_PL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
PL[1] = 'L';
|
||||
PL[2] = 12;
|
||||
PL[3] = 1;
|
||||
susp_append(t, &node->info.dir.parent_susp, PL);
|
||||
susp_append(t, &node->dir.parent_susp, PL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -277,10 +264,10 @@ rrip_add_TF(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
TF[1] = 'F';
|
||||
TF[2] = 5 + 3 * 7;
|
||||
TF[3] = 1;
|
||||
TF[4] = (1 << 1) | (1 << 2) | (1 << 3);
|
||||
iso_datetime_7(&TF[5], node->attrib.st_mtime);
|
||||
iso_datetime_7(&TF[12], node->attrib.st_atime);
|
||||
iso_datetime_7(&TF[19], node->attrib.st_ctime);
|
||||
TF[4] = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 7);
|
||||
iso_datetime_7(&TF[5], node->iso_self->attrib.st_mtime);
|
||||
iso_datetime_7(&TF[12], node->iso_self->attrib.st_atime);
|
||||
iso_datetime_7(&TF[19], node->iso_self->attrib.st_ctime);
|
||||
susp_append(t, &node->susp, TF);
|
||||
}
|
||||
|
||||
@ -291,21 +278,21 @@ rrip_finalize(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
if (dir->parent != dir->info.dir.real_parent) {
|
||||
uint8_t *PL = susp_find(&dir->info.dir.parent_susp, "PL");
|
||||
if (dir->parent != dir->dir.real_parent) {
|
||||
uint8_t *PL = susp_find(&dir->dir.parent_susp, "PL");
|
||||
|
||||
assert(PL);
|
||||
iso_bb(&PL[4], dir->info.dir.real_parent->info.dir.block, 4);
|
||||
iso_bb(&PL[4], dir->dir.real_parent->block, 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
|
||||
if (ch->type == ECMA119_PLACEHOLDER) {
|
||||
if (ch->type == ECMA119_FILE && ch->file.real_me) {
|
||||
uint8_t *CL = susp_find(&ch->susp, "CL");
|
||||
|
||||
assert(CL);
|
||||
iso_bb(&CL[4], ch->info.real_me->info.dir.block, 4);
|
||||
iso_bb(&CL[4], ch->file.real_me->block, 4);
|
||||
} else if (ch->type == ECMA119_DIR) {
|
||||
rrip_finalize(t, ch);
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
/**
|
||||
* Functions and structures used for Rock Ridge support.
|
||||
*
|
||||
* See IEEE P1282, Rock Ridge Interchange Protocol, Draft Standard version
|
||||
* 1.12 for further details.
|
||||
*/
|
||||
/** Functions and structures used for Rock Ridge support. */
|
||||
|
||||
#ifndef ISO_ROCKRIDGE_H
|
||||
#define ISO_ROCKRIDGE_H
|
||||
@ -13,99 +8,18 @@
|
||||
struct ecma119_write_target;
|
||||
struct ecma119_tree_node;
|
||||
|
||||
/**
|
||||
* Add a SUSP "ER" System Use Entry to identify the Rock Ridge specification.
|
||||
*
|
||||
* The "ER" System Use Entry is used to uniquely identify a specification
|
||||
* compliant with SUSP. This method adds to the given tree node "." entry
|
||||
* the "ER" corresponding to the RR protocol.
|
||||
*
|
||||
* See IEEE P1281, section 5.5 and IEEE P1282, section 4.3 for more details.
|
||||
*/
|
||||
void rrip_add_ER(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a PX System Use Entry to the given tree node and, if that node is
|
||||
* a directory, to its "." and ".." entries. The PX System Use Entry is
|
||||
* used to add POSIX file attributes, such as access permissions or user and
|
||||
* group id, to a ECMA 119 directory record.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.1 for more details.
|
||||
*/
|
||||
void rrip_add_PX(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a PN System Use Entry to the given tree node.
|
||||
* The PN System Use Entry is used to store the device number, and it's
|
||||
* mandatory if the tree node corresponds to a character or block device.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.2 for more details.
|
||||
*/
|
||||
void rrip_add_PN(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a SL System Use Entry to the given tree node. This is used to store
|
||||
* the content of a symbolic link, and is mandatory if the tree node
|
||||
* indicates a symbolic link.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.3 for more details.
|
||||
*/
|
||||
void rrip_add_SL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a NM System Use Entry to the given tree node. The purpose of this
|
||||
* System Use Entry is to store the content of an Alternate Name to support
|
||||
* POSIX-style or other names.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.4 for more details.
|
||||
*/
|
||||
void rrip_add_NM(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/*
|
||||
* The next 3 System Use Entries are used to handle Deep Directory
|
||||
* Hierarchies, i.e., hierarchies where the number of directory levels
|
||||
* exceed the eight limit of ECMA-119.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add to the given tree node a CL System Use Entry, that is used to record
|
||||
* the new location of a directory which has been relocated.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.5.1 for more details.
|
||||
*/
|
||||
void rrip_add_CL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a PL System Use Entry, used to record the location of the original
|
||||
* parent directory of a directory which has been relocated.
|
||||
*
|
||||
* This is special because it doesn't modify the susp fields of the directory
|
||||
* that gets passed to it; it modifies the susp fields of the ".." entry in
|
||||
* that directory.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.5.2 for more details.
|
||||
*/
|
||||
void rrip_add_PL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a RE System Use Entry to the given tree node. The purpose of the
|
||||
* this System Use Entry is to indicate to an RRIP-compliant receiving
|
||||
* system that the Directory Record in which an "RE" System Use Entry is
|
||||
* recorded has been relocated from another position in the original
|
||||
* Directory Hierarchy.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.5.3 for more details.
|
||||
*/
|
||||
void rrip_add_RE(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add to the given tree node a TF System Use Entry, used to record some
|
||||
* time stamps related to the file.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.6 for more details.
|
||||
*/
|
||||
void rrip_add_TF(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/* This is special because it doesn't modify the susp fields of the directory
|
||||
* that gets passed to it; it modifies the susp fields of the ".." entry in
|
||||
* that directory. */
|
||||
void rrip_add_PL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
void rrip_finalize(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
|
@ -117,8 +117,8 @@ susp_add_CE(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
try_add_CE(t, &node->susp, node->dirent_len);
|
||||
if (node->type == ECMA119_DIR) {
|
||||
try_add_CE(t, &node->info.dir.self_susp, 34);
|
||||
try_add_CE(t, &node->info.dir.parent_susp, 34);
|
||||
try_add_CE(t, &node->dir.self_susp, 34);
|
||||
try_add_CE(t, &node->dir.parent_susp, 34);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ susp_add_SP(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
SP[4] = 0xbe;
|
||||
SP[5] = 0xef;
|
||||
SP[6] = 0;
|
||||
susp_append(t, &dir->info.dir.self_susp, SP);
|
||||
susp_append(t, &dir->dir.self_susp, SP);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -155,14 +155,38 @@ static void susp_add_ST(struct ecma119_write_target *t,
|
||||
}
|
||||
#endif
|
||||
|
||||
/** See IEEE P1281 Draft Version 1.12/5.5 FIXME: this is rockridge */
|
||||
void
|
||||
rrip_add_ER(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
{
|
||||
unsigned char *ER = malloc(182);
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
ER[0] = 'E';
|
||||
ER[1] = 'R';
|
||||
ER[2] = 182;
|
||||
ER[3] = 1;
|
||||
ER[4] = 9;
|
||||
ER[5] = 72;
|
||||
ER[6] = 93;
|
||||
ER[7] = 1;
|
||||
memcpy(&ER[8], "IEEE_1282", 9);
|
||||
memcpy(&ER[17], "THE IEEE 1282 PROTOCOL PROVIDES SUPPORT FOR POSIX "
|
||||
"FILE SYSTEM SEMANTICS.", 72);
|
||||
memcpy(&ER[89], "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, "
|
||||
"PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION.", 93);
|
||||
susp_append(t, &dir->dir.self_susp, ER);
|
||||
}
|
||||
|
||||
/* calculate the location of the CE areas. Since CE areas don't need to be
|
||||
* aligned to a block boundary, we contatenate all CE areas from a single
|
||||
* directory and dump them immediately after all the directory records.
|
||||
*
|
||||
* Requires that the following be known:
|
||||
* - position of the current directory (dir->info.dir.block)
|
||||
* - length of the current directory (dir->info.dir.len)
|
||||
* - sum of the children's CE lengths (dir->info.dir.CE_len)
|
||||
* - position of the current directory (dir->block)
|
||||
* - length of the current directory (dir->dir.len)
|
||||
* - sum of the children's CE lengths (dir->dir.CE_len)
|
||||
*/
|
||||
static void
|
||||
susp_fin_1_CE(struct ecma119_write_target *t,
|
||||
@ -184,18 +208,18 @@ static void susp_fin_CE(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *dir)
|
||||
{
|
||||
int i;
|
||||
size_t CE_offset = dir->info.dir.len;
|
||||
size_t CE_offset = dir->dir.len;
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
susp_fin_1_CE(t, &dir->info.dir.self_susp, dir->info.dir.block, &CE_offset);
|
||||
susp_fin_1_CE(t, &dir->info.dir.parent_susp, dir->info.dir.block, &CE_offset);
|
||||
susp_fin_1_CE(t, &dir->dir.self_susp, dir->block, &CE_offset);
|
||||
susp_fin_1_CE(t, &dir->dir.parent_susp, dir->block, &CE_offset);
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
susp_fin_1_CE(t, &ch->susp, dir->info.dir.block, &CE_offset);
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
susp_fin_1_CE(t, &ch->susp, dir->block, &CE_offset);
|
||||
}
|
||||
assert(CE_offset == dir->info.dir.len + dir->info.dir.CE_len);
|
||||
assert(CE_offset == dir->dir.len + dir->dir.CE_len);
|
||||
}
|
||||
|
||||
void
|
||||
@ -205,13 +229,13 @@ susp_finalize(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
|
||||
assert(dir->type = ECMA119_DIR);
|
||||
|
||||
if (dir->info.dir.depth != 1) {
|
||||
if (dir->dir.depth != 1) {
|
||||
susp_fin_CE(t, dir);
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
if (dir->info.dir.children[i]->type == ECMA119_DIR)
|
||||
susp_finalize(t, dir->info.dir.children[i]);
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
if (dir->dir.children[i]->type == ECMA119_DIR)
|
||||
susp_finalize(t, dir->dir.children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,6 @@
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
/**
|
||||
* Functions and structures used for SUSP (IEEE 1281).
|
||||
*
|
||||
* Please refer to IEEE P1281 System Use Sharing Protocol, draft standard
|
||||
* version 1.12 for more details.
|
||||
/** Functions and structures used for SUSP (IEEE 1281).
|
||||
*/
|
||||
|
||||
#ifndef __ISO_SUSP
|
||||
@ -32,23 +28,13 @@ struct susp_info
|
||||
* will go in a CE area. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a CE System Use Entry to the given tree node. A "CE" is used to add
|
||||
* a continuation area, where additional System Use Entry can be written.
|
||||
* See IEEE P1281, section 5.1.
|
||||
*/
|
||||
void susp_add_CE(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/**
|
||||
* Add a SP System Use Entry to the "." entry of the directory. The SP provide
|
||||
* an identifier that the SUSP is used within the volume. The SP shall be
|
||||
* recorded in the "." entry of the root directory.
|
||||
* See IEEE P1281, section 5.3 for more details.
|
||||
*
|
||||
* this is special because it doesn't modify the susp fields of the
|
||||
* directory; it modifies the susp fields of the "." entry in the directory.
|
||||
*/
|
||||
/* these next 2 are special because they don't modify the susp fields of the
|
||||
* directory; they modify the susp fields of the
|
||||
* "." entry in the directory. */
|
||||
void susp_add_SP(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_ER(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/** Once all the directories and files are laid out, recurse through the tree
|
||||
* and finalize all SUSP CE entries. */
|
||||
|
418
libisofs/tree.c
418
libisofs/tree.c
@ -20,6 +20,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "exclude.h"
|
||||
|
||||
static void
|
||||
@ -28,352 +30,171 @@ set_default_stat(struct stat *s)
|
||||
time_t now = time(NULL);
|
||||
|
||||
memset(s, 0, sizeof(struct stat));
|
||||
s->st_mode = 0555;
|
||||
s->st_mode = 0777 | S_IFREG;
|
||||
s->st_atime = s->st_mtime = s->st_ctime = now;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_add_child(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *child)
|
||||
static struct stat
|
||||
get_attrib(const struct iso_tree_node *node)
|
||||
{
|
||||
assert( parent && child);
|
||||
|
||||
struct stat st;
|
||||
|
||||
if (node) {
|
||||
return node->attrib;
|
||||
}
|
||||
set_default_stat(&st);
|
||||
return st;
|
||||
}
|
||||
|
||||
static void
|
||||
append_node(struct iso_tree_node *parent,
|
||||
struct iso_tree_node *child)
|
||||
{
|
||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && child);
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
parent->nchildren++;
|
||||
parent->children =
|
||||
realloc(parent->children, parent->nchildren * sizeof(void*));
|
||||
parent->children[parent->nchildren-1] = child;
|
||||
child->parent = parent;
|
||||
}
|
||||
|
||||
struct iso_tree_node_dir*
|
||||
iso_tree_new_root()
|
||||
{
|
||||
struct iso_tree_node_dir *root;
|
||||
|
||||
root = calloc(1, sizeof(struct iso_tree_node_dir));
|
||||
|
||||
set_default_stat(&root->node.attrib);
|
||||
root->node.attrib.st_mode = S_IFDIR | 0777;
|
||||
root->node.type = LIBISO_NODE_DIR;
|
||||
return root;
|
||||
}
|
||||
|
||||
struct iso_tree_node*
|
||||
iso_tree_add_file(struct iso_tree_node_dir *parent, const char *path)
|
||||
iso_tree_new_root(struct iso_volume *vol)
|
||||
{
|
||||
assert(vol);
|
||||
|
||||
if (vol->root) {
|
||||
iso_tree_free(vol->root);
|
||||
}
|
||||
|
||||
vol->root = calloc(1, sizeof(struct iso_tree_node));
|
||||
vol->root->volume = vol;
|
||||
set_default_stat(&vol->root->attrib);
|
||||
vol->root->attrib.st_mode = S_IFDIR | 0777;
|
||||
vol->root->loc.type = LIBISO_NONE;
|
||||
return vol->root;
|
||||
}
|
||||
|
||||
struct iso_tree_node*
|
||||
iso_tree_add_new_file(struct iso_tree_node *parent, const char *name)
|
||||
{
|
||||
struct iso_tree_node *f = calloc(1, sizeof(struct iso_tree_node));
|
||||
|
||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && name);
|
||||
|
||||
f->volume = parent ? parent->volume : NULL;
|
||||
f->parent = parent;
|
||||
f->name = parent ? strdup(name) : NULL;
|
||||
f->attrib = get_attrib(parent);
|
||||
f->attrib.st_mode = 0777 | S_IFREG;
|
||||
f->loc.type = LIBISO_NONE;
|
||||
append_node(parent, f);
|
||||
return f;
|
||||
}
|
||||
|
||||
struct iso_tree_node*
|
||||
iso_tree_add_new_dir(struct iso_tree_node *parent, const char *name)
|
||||
{
|
||||
struct iso_tree_node *d = iso_tree_add_new_file(parent, name);
|
||||
|
||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && name);
|
||||
|
||||
d->attrib.st_mode = (d->attrib.st_mode & ~S_IFMT) | S_IFDIR;
|
||||
return d;
|
||||
}
|
||||
|
||||
struct iso_tree_node*
|
||||
iso_tree_add_node(struct iso_tree_node *parent, const char *path)
|
||||
{
|
||||
struct iso_tree_node_file *f;
|
||||
char *p;
|
||||
struct stat st;
|
||||
|
||||
assert( parent && path);
|
||||
|
||||
if (lstat(path, &st) == -1) {
|
||||
libisofs_errno = NO_FILE;
|
||||
struct iso_tree_node *ret;
|
||||
|
||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && path);
|
||||
|
||||
if (lstat(path, &st) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !S_ISREG(st.st_mode) ) {
|
||||
libisofs_errno = UNEXPECTED_FILE_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( access(path, R_OK) ) {
|
||||
libisofs_errno = NO_READ_ACCESS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f = calloc(1, sizeof(struct iso_tree_node_file));
|
||||
|
||||
/* fill fields */
|
||||
f->node.attrib = st;
|
||||
f->path = strdup(path);
|
||||
f->node.type = LIBISO_NODE_FILE;
|
||||
|
||||
|
||||
p = strdup(path); /* because basename() might modify its arg */
|
||||
f->node.name = strdup( basename(p) );
|
||||
|
||||
/* it doesn't matter if we add a file or directory since we modify
|
||||
* attrib anyway. */
|
||||
ret = iso_tree_add_new_file(parent, basename(p));
|
||||
ret->attrib = st;
|
||||
ret->loc.type = LIBISO_FILESYS;
|
||||
ret->loc.path = strdup(path);
|
||||
free(p);
|
||||
|
||||
/* add to parent (this also sets f->node->parent) */
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) f);
|
||||
|
||||
return (struct iso_tree_node*) f;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct iso_tree_node*
|
||||
iso_tree_add_symlink(struct iso_tree_node_dir *parent,
|
||||
const char *name, const char *dest)
|
||||
{
|
||||
struct iso_tree_node_symlink *link;
|
||||
|
||||
assert( parent && name && dest);
|
||||
|
||||
link = calloc(1, sizeof(struct iso_tree_node_symlink));
|
||||
|
||||
/* fill fields */
|
||||
set_default_stat(&link->node.attrib);
|
||||
link->node.attrib.st_mode |= S_IFLNK;//TODO Not needed
|
||||
link->node.name = strdup(name);
|
||||
link->node.type = LIBISO_NODE_SYMLINK;
|
||||
link->dest = strdup(dest);
|
||||
|
||||
/* add to parent (this also sets link->node->parent) */
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) link);
|
||||
|
||||
return (struct iso_tree_node*) link;
|
||||
}
|
||||
|
||||
struct iso_tree_node_dir*
|
||||
iso_tree_add_dir(struct iso_tree_node_dir *parent,
|
||||
const char *name)
|
||||
{
|
||||
struct iso_tree_node_dir *dir;
|
||||
|
||||
assert( parent && name );
|
||||
|
||||
dir = calloc(1, sizeof(struct iso_tree_node_dir));
|
||||
|
||||
dir->node.attrib = parent->node.attrib;
|
||||
dir->node.type = LIBISO_NODE_DIR;
|
||||
dir->node.name = strdup(name);
|
||||
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_name(struct iso_tree_node *node, const char *name)
|
||||
{
|
||||
free(node->name);
|
||||
node->name = strdup(name);
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_hidden(struct iso_tree_node *node, int hide_attrs)
|
||||
{
|
||||
assert(node);
|
||||
node->hide_flags = hide_attrs;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_gid(struct iso_tree_node *node, gid_t gid)
|
||||
{
|
||||
assert(node);
|
||||
node->attrib.st_gid = gid;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_uid(struct iso_tree_node *node, uid_t uid)
|
||||
{
|
||||
assert(node);
|
||||
node->attrib.st_uid = uid;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_permissions(struct iso_tree_node *node, mode_t mode)
|
||||
{
|
||||
assert(node);
|
||||
node->attrib.st_mode = (node->attrib.st_mode & S_IFMT) |
|
||||
(mode & ~S_IFMT);
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_sort_weight(struct iso_tree_node *node, int w)
|
||||
{
|
||||
assert(node);
|
||||
if ( ISO_ISDIR(node) ) {
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir;
|
||||
dir = (struct iso_tree_node_dir *) node;
|
||||
for (i=0; i < dir->nchildren; i++) {
|
||||
iso_tree_node_set_sort_weight(dir->children[i], w);
|
||||
}
|
||||
} else if ( ISO_ISREG(node) ) {
|
||||
struct iso_tree_node_file *file;
|
||||
file = (struct iso_tree_node_file *) node;
|
||||
file->sort_weight = w;
|
||||
}
|
||||
}
|
||||
|
||||
struct iso_tree_node*
|
||||
iso_tree_add_node(struct iso_tree_node_dir *parent,
|
||||
const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
struct iso_tree_node *node;
|
||||
|
||||
assert( parent && path);
|
||||
|
||||
if (lstat(path, &st) == -1) {
|
||||
libisofs_errno = NO_FILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( access(path, R_OK) ) {
|
||||
libisofs_errno = NO_READ_ACCESS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (st.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
/* regular file */
|
||||
node = iso_tree_add_file(parent, path);
|
||||
break;
|
||||
case S_IFLNK:
|
||||
/* symlink */
|
||||
{
|
||||
char dest[PATH_MAX];
|
||||
char *p;
|
||||
int n;
|
||||
|
||||
n = readlink(path, dest, PATH_MAX);
|
||||
if ( n == -1 ) {
|
||||
libisofs_errno = INTERNAL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
dest[n] = '\0';
|
||||
p = strdup(path); /* because basename() might modify its arg */
|
||||
node = iso_tree_add_symlink(parent, basename(p), dest);
|
||||
free(p);
|
||||
node->attrib = st;
|
||||
}
|
||||
break;
|
||||
case S_IFDIR:
|
||||
/* directory */
|
||||
{
|
||||
char *p;
|
||||
p = strdup(path); /* because basename() might modify its arg */
|
||||
node = (struct iso_tree_node*) iso_tree_add_dir(parent, basename(p));
|
||||
free(p);
|
||||
node->attrib = st;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
libisofs_errno = UNEXPECTED_FILE_TYPE;
|
||||
node = NULL;
|
||||
break;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_free(struct iso_tree_node *root)
|
||||
{
|
||||
if ( ISO_ISDIR(root) ) {
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir;
|
||||
dir = (struct iso_tree_node_dir *) root;
|
||||
for (i=0; i < dir->nchildren; i++) {
|
||||
iso_tree_free(dir->children[i]);
|
||||
}
|
||||
free(dir->children);
|
||||
} else if ( ISO_ISLNK(root) ) {
|
||||
struct iso_tree_node_symlink *link;
|
||||
link = (struct iso_tree_node_symlink *) root;
|
||||
free(link->dest);
|
||||
} else if ( ISO_ISREG(root) ) {
|
||||
struct iso_tree_node_file *file;
|
||||
file = (struct iso_tree_node_file *) root;
|
||||
free(file->path);
|
||||
}
|
||||
free(root->name);
|
||||
free(root);
|
||||
}
|
||||
|
||||
static void
|
||||
iso_tree_radd_dir_aux(struct iso_tree_node_dir *parent, const char *path,
|
||||
struct iso_tree_radd_dir_behavior *behavior,
|
||||
struct iso_hash_table *excludes)
|
||||
iso_tree_radd_dir (struct iso_tree_node *parent, const char *path)
|
||||
{
|
||||
struct iso_tree_node *new;
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && path);
|
||||
|
||||
new = iso_tree_add_node(parent, path);
|
||||
if (!new || !S_ISDIR(new->attrib.st_mode)) {
|
||||
return new;
|
||||
}
|
||||
|
||||
dir = opendir(path);
|
||||
if (!dir) {
|
||||
warn("couldn't open directory %s: %s\n", path, strerror(errno));
|
||||
return;
|
||||
return new;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir))) {
|
||||
char child[strlen(ent->d_name) + strlen(path) + 2];
|
||||
|
||||
if (behavior->stop_on_error & behavior->error)
|
||||
break;
|
||||
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
//TODO check if path already finished in '/'
|
||||
sprintf(child, "%s/%s", path, ent->d_name);
|
||||
|
||||
/* see if this child is excluded. */
|
||||
if (iso_exclude_lookup(excludes, child))
|
||||
if (iso_exclude_lookup(child))
|
||||
continue;
|
||||
|
||||
new = iso_tree_add_node(parent, child);
|
||||
if (!new || !ISO_ISDIR(new)) {
|
||||
if (!new)
|
||||
behavior->error = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
iso_tree_radd_dir_aux( (struct iso_tree_node_dir *) new, child,
|
||||
behavior, excludes);
|
||||
|
||||
iso_tree_radd_dir(new, child);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return;
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_radd_dir(struct iso_tree_node_dir *parent, const char *path,
|
||||
struct iso_tree_radd_dir_behavior *behavior)
|
||||
void
|
||||
iso_tree_free(struct iso_tree_node *root)
|
||||
{
|
||||
struct iso_tree_node_dir *dir;
|
||||
struct iso_hash_table table = { {0,}, 0};
|
||||
|
||||
assert ( parent && path );
|
||||
|
||||
behavior->error = 0;
|
||||
|
||||
/* initialize exclude hash_table */
|
||||
if ( behavior->excludes ) {
|
||||
char *exclude;
|
||||
int i = 0;
|
||||
while ( (exclude = behavior->excludes[i++]) ) {
|
||||
iso_exclude_add_path(&table, exclude);
|
||||
}
|
||||
size_t i;
|
||||
|
||||
for (i=0; i < root->nchildren; i++) {
|
||||
iso_tree_free(root->children[i]);
|
||||
}
|
||||
|
||||
/* recurse into dir */
|
||||
iso_tree_radd_dir_aux(parent, path, behavior, &table);
|
||||
|
||||
/* clear hashtable */
|
||||
iso_exclude_empty(&table);
|
||||
|
||||
return dir;
|
||||
free(root->name);
|
||||
free(root->children);
|
||||
free(root);
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_print(const struct iso_tree_node *root, int spaces)
|
||||
{
|
||||
size_t i;
|
||||
char sp[spaces+1];
|
||||
|
||||
memset(sp, ' ', spaces);
|
||||
sp[spaces] = '\0';
|
||||
|
||||
printf("%s%s\n", sp, root->name);
|
||||
|
||||
if ( ISO_ISDIR(root) ) {
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir;
|
||||
|
||||
dir = (struct iso_tree_node_dir *) root;
|
||||
for (i=0; i < dir->nchildren; i++) {
|
||||
iso_tree_print(dir->children[i], spaces+2);
|
||||
}
|
||||
printf("%s%sn", sp, root->name);
|
||||
for (i=0; i < root->nchildren; i++) {
|
||||
iso_tree_print(root->children[i], spaces+2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,18 +205,19 @@ iso_tree_print_verbose(const struct iso_tree_node *root,
|
||||
void *callback_data,
|
||||
int spaces)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
(ISO_ISDIR(root) ? dir : file)
|
||||
(S_ISDIR(root->attrib.st_mode) ? dir : file)
|
||||
(root, callback_data, spaces);
|
||||
|
||||
if ( ISO_ISDIR(root) ) {
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir_node;
|
||||
|
||||
dir_node = (struct iso_tree_node_dir *) root;
|
||||
for (i=0; i < dir_node->nchildren; i++) {
|
||||
iso_tree_print_verbose(dir_node->children[i], dir,
|
||||
file, callback_data, spaces+2);
|
||||
}
|
||||
for (i=0; i < root->nchildren; i++) {
|
||||
iso_tree_print_verbose(root->children[i], dir,
|
||||
file, callback_data, spaces+2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_node_set_name(struct iso_tree_node *file, const char *name)
|
||||
{
|
||||
free(file->name);
|
||||
file->name = strdup(name);
|
||||
}
|
||||
|
126
libisofs/tree.h
126
libisofs/tree.h
@ -24,31 +24,24 @@
|
||||
|
||||
#include "libisofs.h"
|
||||
|
||||
//enum file_location {
|
||||
// LIBISO_FILESYS,
|
||||
// LIBISO_PREVSESSION,
|
||||
// LIBISO_NONE /**< for files/dirs that were added with
|
||||
// * iso_tree_add_new_XXX. */
|
||||
//};
|
||||
enum file_location {
|
||||
LIBISO_FILESYS,
|
||||
LIBISO_PREVSESSION,
|
||||
LIBISO_NONE /**< for files/dirs that were added with
|
||||
* iso_tree_add_new_XXX. */
|
||||
};
|
||||
|
||||
/**
|
||||
* This tells us where to read the data from a file. Either we read from the
|
||||
* local filesystem or we just point to the block on a previous session.
|
||||
*/
|
||||
//struct iso_file_location
|
||||
//{
|
||||
// enum file_location type;
|
||||
// /* union {*/
|
||||
// char *path; /* in the current locale */
|
||||
// uint32_t block;
|
||||
// /* };*/
|
||||
//};
|
||||
|
||||
enum iso_tree_node_type {
|
||||
LIBISO_NODE_DIR,
|
||||
LIBISO_NODE_FILE,
|
||||
LIBISO_NODE_SYMLINK,
|
||||
LIBISO_NODE_BOOTCATALOG
|
||||
struct iso_file_location
|
||||
{
|
||||
enum file_location type;
|
||||
/* union {*/
|
||||
char *path; /* in the current locale */
|
||||
uint32_t block;
|
||||
/* };*/
|
||||
};
|
||||
|
||||
/**
|
||||
@ -56,61 +49,58 @@ enum iso_tree_node_type {
|
||||
*/
|
||||
struct iso_tree_node
|
||||
{
|
||||
struct iso_tree_node_dir *parent;
|
||||
struct iso_volume *volume;
|
||||
struct iso_tree_node *parent;
|
||||
char *name;
|
||||
struct stat attrib; /**< The POSIX attributes of this node as
|
||||
* documented in "man 2 stat". */
|
||||
|
||||
int hide_flags; /**< If the node is to be hidden in RR/ISO or
|
||||
* Joilet tree */
|
||||
enum iso_tree_node_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* A node in the filesystem tree that represents a regular file
|
||||
*/
|
||||
struct iso_tree_node_file
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
|
||||
char *path; /**< the path of the file on local filesystem */
|
||||
int sort_weight; /**< It sorts the order in which the file data is
|
||||
* written to the CD image. Higher weighting files
|
||||
* are written at the beginning of image */
|
||||
|
||||
/* when read from an existing ISO image, we need to store the
|
||||
* block where file contents are written, and not the path.
|
||||
* Maybe instead of a char *path we will need to go back to
|
||||
* struct iso_file_location loc;
|
||||
*/
|
||||
/* struct iso_file_location loc; */
|
||||
struct iso_file_location loc;
|
||||
/**< Only used for regular files and symbolic
|
||||
* links (ie. files for which we might have to
|
||||
* copy data). */
|
||||
};
|
||||
|
||||
/**
|
||||
* A node in the filesystem tree that represents a symbolic link
|
||||
*/
|
||||
struct iso_tree_node_symlink
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
|
||||
char *dest; /**< Destination of the link */
|
||||
};
|
||||
|
||||
/**
|
||||
* A directory on the filesystem tree
|
||||
*/
|
||||
struct iso_tree_node_dir
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
|
||||
size_t nchildren; /**< The number of children of this
|
||||
* directory (if this is a directory). */
|
||||
struct iso_tree_node **children;
|
||||
|
||||
size_t block; /**< The block at which this file will
|
||||
* reside on disk. We store this here as
|
||||
* well as in the various mangled trees
|
||||
* because many different trees might point
|
||||
* to the same file and they need to share the
|
||||
* block location. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new root directory for a volume.
|
||||
*
|
||||
* \param vol The volume for which to create a new root directory.
|
||||
*
|
||||
* \pre \p vol is non-NULL.
|
||||
* \post \p vol has a non-NULL, empty root directory with permissions 777.
|
||||
* \return \p vol's new non-NULL, empty root directory.
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_new_root(struct iso_volume *vol);
|
||||
|
||||
/**
|
||||
* Create a new, empty, file.
|
||||
*
|
||||
* \param parent The parent directory of the new file. If this is null, create
|
||||
* and return a new file node without adding it to any tree.
|
||||
* \param name The name of the new file, encoded in the current locale.
|
||||
* \pre \p name is non-NULL and it does not match any other file or directory
|
||||
* name in \p parent.
|
||||
* \post \p parent (if non-NULL) contains a file with the following properties:
|
||||
* - the file's name is \p name (converted to wchar_t)
|
||||
* - the file's POSIX permissions are the same as \p parent's
|
||||
* - the file is a regular file
|
||||
* - the file is empty
|
||||
*
|
||||
* \return \p parent's newly created file.
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_add_new_file(struct iso_tree_node *parent,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Recursively free a directory.
|
||||
*
|
||||
@ -120,12 +110,6 @@ struct iso_tree_node_dir
|
||||
*/
|
||||
void iso_tree_free(struct iso_tree_node *root);
|
||||
|
||||
/**
|
||||
* Adds a child to a directory
|
||||
*/
|
||||
void iso_tree_add_child(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *child);
|
||||
|
||||
/**
|
||||
* A function that prints verbose information about a directory.
|
||||
*
|
||||
@ -170,8 +154,6 @@ void iso_tree_print_verbose(const struct iso_tree_node *root,
|
||||
void *callback_data,
|
||||
int spaces);
|
||||
|
||||
#define ISO_ISDIR(n) (n->type == LIBISO_NODE_DIR)
|
||||
#define ISO_ISREG(n) (n->type == LIBISO_NODE_FILE)
|
||||
#define ISO_ISLNK(n) (n->type == LIBISO_NODE_SYMLINK)
|
||||
#define ISO_ISDIR(n) S_ISDIR(n->attrib.st_mode)
|
||||
|
||||
#endif /* LIBISO_TREE_H */
|
||||
|
346
libisofs/util.c
346
libisofs/util.c
@ -16,11 +16,9 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "libisofs.h"
|
||||
|
||||
/* avoids warning and names in iso, joliet and rockridge can't be > 255 bytes
|
||||
* anyway. There are at most 31 characters in iso level 1, 255 for rockridge,
|
||||
@ -37,141 +35,32 @@ int round_up(int n, int mul)
|
||||
return div_up(n, mul) * mul;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a string between charsets.
|
||||
* This assumes '\0' means end-of-string, what is not necessarily true,
|
||||
* but given there are lots of strdup around there, it will fail in other
|
||||
* places anyway...
|
||||
*/
|
||||
char *
|
||||
convert_str(const char *str, const char *icharset, const char *ocharset)
|
||||
{
|
||||
char *ret;
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
|
||||
inbytes = strlen(str);
|
||||
outbytes = (inbytes+1) * MB_LEN_MAX;
|
||||
{
|
||||
/* ensure enought space */
|
||||
char out[outbytes];
|
||||
char *src;
|
||||
size_t n;
|
||||
|
||||
iconv_t conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
printf("Can't convert from %s to %s\n", icharset, ocharset);
|
||||
return NULL;
|
||||
}
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error just return input stream */
|
||||
perror("Convert error.");
|
||||
printf("Maybe string %s is not encoded in %s\n", str, icharset);
|
||||
|
||||
iconv_close(conv);
|
||||
return strdup(str);
|
||||
}
|
||||
iconv_close(conv);
|
||||
*ret = '\0';
|
||||
|
||||
ret = strdup(out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a str in a specified codeset to WCHAR_T.
|
||||
* The result must be free() when no more needed
|
||||
*/
|
||||
static wchar_t *str2wchar(const char *str, const char *codeset)
|
||||
{
|
||||
iconv_t conv;
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
char *ret;
|
||||
char *src;
|
||||
wchar_t *wstr;
|
||||
size_t n;
|
||||
|
||||
conv = iconv_open("WCHAR_T", codeset);
|
||||
if (conv == (iconv_t)-1) {
|
||||
perror("Invalid encodings\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inbytes = strlen(str);
|
||||
outbytes = (inbytes + 1) * sizeof(wchar_t);
|
||||
|
||||
/* we are sure that numchars <= inbytes */
|
||||
wstr = malloc(outbytes);
|
||||
ret = (char *)wstr;
|
||||
src = (char *)str;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
while (n == -1) {
|
||||
|
||||
if( errno != EINVAL ) {
|
||||
/* error, should never occur */
|
||||
iconv_close(conv);
|
||||
perror("Convert error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* invalid input string charset, just log and ignore */
|
||||
printf("String %s is not encoded in %s\n", str, codeset);
|
||||
inbytes--;
|
||||
|
||||
if(!inbytes)
|
||||
break;
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
}
|
||||
iconv_close(conv);
|
||||
|
||||
*( (wchar_t *)ret )='\0';
|
||||
return wstr;
|
||||
}
|
||||
|
||||
/* this function must always return a name
|
||||
* since the caller never checks if a NULL
|
||||
* is returned. It also avoids some warnings. */
|
||||
char *str2ascii(const char *src_arg, const char *icharset)
|
||||
char *str2ascii(const char *src_arg)
|
||||
{
|
||||
wchar_t *wsrc_;
|
||||
char *ret;
|
||||
wchar_t wsrc_[NAME_BUFFER_SIZE];
|
||||
char *src = (char*)wsrc_;
|
||||
char *ret_;
|
||||
char *src;
|
||||
char *ret;
|
||||
mbstate_t state;
|
||||
iconv_t conv;
|
||||
size_t numchars;
|
||||
size_t outbytes;
|
||||
size_t inbytes;
|
||||
size_t n;
|
||||
|
||||
assert(icharset);
|
||||
|
||||
if (!src_arg)
|
||||
return NULL;
|
||||
|
||||
/* convert the string to a wide character string. Note: outbytes
|
||||
* is in fact the number of characters in the string and doesn't
|
||||
* include the last NULL character.
|
||||
*
|
||||
* For now, just assume input to be in UTF-8, we can change
|
||||
* this later.
|
||||
*/
|
||||
|
||||
wsrc_ = str2wchar(src_arg, icharset);
|
||||
|
||||
if (!wsrc_)
|
||||
* include the last NULL character. */
|
||||
memset(&state, 0, sizeof(state));
|
||||
numchars = mbsrtowcs(wsrc_, &src_arg, NAME_BUFFER_SIZE-1, &state);
|
||||
if (numchars < 0)
|
||||
return NULL;
|
||||
|
||||
src = (char *)wsrc_;
|
||||
numchars = wcslen(wsrc_);
|
||||
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
|
||||
@ -181,10 +70,8 @@ char *str2ascii(const char *src_arg, const char *icharset)
|
||||
|
||||
/* initialize iconv */
|
||||
conv = iconv_open("ASCII", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
free(wsrc_);
|
||||
if (conv == (iconv_t)-1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
while(n == -1) {
|
||||
@ -222,18 +109,17 @@ char *str2ascii(const char *src_arg, const char *icharset)
|
||||
iconv_close(conv);
|
||||
|
||||
*ret='\0';
|
||||
free(wsrc_);
|
||||
|
||||
return ret_;
|
||||
}
|
||||
|
||||
/* FIXME: C&P */
|
||||
uint16_t *str2ucs(const char *src_arg, const char *icharset)
|
||||
uint16_t *str2ucs(const char *src_arg)
|
||||
{
|
||||
wchar_t *wsrc_;
|
||||
char *src;
|
||||
wchar_t wsrc_[NAME_BUFFER_SIZE];
|
||||
char *src = (char*)wsrc_;
|
||||
char *ret_;
|
||||
char *ret;
|
||||
mbstate_t state;
|
||||
iconv_t conv;
|
||||
size_t outbytes;
|
||||
size_t numchars;
|
||||
@ -243,17 +129,13 @@ uint16_t *str2ucs(const char *src_arg, const char *icharset)
|
||||
if (!src_arg)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
|
||||
|
||||
/* convert the string to a wide character string. Note: outbytes
|
||||
* is in fact the number of characters in the string and doesn't
|
||||
* include the last NULL character.
|
||||
*/
|
||||
|
||||
wsrc_ = str2wchar(src_arg, icharset);
|
||||
if (!wsrc_)
|
||||
* include the last NULL character. */
|
||||
memset(&state, 0, sizeof(state));
|
||||
numchars = mbsrtowcs(wsrc_, &src_arg, NAME_BUFFER_SIZE-1, &state);
|
||||
if (numchars < 0)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
src = (char*)wsrc_;
|
||||
numchars = wcslen(wsrc_);
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
|
||||
@ -308,6 +190,7 @@ uint16_t *str2ucs(const char *src_arg, const char *icharset)
|
||||
return (uint16_t*)ret_;
|
||||
}
|
||||
|
||||
|
||||
static int valid_d_char(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||
@ -335,45 +218,9 @@ static int valid_p_char(char c)
|
||||
|| (c == '.') || (c == '_') || (c == '-');
|
||||
}
|
||||
|
||||
char *str2d_char(const char *str, const char *icharset) {
|
||||
char *ret;
|
||||
size_t len, i;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
ret = str2ascii(str, icharset);
|
||||
len = strlen(ret);
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
char c = toupper(ret[i]);
|
||||
ret[i] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *str2a_char(const char *str, const char *icharset) {
|
||||
char *ret;
|
||||
size_t len, i;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
ret = str2ascii(str, icharset);
|
||||
len = strlen(ret);
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
char c = toupper(ret[i]);
|
||||
ret[i] = valid_a_char(c) ? c : '_';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *iso_dirid(const char *src, int size, const char *icharset)
|
||||
static char *iso_dirid(const char *src, int size)
|
||||
{
|
||||
char *ret = str2ascii(src, icharset);
|
||||
char *ret = str2ascii(src);
|
||||
size_t len, i;
|
||||
|
||||
if (!ret)
|
||||
@ -392,46 +239,19 @@ static char *iso_dirid(const char *src, int size, const char *icharset)
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *iso_1_dirid(const char *src, const char *icharset)
|
||||
char *iso_1_dirid(const char *src)
|
||||
{
|
||||
return iso_dirid(src, 8, icharset);
|
||||
return iso_dirid(src, 8);
|
||||
}
|
||||
|
||||
char *iso_2_dirid(const char *src, const char *icharset)
|
||||
char *iso_2_dirid(const char *src)
|
||||
{
|
||||
return iso_dirid(src, 31, icharset);
|
||||
return iso_dirid(src, 31);
|
||||
}
|
||||
|
||||
char *iso_r_dirid(const char *src, const char *icharset, int flags)
|
||||
char *iso_1_fileid(const char *src_arg)
|
||||
{
|
||||
char *ret = str2ascii(src, icharset);
|
||||
size_t size, len, i;
|
||||
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
size = flags & ECMA119_37_CHAR_FILENAMES ? 37 : 31;
|
||||
|
||||
len = strlen(ret);
|
||||
if (len > size) {
|
||||
ret[size] = '\0';
|
||||
len = size;
|
||||
}
|
||||
|
||||
if (flags & ECMA119_RELAXED_FILENAMES)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
char c = toupper(ret[i]);
|
||||
ret[i] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *iso_1_fileid(const char *src_arg, const char *icharset)
|
||||
{
|
||||
char *src = str2ascii(src_arg, icharset);
|
||||
char *src = str2ascii(src_arg);
|
||||
char *dest;
|
||||
char *dot; /* Position of the last dot in the
|
||||
filename, will be used to calculate
|
||||
@ -480,9 +300,9 @@ char *iso_1_fileid(const char *src_arg, const char *icharset)
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *iso_2_fileid(const char *src_arg, const char *icharset)
|
||||
char *iso_2_fileid(const char *src_arg)
|
||||
{
|
||||
char *src = str2ascii(src_arg, icharset);
|
||||
char *src = str2ascii(src_arg);
|
||||
char *dest;
|
||||
char *dot;
|
||||
int lname, lext, lnname, lnext, pos, i;
|
||||
@ -498,7 +318,7 @@ char *iso_2_fileid(const char *src_arg, const char *icharset)
|
||||
extension, we need to calculate their new lengths (lnname and
|
||||
lnext). If the original filename is too long, we start by trimming
|
||||
the extension, but keep a minimum extension length of 3. */
|
||||
if (dot == NULL || *(dot + 1) == '\0') {
|
||||
if (dot == NULL || dot == src || *(dot + 1) == '\0') {
|
||||
lname = strlen(src);
|
||||
lnname = (lname > 30) ? 30 : lname;
|
||||
lext = lnext = 0;
|
||||
@ -540,88 +360,9 @@ char *iso_2_fileid(const char *src_arg, const char *icharset)
|
||||
}
|
||||
|
||||
char *
|
||||
iso_r_fileid(const char *src_arg, const char *icharset, int flag)
|
||||
iso_p_fileid(const char *src)
|
||||
{
|
||||
char *src = str2ascii(src_arg, icharset);
|
||||
char *dest;
|
||||
char *dot;
|
||||
int lname, lext, lnname, lnext, pos, i;
|
||||
|
||||
size_t size = flag & (1<<1) ? 37 : 33;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
dest = malloc(size+1);
|
||||
|
||||
if (flag & ECMA119_RELAXED_FILENAMES) {
|
||||
strncpy(dest, src, size);
|
||||
dest[size] = '\0'; /* ensure 37 / 33 max length */
|
||||
pos = strlen(dest);
|
||||
pos = pos < (size == 37 ? 37 : 31) ? pos : (size == 37 ? 37 : 31);
|
||||
if ( !(flag & ECMA119_OMIT_VERSION_NUMBERS) ) {
|
||||
dest[pos++] = ';';
|
||||
dest[pos++] = '1';
|
||||
}
|
||||
dest[pos] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* no relaxed filenames */
|
||||
dot = strrchr(src, '.');
|
||||
|
||||
size_t max = size == 37 ? 36 : 30;
|
||||
/* Since the maximum length can be divided freely over the name and
|
||||
extension, we need to calculate their new lengths (lnname and
|
||||
lnext). If the original filename is too long, we start by trimming
|
||||
the extension, but keep a minimum extension length of 3. */
|
||||
if (dot == NULL || *(dot + 1) == '\0') {
|
||||
lname = strlen(src);
|
||||
lnname = (lname > max) ? max : lname;
|
||||
lext = lnext = 0;
|
||||
} else {
|
||||
lext = strlen(dot + 1);
|
||||
lname = strlen(src) - lext - 1;
|
||||
lnext = (strlen(src) > max + 1 && lext > 3)
|
||||
? (lname < max - 3 ? max - lname : 3) : lext;
|
||||
lnname = (strlen(src) > max +1) ? max - lnext : lname;
|
||||
}
|
||||
|
||||
if (lnname == 0 && lnext == 0) {
|
||||
free(src);
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
/* Convert up to lnname characters of the filename. */
|
||||
for (i = 0; i < lnname; i++) {
|
||||
char c = toupper(src[i]);
|
||||
|
||||
dest[pos++] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
dest[pos++] = '.';
|
||||
/* Convert up to lnext characters of the extension, if any. */
|
||||
for (i = 0; i < lnext; i++) {
|
||||
char c = toupper(src[lname + 1 + i]);
|
||||
|
||||
dest[pos++] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
if ( !(flag & ECMA119_OMIT_VERSION_NUMBERS) ) {
|
||||
dest[pos++] = ';';
|
||||
dest[pos++] = '1';
|
||||
}
|
||||
dest[pos] = '\0';
|
||||
dest = (char *)realloc(dest, pos + 1);
|
||||
|
||||
free(src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *
|
||||
iso_p_fileid(const char *src, const char *icharset)
|
||||
{
|
||||
char *ret = str2ascii(src, icharset);
|
||||
char *ret = str2ascii(src);
|
||||
size_t i, len;
|
||||
|
||||
if (!ret)
|
||||
@ -636,9 +377,9 @@ iso_p_fileid(const char *src, const char *icharset)
|
||||
}
|
||||
|
||||
uint16_t *
|
||||
iso_j_id(const char *src_arg, const char *icharset)
|
||||
iso_j_id(const char *src_arg)
|
||||
{
|
||||
uint16_t *j_str = str2ucs(src_arg, icharset);
|
||||
uint16_t *j_str = str2ucs(src_arg);
|
||||
size_t len = ucslen(j_str);
|
||||
size_t n;
|
||||
|
||||
@ -679,6 +420,7 @@ void iso_bb(uint8_t *buf, uint32_t num, int bytes)
|
||||
iso_msb(buf+bytes, num, bytes);
|
||||
}
|
||||
|
||||
|
||||
void iso_datetime_7(unsigned char *buf, time_t t)
|
||||
{
|
||||
static int tzsetup = 0;
|
||||
@ -699,12 +441,12 @@ void iso_datetime_7(unsigned char *buf, time_t t)
|
||||
buf[4] = tm.tm_min;
|
||||
buf[5] = tm.tm_sec;
|
||||
#ifdef HAVE_TM_GMTOFF
|
||||
tzoffset = tm.tm_gmtoff / 60 / 15;
|
||||
tzoffset = -tm.tm_gmtoff / 60 / 15;
|
||||
#else
|
||||
tzoffset = timezone / 60 / 15;
|
||||
tzoffset = -timezone / 60 / 15;
|
||||
#endif
|
||||
if (tzoffset > 52)
|
||||
tzoffset -= 101;
|
||||
if (tzoffset < -48)
|
||||
tzoffset += 101;
|
||||
buf[6] = tzoffset;
|
||||
}
|
||||
|
||||
@ -748,12 +490,12 @@ void iso_datetime_17(unsigned char *buf, time_t t)
|
||||
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
|
||||
memcpy(&buf[14], "00", 2);
|
||||
#ifdef HAVE_TM_GMTOFF
|
||||
tzoffset = tm.tm_gmtoff / 60 / 15;
|
||||
tzoffset = -tm.tm_gmtoff / 60 / 15;
|
||||
#else
|
||||
tzoffset = timezone / 60 / 15;
|
||||
tzoffset = -timezone / 60 / 15;
|
||||
#endif
|
||||
if (tzoffset > 52)
|
||||
tzoffset -= 101;
|
||||
if (tzoffset < -48)
|
||||
tzoffset += 101;
|
||||
buf[16] = tzoffset;
|
||||
}
|
||||
}
|
||||
|
@ -30,29 +30,19 @@ extern inline int round_up(int n, int mul)
|
||||
return div_up(n, mul) * mul;
|
||||
}
|
||||
|
||||
char *convert_str(const char *str, const char *icharset, const char *ocharset);
|
||||
|
||||
wchar_t *towcs(const char *);
|
||||
char *str2ascii(const char*, const char *);
|
||||
uint16_t *str2ucs(const char *, const char *);
|
||||
|
||||
char *str2d_char(const char*, const char *);
|
||||
char *str2a_char(const char*, const char *);
|
||||
char *str2ascii(const char*);
|
||||
uint16_t *str2ucs(const char*);
|
||||
|
||||
/**
|
||||
* Create a level 1 directory identifier.
|
||||
*/
|
||||
char *iso_1_dirid(const char *src, const char *);
|
||||
char *iso_1_dirid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a level 2 directory identifier.
|
||||
*/
|
||||
char *iso_2_dirid(const char *src, const char *);
|
||||
|
||||
/**
|
||||
* Create a directory identifier with relaxed constraints
|
||||
*/
|
||||
char *iso_r_dirid(const char *src, const char *icharset, int flags);
|
||||
char *iso_2_dirid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a level 1 file identifier that consists of a name, extension and
|
||||
@ -61,7 +51,7 @@ char *iso_r_dirid(const char *src, const char *icharset, int flags);
|
||||
* length 3, followed by a separator (;) and a version number (digit 1).
|
||||
* @return NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
char *iso_1_fileid(const char *src, const char *);
|
||||
char *iso_1_fileid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a level 2 file identifier that consists of a name, extension and
|
||||
@ -70,12 +60,7 @@ char *iso_1_fileid(const char *src, const char *);
|
||||
* followed by a separator (;) and a version number (digit 1).
|
||||
* @return NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
char *iso_2_fileid(const char *src, const char *);
|
||||
|
||||
/**
|
||||
* Create a file identifier with relaxed constraints.
|
||||
*/
|
||||
char *iso_r_fileid(const char *src, const char *icharset, int flags);
|
||||
char *iso_2_fileid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a Joliet file or directory identifier that consists of a name,
|
||||
@ -88,7 +73,7 @@ char *iso_r_fileid(const char *src, const char *icharset, int flags);
|
||||
* @param size will be set to the size (in bytes) of the identifier.
|
||||
* @return NULL if the original name and extension both are of length 0 or the conversion from the current codeset to UCS-2BE is not available.
|
||||
*/
|
||||
uint16_t *iso_j_id(const char *src, const char *icharset);
|
||||
uint16_t *iso_j_id(const char *src);
|
||||
|
||||
/**
|
||||
* FIXME: what are the requirements for these next two? Is this for RR?
|
||||
@ -97,7 +82,7 @@ uint16_t *iso_j_id(const char *src, const char *icharset);
|
||||
* The resulting file name will not exceed 250 characters.
|
||||
* @return NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
char *iso_p_fileid(const char *src, const char *);
|
||||
char *iso_p_fileid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a POSIX portable directory name.
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
struct iso_volset*
|
||||
iso_volset_new(struct iso_volume *vol, const char *id)
|
||||
@ -21,6 +20,8 @@ iso_volset_new(struct iso_volume *vol, const char *id)
|
||||
volset->volume = malloc(sizeof(void *));
|
||||
volset->volume[0] = vol;
|
||||
volset->volset_id = strdup(id);
|
||||
|
||||
vol->refcount++;
|
||||
return volset;
|
||||
}
|
||||
|
||||
@ -34,7 +35,6 @@ iso_volset_free(struct iso_volset *volset)
|
||||
}
|
||||
free(volset->volume);
|
||||
free(volset->volset_id);
|
||||
free(volset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,14 +53,14 @@ struct iso_volume*
|
||||
iso_volume_new_with_root(const char *volume_id,
|
||||
const char *publisher_id,
|
||||
const char *data_preparer_id,
|
||||
struct iso_tree_node_dir *root)
|
||||
struct iso_tree_node *root)
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = calloc(1, sizeof(struct iso_volume));
|
||||
volume->refcount = 1;
|
||||
|
||||
volume->root = root ? root : iso_tree_new_root();
|
||||
volume->root = root ? root : iso_tree_new_root(volume);
|
||||
|
||||
if (volume_id != NULL)
|
||||
volume->volume_id = strdup(volume_id);
|
||||
@ -76,101 +76,39 @@ iso_volume_free(struct iso_volume *volume)
|
||||
{
|
||||
/* Only free if no references are in use. */
|
||||
if (--volume->refcount < 1) {
|
||||
iso_tree_free( (struct iso_tree_node*) volume->root);
|
||||
iso_tree_free(volume->root);
|
||||
|
||||
free(volume->volume_id);
|
||||
free(volume->publisher_id);
|
||||
free(volume->data_preparer_id);
|
||||
free(volume->system_id);
|
||||
free(volume->application_id);
|
||||
free(volume->copyright_file_id);
|
||||
free(volume->abstract_file_id);
|
||||
free(volume->biblio_file_id);
|
||||
if (volume->bootcat)
|
||||
el_torito_boot_catalog_free(volume->bootcat);
|
||||
|
||||
free(volume);
|
||||
}
|
||||
}
|
||||
|
||||
struct iso_tree_node_dir *
|
||||
struct iso_tree_node *
|
||||
iso_volume_get_root(const struct iso_volume *volume)
|
||||
{
|
||||
return volume->root;
|
||||
}
|
||||
|
||||
void iso_volume_set_volume_id(struct iso_volume *volume,
|
||||
const char *volume_id)
|
||||
{
|
||||
free(volume->volume_id);
|
||||
volume->volume_id = strdup(volume_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_publisher_id(struct iso_volume *volume,
|
||||
const char *publisher_id)
|
||||
{
|
||||
free(volume->publisher_id);
|
||||
volume->publisher_id = strdup(publisher_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_data_preparer_id(struct iso_volume *volume,
|
||||
const char *data_preparer_id)
|
||||
{
|
||||
free(volume->data_preparer_id);
|
||||
volume->data_preparer_id = strdup(data_preparer_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_system_id(struct iso_volume *volume,
|
||||
const char *system_id)
|
||||
{
|
||||
free(volume->system_id);
|
||||
volume->system_id = strdup(system_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_application_id(struct iso_volume *volume,
|
||||
const char *application_id)
|
||||
{
|
||||
free(volume->application_id);
|
||||
volume->application_id = strdup(application_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_copyright_file_id(struct iso_volume *volume,
|
||||
const char *copyright_file_id)
|
||||
{
|
||||
free(volume->copyright_file_id);
|
||||
volume->copyright_file_id = strdup(copyright_file_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_abstract_file_id(struct iso_volume *volume,
|
||||
const char *abstract_file_id)
|
||||
{
|
||||
free(volume->abstract_file_id);
|
||||
volume->abstract_file_id = strdup(abstract_file_id);
|
||||
}
|
||||
|
||||
void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
||||
const char *biblio_file_id)
|
||||
{
|
||||
free(volume->biblio_file_id);
|
||||
volume->biblio_file_id = strdup(biblio_file_id);
|
||||
}
|
||||
|
||||
struct iso_tree_node *
|
||||
iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
||||
{
|
||||
struct iso_tree_node *node;
|
||||
struct iso_tree_node_dir *dir;
|
||||
char *ptr, *brk_info, *component;
|
||||
|
||||
/* get the first child at the root of the volume
|
||||
* that is "/" */
|
||||
dir = iso_volume_get_root(volume);
|
||||
node = (struct iso_tree_node *)dir;
|
||||
if (!strcmp(path, "/"))
|
||||
node=iso_volume_get_root(volume);
|
||||
if (!strcmp (path, "/"))
|
||||
return node;
|
||||
|
||||
if (!dir->nchildren)
|
||||
if (!node->nchildren)
|
||||
return NULL;
|
||||
|
||||
/* the name of the nodes is in wide characters so first convert path
|
||||
* into wide characters. */
|
||||
ptr = strdup(path);
|
||||
|
||||
/* get the first component of the path */
|
||||
@ -178,18 +116,12 @@ iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
||||
while (component) {
|
||||
size_t max;
|
||||
size_t i;
|
||||
|
||||
if ( !ISO_ISDIR(node) ) {
|
||||
node=NULL;
|
||||
break;
|
||||
}
|
||||
dir = (struct iso_tree_node_dir *)node;
|
||||
|
||||
/* search among all the children of this directory if this path component exists */
|
||||
max=dir->nchildren;
|
||||
max=node->nchildren;
|
||||
for (i=0; i < max; i++) {
|
||||
if (!strcmp(component, dir->children[i]->name)) {
|
||||
node=dir->children[i];
|
||||
if (!strcmp(component, node->children[i]->name)) {
|
||||
node=node->children[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -204,55 +136,54 @@ iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
||||
}
|
||||
|
||||
free(ptr);
|
||||
return node;
|
||||
}
|
||||
|
||||
struct iso_tree_node *
|
||||
iso_tree_volume_add_path(struct iso_volume *volume,
|
||||
const char *disc_path,
|
||||
const char *path)
|
||||
{
|
||||
char *tmp;
|
||||
struct iso_tree_node *node;
|
||||
struct iso_tree_node *parent_node;
|
||||
|
||||
tmp=strdup(disc_path);
|
||||
parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
||||
free(tmp);
|
||||
|
||||
if (!parent_node)
|
||||
return NULL;
|
||||
|
||||
node = iso_tree_radd_dir(parent_node, path);
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
tmp=strdup(disc_path);
|
||||
iso_tree_node_set_name(node, basename(tmp));
|
||||
free(tmp);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
//struct iso_tree_node *
|
||||
//iso_tree_volume_add_path(struct iso_volume *volume,
|
||||
// const char *disc_path,
|
||||
// const char *path)
|
||||
//{
|
||||
// char *tmp;
|
||||
// struct iso_tree_node *node;
|
||||
// struct iso_tree_node *parent_node;
|
||||
//
|
||||
// tmp=strdup(disc_path);
|
||||
// parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
||||
// free(tmp);
|
||||
//
|
||||
// if (!parent_node)
|
||||
// return NULL;
|
||||
//
|
||||
// node = iso_tree_radd_dir(parent_node, path);
|
||||
// if (!node)
|
||||
// return NULL;
|
||||
//
|
||||
// tmp=strdup(disc_path);
|
||||
// iso_tree_node_set_name(node, basename(tmp));
|
||||
// free(tmp);
|
||||
//
|
||||
// return node;
|
||||
//}
|
||||
//
|
||||
//struct iso_tree_node *
|
||||
//iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
||||
// const char *disc_path)
|
||||
//{
|
||||
// char *tmp;
|
||||
// struct iso_tree_node *node;
|
||||
// struct iso_tree_node *parent_node;
|
||||
//
|
||||
// tmp=strdup(disc_path);
|
||||
// parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
||||
// free(tmp);
|
||||
//
|
||||
// if (!parent_node)
|
||||
// return NULL;
|
||||
//
|
||||
// tmp=strdup(disc_path);
|
||||
// node = iso_tree_add_new_dir(parent_node, basename(tmp));
|
||||
// free(tmp);
|
||||
//
|
||||
// return node;
|
||||
//}
|
||||
struct iso_tree_node *
|
||||
iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
||||
const char *disc_path)
|
||||
{
|
||||
char *tmp;
|
||||
struct iso_tree_node *node;
|
||||
struct iso_tree_node *parent_node;
|
||||
|
||||
tmp=strdup(disc_path);
|
||||
parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
||||
free(tmp);
|
||||
|
||||
if (!parent_node)
|
||||
return NULL;
|
||||
|
||||
tmp=strdup(disc_path);
|
||||
node = iso_tree_add_new_dir(parent_node, basename(tmp));
|
||||
free(tmp);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -18,20 +18,12 @@ struct iso_volume
|
||||
int refcount; /**< Number of used references to this
|
||||
volume. */
|
||||
|
||||
struct iso_tree_node_dir *root; /**< Root of the directory tree for the
|
||||
struct iso_tree_node *root; /**< Root of the directory tree for the
|
||||
volume. */
|
||||
|
||||
char *volume_id; /**< Volume identifier. */
|
||||
char *publisher_id; /**< Volume publisher. */
|
||||
char *data_preparer_id; /**< Volume data preparer. */
|
||||
|
||||
char *system_id; /**< Volume system identifier. */
|
||||
char *application_id; /**< Volume application id */
|
||||
char *copyright_file_id;
|
||||
char *abstract_file_id;
|
||||
char *biblio_file_id;
|
||||
|
||||
struct el_torito_boot_catalog *bootcat; /**< El-Torito boot catalog */
|
||||
};
|
||||
|
||||
/**
|
||||
|
33
test.sh
33
test.sh
@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
TEST_ROOT=/tmp/libisofs_test
|
||||
|
||||
rm -rf $TEST_ROOT
|
||||
|
||||
#create test folders
|
||||
mkdir -p $TEST_ROOT
|
||||
mkdir -p $TEST_ROOT/dir1/dir11
|
||||
chmod 755 $TEST_ROOT/dir1
|
||||
chmod 755 $TEST_ROOT/dir1/dir11
|
||||
|
||||
touch $TEST_ROOT/dir1/dir11/a
|
||||
echo "This file is to check correct file permissions. set them to 754" > $TEST_ROOT/dir1/permtest
|
||||
chmod 754 $TEST_ROOT/dir1/permtest
|
||||
|
||||
mkdir -p $TEST_ROOT/dir2
|
||||
ln -s $TEST_ROOT/dir1 "$TEST_ROOT/link to dir1"
|
||||
|
||||
echo "README file" > $TEST_ROOT/README
|
||||
chmod 555 $TEST_ROOT/README
|
||||
ln -s $TEST_ROOT/README "$TEST_ROOT/link to readme"
|
||||
|
||||
echo "No read file" > $TEST_ROOT/no_read
|
||||
chmod 000 $TEST_ROOT/no_read
|
||||
|
||||
if ! make check
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test/test
|
||||
|
42
test/iso.c
42
test/iso.c
@ -20,7 +20,7 @@
|
||||
|
||||
#define SECSIZE 2048
|
||||
|
||||
const char * const optstring = "JRL:b:h";
|
||||
const char * const optstring = "JRL:h";
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
@ -36,7 +36,6 @@ void help()
|
||||
" -J Add Joliet support\n"
|
||||
" -R Add Rock Ridge support\n"
|
||||
" -L <num> Set the ISO level (1 or 2)\n"
|
||||
" -b file Specifies a boot image to add to image\n"
|
||||
" -h Print this message\n"
|
||||
);
|
||||
}
|
||||
@ -45,14 +44,12 @@ int main(int argc, char **argv)
|
||||
{
|
||||
struct iso_volset *volset;
|
||||
struct iso_volume *volume;
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *root;
|
||||
struct burn_source *src;
|
||||
unsigned char buf[2048];
|
||||
FILE *fd;
|
||||
int c;
|
||||
struct iso_tree_radd_dir_behavior behav = {0,0,0};
|
||||
int level=1, flags=0;
|
||||
char *boot_img = NULL;
|
||||
|
||||
while ((c = getopt(argc, argv, optstring)) != -1) {
|
||||
switch(c) {
|
||||
@ -70,9 +67,6 @@ int main(int argc, char **argv)
|
||||
case 'L':
|
||||
level = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
boot_img = optarg;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
exit(1);
|
||||
@ -95,42 +89,14 @@ int main(int argc, char **argv)
|
||||
err(1, "error opening output file");
|
||||
}
|
||||
|
||||
root = iso_tree_new_root();
|
||||
iso_tree_radd_dir(root, argv[optind], &behav);
|
||||
root = iso_tree_radd_dir(NULL, argv[optind]);
|
||||
if (!root) {
|
||||
err(1, "error opening input directory");
|
||||
}
|
||||
volume = iso_volume_new_with_root( "VOLID", "PUBID", "PREPID", root );
|
||||
|
||||
if ( boot_img ) {
|
||||
/* adds El-Torito boot info. Tunned for isolinux */
|
||||
struct iso_tree_node_dir *boot = (struct iso_tree_node_dir *)
|
||||
iso_tree_volume_path_to_node(volume, "isolinux");
|
||||
struct iso_tree_node *img = iso_tree_volume_path_to_node(volume, boot_img);
|
||||
if (!img) {
|
||||
err(1, "boot image patch is not valid");
|
||||
}
|
||||
struct el_torito_boot_image *bootimg =
|
||||
iso_volume_create_boot_catalog(volume, img, ELTORITO_NO_EMUL,
|
||||
boot, "boot.cat");
|
||||
el_torito_set_load_size(bootimg, 4);
|
||||
el_torito_set_write_boot_info(bootimg);
|
||||
}
|
||||
|
||||
volset = iso_volset_new( volume, "VOLSETID" );
|
||||
|
||||
/* some tests */
|
||||
iso_volume_set_application_id(volume, "Libburnia");
|
||||
iso_volume_set_copyright_file_id(volume, "LICENSE");
|
||||
|
||||
int constraints = ECMA119_OMIT_VERSION_NUMBERS |
|
||||
ECMA119_37_CHAR_FILENAMES | ECMA119_NO_DIR_REALOCATION |
|
||||
ECMA119_RELAXED_FILENAMES;
|
||||
|
||||
struct ecma119_source_opts opts = {0, level, flags, constraints, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, "UTF-8", "UTF-8"};
|
||||
|
||||
src = iso_source_new_ecma119(volset, &opts);
|
||||
src = iso_source_new_ecma119(volset, 0, level, flags);
|
||||
|
||||
while (src->read(src, buf, 2048) == 2048) {
|
||||
fwrite(buf, 1, 2048, fd);
|
||||
|
28
test/test.c
28
test/test.c
@ -1,28 +0,0 @@
|
||||
#include "test.h"
|
||||
|
||||
static void create_test_suite()
|
||||
{
|
||||
add_util_suite();
|
||||
add_tree_suite();
|
||||
add_exclude_suite();
|
||||
add_file_hashtable_suite();
|
||||
add_ecma119_tree_suite();
|
||||
add_volume_suite();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite pSuite = NULL;
|
||||
|
||||
/* initialize the CUnit test registry */
|
||||
if (CUE_SUCCESS != CU_initialize_registry())
|
||||
return CU_get_error();
|
||||
|
||||
create_test_suite();
|
||||
|
||||
/* Run all tests using the console interface */
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
24
test/test.h
24
test/test.h
@ -1,24 +0,0 @@
|
||||
#ifndef TEST_H_
|
||||
#define TEST_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
#include "libisofs.h"
|
||||
|
||||
void add_tree_suite();
|
||||
|
||||
void add_exclude_suite();
|
||||
|
||||
void add_file_hashtable_suite();
|
||||
|
||||
void add_util_suite();
|
||||
|
||||
void add_ecma119_tree_suite();
|
||||
|
||||
void add_volume_suite();
|
||||
|
||||
#endif /*TEST_H_*/
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Unit test for ecma119_tree.h
|
||||
*/
|
||||
//FIXME not implemented yet!!
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "tree.h"
|
||||
#include "test.h"
|
||||
//#include "ecma119_tree.h"
|
||||
|
||||
/*
|
||||
* Also including C file, testing internal functions
|
||||
*/
|
||||
//#include "ecma119_tree.c"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void test_calc_dirent_len()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void add_ecma119_tree_suite()
|
||||
{
|
||||
CU_pSuite pSuite = CU_add_suite("Ecma119TreeSuite", NULL, NULL);
|
||||
|
||||
//CU_add_test(pSuite, "test of calc_dirent_len()", test_calc_dirent_len);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Unit test for exclude.h
|
||||
*/
|
||||
|
||||
|
||||
#include "exclude.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void test_exclude()
|
||||
{
|
||||
struct iso_hash_table table = { {0,}, 0};
|
||||
CU_ASSERT_FALSE( iso_exclude_lookup(&table, "/dir") );
|
||||
CU_ASSERT_FALSE( iso_exclude_lookup(&table, "/otherdir") );
|
||||
iso_exclude_add_path(&table, "/otherdir");
|
||||
CU_ASSERT_TRUE( iso_exclude_lookup(&table, "/otherdir") );
|
||||
CU_ASSERT_FALSE( iso_exclude_lookup(&table, "/dir") );
|
||||
iso_exclude_add_path(&table, "/dir");
|
||||
CU_ASSERT_TRUE( iso_exclude_lookup(&table, "/otherdir") );
|
||||
CU_ASSERT_TRUE( iso_exclude_lookup(&table, "/dir") );
|
||||
iso_exclude_empty(&table);
|
||||
CU_ASSERT_FALSE( iso_exclude_lookup(&table, "/dir") );
|
||||
CU_ASSERT_FALSE( iso_exclude_lookup(&table, "/otherdir") );
|
||||
}
|
||||
|
||||
void add_exclude_suite()
|
||||
{
|
||||
CU_pSuite pSuite = CU_add_suite("ExcludeSuite", NULL, NULL);
|
||||
|
||||
CU_add_test(pSuite, "test of exclude", test_exclude);
|
||||
}
|
@ -1,248 +0,0 @@
|
||||
/*
|
||||
* Unit test for file.h
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
#include "file.h"
|
||||
#include "tree.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void test_iso_file_new()
|
||||
{
|
||||
struct iso_tree_node_file *file;
|
||||
struct iso_file *iso;
|
||||
|
||||
file = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file->node.name = "fileName";
|
||||
file->node.attrib.st_size = 12;
|
||||
file->node.attrib.st_dev = 15;
|
||||
file->node.attrib.st_ino = 204;
|
||||
file->path = "/tmp/filename";
|
||||
file->sort_weight = 1;
|
||||
|
||||
iso = iso_file_new(file);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(iso);
|
||||
CU_ASSERT_STRING_EQUAL(iso->path, "/tmp/filename");
|
||||
CU_ASSERT_EQUAL(iso->size, 12);
|
||||
CU_ASSERT_EQUAL(iso->ino, 0);
|
||||
CU_ASSERT_EQUAL(iso->nlink, 1);
|
||||
CU_ASSERT_EQUAL(iso->sort_weight, 1);
|
||||
CU_ASSERT_EQUAL(iso->real_dev, 15);
|
||||
CU_ASSERT_EQUAL(iso->real_ino, 204);
|
||||
}
|
||||
|
||||
static void test_add_lookup()
|
||||
{
|
||||
struct iso_file_table *table;
|
||||
struct iso_tree_node_file *file1;
|
||||
struct iso_tree_node_file *file2;
|
||||
struct iso_file *iso1;
|
||||
struct iso_file *iso2;
|
||||
struct iso_file *iso3;
|
||||
int r;
|
||||
|
||||
table = iso_file_table_new(1);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL( table );
|
||||
CU_ASSERT_TRUE( table->cache_inodes );
|
||||
CU_ASSERT_EQUAL(table->count, 0);
|
||||
|
||||
file1 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file1->node.name = "fileName";
|
||||
file1->node.attrib.st_dev = 15;
|
||||
file1->node.attrib.st_ino = 204;
|
||||
file1->path = "/tmp/filename";
|
||||
|
||||
iso1 = iso_file_new(file1);
|
||||
|
||||
r = iso_file_table_add_file(table, iso1);
|
||||
CU_ASSERT_EQUAL(r, 1);
|
||||
CU_ASSERT_EQUAL(table->count, 1);
|
||||
|
||||
iso2 = iso_file_table_lookup(table, file1);
|
||||
CU_ASSERT_PTR_NOT_NULL(iso2);
|
||||
CU_ASSERT_PTR_EQUAL(iso2, iso1);
|
||||
|
||||
file2 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file2->node.name = "fileName2";
|
||||
file2->node.attrib.st_dev = 152;
|
||||
file2->node.attrib.st_ino = 2042;
|
||||
file2->path = "/tmp/filename2";
|
||||
|
||||
iso3 = iso_file_new(file2);
|
||||
r = iso_file_table_add_file(table, iso3);
|
||||
CU_ASSERT_EQUAL(r, 1);
|
||||
CU_ASSERT_EQUAL(table->count, 2);
|
||||
|
||||
/* treat to add the same file again */
|
||||
r = iso_file_table_add_file(table, iso3);
|
||||
CU_ASSERT_EQUAL(r, 0);
|
||||
CU_ASSERT_EQUAL(table->count, 2);
|
||||
|
||||
iso2 = iso_file_table_lookup(table, file1);
|
||||
CU_ASSERT_PTR_NOT_NULL(iso2);
|
||||
CU_ASSERT_PTR_EQUAL(iso2, iso1);
|
||||
|
||||
iso2 = iso_file_table_lookup(table, file2);
|
||||
CU_ASSERT_PTR_NOT_NULL(iso2);
|
||||
CU_ASSERT_PTR_EQUAL(iso2, iso3);
|
||||
|
||||
iso3 = iso_file_new(file2);
|
||||
r = iso_file_table_add_file(table, iso3);
|
||||
CU_ASSERT_EQUAL(r, 0);
|
||||
CU_ASSERT_EQUAL(table->count, 2);
|
||||
|
||||
iso_file_table_clear(table);
|
||||
CU_ASSERT_EQUAL(table->count, 0);
|
||||
|
||||
iso2 = iso_file_table_lookup(table, file2);
|
||||
CU_ASSERT_PTR_NULL(iso2);
|
||||
|
||||
free( file1 );
|
||||
free( file2 );
|
||||
free( table );
|
||||
}
|
||||
|
||||
static void test_cache_inodes()
|
||||
{
|
||||
struct iso_file_table *table;
|
||||
struct iso_tree_node_file *file1;
|
||||
struct iso_tree_node_file *file2;
|
||||
struct iso_file *iso1;
|
||||
struct iso_file *iso2;
|
||||
struct iso_file *iso3;
|
||||
int r;
|
||||
|
||||
table = iso_file_table_new(1);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL( table );
|
||||
CU_ASSERT_TRUE( table->cache_inodes );
|
||||
CU_ASSERT_EQUAL(table->count, 0);
|
||||
|
||||
file1 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file1->node.name = "fileName";
|
||||
file1->node.attrib.st_dev = 15;
|
||||
file1->node.attrib.st_ino = 204;
|
||||
file1->path = "/tmp/filename";
|
||||
|
||||
iso1 = iso_file_new(file1);
|
||||
|
||||
r = iso_file_table_add_file(table, iso1);
|
||||
CU_ASSERT_EQUAL(r, 1);
|
||||
|
||||
/* another file, different but with the same inode id */
|
||||
file2 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file2->node.name = "another file";
|
||||
file2->node.attrib.st_dev = 15;
|
||||
file2->node.attrib.st_ino = 204;
|
||||
file2->path = "/tmp/another";
|
||||
iso2 = iso_file_new(file2);
|
||||
|
||||
/* ensure it's not added again... */
|
||||
r = iso_file_table_add_file(table, iso2);
|
||||
CU_ASSERT_EQUAL(r, 0);
|
||||
|
||||
/* ...and the lookup returns the first */
|
||||
iso3 = iso_file_table_lookup(table, file2);
|
||||
CU_ASSERT_PTR_EQUAL(iso1, iso3);
|
||||
|
||||
free(iso2);
|
||||
free(file2);
|
||||
|
||||
/* and now a file with same inode but different device */
|
||||
file2 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file2->node.name = "different file";
|
||||
file2->node.attrib.st_dev = 16; /* different dev id */
|
||||
file2->node.attrib.st_ino = 204;
|
||||
file2->path = "/tmp/different";
|
||||
iso2 = iso_file_new(file2);
|
||||
|
||||
r = iso_file_table_add_file(table, iso2);
|
||||
CU_ASSERT_EQUAL(r, 1);
|
||||
iso3 = iso_file_table_lookup(table, file2);
|
||||
CU_ASSERT_PTR_NOT_EQUAL(iso3, iso1);
|
||||
CU_ASSERT_PTR_EQUAL(iso3, iso2);
|
||||
|
||||
iso_file_table_clear(table);
|
||||
free( file1 );
|
||||
free( file2 );
|
||||
free( table );
|
||||
}
|
||||
|
||||
static void test_no_cache_inodes()
|
||||
{
|
||||
struct iso_file_table *table;
|
||||
struct iso_tree_node_file *file1;
|
||||
struct iso_tree_node_file *file2;
|
||||
struct iso_tree_node_file *file3;
|
||||
struct iso_file *iso1;
|
||||
struct iso_file *iso2;
|
||||
struct iso_file *iso3;
|
||||
int r;
|
||||
|
||||
table = iso_file_table_new(0);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL( table );
|
||||
CU_ASSERT_FALSE( table->cache_inodes );
|
||||
CU_ASSERT_EQUAL(table->count, 0);
|
||||
|
||||
file1 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file1->node.name = "fileName";
|
||||
file1->node.attrib.st_dev = 15;
|
||||
file1->node.attrib.st_ino = 204;
|
||||
file1->path = "/tmp/filename";
|
||||
|
||||
iso1 = iso_file_new(file1);
|
||||
|
||||
r = iso_file_table_add_file(table, iso1);
|
||||
CU_ASSERT_EQUAL(r, 1);
|
||||
|
||||
/* another file, different but with the same inode id */
|
||||
file2 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file2->node.name = "another file";
|
||||
file2->node.attrib.st_dev = 15;
|
||||
file2->node.attrib.st_ino = 204;
|
||||
file2->path = "/tmp/another";
|
||||
iso2 = iso_file_new(file2);
|
||||
|
||||
/* ensure is added */
|
||||
r = iso_file_table_add_file(table, iso2);
|
||||
CU_ASSERT_EQUAL(r, 1);
|
||||
|
||||
iso3 = iso_file_table_lookup(table, file2);
|
||||
CU_ASSERT_PTR_EQUAL(iso3, iso2);
|
||||
|
||||
/* and now a file with same inode and path */
|
||||
file3 = calloc(1, sizeof(struct iso_tree_node_file) );
|
||||
file3->node.name = "different file";
|
||||
file3->node.attrib.st_dev = 15;
|
||||
file3->node.attrib.st_ino = 204;
|
||||
file3->path = "/tmp/filename";
|
||||
iso3 = iso_file_new(file3);
|
||||
|
||||
r = iso_file_table_add_file(table, iso3);
|
||||
CU_ASSERT_EQUAL(r, 0);
|
||||
iso3 = iso_file_table_lookup(table, file3);
|
||||
CU_ASSERT_PTR_EQUAL(iso3, iso1);
|
||||
|
||||
iso_file_table_clear(table);
|
||||
free(file1);
|
||||
free(file2);
|
||||
free(file3);
|
||||
free(table);
|
||||
}
|
||||
|
||||
|
||||
void add_file_hashtable_suite()
|
||||
{
|
||||
CU_pSuite pSuite = CU_add_suite("FileHashtableSuite", NULL, NULL);
|
||||
CU_add_test(pSuite, "test of iso_file_new()", test_iso_file_new);
|
||||
CU_add_test(pSuite, "test of add and lookup", test_add_lookup);
|
||||
CU_add_test(pSuite, "test with cache_inodes", test_cache_inodes);
|
||||
CU_add_test(pSuite, "test without cache_inodes", test_no_cache_inodes);
|
||||
}
|
395
test/test_tree.c
395
test/test_tree.c
@ -1,395 +0,0 @@
|
||||
/*
|
||||
* Unit test for tree.h
|
||||
*/
|
||||
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "tree.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void test_new_root() {
|
||||
struct iso_tree_node_dir *root;
|
||||
root = iso_tree_new_root();
|
||||
CU_ASSERT_PTR_NOT_NULL(root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 0);
|
||||
CU_ASSERT_PTR_NULL(root->children);
|
||||
CU_ASSERT_PTR_NULL(root->node.parent);
|
||||
CU_ASSERT_PTR_NULL(root->node.name);
|
||||
CU_ASSERT(S_ISDIR(root->node.attrib.st_mode) );
|
||||
}
|
||||
|
||||
static void test_add_dir() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node_dir *dir;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
CU_ASSERT_PTR_NOT_NULL(root);
|
||||
dir = iso_tree_add_dir(root, "New dir name");
|
||||
CU_ASSERT_PTR_NOT_NULL(root);
|
||||
CU_ASSERT_PTR_NOT_NULL(dir);
|
||||
CU_ASSERT_PTR_EQUAL(dir->node.parent, root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 1);
|
||||
CU_ASSERT_PTR_EQUAL(root->children[0], (struct iso_tree_node *)dir);
|
||||
CU_ASSERT_STRING_EQUAL( dir->node.name, "New dir name");
|
||||
CU_ASSERT( S_ISDIR(dir->node.attrib.st_mode) );
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_add_file() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node_file *file;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
file = (struct iso_tree_node_file *)
|
||||
iso_tree_add_file(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(root);
|
||||
CU_ASSERT_PTR_NOT_NULL(file);
|
||||
CU_ASSERT_PTR_EQUAL(file->node.parent, root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 1);
|
||||
CU_ASSERT_PTR_EQUAL(root->children[0], (struct iso_tree_node *)file);
|
||||
CU_ASSERT_STRING_EQUAL( file->node.name, "README" );
|
||||
CU_ASSERT_STRING_EQUAL( file->path, "/tmp/libisofs_test/README" );
|
||||
CU_ASSERT( S_ISREG(file->node.attrib.st_mode) );
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_add_symlink() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *lnk;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
lnk = iso_tree_add_symlink(root, "read", "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(root);
|
||||
CU_ASSERT_PTR_NOT_NULL(lnk);
|
||||
CU_ASSERT_PTR_EQUAL(lnk->parent, root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 1);
|
||||
CU_ASSERT_PTR_EQUAL(root->children[0], (struct iso_tree_node *)lnk);
|
||||
CU_ASSERT_STRING_EQUAL( lnk->name, "read");
|
||||
CU_ASSERT_STRING_EQUAL( ((struct iso_tree_node_symlink*)lnk)->dest,
|
||||
"/tmp/libisofs_test/README" );
|
||||
CU_ASSERT( S_ISLNK(lnk->attrib.st_mode) );
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_add_node() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *node;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
/* test addition of a dir */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/dir1");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_PTR_EQUAL(node->parent, root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 1);
|
||||
CU_ASSERT_PTR_EQUAL(root->children[0], node);
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "dir1");
|
||||
CU_ASSERT( ISO_ISDIR(node) );
|
||||
CU_ASSERT( S_ISDIR(node->attrib.st_mode) );
|
||||
|
||||
/* test addition of a link */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/link to readme");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_PTR_EQUAL(node->parent, root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 2);
|
||||
CU_ASSERT_PTR_EQUAL(root->children[1], node);
|
||||
CU_ASSERT( ISO_ISLNK(node) );
|
||||
CU_ASSERT( S_ISLNK(node->attrib.st_mode) );
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "link to readme");
|
||||
CU_ASSERT_STRING_EQUAL( ((struct iso_tree_node_symlink*)node)->dest,
|
||||
"/tmp/libisofs_test/README" );
|
||||
|
||||
/* test addition of a file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_PTR_EQUAL(node->parent, root);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 3);
|
||||
CU_ASSERT_PTR_EQUAL(root->children[2], node);
|
||||
CU_ASSERT( S_ISREG(node->attrib.st_mode) );
|
||||
CU_ASSERT( ISO_ISREG(node) );
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "README" );
|
||||
CU_ASSERT_STRING_EQUAL( ((struct iso_tree_node_file *) node)->path,
|
||||
"/tmp/libisofs_test/README" );
|
||||
|
||||
/* test no exiting file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/THISNOTEXIST");
|
||||
CU_ASSERT_PTR_NULL(node);
|
||||
CU_ASSERT_EQUAL(libisofs_errno, NO_FILE);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 3);
|
||||
|
||||
/* test no valid file */
|
||||
node = iso_tree_add_node(root, "/dev/zero");
|
||||
CU_ASSERT_PTR_NULL(node);
|
||||
CU_ASSERT_EQUAL(libisofs_errno, UNEXPECTED_FILE_TYPE);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 3);
|
||||
|
||||
/* test no read perm file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/no_read");
|
||||
CU_ASSERT_PTR_NULL(node);
|
||||
CU_ASSERT_EQUAL(libisofs_errno, NO_READ_ACCESS);
|
||||
CU_ASSERT_EQUAL(root->nchildren, 3);
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_radd_dir() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node_dir *child;
|
||||
struct iso_tree_node_file *file;
|
||||
struct iso_tree_radd_dir_behavior behavior = {0,0,0};
|
||||
|
||||
//TODO write really full test
|
||||
|
||||
root = iso_tree_new_root();
|
||||
CU_ASSERT_PTR_NOT_NULL(root);
|
||||
|
||||
iso_tree_radd_dir(root, "/tmp/libisofs_test", &behavior);
|
||||
|
||||
/* test _root_ children */
|
||||
/*
|
||||
child = (struct iso_tree_node_dir *)root->children[0];
|
||||
CU_ASSERT( S_ISDIR(child->node.attrib.st_mode) );
|
||||
CU_ASSERT_EQUAL( child->nchildren, 2);
|
||||
CU_ASSERT_STRING_EQUAL( child->node.name, "dir1" );
|
||||
|
||||
child = (struct iso_tree_node_dir *)root->children[1];
|
||||
CU_ASSERT( S_ISDIR(child->node.attrib.st_mode) );
|
||||
CU_ASSERT_EQUAL( child->nchildren, 0);
|
||||
CU_ASSERT_STRING_EQUAL( child->node.name, "dir2" );
|
||||
|
||||
file = (struct iso_tree_node_file *)root->children[2];
|
||||
CU_ASSERT( S_ISREG(file->node.attrib.st_mode) );
|
||||
CU_ASSERT_STRING_EQUAL( file->node.name, "README" );
|
||||
*/
|
||||
//iso_tree_print( (struct iso_tree_node *)root, 4 );
|
||||
}
|
||||
|
||||
static void test_set_name() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *node;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
/* test on a dir */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/dir1");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "dir1");
|
||||
iso_tree_node_set_name(node, "newname");
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "newname");
|
||||
|
||||
/* test on a link */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/link to readme");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "link to readme");
|
||||
iso_tree_node_set_name(node, "new link name");
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "new link name");
|
||||
|
||||
/* test on a file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "README" );
|
||||
iso_tree_node_set_name(node, "new file name");
|
||||
CU_ASSERT_STRING_EQUAL( node->name, "new file name");
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_set_hidden() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *node;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
/* test on a dir */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/dir1");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, 0);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_RR);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_RR);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_JOLIET);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_JOLIET);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_RR|LIBISO_HIDE_ON_JOLIET);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_RR|LIBISO_HIDE_ON_JOLIET);
|
||||
|
||||
/* test on a link */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/link to readme");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, 0);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_RR);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_RR);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_JOLIET);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_JOLIET);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_RR|LIBISO_HIDE_ON_JOLIET);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_RR|LIBISO_HIDE_ON_JOLIET);
|
||||
|
||||
/* test on a file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, 0);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_RR);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_RR);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_JOLIET);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_JOLIET);
|
||||
iso_tree_node_set_hidden(node, LIBISO_HIDE_ON_RR|LIBISO_HIDE_ON_JOLIET);
|
||||
CU_ASSERT_EQUAL(node->hide_flags, LIBISO_HIDE_ON_RR|LIBISO_HIDE_ON_JOLIET);
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_set_gid() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *node;
|
||||
gid_t mygid = getgid();
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
/* test on a dir */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/dir1");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_gid, mygid);
|
||||
iso_tree_node_set_gid(node, 1234);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_gid, 1234);
|
||||
|
||||
/* test on a link */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/link to readme");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_gid, mygid);
|
||||
iso_tree_node_set_gid(node, 1234);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_gid, 1234);
|
||||
|
||||
/* test on a file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_gid, mygid);
|
||||
iso_tree_node_set_gid(node, 1234);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_gid, 1234);
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_set_uid() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *node;
|
||||
uid_t myuid = getuid();
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
/* test on a dir */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/dir1");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_uid, myuid);
|
||||
iso_tree_node_set_uid(node, 1234);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_uid, 1234);
|
||||
|
||||
/* test on a link */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/link to readme");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_uid, myuid);
|
||||
iso_tree_node_set_uid(node, 1234);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_uid, 1234);
|
||||
|
||||
/* test on a file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_uid, myuid);
|
||||
iso_tree_node_set_uid(node, 1234);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_uid, 1234);
|
||||
|
||||
//TODO
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_set_permissions() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node *node;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
/* test on a dir */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/dir1");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFDIR | 0755);
|
||||
iso_tree_node_set_permissions(node, 0777);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFDIR | 0777);
|
||||
iso_tree_node_set_permissions(node, 0744);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFDIR | 0744);
|
||||
iso_tree_node_set_permissions(node, 0411);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFDIR | 0411);
|
||||
|
||||
/* test on a link */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/link to readme");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFLNK | 0777);
|
||||
iso_tree_node_set_permissions(node, 0555);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFLNK | 0555);
|
||||
iso_tree_node_set_permissions(node, 0744);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFLNK | 0744);
|
||||
iso_tree_node_set_permissions(node, 0411);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFLNK | 0411);
|
||||
|
||||
/* test on a file */
|
||||
node = iso_tree_add_node(root, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_PTR_NOT_NULL(node);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFREG | 0555);
|
||||
iso_tree_node_set_permissions(node, 0777);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFREG | 0777);
|
||||
iso_tree_node_set_permissions(node, 0744);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFREG | 0744);
|
||||
iso_tree_node_set_permissions(node, 0411);
|
||||
CU_ASSERT_EQUAL(node->attrib.st_mode, S_IFREG | 0411);
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
static void test_set_sort_weight() {
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node_dir *dir;
|
||||
struct iso_tree_node_file *file;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
|
||||
dir = iso_tree_add_dir(root, "New dir name");
|
||||
CU_ASSERT_PTR_NOT_NULL(dir);
|
||||
|
||||
file = (struct iso_tree_node_file *)
|
||||
iso_tree_add_file(dir, "/tmp/libisofs_test/README");
|
||||
CU_ASSERT_EQUAL(file->sort_weight, 0);
|
||||
iso_tree_node_set_sort_weight((struct iso_tree_node *) file, 15);
|
||||
CU_ASSERT_EQUAL(file->sort_weight, 15);
|
||||
iso_tree_node_set_sort_weight((struct iso_tree_node *) file, -15);
|
||||
CU_ASSERT_EQUAL(file->sort_weight, -15);
|
||||
|
||||
/* changes to dir involve update files inside it */
|
||||
iso_tree_node_set_sort_weight((struct iso_tree_node *) dir, 28);
|
||||
CU_ASSERT_EQUAL(file->sort_weight, 28);
|
||||
|
||||
iso_tree_free((struct iso_tree_node *)root);
|
||||
}
|
||||
|
||||
void add_tree_suite()
|
||||
{
|
||||
CU_pSuite pSuite = CU_add_suite("TreeSuite", NULL, NULL);
|
||||
|
||||
CU_add_test(pSuite, "test of iso_tree_new_root()", test_new_root);
|
||||
CU_add_test(pSuite, "test of iso_tree_add_dir()", test_add_dir);
|
||||
CU_add_test(pSuite, "test of iso_tree_add_file()", test_add_file);
|
||||
CU_add_test(pSuite, "test of iso_tree_add_symlink()", test_add_symlink);
|
||||
CU_add_test(pSuite, "test of iso_tree_add_node()", test_add_node);
|
||||
CU_add_test(pSuite, "test of iso_tree_radd_dir()", test_radd_dir);
|
||||
|
||||
CU_add_test(pSuite, "test of iso_tree_node_set_name()", test_set_name);
|
||||
CU_add_test(pSuite, "test of iso_tree_node_set_hidden()", test_set_hidden);
|
||||
CU_add_test(pSuite, "test of iso_tree_node_set_gid()", test_set_gid);
|
||||
CU_add_test(pSuite, "test of iso_tree_node_set_uid()", test_set_uid);
|
||||
CU_add_test(pSuite, "test of iso_tree_node_set_permissions()", test_set_permissions);
|
||||
CU_add_test(pSuite, "test of iso_tree_node_set_sort_weight()", test_set_sort_weight);
|
||||
}
|
265
test/test_util.c
265
test/test_util.c
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Unit test for util.h
|
||||
*
|
||||
* This test utiliy functions
|
||||
*
|
||||
*/
|
||||
#include "test.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
static void test_div_up()
|
||||
{
|
||||
CU_ASSERT_EQUAL( div_up(1, 2), 1 );
|
||||
CU_ASSERT_EQUAL( div_up(2, 2), 1 );
|
||||
CU_ASSERT_EQUAL( div_up(0, 2), 0 );
|
||||
CU_ASSERT_EQUAL( div_up(-1, 2), 0 );
|
||||
CU_ASSERT_EQUAL( div_up(3, 2), 2 );
|
||||
}
|
||||
|
||||
static void test_round_up()
|
||||
{
|
||||
CU_ASSERT_EQUAL( round_up(1, 2), 2 );
|
||||
CU_ASSERT_EQUAL( round_up(2, 2), 2 );
|
||||
CU_ASSERT_EQUAL( round_up(0, 2), 0 );
|
||||
CU_ASSERT_EQUAL( round_up(-1, 2), 0 );
|
||||
CU_ASSERT_EQUAL( round_up(3, 2), 4 );
|
||||
CU_ASSERT_EQUAL( round_up(15, 7), 21 );
|
||||
CU_ASSERT_EQUAL( round_up(13, 7), 14 );
|
||||
CU_ASSERT_EQUAL( round_up(14, 7), 14 );
|
||||
}
|
||||
|
||||
static void test_iso_lsb_msb()
|
||||
{
|
||||
uint8_t buf[4];
|
||||
uint32_t num;
|
||||
|
||||
num = 0x01020304;
|
||||
iso_lsb(buf, num, 4);
|
||||
CU_ASSERT_EQUAL( buf[0], 0x04 );
|
||||
CU_ASSERT_EQUAL( buf[1], 0x03 );
|
||||
CU_ASSERT_EQUAL( buf[2], 0x02 );
|
||||
CU_ASSERT_EQUAL( buf[3], 0x01 );
|
||||
|
||||
iso_msb(buf, num, 4);
|
||||
CU_ASSERT_EQUAL( buf[0], 0x01 );
|
||||
CU_ASSERT_EQUAL( buf[1], 0x02 );
|
||||
CU_ASSERT_EQUAL( buf[2], 0x03 );
|
||||
CU_ASSERT_EQUAL( buf[3], 0x04 );
|
||||
|
||||
iso_lsb(buf, num, 2);
|
||||
CU_ASSERT_EQUAL( buf[0], 0x04 );
|
||||
CU_ASSERT_EQUAL( buf[1], 0x03 );
|
||||
|
||||
iso_msb(buf, num, 2);
|
||||
CU_ASSERT_EQUAL( buf[0], 0x03 );
|
||||
CU_ASSERT_EQUAL( buf[1], 0x04 );
|
||||
}
|
||||
|
||||
static void test_iso_1_dirid()
|
||||
{
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("dir1", "UTF-8"), "DIR1" );
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("dIR1", "UTF-8"), "DIR1" );
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("DIR1", "UTF-8"), "DIR1" );
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("dirwithbigname", "UTF-8"), "DIRWITHB");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("dirwith8", "UTF-8"), "DIRWITH8");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("dir.1", "UTF-8"), "DIR_1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_dirid("4f<0KmM::xcvf", "UTF-8"), "4F_0KMM_");
|
||||
}
|
||||
|
||||
static void test_iso_2_dirid()
|
||||
{
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("dir1", "UTF-8"), "DIR1" );
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("dIR1", "UTF-8"), "DIR1" );
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("DIR1", "UTF-8"), "DIR1" );
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("dirwithbigname", "UTF-8"), "DIRWITHBIGNAME");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("dirwith8", "UTF-8"), "DIRWITH8");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("dir.1", "UTF-8"), "DIR_1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("4f<0KmM::xcvf", "UTF-8"), "4F_0KMM__XCVF");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("directory with 31 characters ok", "UTF-8"), "DIRECTORY_WITH_31_CHARACTERS_OK");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_dirid("directory with more than 31 characters", "UTF-8"), "DIRECTORY_WITH_MORE_THAN_31_CHA");
|
||||
}
|
||||
|
||||
static void test_iso_r_dirid()
|
||||
{
|
||||
int flag;
|
||||
|
||||
/* 1. only ECMA119_37_CHAR_FILENAMES */
|
||||
flag = ECMA119_37_CHAR_FILENAMES;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dir1", "UTF-8", flag), "DIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dIR1", "UTF-8", flag), "DIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("DIR1", "UTF-8", flag), "DIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dirwithbigname", "UTF-8", flag), "DIRWITHBIGNAME");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dirwith8", "UTF-8", flag), "DIRWITH8");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dir.1", "UTF-8", flag), "DIR_1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("4f<0KmM::xcvf", "UTF-8", flag), "4F_0KMM__XCVF");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with 31 characters ok", "UTF-8", flag), "DIRECTORY_WITH_31_CHARACTERS_OK");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with more than 37 characters", "UTF-8", flag), "DIRECTORY_WITH_MORE_THAN_37_CHARACTER");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with just 37 characters ok", "UTF-8", flag), "DIRECTORY_WITH_JUST_37_CHARACTERS__OK");
|
||||
|
||||
/* 2. only ECMA119_RELAXED_FILENAMES */
|
||||
flag = ECMA119_RELAXED_FILENAMES;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dir1", "UTF-8", flag), "dir1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dIR1", "UTF-8", flag), "dIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("DIR1", "UTF-8", flag), "DIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dirwithbigname", "UTF-8", flag), "dirwithbigname");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dirwith8", "UTF-8", flag), "dirwith8");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dir.1", "UTF-8", flag), "dir.1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("4f<0KmM::xcvf", "UTF-8", flag), "4f<0KmM::xcvf");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with 31 characters ok", "UTF-8", flag), "directory with 31 characters ok");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with more than 37 characters", "UTF-8", flag), "directory with more than 37 cha");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with just 37 characters ok", "UTF-8", flag), "directory with just 37 characte");
|
||||
|
||||
/* 3. both ECMA119_RELAXED_FILENAMES and ECMA119_37_CHAR_FILENAMES */
|
||||
flag = ECMA119_RELAXED_FILENAMES | ECMA119_37_CHAR_FILENAMES;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dir1", "UTF-8", flag), "dir1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dIR1", "UTF-8", flag), "dIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("DIR1", "UTF-8", flag), "DIR1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dirwithbigname", "UTF-8", flag), "dirwithbigname");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dirwith8", "UTF-8", flag), "dirwith8");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("dir.1", "UTF-8", flag), "dir.1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("4f<0KmM::xcvf", "UTF-8", flag), "4f<0KmM::xcvf");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with 31 characters ok", "UTF-8", flag), "directory with 31 characters ok");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with more than 37 characters", "UTF-8", flag), "directory with more than 37 character");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_dirid("directory with just 37 characters ok", "UTF-8", flag), "directory with just 37 characters ok");
|
||||
}
|
||||
|
||||
static void test_iso_1_fileid()
|
||||
{
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file1", "UTF-8"), "FILE1.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("fILe1", "UTF-8"), "FILE1.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("FILE1", "UTF-8"), "FILE1.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid(".EXT", "UTF-8"), ".EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file.ext", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("fiLE.ext", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file.EXt", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("FILE.EXT", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("bigfilename", "UTF-8"), "BIGFILEN.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("bigfilename.ext", "UTF-8"), "BIGFILEN.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("bigfilename.e", "UTF-8"), "BIGFILEN.E;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file.bigext", "UTF-8"), "FILE.BIG;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid(".bigext", "UTF-8"), ".BIG;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("bigfilename.bigext", "UTF-8"), "BIGFILEN.BIG;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file<:a.ext", "UTF-8"), "FILE__A.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file.<:a", "UTF-8"), "FILE.__A;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file<:a.--a", "UTF-8"), "FILE__A.__A;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file.ex1.ex2", "UTF-8"), "FILE_EX1.EX2;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("file.ex1.ex2.ex3", "UTF-8"), "FILE_EX1.EX3;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_1_fileid("fil.ex1.ex2.ex3", "UTF-8"), "FIL_EX1_.EX3;1");
|
||||
}
|
||||
|
||||
static void test_iso_2_fileid()
|
||||
{
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file1", "UTF-8"), "FILE1.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("fILe1", "UTF-8"), "FILE1.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("FILE1", "UTF-8"), "FILE1.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid(".EXT", "UTF-8"), ".EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file.ext", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("fiLE.ext", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file.EXt", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("FILE.EXT", "UTF-8"), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("bigfilename", "UTF-8"), "BIGFILENAME.;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("bigfilename.ext", "UTF-8"), "BIGFILENAME.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("bigfilename.e", "UTF-8"), "BIGFILENAME.E;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("31 characters filename.extensio", "UTF-8"), "31_CHARACTERS_FILENAME.EXTENSIO;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("32 characters filename.extension", "UTF-8"), "32_CHARACTERS_FILENAME.EXTENSIO;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("more than 30 characters filename.extension", "UTF-8"), "MORE_THAN_30_CHARACTERS_FIL.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file.bigext", "UTF-8"), "FILE.BIGEXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid(".bigext", "UTF-8"), ".BIGEXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("bigfilename.bigext", "UTF-8"), "BIGFILENAME.BIGEXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file<:a.ext", "UTF-8"), "FILE__A.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file.<:a", "UTF-8"), "FILE.__A;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file<:a.--a", "UTF-8"), "FILE__A.__A;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file.ex1.ex2", "UTF-8"), "FILE_EX1.EX2;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("file.ex1.ex2.ex3", "UTF-8"), "FILE_EX1_EX2.EX3;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid("fil.ex1.ex2.ex3", "UTF-8"), "FIL_EX1_EX2.EX3;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_2_fileid(".file.bigext", "UTF-8"), "_FILE.BIGEXT;1");
|
||||
}
|
||||
|
||||
static void test_iso_r_fileid()
|
||||
{
|
||||
int flag;
|
||||
|
||||
/* 1. only ECMA119_OMIT_VERSION_NUMBERS */
|
||||
flag = ECMA119_OMIT_VERSION_NUMBERS;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file1", "UTF-8", flag), "FILE1.");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fILe1", "UTF-8", flag), "FILE1.");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("31 characters filename.extensio", "UTF-8", flag), "31_CHARACTERS_FILENAME.EXTENSIO");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("it's 37 characters filename.extension", "UTF-8", flag), "IT_S_37_CHARACTERS_FILENAME.EXT");
|
||||
|
||||
/* 2. only ECMA119_37_CHAR_FILENAMES */
|
||||
flag = ECMA119_37_CHAR_FILENAMES;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file1", "UTF-8", flag), "FILE1.");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fILe1", "UTF-8", flag), "FILE1.");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("FILE1", "UTF-8", flag), "FILE1.");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid(".EXT", "UTF-8", flag), ".EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.ext", "UTF-8", flag), "FILE.EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fiLE.ext", "UTF-8", flag), "FILE.EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.EXt", "UTF-8", flag), "FILE.EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("FILE.EXT", "UTF-8", flag), "FILE.EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename", "UTF-8", flag), "BIGFILENAME.");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename.ext", "UTF-8", flag), "BIGFILENAME.EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename.e", "UTF-8", flag), "BIGFILENAME.E");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.bigext", "UTF-8", flag), "FILE.BIGEXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("31 characters filename.extensio", "UTF-8", flag), "31_CHARACTERS_FILENAME.EXTENSIO");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("it's 37 characters filename.extension", "UTF-8", flag), "IT_S_37_CHARACTERS_FILENAME.EXTENSION");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("more than 37 characters filename.extension", "UTF-8", flag), "MORE_THAN_37_CHARACTERS_FILENAME.EXTE");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.this is a 37 chars len extension", "UTF-8", flag), "FILE.THIS_IS_A_37_CHARS_LEN_EXTENSION");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.this is a very very big extension", "UTF-8", flag), "FILE.THIS_IS_A_VERY_VERY_BIG_EXTENSIO");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fil.ex1.ex2.ex3", "UTF-8", flag), "FIL_EX1_EX2.EX3");
|
||||
|
||||
/* 3. only ECMA119_RELAXED_FILENAMES */
|
||||
flag = ECMA119_RELAXED_FILENAMES;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file1", "UTF-8", flag), "file1;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fILe1", "UTF-8", flag), "fILe1;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("FILE1", "UTF-8", flag), "FILE1;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid(".EXT", "UTF-8", flag), ".EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.ext", "UTF-8", flag), "file.ext;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fiLE.ext", "UTF-8", flag), "fiLE.ext;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.EXt", "UTF-8", flag), "file.EXt;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("FILE.EXT", "UTF-8", flag), "FILE.EXT;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename", "UTF-8", flag), "bigfilename;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename.ext", "UTF-8", flag), "bigfilename.ext;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename.e", "UTF-8", flag), "bigfilename.e;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.bigext", "UTF-8", flag), "file.bigext;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("31 characters filename.extensio", "UTF-8", flag), "31 characters filename.extensio;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("it's 37 characters filename.extension", "UTF-8", flag), "it's 37 characters filename.ext;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.this is a 37 chars len extension", "UTF-8", flag), "file.this is a 37 chars len ext;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fil.ex1.ex2.ex3", "UTF-8", flag), "fil.ex1.ex2.ex3;1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.<:a", "UTF-8", flag), "file.<:a;1");
|
||||
|
||||
/* 3. ECMA119_RELAXED_FILENAMES and ECMA119_OMIT_VERSION_NUMBERS*/
|
||||
flag = ECMA119_RELAXED_FILENAMES | ECMA119_OMIT_VERSION_NUMBERS;
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file1", "UTF-8", flag), "file1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fILe1", "UTF-8", flag), "fILe1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("FILE1", "UTF-8", flag), "FILE1");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid(".EXT", "UTF-8", flag), ".EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.ext", "UTF-8", flag), "file.ext");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fiLE.ext", "UTF-8", flag), "fiLE.ext");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.EXt", "UTF-8", flag), "file.EXt");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("FILE.EXT", "UTF-8", flag), "FILE.EXT");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename", "UTF-8", flag), "bigfilename");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename.ext", "UTF-8", flag), "bigfilename.ext");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("bigfilename.e", "UTF-8", flag), "bigfilename.e");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.bigext", "UTF-8", flag), "file.bigext");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("31 characters filename.extensio", "UTF-8", flag), "31 characters filename.extensio");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("it's 37 characters filename.extension", "UTF-8", flag), "it's 37 characters filename.ext");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.this is a 37 chars len extension", "UTF-8", flag), "file.this is a 37 chars len ext");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("fil.ex1.ex2.ex3", "UTF-8", flag), "fil.ex1.ex2.ex3");
|
||||
CU_ASSERT_STRING_EQUAL( iso_r_fileid("file.<:a", "UTF-8", flag), "file.<:a");
|
||||
}
|
||||
|
||||
void add_util_suite()
|
||||
{
|
||||
CU_pSuite pSuite = CU_add_suite("UtilSuite", NULL, NULL);
|
||||
|
||||
CU_add_test(pSuite, "test of div_up()", test_div_up);
|
||||
CU_add_test(pSuite, "test of round_up()", test_round_up);
|
||||
CU_add_test(pSuite, "test of iso_lsb_msb()", test_iso_lsb_msb);
|
||||
CU_add_test(pSuite, "test of iso_1_dirid()", test_iso_1_dirid);
|
||||
CU_add_test(pSuite, "test of iso_2_dirid()", test_iso_2_dirid);
|
||||
CU_add_test(pSuite, "test of iso_r_dirid()", test_iso_r_dirid);
|
||||
CU_add_test(pSuite, "test of iso_1_fileid()", test_iso_1_fileid);
|
||||
CU_add_test(pSuite, "test of iso_2_fileid()", test_iso_2_fileid);
|
||||
CU_add_test(pSuite, "test of iso_r_fileid()", test_iso_r_fileid);
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Unit test for volume.h
|
||||
*/
|
||||
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "tree.h"
|
||||
#include "test.h"
|
||||
#include "volume.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void test_iso_volume_new()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_PTR_NOT_NULL(volume);
|
||||
CU_ASSERT_EQUAL(volume->refcount, 1);
|
||||
/* a new root must be created */
|
||||
CU_ASSERT_PTR_NOT_NULL(volume->root);
|
||||
|
||||
CU_ASSERT_STRING_EQUAL( volume->volume_id, "volume_id" );
|
||||
CU_ASSERT_STRING_EQUAL( volume->publisher_id, "publisher_id" );
|
||||
CU_ASSERT_STRING_EQUAL( volume->data_preparer_id, "data_preparer_id" );
|
||||
|
||||
CU_ASSERT_PTR_NULL(volume->system_id);
|
||||
CU_ASSERT_PTR_NULL(volume->application_id);
|
||||
CU_ASSERT_PTR_NULL(volume->copyright_file_id);
|
||||
CU_ASSERT_PTR_NULL(volume->abstract_file_id);
|
||||
CU_ASSERT_PTR_NULL(volume->biblio_file_id);
|
||||
|
||||
CU_ASSERT_PTR_NULL(volume->bootcat);
|
||||
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_new_with_root()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
struct iso_tree_node_dir *root;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
volume = iso_volume_new_with_root("volume_id", "publisher_id",
|
||||
"data_preparer_id", root);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(volume);
|
||||
CU_ASSERT_EQUAL(volume->refcount, 1);
|
||||
CU_ASSERT_PTR_NOT_NULL(volume->root);
|
||||
CU_ASSERT_PTR_EQUAL(volume->root, root);
|
||||
|
||||
CU_ASSERT_STRING_EQUAL( volume->volume_id, "volume_id" );
|
||||
CU_ASSERT_STRING_EQUAL( volume->publisher_id, "publisher_id" );
|
||||
CU_ASSERT_STRING_EQUAL( volume->data_preparer_id, "data_preparer_id" );
|
||||
|
||||
CU_ASSERT_PTR_NULL(volume->system_id);
|
||||
CU_ASSERT_PTR_NULL(volume->application_id);
|
||||
CU_ASSERT_PTR_NULL(volume->copyright_file_id);
|
||||
CU_ASSERT_PTR_NULL(volume->abstract_file_id);
|
||||
CU_ASSERT_PTR_NULL(volume->biblio_file_id);
|
||||
|
||||
CU_ASSERT_PTR_NULL(volume->bootcat);
|
||||
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_get_root()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
struct iso_tree_node_dir *root;
|
||||
struct iso_tree_node_dir *root2;
|
||||
|
||||
root = iso_tree_new_root();
|
||||
volume = iso_volume_new_with_root("volume_id", "publisher_id",
|
||||
"data_preparer_id", root);
|
||||
|
||||
root2 = iso_volume_get_root(volume);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(root2);
|
||||
CU_ASSERT_PTR_EQUAL(root2, volume->root);
|
||||
CU_ASSERT_PTR_EQUAL(root2, root);
|
||||
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_volume_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_STRING_EQUAL( volume->volume_id, "volume_id" );
|
||||
|
||||
char *volid = "new volume id";
|
||||
iso_volume_set_volume_id(volume, volid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->volume_id, "new volume id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->volume_id, volid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_publisher_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_STRING_EQUAL( volume->publisher_id, "publisher_id" );
|
||||
|
||||
char *pubid = "new publisher id";
|
||||
iso_volume_set_publisher_id(volume, pubid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->publisher_id, "new publisher id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->publisher_id, pubid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_data_preparer_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_STRING_EQUAL( volume->data_preparer_id, "data_preparer_id" );
|
||||
|
||||
char *dpid = "new data preparer id";
|
||||
iso_volume_set_data_preparer_id(volume, dpid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->data_preparer_id, "new data preparer id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->data_preparer_id, dpid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_system_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_PTR_NULL(volume->system_id);
|
||||
|
||||
char *sysid = "new system id";
|
||||
iso_volume_set_system_id(volume, sysid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->system_id, "new system id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->system_id, sysid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_application_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_PTR_NULL(volume->application_id);
|
||||
|
||||
char *appid = "new application id";
|
||||
iso_volume_set_application_id(volume, appid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->application_id, "new application id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->application_id, appid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_abstract_file_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_PTR_NULL(volume->abstract_file_id);
|
||||
|
||||
char *absid = "new abstract id";
|
||||
iso_volume_set_abstract_file_id(volume, absid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->abstract_file_id, "new abstract id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->abstract_file_id, absid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volume_set_biblio_file_id()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
CU_ASSERT_PTR_NULL(volume->biblio_file_id);
|
||||
|
||||
char *bibid = "new biblio id";
|
||||
iso_volume_set_biblio_file_id(volume, bibid);
|
||||
CU_ASSERT_STRING_EQUAL( volume->biblio_file_id, "new biblio id" );
|
||||
|
||||
/* check string was strdup'ed */
|
||||
CU_ASSERT_PTR_NOT_EQUAL( volume->biblio_file_id, bibid );
|
||||
iso_volume_free(volume);
|
||||
}
|
||||
|
||||
static void test_iso_volset_new()
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
struct iso_volset *volset;
|
||||
|
||||
volume = iso_volume_new("volume_id", "publisher_id", "data_preparer_id");
|
||||
|
||||
volset = iso_volset_new(volume, "volset_id");
|
||||
CU_ASSERT_PTR_NOT_NULL(volset);
|
||||
CU_ASSERT_EQUAL(volset->refcount, 1);
|
||||
CU_ASSERT_EQUAL(volset->volset_size, 1);
|
||||
CU_ASSERT_PTR_NOT_NULL(volset->volume);
|
||||
CU_ASSERT_PTR_NOT_NULL(volset->volume[0]);
|
||||
CU_ASSERT_PTR_EQUAL(volset->volume[0], volume);
|
||||
CU_ASSERT_STRING_EQUAL( volset->volset_id, "volset_id" );
|
||||
|
||||
iso_volset_free(volset);
|
||||
}
|
||||
|
||||
void add_volume_suite()
|
||||
{
|
||||
CU_pSuite pSuite = CU_add_suite("VolumeSuite", NULL, NULL);
|
||||
|
||||
CU_add_test(pSuite, "test of iso_volume_new()", test_iso_volume_new);
|
||||
CU_add_test(pSuite, "test of iso_volume_new_with_root()", test_iso_volume_new_with_root);
|
||||
CU_add_test(pSuite, "test of iso_volume_get_root()", test_iso_volume_get_root);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_volume_id()", test_iso_volume_set_volume_id);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_publisher_id()", test_iso_volume_set_publisher_id);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_data_preparer_id()", test_iso_volume_set_data_preparer_id);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_system_id()", test_iso_volume_set_system_id);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_application_id()", test_iso_volume_set_application_id);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_abstract_file_id()", test_iso_volume_set_abstract_file_id);
|
||||
CU_add_test(pSuite, "test of iso_volume_set_biblio_file_id()", test_iso_volume_set_biblio_file_id);
|
||||
CU_add_test(pSuite, "test of iso_volset_new()", test_iso_volset_new);
|
||||
}
|
Reference in New Issue
Block a user