Compare commits
70 Commits
release-0.
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
d863451771 | |||
78308eea24 | |||
0ab2b8260c | |||
a30bd36a81 | |||
3814396b08 | |||
f88d8a76b0 | |||
6bc1395e15 | |||
6bf538ff40 | |||
c992687200 | |||
9cfa55345e | |||
d9a11a3b8d | |||
2e7d85b85a | |||
dfe6d16353 | |||
1ad1d02e9f | |||
d0996450c7 | |||
b1c4571a95 | |||
3f918d1acb | |||
cadd77776b | |||
72e9c67d05 | |||
62edebad06 | |||
363a39af3e | |||
8b800094af | |||
868005ed0e | |||
07a67a59e7 | |||
955471a064 | |||
b4e2a60cd9 | |||
9467f2e644 | |||
ba66a7896a | |||
74198afa04 | |||
40c39af271 | |||
ecf2ca044e | |||
fd124c82d2 | |||
429b4cd21c | |||
b5f4a66c59 | |||
55690756ae | |||
bbbe89166d | |||
67ac2b9b70 | |||
4b5a5658a6 | |||
9c2bf0197b | |||
e52b5e7f2a | |||
0e14549521 | |||
1d44d931d0 | |||
5d5a0cbfd4 | |||
4353a35c59 | |||
2f48297d25 | |||
dfcb815480 | |||
f370829717 | |||
ef96f3588c | |||
e8fc149423 | |||
e12d409b80 | |||
b34fd35e62 | |||
714ee67472 | |||
8c4682ae92 | |||
5b073a2f29 | |||
c6f1101e9d | |||
f8d3bca20a | |||
46a947b602 | |||
56796ff55f | |||
1cbae01f12 | |||
da4634a593 | |||
f18d5157dc | |||
1195614881 | |||
1218e6e32d | |||
95381ce258 | |||
19fd87ef7b | |||
d20da80767 | |||
5009d1038d | |||
1ae2a39d1d | |||
70af4872c9 | |||
71d491ed37 |
184
Makefile.am
184
Makefile.am
@ -73,7 +73,9 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/iso1999.c \
|
||||
libisofs/data_source.c \
|
||||
libisofs/aaip_0_2.h \
|
||||
libisofs/aaip_0_2.c
|
||||
libisofs/aaip_0_2.c \
|
||||
libisofs/md5.h \
|
||||
libisofs/md5.c
|
||||
libisofs_libisofs_la_LIBADD= \
|
||||
$(THREAD_LIBS)
|
||||
libinclude_HEADERS = \
|
||||
@ -83,71 +85,102 @@ libinclude_HEADERS = \
|
||||
|
||||
## Build demo applications
|
||||
noinst_PROGRAMS = \
|
||||
demo/lsl \
|
||||
demo/cat \
|
||||
demo/catbuffer \
|
||||
demo/tree \
|
||||
demo/find \
|
||||
demo/ecma119tree \
|
||||
demo/iso \
|
||||
demo/isoread \
|
||||
demo/isocat \
|
||||
demo/isomodify \
|
||||
demo/isoms
|
||||
demo/demo
|
||||
|
||||
# demo/tree \
|
||||
# demo/find \
|
||||
# demo/iso \
|
||||
# demo/isoread \
|
||||
# demo/isocat \
|
||||
# demo/isomodify \
|
||||
# demo/isoms
|
||||
|
||||
# demo/ecma119tree \
|
||||
# demo/lsl \
|
||||
# demo/cat \
|
||||
# demo/catbuffer \
|
||||
# demo/isogrow
|
||||
|
||||
demo_lsl_CPPFLAGS = -Ilibisofs
|
||||
demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
demo_lsl_SOURCES = demo/lsl.c
|
||||
|
||||
demo_cat_CPPFLAGS = -Ilibisofs
|
||||
demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
demo_cat_SOURCES = demo/cat.c
|
||||
# ts A90807
|
||||
# Consolidated demo code for having less linker mesages with a make run.
|
||||
demo_demo_CPPFLAGS = -Ilibisofs
|
||||
demo_demo_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
demo_demo_SOURCES = demo/demo.c
|
||||
|
||||
demo_catbuffer_CPPFLAGS = -Ilibisofs
|
||||
demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_catbuffer_SOURCES = demo/cat_buffer.c
|
||||
# ts A90806
|
||||
# This includes fsource.h and thus is no API demo
|
||||
# demo_lsl_CPPFLAGS = -Ilibisofs
|
||||
# demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_lsl_SOURCES = demo/lsl.c
|
||||
|
||||
demo_tree_CPPFLAGS = -Ilibisofs
|
||||
demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_tree_SOURCES = demo/tree.c
|
||||
# ts A90806
|
||||
# This includes fsource.h and thus is no API demo
|
||||
# demo_cat_CPPFLAGS = -Ilibisofs
|
||||
# demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_cat_SOURCES = demo/cat.c
|
||||
|
||||
demo_find_CPPFLAGS = -Ilibisofs
|
||||
demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_find_SOURCES = demo/find.c
|
||||
# ts A90806
|
||||
# This inlcudes buffer.h and thus is no API demo
|
||||
# demo_catbuffer_CPPFLAGS = -Ilibisofs
|
||||
# demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_catbuffer_SOURCES = demo/cat_buffer.c
|
||||
|
||||
demo_ecma119tree_CPPFLAGS = -Ilibisofs
|
||||
demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_ecma119tree_SOURCES = demo/ecma119_tree.c
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_tree_CPPFLAGS = -Ilibisofs
|
||||
# demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_tree_SOURCES = demo/tree.c
|
||||
|
||||
demo_iso_CPPFLAGS = -Ilibisofs
|
||||
demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
demo_iso_SOURCES = demo/iso.c
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_find_CPPFLAGS = -Ilibisofs
|
||||
# demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_find_SOURCES = demo/find.c
|
||||
|
||||
demo_isoread_CPPFLAGS = -Ilibisofs
|
||||
demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_isoread_SOURCES = demo/iso_read.c
|
||||
# ts A90806
|
||||
# This inlcudes lots of internal .h files and thus is no API demo
|
||||
# demo_ecma119tree_CPPFLAGS = -Ilibisofs
|
||||
# demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_ecma119tree_SOURCES = demo/ecma119_tree.c
|
||||
|
||||
demo_isocat_CPPFLAGS = -Ilibisofs
|
||||
demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_isocat_SOURCES = demo/iso_cat.c
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_iso_CPPFLAGS = -Ilibisofs
|
||||
# demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_iso_SOURCES = demo/iso.c
|
||||
|
||||
demo_isomodify_CPPFLAGS = -Ilibisofs
|
||||
demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_isomodify_SOURCES = demo/iso_modify.c
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_isoread_CPPFLAGS = -Ilibisofs
|
||||
# demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_isoread_SOURCES = demo/iso_read.c
|
||||
|
||||
demo_isoms_CPPFLAGS = -Ilibisofs
|
||||
demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD)
|
||||
demo_isoms_SOURCES = demo/iso_ms.c
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_isocat_CPPFLAGS = -Ilibisofs
|
||||
# demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_isocat_SOURCES = demo/iso_cat.c
|
||||
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_isomodify_CPPFLAGS = -Ilibisofs
|
||||
# demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_isomodify_SOURCES = demo/iso_modify.c
|
||||
|
||||
# ts A90807
|
||||
# Consolidated in demo/demo
|
||||
# demo_isoms_CPPFLAGS = -Ilibisofs
|
||||
# demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD)
|
||||
# demo_isoms_SOURCES = demo/iso_ms.c
|
||||
|
||||
# demo_isogrow_CPPFLAGS = -Ilibisofs -Ilibburn
|
||||
# demo_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
@ -156,27 +189,31 @@ demo_isoms_SOURCES = demo/iso_ms.c
|
||||
# demo_isogrow_SOURCES = demo/iso_grow.c
|
||||
|
||||
|
||||
## Build unit test
|
||||
## ts A90428 , ticket 147, The test code does not use the API and is totally
|
||||
## outdated in its creation of mocked objects.
|
||||
## A volunteer is needed to rewrite it using the API.
|
||||
|
||||
# ## Build unit test
|
||||
|
||||
check_PROGRAMS = \
|
||||
test/test
|
||||
|
||||
test_test_CPPFLAGS = -Ilibisofs
|
||||
test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD) -lcunit
|
||||
test_test_LDFLAGS = -L.. -lm
|
||||
|
||||
test_test_SOURCES = \
|
||||
test/test.h \
|
||||
test/test.c \
|
||||
test/test_node.c \
|
||||
test/test_image.c \
|
||||
test/test_tree.c \
|
||||
test/test_util.c \
|
||||
test/test_rockridge.c \
|
||||
test/test_stream.c \
|
||||
test/mocked_fsrc.h \
|
||||
test/mocked_fsrc.c
|
||||
# check_PROGRAMS = \
|
||||
# test/test
|
||||
#
|
||||
# test_test_CPPFLAGS = -Ilibisofs
|
||||
# test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD) -lcunit
|
||||
# test_test_LDFLAGS = -L.. -lm
|
||||
#
|
||||
# test_test_SOURCES = \
|
||||
# test/test.h \
|
||||
# test/test.c \
|
||||
# test/test_node.c \
|
||||
# test/test_image.c \
|
||||
# test/test_tree.c \
|
||||
# test/test_util.c \
|
||||
# test/test_rockridge.c \
|
||||
# test/test_stream.c \
|
||||
# test/mocked_fsrc.h \
|
||||
# test/mocked_fsrc.c
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
@ -224,6 +261,7 @@ EXTRA_DIST = \
|
||||
doc/susp_aaip_2_0.txt \
|
||||
doc/susp_aaip_isofs_names.txt \
|
||||
doc/zisofs_format.txt \
|
||||
doc/checksums.txt \
|
||||
libisofs/aaip-os-dummy.c \
|
||||
libisofs/aaip-os-linux.c \
|
||||
libisofs/aaip-os-freebsd.c
|
||||
|
94
acinclude.m4
94
acinclude.m4
@ -13,6 +13,8 @@ AC_DEFUN([TARGET_SHIZZLE],
|
||||
*-*-freebsd*)
|
||||
ARCH=freebsd
|
||||
LIBBURN_ARCH_LIBS=-lcam
|
||||
|
||||
# This may later be overridden by configure --enable-libdir-pkgconfig
|
||||
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
|
||||
;;
|
||||
*)
|
||||
@ -24,3 +26,95 @@ AC_DEFUN([TARGET_SHIZZLE],
|
||||
|
||||
AC_MSG_RESULT([$ARCH])
|
||||
])
|
||||
|
||||
|
||||
dnl LIBBURNIA_CHECK_ICONV is by Thomas Schmitt, libburnia project
|
||||
dnl It is based on gestures from:
|
||||
dnl iconv.m4 serial AM7 (gettext-0.18)
|
||||
dnl Copyright (C) 2000-2002, 2007-2009 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
dnl From Bruno Haible.
|
||||
dnl
|
||||
AC_DEFUN([LIBBURNIA_CHECK_ICONV],
|
||||
[
|
||||
dnl Check whether it is allowed to link with -liconv
|
||||
AC_MSG_CHECKING([for separate -liconv ])
|
||||
libburnia_liconv="no"
|
||||
libburnia_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -liconv"
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
[libburnia_liconv="yes"],
|
||||
[LIBS="$libburnia_save_LIBS"]
|
||||
)
|
||||
AC_MSG_RESULT([$libburnia_liconv])
|
||||
|
||||
dnl Check for iconv(..., const char **inbuf, ...)
|
||||
AC_MSG_CHECKING([for const qualifier with iconv() ])
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
], [], [libburnia_iconv_const=""], [libburnia_iconv_const="const"]
|
||||
)
|
||||
AC_DEFINE_UNQUOTED([ICONV_CONST], [$libburnia_iconv_const])
|
||||
test -z "$libburnia_iconv_const" && libburnia_iconv_const="no"
|
||||
AC_MSG_RESULT([$libburnia_iconv_const])
|
||||
])
|
||||
|
||||
|
||||
dnl LIBBURNIA_SET_PKGCONFIG determines the install directory for the *.pc file.
|
||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
||||
dnl
|
||||
AC_DEFUN([LIBBURNIA_SET_PKGCONFIG],
|
||||
[
|
||||
### for testing --enable-libdir-pkgconfig on Linux
|
||||
### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig
|
||||
|
||||
if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
AC_ARG_ENABLE(libdir-pkgconfig,
|
||||
[ --enable-libdir-pkgconfig Install to $libdir/pkgconfig on any OS, default=no],
|
||||
, enable_libdir_pkgconfig="no")
|
||||
AC_MSG_CHECKING([for --enable-libdir-pkgconfig])
|
||||
if test "x$enable_libdir_pkgconfig" = xyes
|
||||
then
|
||||
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
|
||||
fi
|
||||
AC_MSG_RESULT([$enable_libdir_pkgconfig])
|
||||
fi
|
||||
|
||||
libburnia_pkgconfig_override="no"
|
||||
AC_ARG_ENABLE(pkgconfig-path,
|
||||
[ --enable-pkgconfig-path=DIR Absolute path of directory for libisofs-*.pc],
|
||||
libburnia_pkgconfig_override="yes" , enable_pkgconfig_path="none")
|
||||
AC_MSG_CHECKING([for overridden pkgconfig directory path])
|
||||
if test "x$enable_pkgconfig_path" = xno
|
||||
then
|
||||
libburnia_pkgconfig_override="no"
|
||||
fi
|
||||
if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes
|
||||
then
|
||||
libburnia_pkgconfig_override="invalid argument"
|
||||
fi
|
||||
if test "x$libburnia_pkgconfig_override" = xyes
|
||||
then
|
||||
LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path"
|
||||
AC_MSG_RESULT([$LIBBURNIA_PKGCONFDIR])
|
||||
else
|
||||
AC_MSG_RESULT([$libburnia_pkgconfig_override])
|
||||
fi
|
||||
AC_SUBST(LIBBURNIA_PKGCONFDIR)
|
||||
|
||||
dnl For debugging only
|
||||
### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR])
|
||||
|
||||
])
|
||||
|
||||
|
44
configure.ac
44
configure.ac
@ -1,4 +1,4 @@
|
||||
AC_INIT([libisofs], [0.6.18], [http://libburnia-project.org])
|
||||
AC_INIT([libisofs], [0.6.24], [http://libburnia-project.org])
|
||||
AC_PREREQ([2.50])
|
||||
dnl AC_CONFIG_HEADER([config.h])
|
||||
|
||||
@ -37,14 +37,14 @@ dnl iso_lib_version(). It returns the major, minor and micro revision of the
|
||||
dnl library. This means LIBISOFS_*_VERSION kept its second job which does not
|
||||
dnl comply to the usual ways of configure.ac . I.e. now *officially* this is
|
||||
dnl the source code release version as announced to the public. It has no
|
||||
dnl conection to SONAME or libtool version numbering.
|
||||
dnl connection to SONAME or libtool version numbering.
|
||||
dnl It rather feeds the API function iso_lib_version().
|
||||
dnl
|
||||
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
|
||||
dnl
|
||||
LIBISOFS_MAJOR_VERSION=0
|
||||
LIBISOFS_MINOR_VERSION=6
|
||||
LIBISOFS_MICRO_VERSION=18
|
||||
LIBISOFS_MICRO_VERSION=24
|
||||
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
|
||||
|
||||
AC_SUBST(LIBISOFS_MAJOR_VERSION)
|
||||
@ -54,11 +54,11 @@ AC_SUBST(LIBISOFS_VERSION)
|
||||
|
||||
dnl Libtool versioning
|
||||
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
|
||||
# 2009.04.15: development jump has not yet happened
|
||||
# SONAME = 20 - 14 = 6 . Library name = libisofs.6.14.0
|
||||
LT_CURRENT=20
|
||||
# 2009.10.08 development jump has not yet happened
|
||||
# SONAME = 26 - 20 = 6 . Library name = libisofs.6.20.0
|
||||
LT_CURRENT=26
|
||||
LT_REVISION=0
|
||||
LT_AGE=14
|
||||
LT_AGE=20
|
||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||
|
||||
AC_SUBST(LT_RELEASE)
|
||||
@ -87,7 +87,8 @@ fi
|
||||
|
||||
dnl If iconv(3) is in an extra lib, then it gets added to variable LIBS.
|
||||
dnl If not, then no -liconv will be added.
|
||||
AC_CHECK_LIB(iconv, iconv, , )
|
||||
LIBBURNIA_CHECK_ICONV
|
||||
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
AC_SUBST(LIBTOOL_DEPS)
|
||||
@ -124,14 +125,12 @@ AC_SUBST(THREAD_LIBS)
|
||||
|
||||
TARGET_SHIZZLE
|
||||
AC_SUBST(ARCH)
|
||||
AC_SUBST(LIBBURNIA_PKGCONFDIR)
|
||||
AC_SUBST(LIBBURN_ARCH_LIBS)
|
||||
|
||||
dnl Add compiler-specific flags
|
||||
|
||||
dnl See if the user wants aggressive optimizations of the code
|
||||
AC_ARG_ENABLE(debug,
|
||||
[ --enable-debug Disable aggressive optimizations [default=yes]],
|
||||
[ --enable-debug Disable aggressive optimizations, default=yes],
|
||||
, enable_debug=yes)
|
||||
if test x$enable_debug != xyes; then
|
||||
if test x$GCC = xyes; then
|
||||
@ -148,15 +147,22 @@ fi
|
||||
|
||||
dnl Verbose debug to make libisofs issue more debug messages
|
||||
AC_ARG_ENABLE(verbose-debug,
|
||||
[ --enable-verbose-debug Enable verbose debug messages [default=no]],
|
||||
[ --enable-verbose-debug Enable verbose debug messages, default=no],
|
||||
AC_DEFINE(LIBISOFS_VERBOSE_DEBUG, 1))
|
||||
|
||||
|
||||
dnl ts A90123
|
||||
dnl Determine target directory for libisofs-*.pc
|
||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
||||
dnl
|
||||
LIBBURNIA_SET_PKGCONFIG
|
||||
|
||||
|
||||
dnl Add compiler-specific flags
|
||||
|
||||
AC_ARG_ENABLE(libacl,
|
||||
[ --enable-libacl Enable use of libacl by libisofs, default=yes],
|
||||
[ --enable-libacl Enable use of libacl by libisofs, default=yes],
|
||||
, enable_libacl=yes)
|
||||
if test x$enable_libacl = xyes; then
|
||||
if test "x$enable_libacl" = xyes; then
|
||||
dnl Check whether there is libacl-devel and libacl-runtime.
|
||||
dnl If not, erase this macro which would enable use of acl_to_text and others
|
||||
LIBACL_DEF="-DLibisofs_with_aaip_acL"
|
||||
@ -170,9 +176,9 @@ AC_SUBST(LIBACL_DEF)
|
||||
|
||||
dnl ts A90123
|
||||
AC_ARG_ENABLE(xattr,
|
||||
[ --enable-xattr Enable use of xattr by libisofs, default=yes],
|
||||
[ --enable-xattr Enable use of xattr by libisofs, default=yes],
|
||||
, enable_xattr=yes)
|
||||
if test x$enable_xattr = xyes; then
|
||||
if test "x$enable_xattr" = xyes; then
|
||||
dnl Check whether there is the header for Linux xattr.
|
||||
dnl If not, erase this macro which would enable use of listxattr and others
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
@ -185,9 +191,9 @@ AC_SUBST(XATTR_DEF)
|
||||
|
||||
dnl ts A90409
|
||||
AC_ARG_ENABLE(zlib,
|
||||
[ --enable-zlib Enable use of zlib by libisofs, default=yes],
|
||||
[ --enable-zlib Enable use of zlib by libisofs, default=yes],
|
||||
, enable_zlib=yes)
|
||||
if test x$enable_zlib = xyes; then
|
||||
if test "x$enable_zlib" = xyes; then
|
||||
dnl Check whether there is the header for zlib.
|
||||
dnl If not, erase this macro which would enable use of compress2() and others.
|
||||
dnl The empty parameter after "compress2" causes -lz.
|
||||
|
854
demo/demo.c
Normal file
854
demo/demo.c
Normal file
@ -0,0 +1,854 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 - 2009 Vreixo Formoso, Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*
|
||||
*/
|
||||
|
||||
static char helptext[][80] = {
|
||||
"",
|
||||
"This is a collection of libisofs gestures which formerly were distinct",
|
||||
"programs. The first argument chooses the gesture:",
|
||||
" -tree absolute_directory_path",
|
||||
" Import a directory and print the resulting iso tree.",
|
||||
" -find absolute_directory_path",
|
||||
" Import a directory, find matching nodes and print the",
|
||||
" resulting iso tree.",
|
||||
" -iso [options] directory output_file",
|
||||
" Create an iso image from a local directory. For options see",
|
||||
" output of -iso -h",
|
||||
" -iso_read image_file",
|
||||
" Output the contents of an iso image.",
|
||||
" -iso_cat image_file path_in_image",
|
||||
" Extract a file from a given ISO image and put out its content",
|
||||
" to stdout. The file is addressed by path_in_image.",
|
||||
" -iso_modify image_file absolute_directory_path output_file",
|
||||
" Load an iso image, add a directory, and write complete image.",
|
||||
" -iso_ms image_lba nwa image_file directory_path output_file",
|
||||
" Load an iso image, add a directory, and write as add-on",
|
||||
" session which shall be appended to the old image.",
|
||||
" image_lba gives the block address of the start of the most",
|
||||
" recent session in the image_file. nwa gives the block address",
|
||||
" where the add-on session will be appended to the image.",
|
||||
"@"
|
||||
};
|
||||
|
||||
|
||||
#define LIBISOFS_WITHOUT_LIBBURN yes
|
||||
#include "libisofs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
|
||||
#define LIBISOFS_WITHOUT_LIBBURN yes
|
||||
#include "libisofs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
|
||||
/* ------------------------- from demo/tree.c ----------------------- */
|
||||
|
||||
static void
|
||||
print_permissions(mode_t mode)
|
||||
{
|
||||
char perm[10];
|
||||
|
||||
/* TODO suid, sticky... */
|
||||
|
||||
perm[9] = '\0';
|
||||
perm[8] = mode & S_IXOTH ? 'x' : '-';
|
||||
perm[7] = mode & S_IWOTH ? 'w' : '-';
|
||||
perm[6] = mode & S_IROTH ? 'r' : '-';
|
||||
perm[5] = mode & S_IXGRP ? 'x' : '-';
|
||||
perm[4] = mode & S_IWGRP ? 'w' : '-';
|
||||
perm[3] = mode & S_IRGRP ? 'r' : '-';
|
||||
perm[2] = mode & S_IXUSR ? 'x' : '-';
|
||||
perm[1] = mode & S_IWUSR ? 'w' : '-';
|
||||
perm[0] = mode & S_IRUSR ? 'r' : '-';
|
||||
printf("[%s]",perm);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_print_dir(IsoDir *dir, int level)
|
||||
{
|
||||
int i;
|
||||
IsoDirIter *iter;
|
||||
IsoNode *node;
|
||||
char *sp = alloca(level * 2 + 1);
|
||||
|
||||
for (i = 0; i < level * 2; i += 2) {
|
||||
sp[i] = '|';
|
||||
sp[i+1] = ' ';
|
||||
}
|
||||
|
||||
sp[level * 2-1] = '-';
|
||||
sp[level * 2] = '\0';
|
||||
|
||||
iso_dir_get_children(dir, &iter);
|
||||
while (iso_dir_iter_next(iter, &node) == 1) {
|
||||
|
||||
if (ISO_NODE_IS_DIR(node)) {
|
||||
printf("%s+[D] ", sp);
|
||||
print_permissions(iso_node_get_permissions(node));
|
||||
printf(" %s\n", iso_node_get_name(node));
|
||||
tree_print_dir(ISO_DIR(node), level+1);
|
||||
} else if (ISO_NODE_IS_FILE(node)) {
|
||||
printf("%s-[F] ", sp);
|
||||
print_permissions(iso_node_get_permissions(node));
|
||||
printf(" %s\n", iso_node_get_name(node) );
|
||||
} else if (ISO_NODE_IS_SYMLINK(node)) {
|
||||
printf("%s-[L] ", sp);
|
||||
print_permissions(iso_node_get_permissions(node));
|
||||
printf(" %s -> %s \n", iso_node_get_name(node),
|
||||
iso_symlink_get_dest(ISO_SYMLINK(node)) );
|
||||
} else {
|
||||
printf("%s-[C] ", sp);
|
||||
print_permissions(iso_node_get_permissions(node));
|
||||
printf(" %s\n", iso_node_get_name(node) );
|
||||
}
|
||||
}
|
||||
iso_dir_iter_free(iter);
|
||||
}
|
||||
|
||||
int gesture_tree(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
|
||||
if (argc != 2) {
|
||||
need_abs_path:;
|
||||
fprintf (stderr, "You need to specify a valid absolute path\n");
|
||||
return 1;
|
||||
}
|
||||
if (argv[1][0] != '/')
|
||||
goto need_abs_path;
|
||||
|
||||
iso_init();
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("================= IMAGE =================\n");
|
||||
tree_print_dir(iso_image_get_root(image), 0);
|
||||
printf("\n\n");
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/find.c ----------------------- */
|
||||
|
||||
static void
|
||||
find_print_dir(IsoDir *dir)
|
||||
{
|
||||
IsoDirIter *iter;
|
||||
IsoNode *node;
|
||||
IsoFindCondition *cond, *c1, *c2;
|
||||
|
||||
c1 = iso_new_find_conditions_name("*a*");
|
||||
c2 = iso_new_find_conditions_mode(S_IFREG);
|
||||
cond = iso_new_find_conditions_and(c1, c2);
|
||||
iso_dir_find_children(dir, cond, &iter);
|
||||
while (iso_dir_iter_next(iter, &node) == 1) {
|
||||
char *path = iso_tree_get_node_path(node);
|
||||
printf(" %s\n", path);
|
||||
free(path);
|
||||
}
|
||||
iso_dir_iter_free(iter);
|
||||
}
|
||||
|
||||
int gesture_find(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
|
||||
if (argc != 2) {
|
||||
need_abs_path:;
|
||||
fprintf (stderr, "You need to specify a valid absolute path\n");
|
||||
return 1;
|
||||
}
|
||||
if (argv[1][0] != '/')
|
||||
goto need_abs_path;
|
||||
|
||||
iso_init();
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
find_print_dir(iso_image_get_root(image));
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/iso.c ----------------------- */
|
||||
|
||||
|
||||
static const char * const optstring = "JRIL:b:hV:";
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
void iso_usage(char **argv)
|
||||
{
|
||||
printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]);
|
||||
}
|
||||
|
||||
void iso_help()
|
||||
{
|
||||
printf(
|
||||
"Options:\n"
|
||||
" -J Add Joliet support\n"
|
||||
" -R Add Rock Ridge support\n"
|
||||
" -I Add ISO 9660:1999 support\n"
|
||||
" -V label Volume Label\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"
|
||||
);
|
||||
}
|
||||
|
||||
int iso_callback(IsoFileSource *src)
|
||||
{
|
||||
char *path = iso_file_source_get_path(src);
|
||||
printf("CALLBACK: %s\n", path);
|
||||
free(path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gesture_iso(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
int c;
|
||||
IsoImage *image;
|
||||
struct burn_source *burn_src;
|
||||
unsigned char buf[2048];
|
||||
FILE *fd;
|
||||
IsoWriteOpts *opts;
|
||||
char *volid = "VOLID";
|
||||
char *boot_img = NULL;
|
||||
int rr = 0, j = 0, iso1999 = 0, level = 1;
|
||||
|
||||
while ((c = getopt(argc, argv, optstring)) != -1) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
iso_usage(argv);
|
||||
iso_help();
|
||||
exit(0);
|
||||
break;
|
||||
case 'J':
|
||||
j = 1;
|
||||
break;
|
||||
case 'R':
|
||||
rr = 1;
|
||||
break;
|
||||
case 'I':
|
||||
iso1999 = 1;
|
||||
break;
|
||||
case 'L':
|
||||
level = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
boot_img = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
volid = optarg;
|
||||
break;
|
||||
case '?':
|
||||
iso_usage(argv);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Please pass directory from which to build ISO\n");
|
||||
iso_usage(argv);
|
||||
return 1;
|
||||
}
|
||||
if (argc < 3) {
|
||||
printf ("Please supply output file\n");
|
||||
iso_usage(argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = fopen(argv[optind+1], "w");
|
||||
if (!fd) {
|
||||
err(1, "error opening output file");
|
||||
}
|
||||
|
||||
result = iso_init();
|
||||
if (result < 0) {
|
||||
printf ("Can't initialize libisofs\n");
|
||||
return 1;
|
||||
}
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
result = iso_image_new(volid, &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
return 1;
|
||||
}
|
||||
iso_tree_set_follow_symlinks(image, 0);
|
||||
iso_tree_set_ignore_hidden(image, 0);
|
||||
iso_tree_set_ignore_special(image, 0);
|
||||
iso_set_abort_severity("SORRY");
|
||||
/*iso_tree_set_report_callback(image, callback);*/
|
||||
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image),
|
||||
argv[optind]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (boot_img) {
|
||||
/* adds El-Torito boot info. Tunned for isolinux */
|
||||
ElToritoBootImage *bootimg;
|
||||
result = iso_image_set_boot_image(image, boot_img, ELTORITO_NO_EMUL,
|
||||
"/isolinux/boot.cat", &bootimg);
|
||||
if (result < 0) {
|
||||
printf ("Error adding boot image %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
el_torito_set_load_size(bootimg, 4);
|
||||
el_torito_patch_isolinux_image(bootimg);
|
||||
}
|
||||
|
||||
result = iso_write_opts_new(&opts, 0);
|
||||
if (result < 0) {
|
||||
printf ("Cant create write opts, error %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
iso_write_opts_set_iso_level(opts, level);
|
||||
iso_write_opts_set_rockridge(opts, rr);
|
||||
iso_write_opts_set_joliet(opts, j);
|
||||
iso_write_opts_set_iso1999(opts, iso1999);
|
||||
|
||||
result = iso_image_create_burn_source(image, opts, &burn_src);
|
||||
if (result < 0) {
|
||||
printf ("Cant create image, error %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
iso_write_opts_free(opts);
|
||||
|
||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
||||
fwrite(buf, 1, 2048, fd);
|
||||
}
|
||||
fclose(fd);
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/iso_read.c ----------------------- */
|
||||
|
||||
|
||||
static void
|
||||
iso_read_print_type(mode_t mode)
|
||||
{
|
||||
switch(mode & S_IFMT) {
|
||||
case S_IFSOCK: printf("[S] "); break;
|
||||
case S_IFLNK: printf("[L] "); break;
|
||||
case S_IFREG: printf("[R] "); break;
|
||||
case S_IFBLK: printf("[B] "); break;
|
||||
case S_IFDIR: printf("[D] "); break;
|
||||
case S_IFIFO: printf("[F] "); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iso_read_print_file_src(IsoFileSource *file)
|
||||
{
|
||||
struct stat info;
|
||||
char *name;
|
||||
iso_file_source_lstat(file, &info);
|
||||
iso_read_print_type(info.st_mode);
|
||||
print_permissions(info.st_mode);
|
||||
printf(" %10.f ", (double) info.st_size);
|
||||
/* printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino); */
|
||||
name = iso_file_source_get_name(file);
|
||||
printf(" %s", name);
|
||||
free(name);
|
||||
if (S_ISLNK(info.st_mode)) {
|
||||
char buf[PATH_MAX];
|
||||
iso_file_source_readlink(file, buf, PATH_MAX);
|
||||
printf(" -> %s\n", buf);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
iso_read_print_dir(IsoFileSource *dir, int level)
|
||||
{
|
||||
int ret, i;
|
||||
IsoFileSource *file;
|
||||
struct stat info;
|
||||
char *sp = alloca(level * 2 + 1);
|
||||
|
||||
for (i = 0; i < level * 2; i += 2) {
|
||||
sp[i] = '|';
|
||||
sp[i+1] = ' ';
|
||||
}
|
||||
|
||||
sp[level * 2-1] = '-';
|
||||
sp[level * 2] = '\0';
|
||||
|
||||
ret = iso_file_source_open(dir);
|
||||
if (ret < 0) {
|
||||
printf ("Can't open dir %d\n", ret);
|
||||
}
|
||||
while ((ret = iso_file_source_readdir(dir, &file)) == 1) {
|
||||
printf("%s", sp);
|
||||
iso_read_print_file_src(file);
|
||||
ret = iso_file_source_lstat(file, &info);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
if (S_ISDIR(info.st_mode)) {
|
||||
iso_read_print_dir(file, level + 1);
|
||||
}
|
||||
iso_file_source_unref(file);
|
||||
}
|
||||
iso_file_source_close(dir);
|
||||
if (ret < 0) {
|
||||
printf ("Can't print dir\n");
|
||||
}
|
||||
}
|
||||
|
||||
int gesture_iso_read(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImageFilesystem *fs;
|
||||
IsoDataSource *src;
|
||||
IsoFileSource *root;
|
||||
IsoReadOpts *ropts;
|
||||
|
||||
if (argc != 2) {
|
||||
printf ("You need to specify a valid path\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iso_init();
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
result = iso_data_source_new_from_file(argv[1], &src);
|
||||
if (result < 0) {
|
||||
printf ("Error creating data source\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = iso_read_opts_new(&ropts, 0);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
return 1;
|
||||
}
|
||||
result = iso_image_filesystem_new(src, ropts, 1, &fs);
|
||||
iso_read_opts_free(ropts);
|
||||
if (result < 0) {
|
||||
printf ("Error creating filesystem\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nVOLUME INFORMATION\n");
|
||||
printf("==================\n\n");
|
||||
|
||||
printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs));
|
||||
printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs));
|
||||
printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs));
|
||||
printf("System: %s\n", iso_image_fs_get_system_id(fs));
|
||||
printf("Application: %s\n", iso_image_fs_get_application_id(fs));
|
||||
printf("Copyright: %s\n", iso_image_fs_get_copyright_file_id(fs));
|
||||
printf("Abstract: %s\n", iso_image_fs_get_abstract_file_id(fs));
|
||||
printf("Biblio: %s\n", iso_image_fs_get_biblio_file_id(fs));
|
||||
|
||||
printf("\nDIRECTORY TREE\n");
|
||||
printf("==============\n");
|
||||
|
||||
result = fs->get_root(fs, &root);
|
||||
if (result < 0) {
|
||||
printf ("Can't get root %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
/* iso_read_print_file_src(root); */
|
||||
iso_read_print_dir(root, 0);
|
||||
iso_file_source_unref(root);
|
||||
|
||||
fs->close(fs);
|
||||
iso_filesystem_unref((IsoFilesystem*)fs);
|
||||
iso_data_source_unref(src);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/iso_cat.c ----------------------- */
|
||||
|
||||
|
||||
int gesture_iso_cat(int argc, char **argv)
|
||||
{
|
||||
int res;
|
||||
IsoFilesystem *fs;
|
||||
IsoFileSource *file;
|
||||
struct stat info;
|
||||
IsoDataSource *src;
|
||||
IsoReadOpts *opts;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: isocat /path/to/image /path/to/file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = iso_init();
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't init libisofs\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = iso_data_source_new_from_file(argv[1], &src);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error creating data source\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = iso_read_opts_new(&opts, 0);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
return 1;
|
||||
}
|
||||
res = iso_image_filesystem_new(src, opts, 1, &fs);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error creating filesystem\n");
|
||||
return 1;
|
||||
}
|
||||
iso_read_opts_free(opts);
|
||||
|
||||
res = fs->get_by_path(fs, argv[2], &file);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't get file, err = %d\n", res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = iso_file_source_lstat(file, &info);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't stat file, err = %d\n", res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (S_ISDIR(info.st_mode)) {
|
||||
fprintf(stderr, "Path refers to a directory!!\n");
|
||||
return 1;
|
||||
} else {
|
||||
char buf[1024];
|
||||
res = iso_file_source_open(file);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't open file, err = %d\n", res);
|
||||
return 1;
|
||||
}
|
||||
while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
|
||||
fwrite(buf, 1, res, stdout);
|
||||
}
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error reading, err = %d\n", res);
|
||||
return 1;
|
||||
}
|
||||
iso_file_source_close(file);
|
||||
}
|
||||
|
||||
iso_file_source_unref(file);
|
||||
iso_filesystem_unref(fs);
|
||||
iso_data_source_unref(src);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/iso_modify.c ----------------------- */
|
||||
|
||||
|
||||
void iso_modify_usage(char **argv)
|
||||
{
|
||||
printf("%s IMAGE DIRECTORY OUTPUT\n", argv[0]);
|
||||
}
|
||||
|
||||
int gesture_iso_modify(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
IsoDataSource *src;
|
||||
struct burn_source *burn_src;
|
||||
unsigned char buf[2048];
|
||||
FILE *fd;
|
||||
IsoWriteOpts *opts;
|
||||
IsoReadOpts *ropts;
|
||||
|
||||
if (argc < 4) {
|
||||
iso_modify_usage(argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = fopen(argv[3], "w");
|
||||
if (!fd) {
|
||||
err(1, "error opening output file");
|
||||
}
|
||||
|
||||
iso_init();
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
/* create the data source to accesss previous image */
|
||||
result = iso_data_source_new_from_file(argv[1], &src);
|
||||
if (result < 0) {
|
||||
printf ("Error creating data source\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create the image context */
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
return 1;
|
||||
}
|
||||
iso_tree_set_follow_symlinks(image, 0);
|
||||
iso_tree_set_ignore_hidden(image, 0);
|
||||
|
||||
/* import previous image */
|
||||
result = iso_read_opts_new(&ropts, 0);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
return 1;
|
||||
}
|
||||
result = iso_image_import(image, src, ropts, NULL);
|
||||
iso_read_opts_free(ropts);
|
||||
iso_data_source_unref(src);
|
||||
if (result < 0) {
|
||||
printf ("Error importing previous session %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* add new dir */
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* generate a new image with both previous and added contents */
|
||||
result = iso_write_opts_new(&opts, 1);
|
||||
if (result < 0) {
|
||||
printf("Cant create write opts, error %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
/* for isolinux: iso_write_opts_set_allow_full_ascii(opts, 1); */
|
||||
|
||||
result = iso_image_create_burn_source(image, opts, &burn_src);
|
||||
if (result < 0) {
|
||||
printf ("Cant create image, error %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
iso_write_opts_free(opts);
|
||||
|
||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
||||
fwrite(buf, 1, 2048, fd);
|
||||
}
|
||||
fclose(fd);
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/iso_ms.c ----------------------- */
|
||||
|
||||
|
||||
void iso_ms_usage(char **argv)
|
||||
{
|
||||
printf("%s LSS NWA DISC DIRECTORY OUTPUT\n", argv[0]);
|
||||
}
|
||||
|
||||
int gesture_iso_ms(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
IsoDataSource *src;
|
||||
struct burn_source *burn_src;
|
||||
unsigned char buf[2048];
|
||||
FILE *fd;
|
||||
IsoWriteOpts *opts;
|
||||
IsoReadOpts *ropts;
|
||||
uint32_t ms_block;
|
||||
|
||||
if (argc < 6) {
|
||||
iso_ms_usage(argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[3], argv[5]) == 0) {
|
||||
fprintf(stderr,
|
||||
"image_file and output_file must not be the same file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = fopen(argv[5], "w");
|
||||
if (!fd) {
|
||||
err(1, "error opening output file");
|
||||
}
|
||||
|
||||
iso_init();
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
/* create the data source to accesss previous image */
|
||||
result = iso_data_source_new_from_file(argv[3], &src);
|
||||
if (result < 0) {
|
||||
printf ("Error creating data source\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create the image context */
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
return 1;
|
||||
}
|
||||
iso_tree_set_follow_symlinks(image, 0);
|
||||
iso_tree_set_ignore_hidden(image, 0);
|
||||
|
||||
/* import previous image */
|
||||
result = iso_read_opts_new(&ropts, 0);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
return 1;
|
||||
}
|
||||
iso_read_opts_set_start_block(ropts, atoi(argv[1]));
|
||||
result = iso_image_import(image, src, ropts, NULL);
|
||||
iso_read_opts_free(ropts);
|
||||
iso_data_source_unref(src);
|
||||
if (result < 0) {
|
||||
printf ("Error importing previous session %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* add new dir */
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* generate a multisession image with new contents */
|
||||
result = iso_write_opts_new(&opts, 1);
|
||||
if (result < 0) {
|
||||
printf("Cant create write opts, error %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* round up to 32kb aligment = 16 block */
|
||||
ms_block = atoi(argv[2]);
|
||||
iso_write_opts_set_ms_block(opts, ms_block);
|
||||
iso_write_opts_set_appendable(opts, 1);
|
||||
|
||||
result = iso_image_create_burn_source(image, opts, &burn_src);
|
||||
if (result < 0) {
|
||||
printf ("Cant create image, error %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
iso_write_opts_free(opts);
|
||||
|
||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
||||
fwrite(buf, 1, 2048, fd);
|
||||
}
|
||||
fclose(fd);
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- switcher ----------------------- */
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *gesture;
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
usage:;
|
||||
fprintf(stderr, "usage: %s gesture [gesture_options]\n", argv[0]);
|
||||
for (i = 0; helptext[i][0] != '@'; i++)
|
||||
fprintf(stderr, "%s\n", helptext[i]);
|
||||
exit(1);
|
||||
}
|
||||
for (gesture = argv[1]; *gesture == '-'; gesture++);
|
||||
if (strcmp(gesture, "tree") == 0) {
|
||||
gesture_tree(argc - 1, &(argv[1]));
|
||||
} else if(strcmp(gesture, "find") == 0) {
|
||||
gesture_find(argc - 1, &(argv[1]));
|
||||
} else if(strcmp(gesture, "iso") == 0) {
|
||||
gesture_iso(argc - 1, &(argv[1]));
|
||||
} else if(strcmp(gesture, "iso_read") == 0) {
|
||||
gesture_iso_read(argc - 1, &(argv[1]));
|
||||
} else if(strcmp(gesture, "iso_cat") == 0) {
|
||||
gesture_iso_cat(argc - 1, &(argv[1]));
|
||||
} else if(strcmp(gesture, "iso_modify") == 0) {
|
||||
gesture_iso_modify(argc - 1, &(argv[1]));
|
||||
} else if(strcmp(gesture, "iso_ms") == 0) {
|
||||
gesture_iso_ms(argc - 1, &(argv[1]));
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
exit(0);
|
||||
}
|
@ -15,7 +15,7 @@ print_permissions(mode_t mode)
|
||||
{
|
||||
char perm[10];
|
||||
|
||||
//TODO suid, sticky...
|
||||
/* TODO suid, sticky... */
|
||||
|
||||
perm[9] = '\0';
|
||||
perm[8] = mode & S_IXOTH ? 'x' : '-';
|
||||
@ -51,8 +51,8 @@ print_file_src(IsoFileSource *file)
|
||||
iso_file_source_lstat(file, &info);
|
||||
print_type(info.st_mode);
|
||||
print_permissions(info.st_mode);
|
||||
printf(" %10llu ", info.st_size);
|
||||
//printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
|
||||
printf(" %10.f ", (double) info.st_size);
|
||||
/* printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino); */
|
||||
name = iso_file_source_get_name(file);
|
||||
printf(" %s", name);
|
||||
free(name);
|
||||
@ -156,7 +156,7 @@ int main(int argc, char **argv)
|
||||
printf ("Can't get root %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
//print_file_src(root);
|
||||
/* print_file_src(root); */
|
||||
print_dir(root, 0);
|
||||
iso_file_source_unref(root);
|
||||
|
||||
|
@ -15,7 +15,7 @@ print_permissions(mode_t mode)
|
||||
{
|
||||
char perm[10];
|
||||
|
||||
//TODO suid, sticky...
|
||||
/* TODO suid, sticky... */
|
||||
|
||||
perm[9] = '\0';
|
||||
perm[8] = mode & S_IXOTH ? 'x' : '-';
|
||||
|
282
doc/checksums.txt
Normal file
282
doc/checksums.txt
Normal file
@ -0,0 +1,282 @@
|
||||
|
||||
Description of libisofs MD5 checksumming
|
||||
|
||||
by Thomas Schmitt - mailto:scdbackup@gmx.net
|
||||
Libburnia project - mailto:libburn-hackers@pykix.org
|
||||
26 Aug 2009
|
||||
|
||||
|
||||
MD5 is a 128 bit message digest with a very low probability to be the same for
|
||||
any pair of differing data files. It is described in RFC 1321. and can be
|
||||
computed e.g. by program md5sum.
|
||||
|
||||
libisofs can equip its images with MD5 checksums for superblock, directory
|
||||
tree, the whole session, and for each single data file.
|
||||
See libisofs.h, iso_write_opts_set_record_md5().
|
||||
|
||||
The data file checksums get loaded together with the directory tree if this
|
||||
is enabled by iso_read_opts_set_no_md5(). Loaded checksums can be inquired by
|
||||
iso_image_get_session_md5() and iso_file_get_md5().
|
||||
|
||||
Stream recognizable checksum tags occupy exactly one block each. They can
|
||||
be detected by submitting a block to iso_util_decode_md5_tag().
|
||||
|
||||
libisofs has own MD5 computation functions:
|
||||
iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end(),
|
||||
iso_md5_match()
|
||||
|
||||
|
||||
Representation in the Image
|
||||
|
||||
There may be several stream recognizable checksum tags and a compact array
|
||||
of MD5 items at the end of the session. The latter allows to quickly load many
|
||||
file checksums from media with slow random access.
|
||||
|
||||
|
||||
The Checksum Array
|
||||
|
||||
Location and layout of the checksum array is recorded as AAIP attribute
|
||||
"isofs.ca" of the root node.
|
||||
See doc/susp_aaip_2_0.txt for a general description of AAIP and
|
||||
doc/susp_aaip_isofs_names.txt for the layout of "isofs.ca".
|
||||
|
||||
The single data files hold an index to their MD5 checksum in individual AAIP
|
||||
attributes "isofs.cx". Index I means: array base address + 16 * I.
|
||||
|
||||
If there are N checksummed data files then the array consists of N + 2 entries
|
||||
with 16 bytes each.
|
||||
|
||||
Entry number 0 holds a session checksum which covers the range from the session
|
||||
start block up to (but not including) the start block of the checksum area.
|
||||
This range is described by attribute "isofs.ca" of the root node.
|
||||
|
||||
Entries 1 to N hold the checksums of individual data files.
|
||||
|
||||
Entry number N + 1 holds the MD5 checksum of entries 0 to N.
|
||||
|
||||
|
||||
The Checksum Tags
|
||||
|
||||
Because the inquiry of AAIP attributes demands loading of the image tree,
|
||||
there are also checksum tags which can be detected on the fly when reading
|
||||
and checksumming the session from the start point as learned from a media
|
||||
table-of-content.
|
||||
|
||||
The superblock checksum tag is written after the ECMA-119 volume descriptors.
|
||||
The tree checksum tag is written after the ECMA-119 directory entries.
|
||||
The session checksum tag is written after all payload including the checksum
|
||||
array. (Then follows eventual padding.)
|
||||
|
||||
The tags are single lines of printable text at the very beginning of a block
|
||||
of 2048 bytes. They have the following format:
|
||||
|
||||
Tag_id pos=# range_start=# range_size=# [session_start|next=#] md5=# self=#\n
|
||||
|
||||
Tag_id distinguishes the following tag types
|
||||
"libisofs_rlsb32_checksum_tag_v1" Relocated 64 kB superblock tag
|
||||
"libisofs_sb_checksum_tag_v1" Superblock tag
|
||||
"libisofs_tree_checksum_tag_v1" Directory tree tag
|
||||
"libisofs_checksum_tag_v1" Session tag
|
||||
|
||||
A relocated superblock may appear at LBA 0 of an image which was produced for
|
||||
being stored in a disk file or on overwriteable media (e.g. DVD+R, BD-RE).
|
||||
Typically there is a first session recorded with a superblock at LBA 32 and
|
||||
the next session may follow shortly after its session tag. (Typically at the
|
||||
next block address which is divisible by 32.) Normally no session starts after
|
||||
the address given by parameter session_start=.
|
||||
|
||||
Session oriented media like CD-R[W], DVD+R, BD-R will have no relocated
|
||||
superblock but rather bear a table-of-content on media level (to be inquired
|
||||
by MMC commands).
|
||||
|
||||
|
||||
Example:
|
||||
A relocated superblock which points to the last session. Then the first session
|
||||
which starts at Logical Block Address 32. The following sessions have the same
|
||||
structure as the first one.
|
||||
|
||||
LBA 0:
|
||||
<... ECMA-119 System Area and Volume Descriptors ...>
|
||||
LBA 18:
|
||||
libisofs_rlsb32_checksum_tag_v1 pos=18 range_start=0 range_size=18 session_start=311936 md5=6fd252d5b1db52b3c5193447081820e4 self=526f7a3c7fefce09754275c6b924b6d9
|
||||
<... padding up to LBA 32 ...>
|
||||
LBA 32:
|
||||
<... First Session: ECMA-119 System Area and Volume Descriptors ...>
|
||||
libisofs_sb_checksum_tag_v1 pos=50 range_start=32 range_size=18 md5=17471035f1360a69eedbd1d0c67a6aa2 self=52d602210883eeababfc9cd287e28682
|
||||
<... ECMA-119 Directory Entries (the tree of file names) ...>
|
||||
LBA 334:
|
||||
libisofs_tree_checksum_tag_v1 pos=334 range_start=32 range_size=302 md5=41acd50285339be5318decce39834a45 self=fe100c338c8f9a494a5432b5bfe6bf3c
|
||||
<... Data file payload and checksum array ...>
|
||||
LBA 81554:
|
||||
libisofs_checksum_tag_v1 pos=81554 range_start=32 range_size=81522 md5=8adb404bdf7f5c0a078873bb129ee5b9 self=57c2c2192822b658240d62cbc88270cb
|
||||
|
||||
<... more sessions ...>
|
||||
|
||||
LBA 311936:
|
||||
<... Last Session: ECMA-119 System Area and Volume Descriptors ...>
|
||||
LBA 311954:
|
||||
libisofs_sb_checksum_tag_v1 pos=311954 range_start=311936 range_size=18 next=312286 md5=7f1586e02ac962432dc859a4ae166027 self=2c5fce263cd0ca6984699060f6253e62
|
||||
<... Last Session: tree, tree checksum tag, data payload, session tag ...>
|
||||
|
||||
|
||||
There are several tag parameters. Addresses are given as decimal numbers, MD5
|
||||
checksums as strings of 32 hex digits.
|
||||
|
||||
pos=
|
||||
gives the block address where the tag supposes itself to be stored.
|
||||
If this does not match the block address where the tag is found then this
|
||||
either indicates that the tag is payload of the image or that the image has
|
||||
been relocated. (The latter makes the image unusable.)
|
||||
|
||||
range_start=
|
||||
The block address where the session is supposed to start. If this does not
|
||||
match the session start on media then the volume descriptors of the
|
||||
image have been relocated. (This can happen with overwriteable media. If
|
||||
checksumming started at LBA 0 and finds range_start=32, then one has to
|
||||
restart checksumming at LBA 32. See libburn/doc/cookbook.txt
|
||||
"ISO 9660 multi-session emulation on overwriteable media" for background
|
||||
information.)
|
||||
|
||||
range_size=
|
||||
The number of blocks beginning at range_start which are covered by the
|
||||
checksum of the tag.
|
||||
|
||||
Only with superblock tag and tree tag:
|
||||
next=
|
||||
The block address where the next tag is supposed to be found. This is
|
||||
to avoid the small possibility that a checksum tag with matching position
|
||||
is part of a directory entry or data file. The superblock tag is quite
|
||||
uniquely placed directly after the ECMA-119 Volume Descriptor Set Terminator
|
||||
where no such cleartext is supposed to reside by accident.
|
||||
|
||||
Only with relocated 64 kB superblock tag:
|
||||
session_start=
|
||||
The start block address (System Area) of the session to which the relocated
|
||||
superblock points.
|
||||
|
||||
md5=
|
||||
The checksum payload of the tag as lower case hex digits.
|
||||
|
||||
self=
|
||||
The MD5 checksum of the tag itself up to and including the last hex digit of
|
||||
parameter "md5=".
|
||||
|
||||
The newline character at the end is mandatory. After that newline there may
|
||||
follow more lines. Their meaning is not necessarily described in this document.
|
||||
|
||||
One such line type is the scdbackup checksum tag, an ancestor of libisofs tags
|
||||
which is suitable only for single session images which begin at LBA 0. It bears
|
||||
a checksum record which by its MD5 covers all bytes from LBA 0 up to the
|
||||
newline character preceding the scdbackup tag. See scdbackup/README appendix
|
||||
VERIFY for details.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Usage at Read Time
|
||||
|
||||
Checking Before Image Tree Loading
|
||||
|
||||
In order to check for a trustworthy loadable image tree, read the first 32
|
||||
blocks from to the session start and look in block 16 to 32 for a superblock
|
||||
checksum tag by
|
||||
iso_util_decode_md5_tag(block, &tag_type, &pos,
|
||||
&range_start, &range_size, &next_tag, md5, 0);
|
||||
|
||||
If a tag of type 2 or 4 appears and has plausible parameters, then check
|
||||
whether its MD5 matches the MD5 of the data blocks which were read before.
|
||||
|
||||
With tag type 2:
|
||||
|
||||
Keep the original MD5 context of the data blocks and clone one for obtaining
|
||||
the MD5 bytes.
|
||||
If the MD5s match, then compute the checksum block and all folowing ones into
|
||||
the kept MD5 context and go on with reading and computing for the tree checksum
|
||||
tag. This will be found at block address next_tag, verified and parsed by:
|
||||
iso_util_decode_md5_tag(block, &tag_type, &pos,
|
||||
&range_start, &range_size, &next_tag, md5, 3);
|
||||
|
||||
Again, if the parameters match the reading state, the MD5 must match the
|
||||
MD5 computed from the data blocks which were before.
|
||||
If so, then the tree is ok and safe to be loaded by iso_image_import().
|
||||
|
||||
With tag type 4:
|
||||
|
||||
End the MD5 context and start a new context for the session which you will
|
||||
read next.
|
||||
|
||||
Then look for the actual session by starting to read at the address given by
|
||||
parameter session_start= which is returned by iso_util_decode_md5_tag() as
|
||||
next_tag. Go on by looking for tag type 2 and follow above prescription.
|
||||
|
||||
|
||||
Checking the Data Part of the Session
|
||||
|
||||
In order to check the trustworthyness of a whole session, continue reading
|
||||
and checksumming after the tree was verified.
|
||||
|
||||
Read and checksum the blocks. When reaching block address next_tag (from the
|
||||
tree tag) submit this block to
|
||||
|
||||
iso_util_decode_md5_tag(block, &tag_type, &pos,
|
||||
&range_start, &range_size, &next_tag, md5, 1);
|
||||
|
||||
If this returns 1, then check whether the returned parameters pos, range_start,
|
||||
and range_size match the state of block reading, and whether the returned
|
||||
bytes in parameter md5 match the MD5 computed from the data blocks which were
|
||||
read before the tag block.
|
||||
|
||||
|
||||
Checking All Sessions
|
||||
|
||||
If the media is sequentially recordable, obtain a table of content and check
|
||||
the first track of each session as prescribed above in Checking Before Image
|
||||
Tree Loading and in Checking the Data Part of the Session.
|
||||
|
||||
With disk files or overwriteable media, look for a relocated superblock tag
|
||||
but do not hop to address next_tag (given by session_start=). Instead look at
|
||||
LBA 32 for the first session and check it as prescribed above.
|
||||
After reaching its end, round up the read address to the next multiple of 32
|
||||
and check whether it is smaller than session_start= from the super block.
|
||||
If so, expect another session to start there.
|
||||
|
||||
|
||||
Checking Single Files in a Loaded Image
|
||||
|
||||
An image may consist of many sessions wherein many data blocks may not belong
|
||||
to files in the directory tree of the most recent session. Checking this
|
||||
tree and all its data files can ensure that all actually valid data in the
|
||||
image are trustworthy. This will leave out the trees of the older sessions
|
||||
and the obsolete data blocks of overwritten or deleted files.
|
||||
|
||||
Once the image has been loaded, you can obtain MD5 sums from IsoNode objects
|
||||
which fulfill
|
||||
iso_node_get_type(node) == LIBISO_FILE
|
||||
|
||||
The recorded checksum can be obtained by
|
||||
iso_file_get_md5(image, (IsoFile *) node, md5, 0);
|
||||
|
||||
For accessing the file data in the loaded image use
|
||||
iso_file_get_stream((IsoFile *) node);
|
||||
to get the data stream of the object.
|
||||
The checksums cover the data content as it was actually written into the ISO
|
||||
image stream, not necessarily as it was on hard disk before or afterwards.
|
||||
This implies that content filtered files bear the MD5 of the filtered data
|
||||
and not of the original files on disk. When checkreading, one has to avoid
|
||||
any reverse filtering. Dig out the stream which directly reads image data
|
||||
by calling iso_stream_get_input_stream() until it returns NULL and use
|
||||
iso_stream_get_size() rather than iso_file_get_size().
|
||||
|
||||
Now you may call iso_stream_open(), iso_stream_read(), iso_stream_close()
|
||||
for reading file content from the loaded image.
|
||||
|
||||
|
||||
Session Check in a Loaded Image
|
||||
|
||||
iso_image_get_session_md5() gives start LBA and session payload size as of
|
||||
"isofs.ca" and the session checksum as of the checksum array.
|
||||
|
||||
For reading you may use the IsoDataSource object which you submitted
|
||||
to iso_image_import() when reading the image. If this source is associated
|
||||
to a libburn drive, then libburn function burn_read_data() can read directly
|
||||
from it.
|
||||
|
@ -12,6 +12,93 @@ specification of AAIP :
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.ca
|
||||
|
||||
Purpose:
|
||||
Records the range of checksummed image data (START, END), the number
|
||||
of checksum items (COUNT), the number of bytes in a single checksum item
|
||||
(SIZE), and the name of the checksum algorithm (CHECKSUM_TYPE).
|
||||
END is also the block address of the start of the checksum recording
|
||||
area in the image.
|
||||
See also isofs.cx .
|
||||
|
||||
Format of Value:
|
||||
START_LEN | START_BYTES | END_LEN | END_BYTES |
|
||||
COUNT_LEN | COUNT_BYTES | SIZE_LEN | SIZE_BYTES | CHECKSUM_TYPE
|
||||
Each number is encoded as _LEN byte and _BYTES value string.
|
||||
The _LEN fields comply to ISO 9660 Format section 7.1.1.
|
||||
The byte strings START_BYTES, END_BYTES, COUNT_BYTES, SIZE_BYTES begin
|
||||
with the most significant byte. Leading zero bytes are allowed.
|
||||
CHECKSUM_TYPE consists of the bytes after
|
||||
START_LEN + END_LEN + COUNT_LEN + SIZE_LEN + 4.
|
||||
It shall be a string of printable characters without terminating 0-byte.
|
||||
Type names shall be registered here.
|
||||
For now there is:
|
||||
"MD5" 128 bit message digest, see RFC 1321, see man md5sum
|
||||
|
||||
Example:
|
||||
LBA range 32 to 1000000 , 520 checksums recorded, MD5
|
||||
{ 1, 32,
|
||||
3, 15, 66, 64,
|
||||
2, 2, 8,
|
||||
1, 16,
|
||||
'M', 'D', '5' }
|
||||
or
|
||||
{ 4, 0, 0, 0, 32,
|
||||
4, 0, 15, 66, 64,
|
||||
4, 0, 0, 2, 8,
|
||||
1, 16,
|
||||
'M', 'D', '5' }
|
||||
|
||||
Registered:
|
||||
16 Jul 2009 by Thomas Schmitt for libisofs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.cs
|
||||
|
||||
Purpose:
|
||||
Records the name of the character set that was used as output character
|
||||
set when writing the RRIP name tree of the ISO 9660 image. It shall be
|
||||
suitable as parameter for function iconv_open(3).
|
||||
This attribute shall eventually be attached to the root directory entry
|
||||
and be global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
Shall hold the character set name without terminating 0-byte.
|
||||
|
||||
Example:
|
||||
{ 'I', 'S', 'O', '-', '8', '8', '5', '9' , '-', '1' }
|
||||
|
||||
Registered:
|
||||
18 Mar 2009 by Thomas Schmitt for libisofs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.cx
|
||||
|
||||
Purpose:
|
||||
Records the index of the file's checksum in the checksum area at the
|
||||
end of the image. The byte address of the checksum is
|
||||
checksum_area_lba * 2048 + isofs.cx * checksum_size
|
||||
Default checksum algorithm is MD5 with a size of 16 byte.
|
||||
See also isofs.ca .
|
||||
|
||||
Format of Value:
|
||||
A byte string which begins with the most significant byte.
|
||||
|
||||
Example:
|
||||
Index 123456
|
||||
{ 1, 226, 64 }
|
||||
|
||||
Registered:
|
||||
16 Jul 2009 by Thomas Schmitt for libisofs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.di
|
||||
|
||||
@ -31,28 +118,7 @@ Example:
|
||||
|
||||
Registered:
|
||||
17 Feb 2009 by Thomas Schmitt for xorriso.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.cs
|
||||
|
||||
Purpose:
|
||||
Records the name of the character set that was used as output character
|
||||
set when writing the RRIP name tree of the ISO 9660 image. It shall be
|
||||
suitable as parameter for function iconv_open(3).
|
||||
This attribute shall eventually be attached to the root directory entry
|
||||
and be global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
Shall hold the character set name without terminating 0-byte.
|
||||
|
||||
Example:
|
||||
{ 'I', 'S', 'O', '-', '8', '8', '5', '9' , '-', '1' }
|
||||
|
||||
Registered:
|
||||
18 Mar 2009 by Thomas Schmitt for libisofs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
@ -78,7 +144,7 @@ Example:
|
||||
|
||||
Registered:
|
||||
03 Apr 2009 by Thomas Schmitt for xorriso.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -131,13 +131,19 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
size_t **value_lengths, char ***values, int flag)
|
||||
{
|
||||
int ret, retry= 0;
|
||||
int ret;
|
||||
char *list= NULL;
|
||||
ssize_t list_size= 0, i, num_names= 0, value_ret;
|
||||
size_t acl_len= 0;
|
||||
ssize_t list_size= 0, i, num_names= 0;
|
||||
unsigned char *acl= NULL;
|
||||
char *a_acl_text= NULL, *d_acl_text= NULL;
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
size_t acl_len= 0;
|
||||
#endif
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
ssize_t value_ret, retry= 0;
|
||||
#endif
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
{ret= 1; goto ex;}
|
||||
}
|
||||
@ -375,8 +381,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
{
|
||||
int ret, has_default_acl= 0;
|
||||
size_t i, consumed, acl_text_fill, list_size= 0, acl_idx= 0, h_consumed;
|
||||
size_t i, consumed, acl_text_fill, acl_idx= 0, h_consumed;
|
||||
char *acl_text= NULL, *list= NULL;
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
size_t list_size= 0;
|
||||
#endif
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
|
||||
#include "libisofs.h"
|
||||
|
||||
/* <<<
|
||||
*/
|
||||
/*
|
||||
#define Aaip_encode_debuG 1
|
||||
*/
|
||||
|
||||
#include "aaip_0_2.h"
|
||||
|
||||
@ -128,13 +128,7 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
||||
/* write the field headers */
|
||||
for(i= 0; i < number_of_fields; i++) {
|
||||
(*result)[i * 255 + 0]= 'A';
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
(*result)[i * 255 + 1]= 'L';
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
(*result)[i * 255 + 1]= 'A';
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
if(i < number_of_fields - 1 || (mem_size % 255) == 0)
|
||||
(*result)[i * 255 + 2]= 255;
|
||||
else
|
||||
@ -1186,16 +1180,9 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
|
||||
aaip->aa_head_missing-= todo;
|
||||
if(aaip->aa_head_missing == 0) {
|
||||
aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0);
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
if(aa_head[0] != 'A' || (aa_head[1] != 'L' && aa_head[1] != 'A') ||
|
||||
aa_head[3] != 1)
|
||||
return(-1);
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
if(aa_head[0] != 'A' || aa_head[1] != 'A' || aa_head[3] != 1)
|
||||
return(-1);
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
aaip->aa_missing= aa_head[2];
|
||||
aaip->aa_ends= !(aa_head[4] & 1);
|
||||
aaip->recs_fill-= 5; /* AAIP field heads do not get delivered */
|
||||
|
@ -92,6 +92,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
int ret;
|
||||
struct stat info;
|
||||
IsoNode *new;
|
||||
IsoFilesystem *fs;
|
||||
char *name;
|
||||
unsigned char *aa_string;
|
||||
char *a_text = NULL, *d_text = NULL;
|
||||
@ -111,6 +112,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
fs = iso_file_source_get_filesystem(src);
|
||||
new = NULL;
|
||||
|
||||
switch (info.st_mode & S_IFMT) {
|
||||
@ -154,6 +156,13 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
ret = iso_node_new_symlink(name, strdup(dest), &link);
|
||||
new = (IsoNode*) link;
|
||||
if (fs != NULL) {
|
||||
link->fs_id = fs->get_id(fs);
|
||||
if (link->fs_id != 0) {
|
||||
link->st_ino = info.st_ino;
|
||||
link->st_dev = info.st_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case S_IFSOCK:
|
||||
@ -166,6 +175,13 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
ret = iso_node_new_special(name, info.st_mode, info.st_rdev,
|
||||
&special);
|
||||
new = (IsoNode*) special;
|
||||
if (fs != NULL) {
|
||||
special->fs_id = fs->get_id(fs);
|
||||
if (special->fs_id != 0) {
|
||||
special->st_ino = info.st_ino;
|
||||
special->st_dev = info.st_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -27,11 +27,17 @@
|
||||
#include "util.h"
|
||||
#include "system_area.h"
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
#include "md5.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <langinfo.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* TODO #00011 : guard against bad path table usage with more than 65535 dirs
|
||||
@ -45,19 +51,38 @@ void ecma119_image_free(Ecma119Image *t)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
ecma119_node_free(t->root);
|
||||
iso_image_unref(t->image);
|
||||
iso_rbtree_destroy(t->files, iso_file_src_free);
|
||||
iso_ring_buffer_free(t->buffer);
|
||||
if (t == NULL)
|
||||
return;
|
||||
if (t->root != NULL)
|
||||
ecma119_node_free(t->root);
|
||||
if (t->image != NULL)
|
||||
iso_image_unref(t->image);
|
||||
if (t->files != NULL)
|
||||
iso_rbtree_destroy(t->files, iso_file_src_free);
|
||||
if (t->buffer != NULL)
|
||||
iso_ring_buffer_free(t->buffer);
|
||||
|
||||
for (i = 0; i < t->nwriters; ++i) {
|
||||
IsoImageWriter *writer = t->writers[i];
|
||||
writer->free_data(writer);
|
||||
free(writer);
|
||||
}
|
||||
free(t->input_charset);
|
||||
free(t->output_charset);
|
||||
free(t->writers);
|
||||
if (t->input_charset != NULL)
|
||||
free(t->input_charset);
|
||||
if (t->output_charset != NULL)
|
||||
free(t->output_charset);
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
if (t->checksum_ctx != NULL) { /* dispose checksum context */
|
||||
char md5[16];
|
||||
iso_md5_end(&(t->checksum_ctx), md5);
|
||||
}
|
||||
if (t->checksum_buffer != NULL)
|
||||
free(t->checksum_buffer);
|
||||
#endif
|
||||
|
||||
if (t->writers != NULL)
|
||||
free(t->writers);
|
||||
free(t);
|
||||
}
|
||||
|
||||
@ -227,6 +252,16 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
|
||||
target->path_table_size = path_table_size;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (target->md5_session_checksum) {
|
||||
/* Account for tree checksum tag */
|
||||
target->checksum_tree_tag_pos = target->curblock;
|
||||
target->curblock++;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
@ -294,7 +329,7 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
|
||||
rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0);
|
||||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
if(t->dir_rec_mtime) {
|
||||
if (t->dir_rec_mtime) {
|
||||
iso= node->node;
|
||||
iso_datetime_7(rec->recording_time,
|
||||
t->replace_timestamps ? t->timestamp : iso->mtime,
|
||||
@ -660,6 +695,17 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
|
||||
|
||||
/* and write the path tables */
|
||||
ret = write_path_tables(t);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (t->md5_session_checksum) {
|
||||
/* Write tree checksum tag */
|
||||
ret = iso_md5_write_tag(t, 3);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -783,6 +829,19 @@ int pad_writer_create(Ecma119Image *target)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int transplant_checksum_buffer(Ecma119Image *target, int flag)
|
||||
{
|
||||
/* Transplant checksum buffer from Ecma119Image to IsoImage */
|
||||
iso_image_set_checksums(target->image, target->checksum_buffer,
|
||||
target->checksum_range_start,
|
||||
target->checksum_array_pos,
|
||||
target->checksum_idx_counter + 2, 0);
|
||||
target->checksum_buffer = NULL;
|
||||
target->checksum_idx_counter = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void *write_function(void *arg)
|
||||
{
|
||||
@ -835,6 +894,18 @@ void *write_function(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/* Write superblock checksum tag */
|
||||
if (target->md5_session_checksum && target->checksum_ctx != NULL) {
|
||||
res = iso_md5_write_tag(target, 2);
|
||||
if (res < 0)
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
||||
/* write data for each writer */
|
||||
for (i = 0; i < target->nwriters; ++i) {
|
||||
writer = target->writers[i];
|
||||
@ -844,6 +915,13 @@ void *write_function(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/* Transplant checksum buffer from Ecma119Image to IsoImage */
|
||||
transplant_checksum_buffer(target, 0);
|
||||
|
||||
#endif
|
||||
|
||||
iso_ring_buffer_writer_close(target->buffer, 0);
|
||||
pthread_exit(NULL);
|
||||
|
||||
@ -857,13 +935,122 @@ void *write_function(void *arg)
|
||||
"Image write error");
|
||||
}
|
||||
iso_ring_buffer_writer_close(target->buffer, 1);
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/* Transplant checksum buffer from Ecma119Image to IsoImage */
|
||||
transplant_checksum_buffer(target, 0);
|
||||
|
||||
#endif
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
|
||||
static
|
||||
int checksum_prepare_image(IsoImage *src, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Set provisory value of isofs.ca with
|
||||
4 byte LBA, 4 byte count, size 16, name MD5 */
|
||||
ret = iso_root_set_isofsca((IsoNode *) src->root, 0, 0, 0, 16, "MD5", 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@flag bit0= recursion
|
||||
*/
|
||||
static
|
||||
int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
|
||||
{
|
||||
IsoNode *pos;
|
||||
IsoFile *file;
|
||||
IsoImage *img;
|
||||
int ret, i, no_md5 = 0, has_xinfo = 0;
|
||||
size_t value_length;
|
||||
unsigned int idx = 0;
|
||||
char *value= NULL;
|
||||
void *xipt = NULL;
|
||||
static char *cx_names = "isofs.cx";
|
||||
static size_t cx_value_lengths[1] = {0};
|
||||
char *cx_valuept = "";
|
||||
|
||||
img= target->image;
|
||||
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file = (IsoFile *) node;
|
||||
if (file->from_old_session && target->appendable) {
|
||||
/* Save MD5 data of files from old image which will not
|
||||
be copied and have an MD5 recorded in the old image. */
|
||||
has_xinfo = iso_node_get_xinfo(node, checksum_md5_xinfo_func,
|
||||
&xipt);
|
||||
if (has_xinfo <= 0) {
|
||||
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
|
||||
&value, 0);
|
||||
}
|
||||
if (has_xinfo > 0) {
|
||||
/* xinfo MD5 overrides everything else unless data get copied
|
||||
and checksummed during that copying
|
||||
*/;
|
||||
} else if (ret == 1 && img->checksum_array == NULL) {
|
||||
/* No checksum array loaded. Delete "isofs.cx" */
|
||||
iso_node_set_attrs(node, (size_t) 1,
|
||||
&cx_names, cx_value_lengths, &cx_valuept, 4 | 8);
|
||||
no_md5 = 1;
|
||||
} else if (ret == 1 && value_length == 4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||
if (idx > 0 && idx < 0x8000000) {
|
||||
/* xipt is an int disguised as void pointer */
|
||||
for (i = 0; i < 4; i++)
|
||||
((char *) &xipt)[i] = value[i];
|
||||
ret = iso_node_add_xinfo(node, checksum_cx_xinfo_func,
|
||||
xipt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else
|
||||
no_md5 = 1;
|
||||
} else {
|
||||
no_md5 = 1;
|
||||
}
|
||||
if (value != NULL) {
|
||||
free(value);
|
||||
value= NULL;
|
||||
}
|
||||
}
|
||||
/* Equip nodes with provisory isofs.cx numbers: 4 byte, all 0.
|
||||
Omit those from old image which will not be copied and have no MD5.
|
||||
*/
|
||||
if (!no_md5) {
|
||||
ret = iso_file_set_isofscx(file, (unsigned int) 0, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
} else if (node->type == LIBISO_DIR) {
|
||||
for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
|
||||
ret = checksum_prepare_nodes(target, pos, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
||||
static
|
||||
int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
{
|
||||
int ret, i, voldesc_size, nwriters;
|
||||
int ret, i, voldesc_size, nwriters, image_checksums_mad = 0;
|
||||
Ecma119Image *target;
|
||||
int el_torito_writer_index = -1, file_src_writer_index= -1;
|
||||
|
||||
@ -876,8 +1063,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
/* create the tree for file caching */
|
||||
ret = iso_rbtree_new(iso_file_src_cmp, &(target->files));
|
||||
if (ret < 0) {
|
||||
free(target);
|
||||
return ret;
|
||||
goto target_cleanup;
|
||||
}
|
||||
|
||||
target->image = src;
|
||||
@ -887,9 +1073,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->rockridge = opts->rockridge;
|
||||
target->joliet = opts->joliet;
|
||||
target->iso1999 = opts->iso1999;
|
||||
target->hardlinks = opts->hardlinks;
|
||||
target->aaip = opts->aaip;
|
||||
target->always_gmt = opts->always_gmt;
|
||||
target->ino = 0;
|
||||
target->omit_version_numbers = opts->omit_version_numbers
|
||||
| opts->max_37_char_filenames;
|
||||
target->allow_deep_paths = opts->allow_deep_paths;
|
||||
@ -901,6 +1087,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->relaxed_vol_atts = opts->relaxed_vol_atts;
|
||||
target->joliet_longer_paths = opts->joliet_longer_paths;
|
||||
target->rrip_version_1_10 = opts->rrip_version_1_10;
|
||||
target->rrip_1_10_px_ino = opts->rrip_1_10_px_ino;
|
||||
target->aaip_susp_1_10 = opts->aaip_susp_1_10;
|
||||
target->dir_rec_mtime = opts->dir_rec_mtime;
|
||||
target->sort_files = opts->sort_files;
|
||||
@ -927,20 +1114,10 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->eltorito = (src->bootcat == NULL ? 0 : 1);
|
||||
target->catalog = src->bootcat;
|
||||
|
||||
#ifndef Libisofs_setlocale_in_iniT
|
||||
/* default to locale charset */
|
||||
/* ??? ts Nov 25 2008 :
|
||||
Shouldn't this go to library initialization or even to app ?
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
target->input_charset = strdup(iso_get_local_charset(0));
|
||||
|
||||
if (target->input_charset == NULL) {
|
||||
iso_image_unref(src);
|
||||
free(target);
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto target_cleanup;
|
||||
}
|
||||
|
||||
if (opts->output_charset != NULL) {
|
||||
@ -949,11 +1126,31 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->output_charset = strdup(target->input_charset);
|
||||
}
|
||||
if (target->output_charset == NULL) {
|
||||
iso_image_unref(src);
|
||||
free(target);
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto target_cleanup;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
target->md5_file_checksums = opts->md5_file_checksums;
|
||||
target->md5_session_checksum = opts->md5_session_checksum;
|
||||
strcpy(target->scdbackup_tag_parm, opts->scdbackup_tag_parm);
|
||||
target->scdbackup_tag_written = opts->scdbackup_tag_written;
|
||||
target->checksum_idx_counter = 0;
|
||||
target->checksum_ctx = NULL;
|
||||
target->checksum_counter = 0;
|
||||
target->checksum_rlsb_tag_pos = 0;
|
||||
target->checksum_sb_tag_pos = 0;
|
||||
target->checksum_tree_tag_pos = 0;
|
||||
target->checksum_tag_pos = 0;
|
||||
target->checksum_buffer = NULL;
|
||||
target->checksum_array_pos = 0;
|
||||
target->checksum_range_start = 0;
|
||||
target->checksum_range_size = 0;
|
||||
target->opts_overwrite = 0;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2. Based on those options, create needed writers: iso, joliet...
|
||||
* Each writer inits its structures and stores needed info into
|
||||
@ -977,11 +1174,32 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
nwriters++;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
|
||||
nwriters++;
|
||||
image_checksums_mad = 1; /* from here on the loaded checksums are
|
||||
not consistent with isofs.cx any more.
|
||||
*/
|
||||
ret = checksum_prepare_image(src, 0);
|
||||
if (ret < 0)
|
||||
goto target_cleanup;
|
||||
if (target->appendable) {
|
||||
ret = checksum_prepare_nodes(target, (IsoNode *) src->root, 0);
|
||||
if (ret < 0)
|
||||
goto target_cleanup;
|
||||
}
|
||||
target->checksum_idx_counter = 0;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
||||
target->writers = malloc(nwriters * sizeof(void*));
|
||||
if (target->writers == NULL) {
|
||||
iso_image_unref(src);
|
||||
free(target);
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto target_cleanup;
|
||||
}
|
||||
|
||||
/* create writer for ECMA-119 structure */
|
||||
@ -1022,7 +1240,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
|
||||
/*
|
||||
* Create the writer for possible padding to ensure that in case of image
|
||||
* growing we can safety overwrite the first 64 KiB of image.
|
||||
* growing we can safely overwrite the first 64 KiB of image.
|
||||
*/
|
||||
ret = pad_writer_create(target);
|
||||
if (ret < 0) {
|
||||
@ -1036,6 +1254,18 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
}
|
||||
file_src_writer_index = target->nwriters - 1;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
|
||||
ret = checksum_writer_create(target);
|
||||
if (ret < 0)
|
||||
goto target_cleanup;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
||||
/*
|
||||
* 3.
|
||||
* Call compute_data_blocks() in each Writer.
|
||||
@ -1081,7 +1311,6 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
|
||||
/* check if we need to provide a copy of volume descriptors */
|
||||
if (opts->overwrite) {
|
||||
|
||||
/*
|
||||
* Get a copy of the volume descriptors to be written in a DVD+RW
|
||||
* disc
|
||||
@ -1134,6 +1363,28 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
vol->vol_desc_type[0] = 255;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/* Write relocated superblock checksum tag */
|
||||
if (target->md5_session_checksum) {
|
||||
target->checksum_rlsb_tag_pos = voldesc_size / BLOCK_SIZE + 16 + 1;
|
||||
if (target->checksum_rlsb_tag_pos < 32) {
|
||||
ret = iso_md5_start(&(target->checksum_ctx));
|
||||
if (ret < 0)
|
||||
goto target_cleanup;
|
||||
target->opts_overwrite = (char *) opts->overwrite;
|
||||
iso_md5_compute(target->checksum_ctx, target->opts_overwrite,
|
||||
target->checksum_rlsb_tag_pos * 2048);
|
||||
ret = iso_md5_write_tag(target, 4);
|
||||
target->opts_overwrite = NULL; /* opts might not persist */
|
||||
if (ret < 0)
|
||||
goto target_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1143,7 +1394,24 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->vol_space_size = target->curblock - target->ms_block;
|
||||
target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE;
|
||||
|
||||
/* 4. Create and start writting thread */
|
||||
|
||||
/* 4. Create and start writing thread */
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
if (target->md5_session_checksum) {
|
||||
/* After any fake writes are done: Initialize image checksum context */
|
||||
if (target->checksum_ctx != NULL)
|
||||
iso_md5_end(&(target->checksum_ctx), target->image_md5);
|
||||
ret = iso_md5_start(&(target->checksum_ctx));
|
||||
if (ret < 0)
|
||||
goto target_cleanup;
|
||||
}
|
||||
/* Dispose old image checksum buffer. The one of target is supposed to
|
||||
get attached at the end of write_function(). */
|
||||
iso_image_free_checksums(target->image, 0);
|
||||
image_checksums_mad = 0;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/* ensure the thread is created joinable */
|
||||
pthread_attr_init(&(target->th_attr));
|
||||
@ -1169,6 +1437,14 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
return ISO_SUCCESS;
|
||||
|
||||
target_cleanup: ;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if(image_checksums_mad) /* No checksums is better than mad checksums */
|
||||
iso_image_free_checksums(target->image, 0);
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
ecma119_image_free(target);
|
||||
return ret;
|
||||
}
|
||||
@ -1309,6 +1585,16 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
|
||||
return ISO_CANCELED;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (target->checksum_ctx != NULL) {
|
||||
/* Add to image checksum */
|
||||
target->checksum_counter += count;
|
||||
iso_md5_compute(target->checksum_ctx, (char *) buf, (int) count);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/* total size is 0 when writing the overwrite buffer */
|
||||
if (ret > 0 && (target->total_size != (off_t) 0)){
|
||||
unsigned int kbw, kbt;
|
||||
@ -1345,6 +1631,7 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
|
||||
if (wopts == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
wopts->scdbackup_tag_written = NULL;
|
||||
|
||||
switch (profile) {
|
||||
case 0:
|
||||
@ -1427,6 +1714,15 @@ int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->hardlinks = enable ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
@ -1526,6 +1822,15 @@ int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->rrip_1_10_px_ino = enable ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
@ -1553,6 +1858,57 @@ int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
opts->md5_session_checksum = session & 1;
|
||||
opts->md5_file_checksums = files & 3;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts,
|
||||
char *name, char *timestamp,
|
||||
char *tag_written)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
char eff_name[81], eff_time[19];
|
||||
int i;
|
||||
|
||||
for (i = 0; name[i] != 0 && i < 80; i++)
|
||||
if (isspace((int) ((unsigned char *) name)[i]))
|
||||
eff_name[i] = '_';
|
||||
else
|
||||
eff_name[i] = name[i];
|
||||
if (i == 0)
|
||||
eff_name[i++] = '_';
|
||||
eff_name[i] = 0;
|
||||
for (i = 0; timestamp[i] != 0 && i < 18; i++)
|
||||
if (isspace((int) ((unsigned char *) timestamp)[i]))
|
||||
eff_time[i] = '_';
|
||||
else
|
||||
eff_time[i] = timestamp[i];
|
||||
if (i == 0)
|
||||
eff_time[i++] = '_';
|
||||
eff_time[i] = 0;
|
||||
|
||||
sprintf(opts->scdbackup_tag_parm, "%s %s", eff_name, eff_time);
|
||||
|
||||
opts->scdbackup_tag_written = tag_written;
|
||||
if (tag_written != NULL)
|
||||
tag_written[0] = 0;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_replace_mode(IsoWriteOpts *opts, int dir_mode,
|
||||
int file_mode, int uid, int gid)
|
||||
{
|
||||
@ -1695,7 +2051,7 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size)
|
||||
int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start,
|
||||
int flag)
|
||||
{
|
||||
if(opts->data_start_lba == 0)
|
||||
if (opts->data_start_lba == 0)
|
||||
return ISO_ERROR;
|
||||
*data_start = opts->data_start_lba;
|
||||
return ISO_SUCCESS;
|
||||
|
@ -115,6 +115,16 @@ struct iso_write_opts {
|
||||
*/
|
||||
unsigned int rrip_version_1_10 :1;
|
||||
|
||||
/**
|
||||
* Write field PX with file serial number even with RRIP-1.10
|
||||
*/
|
||||
unsigned int rrip_1_10_px_ino :1;
|
||||
|
||||
/**
|
||||
* See iso_write_opts_set_hardlinks()
|
||||
*/
|
||||
unsigned int hardlinks:1;
|
||||
|
||||
/**
|
||||
* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12.
|
||||
* I.e. without announcing it by an ER field and thus without the need
|
||||
@ -137,6 +147,30 @@ struct iso_write_opts {
|
||||
*/
|
||||
unsigned int dir_rec_mtime :1;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/**
|
||||
* Compute MD5 checksum for the whole session and record it as index 0 of
|
||||
* the checksum blocks after the data area of the session. The layout and
|
||||
* position of these blocks will be recorded in xattr "isofs.ca" of the
|
||||
* root node. See see also API call iso_image_get_session_md5().
|
||||
*/
|
||||
unsigned int md5_session_checksum :1;
|
||||
|
||||
/**
|
||||
* Compute MD5 checksums for IsoFile objects and write them to blocks
|
||||
* after the data area of the session. The layout and position of these
|
||||
* blocks will be recorded in xattr "isofs.ca" of the root node.
|
||||
* The indice of the MD5 sums will be recorded with the IsoFile directory
|
||||
* entries as xattr "isofs.cx". See also API call iso_file_get_md5().
|
||||
* bit0= compute individual checksums
|
||||
* bit1= pre-compute checksum and compare it with actual one.
|
||||
* Raise MISHAP if mismatch.
|
||||
*/
|
||||
unsigned int md5_file_checksums :2;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/** If files should be sorted based on their weight. */
|
||||
unsigned int sort_files :1;
|
||||
|
||||
@ -247,6 +281,22 @@ struct iso_write_opts {
|
||||
*/
|
||||
uint32_t data_start_lba;
|
||||
|
||||
/**
|
||||
* If not empty: A text holding parameters "name" and "timestamp" for
|
||||
* a scdbackup stream checksum tag. See scdbackup/README appendix VERIFY.
|
||||
* It makes sense only for single session images which start at LBA 0.
|
||||
* Such a tag may be part of a libisofs checksum tag block after the
|
||||
* session tag line. It then covers the whole session up to its own start
|
||||
* position.
|
||||
*/
|
||||
char scdbackup_tag_parm[100];
|
||||
|
||||
/* If not NULL: A pointer to an application provided array with
|
||||
at least 512 characters. The effectively written scdbackup tag
|
||||
will be copied to this memory location.
|
||||
*/
|
||||
char *scdbackup_tag_written;
|
||||
|
||||
};
|
||||
|
||||
typedef struct ecma119_image Ecma119Image;
|
||||
@ -269,7 +319,9 @@ struct ecma119_image
|
||||
unsigned int eltorito :1;
|
||||
unsigned int iso1999 :1;
|
||||
|
||||
unsigned int aaip :1; /* whether to write eventual ACLs and EAs */
|
||||
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
|
||||
|
||||
unsigned int aaip :1; /* see iso_write_opts_set_aaip() */
|
||||
|
||||
/* allways write timestamps in GMT */
|
||||
unsigned int always_gmt :1;
|
||||
@ -291,12 +343,22 @@ struct ecma119_image
|
||||
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
|
||||
unsigned int rrip_version_1_10 :1;
|
||||
|
||||
/** Write field PX with file serial number even with RRIP-1.10 */
|
||||
unsigned int rrip_1_10_px_ino :1;
|
||||
|
||||
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
|
||||
unsigned int aaip_susp_1_10 :1;
|
||||
|
||||
/* Store in ECMA-119 timestamp mtime of source */
|
||||
unsigned int dir_rec_mtime :1;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
unsigned int md5_session_checksum :1;
|
||||
unsigned int md5_file_checksums :2;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/*
|
||||
* Mode replace. If one of these flags is set, the correspodent values are
|
||||
* replaced with values below.
|
||||
@ -318,12 +380,6 @@ struct ecma119_image
|
||||
*/
|
||||
int sort_files;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
char *input_charset;
|
||||
char *output_charset;
|
||||
|
||||
@ -400,6 +456,35 @@ struct ecma119_image
|
||||
/* tree of files sources */
|
||||
IsoRBTree *files;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
unsigned int checksum_idx_counter;
|
||||
void *checksum_ctx;
|
||||
off_t checksum_counter;
|
||||
uint32_t checksum_rlsb_tag_pos;
|
||||
uint32_t checksum_sb_tag_pos;
|
||||
uint32_t checksum_tree_tag_pos;
|
||||
uint32_t checksum_tag_pos;
|
||||
char image_md5[16];
|
||||
char *checksum_buffer;
|
||||
uint32_t checksum_array_pos;
|
||||
uint32_t checksum_range_start;
|
||||
uint32_t checksum_range_size;
|
||||
|
||||
char *opts_overwrite; /* Points to IsoWriteOpts->overwrite.
|
||||
Use only underneath ecma119_image_new()
|
||||
and if not NULL*/
|
||||
|
||||
/* ??? Is there a reason why we copy lots of items from IsoWriteOpts
|
||||
rather than taking ownership of the IsoWriteOpts object which
|
||||
is submitted with ecma119_image_new() ?
|
||||
*/
|
||||
|
||||
char scdbackup_tag_parm[100];
|
||||
char *scdbackup_tag_written;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/* Buffer for communication between burn_source and writer thread */
|
||||
IsoRingBuffer *buffer;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -102,14 +103,9 @@ int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
/* take a ref to the IsoNode */
|
||||
ecma->node = iso;
|
||||
iso_node_ref(iso);
|
||||
|
||||
/* TODO #00009 : add true support for harlinks and inode numbers */
|
||||
ecma->nlink = 1;
|
||||
ecma->ino = ++img->ino;
|
||||
|
||||
*node = ecma;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -811,6 +807,174 @@ int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= recursion
|
||||
* bit1= count nodes rather than fill them into *nodes
|
||||
* @return
|
||||
* <0 error
|
||||
* bit0= saw ino == 0
|
||||
* bit1= saw ino != 0
|
||||
*/
|
||||
static
|
||||
int make_node_array(Ecma119Image *img, Ecma119Node *dir,
|
||||
Ecma119Node **nodes, size_t nodes_size, size_t *node_count,
|
||||
int flag)
|
||||
{
|
||||
int ret, result = 0;
|
||||
size_t i;
|
||||
Ecma119Node *child;
|
||||
|
||||
if (!(flag & 1)) {
|
||||
*node_count = 0;
|
||||
if (!(flag & 2)) {
|
||||
/* Register the tree root node */
|
||||
if (*node_count >= nodes_size) {
|
||||
iso_msg_submit(img->image->id, ISO_ASSERT_FAILURE, 0,
|
||||
"Programming error: Overflow of hardlink sort array");
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
nodes[*node_count] = dir;
|
||||
}
|
||||
result|= (dir->ino == 0 ? 1 : 2);
|
||||
(*node_count)++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
child = dir->info.dir->children[i];
|
||||
if (!(flag & 2)) {
|
||||
if (*node_count >= nodes_size) {
|
||||
iso_msg_submit(img->image->id, ISO_ASSERT_FAILURE, 0,
|
||||
"Programming error: Overflow of hardlink sort array");
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
nodes[*node_count] = child;
|
||||
}
|
||||
result|= (child->ino == 0 ? 1 : 2);
|
||||
(*node_count)++;
|
||||
|
||||
if (child->type == ECMA119_DIR) {
|
||||
ret = make_node_array(img, child,
|
||||
nodes, nodes_size, node_count, flag | 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= compare stat properties and attributes
|
||||
* bit1= treat all nodes with image ino == 0 as unique
|
||||
*/
|
||||
static
|
||||
int ecma119_node_cmp_flag(const void *v1, const void *v2, int flag)
|
||||
{
|
||||
int ret;
|
||||
Ecma119Node *n1, *n2;
|
||||
|
||||
n1 = *((Ecma119Node **) v1);
|
||||
n2 = *((Ecma119Node **) v2);
|
||||
if (n1 == n2)
|
||||
return 0;
|
||||
|
||||
ret = iso_node_cmp_flag(n1->node, n2->node, flag & (1 | 2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ecma119_node_cmp_hard(const void *v1, const void *v2)
|
||||
{
|
||||
return ecma119_node_cmp_flag(v1, v2, 1);
|
||||
}
|
||||
|
||||
static
|
||||
int ecma119_node_cmp_nohard(const void *v1, const void *v2)
|
||||
{
|
||||
return ecma119_node_cmp_flag(v1, v2, 1 | 2);
|
||||
}
|
||||
|
||||
static
|
||||
int family_set_ino(Ecma119Image *img, Ecma119Node **nodes, size_t family_start,
|
||||
size_t next_family, ino_t img_ino, ino_t prev_ino, int flag)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (img_ino != 0) {
|
||||
/* Check whether this is the same img_ino as in the previous
|
||||
family (e.g. by property divergence of imported hardlink).
|
||||
*/
|
||||
if (img_ino == prev_ino)
|
||||
img_ino = 0;
|
||||
}
|
||||
if (img_ino == 0) {
|
||||
img_ino = img_give_ino_number(img->image, 0);
|
||||
}
|
||||
for (i = family_start; i < next_family; i++) {
|
||||
nodes[i]->ino = img_ino;
|
||||
nodes[i]->nlink = next_family - family_start;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int match_hardlinks(Ecma119Image *img, Ecma119Node *dir, int flag)
|
||||
{
|
||||
int ret;
|
||||
size_t nodes_size = 0, node_count = 0, i, family_start;
|
||||
Ecma119Node **nodes = NULL;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
ino_t img_ino = 0, prev_ino = 0;
|
||||
|
||||
ret = make_node_array(img, dir, nodes, nodes_size, &node_count, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
nodes_size = node_count;
|
||||
nodes = (Ecma119Node **) calloc(sizeof(Ecma119Node *), nodes_size);
|
||||
if (nodes == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = make_node_array(img, dir, nodes, nodes_size, &node_count, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
/* Sort according to id tuples, IsoFileSrc identity, properties, xattr. */
|
||||
if (img->hardlinks)
|
||||
qsort(nodes, node_count, sizeof(Ecma119Node *), ecma119_node_cmp_hard);
|
||||
else
|
||||
qsort(nodes, node_count, sizeof(Ecma119Node *),
|
||||
ecma119_node_cmp_nohard);
|
||||
|
||||
/* Hand out image inode numbers to all Ecma119Node.ino == 0 .
|
||||
Same sorting rank gets same inode number.
|
||||
Split those image inode number families where the sort criterion
|
||||
differs.
|
||||
*/
|
||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
family_start = 0;
|
||||
for (i = 1; i < node_count; i++) {
|
||||
if (ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
|
||||
/* Still in same ino family */
|
||||
if (img_ino == 0) { /* Just in case any member knows its img_ino */
|
||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
||||
prev_ino = img_ino;
|
||||
iso_node_get_id(nodes[i]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
family_start = i;
|
||||
}
|
||||
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (nodes != NULL)
|
||||
free((char *) nodes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ecma119_tree_create(Ecma119Image *img)
|
||||
{
|
||||
int ret;
|
||||
@ -826,6 +990,12 @@ int ecma119_tree_create(Ecma119Image *img)
|
||||
}
|
||||
img->root = root;
|
||||
|
||||
iso_msg_debug(img->image->id, "Matching hardlinks...");
|
||||
ret = match_hardlinks(img, img->root, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
iso_msg_debug(img->image->id, "Sorting the low level tree...");
|
||||
sort_tree(root);
|
||||
|
||||
|
@ -62,8 +62,10 @@ struct ecma119_node
|
||||
|
||||
IsoNode *node; /*< reference to the iso node */
|
||||
|
||||
/* TODO #00009 : add true support for harlinks and inode numbers */
|
||||
/* >>> ts A90501 : Shouldn't this be uint32_t
|
||||
as this is what PX will take ? */
|
||||
ino_t ino;
|
||||
|
||||
nlink_t nlink;
|
||||
|
||||
/**< file, symlink, special, directory or placeholder */
|
||||
|
@ -12,49 +12,32 @@
|
||||
#include "writer.h"
|
||||
#include "messages.h"
|
||||
#include "image.h"
|
||||
#include "stream.h"
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
#include "md5.h"
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
int iso_file_src_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
int ret;
|
||||
const IsoFileSrc *f1, *f2;
|
||||
unsigned int fs_id1, fs_id2;
|
||||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
off_t size1, size2;
|
||||
|
||||
if (n1 == n2) {
|
||||
return 0; /* Normally just a shortcut.
|
||||
But important if Libisofs_file_src_cmp_non_zerO */
|
||||
}
|
||||
|
||||
f1 = (const IsoFileSrc *)n1;
|
||||
f2 = (const IsoFileSrc *)n2;
|
||||
|
||||
iso_stream_get_id(f1->stream, &fs_id1, &dev_id1, &ino_id1);
|
||||
iso_stream_get_id(f2->stream, &fs_id2, &dev_id2, &ino_id2);
|
||||
|
||||
if (fs_id1 < fs_id2) {
|
||||
return -1;
|
||||
} else if (fs_id1 > fs_id2) {
|
||||
return 1;
|
||||
} else {
|
||||
/* files belong to the same fs */
|
||||
if (dev_id1 > dev_id2) {
|
||||
return -1;
|
||||
} else if (dev_id1 < dev_id2) {
|
||||
return 1;
|
||||
} else if (ino_id1 < ino_id2) {
|
||||
return -1;
|
||||
} else if (ino_id1 > ino_id2) {
|
||||
return 1;
|
||||
} else {
|
||||
size1 = iso_stream_get_size(f1->stream);
|
||||
size2 = iso_stream_get_size(f2->stream);
|
||||
if (size1 < size2) {
|
||||
return -1;
|
||||
} else if (size1 > size2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ret = iso_stream_cmp_ino(f1->stream, f2->stream, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
@ -65,6 +48,11 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
dev_t dev_id;
|
||||
ino_t ino_id;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
int cret, no_md5= 0;
|
||||
void *xipt = NULL;
|
||||
#endif
|
||||
|
||||
if (img == NULL || file == NULL || src == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
@ -109,11 +97,54 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
/* insert the filesrc in the tree */
|
||||
ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
|
||||
if (ret <= 0) {
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (ret == 0 && (*src)->checksum_index > 0) {
|
||||
/* Duplicate file source was mapped to previously registered source
|
||||
*/
|
||||
cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
|
||||
if (cret < 0)
|
||||
ret = cret;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
free(fsrc->sections);
|
||||
free(fsrc);
|
||||
return ret;
|
||||
}
|
||||
iso_stream_ref(fsrc->stream);
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if ((img->md5_file_checksums & 1) &&
|
||||
file->from_old_session && img->appendable) {
|
||||
ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func,
|
||||
&xipt);
|
||||
if (ret <= 0)
|
||||
ret = iso_node_get_xinfo((IsoNode *) file, checksum_cx_xinfo_func,
|
||||
&xipt);
|
||||
if (ret <= 0)
|
||||
/* Omit MD5 indexing with old image nodes which have no MD5 */
|
||||
no_md5 = 1;
|
||||
}
|
||||
|
||||
if ((img->md5_file_checksums & 1) && !no_md5) {
|
||||
img->checksum_idx_counter++;
|
||||
if (img->checksum_idx_counter < 0x80000000) {
|
||||
fsrc->checksum_index = img->checksum_idx_counter;
|
||||
} else {
|
||||
fsrc->checksum_index= 0;
|
||||
img->checksum_idx_counter= 0x80000000; /* keep from rolling over */
|
||||
}
|
||||
cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
|
||||
if (cret < 0)
|
||||
return cret;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
@ -262,41 +293,45 @@ int filesrc_close(IsoFileSrc *file)
|
||||
static
|
||||
int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
size_t got;
|
||||
|
||||
/* loop to ensure the full buffer is filled */
|
||||
do {
|
||||
ssize_t result;
|
||||
result = iso_stream_read(file->stream, buf + bytes, count - bytes);
|
||||
if (result < 0) {
|
||||
/* fill buffer with 0s and return */
|
||||
memset(buf + bytes, 0, count - bytes);
|
||||
return result;
|
||||
}
|
||||
if (result == 0)
|
||||
break;
|
||||
bytes += result;
|
||||
} while (bytes < count);
|
||||
|
||||
if (bytes < count) {
|
||||
/* eof */
|
||||
memset(buf + bytes, 0, count - bytes);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return iso_stream_read_buffer(file->stream, buf, count, &got);
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/* @return 1=ok, md5 is valid,
|
||||
0= not ok, go on,
|
||||
<0 fatal error, abort
|
||||
*/
|
||||
|
||||
static
|
||||
int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
|
||||
{
|
||||
return iso_stream_make_md5(file->stream, md5, 0);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
static
|
||||
int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
{
|
||||
int res;
|
||||
int res, ret, was_error;
|
||||
size_t i, b;
|
||||
Ecma119Image *t;
|
||||
IsoFileSrc *file;
|
||||
IsoFileSrc **filelist;
|
||||
char name[PATH_MAX];
|
||||
char buffer[BLOCK_SIZE];
|
||||
off_t file_size;
|
||||
uint32_t nblocks;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
void *ctx= NULL;
|
||||
char md5[16], pre_md5[16];
|
||||
int pre_md5_valid = 0;
|
||||
#endif
|
||||
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
@ -309,8 +344,19 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
|
||||
i = 0;
|
||||
while ((file = filelist[i++]) != NULL) {
|
||||
was_error = 0;
|
||||
file_size = iso_file_src_get_size(file);
|
||||
nblocks = DIV_UP(file_size, BLOCK_SIZE);
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
uint32_t nblocks = DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
|
||||
pre_md5_valid = 0;
|
||||
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
|
||||
/* Obtain an MD5 of content by a first read pass */
|
||||
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
res = filesrc_open(file);
|
||||
iso_stream_get_file_name(file->stream, name);
|
||||
@ -320,28 +366,33 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
* 0's to image
|
||||
*/
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||
"File \"%s\" can't be opened. Filling with 0s.", name);
|
||||
if (res < 0) {
|
||||
return res; /* aborted due to error severity */
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (res < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
return res;
|
||||
ret = res;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else if (res > 1) {
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Size of file \"%s\" has changed. It will be %s", name,
|
||||
(res == 2 ? "truncated" : "padded with 0's"));
|
||||
if (res < 0) {
|
||||
filesrc_close(file);
|
||||
return res; /* aborted due to error severity */
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
#ifdef LIBISOFS_VERBOSE_DEBUG
|
||||
@ -350,6 +401,18 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (file->checksum_index > 0) {
|
||||
/* initialize file checksum */
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/* write file contents to image */
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
int wres;
|
||||
@ -362,8 +425,25 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
if (wres < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
filesrc_close(file);
|
||||
return wres;
|
||||
ret = wres;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (file->checksum_index > 0) {
|
||||
/* Add to file checksum */
|
||||
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
|
||||
res = BLOCK_SIZE;
|
||||
else
|
||||
res = file_size - b * BLOCK_SIZE;
|
||||
res = iso_md5_compute(ctx, buffer, res);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
filesrc_close(file);
|
||||
@ -371,6 +451,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
if (b < nblocks) {
|
||||
/* premature end of file, due to error or eof */
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
if (res < 0) {
|
||||
/* error */
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||
@ -382,7 +463,8 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
return res; /* aborted due error severity */
|
||||
ret = res; /* aborted due error severity */
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* fill with 0s */
|
||||
@ -393,13 +475,67 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (res < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
return res;
|
||||
ret = res;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (file->checksum_index > 0) {
|
||||
/* Add to file checksum */
|
||||
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
|
||||
res = BLOCK_SIZE;
|
||||
else
|
||||
res = file_size - b * BLOCK_SIZE;
|
||||
res = iso_md5_compute(ctx, buffer, res);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (file->checksum_index > 0) {
|
||||
/* Obtain checksum and dispose checksum context */
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||
!was_error) {
|
||||
if (! iso_md5_match(md5, pre_md5)) {
|
||||
/* Issue MISHAP event */
|
||||
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
|
||||
"Content of file '%s' changed while it was written into the image.",
|
||||
name);
|
||||
if (res < 0) {
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Write md5 into checksum buffer at file->checksum_index */
|
||||
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
return ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
if (ctx != NULL) /* avoid any memory leak */
|
||||
iso_md5_end(&ctx, md5);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
@ -416,7 +552,7 @@ int iso_file_src_writer_create(Ecma119Image *target)
|
||||
|
||||
writer = malloc(sizeof(IsoImageWriter));
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
writer->compute_data_blocks = filesrc_writer_compute_data_blocks;
|
||||
|
@ -18,6 +18,13 @@ struct Iso_File_Src
|
||||
{
|
||||
unsigned int prev_img :1; /**< if the file comes from a previous image */
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
unsigned int checksum_index :31;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
||||
/** File Sections of the file in the image */
|
||||
struct iso_file_section *sections;
|
||||
int nsections;
|
||||
@ -43,7 +50,7 @@ int iso_file_src_cmp(const void *n1, const void *n2);
|
||||
* @param src
|
||||
* Will be filled with a pointer to the IsoFileSrc
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
* 1 if new object was created, 0 if object existed, < 0 on error
|
||||
*/
|
||||
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src);
|
||||
|
||||
|
@ -594,8 +594,13 @@ IsoStream *extf_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
/* Function is defined after definition of extf_stream_class */
|
||||
|
||||
|
||||
IsoStreamIface extf_stream_class = {
|
||||
2,
|
||||
3,
|
||||
"extf",
|
||||
extf_stream_open,
|
||||
extf_stream_close,
|
||||
@ -605,10 +610,28 @@ IsoStreamIface extf_stream_class = {
|
||||
extf_stream_get_id,
|
||||
extf_stream_free,
|
||||
extf_update_size,
|
||||
extf_get_input_stream
|
||||
extf_get_input_stream,
|
||||
extf_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
ExternalFilterStreamData *data1, *data2;
|
||||
|
||||
if (s1->class != &extf_stream_class || s2->class != &extf_stream_class)
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
data1 = (ExternalFilterStreamData*) s1->data;
|
||||
data2 = (ExternalFilterStreamData*) s2->data;
|
||||
if (data1->cmd != data2->cmd)
|
||||
return (data1->cmd < data2->cmd ? -1 : 1);
|
||||
return iso_stream_cmp_ino(data1->orig, data2->orig, 0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static
|
||||
void extf_filter_free(FilterContext *filter)
|
||||
{
|
||||
|
@ -70,6 +70,7 @@ typedef struct
|
||||
|
||||
} GzipFilterRuntime;
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
|
||||
static
|
||||
int gzip_running_destroy(GzipFilterRuntime **running, int flag)
|
||||
@ -96,9 +97,7 @@ int gzip_running_new(GzipFilterRuntime **running, int flag)
|
||||
if (o == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
#ifdef Libisofs_with_zliB
|
||||
memset(&(o->strm), 0, sizeof(o->strm));
|
||||
#endif
|
||||
o->in_buffer = NULL;
|
||||
o->out_buffer = NULL;
|
||||
o->in_buffer_size = 0;
|
||||
@ -106,9 +105,7 @@ int gzip_running_new(GzipFilterRuntime **running, int flag)
|
||||
o->rpt = NULL;
|
||||
o->in_counter = 0;
|
||||
o->out_counter = 0;
|
||||
#ifdef Libisofs_with_zliB
|
||||
o->do_flush = Z_NO_FLUSH;
|
||||
#endif
|
||||
o->error_ret = 1;
|
||||
|
||||
o->in_buffer_size= 2048;
|
||||
@ -123,6 +120,7 @@ failed:
|
||||
gzip_running_destroy(running, 0);
|
||||
return -1;
|
||||
}
|
||||
#endif /* Libisofs_with_zliB */
|
||||
|
||||
|
||||
/* ---------------------------- GzipFilterStreamData --------------------- */
|
||||
@ -164,12 +162,17 @@ typedef struct
|
||||
|
||||
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
|
||||
/* Each individual GzipFilterStreamData needs a unique id number. */
|
||||
/* >>> This is very suboptimal:
|
||||
The counter can rollover.
|
||||
*/
|
||||
static ino_t gzip_ino_id = 0;
|
||||
|
||||
#endif /* Libisofs_with_zliB */
|
||||
|
||||
|
||||
static
|
||||
int gzip_stream_uncompress(IsoStream *stream, void *buf, size_t desired);
|
||||
|
||||
@ -521,8 +524,12 @@ IsoStream *gzip_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_compress_class = {
|
||||
2,
|
||||
3,
|
||||
"gzip",
|
||||
gzip_stream_open,
|
||||
gzip_stream_close,
|
||||
@ -532,12 +539,13 @@ IsoStreamIface gzip_stream_compress_class = {
|
||||
gzip_stream_get_id,
|
||||
gzip_stream_free,
|
||||
gzip_update_size,
|
||||
gzip_get_input_stream
|
||||
gzip_get_input_stream,
|
||||
gzip_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_uncompress_class = {
|
||||
2,
|
||||
3,
|
||||
"pizg",
|
||||
gzip_stream_open,
|
||||
gzip_stream_close,
|
||||
@ -547,9 +555,26 @@ IsoStreamIface gzip_stream_uncompress_class = {
|
||||
gzip_stream_get_id,
|
||||
gzip_stream_free,
|
||||
gzip_update_size,
|
||||
gzip_get_input_stream
|
||||
gzip_get_input_stream,
|
||||
gzip_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
if (s1->class != s2->class || (s1->class != &gzip_stream_compress_class &&
|
||||
s2->class != &gzip_stream_compress_class))
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
iso_stream_get_input_stream(s2, 0), 0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
|
||||
static
|
||||
void gzip_filter_free(FilterContext *filter)
|
||||
@ -557,7 +582,6 @@ void gzip_filter_free(FilterContext *filter)
|
||||
/* no data are allocated */;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param flag bit1= Install a decompression filter
|
||||
*/
|
||||
@ -606,7 +630,6 @@ int gzip_filter_get_filter(FilterContext *filter, IsoStream *original,
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* To be called by iso_file_add_filter().
|
||||
* The FilterContext input parameter is not furtherly needed for the
|
||||
* emerging IsoStream.
|
||||
@ -652,6 +675,7 @@ int gzip_create_context(FilterContext **filter, int flag)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_zliB */
|
||||
|
||||
/*
|
||||
* @param flag bit0= if_block_reduction rather than if_reduction
|
||||
|
@ -775,8 +775,12 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface ziso_stream_compress_class = {
|
||||
2,
|
||||
3,
|
||||
"ziso",
|
||||
ziso_stream_open,
|
||||
ziso_stream_close,
|
||||
@ -786,12 +790,13 @@ IsoStreamIface ziso_stream_compress_class = {
|
||||
ziso_stream_get_id,
|
||||
ziso_stream_free,
|
||||
ziso_update_size,
|
||||
ziso_get_input_stream
|
||||
ziso_get_input_stream,
|
||||
ziso_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
IsoStreamIface ziso_stream_uncompress_class = {
|
||||
2,
|
||||
3,
|
||||
"osiz",
|
||||
ziso_stream_open,
|
||||
ziso_stream_close,
|
||||
@ -801,10 +806,25 @@ IsoStreamIface ziso_stream_uncompress_class = {
|
||||
ziso_stream_get_id,
|
||||
ziso_stream_free,
|
||||
ziso_update_size,
|
||||
ziso_get_input_stream
|
||||
ziso_get_input_stream,
|
||||
ziso_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
if (s1->class != s2->class || (s1->class != &ziso_stream_compress_class &&
|
||||
s2->class != &ziso_stream_uncompress_class))
|
||||
iso_stream_cmp_ino(s1, s2, 1);
|
||||
return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
iso_stream_get_input_stream(s2, 0), 0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static
|
||||
void ziso_filter_free(FilterContext *filter)
|
||||
{
|
||||
|
@ -62,6 +62,13 @@ struct iso_read_opts
|
||||
unsigned int nojoliet : 1; /*< Do not read Joliet extensions */
|
||||
unsigned int noiso1999 : 1; /*< Do not read ISO 9660:1999 enhanced tree */
|
||||
unsigned int noaaip : 1; /* Do not read AAIP extension for xattr and ACL */
|
||||
unsigned int nomd5 : 1; /* Do not read MD5 array */
|
||||
|
||||
/**
|
||||
* Hand out new inode numbers and overwrite eventually read PX inode
|
||||
* numbers. This will split apart any hardlinks.
|
||||
*/
|
||||
unsigned int make_new_ino : 1 ;
|
||||
|
||||
/**
|
||||
* When both Joliet and RR extensions are present, the RR tree is used.
|
||||
@ -88,6 +95,7 @@ struct iso_read_opts
|
||||
* attribute "isofs.cs" of root directory
|
||||
*/
|
||||
int auto_input_charset;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -137,6 +145,7 @@ enum read_rr_ext {
|
||||
RR_EXT_112 = 2 /*< RR extensions conforming version 1.12 */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private data for the image IsoFilesystem
|
||||
*/
|
||||
@ -241,6 +250,11 @@ typedef struct
|
||||
*/
|
||||
int aaip_load;
|
||||
|
||||
/** Whether the MD5 array shall be read if available.
|
||||
* 1 = yes , 0 = no
|
||||
*/
|
||||
int md5_load;
|
||||
|
||||
/** Whether AAIP is present. Version major.minor = major * 100 + minor
|
||||
* Value -1 means that no AAIP ER was detected yet.
|
||||
*/
|
||||
@ -261,9 +275,20 @@ typedef struct
|
||||
uint32_t imgblock; /**< Block for El-Torito boot image */
|
||||
uint32_t catblock; /**< Block for El-Torito catalog */
|
||||
|
||||
/* Whether inode numbers from PX entries shall be discarded */
|
||||
unsigned int make_new_ino : 1 ;
|
||||
|
||||
/* Inode number generator counter */
|
||||
ino_t inode_counter;
|
||||
|
||||
/* PX inode number status
|
||||
bit0= there were nodes with PX inode numbers
|
||||
bit1= there were nodes with PX but without inode numbers
|
||||
bit2= there were nodes without PX
|
||||
bit3= there were nodes with faulty PX
|
||||
*/
|
||||
int px_ino_status;
|
||||
|
||||
} _ImageFsData;
|
||||
|
||||
typedef struct image_fs_data ImageFileSourceData;
|
||||
@ -1070,29 +1095,6 @@ char *get_name(_ImageFsData *fsdata, const char *str, size_t len)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A global counter for default inode numbers for the ISO image filesystem.
|
||||
* @param fs The filesystem where the number shall be used
|
||||
* @param flag bit0= reset count
|
||||
*/
|
||||
static
|
||||
ino_t fs_give_ino_number(IsoImageFilesystem *fs, int flag)
|
||||
{
|
||||
_ImageFsData *fsdata;
|
||||
|
||||
fsdata = (_ImageFsData*)fs->data;
|
||||
if (flag & 1)
|
||||
fsdata->inode_counter = 0;
|
||||
fsdata->inode_counter++;
|
||||
if (fsdata->inode_counter == 0) {
|
||||
|
||||
/* >>> raise alert because of inode rollover */;
|
||||
|
||||
}
|
||||
return fsdata->inode_counter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param src
|
||||
@ -1135,6 +1137,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
size_t cs_value_length = 0;
|
||||
char msg[160];
|
||||
|
||||
int has_px = 0;
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
uint8_t zisofs_alg[2], zisofs_hs4 = 0, zisofs_bsl2 = 0;
|
||||
uint32_t zisofs_usize = 0;
|
||||
@ -1147,6 +1151,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
fsdata = (_ImageFsData*)fs->data;
|
||||
|
||||
memset(&atts, 0, sizeof(struct stat));
|
||||
atts.st_nlink = 1;
|
||||
|
||||
/*
|
||||
* First of all, check for unsupported ECMA-119 features
|
||||
@ -1275,12 +1280,22 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
continue;
|
||||
|
||||
if (SUSP_SIG(sue, 'P', 'X')) {
|
||||
has_px = 1;
|
||||
ret = read_rr_PX(sue, &atts);
|
||||
if (ret < 0) {
|
||||
/* notify and continue */
|
||||
ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_RR_WARN, ret,
|
||||
"Invalid PX entry");
|
||||
fsdata->px_ino_status |= 8;
|
||||
} if (ret == 2) {
|
||||
if (fsdata->inode_counter < atts.st_ino)
|
||||
fsdata->inode_counter = atts.st_ino;
|
||||
fsdata->px_ino_status |= 1;
|
||||
|
||||
} else {
|
||||
fsdata->px_ino_status |= 2;
|
||||
}
|
||||
|
||||
} else if (SUSP_SIG(sue, 'T', 'F')) {
|
||||
ret = read_rr_TF(sue, &atts);
|
||||
if (ret < 0) {
|
||||
@ -1536,6 +1551,10 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_px) {
|
||||
fsdata->px_ino_status |= 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we haven't RR extensions, or no NM entry is present,
|
||||
* we use the name in directory record
|
||||
@ -1596,59 +1615,14 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
/* but the real name is the name of the placeholder */
|
||||
ifsdata = (ImageFileSourceData*) (*src)->data;
|
||||
ifsdata->name = name;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_new_fs_image_inO
|
||||
|
||||
if (fsdata->rr != RR_EXT_112) {
|
||||
if (fsdata->rr == 0) {
|
||||
atts.st_nlink = 1;
|
||||
}
|
||||
}
|
||||
atts.st_ino = fs_give_ino_number(fs, 0);
|
||||
|
||||
#else /* Libisofs_new_fs_image_inO */
|
||||
|
||||
/* ts Nov 25 2008: TODO
|
||||
This seems not fully consistent with read_rr_PX() which decides
|
||||
by (px->len_sue[0] == 44) whether an inode number is present or not.
|
||||
What if read_rr_PX finds a PX of length 36 in a IEEE_1282 image ?
|
||||
It is illegal but could confuse the image by duplicate inode numbers.
|
||||
|
||||
Regrettably it is not enough to just use single default numbers.
|
||||
If only one number misses in the image, then all would need to be
|
||||
defaulted by the following iso_global_inode code.
|
||||
|
||||
Why do duplicate inode numbers confuse the file lengths, anyway ?
|
||||
(See ticket 144)
|
||||
/* Production of missing inode numbers is delayed until the image is
|
||||
complete. Then all nodes which shall get a new inode number will
|
||||
be served.
|
||||
*/
|
||||
if (fsdata->rr != RR_EXT_112) {
|
||||
/*
|
||||
* Only RRIP 1.12 provides valid inode numbers. If not, it is not easy
|
||||
* to generate those serial numbers, and we use extend block instead.
|
||||
* It BREAKS POSIX SEMANTICS, but its suitable for our needs
|
||||
*/
|
||||
|
||||
#ifndef Libisofs_ino_from_lbA
|
||||
#define Libisofs_patch_ticket_144 yes
|
||||
#endif
|
||||
#ifdef Libisofs_patch_ticket_144
|
||||
|
||||
atts.st_ino = fs_give_ino_number(fs, 0);
|
||||
|
||||
#else
|
||||
/* Ticket 144: This produces duplicate numbers with empty files.
|
||||
*/
|
||||
atts.st_ino = (ino_t) iso_read_bb(record->block, 4, NULL);
|
||||
#endif
|
||||
if (fsdata->rr == 0) {
|
||||
atts.st_nlink = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ! Libisofs_new_fs_image_inO */
|
||||
|
||||
/*
|
||||
* if we haven't RR extensions, or a needed TF time stamp is not present,
|
||||
@ -1974,7 +1948,6 @@ void ifs_fs_free(IsoFilesystem *fs)
|
||||
free(data->copyright_file_id);
|
||||
free(data->abstract_file_id);
|
||||
free(data->biblio_file_id);
|
||||
|
||||
free(data->input_charset);
|
||||
free(data->local_charset);
|
||||
free(data);
|
||||
@ -2154,15 +2127,34 @@ int read_pvm(_ImageFsData *data, uint32_t block)
|
||||
|
||||
/* fill volume attributes */
|
||||
/* TODO take care of input charset */
|
||||
data->volset_id = strcopy((char*)pvm->vol_set_id, 128);
|
||||
data->volume_id = strcopy((char*)pvm->volume_id, 32);
|
||||
data->publisher_id = strcopy((char*)pvm->publisher_id, 128);
|
||||
data->data_preparer_id = strcopy((char*)pvm->data_prep_id, 128);
|
||||
data->system_id = strcopy((char*)pvm->system_id, 32);
|
||||
data->application_id = strcopy((char*)pvm->application_id, 128);
|
||||
data->copyright_file_id = strcopy((char*)pvm->copyright_file_id, 37);
|
||||
data->abstract_file_id = strcopy((char*)pvm->abstract_file_id, 37);
|
||||
data->biblio_file_id = strcopy((char*)pvm->bibliographic_file_id, 37);
|
||||
data->volset_id = iso_util_strcopy_untail((char*)pvm->vol_set_id, 128);
|
||||
data->volume_id = iso_util_strcopy_untail((char*)pvm->volume_id, 32);
|
||||
data->publisher_id =
|
||||
iso_util_strcopy_untail((char*)pvm->publisher_id, 128);
|
||||
data->data_preparer_id =
|
||||
iso_util_strcopy_untail((char*)pvm->data_prep_id, 128);
|
||||
data->system_id = iso_util_strcopy_untail((char*)pvm->system_id, 32);
|
||||
data->application_id =
|
||||
iso_util_strcopy_untail((char*)pvm->application_id, 128);
|
||||
data->copyright_file_id =
|
||||
iso_util_strcopy_untail((char*) pvm->copyright_file_id, 37);
|
||||
data->abstract_file_id =
|
||||
iso_util_strcopy_untail((char*) pvm->abstract_file_id, 37);
|
||||
data->biblio_file_id =
|
||||
iso_util_strcopy_untail((char*) pvm->bibliographic_file_id, 37);
|
||||
if (data->copyright_file_id[0] == '_' && data->copyright_file_id[1] == 0 &&
|
||||
data->abstract_file_id[0] == '_' && data->abstract_file_id[1] == 0 &&
|
||||
data->biblio_file_id[0] == '_' && data->biblio_file_id[1] == 0) {
|
||||
/* This is bug output from libisofs <= 0.6.23 . The texts mean file
|
||||
names and should have been empty to indicate that there are no such
|
||||
files. It is obvious that not all three roles can be fulfilled by
|
||||
one file "_" so that one cannot spoil anything by assuming them
|
||||
empty now.
|
||||
*/
|
||||
data->copyright_file_id[0] = 0;
|
||||
data->abstract_file_id[0] = 0;
|
||||
data->biblio_file_id[0] = 0;
|
||||
}
|
||||
|
||||
data->nblocks = iso_read_bb(pvm->vol_space_size, 4, NULL);
|
||||
|
||||
@ -2233,6 +2225,83 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@return 1= ok, checked, go on with loading
|
||||
2= no checksum tags found, go on with loading
|
||||
<0= libisofs error
|
||||
especially ISO_SB_TREE_CORRUPTED
|
||||
*/
|
||||
static
|
||||
int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag)
|
||||
{
|
||||
int tag_type, ret;
|
||||
char block[2048], md5[16];
|
||||
int desired = (1 << 2);
|
||||
void *ctx = NULL;
|
||||
uint32_t next_tag = 0, i;
|
||||
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (start_lba == 0)
|
||||
desired |= (1 << 4);
|
||||
for (i = 0; i < 32; i++) {
|
||||
ret = src->read_block(src, start_lba + i, (uint8_t *) block);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = 0;
|
||||
if (i >= 16)
|
||||
ret = iso_util_eval_md5_tag(block, desired, start_lba + i,
|
||||
ctx, start_lba, &tag_type, &next_tag, 0);
|
||||
iso_md5_compute(ctx, block, 2048);
|
||||
if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
|
||||
ret = ISO_SB_TREE_CORRUPTED;
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret == 1)
|
||||
break;
|
||||
}
|
||||
if (i >= 32) {
|
||||
ret = 2;
|
||||
goto ex;
|
||||
}
|
||||
if (tag_type == 4) {
|
||||
/* Relocated Superblock: restart checking at real session start */
|
||||
if (next_tag < 32) {
|
||||
/* Non plausible session_start address */
|
||||
ret = ISO_SB_TREE_CORRUPTED;
|
||||
iso_msg_submit(-1, ret, 0, NULL);
|
||||
goto ex;
|
||||
}
|
||||
/* Check real session */
|
||||
ret = iso_src_check_sb_tree(src, next_tag, 0);
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* Go on with tree */
|
||||
for (i++; start_lba + i <= next_tag; i++) {
|
||||
ret = src->read_block(src, start_lba + i, (uint8_t *) block);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (start_lba + i < next_tag)
|
||||
iso_md5_compute(ctx, block, 2048);
|
||||
}
|
||||
ret = iso_util_eval_md5_tag(block, (1 << 3), start_lba + i - 1,
|
||||
ctx, start_lba, &tag_type, &next_tag, 0);
|
||||
if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
|
||||
ret = ISO_SB_TREE_CORRUPTED;
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
ret = 1;
|
||||
ex:
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||
int msgid, IsoImageFilesystem **fs)
|
||||
{
|
||||
@ -2272,14 +2341,11 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||
data->dir_mode = opts->dir_mode & ~S_IFMT;
|
||||
data->msgid = msgid;
|
||||
data->aaip_load = !opts->noaaip;
|
||||
data->md5_load = !opts->nomd5;
|
||||
data->aaip_version = -1;
|
||||
|
||||
#ifndef Libisofs_setlocale_in_iniT
|
||||
/* ??? ts Nov 25 2008 :
|
||||
Shouldn't this go to library initialization or even to app ?
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
data->make_new_ino = opts->make_new_ino;
|
||||
data->inode_counter = 0;
|
||||
data->px_ino_status = 0;
|
||||
|
||||
data->local_charset = strdup(iso_get_local_charset(0));
|
||||
if (data->local_charset == NULL) {
|
||||
@ -2300,6 +2366,24 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||
|
||||
/* read Volume Descriptors and ensure it is a valid image */
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (data->md5_load) {
|
||||
/* From opts->block on : check for superblock and tree tags */;
|
||||
ret = iso_src_check_sb_tree(src, opts->block, 0);
|
||||
if (ret < 0) {
|
||||
iso_msgs_submit(0,
|
||||
"Image loading aborted due to MD5 mismatch of image tree data",
|
||||
0, "FAILURE", 0);
|
||||
iso_msgs_submit(0,
|
||||
"You may override this refusal by disabling MD5 checking",
|
||||
0, "HINT", 0);
|
||||
goto fs_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/* 1. first, open the filesystem */
|
||||
ifs_fs_open(ifs);
|
||||
|
||||
@ -2522,6 +2606,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoNode *new;
|
||||
char *name;
|
||||
ImageFileSourceData *data;
|
||||
_ImageFsData *fsdata;
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
/* Intimate friendship with this function in filters/zisofs.c */
|
||||
@ -2536,6 +2621,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
fsdata = data->fs->data;
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
|
||||
@ -2550,7 +2636,6 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
case S_IFREG:
|
||||
{
|
||||
/* source is a regular file */
|
||||
_ImageFsData *fsdata = data->fs->data;
|
||||
|
||||
/* El-Torito images have only one section */
|
||||
if (fsdata->eltorito && data->sections[0].block == fsdata->catblock) {
|
||||
@ -2677,6 +2762,9 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
link->dest = strdup(dest);
|
||||
link->node.type = LIBISO_SYMLINK;
|
||||
link->fs_id = ISO_IMAGE_FS_ID;
|
||||
link->st_dev = info.st_dev;
|
||||
link->st_ino = info.st_ino;
|
||||
new = (IsoNode*) link;
|
||||
new->refcount = 0;
|
||||
}
|
||||
@ -2695,6 +2783,9 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
special->dev = info.st_rdev;
|
||||
special->node.type = LIBISO_SPECIAL;
|
||||
special->fs_id = ISO_IMAGE_FS_ID;
|
||||
special->st_dev = info.st_dev;
|
||||
special->st_ino = info.st_ino;
|
||||
new = (IsoNode*) special;
|
||||
new->refcount = 0;
|
||||
}
|
||||
@ -2718,15 +2809,26 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
|
||||
ret = src_aa_to_node(src, new, 0);
|
||||
if (ret < 0) {
|
||||
/* todo: stuff any possible memory leak here */
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
free(new);
|
||||
return ret;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Attach ino as xinfo if valid and no IsoStream is involved */
|
||||
if (info.st_ino != 0 && (info.st_mode & S_IFMT) != S_IFREG &&
|
||||
!fsdata->make_new_ino) {
|
||||
ret = iso_node_set_ino(new, info.st_ino, 0);
|
||||
if (ret < 0)
|
||||
goto failure;
|
||||
}
|
||||
|
||||
*node = new;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
failure:;
|
||||
/* todo: stuff any possible memory leak here */
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
free(new);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2763,7 +2865,8 @@ int iso_image_builder_new(IsoNodeBuilder *old, IsoNodeBuilder **builder)
|
||||
* accessible from the ISO filesystem.
|
||||
*/
|
||||
static
|
||||
int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
|
||||
int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image,
|
||||
IsoFileSource **src)
|
||||
{
|
||||
int ret;
|
||||
struct stat atts;
|
||||
@ -2779,17 +2882,7 @@ int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
|
||||
|
||||
memset(&atts, 0, sizeof(struct stat));
|
||||
atts.st_mode = S_IFREG;
|
||||
|
||||
#ifdef Libisofs_new_fs_image_inO
|
||||
|
||||
atts.st_ino = fs_give_ino_number(fs, 0);
|
||||
|
||||
#else /* Libisofs_new_fs_image_inO */
|
||||
|
||||
atts.st_ino = fsdata->imgblock; /* not the best solution, but... */
|
||||
|
||||
#endif /* ! Libisofs_new_fs_image_inO */
|
||||
|
||||
atts.st_ino = img_give_ino_number(image, 0);
|
||||
atts.st_nlink = 1;
|
||||
|
||||
/*
|
||||
@ -2852,7 +2945,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
struct iso_read_opts *opts,
|
||||
IsoReadImageFeatures **features)
|
||||
{
|
||||
int ret;
|
||||
int ret, hflag;
|
||||
IsoImageFilesystem *fs;
|
||||
IsoFilesystem *fsback;
|
||||
IsoNodeBuilder *blback;
|
||||
@ -2861,6 +2954,20 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
_ImageFsData *data;
|
||||
struct el_torito_boot_catalog *oldbootcat;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
int i;
|
||||
uint32_t old_checksum_start_lba;
|
||||
uint32_t old_checksum_end_lba;
|
||||
uint32_t old_checksum_idx_count;
|
||||
char *old_checksum_array = NULL;
|
||||
char checksum_type[81];
|
||||
uint32_t checksum_size;
|
||||
size_t size;
|
||||
uint8_t *rpt;
|
||||
void *ctx = NULL;
|
||||
char md5[16];
|
||||
#endif
|
||||
|
||||
if (image == NULL || src == NULL || opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
@ -2882,9 +2989,16 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
blback = image->builder;
|
||||
oldroot = image->root;
|
||||
oldbootcat = image->bootcat; /* could be NULL */
|
||||
|
||||
image->bootcat = NULL;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
old_checksum_start_lba = image->checksum_start_lba;
|
||||
old_checksum_end_lba = image->checksum_end_lba;
|
||||
old_checksum_idx_count = image->checksum_idx_count;
|
||||
old_checksum_array = image->checksum_array;
|
||||
image->checksum_array = NULL;
|
||||
#endif
|
||||
|
||||
/* create new builder */
|
||||
ret = iso_image_builder_new(blback, &image->builder);
|
||||
if (ret < 0) {
|
||||
@ -2915,6 +3029,12 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
if (ret < 0)
|
||||
goto import_revert;
|
||||
|
||||
/* Attach ino as xinfo if valid */
|
||||
if (info.st_ino != 0 && !data->make_new_ino) {
|
||||
ret = iso_node_set_ino(&(image->root->node), info.st_ino, 0);
|
||||
if (ret < 0)
|
||||
goto import_revert;
|
||||
}
|
||||
}
|
||||
|
||||
/* if old image has el-torito, add a new catalog */
|
||||
@ -2951,12 +3071,32 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
goto import_revert;
|
||||
}
|
||||
|
||||
/* Take over inode management from IsoImageFilesystem.
|
||||
data->inode_counter is supposed to hold the maximum PX inode number.
|
||||
*/
|
||||
image->inode_counter = data->inode_counter;
|
||||
|
||||
if ((data->px_ino_status & (2 | 4 | 8)) || opts->make_new_ino) {
|
||||
/* Attach new inode numbers to any node which does not have one,
|
||||
resp. to all nodes in case of opts->make_new_ino
|
||||
*/
|
||||
if (opts->make_new_ino)
|
||||
hflag = 1; /* Equip all data files with new unique inos */
|
||||
else
|
||||
hflag = 2 | 4 | 8; /* Equip any file type if it has ino == 0 */
|
||||
ret = img_make_inos(image, image->root, hflag);
|
||||
if (ret < 0) {
|
||||
iso_node_builder_unref(image->builder);
|
||||
goto import_revert;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->eltorito) {
|
||||
/* if catalog and image nodes were not filled, we create them here */
|
||||
if (image->bootcat->image->image == NULL) {
|
||||
IsoFileSource *src;
|
||||
IsoNode *node;
|
||||
ret = create_boot_img_filesrc(fs, &src);
|
||||
ret = create_boot_img_filesrc(fs, image, &src);
|
||||
if (ret < 0) {
|
||||
iso_node_builder_unref(image->builder);
|
||||
goto import_revert;
|
||||
@ -3010,7 +3150,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
*features = malloc(sizeof(IsoReadImageFeatures));
|
||||
if (*features == NULL) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto import_cleanup;
|
||||
goto import_revert;
|
||||
}
|
||||
(*features)->hasJoliet = data->joliet;
|
||||
(*features)->hasRR = data->rr_version != 0;
|
||||
@ -3019,6 +3159,62 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
(*features)->size = data->nblocks;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (data->md5_load) {
|
||||
/* Read checksum array */
|
||||
ret = iso_root_get_isofsca((IsoNode *) image->root,
|
||||
&(image->checksum_start_lba),
|
||||
&(image->checksum_end_lba),
|
||||
&(image->checksum_idx_count),
|
||||
&checksum_size, checksum_type, 0);
|
||||
if (ret > 0)
|
||||
if (checksum_size != 16 || strcmp(checksum_type, "MD5") != 0)
|
||||
ret = 0;
|
||||
if (ret > 0 && image->checksum_idx_count > 1) {
|
||||
size = image->checksum_idx_count / 128;
|
||||
if (size * 128 < image->checksum_idx_count)
|
||||
size++;
|
||||
image->checksum_array = calloc(size, 2048);
|
||||
if (image->checksum_array == NULL) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto import_revert;
|
||||
}
|
||||
|
||||
/* Load from image->checksum_end_lba */;
|
||||
for (i = 0; i < size; i++) {
|
||||
rpt = (uint8_t *) (image->checksum_array + i * 2048);
|
||||
ret = src->read_block(src, image->checksum_end_lba + i, rpt);
|
||||
if (ret <= 0)
|
||||
goto import_cleanup;
|
||||
}
|
||||
|
||||
/* Compute MD5 and compare with recorded MD5 */
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto import_revert;
|
||||
}
|
||||
for (i = 0; i < image->checksum_idx_count - 1; i++)
|
||||
iso_md5_compute(ctx, image->checksum_array + i * 16, 16);
|
||||
iso_md5_end(&ctx, md5);
|
||||
for (i = 0; i < 16; i++)
|
||||
if (md5[i] != image->checksum_array[
|
||||
(image->checksum_idx_count - 1) * 16 + i]
|
||||
)
|
||||
break;
|
||||
if (i < 16) {
|
||||
iso_msg_submit(image->id, ISO_MD5_AREA_CORRUPTED, 0,
|
||||
"MD5 checksum array appears damaged and not trustworthy for verifications.");
|
||||
free(image->checksum_array);
|
||||
image->checksum_array = NULL;
|
||||
image->checksum_idx_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
goto import_cleanup;
|
||||
|
||||
@ -3027,9 +3223,16 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
iso_node_unref((IsoNode*)image->root);
|
||||
el_torito_boot_catalog_free(image->bootcat);
|
||||
image->root = oldroot;
|
||||
image->fs = fsback;
|
||||
image->bootcat = oldbootcat;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
old_checksum_start_lba = image->checksum_start_lba;
|
||||
old_checksum_end_lba = image->checksum_end_lba;
|
||||
old_checksum_idx_count = image->checksum_idx_count;
|
||||
image->checksum_array = old_checksum_array;
|
||||
old_checksum_array = NULL;
|
||||
#endif
|
||||
|
||||
import_cleanup:;
|
||||
|
||||
/* recover backed fs and builder */
|
||||
@ -3040,6 +3243,13 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
fs->close(fs);
|
||||
iso_filesystem_unref(fs);
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
if (old_checksum_array != NULL)
|
||||
free(old_checksum_array);
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3117,6 +3327,7 @@ int iso_read_opts_new(IsoReadOpts **opts, int profile)
|
||||
ropts->file_mode = 0444;
|
||||
ropts->dir_mode = 0555;
|
||||
ropts->noaaip= 1;
|
||||
ropts->nomd5= 1;
|
||||
|
||||
*opts = ropts;
|
||||
return ISO_SUCCESS;
|
||||
@ -3177,6 +3388,25 @@ int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->nomd5 = no_md5 ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->make_new_ino = new_inos ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_read_opts_set_preferjoliet(IsoReadOpts *opts, int preferjoliet)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
@ -3355,3 +3585,29 @@ int iso_file_get_old_image_sections(IsoFile *file, int *section_count,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rank two IsoFileSource by their eventual old image LBAs.
|
||||
Other IsoFileSource classes will be ranked only roughly.
|
||||
*/
|
||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag)
|
||||
{
|
||||
int i;
|
||||
ImageFileSourceData *d1, *d2;
|
||||
|
||||
if (s1->class != s2->class)
|
||||
return (s1->class < s2->class ? -1 : 1);
|
||||
if (s1->class != &ifs_class)
|
||||
return(0);
|
||||
|
||||
d1= s1->data;
|
||||
d2= s2->data;
|
||||
for (i = 0; i < d1->nsections; i++) {
|
||||
if (i >= d2->nsections)
|
||||
return 1;
|
||||
if (d1->sections[i].block != d2->sections[i].block)
|
||||
return (d1->sections[i].block < d2->sections[i].block ? -1 : 1);
|
||||
if (d1->sections[i].size != d2->sections[i].size)
|
||||
return (d1->sections[i].size < d2->sections[i].size ? -1 : 1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -30,4 +31,10 @@
|
||||
*/
|
||||
int iso_local_filesystem_new(IsoFilesystem **fs);
|
||||
|
||||
|
||||
/* Rank two IsoFileSource by their eventual old image LBAs.
|
||||
Other IsoFileSource classes will be ranked only roughly.
|
||||
*/
|
||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag);
|
||||
|
||||
#endif /*LIBISO_FSOURCE_H_*/
|
||||
|
297
libisofs/image.c
297
libisofs/image.c
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -14,6 +15,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* Create a new image, empty.
|
||||
@ -73,6 +75,17 @@ int iso_image_new(const char *name, IsoImage **image)
|
||||
}
|
||||
img->builder_ignore_acl = 1;
|
||||
img->builder_ignore_ea = 1;
|
||||
img->inode_counter = 0;
|
||||
img->used_inodes = NULL;
|
||||
img->used_inodes_start = 0;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
img->checksum_start_lba = 0;
|
||||
img->checksum_end_lba = 0;
|
||||
img->checksum_idx_count = 0;
|
||||
img->checksum_array = NULL;
|
||||
#endif
|
||||
|
||||
*image = img;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -119,10 +132,31 @@ void iso_image_unref(IsoImage *image)
|
||||
free(image->copyright_file_id);
|
||||
free(image->abstract_file_id);
|
||||
free(image->biblio_file_id);
|
||||
if (image->used_inodes != NULL)
|
||||
free(image->used_inodes);
|
||||
iso_image_free_checksums(image, 0);
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int iso_image_free_checksums(IsoImage *image, int flag)
|
||||
{
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
image->checksum_start_lba = 0;
|
||||
image->checksum_end_lba = 0;
|
||||
image->checksum_idx_count = 0;
|
||||
if (image->checksum_array != NULL)
|
||||
free(image->checksum_array);
|
||||
image->checksum_array = NULL;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attach user defined data to the image. Use this if your application needs
|
||||
* to store addition info together with the IsoImage. If the image already
|
||||
@ -179,6 +213,8 @@ void iso_image_set_volset_id(IsoImage *image, const char *volset_id)
|
||||
|
||||
const char *iso_image_get_volset_id(const IsoImage *image)
|
||||
{
|
||||
if (image->volset_id == NULL)
|
||||
return "";
|
||||
return image->volset_id;
|
||||
}
|
||||
|
||||
@ -190,6 +226,8 @@ void iso_image_set_volume_id(IsoImage *image, const char *volume_id)
|
||||
|
||||
const char *iso_image_get_volume_id(const IsoImage *image)
|
||||
{
|
||||
if (image->volume_id == NULL)
|
||||
return "";
|
||||
return image->volume_id;
|
||||
}
|
||||
|
||||
@ -201,6 +239,8 @@ void iso_image_set_publisher_id(IsoImage *image, const char *publisher_id)
|
||||
|
||||
const char *iso_image_get_publisher_id(const IsoImage *image)
|
||||
{
|
||||
if (image->publisher_id == NULL)
|
||||
return "";
|
||||
return image->publisher_id;
|
||||
}
|
||||
|
||||
@ -213,6 +253,8 @@ void iso_image_set_data_preparer_id(IsoImage *image,
|
||||
|
||||
const char *iso_image_get_data_preparer_id(const IsoImage *image)
|
||||
{
|
||||
if (image->data_preparer_id == NULL)
|
||||
return "";
|
||||
return image->data_preparer_id;
|
||||
}
|
||||
|
||||
@ -224,6 +266,8 @@ void iso_image_set_system_id(IsoImage *image, const char *system_id)
|
||||
|
||||
const char *iso_image_get_system_id(const IsoImage *image)
|
||||
{
|
||||
if (image->system_id == NULL)
|
||||
return "";
|
||||
return image->system_id;
|
||||
}
|
||||
|
||||
@ -235,6 +279,8 @@ void iso_image_set_application_id(IsoImage *image, const char *application_id)
|
||||
|
||||
const char *iso_image_get_application_id(const IsoImage *image)
|
||||
{
|
||||
if (image->application_id == NULL)
|
||||
return "";
|
||||
return image->application_id;
|
||||
}
|
||||
|
||||
@ -247,6 +293,8 @@ void iso_image_set_copyright_file_id(IsoImage *image,
|
||||
|
||||
const char *iso_image_get_copyright_file_id(const IsoImage *image)
|
||||
{
|
||||
if (image->copyright_file_id == NULL)
|
||||
return "";
|
||||
return image->copyright_file_id;
|
||||
}
|
||||
|
||||
@ -259,6 +307,8 @@ void iso_image_set_abstract_file_id(IsoImage *image,
|
||||
|
||||
const char *iso_image_get_abstract_file_id(const IsoImage *image)
|
||||
{
|
||||
if (image->abstract_file_id == NULL)
|
||||
return "";
|
||||
return image->abstract_file_id;
|
||||
}
|
||||
|
||||
@ -270,6 +320,8 @@ void iso_image_set_biblio_file_id(IsoImage *image, const char *biblio_file_id)
|
||||
|
||||
const char *iso_image_get_biblio_file_id(const IsoImage *image)
|
||||
{
|
||||
if (image->biblio_file_id == NULL)
|
||||
return "";
|
||||
return image->biblio_file_id;
|
||||
}
|
||||
|
||||
@ -318,3 +370,248 @@ void iso_image_set_ignore_aclea(IsoImage *image, int what)
|
||||
image->builder_ignore_ea = !!(what & 2);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int img_register_ino(IsoImage *image, IsoNode *node, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t ino;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
|
||||
ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0 && ino >= image->used_inodes_start &&
|
||||
ino <= image->used_inodes_start + (ISO_USED_INODE_RANGE - 1)) {
|
||||
/* without -1 : rollover hazard on 32 bit */
|
||||
image->used_inodes[(ino - image->used_inodes_start) / 8]
|
||||
|= (1 << (ino % 8));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Collect the bitmap of used inode numbers in the range of
|
||||
_ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE
|
||||
@param flag bit0= recursion is active
|
||||
*/
|
||||
int img_collect_inos(IsoImage *image, IsoDir *dir, int flag)
|
||||
{
|
||||
int ret, register_dir = 1;
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *node;
|
||||
IsoDir *subdir;
|
||||
|
||||
if (dir == NULL)
|
||||
dir = image->root;
|
||||
if (image->used_inodes == NULL) {
|
||||
image->used_inodes = calloc(ISO_USED_INODE_RANGE / 8, 1);
|
||||
if (image->used_inodes == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
} else if(!(flag & 1)) {
|
||||
memset(image->used_inodes, 0, ISO_USED_INODE_RANGE / 8);
|
||||
} else {
|
||||
register_dir = 0;
|
||||
}
|
||||
if (register_dir) {
|
||||
node = (IsoNode *) dir;
|
||||
ret = img_register_ino(image, node, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iso_dir_get_children(dir, &iter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (iso_dir_iter_next(iter, &node) == 1 ) {
|
||||
ret = img_register_ino(image, node, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (iso_node_get_type(node) == LIBISO_DIR) {
|
||||
subdir = (IsoDir *) node;
|
||||
ret = img_collect_inos(image, subdir, flag | 1);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A global counter for inode numbers for the ISO image filesystem.
|
||||
* On image import it gets maxed by the eventual inode numbers from PX
|
||||
* entries. Up to the first 32 bit rollover it simply increments the counter.
|
||||
* After the first rollover it uses a look ahead bitmap which gets filled
|
||||
* by a full tree traversal. It covers the next inode numbers to come
|
||||
* (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many)
|
||||
* and advances when being exhausted.
|
||||
* @param image The image where the number shall be used
|
||||
* @param flag bit0= reset count (Caution: image must get new inos then)
|
||||
* @return
|
||||
* Since ino_t 0 is used as default and considered self-unique,
|
||||
* the value 0 should only be returned in case of error.
|
||||
*/
|
||||
ino_t img_give_ino_number(IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t new_ino, ino_idx;
|
||||
static uint64_t limit = 0xffffffff;
|
||||
|
||||
if (flag & 1) {
|
||||
image->inode_counter = 0;
|
||||
if (image->used_inodes != NULL)
|
||||
free(image->used_inodes);
|
||||
image->used_inodes = NULL;
|
||||
image->used_inodes_start = 0;
|
||||
}
|
||||
new_ino = image->inode_counter + 1;
|
||||
if (image->used_inodes == NULL) {
|
||||
if (new_ino > 0 && new_ino <= limit) {
|
||||
image->inode_counter = new_ino;
|
||||
return image->inode_counter;
|
||||
}
|
||||
}
|
||||
/* Look for free number in used territory */
|
||||
while (1) {
|
||||
if (new_ino <= 0 || new_ino > limit ||
|
||||
new_ino >= image->used_inodes_start + ISO_USED_INODE_RANGE ) {
|
||||
|
||||
/* Collect a bitmap of used inode numbers ahead */
|
||||
|
||||
image->used_inodes_start += ISO_USED_INODE_RANGE;
|
||||
if (image->used_inodes_start > 0xffffffff ||
|
||||
image->used_inodes_start <= 0)
|
||||
image->used_inodes_start = 0;
|
||||
ret = img_collect_inos(image, NULL, 0);
|
||||
if (ret < 0)
|
||||
goto return_result; /* >>> need error return value */
|
||||
|
||||
new_ino = image->used_inodes_start + !image->used_inodes_start;
|
||||
}
|
||||
ino_idx = (new_ino - image->used_inodes_start) / 8;
|
||||
if (!(image->used_inodes[ino_idx] & (1 << (new_ino % 8)))) {
|
||||
image->used_inodes[ino_idx] |= (1 << (new_ino % 8));
|
||||
break;
|
||||
}
|
||||
new_ino++;
|
||||
}
|
||||
return_result:;
|
||||
image->inode_counter = new_ino;
|
||||
return image->inode_counter;
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
bit2= install inode with directories
|
||||
*/
|
||||
static
|
||||
int img_update_ino(IsoImage *image, IsoNode *node, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t ino;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
|
||||
ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
ino = 0;
|
||||
if (((flag & 1) || ino == 0) &&
|
||||
(iso_node_get_type(node) == LIBISO_FILE || (flag & (2 | 4))) &&
|
||||
((flag & 4) || iso_node_get_type(node) != LIBISO_DIR)) {
|
||||
ret = iso_node_set_unique_id(node, image, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
bit2= install inode with directories
|
||||
bit3= with bit2: install inode on parameter dir
|
||||
*/
|
||||
int img_make_inos(IsoImage *image, IsoDir *dir, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *node;
|
||||
IsoDir *subdir;
|
||||
|
||||
if (flag & 8) {
|
||||
node = (IsoNode *) dir;
|
||||
ret = img_update_ino(image, node, flag & 7);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
ret = iso_dir_get_children(dir, &iter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (iso_dir_iter_next(iter, &node) == 1) {
|
||||
ret = img_update_ino(image, node, flag & 7);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (iso_node_get_type(node) == LIBISO_DIR) {
|
||||
subdir = (IsoDir *) node;
|
||||
ret = img_make_inos(image, subdir, flag & ~8);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
|
||||
uint32_t *end_lba, char md5[16], int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
if (image->checksum_array == NULL || image->checksum_idx_count < 1)
|
||||
return 0;
|
||||
*start_lba = image->checksum_start_lba;
|
||||
*end_lba = image->checksum_end_lba;
|
||||
memcpy(md5, image->checksum_array, 16);
|
||||
return ISO_SUCCESS;
|
||||
|
||||
#else
|
||||
|
||||
return 0;
|
||||
|
||||
#endif /* ! Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
int iso_image_set_checksums(IsoImage *image, char *checksum_array,
|
||||
uint32_t start_lba, uint32_t end_lba,
|
||||
uint32_t idx_count, int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
iso_image_free_checksums(image, 0);
|
||||
image->checksum_array = checksum_array;
|
||||
image->checksum_start_lba = start_lba;
|
||||
image->checksum_end_lba = end_lba;
|
||||
image->checksum_idx_count = idx_count;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -13,6 +14,14 @@
|
||||
#include "fsource.h"
|
||||
#include "builder.h"
|
||||
|
||||
/* Size of a inode recycling window. Each new window causes a tree traversal.
|
||||
Window memory consumption is ISO_USED_INODE_RANGE / 8.
|
||||
This must be a power of 2 smaller than 30 bit and larger than 8 bit.
|
||||
Here: 32 kB memory for 256k inodes.
|
||||
*/
|
||||
#define ISO_USED_INODE_RANGE (1 << 18)
|
||||
|
||||
|
||||
/*
|
||||
* Image is a context for image manipulation.
|
||||
* Global objects such as the message_queues must belogn to that
|
||||
@ -121,6 +130,85 @@ struct Iso_Image
|
||||
*/
|
||||
void *user_data;
|
||||
void (*user_data_free)(void *ptr);
|
||||
|
||||
/**
|
||||
* Inode number management. inode_counter is taken over from
|
||||
* IsoImageFilesystem._ImageFsData after image import.
|
||||
* It is to be used with img_give_ino_number()
|
||||
*/
|
||||
ino_t inode_counter;
|
||||
/*
|
||||
* A bitmap of used inode numbers in an interval beginning at
|
||||
* used_inodes_start and holding ISO_USED_INODE_RANGE bits.
|
||||
* If a bit is set, then the corresponding inode number is occupied.
|
||||
* This interval is kept around inode_counter and eventually gets
|
||||
* advanced by ISO_USED_INODE_RANGE numbers in a tree traversal
|
||||
* done by img_collect_inos().
|
||||
*/
|
||||
uint8_t *used_inodes;
|
||||
ino_t used_inodes_start;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/**
|
||||
* Array of MD5 checksums as announced by xattr "isofs.ca" of the
|
||||
* root node. Array element 0 contains an overall image checksum for the
|
||||
* block range checksum_start_lba,checksum_end_lba. Element size is
|
||||
* 16 bytes. IsoFile objects in the image may have xattr "isofs.cx"
|
||||
* which gives their index in checksum_array.
|
||||
*/
|
||||
uint32_t checksum_start_lba;
|
||||
uint32_t checksum_end_lba;
|
||||
uint32_t checksum_idx_count;
|
||||
char *checksum_array;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Collect the bitmap of used inode numbers in the range of
|
||||
_ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE
|
||||
@param flag bit0= recursion is active
|
||||
*/
|
||||
int img_collect_inos(IsoImage *image, IsoDir *dir, int flag);
|
||||
|
||||
/**
|
||||
* A global counter for inode numbers for the ISO image filesystem.
|
||||
* On image import it gets maxed by the eventual inode numbers from PX
|
||||
* entries. Up to the first 32 bit rollover it simply increments the counter.
|
||||
* After the first rollover it uses a look ahead bitmap which gets filled
|
||||
* by a full tree traversal. It covers the next inode numbers to come
|
||||
* (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many)
|
||||
* and advances when being exhausted.
|
||||
* @param image The image where the number shall be used
|
||||
* @param flag bit0= reset count (Caution: image must get new inos then)
|
||||
* @return
|
||||
* Since ino_t 0 is used as default and considered self-unique,
|
||||
* the value 0 should only be returned in case of error.
|
||||
*/
|
||||
ino_t img_give_ino_number(IsoImage *image, int flag);
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
bit2= install inode with directories
|
||||
bit3= with bit2: install inode on parameter dir
|
||||
*/
|
||||
int img_make_inos(IsoImage *image, IsoDir *dir, int flag);
|
||||
|
||||
|
||||
/* Free the checksum array of an image and reset its layout parameters
|
||||
*/
|
||||
int iso_image_free_checksums(IsoImage *image, int flag);
|
||||
|
||||
|
||||
/* Equip an ISO image with a new checksum array buffer (after isofs.ca and
|
||||
isofs.cx have already been adjusted).
|
||||
*/
|
||||
int iso_image_set_checksums(IsoImage *image, char *checksum_array,
|
||||
uint32_t start_lba, uint32_t end_lba,
|
||||
uint32_t idx_count, int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_IMAGE_H_*/
|
||||
|
@ -759,8 +759,11 @@ typedef struct IsoStream_Iface IsoStreamIface;
|
||||
extern ino_t serial_id;
|
||||
|
||||
/**
|
||||
* Interface definition for IsoStream methods.
|
||||
*
|
||||
* Interface definition for IsoStream methods. It is public to allow
|
||||
* implementation of own stream types.
|
||||
* The methods defined here typically make use of stream.data which points
|
||||
* to the individual state data of stream instances.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
struct IsoStream_Iface
|
||||
@ -772,7 +775,9 @@ struct IsoStream_Iface
|
||||
* Version 1 (since 0.6.8)
|
||||
* update_size() added.
|
||||
* Version 2 (since 0.6.18)
|
||||
* get_input_stream() added. A filter stream should have version 2.
|
||||
* get_input_stream() added. A filter stream must have version 2.
|
||||
* Version 3 (since 0.6.20)
|
||||
* compare() added. A filter stream should have version 3.
|
||||
*/
|
||||
int version;
|
||||
|
||||
@ -784,6 +789,8 @@ struct IsoStream_Iface
|
||||
* "extf" -> External filter program
|
||||
* "ziso" -> zisofs compression
|
||||
* "osiz" -> zisofs uncompression
|
||||
* "gzip" -> gzip compression
|
||||
* "pizg" -> gzip uncompression (gunzip)
|
||||
* "user" -> User supplied stream
|
||||
*/
|
||||
char type[4];
|
||||
@ -854,7 +861,6 @@ struct IsoStream_Iface
|
||||
void (*free)(IsoStream *stream);
|
||||
|
||||
/**
|
||||
* Present if .version is 1 or higher:
|
||||
* Updates the size of the IsoStream with the current size of the
|
||||
* underlying source. After calling this, get_size() will return
|
||||
* the new size. This should never be called after
|
||||
@ -867,24 +873,70 @@ struct IsoStream_Iface
|
||||
* 1 if ok, < 0 on error (has to be a valid libisofs error code)
|
||||
*
|
||||
* @since 0.6.8
|
||||
* Present if .version is 1 or higher.
|
||||
*/
|
||||
int (*update_size)(IsoStream *stream);
|
||||
|
||||
/**
|
||||
* Present if .version is 2 or higher:
|
||||
* Obtains the eventual input stream of a filter stream.
|
||||
*
|
||||
* @param stream
|
||||
* The eventual filter stream to be inquired.
|
||||
* The eventual filter stream to be inquired.
|
||||
* @param flag
|
||||
* Bitfield for control purposes. Submit 0 for now.
|
||||
* Bitfield for control purposes. Submit 0 for now.
|
||||
* @return
|
||||
* The input stream, if one exists. Elsewise NULL.
|
||||
* No extra reference to the stream is taken by this call.
|
||||
* The input stream, if one exists. Elsewise NULL.
|
||||
* No extra reference to the stream is taken by this call.
|
||||
*
|
||||
* @since 0.6.18
|
||||
* Present if .version is 2 or higher.
|
||||
*/
|
||||
IsoStream *(*get_input_stream)(IsoStream *stream, int flag);
|
||||
|
||||
/**
|
||||
* Compare two streams whether they are based on the same input and will
|
||||
* produce the same output. If in any doubt, then this comparison should
|
||||
* indicate no match. A match might allow hardlinking of IsoFile objects.
|
||||
*
|
||||
* This function has to establish an equivalence and order relation:
|
||||
* cmp_ino(A,A) == 0
|
||||
* cmp_ino(A,B) == -cmp_ino(B,A)
|
||||
* if cmp_ino(A,B) == 0 && cmp_ino(B,C) == 0 then cmp_ino(A,C) == 0
|
||||
* if cmp_ino(A,B) < 0 && cmp_ino(B,C) < 0 then cmp_ino(A,C) < 0
|
||||
*
|
||||
* A big hazard to the last constraint are tests which do not apply to some
|
||||
* types of streams. In this case for any A that is applicable and any B
|
||||
* that is not applicable, cmp_ino(A,B) must have the same non-zero
|
||||
* result. I.e. a pair of applicable and non-applicable streams must
|
||||
* return that non-zero result before the test for a pair of applicable
|
||||
* streams would happen.
|
||||
*
|
||||
* A function s1.(*cmp_ino)() must only accept stream s2 if function
|
||||
* s2.(*cmp_ino)() would accept s1. Best is to accept only the own stream
|
||||
* type or to have the same function for a family of similar stream types.
|
||||
*
|
||||
* If the function cannot accept one of the given stream types, then
|
||||
* the decision must be delegated to
|
||||
* iso_stream_cmp_ino(s1, s2, 1);
|
||||
* This is also appropriate if one has reason to implement stream.cmp_ino()
|
||||
* without special comparison algorithm.
|
||||
* With filter streams the decision whether the underlying chains of
|
||||
* streams match should be delegated to
|
||||
* iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
* iso_stream_get_input_stream(s2, 0), 0);
|
||||
*
|
||||
* @param s1
|
||||
* The first stream to compare. Expect foreign stream types.
|
||||
* @param s2
|
||||
* The second stream to compare. Expect foreign stream types.
|
||||
* @return
|
||||
* -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2
|
||||
*
|
||||
* @since 0.6.20
|
||||
* Present if .version is 3 or higher.
|
||||
*/
|
||||
int (*cmp_ino)(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1038,7 +1090,7 @@ int iso_lib_is_compatible(int major, int minor, int micro);
|
||||
*/
|
||||
#define iso_lib_header_version_major 0
|
||||
#define iso_lib_header_version_minor 6
|
||||
#define iso_lib_header_version_micro 18
|
||||
#define iso_lib_header_version_micro 24
|
||||
|
||||
/**
|
||||
* Usage discussion:
|
||||
@ -1184,15 +1236,47 @@ int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable);
|
||||
*/
|
||||
int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable);
|
||||
|
||||
/**
|
||||
* Control generation of non-unique inode numbers for the emerging image.
|
||||
* Inode numbers get written as "file serial number" with PX entries as of
|
||||
* RRIP-1.12. They may mark families of hardlinks.
|
||||
* RRIP-1.10 prescribes a PX entry without file serial number. If not overriden
|
||||
* by iso_write_opts_set_rrip_1_10_px_ino() there will be no file serial
|
||||
* written into RRIP-1.10 images.
|
||||
*
|
||||
* Inode number generation does not affect IsoNode objects which imported their
|
||||
* inode numbers from the old ISO image (see iso_read_opts_set_new_inos())
|
||||
* and which have not been altered since import. It rather applies to IsoNode
|
||||
* objects which were newly added to the image, or to IsoNode which brought no
|
||||
* inode number from the old image, or to IsoNode where certain properties
|
||||
* have been altered since image import.
|
||||
*
|
||||
* If two IsoNode are found with same imported inode number but differing
|
||||
* properties, then one of them will get assigned a new unique inode number.
|
||||
* I.e. the hardlink relation between both IsoNode objects ends.
|
||||
*
|
||||
* @param enable
|
||||
* 1 = Collect IsoNode objects which have identical data sources and
|
||||
* properties.
|
||||
* 0 = Generate unique inode numbers for all IsoNode objects which do not
|
||||
* have a valid inode number from an imported ISO image.
|
||||
* All other values are reserved.
|
||||
*
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable);
|
||||
|
||||
/**
|
||||
* Control writing of AAIP informations for ACL and xattr.
|
||||
* For importing ACL and xattr when inserting nodes from external filesystems
|
||||
* (e.g. the local POSIX filesystem) see iso_image_set_ignore_aclea().
|
||||
* For loading of this information from images see iso_read_opts_set_no_aaip().
|
||||
*
|
||||
* @param enable 1 = write AAIP information from nodes into the image
|
||||
* 0 = do not write AAIP information into the image
|
||||
* All other values are reserved.
|
||||
* @param enable
|
||||
* 1 = write AAIP information from nodes into the image
|
||||
* 0 = do not write AAIP information into the image
|
||||
* All other values are reserved.
|
||||
*
|
||||
* @since 0.6.14
|
||||
*/
|
||||
int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable);
|
||||
@ -1288,6 +1372,18 @@ int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow);
|
||||
*/
|
||||
int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers);
|
||||
|
||||
/**
|
||||
* Write field PX with file serial number (i.e. inode number) even if
|
||||
* iso_write_opts_set_rrip_version_1_10(,1) is in effect.
|
||||
* This clearly violates the RRIP-1.10 specs. But it is done by mkisofs since
|
||||
* a while and no widespread protest is visible in the web.
|
||||
* If this option is not enabled, then iso_write_opts_set_hardlinks() will
|
||||
* only have an effect with iso_write_opts_set_rrip_version_1_10(,0).
|
||||
*
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable);
|
||||
|
||||
/**
|
||||
* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12.
|
||||
* I.e. without announcing it by an ER field and thus without the need
|
||||
@ -1319,11 +1415,69 @@ int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow);
|
||||
*/
|
||||
int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort);
|
||||
|
||||
/**
|
||||
* Whether to compute and record MD5 checksums for the whole session and/or
|
||||
* for each single IsoFile object. The checksums represent the data as they
|
||||
* were written into the image output stream, not necessarily as they were
|
||||
* on hard disk at any point of time.
|
||||
* See also calls iso_image_get_session_md5() and iso_file_get_md5().
|
||||
* @param opts
|
||||
* The option set to be manipulated.
|
||||
* @param session
|
||||
* If bit0 set: Compute session checksum
|
||||
* @param files
|
||||
* If bit0 set: Compute a checksum for each single IsoFile object which
|
||||
* gets its data content written into the session. Copy
|
||||
* checksums from files which keep their data in older
|
||||
* sessions.
|
||||
* If bit1 set: Check content stability (only with bit0). I.e. before
|
||||
* writing the file content into to image stream, read it
|
||||
* once and compute a MD5. Do a second reading for writing
|
||||
* into the image stream. Afterwards compare both MD5 and
|
||||
* issue a MISHAP event ISO_MD5_STREAM_CHANGE if they do not
|
||||
* match.
|
||||
* Such a mismatch indicates content changes between the
|
||||
* time point when the first MD5 reading started and the
|
||||
* time point when the last block was read for writing.
|
||||
* So there is high risk that the image stream was fed from
|
||||
* changing and possibly inconsistent file content.
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files);
|
||||
|
||||
/**
|
||||
* Set the parameters "name" and "timestamp" for a scdbackup checksum tag.
|
||||
* It will be appended to the libisofs session tag if the image starts at
|
||||
* LBA 0 (see iso_write_opts_set_ms_block()). The scdbackup tag can be used
|
||||
* to verify the image by command scdbackup_verify <device> -auto_end.
|
||||
* See scdbackup/README appendix VERIFY for its inner details.
|
||||
*
|
||||
* @param name
|
||||
* A word of up to 80 characters. Typically <volno>_<totalno> telling
|
||||
* that this is volume <volno> of a total of <totalno> volumes.
|
||||
* @param timestamp
|
||||
* A string of 13 characters YYMMDD.hhmmss (e.g. A90831.190324).
|
||||
* A9 = 2009, B0 = 2010, B1 = 2011, ... C0 = 2020, ...
|
||||
* @param tag_written
|
||||
* Either NULL or the address of an array with at least 512 characters.
|
||||
* In the latter case the eventually produced scdbackup tag will be
|
||||
* copied to this array when the image gets written. This call sets
|
||||
* scdbackup_tag_written[0] = 0 to mark its preliminary invalidity.
|
||||
* @return
|
||||
* 1 indicates success, <0 is error
|
||||
*
|
||||
* @since 0.6.24
|
||||
*/
|
||||
int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts,
|
||||
char *name, char *timestamp,
|
||||
char *tag_written);
|
||||
|
||||
/**
|
||||
* Whether to set default values for files and directory permissions, gid and
|
||||
* uid. All these take one of three values: 0, 1 or 2.
|
||||
*
|
||||
* If 0, the corresponding attribute will be kept as setted in the IsoNode.
|
||||
* If 0, the corresponding attribute will be kept as set in the IsoNode.
|
||||
* Unless you have changed it, it corresponds to the value on disc, so it
|
||||
* is suitable for backup purposes. If set to 1, the corresponding attrib.
|
||||
* will be changed by a default suitable value. Finally, if you set it to
|
||||
@ -1651,13 +1805,50 @@ int iso_read_opts_set_no_iso1999(IsoReadOpts *opts, int noiso1999);
|
||||
* (e.g. the local POSIX filesystem) see iso_image_set_ignore_aclea().
|
||||
* For eventual writing of this information see iso_write_opts_set_aaip().
|
||||
*
|
||||
* @param noaaip 1 = do not read AAIP information
|
||||
* 0 = read AAIP information if available
|
||||
* All other values are reserved.
|
||||
* @param noaaip
|
||||
* 1 = Do not read AAIP information
|
||||
* 0 = Read AAIP information if available
|
||||
* All other values are reserved.
|
||||
* @since 0.6.14
|
||||
*/
|
||||
int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip);
|
||||
|
||||
/**
|
||||
* Control reading of an array of MD5 checksums which is eventually stored
|
||||
* at the end of a session. See also iso_write_opts_set_record_md5().
|
||||
* Important: Loading of the MD5 array will only work if AAIP is enabled
|
||||
* because its position and layout is recorded in xattr "isofs.ca".
|
||||
*
|
||||
* @param no_md5
|
||||
* 1 = Do not read MD5 checksum array
|
||||
* 0 = Read Md% array if available
|
||||
* All other values are reserved.
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5);
|
||||
|
||||
|
||||
/**
|
||||
* Control discarding of eventual inode numbers from existing images.
|
||||
* Such numbers may come from RRIP 1.12 entries PX. If not discarded they
|
||||
* get written unchanged when the file object gets written into an ISO image.
|
||||
* If this inode number is missing with a file in the imported image,
|
||||
* or if it has been discarded during image reading, then a unique inode number
|
||||
* will be generated at some time before the file gets written into an ISO
|
||||
* image.
|
||||
* Two image nodes which have the same inode number represent two hardlinks
|
||||
* of the same file object. So discarding the numbers splits hardlinks.
|
||||
*
|
||||
* @param new_inos
|
||||
* 1 = Discard imported inode numbers and finally hand out a unique new
|
||||
* one to each single file before it gets written into an ISO image.
|
||||
* 0 = Keep eventual inode numbers from PX entries.
|
||||
* All other values are reserved.
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos);
|
||||
|
||||
/**
|
||||
* Whether to prefer Joliet over RR. libisofs usually prefers RR over
|
||||
* Joliet, as it give us much more info about files. So, if both extensions
|
||||
@ -2122,7 +2313,7 @@ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors);
|
||||
void el_torito_set_no_bootable(ElToritoBootImage *bootimg);
|
||||
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writting
|
||||
* Specifies that this image needs to be patched. This involves the writing
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* The original boot image file won't be modified.
|
||||
* This is needed for isolinux boot images.
|
||||
@ -2384,7 +2575,7 @@ time_t iso_node_get_ctime(const IsoNode *node);
|
||||
/**
|
||||
* 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
|
||||
* If the file is set 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
|
||||
@ -2402,6 +2593,22 @@ time_t iso_node_get_ctime(const IsoNode *node);
|
||||
*/
|
||||
void iso_node_set_hidden(IsoNode *node, int hide_attrs);
|
||||
|
||||
/**
|
||||
* Compare two nodes whether they are based on the same input and
|
||||
* can be considered as hardlinks to the same file objects.
|
||||
*
|
||||
* @param n1
|
||||
* The first node to compare.
|
||||
* @param n2
|
||||
* The second node to compare.
|
||||
* @return
|
||||
* -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2
|
||||
* @param flag
|
||||
* Bitfield for control purposes, unused yet, submit 0
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag);
|
||||
|
||||
/**
|
||||
* Add a new node to a dir. Note that this function don't add a new ref to
|
||||
* the node, so you don't need to free it, it will be automatically freed
|
||||
@ -2503,7 +2710,7 @@ int iso_node_remove(IsoNode *node);
|
||||
* If node is the root node, the same node will be returned as its parent.
|
||||
*
|
||||
* This returns NULL if the node doesn't pertain to any tree
|
||||
* (it was removed/take).
|
||||
* (it was removed/taken).
|
||||
*
|
||||
* @since 0.6.2
|
||||
*/
|
||||
@ -4078,7 +4285,9 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
/**
|
||||
* Try to get eventual source path string of a stream. Meaning and availability
|
||||
* of this string depends on the stream.class . Expect valid results with
|
||||
* types "fsrc" and "cout".
|
||||
* types "fsrc" and "cout". Result formats are
|
||||
* fsrc: result of file_source_get_path()
|
||||
* cout: result of file_source_get_path() " " offset " " size
|
||||
* @param stream
|
||||
* The stream to be inquired.
|
||||
* @param flag
|
||||
@ -4091,6 +4300,25 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
*/
|
||||
char *iso_stream_get_source_path(IsoStream *stream, int flag);
|
||||
|
||||
/**
|
||||
* Compare two streams whether they are based on the same input and will
|
||||
* produce the same output. If in any doubt, then this comparison will
|
||||
* indicate no match.
|
||||
*
|
||||
* @param s1
|
||||
* The first stream to compare.
|
||||
* @param s2
|
||||
* The second stream to compare.
|
||||
* @return
|
||||
* -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2
|
||||
* @param flag
|
||||
* bit0= do not use s1->class->compare() even if available
|
||||
* (e.g. because iso_stream_cmp_ino(0 is called as fallback
|
||||
* from said stream->class->compare())
|
||||
*
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag);
|
||||
|
||||
/* --------------------------------- AAIP --------------------------------- */
|
||||
|
||||
@ -4258,7 +4486,7 @@ int iso_node_get_attrs(IsoNode *node, size_t *num_attrs,
|
||||
* @param flag
|
||||
* Bitfield for control purposes, unused yet, submit 0
|
||||
* @return
|
||||
* 1= name found , 0= name not found , <0 indicates error error
|
||||
* 1= name found , 0= name not found , <0 indicates error
|
||||
*
|
||||
* @since 0.6.18
|
||||
*/
|
||||
@ -4288,7 +4516,11 @@ int iso_node_lookup_attr(IsoNode *node, char *name,
|
||||
* bit0= Do not maintain eventual existing ACL of the node.
|
||||
* Set eventual new ACL from value of empty name.
|
||||
* bit1= Do not clear the existing attribute list but merge it with
|
||||
* the list given by this call
|
||||
* the list given by this call.
|
||||
* The given values override the values of their eventually existing
|
||||
* names. If no xattr with a given name exists, then it will be
|
||||
* added as new xattr. So this bit can be used to set a single
|
||||
* xattr without inquiring any other xattr of the node.
|
||||
* bit2= Delete the attributes with the given names
|
||||
* bit3= Allow to affect non-user attributes.
|
||||
* I.e. those with a non-empty name which does not begin by "user."
|
||||
@ -4799,6 +5031,223 @@ int iso_file_add_gzip_filter(IsoFile *file, int flag);
|
||||
int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
|
||||
|
||||
|
||||
/* ---------------------------- MD5 Checksums --------------------------- */
|
||||
|
||||
/* Production and loading of MD5 checksums is controlled by calls
|
||||
iso_write_opts_set_record_md5() and iso_read_opts_set_no_md5().
|
||||
For data representation details see doc/checksums.txt .
|
||||
*/
|
||||
|
||||
/**
|
||||
* Eventually obtain the recorded MD5 checksum of the session which was
|
||||
* loaded as ISO image. Such a checksum may be stored together with others
|
||||
* in a contiguous array at the end of the session. The session checksum
|
||||
* covers the data blocks from address start_lba to address end_lba - 1.
|
||||
* It does not cover the recorded array of md5 checksums.
|
||||
* Layout, size, and position of the checksum array is recorded in the xattr
|
||||
* "isofs.ca" of the session root node.
|
||||
* @param image
|
||||
* The image to inquire
|
||||
* @param start_lba
|
||||
* Eventually returns the first block address covered by md5
|
||||
* @param end_lba
|
||||
* Eventually returns the first block address not covered by md5 any more
|
||||
* @param md5
|
||||
* Eventually returns 16 byte of MD5 checksum
|
||||
* @param flag
|
||||
* Bitfield for control purposes, unused yet, submit 0
|
||||
* @return
|
||||
* 1= md5 found , 0= no md5 available , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
|
||||
uint32_t *end_lba, char md5[16], int flag);
|
||||
|
||||
/**
|
||||
* Eventually obtain the recorded MD5 checksum of a data file from the loaded
|
||||
* ISO image. Such a checksum may be stored with others in a contiguous
|
||||
* array at the end of the loaded session. The data file eventually has an
|
||||
* xattr "isofs.cx" which gives the index in that array.
|
||||
* @param image
|
||||
* The image from which file stems.
|
||||
* @param file
|
||||
* The file object to inquire
|
||||
* @param md5
|
||||
* Eventually returns 16 byte of MD5 checksum
|
||||
* @param flag
|
||||
* Bitfield for control purposes
|
||||
* bit0= only determine return value, do not touch parameter md5
|
||||
* @return
|
||||
* 1= md5 found , 0= no md5 available , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
|
||||
|
||||
/**
|
||||
* Read the content of an IsoFile object, compute its MD5 and attach it to
|
||||
* the IsoFile. It can then be inquired by iso_file_get_md5() and will get
|
||||
* written into the next session if this is enabled at write time and if the
|
||||
* image write process does not compute an MD5 from content which it copies.
|
||||
* So this call can be used to equip nodes from the old image with checksums
|
||||
* or to make available checksums of newly added files before the session gets
|
||||
* written.
|
||||
* @param file
|
||||
* The file object to read data from and to which to attach the checksum.
|
||||
* If the file is from the imported image, then its most original stream
|
||||
* will be checksummed. Else the eventual filter streams will get into
|
||||
* effect.
|
||||
* @param flag
|
||||
* Bitfield for control purposes. Unused yet. Submit 0.
|
||||
* @return
|
||||
* 1= ok, MD5 is computed and attached , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_file_make_md5(IsoFile *file, int flag);
|
||||
|
||||
/**
|
||||
* Check a data block whether it is a libisofs session checksum tag and
|
||||
* eventually obtain its recorded parameters. These tags get written after
|
||||
* volume descriptors, directory tree and checksum array and can be detected
|
||||
* without loading the image tree.
|
||||
* One may start reading and computing MD5 at the suspected image session
|
||||
* start and look out for a session tag on the fly. See doc/checksum.txt .
|
||||
* @param data
|
||||
* A complete and aligned data block read from an ISO image session.
|
||||
* @param tag_type
|
||||
* 0= no tag
|
||||
* 1= session tag
|
||||
* 2= superblock tag
|
||||
* 3= tree tag
|
||||
* 4= relocated 64 kB superblock tag (at LBA 0 of overwriteable media)
|
||||
* @param pos
|
||||
* Returns the LBA where the tag supposes itself to be stored.
|
||||
* If this does not match the data block LBA then the tag might be
|
||||
* image data payload and should be ignored for image checksumming.
|
||||
* @param range_start
|
||||
* Returns the block address where the session is supposed to start.
|
||||
* If this does not match the session start on media then the image
|
||||
* volume descriptors have been been relocated.
|
||||
* A proper checksum will only emerge if computing started at range_start.
|
||||
* @param range_size
|
||||
* Returns the number of blocks beginning at range_start which are
|
||||
* covered by parameter md5.
|
||||
* @param next_tag
|
||||
* Returns the predicted block address of the next tag.
|
||||
* next_tag is valid only if not 0 and only with return values 2, 3, 4.
|
||||
* With tag types 2 and 3, reading shall go on sequentially and the MD5
|
||||
* computation shall continue up to that address.
|
||||
* With tag type 4, reading shall resume either at LBA 32 for the first
|
||||
* session or at the given address for the session which is to be loaded
|
||||
* by default. In both cases the MD5 computation shall be re-started from
|
||||
* scratch.
|
||||
* @param md5
|
||||
* Returns 16 byte of MD5 checksum.
|
||||
* @param flag
|
||||
* Bitfield for control purposes:
|
||||
* bit0-bit7= tag type being looked for
|
||||
* 0= any checksum tag
|
||||
* 1= session tag
|
||||
* 2= superblock tag
|
||||
* 3= tree tag
|
||||
* 4= relocated superblock tag
|
||||
* @return
|
||||
* 0= not a checksum tag, return parameters are invalid
|
||||
* 1= checksum tag found, return parameters are valid
|
||||
* <0= error
|
||||
* (return parameters are valid with error ISO_MD5_AREA_CORRUPTED
|
||||
* but not trustworthy because the tag seems corrupted)
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
|
||||
uint32_t *range_start, uint32_t *range_size,
|
||||
uint32_t *next_tag, char md5[16], int flag);
|
||||
|
||||
|
||||
/* The following functions allow to do own MD5 computations. E.g for
|
||||
comparing the result with a recorded checksum.
|
||||
*/
|
||||
/**
|
||||
* Create a MD5 computation context and hand out an opaque handle.
|
||||
*
|
||||
* @param md5_context
|
||||
* Returns the opaque handle. Submitted *md5_context must be NULL or
|
||||
* point to freeable memory.
|
||||
* @return
|
||||
* 1= success , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_md5_start(void **md5_context);
|
||||
|
||||
/**
|
||||
* Advance the computation of a MD5 checksum by a chunk of data bytes.
|
||||
*
|
||||
* @param md5_context
|
||||
* An opaque handle once returned by iso_md5_start() or iso_md5_clone().
|
||||
* @param data
|
||||
* The bytes which shall be processed into to the checksum.
|
||||
* @param datalen
|
||||
* The number of bytes to be processed.
|
||||
* @return
|
||||
* 1= success , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_md5_compute(void *md5_context, char *data, int datalen);
|
||||
|
||||
/**
|
||||
* Create a MD5 computation context as clone of an existing one. One may call
|
||||
* iso_md5_clone(old, &new, 0) and then iso_md5_end(&new, result, 0) in order
|
||||
* to obtain an intermediate MD5 sum before the computation goes on.
|
||||
*
|
||||
* @param old_md5_context
|
||||
* An opaque handle once returned by iso_md5_start() or iso_md5_clone().
|
||||
* @param new_md5_context
|
||||
* Returns the opaque handle to the new MD5 context. Submitted
|
||||
* *md5_context must be NULL or point to freeable memory.
|
||||
* @return
|
||||
* 1= success , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_md5_clone(void *old_md5_context, void **new_md5_context);
|
||||
|
||||
/**
|
||||
* Obtain the MD5 checksum from a MD5 computation context and dispose this
|
||||
* context. (If you want to keep the context then call iso_md5_clone() and
|
||||
* apply iso_md5_end() to the clone.)
|
||||
*
|
||||
* @param md5_context
|
||||
* A pointer to an opaque handle once returned by iso_md5_start() or
|
||||
* iso_md5_clone(). *md5_context will be set to NULL in this call.
|
||||
* @param result
|
||||
* Gets filled with the 16 bytes of MD5 checksum.
|
||||
* @return
|
||||
* 1= success , <0 indicates error
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_md5_end(void **md5_context, char result[16]);
|
||||
|
||||
/**
|
||||
* Inquire whether two MD5 checksums match. (This is trivial but such a call
|
||||
* is convenient and completes the interface.)
|
||||
* @param first_md5
|
||||
* A MD5 byte string as returned by iso_md5_end()
|
||||
* @param second_md5
|
||||
* A MD5 byte string as returned by iso_md5_end()
|
||||
* @return
|
||||
* 1= match , 0= mismatch
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_md5_match(char first_md5[16], char second_md5[16]);
|
||||
|
||||
|
||||
/************ Error codes and return values for libisofs ********************/
|
||||
|
||||
/** successfully execution */
|
||||
@ -4931,11 +5380,12 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
|
||||
#define ISO_FILE_IMGPATH_WRONG 0xD020FF70
|
||||
|
||||
/**
|
||||
* Offset greater than file size (FAILURE,HIGH, -145)
|
||||
* Offset greater than file size (FAILURE,HIGH, -150)
|
||||
* @since 0.6.4
|
||||
*/
|
||||
#define ISO_FILE_OFFSET_TOO_BIG 0xE830FF6A
|
||||
|
||||
|
||||
/** Charset conversion error (FAILURE,HIGH, -256) */
|
||||
#define ISO_CHARSET_CONV_ERROR 0xE830FF00
|
||||
|
||||
@ -4998,18 +5448,6 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
|
||||
/** El-Torito image is hidden (WARNING,HIGH, -335) */
|
||||
#define ISO_EL_TORITO_HIDDEN 0xD030FEB1
|
||||
|
||||
/** Read error occured with IsoDataSource (SORRY,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_SORRY 0xE030FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (MISHAP,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_MISHAP 0xE430FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FAILURE,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FAILURE 0xE830FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FATAL,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FATAL 0xF030FCFF
|
||||
|
||||
|
||||
/** AAIP info with ACL or xattr in ISO image will be ignored
|
||||
(NOTE, HIGH, -336) */
|
||||
@ -5065,6 +5503,78 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
|
||||
/** Premature EOF of zlib input stream (FAILURE, HIGH, -351) */
|
||||
#define ISO_ZLIB_EARLY_EOF 0xE830FEA1
|
||||
|
||||
/**
|
||||
* Checksum area or checksum tag appear corrupted (WARNING,HIGH, -352)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_AREA_CORRUPTED 0xD030FEA0
|
||||
|
||||
/**
|
||||
* Checksum mismatch between checksum tag and data blocks
|
||||
* (FAILURE, HIGH, -353)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_MISMATCH 0xE830FE9F
|
||||
|
||||
/**
|
||||
* Checksum mismatch in System Area, Volume Descriptors, or directory tree.
|
||||
* (FAILURE, HIGH, -354)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_SB_TREE_CORRUPTED 0xE830FE9E
|
||||
|
||||
/**
|
||||
* Unexpected checksum tag type encountered. (WARNING, HIGH, -355)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_UNEXPECTED 0xD030FE9D
|
||||
|
||||
/**
|
||||
* Misplaced checksum tag encountered. (WARNING, HIGH, -356)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_MISPLACED 0xD030FE9C
|
||||
|
||||
/**
|
||||
* Checksum tag with unexpected address range encountered.
|
||||
* (WARNING, HIGH, -357)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_OTHER_RANGE 0xD030FE9B
|
||||
|
||||
/**
|
||||
* Detected file content changes while it was written into the image.
|
||||
* (MISHAP, HIGH, -358)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_STREAM_CHANGE 0xE430FE9A
|
||||
|
||||
/**
|
||||
* Session does not start at LBA 0. scdbackup checksum tag not written.
|
||||
* (WARNING, HIGH, -359)
|
||||
* @since 0.6.24
|
||||
*/
|
||||
#define ISO_SCDBACKUP_TAG_NOT_0 0xD030FE99
|
||||
|
||||
|
||||
/* ! PLACE NEW ERROR CODES HERE ! */
|
||||
|
||||
|
||||
/** Read error occured with IsoDataSource (SORRY,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_SORRY 0xE030FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (MISHAP,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_MISHAP 0xE430FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FAILURE,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FAILURE 0xE830FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FATAL,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FATAL 0xF030FCFF
|
||||
|
||||
|
||||
/* ! PLACE NEW ERROR CODES ABOVE. NOT HERE ! */
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@ -5251,35 +5761,21 @@ struct burn_source {
|
||||
|
||||
/* currently none being tested */
|
||||
|
||||
|
||||
/* ---------------------------- Improvements --------------------------- */
|
||||
|
||||
|
||||
/* Cleanup : make call setlocale() at init time resp. never
|
||||
/* Checksums : During image writing equip IsoFile objects with MD5 checksums
|
||||
and compute an overall checksum of the session. Store them in
|
||||
a separate checksum block area after the data area of the
|
||||
session.
|
||||
*/
|
||||
#define Libisofs_setlocale_in_iniT yes
|
||||
|
||||
|
||||
/* Protocol Upgrade : change to AAIP-2.0 with field signature "AL"
|
||||
*/
|
||||
#define Libisofs_aaip_2_0 yes
|
||||
#define Libisofs_with_checksumS yes
|
||||
|
||||
|
||||
/* ---------------------------- Experiments ---------------------------- */
|
||||
|
||||
|
||||
/* Experiment: Ignore PX inode numbers,
|
||||
have boot image inode number counted by fs_give_ino_number()
|
||||
*/
|
||||
#define Libisofs_new_fs_image_inO yes
|
||||
|
||||
|
||||
|
||||
/* Experiment: Revoke Ticket 144, use data file LBAs again.
|
||||
(will work only if not Libisofs_new_fs_image_inO)
|
||||
#define Libisofs_ino_from_lbA yes
|
||||
*/
|
||||
|
||||
|
||||
/* Experiment: Write obsolete RR entries with Rock Ridge.
|
||||
I suspect Solaris wants to see them.
|
||||
DID NOT HELP: Solaris knows only RRIP_1991A.
|
||||
@ -5288,12 +5784,4 @@ struct burn_source {
|
||||
*/
|
||||
|
||||
|
||||
/* Experiment: Use iso_iconv*() wrappers.
|
||||
They can print errno messages and they
|
||||
can avoid iconv() if the identical mapping is desired.
|
||||
One could install own simple conversion capabilities.
|
||||
*/
|
||||
#define Libisofs_with_iso_iconV yes
|
||||
|
||||
|
||||
#endif /*LIBISO_LIBISOFS_H_*/
|
||||
|
@ -25,12 +25,13 @@ and is now under the licenses to which H.Peter Anvin agreed:
|
||||
or both, at your option.
|
||||
Sincerely, H. Peter Anvin
|
||||
|
||||
In the context of libisofs this code derives its matching open source
|
||||
In the context of xorriso-standalone, this code is under GPLv2 derived from
|
||||
LGPL. In the context of libisofs this code derives its matching open source
|
||||
license from above stem licenses, typically from LGPL.
|
||||
In case its generosity is needed, here is the 2-clause BSD license:
|
||||
|
||||
make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin
|
||||
and 2008 libburnia project.
|
||||
and 2008-2009 libburnia project.
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
874
libisofs/md5.c
Normal file
874
libisofs/md5.c
Normal file
@ -0,0 +1,874 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "writer.h"
|
||||
#include "messages.h"
|
||||
#include "ecma119.h"
|
||||
#include "image.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
|
||||
/* This code is derived from RFC 1321 and implements computation of the
|
||||
"RSA Data Security, Inc. MD5 Message-Digest Algorithm" */
|
||||
|
||||
#define Libisofs_md5_S11 7
|
||||
#define Libisofs_md5_S12 12
|
||||
#define Libisofs_md5_S13 17
|
||||
#define Libisofs_md5_S14 22
|
||||
#define Libisofs_md5_S21 5
|
||||
#define Libisofs_md5_S22 9
|
||||
#define Libisofs_md5_S23 14
|
||||
#define Libisofs_md5_S24 20
|
||||
#define Libisofs_md5_S31 4
|
||||
#define Libisofs_md5_S32 11
|
||||
#define Libisofs_md5_S33 16
|
||||
#define Libisofs_md5_S34 23
|
||||
#define Libisofs_md5_S41 6
|
||||
#define Libisofs_md5_S42 10
|
||||
#define Libisofs_md5_S43 15
|
||||
#define Libisofs_md5_S44 21
|
||||
|
||||
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
*/
|
||||
#define Libisofs_md5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define Libisofs_md5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define Libisofs_md5_H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define Libisofs_md5_I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
*/
|
||||
#define Libisofs_md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
#define Libisofs_md5_FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += Libisofs_md5_F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define Libisofs_md5_GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += Libisofs_md5_G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define Libisofs_md5_HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += Libisofs_md5_H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define Libisofs_md5_II(a, b, c, d, x, s, ac) { \
|
||||
(a) += Libisofs_md5_I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
|
||||
/* MD5 context. */
|
||||
struct _libisofs_md5_ctx {
|
||||
uint32_t state[4]; /* state (ABCD) */
|
||||
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
};
|
||||
|
||||
typedef struct _libisofs_md5_ctx libisofs_md5_ctx;
|
||||
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
*/
|
||||
static int md5__transform (uint32_t state[4], unsigned char block[64])
|
||||
{
|
||||
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < 64; i++, j += 4)
|
||||
x[i] = ((uint32_t)block[j]) | (((uint32_t)block[j+1]) << 8) |
|
||||
(((uint32_t)block[j+2]) << 16) | (((uint32_t)block[j+3]) << 24);
|
||||
|
||||
/* Round 1 */
|
||||
Libisofs_md5_FF (a, b, c, d, x[ 0], Libisofs_md5_S11, 0xd76aa478); /* 1 */
|
||||
Libisofs_md5_FF (d, a, b, c, x[ 1], Libisofs_md5_S12, 0xe8c7b756); /* 2 */
|
||||
Libisofs_md5_FF (c, d, a, b, x[ 2], Libisofs_md5_S13, 0x242070db); /* 3 */
|
||||
Libisofs_md5_FF (b, c, d, a, x[ 3], Libisofs_md5_S14, 0xc1bdceee); /* 4 */
|
||||
Libisofs_md5_FF (a, b, c, d, x[ 4], Libisofs_md5_S11, 0xf57c0faf); /* 5 */
|
||||
Libisofs_md5_FF (d, a, b, c, x[ 5], Libisofs_md5_S12, 0x4787c62a); /* 6 */
|
||||
Libisofs_md5_FF (c, d, a, b, x[ 6], Libisofs_md5_S13, 0xa8304613); /* 7 */
|
||||
Libisofs_md5_FF (b, c, d, a, x[ 7], Libisofs_md5_S14, 0xfd469501); /* 8 */
|
||||
Libisofs_md5_FF (a, b, c, d, x[ 8], Libisofs_md5_S11, 0x698098d8); /* 9 */
|
||||
Libisofs_md5_FF (d, a, b, c, x[ 9], Libisofs_md5_S12, 0x8b44f7af); /* 10 */
|
||||
Libisofs_md5_FF (c, d, a, b, x[10], Libisofs_md5_S13, 0xffff5bb1); /* 11 */
|
||||
Libisofs_md5_FF (b, c, d, a, x[11], Libisofs_md5_S14, 0x895cd7be); /* 12 */
|
||||
Libisofs_md5_FF (a, b, c, d, x[12], Libisofs_md5_S11, 0x6b901122); /* 13 */
|
||||
Libisofs_md5_FF (d, a, b, c, x[13], Libisofs_md5_S12, 0xfd987193); /* 14 */
|
||||
Libisofs_md5_FF (c, d, a, b, x[14], Libisofs_md5_S13, 0xa679438e); /* 15 */
|
||||
Libisofs_md5_FF (b, c, d, a, x[15], Libisofs_md5_S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
Libisofs_md5_GG (a, b, c, d, x[ 1], Libisofs_md5_S21, 0xf61e2562); /* 17 */
|
||||
Libisofs_md5_GG (d, a, b, c, x[ 6], Libisofs_md5_S22, 0xc040b340); /* 18 */
|
||||
Libisofs_md5_GG (c, d, a, b, x[11], Libisofs_md5_S23, 0x265e5a51); /* 19 */
|
||||
Libisofs_md5_GG (b, c, d, a, x[ 0], Libisofs_md5_S24, 0xe9b6c7aa); /* 20 */
|
||||
Libisofs_md5_GG (a, b, c, d, x[ 5], Libisofs_md5_S21, 0xd62f105d); /* 21 */
|
||||
Libisofs_md5_GG (d, a, b, c, x[10], Libisofs_md5_S22, 0x2441453); /* 22 */
|
||||
Libisofs_md5_GG (c, d, a, b, x[15], Libisofs_md5_S23, 0xd8a1e681); /* 23 */
|
||||
Libisofs_md5_GG (b, c, d, a, x[ 4], Libisofs_md5_S24, 0xe7d3fbc8); /* 24 */
|
||||
Libisofs_md5_GG (a, b, c, d, x[ 9], Libisofs_md5_S21, 0x21e1cde6); /* 25 */
|
||||
Libisofs_md5_GG (d, a, b, c, x[14], Libisofs_md5_S22, 0xc33707d6); /* 26 */
|
||||
Libisofs_md5_GG (c, d, a, b, x[ 3], Libisofs_md5_S23, 0xf4d50d87); /* 27 */
|
||||
Libisofs_md5_GG (b, c, d, a, x[ 8], Libisofs_md5_S24, 0x455a14ed); /* 28 */
|
||||
Libisofs_md5_GG (a, b, c, d, x[13], Libisofs_md5_S21, 0xa9e3e905); /* 29 */
|
||||
Libisofs_md5_GG (d, a, b, c, x[ 2], Libisofs_md5_S22, 0xfcefa3f8); /* 30 */
|
||||
Libisofs_md5_GG (c, d, a, b, x[ 7], Libisofs_md5_S23, 0x676f02d9); /* 31 */
|
||||
Libisofs_md5_GG (b, c, d, a, x[12], Libisofs_md5_S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
Libisofs_md5_HH (a, b, c, d, x[ 5], Libisofs_md5_S31, 0xfffa3942); /* 33 */
|
||||
Libisofs_md5_HH (d, a, b, c, x[ 8], Libisofs_md5_S32, 0x8771f681); /* 34 */
|
||||
Libisofs_md5_HH (c, d, a, b, x[11], Libisofs_md5_S33, 0x6d9d6122); /* 35 */
|
||||
Libisofs_md5_HH (b, c, d, a, x[14], Libisofs_md5_S34, 0xfde5380c); /* 36 */
|
||||
Libisofs_md5_HH (a, b, c, d, x[ 1], Libisofs_md5_S31, 0xa4beea44); /* 37 */
|
||||
Libisofs_md5_HH (d, a, b, c, x[ 4], Libisofs_md5_S32, 0x4bdecfa9); /* 38 */
|
||||
Libisofs_md5_HH (c, d, a, b, x[ 7], Libisofs_md5_S33, 0xf6bb4b60); /* 39 */
|
||||
Libisofs_md5_HH (b, c, d, a, x[10], Libisofs_md5_S34, 0xbebfbc70); /* 40 */
|
||||
Libisofs_md5_HH (a, b, c, d, x[13], Libisofs_md5_S31, 0x289b7ec6); /* 41 */
|
||||
Libisofs_md5_HH (d, a, b, c, x[ 0], Libisofs_md5_S32, 0xeaa127fa); /* 42 */
|
||||
Libisofs_md5_HH (c, d, a, b, x[ 3], Libisofs_md5_S33, 0xd4ef3085); /* 43 */
|
||||
Libisofs_md5_HH (b, c, d, a, x[ 6], Libisofs_md5_S34, 0x4881d05); /* 44 */
|
||||
Libisofs_md5_HH (a, b, c, d, x[ 9], Libisofs_md5_S31, 0xd9d4d039); /* 45 */
|
||||
Libisofs_md5_HH (d, a, b, c, x[12], Libisofs_md5_S32, 0xe6db99e5); /* 46 */
|
||||
Libisofs_md5_HH (c, d, a, b, x[15], Libisofs_md5_S33, 0x1fa27cf8); /* 47 */
|
||||
Libisofs_md5_HH (b, c, d, a, x[ 2], Libisofs_md5_S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
Libisofs_md5_II (a, b, c, d, x[ 0], Libisofs_md5_S41, 0xf4292244); /* 49 */
|
||||
Libisofs_md5_II (d, a, b, c, x[ 7], Libisofs_md5_S42, 0x432aff97); /* 50 */
|
||||
Libisofs_md5_II (c, d, a, b, x[14], Libisofs_md5_S43, 0xab9423a7); /* 51 */
|
||||
Libisofs_md5_II (b, c, d, a, x[ 5], Libisofs_md5_S44, 0xfc93a039); /* 52 */
|
||||
Libisofs_md5_II (a, b, c, d, x[12], Libisofs_md5_S41, 0x655b59c3); /* 53 */
|
||||
Libisofs_md5_II (d, a, b, c, x[ 3], Libisofs_md5_S42, 0x8f0ccc92); /* 54 */
|
||||
Libisofs_md5_II (c, d, a, b, x[10], Libisofs_md5_S43, 0xffeff47d); /* 55 */
|
||||
Libisofs_md5_II (b, c, d, a, x[ 1], Libisofs_md5_S44, 0x85845dd1); /* 56 */
|
||||
Libisofs_md5_II (a, b, c, d, x[ 8], Libisofs_md5_S41, 0x6fa87e4f); /* 57 */
|
||||
Libisofs_md5_II (d, a, b, c, x[15], Libisofs_md5_S42, 0xfe2ce6e0); /* 58 */
|
||||
Libisofs_md5_II (c, d, a, b, x[ 6], Libisofs_md5_S43, 0xa3014314); /* 59 */
|
||||
Libisofs_md5_II (b, c, d, a, x[13], Libisofs_md5_S44, 0x4e0811a1); /* 60 */
|
||||
Libisofs_md5_II (a, b, c, d, x[ 4], Libisofs_md5_S41, 0xf7537e82); /* 61 */
|
||||
Libisofs_md5_II (d, a, b, c, x[11], Libisofs_md5_S42, 0xbd3af235); /* 62 */
|
||||
Libisofs_md5_II (c, d, a, b, x[ 2], Libisofs_md5_S43, 0x2ad7d2bb); /* 63 */
|
||||
Libisofs_md5_II (b, c, d, a, x[ 9], Libisofs_md5_S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information. */
|
||||
memset ((char *) x, 0, sizeof (x));
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static int md5__encode(unsigned char *output, uint32_t *input,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int md5_init(libisofs_md5_ctx *ctx, int flag)
|
||||
{
|
||||
ctx->count[0] = ctx->count[1] = 0;
|
||||
/* Load magic initialization constants. */
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xefcdab89;
|
||||
ctx->state[2] = 0x98badcfe;
|
||||
ctx->state[3] = 0x10325476;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* MD5 block update operation. Continues an MD5 message-digest
|
||||
operation, processing another message block, and updating the
|
||||
context.
|
||||
*/
|
||||
static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data,
|
||||
int datalen, int flag)
|
||||
{
|
||||
unsigned int i, index, partlen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((ctx->count[0] >> 3) & 0x3F);
|
||||
/* Update number of bits */
|
||||
if ((ctx->count[0] += ((uint32_t) datalen << 3)) <
|
||||
((uint32_t) datalen << 3))
|
||||
ctx->count[1]++;
|
||||
ctx->count[1] += ((uint32_t) datalen >> 29);
|
||||
partlen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible. */
|
||||
if (datalen >= partlen) {
|
||||
memcpy((char *) &ctx->buffer[index], (char *) data, partlen);
|
||||
md5__transform(ctx->state, ctx->buffer);
|
||||
for (i = partlen; i + 63 < datalen; i += 64)
|
||||
md5__transform(ctx->state, &data[i]);
|
||||
index = 0;
|
||||
} else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining data */
|
||||
memcpy((char *) &ctx->buffer[index], (char *) &data[i],datalen-i);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static int md5_final(libisofs_md5_ctx *ctx, char result[16], int flag)
|
||||
{
|
||||
unsigned char bits[8], *respt;
|
||||
unsigned int index, padlen;
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* Save number of bits */
|
||||
md5__encode(bits, ctx->count, 8);
|
||||
/* Pad out to 56 mod 64. */
|
||||
index = (unsigned int)((ctx->count[0] >> 3) & 0x3f);
|
||||
padlen = (index < 56) ? (56 - index) : (120 - index);
|
||||
md5_update(ctx, PADDING, padlen,0);
|
||||
/* Append length (before padding) */
|
||||
md5_update(ctx, bits, 8,0);
|
||||
/* Store state in result */
|
||||
respt= (unsigned char *) result;
|
||||
md5__encode(respt, ctx->state, 16);
|
||||
/* Zeroize sensitive information. */
|
||||
memset ((char *) ctx, 0, sizeof (*ctx));
|
||||
return(1);
|
||||
}
|
||||
|
||||
/** Compute a MD5 checksum from one or more calls of this function.
|
||||
The first call has to be made with flag bit0 == 1. It may already submit
|
||||
processing payload in data and datalen.
|
||||
The last call has to be made with bit15 set. Normally bit1 will be set
|
||||
too in order to receive the checksum before it gets disposed.
|
||||
bit1 may only be set in the last call or together with bit2.
|
||||
The combination of bit1 and bit2 may be used to get an intermediate
|
||||
result without hampering an ongoing checksum computation.
|
||||
|
||||
@param ctx the checksum context which stores the state between calls.
|
||||
It gets created with flag bit0 and disposed with bit15.
|
||||
With flag bit0, *ctx has to be NULL or point to freeable
|
||||
memory.
|
||||
@param data the bytes to be checksummed
|
||||
@param datalen the number of bytes in data
|
||||
@param result returns the 16 bytes of checksum if called with bit1 set
|
||||
@param flag bit0= allocate and init *ctx
|
||||
bit1= transfer ctx to result
|
||||
bit2= with bit 0 : clone new *ctx from data
|
||||
bit15= free *ctx
|
||||
*/
|
||||
static
|
||||
int libisofs_md5(void **ctx_in, char *data, int datalen,
|
||||
char result[16], int flag)
|
||||
/* *ctx has to be NULL or point to freeable memory */
|
||||
/*
|
||||
bit0= allocate and init *ctx
|
||||
bit1= transfer ctx to result
|
||||
bit2= with bit 0 : clone new *ctx from data
|
||||
bit15= free *ctx
|
||||
*/
|
||||
{
|
||||
unsigned char *datapt;
|
||||
libisofs_md5_ctx **ctx;
|
||||
|
||||
ctx= (libisofs_md5_ctx **) ctx_in;
|
||||
if(flag&1) {
|
||||
if(*ctx!=NULL)
|
||||
free((char *) *ctx);
|
||||
*ctx= calloc(1, sizeof(libisofs_md5_ctx));
|
||||
if(*ctx==NULL)
|
||||
return(-1);
|
||||
md5_init(*ctx,0);
|
||||
if(flag&4)
|
||||
memcpy((char *) *ctx,data,sizeof(libisofs_md5_ctx));
|
||||
}
|
||||
if(*ctx==NULL)
|
||||
return(0);
|
||||
if(datalen>0) {
|
||||
datapt= (unsigned char *) data;
|
||||
md5_update(*ctx, datapt, datalen, 0);
|
||||
}
|
||||
if(flag&2)
|
||||
md5_final(*ctx, result, 0);
|
||||
if(flag&(1<<15)) {
|
||||
free((char *) *ctx);
|
||||
*ctx= NULL;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/* Public MD5 computing facility */
|
||||
|
||||
/* API */
|
||||
int iso_md5_start(void **md5_context)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libisofs_md5(md5_context, NULL, 0, NULL, 1);
|
||||
if (ret <= 0)
|
||||
return ISO_OUT_OF_MEM;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_md5_compute(void *md5_context, char *data, int datalen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libisofs_md5(&md5_context, data, datalen, NULL, 0);
|
||||
if (ret <= 0)
|
||||
return ISO_NULL_POINTER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_md5_clone(void *old_md5_context, void **new_md5_context)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libisofs_md5(new_md5_context, old_md5_context, 0, NULL, 1 | 4);
|
||||
if (ret < 0)
|
||||
return ISO_OUT_OF_MEM;
|
||||
if (ret == 0)
|
||||
return ISO_NULL_POINTER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_md5_end(void **md5_context, char result[16])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libisofs_md5(md5_context, NULL, 0, result, 2 | (1 << 15));
|
||||
if (ret <= 0)
|
||||
return ISO_NULL_POINTER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_md5_match(char first_md5[16], char second_md5[16])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i= 0; i < 16; i++)
|
||||
if (first_md5[i] != second_md5[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* Function to identify and manage md5sum indice of the old image.
|
||||
* data is supposed to be a 4 byte integer, bit 31 shall be 0,
|
||||
* value 0 of this integer means that it is not a valid index.
|
||||
*/
|
||||
int checksum_cx_xinfo_func(void *data, int flag)
|
||||
{
|
||||
/* data is an int disguised as pointer. It does not point to memory. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Function to identify and manage md5 sums of unspecified providence stored
|
||||
* directly in this xinfo.
|
||||
*/
|
||||
int checksum_md5_xinfo_func(void *data, int flag)
|
||||
{
|
||||
if (data == NULL)
|
||||
return 1;
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/* MD5 checksum image writer */
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/*
|
||||
@flag bit0= recursion
|
||||
bit1= session will be appended to an existing image
|
||||
*/
|
||||
static
|
||||
int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
|
||||
{
|
||||
IsoNode *pos;
|
||||
IsoFile *file;
|
||||
IsoImage *img;
|
||||
int ret, i;
|
||||
size_t value_length;
|
||||
unsigned int idx = 0, old_idx = 0;
|
||||
char *value = NULL, *md5_pt = NULL;
|
||||
void *xipt;
|
||||
|
||||
img = target->image;
|
||||
if (target->checksum_buffer == NULL)
|
||||
return 0;
|
||||
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file = (IsoFile *) node;
|
||||
if (file->from_old_session && target->appendable) {
|
||||
/* Look for checksums at various places */
|
||||
|
||||
/* Try checksum directly stored with node */
|
||||
if (md5_pt == NULL) {
|
||||
ret = iso_node_get_xinfo(node, checksum_md5_xinfo_func, &xipt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 1)
|
||||
md5_pt = (char *) xipt;
|
||||
}
|
||||
|
||||
/* Try checksum index to image checksum buffer */
|
||||
if (md5_pt == NULL && img->checksum_array != NULL) {
|
||||
ret = iso_node_get_xinfo(node, checksum_cx_xinfo_func, &xipt);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
/* xipt is an int disguised as void pointer */
|
||||
old_idx = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
old_idx = (old_idx << 8) | ((unsigned char *) &xipt)[i];
|
||||
|
||||
if (old_idx == 0 || old_idx > img->checksum_idx_count - 1)
|
||||
return 0;
|
||||
md5_pt = img->checksum_array + 16 * old_idx;
|
||||
}
|
||||
|
||||
if (md5_pt == NULL)
|
||||
return 0;
|
||||
|
||||
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
|
||||
&value, 0);
|
||||
if (ret == 1 && value_length == 4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||
if (idx > 0 && idx <= target->checksum_idx_counter) {
|
||||
memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
|
||||
}
|
||||
}
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
iso_node_remove_xinfo(node, checksum_md5_xinfo_func);
|
||||
iso_node_remove_xinfo(node, checksum_cx_xinfo_func);
|
||||
}
|
||||
} else if (node->type == LIBISO_DIR) {
|
||||
for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
|
||||
ret = checksum_copy_old_nodes(target, pos, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
||||
static
|
||||
int checksum_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
size_t size;
|
||||
Ecma119Image *t;
|
||||
int ret;
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
t = writer->target;
|
||||
|
||||
t->checksum_array_pos = t->curblock;
|
||||
/* (t->curblock already contains t->ms_block) */
|
||||
t->checksum_range_start = t->ms_block;
|
||||
size = (t->checksum_idx_counter + 2) / 128;
|
||||
if (size * 128 < t->checksum_idx_counter + 2)
|
||||
size++;
|
||||
t->curblock += size;
|
||||
t->checksum_range_size = t->checksum_array_pos + size
|
||||
- t->checksum_range_start;
|
||||
|
||||
/* Extra block for stream detectable checksum tag */
|
||||
t->checksum_tag_pos = t->curblock;
|
||||
t->curblock++;
|
||||
|
||||
/* Allocate array of MD5 sums */
|
||||
t->checksum_buffer = calloc(size, 2048);
|
||||
if (t->checksum_buffer == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
/* Copy MD5 from nodes of old image into writer->data */
|
||||
ret = checksum_copy_old_nodes(t, (IsoNode *) t->image->root, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Record lba,count,size,cecksum_type in "isofs.ca" of root node */
|
||||
ret = iso_root_set_isofsca((IsoNode *) t->image->root,
|
||||
t->checksum_range_start,
|
||||
t->checksum_array_pos,
|
||||
t->checksum_idx_counter + 2, 16, "MD5", 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int checksum_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
{
|
||||
|
||||
/* The superblock checksum tag has to be written after
|
||||
the Volume Descriptor Set Terminator and thus may not be
|
||||
written by this function. (It would have been neat, though).
|
||||
*/
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int checksum_writer_write_data(IsoImageWriter *writer)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
int wres, res;
|
||||
size_t i, size;
|
||||
Ecma119Image *t;
|
||||
void *ctx = NULL;
|
||||
char md5[16];
|
||||
|
||||
#ifdef NIX
|
||||
char tag_block[2048];
|
||||
int l;
|
||||
#endif
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
|
||||
t = writer->target;
|
||||
iso_msg_debug(t->image->id, "Writing Checksums...");
|
||||
|
||||
/* Write image checksum to index 0 */
|
||||
if (t->checksum_ctx != NULL) {
|
||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (res > 0) {
|
||||
res = iso_md5_end(&ctx, t->image_md5);
|
||||
if (res > 0)
|
||||
memcpy(t->checksum_buffer + 0 * 16, t->image_md5, 16);
|
||||
}
|
||||
}
|
||||
|
||||
size = (t->checksum_idx_counter + 2) / 128;
|
||||
if (size * 128 < t->checksum_idx_counter + 2)
|
||||
size++;
|
||||
|
||||
/* Write checksum of checksum array as index t->checksum_idx_counter + 1 */
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res > 0) {
|
||||
for (i = 0; i < t->checksum_idx_counter + 1; i++)
|
||||
iso_md5_compute(ctx,
|
||||
t->checksum_buffer + ((size_t) i) * (size_t) 16, 16);
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
if (res > 0)
|
||||
memcpy(t->checksum_buffer + (t->checksum_idx_counter + 1) * 16,
|
||||
md5, 16);
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
wres = iso_write(t, t->checksum_buffer + ((size_t) 2048) * i, 2048);
|
||||
if (wres < 0) {
|
||||
res = wres;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
if (t->checksum_ctx == NULL) {
|
||||
res = ISO_SUCCESS;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* Write stream detectable checksum tag to extra block */;
|
||||
res = iso_md5_write_tag(t, 1);
|
||||
if (res < 0)
|
||||
goto ex;
|
||||
|
||||
res = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return(res);
|
||||
|
||||
#else /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
|
||||
#endif /* ! Libisofs_with_checksumS */
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int checksum_writer_free_data(IsoImageWriter *writer)
|
||||
{
|
||||
/* nothing was allocated at writer->data */
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int checksum_writer_create(Ecma119Image *target)
|
||||
{
|
||||
IsoImageWriter *writer;
|
||||
|
||||
writer = malloc(sizeof(IsoImageWriter));
|
||||
if (writer == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
writer->compute_data_blocks = checksum_writer_compute_data_blocks;
|
||||
writer->write_vol_desc = checksum_writer_write_vol_desc;
|
||||
writer->write_data = checksum_writer_write_data;
|
||||
writer->free_data = checksum_writer_free_data;
|
||||
writer->data = NULL;
|
||||
writer->target = target;
|
||||
|
||||
/* add this writer to image */
|
||||
target->writers[target->nwriters++] = writer;
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
/* Account for superblock checksum tag */
|
||||
if (target->md5_session_checksum) {
|
||||
target->checksum_sb_tag_pos = target->curblock;
|
||||
target->curblock++;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
void *ctx = NULL;
|
||||
off_t pos = 0, line_start;
|
||||
int record_len, block_len, res, i;
|
||||
char postext[40], md5[16], record[160];
|
||||
|
||||
line_start = strlen(tag_block);
|
||||
iso_md5_compute(t->checksum_ctx, tag_block, line_start);
|
||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (res < 0)
|
||||
goto ex;
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
|
||||
pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
|
||||
if(pos >= 1000000000)
|
||||
sprintf(postext, "%u%9.9u", (unsigned int) (pos / 1000000000),
|
||||
(unsigned int) (pos % 1000000000));
|
||||
else
|
||||
sprintf(postext, "%u", (unsigned int) pos);
|
||||
sprintf(record, "%s %s ", t->scdbackup_tag_parm, postext);
|
||||
record_len = strlen(record);
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(record + record_len + 2 * i,
|
||||
"%2.2x", ((unsigned char *) md5)[i]);
|
||||
record_len += 32;
|
||||
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res < 0)
|
||||
goto ex;
|
||||
iso_md5_compute(ctx, record, record_len);
|
||||
iso_md5_end(&ctx, md5);
|
||||
|
||||
sprintf(tag_block + line_start, "scdbackup_checksum_tag_v0.1 %s %d %s ",
|
||||
postext, record_len, record);
|
||||
block_len = strlen(tag_block);
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(tag_block + block_len + 2 * i,
|
||||
"%2.2x", ((unsigned char *) md5)[i]);
|
||||
block_len+= 32;
|
||||
tag_block[block_len++]= '\n';
|
||||
|
||||
if (t->scdbackup_tag_written != NULL)
|
||||
strncpy(t->scdbackup_tag_written, tag_block + line_start,
|
||||
block_len - line_start);
|
||||
res = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return res;
|
||||
|
||||
#else
|
||||
|
||||
return ISO_SUCCESS;
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
}
|
||||
|
||||
|
||||
/* Write stream detectable checksum tag to extra block.
|
||||
* @flag bit0-7= tag type
|
||||
* 1= session tag (End checksumming.)
|
||||
* 2= superblock tag (System Area and Volume Descriptors)
|
||||
* 3= tree tag (ECMA-119 and Rock Ridge tree)
|
||||
* 4= relocated superblock tag (at LBA 0 of overwriteable media)
|
||||
* Write to target->opts_overwrite rather than to iso_write().
|
||||
*/
|
||||
int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
int res, mode, l, i, wres, tag_id_len;
|
||||
void *ctx = NULL;
|
||||
char md5[16], tag_block[2048], *tag_id;
|
||||
uint32_t size = 0, pos = 0, start;
|
||||
|
||||
start = t->checksum_range_start;
|
||||
memset(tag_block, 0, 2048);
|
||||
mode = flag & 255;
|
||||
if (mode < 1 || mode > 4)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
if (mode == 1) {
|
||||
size = t->checksum_range_size;
|
||||
pos = t->checksum_tag_pos;
|
||||
} else {
|
||||
if (mode == 2) {
|
||||
pos = t->checksum_sb_tag_pos;
|
||||
} else if (mode == 3) {
|
||||
pos = t->checksum_tree_tag_pos;
|
||||
} else if (mode == 4) {
|
||||
pos = t->checksum_rlsb_tag_pos;
|
||||
start = pos - (pos % 32);
|
||||
}
|
||||
size = pos - start;
|
||||
}
|
||||
if (res < 0)
|
||||
goto ex;
|
||||
|
||||
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
|
||||
sprintf(tag_block, "%s pos=%u range_start=%u range_size=%u",
|
||||
tag_id, pos, start, size);
|
||||
|
||||
l = strlen(tag_block);
|
||||
if (mode == 2) {
|
||||
sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos);
|
||||
} else if (mode == 3) {
|
||||
sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
|
||||
} else if (mode == 4) {
|
||||
sprintf(tag_block + l, " session_start=%u", t->ms_block);
|
||||
}
|
||||
strcat(tag_block + l, " md5=");
|
||||
l = strlen(tag_block);
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(tag_block + l + 2 * i, "%2.2x",
|
||||
((unsigned char *) md5)[i]);
|
||||
l+= 32;
|
||||
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res > 0) {
|
||||
iso_md5_compute(ctx, tag_block, l);
|
||||
iso_md5_end(&ctx, md5);
|
||||
strcpy(tag_block + l, " self=");
|
||||
l += 6;
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(tag_block + l + 2 * i, "%2.2x",
|
||||
((unsigned char *) md5)[i]);
|
||||
}
|
||||
tag_block[l + 32] = '\n';
|
||||
|
||||
if (mode == 1 && t->scdbackup_tag_parm[0]) {
|
||||
if (t->ms_block > 0) {
|
||||
iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
|
||||
} else {
|
||||
res = iso_md5_write_scdbackup_tag(t, tag_block, 0);
|
||||
if (res < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == 4) {
|
||||
if (t->opts_overwrite != NULL)
|
||||
memcpy(t->opts_overwrite + pos * 2048, tag_block, 2048);
|
||||
} else {
|
||||
wres = iso_write(t, tag_block, 2048);
|
||||
if (wres < 0) {
|
||||
res = wres;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
res = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return res;
|
||||
|
||||
#else /* Libisofs_with_checksumS */
|
||||
|
||||
return ISO_SUCCESS;
|
||||
|
||||
#endif /* ! Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
|
40
libisofs/md5.h
Normal file
40
libisofs/md5.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*/
|
||||
|
||||
#ifndef LIBISO_MD5_H_
|
||||
#define LIBISO_MD5_H_
|
||||
|
||||
|
||||
/* The MD5 computation API is in libisofs.h : iso_md5_start() et.al. */
|
||||
|
||||
|
||||
/** Create a writer object for checksums and add it to the writer list of
|
||||
the given Ecma119Image.
|
||||
*/
|
||||
int checksum_writer_create(Ecma119Image *target);
|
||||
|
||||
|
||||
/* Write stream detectable checksum tag to extra block.
|
||||
* All tag ranges start at the beginning of the System Area (i.e. t->ms_block)
|
||||
* and stem from the same MD5 computation context. Tag types 2 and 3 are
|
||||
* intermediate checksums. Type 2 announces the existence of type 3.
|
||||
* If both match, then at least the directory tree is trustworthy.
|
||||
* Type 1 is written at the very end of the session. If it matches, then
|
||||
* the whole image is trustworthy.
|
||||
* @param t The image being written
|
||||
* @flag bit0-7= tag type
|
||||
* 1= session tag (End checksumming.)
|
||||
* 2= superblock tag (System Area and Volume Descriptors)
|
||||
* 3= tree tag (ECMA-119 and Rock Ridge tree)
|
||||
*/
|
||||
int iso_md5_write_tag(Ecma119Image *t, int flag);
|
||||
|
||||
|
||||
#endif /* ! LIBISO_MD5_H_ */
|
||||
|
||||
|
@ -65,12 +65,9 @@ struct libiso_msgs *libiso_msgr = NULL;
|
||||
int iso_init_with_flag(int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_setlocale_in_iniT
|
||||
if (! (flag & 1)) {
|
||||
iso_init_locale(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (libiso_msgr == NULL) {
|
||||
if (libiso_msgs_new(&libiso_msgr, 0) <= 0)
|
||||
return ISO_FATAL_ERROR;
|
||||
@ -263,11 +260,35 @@ const char *iso_error_to_msg(int errcode)
|
||||
return "Cannot set global zisofs parameters while filters exist";
|
||||
case ISO_ZLIB_EARLY_EOF:
|
||||
return "Premature EOF of zlib input stream";
|
||||
case ISO_MD5_AREA_CORRUPTED:
|
||||
return "Checksum area or checksum tag appear corrupted";
|
||||
case ISO_MD5_TAG_MISMATCH:
|
||||
return "Checksum mismatch between checksum tag and data blocks";
|
||||
case ISO_SB_TREE_CORRUPTED:
|
||||
return "Checksum mismatch in System Area, Volume Descriptors, or directory tree";
|
||||
case ISO_MD5_TAG_UNEXPECTED:
|
||||
return "Unexpected checksum tag type encountered";
|
||||
case ISO_MD5_TAG_MISPLACED:
|
||||
return "Misplaced checksum tag type encountered";
|
||||
case ISO_MD5_TAG_OTHER_RANGE:
|
||||
return "Checksum tag with unexpected address range encountered";
|
||||
case ISO_MD5_STREAM_CHANGE:
|
||||
return "Detected file content changes while it was written into the image";
|
||||
case ISO_SCDBACKUP_TAG_NOT_0:
|
||||
return "Session does not start at LBA 0. scdbackup checksum tag not written.";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
int iso_msg_is_abort(int errcode)
|
||||
{
|
||||
if (ISO_ERR_SEV(errcode) >= abort_threshold)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
|
||||
{
|
||||
char msg[MAX_MSG_LEN];
|
||||
@ -298,7 +319,7 @@ int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
if (ISO_ERR_SEV(errcode) >= abort_threshold) {
|
||||
if (iso_msg_is_abort(errcode)) {
|
||||
return ISO_CANCELED;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -24,6 +24,13 @@ extern int iso_message_id;
|
||||
*/
|
||||
void iso_msg_debug(int imgid, const char *fmt, ...);
|
||||
|
||||
|
||||
/**
|
||||
* Inquire whether the given error code triggers the abort threshold
|
||||
*/
|
||||
int iso_msg_is_abort(int errcode);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param errcode
|
||||
@ -33,7 +40,7 @@ void iso_msg_debug(int imgid, const char *fmt, ...);
|
||||
* < 0 will be returned in any case. Use 0 if there is no previous
|
||||
* cause for the error.
|
||||
* @return
|
||||
* 1 on success, < 0 if function must abort asap.
|
||||
* 0 on success, < 0 if function must abort asap.
|
||||
*/
|
||||
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...);
|
||||
|
||||
|
502
libisofs/node.c
502
libisofs/node.c
@ -8,10 +8,12 @@
|
||||
*/
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "image.h"
|
||||
#include "node.h"
|
||||
#include "stream.h"
|
||||
#include "aaip_0_2.h"
|
||||
#include "messages.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -1308,6 +1310,9 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link)
|
||||
new->node.name = name;
|
||||
new->dest = dest;
|
||||
new->node.mode = S_IFLNK;
|
||||
new->fs_id = 0;
|
||||
new->st_dev = 0;
|
||||
new->st_ino = 0;
|
||||
*link = new;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -1339,7 +1344,9 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
|
||||
new->node.mode = mode;
|
||||
new->dev = dev;
|
||||
|
||||
new->fs_id = 0;
|
||||
new->st_dev = 0;
|
||||
new->st_ino = 0;
|
||||
*special = new;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -2239,3 +2246,496 @@ int iso_node_zf_by_magic(IsoNode *node, int flag)
|
||||
return total_ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_px_ino_xinfo_func(void *data, int flag)
|
||||
{
|
||||
if (flag == 1) {
|
||||
free(data);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= do only retrieve id if node is in imported ISO image
|
||||
* or has an explicit xinfo inode number
|
||||
* @return
|
||||
* 1= reply is valid from stream, 2= reply is valid from xinfo
|
||||
* 0= no id available, <0= error
|
||||
* (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0
|
||||
*/
|
||||
int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id,
|
||||
ino_t *ino_id, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoFile *file;
|
||||
IsoSymlink *symlink;
|
||||
IsoSpecial *special;
|
||||
void *xipt;
|
||||
|
||||
ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt);
|
||||
if (ret < 0)
|
||||
goto no_id;
|
||||
if (ret == 1) {
|
||||
*fs_id = ISO_IMAGE_FS_ID;
|
||||
*dev_id = 0;
|
||||
*ino_id = *((ino_t *) xipt);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file= (IsoFile *) node;
|
||||
iso_stream_get_id(file->stream, fs_id, dev_id, ino_id);
|
||||
if (*fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
|
||||
ret = 0;
|
||||
goto no_id;
|
||||
}
|
||||
return 1;
|
||||
|
||||
} else if (node->type == LIBISO_SYMLINK) {
|
||||
symlink = (IsoSymlink *) node;
|
||||
if (symlink->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
|
||||
ret = 0;
|
||||
goto no_id;
|
||||
}
|
||||
*fs_id = symlink->fs_id;
|
||||
*dev_id = symlink->st_dev;
|
||||
*ino_id = symlink->st_ino;
|
||||
return 1;
|
||||
|
||||
} else if (node->type == LIBISO_SPECIAL) {
|
||||
special = (IsoSpecial *) node;
|
||||
if (special->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
|
||||
ret = 0;
|
||||
goto no_id;
|
||||
}
|
||||
*fs_id = special->fs_id;
|
||||
*dev_id = special->st_dev;
|
||||
*ino_id = special->st_ino;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
no_id:;
|
||||
*fs_id = 0;
|
||||
*dev_id = 0;
|
||||
*ino_id = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
|
||||
{
|
||||
int ret;
|
||||
void *xipt;
|
||||
|
||||
if (flag & 1) {
|
||||
ret = iso_node_remove_xinfo(node, iso_px_ino_xinfo_func);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
xipt = calloc(1, sizeof(ino_t));
|
||||
if (xipt == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(xipt, &ino, sizeof(ino_t));
|
||||
ret = iso_node_add_xinfo(node, iso_px_ino_xinfo_func, xipt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoFile *file;
|
||||
IsoSymlink *symlink;
|
||||
IsoSpecial *special;
|
||||
void *xipt;
|
||||
|
||||
ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 1) {
|
||||
ret = iso_node_set_ino_xinfo(node, ino, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 2;
|
||||
}
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file= (IsoFile *) node;
|
||||
ret = iso_stream_set_image_ino(file->stream, ino, 0);
|
||||
if (ret < 0 || ret == 1)
|
||||
return ret;
|
||||
|
||||
} else if (node->type == LIBISO_SYMLINK) {
|
||||
symlink = (IsoSymlink *) node;
|
||||
if (symlink->fs_id == ISO_IMAGE_FS_ID) {
|
||||
symlink->st_ino = ino;
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else if (node->type == LIBISO_SPECIAL) {
|
||||
special = (IsoSpecial *) node;
|
||||
if (special->fs_id == ISO_IMAGE_FS_ID) {
|
||||
special->st_ino = ino;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
ret = iso_node_set_ino_xinfo(node, ino, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t ino;
|
||||
|
||||
ino = img_give_ino_number(image, 0);
|
||||
ret = iso_node_set_ino(node, ino, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note to programmers: It is crucial not to break the following constraints.
|
||||
* Anti-symmetry: cmp(X,Y) == - cmp(Y,X)
|
||||
* Transitivity : if cmp(A,B) < 0 && cmp(B,C) < 0 then cmp(A,C) < 0
|
||||
* if cmp(A,B) == 0 && cmp(B,C) == 0 then cmp(A,C) == 0
|
||||
* A big transitivity hazard are tests which do not apply to some nodes.
|
||||
* In this case for any A that is applicable and any B that is not applicable
|
||||
* the comparison must have the same non-zero result. I.e. a pair of applicable
|
||||
* and non-applicable node must return that non-zero result before the test
|
||||
* for a pair of applicable nodes would happen.
|
||||
*
|
||||
* @param flag
|
||||
* bit0= compare stat properties and attributes
|
||||
* bit1= treat all nodes with image ino == 0 as unique
|
||||
*/
|
||||
int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag)
|
||||
{
|
||||
int ret1, ret2;
|
||||
unsigned int fs_id1, fs_id2;
|
||||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
IsoFile *f1 = NULL, *f2 = NULL;
|
||||
IsoSymlink *l1 = NULL, *l2 = NULL;
|
||||
IsoSpecial *s1 = NULL, *s2 = NULL;
|
||||
void *x1, *x2;
|
||||
|
||||
if (n1 == n2)
|
||||
return 0;
|
||||
if (n1->type != n2->type)
|
||||
return (n1->type < n2->type ? -1 : 1);
|
||||
|
||||
/* Imported or explicite ISO image node id has priority */
|
||||
ret1 = (iso_node_get_id(n1, &fs_id1, &dev_id1, &ino_id1, 1) > 0);
|
||||
ret2 = (iso_node_get_id(n2, &fs_id2, &dev_id2, &ino_id2, 1) > 0);
|
||||
if (ret1 != ret2)
|
||||
return (ret1 < ret2 ? -1 : 1);
|
||||
if (ret1) {
|
||||
/* fs_id and dev_id do not matter here.
|
||||
Both nodes have explicit inode numbers of the emerging image.
|
||||
*/
|
||||
if (ino_id1 != ino_id2)
|
||||
return (ino_id1 < ino_id2 ? -1 : 1);
|
||||
if (ino_id1 == 0) /* Image ino 0 is always unique */
|
||||
return (n1 < n2 ? -1 : 1);
|
||||
goto image_inode_match;
|
||||
}
|
||||
|
||||
if (n1->type == LIBISO_FILE) {
|
||||
|
||||
f1 = (IsoFile *) n1;
|
||||
f2 = (IsoFile *) n2;
|
||||
ret1 = iso_stream_cmp_ino(f1->stream, f2->stream, 0);
|
||||
if (ret1)
|
||||
return ret1;
|
||||
goto inode_match;
|
||||
|
||||
} else if (n1->type == LIBISO_SYMLINK) {
|
||||
|
||||
l1 = (IsoSymlink *) n1;
|
||||
l2 = (IsoSymlink *) n2;
|
||||
fs_id1 = l1->fs_id;
|
||||
dev_id1 = l1->st_dev;
|
||||
ino_id1 = l1->st_ino;
|
||||
fs_id2 = l2->fs_id;
|
||||
dev_id2 = l2->st_dev;
|
||||
ino_id2 = l2->st_ino;
|
||||
|
||||
} else if (n1->type == LIBISO_SPECIAL) {
|
||||
|
||||
s1 = (IsoSpecial *) n1;
|
||||
s2 = (IsoSpecial *) n2;
|
||||
fs_id1 = s1->fs_id;
|
||||
dev_id1 = s1->st_dev;
|
||||
ino_id1 = s1->st_ino;
|
||||
fs_id2 = s2->fs_id;
|
||||
dev_id2 = s2->st_dev;
|
||||
ino_id2 = s2->st_ino;
|
||||
|
||||
} else {
|
||||
return (n1 < n2 ? -1 : 1); /* case n1 == n2 is handled above */
|
||||
}
|
||||
if (fs_id1 != fs_id2)
|
||||
return (fs_id1 < fs_id2 ? -1 : 1);
|
||||
if (dev_id1 != dev_id2)
|
||||
return (dev_id1 < dev_id2 ? -1 : 1);
|
||||
if (ino_id1 != ino_id2)
|
||||
return (ino_id1 < ino_id2 ? -1 : 1);
|
||||
if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0)
|
||||
return (n1 < n2 ? -1 : 1);
|
||||
|
||||
inode_match:;
|
||||
|
||||
if (flag & 2) {
|
||||
/* What comes here has no predefined image ino resp. image_ino == 0 .
|
||||
Regard this as not equal.
|
||||
*/
|
||||
return (n1 < n2 ? -1 : 1);
|
||||
}
|
||||
|
||||
image_inode_match:;
|
||||
|
||||
if (!(flag & 1))
|
||||
return 0;
|
||||
if (n1->type == LIBISO_SYMLINK) {
|
||||
l1 = (IsoSymlink *) n1;
|
||||
l2 = (IsoSymlink *) n2;
|
||||
ret1 = strcmp(l1->dest, l2->dest);
|
||||
if (ret1)
|
||||
return ret1;
|
||||
} else if (n1->type == LIBISO_SPECIAL) {
|
||||
s1 = (IsoSpecial *) n1;
|
||||
s2 = (IsoSpecial *) n2;
|
||||
if (s1->dev != s2->dev)
|
||||
return (s1->dev < s2->dev ? -1 : 1);
|
||||
}
|
||||
|
||||
if (n1->mode != n2->mode)
|
||||
return (n1->mode < n2->mode ? -1 : 1);
|
||||
if (n1->uid != n2->uid)
|
||||
return (n1->uid < n2->uid ? -1 : 1);
|
||||
if (n1->gid != n2->gid)
|
||||
return (n1->gid < n2->gid ? -1 : 1);
|
||||
if (n1->atime != n2->atime)
|
||||
return (n1->atime < n2->atime ? -1 : 1);
|
||||
if (n1->mtime != n2->mtime)
|
||||
return (n1->mtime < n2->mtime ? -1 : 1);
|
||||
if (n1->ctime != n2->ctime)
|
||||
return (n1->ctime < n2->ctime ? -1 : 1);
|
||||
|
||||
/* Compare xinfo */
|
||||
/* :( cannot compare general xinfo because data length is not known :( */
|
||||
|
||||
/* compare aa_string */
|
||||
ret1 = iso_node_get_xinfo(n1, aaip_xinfo_func, &x1);
|
||||
ret2 = iso_node_get_xinfo(n2, aaip_xinfo_func, &x2);
|
||||
if (ret1 != ret2)
|
||||
return (ret1 < ret2 ? -1 : 1);
|
||||
if (ret1 == 1) {
|
||||
ret1 = aaip_count_bytes((unsigned char *) x1, 0);
|
||||
ret2 = aaip_count_bytes((unsigned char *) x2, 0);
|
||||
if (ret1 != ret2)
|
||||
return (ret1 < ret2 ? -1 : 1);
|
||||
ret1 = memcmp(x1, x2, ret1);
|
||||
if (ret1)
|
||||
return ret1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag)
|
||||
{
|
||||
return iso_node_cmp_flag(n1, n2, 1);
|
||||
}
|
||||
|
||||
|
||||
int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
|
||||
int flag)
|
||||
{
|
||||
static char *names = "isofs.cx";
|
||||
static size_t value_lengths[1] = {4};
|
||||
unsigned char value[4];
|
||||
char *valuept;
|
||||
int i, ret;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
value[3 - i] = (checksum_index >> (8 * i)) & 0xff;
|
||||
valuept= (char *) value;
|
||||
ret = iso_node_set_attrs((IsoNode *) file, (size_t) 1,
|
||||
&names, value_lengths, &valuept, 2 | 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba,
|
||||
uint32_t count, uint32_t size, char *typetext,
|
||||
int flag)
|
||||
{
|
||||
char buffer[5 + 5 + 5 + 2 + 81], *wpt = buffer, *valuept = buffer;
|
||||
int result_len, ret;
|
||||
static char *names = "isofs.ca";
|
||||
static size_t value_lengths[1];
|
||||
|
||||
/* Set value of isofs.ca with
|
||||
4 byte START, 4 byte END, 4 byte COUNT, SIZE = 16, MD5 */
|
||||
iso_util_encode_len_bytes(start_lba, wpt, 4, &result_len, 0);
|
||||
wpt += result_len;
|
||||
iso_util_encode_len_bytes(end_lba, wpt, 4, &result_len, 0);
|
||||
wpt += result_len;
|
||||
iso_util_encode_len_bytes(count, wpt, 4, &result_len, 0);
|
||||
wpt += result_len;
|
||||
iso_util_encode_len_bytes(size, wpt, 1, &result_len, 0);
|
||||
wpt += result_len;
|
||||
strncpy(wpt, typetext, 80);
|
||||
if (strlen(typetext) > 80)
|
||||
wpt += 80;
|
||||
else
|
||||
wpt += strlen(typetext);
|
||||
value_lengths[0] = wpt - buffer;
|
||||
ret = iso_node_set_attrs(node, (size_t) 1,
|
||||
&names, value_lengths, &valuept, 2 | 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
|
||||
uint32_t *count, uint32_t *size, char typetext[81],
|
||||
int flag)
|
||||
{
|
||||
int ret, len;
|
||||
size_t value_len;
|
||||
char *value = NULL, *rpt;
|
||||
|
||||
ret = iso_node_lookup_attr(node, "isofs.ca", &value_len, &value, 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
|
||||
/* Parse value of isofs.ca with
|
||||
4 byte START, 4 byte END, 4 byte COUNT, SIZE = 16, MD5 */
|
||||
rpt = value;
|
||||
iso_util_decode_len_bytes(start_lba, rpt, &len,
|
||||
value_len - (rpt - value), 0);
|
||||
rpt += len + 1;
|
||||
iso_util_decode_len_bytes(end_lba, rpt, &len,
|
||||
value_len - (rpt - value), 0);
|
||||
rpt += len + 1;
|
||||
iso_util_decode_len_bytes(count, rpt, &len,
|
||||
value_len - (rpt - value), 0);
|
||||
rpt += len + 1;
|
||||
iso_util_decode_len_bytes(size, rpt, &len,
|
||||
value_len - (rpt - value), 0);
|
||||
rpt += len + 1;
|
||||
len = value_len - (rpt - value);
|
||||
if (len > 80)
|
||||
len = 80;
|
||||
memcpy(typetext, rpt, len);
|
||||
typetext[len] = 0;
|
||||
|
||||
ret= ISO_SUCCESS;
|
||||
ex:;
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
int ret, i;
|
||||
size_t value_len;
|
||||
char *value = NULL;
|
||||
uint32_t idx = 0;
|
||||
void *xipt;
|
||||
|
||||
/* xinfo MD5 overrides everything else */
|
||||
ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func, &xipt);
|
||||
if (ret == 1) {
|
||||
memcpy(md5, (char *) xipt, 16);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (image->checksum_array == NULL)
|
||||
return 0;
|
||||
ret = iso_node_lookup_attr((IsoNode *) file, "isofs.cx",
|
||||
&value_len, &value, 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
if (value_len > 4) {
|
||||
ret = 0;
|
||||
goto ex;
|
||||
}
|
||||
for (i = 0; i < value_len; i++)
|
||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||
if (idx == 0 || idx > image->checksum_idx_count - 1) {
|
||||
/* (last index is not MD5 of a file) */
|
||||
ret = 0;
|
||||
goto ex;
|
||||
}
|
||||
if (!(flag & 1)) {
|
||||
memcpy(md5, image->checksum_array + ((size_t) 16) * ((size_t) idx),
|
||||
16);
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
return ret;
|
||||
|
||||
#else
|
||||
|
||||
return 0;
|
||||
|
||||
#endif /* ! Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_file_make_md5(IsoFile *file, int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
int ret, dig = 0;
|
||||
char *md5 = NULL;
|
||||
|
||||
if (file->from_old_session)
|
||||
dig = 1;
|
||||
md5= calloc(16, 1);
|
||||
ret = iso_stream_make_md5(file->stream, md5, dig);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
iso_node_remove_xinfo((IsoNode *) file, checksum_md5_xinfo_func);
|
||||
ret = iso_node_add_xinfo((IsoNode *) file, checksum_md5_xinfo_func, md5);
|
||||
if (ret == 0)
|
||||
ret = ISO_ERROR; /* should not happen after iso_node_remove_xinfo() */
|
||||
if (ret < 0) {
|
||||
free(md5);
|
||||
goto ex;
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
return ret;
|
||||
|
||||
#else
|
||||
|
||||
return ISO_ERROR;
|
||||
|
||||
#endif /* ! Libisofs_with_checksumS */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -23,7 +24,7 @@
|
||||
/**
|
||||
* The extended information is a way to attach additional information to each
|
||||
* IsoNode. External applications may want to use this extension system to
|
||||
* store application speficic information related to each node. On the other
|
||||
* store application specific information related to each node. On the other
|
||||
* side, libisofs may make use of this struct to attach information to nodes in
|
||||
* some particular, uncommon, cases, without incrementing the size of the
|
||||
* IsoNode struct.
|
||||
@ -66,7 +67,7 @@ struct iso_extended_info {
|
||||
struct Iso_Node
|
||||
{
|
||||
/*
|
||||
* Initilized to 1, originally owned by user, until added to another node.
|
||||
* Initialized to 1, originally owned by user, until added to another node.
|
||||
* Then it is owned by the parent node, so the user must take his own ref
|
||||
* if needed. With the exception of the creation functions, none of the
|
||||
* other libisofs functions that return an IsoNode increment its
|
||||
@ -122,7 +123,7 @@ struct Iso_File
|
||||
* Higher weighting files are written at the beginning of image
|
||||
*/
|
||||
int sort_weight;
|
||||
IsoStream *stream;
|
||||
IsoStream *stream; /* Knows fs_id, st_dev, and st_ino */
|
||||
};
|
||||
|
||||
struct Iso_Symlink
|
||||
@ -130,12 +131,28 @@ struct Iso_Symlink
|
||||
IsoNode node;
|
||||
|
||||
char *dest;
|
||||
|
||||
/* If the IsoNode represents an object in an existing filesystem then
|
||||
the following three numbers should unique identify it.
|
||||
(0,0,0) will always be taken as unique.
|
||||
*/
|
||||
unsigned int fs_id;
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
};
|
||||
|
||||
struct Iso_Special
|
||||
{
|
||||
IsoNode node;
|
||||
dev_t dev;
|
||||
|
||||
/* If the IsoNode represents an object in an existing filesystem then
|
||||
the following three numbers should unique identify it.
|
||||
(0,0,0) will always be taken as unique.
|
||||
*/
|
||||
unsigned int fs_id;
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
};
|
||||
|
||||
struct iso_dir_iter_iface
|
||||
@ -398,5 +415,61 @@ struct zisofs_zf_info {
|
||||
*/
|
||||
int iso_file_zf_by_magic(IsoFile *file, int flag);
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= do only retrieve id if node is in imported ISO image
|
||||
* or has an explicit xinfo inode number
|
||||
* @return
|
||||
* 1= reply is valid from stream, 2= reply is valid from xinfo
|
||||
* 0= no id available, <0= error
|
||||
* (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0
|
||||
*/
|
||||
int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id,
|
||||
ino_t *ino_id, int flag);
|
||||
|
||||
/* Set a new unique inode ISO image number to the given node.
|
||||
* This number shall eventually persist during image generation.
|
||||
*/
|
||||
int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag);
|
||||
|
||||
/* Use this with extreme care. Duplicate inode numbers will indicate hardlink
|
||||
* relationship between the nodes.
|
||||
*/
|
||||
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag);
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= compare stat properties and attributes
|
||||
* bit1= treat all nodes with image ino == 0 as unique
|
||||
* (those with 0,0,0 are treated as unique anyway)
|
||||
*/
|
||||
int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Set the checksum index (typically comming from IsoFileSrc.checksum_index)
|
||||
* of a regular file node. The index is encoded as xattr "isofs.cx" with
|
||||
* four bytes of value.
|
||||
*/
|
||||
int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
|
||||
int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Set the checksum area description. node should be the root node.
|
||||
* It is encoded as xattr "isofs.ca".
|
||||
*/
|
||||
int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba,
|
||||
uint32_t count, uint32_t size, char *typetext,
|
||||
int flag);
|
||||
|
||||
/**
|
||||
* Get the checksum area description. node should be the root node.
|
||||
* It is encoded as xattr "isofs.ca".
|
||||
*/
|
||||
int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
|
||||
uint32_t *count, uint32_t *size, char typetext[81],
|
||||
int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_NODE_H_*/
|
||||
|
@ -102,7 +102,7 @@ int rrip_add_PX(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
||||
|
||||
PX[0] = 'P';
|
||||
PX[1] = 'X';
|
||||
if (!t->rrip_version_1_10) {
|
||||
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10 ) {
|
||||
PX[2] = 44;
|
||||
} else {
|
||||
PX[2] = 36;
|
||||
@ -112,7 +112,7 @@ int rrip_add_PX(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
||||
iso_bb(&PX[12], n->nlink, 4);
|
||||
iso_bb(&PX[20], px_get_uid(t, n), 4);
|
||||
iso_bb(&PX[28], px_get_gid(t, n), 4);
|
||||
if (!t->rrip_version_1_10) {
|
||||
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
|
||||
iso_bb(&PX[36], n->ino, 4);
|
||||
}
|
||||
|
||||
@ -662,9 +662,6 @@ int aaip_add_ER(Ecma119Image *t, struct susp_info *susp, int flag)
|
||||
ER[5] = 81;
|
||||
ER[6] = 62;
|
||||
ER[7] = 1;
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
|
||||
memcpy(ER + 8, "AAIP_0200", 9);
|
||||
memcpy(ER + 17,
|
||||
"AL PROVIDES VIA AAIP 2.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
|
||||
@ -673,18 +670,6 @@ int aaip_add_ER(Ecma119Image *t, struct susp_info *susp, int flag)
|
||||
"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG",
|
||||
62);
|
||||
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
|
||||
memcpy(ER + 8, "AAIP_0100", 9);
|
||||
memcpy(ER + 17,
|
||||
"AA PROVIDES VIA AAIP 1.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
|
||||
" IN ISO 9660 IMAGES", 81);
|
||||
memcpy(ER + 98,
|
||||
"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG",
|
||||
62);
|
||||
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
/** This always goes to continuation area */
|
||||
return susp_append_ce(t, susp, ER);
|
||||
}
|
||||
@ -1144,7 +1129,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
#endif
|
||||
|
||||
/* PX and TF, we are sure they always fit in SUA */
|
||||
if (!t->rrip_version_1_10) {
|
||||
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
|
||||
su_size += 44 + 26;
|
||||
} else {
|
||||
su_size += 36 + 26;
|
||||
@ -1249,12 +1234,16 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
|
||||
if (ret == 1) {
|
||||
num_aapt = aaip_count_bytes((unsigned char *) xipt, 0);
|
||||
if (num_aapt > 0) {
|
||||
aapt = malloc(num_aapt);
|
||||
if (aapt == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(aapt, xipt, num_aapt);
|
||||
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
|
||||
flag & 1);
|
||||
if (flag & 1) {
|
||||
ret = aaip_add_AL(t, NULL,NULL, num_aapt, sua_free, ce_len, 1);
|
||||
} else {
|
||||
aapt = malloc(num_aapt);
|
||||
if (aapt == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(aapt, xipt, num_aapt);
|
||||
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
|
||||
0);
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* aapt is NULL now and the memory is owned by t */
|
||||
|
@ -263,7 +263,9 @@ void susp_iter_free(SuspIterator *iter);
|
||||
* Fills a struct stat with the values of a Rock Ridge PX entry (RRIP, 4.1.1).
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
* < 0 on error
|
||||
* 1 on success with no inode number,
|
||||
* 2 on success with inode number,
|
||||
*/
|
||||
int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st);
|
||||
|
||||
|
@ -169,11 +169,14 @@ int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st)
|
||||
st->st_nlink = iso_read_bb(px->data.PX.links, 4, NULL);
|
||||
st->st_uid = iso_read_bb(px->data.PX.uid, 4, NULL);
|
||||
st->st_gid = iso_read_bb(px->data.PX.gid, 4, NULL);
|
||||
st->st_ino = 0;
|
||||
if (px->len_sue[0] == 44) {
|
||||
/* this corresponds to RRIP 1.12, so we have inode serial number */
|
||||
st->st_ino = iso_read_bb(px->data.PX.serial, 4, NULL);
|
||||
/* Indicate that st_ino is valid */
|
||||
return 2;
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,7 +302,7 @@ int read_rr_NM(struct susp_sys_user_entry *nm, char **name, int *cont)
|
||||
*name = realloc(*name, strlen(*name) + nm->len_sue[0] - 5 + 1);
|
||||
strncat(*name, (char*)nm->data.NM.name, nm->len_sue[0] - 5);
|
||||
} else {
|
||||
*name = strcopy((char*)nm->data.NM.name, nm->len_sue[0] - 5);
|
||||
*name = iso_util_strcopy((char*)nm->data.NM.name, nm->len_sue[0] - 5);
|
||||
}
|
||||
if (*name == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -377,7 +380,7 @@ int read_rr_SL(struct susp_sys_user_entry *sl, char **dest, int *cont)
|
||||
/* we don't have to add the '/' */
|
||||
strncat(*dest, comp, len);
|
||||
} else {
|
||||
*dest = strcopy(comp, len);
|
||||
*dest = iso_util_strcopy(comp, len);
|
||||
}
|
||||
if (*dest == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -492,26 +495,14 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
|
||||
aapt = *aa_string + *aa_len;
|
||||
|
||||
aapt[0] = 'A';
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
aapt[1] = 'L';
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
aapt[1] = 'A';
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
aapt[2] = sue->len_sue[0];
|
||||
aapt[3] = 1;
|
||||
aapt[4] = 0;
|
||||
/* Append sue payload */
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
/* Append sue payload */
|
||||
memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AL.flags[0] & 1);
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
memcpy(aapt + 5, sue->data.AA.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AA.flags[0] & 1);
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
*aa_len += sue->len_sue[0];
|
||||
|
||||
return ISO_SUCCESS;
|
||||
@ -554,26 +545,14 @@ int read_aaip_AL(struct susp_sys_user_entry *sue,
|
||||
aapt = *aa_string + *aa_len;
|
||||
|
||||
aapt[0] = 'A';
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
aapt[1] = 'L';
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
aapt[1] = 'A';
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
aapt[2] = sue->len_sue[0];
|
||||
aapt[3] = 1;
|
||||
aapt[4] = 0;
|
||||
/* Append sue payload */
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
/* Append sue payload */
|
||||
memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AL.flags[0] & 1);
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
memcpy(aapt + 5, sue->data.AA.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AA.flags[0] & 1);
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
*aa_len += sue->len_sue[0];
|
||||
|
||||
return ISO_SUCCESS;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -672,8 +673,12 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
||||
|
||||
IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag)
|
||||
{
|
||||
IsoStreamIface* class = stream->class;
|
||||
IsoStreamIface* class;
|
||||
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
class = stream->class;
|
||||
if (class->version < 2)
|
||||
return NULL;
|
||||
return class->get_input_stream(stream, 0);
|
||||
@ -709,3 +714,208 @@ ex:;
|
||||
return path;
|
||||
}
|
||||
|
||||
/* @return 1 = ok , 0 = not an ISO image stream , <0 = error */
|
||||
int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (stream->class == &fsrc_stream_class) {
|
||||
FSrcStreamData *fsrc_data = stream->data;
|
||||
fsrc_data->ino_id = ino;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
|
||||
{
|
||||
int ret;
|
||||
unsigned int fs_id1, fs_id2;
|
||||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
off_t size1, size2;
|
||||
FSrcStreamData *fssd1, *fssd2;
|
||||
|
||||
|
||||
/*
|
||||
#define Libisofs_stream_cmp_ino_debuG 1
|
||||
*/
|
||||
#ifdef Libisofs_stream_cmp_ino_debuG
|
||||
static int report_counter = 0;
|
||||
static int debug = 1;
|
||||
#endif /* Libisofs_stream_cmp_ino_debuG */
|
||||
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
if (s1 == NULL)
|
||||
return -1;
|
||||
if (s2 == NULL)
|
||||
return 1;
|
||||
|
||||
if (s1->class->version >= 3 && !(flag & 1)) {
|
||||
/* Filters may have smarter methods to compare themselves with others */
|
||||
ret = s1->class->cmp_ino(s1, s2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
iso_stream_get_id(s1, &fs_id1, &dev_id1, &ino_id1);
|
||||
iso_stream_get_id(s2, &fs_id2, &dev_id2, &ino_id2);
|
||||
if (fs_id1 < fs_id2) {
|
||||
return -1;
|
||||
} else if (fs_id1 > fs_id2) {
|
||||
return 1;
|
||||
}
|
||||
/* files belong to the same fs */
|
||||
if (dev_id1 > dev_id2) {
|
||||
return -1;
|
||||
} else if (dev_id1 < dev_id2) {
|
||||
return 1;
|
||||
} else if (ino_id1 < ino_id2) {
|
||||
return -1;
|
||||
} else if (ino_id1 > ino_id2) {
|
||||
return 1;
|
||||
}
|
||||
size1 = iso_stream_get_size(s1);
|
||||
size2 = iso_stream_get_size(s2);
|
||||
if (size1 < size2) {
|
||||
|
||||
#ifdef Libisofs_stream_cmp_ino_debuG
|
||||
if (debug) {
|
||||
if (report_counter < 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Program error: same ino but differing size\n\n\n");
|
||||
else if (report_counter == 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Inode error: more of same ino but differing size\n\n\n");
|
||||
report_counter++;
|
||||
}
|
||||
#endif /* Libisofs_stream_cmp_ino_debuG */
|
||||
|
||||
return -1;
|
||||
} else if (size1 > size2) {
|
||||
|
||||
#ifdef Libisofs_stream_cmp_ino_debuG
|
||||
if (debug) {
|
||||
if (report_counter < 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Inode error: same ino but differing size\n\n\n");
|
||||
else if (report_counter == 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Program error: more of same ino but differing size\n\n\n");
|
||||
report_counter++;
|
||||
}
|
||||
#endif /* Libisofs_stream_cmp_ino_debuG */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s1->class != s2->class)
|
||||
return (s1->class < s2->class ? -1 : 1);
|
||||
if (s1->class == &fsrc_stream_class) {
|
||||
/* Compare eventual image data section LBA and sizes */
|
||||
fssd1= (FSrcStreamData *) s1->data;
|
||||
fssd2= (FSrcStreamData *) s2->data;
|
||||
ret = iso_ifs_sections_cmp(fssd1->src, fssd2->src, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) {
|
||||
return (s1 < s2 ? -1 : 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
* 1 ok, 0 EOF, < 0 error
|
||||
*/
|
||||
int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
|
||||
size_t *got)
|
||||
{
|
||||
ssize_t result;
|
||||
|
||||
*got = 0;
|
||||
do {
|
||||
result = iso_stream_read(stream, buf + *got, count - *got);
|
||||
if (result < 0) {
|
||||
memset(buf + *got, 0, count - *got);
|
||||
return result;
|
||||
}
|
||||
if (result == 0)
|
||||
break;
|
||||
*got += result;
|
||||
} while (*got < count);
|
||||
|
||||
if (*got < count) {
|
||||
/* eof */
|
||||
memset(buf + *got, 0, count - *got);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
|
||||
/* @param flag bit0= dig out most original stream (e.g. because from old image)
|
||||
@return 1=ok, md5 is valid,
|
||||
0= not ok,
|
||||
<0 fatal error, abort
|
||||
*/
|
||||
int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
|
||||
{
|
||||
int res, is_open = 0;
|
||||
char buffer[2048];
|
||||
void *ctx= NULL;
|
||||
off_t file_size;
|
||||
uint32_t b, nblocks;
|
||||
size_t got_bytes;
|
||||
IsoStream *input_stream;
|
||||
|
||||
if (flag & 1) {
|
||||
while(1) {
|
||||
input_stream = iso_stream_get_input_stream(stream, 0);
|
||||
if (input_stream == NULL)
|
||||
break;
|
||||
stream = input_stream;
|
||||
}
|
||||
}
|
||||
|
||||
if (! iso_stream_is_repeatable(stream))
|
||||
return 0;
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = iso_stream_open(stream);
|
||||
if (res < 0)
|
||||
return 0;
|
||||
is_open = 1;
|
||||
file_size = iso_stream_get_size(stream);
|
||||
nblocks = DIV_UP(file_size, 2048);
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
res = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
|
||||
if (res < 0) {
|
||||
res = 0;
|
||||
goto ex;
|
||||
}
|
||||
/* Do not use got_bytes to stay closer to IsoFileSrc processing */
|
||||
if (file_size - b * 2048 > 2048)
|
||||
res = 2048;
|
||||
else
|
||||
res = file_size - b * 2048;
|
||||
iso_md5_compute(ctx, buffer, res);
|
||||
}
|
||||
res = 1;
|
||||
ex:;
|
||||
if (is_open)
|
||||
iso_stream_close(stream);
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -74,4 +75,32 @@ int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4,
|
||||
int *block_size_log2, uint32_t *uncompressed_size,
|
||||
int flag);
|
||||
|
||||
/**
|
||||
* Set the inode number of a stream that is based on FSrcStreamData, i.e.
|
||||
* stems from the imported ISO image.
|
||||
* @return 1 = ok , 0 = not an ISO image stream , <0 = error
|
||||
*/
|
||||
int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Read the full required amount of data unless error or EOF occurs.
|
||||
* Fill missing bytes by 0s.
|
||||
* @param count Required amount
|
||||
* @param got Returns number of actually read bytes
|
||||
* @return
|
||||
* 1 no problem encountered, 0 EOF encountered, < 0 error
|
||||
*/
|
||||
int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
|
||||
size_t *got);
|
||||
|
||||
/**
|
||||
* @return 1=ok, md5 is valid,
|
||||
* 0= not ok
|
||||
* <0 fatal error, abort
|
||||
*/
|
||||
int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag);
|
||||
|
||||
|
||||
|
||||
#endif /*STREAM_H_*/
|
||||
|
440
libisofs/util.c
440
libisofs/util.c
@ -9,6 +9,7 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "libisofs.h"
|
||||
#include "messages.h"
|
||||
#include "../version.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -32,9 +33,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
|
||||
|
||||
/* Produce possibly inflationary error messages directly to stderr */
|
||||
static int iso_iconv_debug = 0;
|
||||
|
||||
@ -78,6 +76,15 @@ size_t iso_iconv(struct iso_iconv_handle *handle,
|
||||
char **outbuf, size_t *outbytesleft, int flag)
|
||||
{
|
||||
size_t ret;
|
||||
/* The build system might indicate iconv(,const char **inbuf,) by
|
||||
defining ICONV_CONST const
|
||||
*/
|
||||
#ifndef ICONV_CONST
|
||||
#define ICONV_CONST
|
||||
#endif
|
||||
ICONV_CONST char **local_inbuf;
|
||||
|
||||
local_inbuf = (ICONV_CONST char **) inbuf;
|
||||
|
||||
if (!(handle->status & 1)) {
|
||||
if (iso_iconv_debug)
|
||||
@ -104,7 +111,7 @@ null_buf:;
|
||||
return (size_t) -1;
|
||||
return (size_t) 0;
|
||||
}
|
||||
ret = iconv(handle->descr, inbuf, inbytesleft, outbuf, outbytesleft);
|
||||
ret = iconv(handle->descr, local_inbuf, inbytesleft, outbuf, outbytesleft);
|
||||
if (ret == (size_t) -1) {
|
||||
if (iso_iconv_debug)
|
||||
fprintf(stderr, "libisofs_DEBUG: iconv() failed: errno= %d %s\n",
|
||||
@ -141,8 +148,6 @@ int iso_iconv_close(struct iso_iconv_handle *handle, int flag)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_iso_iconV */
|
||||
|
||||
|
||||
int int_pow(int base, int power)
|
||||
{
|
||||
@ -183,13 +188,8 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t n;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
char *out = NULL;
|
||||
char *src;
|
||||
@ -204,43 +204,22 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
*ret = '\0';
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
if (*output == NULL) {
|
||||
@ -261,14 +240,8 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t n;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
char *out = NULL;
|
||||
char *src;
|
||||
char *ret;
|
||||
@ -281,43 +254,22 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
retval = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
*ret = '\0';
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
if (*output == NULL) {
|
||||
@ -342,13 +294,8 @@ ex:;
|
||||
static
|
||||
int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* That while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
@ -364,15 +311,8 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "WCHAR_T", (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("WCHAR_T", icharset);
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
@ -388,13 +328,7 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
ret = (char *)wstr;
|
||||
src = (char *)input;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
|
||||
if (errno == E2BIG) {
|
||||
@ -424,34 +358,16 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
goto conv_error;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*( (wchar_t *)ret )='\0';
|
||||
*output = wstr;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
conv_error:;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
free(wstr);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
@ -463,13 +379,8 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
char *ret;
|
||||
char *ret_;
|
||||
char *src;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* That while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
@ -509,27 +420,14 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("ASCII", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
@ -563,21 +461,9 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*ret='\0';
|
||||
free(wsrc_);
|
||||
|
||||
@ -628,13 +514,8 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
char *src;
|
||||
char *ret;
|
||||
char *ret_;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* That while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
@ -670,27 +551,14 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("UCS-2BE", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
@ -724,20 +592,9 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
/* close the ucs string */
|
||||
set_ucsbe((uint16_t*) ret, '\0');
|
||||
@ -1524,21 +1381,33 @@ int iso_eaccess(const char *path)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
char *strcopy(const char *buf, size_t len)
|
||||
char *iso_util_strcopy(const char *buf, size_t len)
|
||||
{
|
||||
char *str;
|
||||
|
||||
str = malloc((len + 1) * sizeof(char));
|
||||
str = calloc(len + 1, 1);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
strncpy(str, buf, len);
|
||||
str[len] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
char *iso_util_strcopy_untail(const char *buf, size_t len)
|
||||
{
|
||||
char *str;
|
||||
|
||||
str = iso_util_strcopy(buf, len);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* remove trailing spaces */
|
||||
for (len = len-1; str[len] == ' ' && len > 0; --len)
|
||||
str[len] = '\0';
|
||||
|
||||
for (len = len-1; len >= 0; --len) {
|
||||
if (str[len] != ' ')
|
||||
break;
|
||||
str[len] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -1566,14 +1435,8 @@ char *ucs2str(const char *buf, size_t len)
|
||||
{
|
||||
size_t outbytes, inbytes;
|
||||
char *str, *src, *out = NULL, *retval = NULL;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
size_t n;
|
||||
|
||||
inbytes = len;
|
||||
@ -1584,36 +1447,15 @@ char *ucs2str(const char *buf, size_t len)
|
||||
out = calloc(outbytes, 1);
|
||||
|
||||
/* convert to local charset */
|
||||
|
||||
#ifndef Libisofs_setlocale_in_iniT
|
||||
/* ??? ts Nov 25 2008 :
|
||||
Shouldn't this go to library initialization or even to app ?
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(iso_get_local_charset(0), "UCS-2BE");
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
goto ex;
|
||||
}
|
||||
src = (char *)buf;
|
||||
str = (char *)out;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0);
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &str, &outbytes);
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
goto ex;
|
||||
@ -1660,3 +1502,229 @@ int iso_init_locale(int flag)
|
||||
}
|
||||
|
||||
|
||||
int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len,
|
||||
int *result_len, int flag)
|
||||
{
|
||||
uint32_t x;
|
||||
int i, l;
|
||||
char *wpt = buffer;
|
||||
|
||||
if (data_len <= 0) {
|
||||
x = data;
|
||||
for (i = 0; i < 4 && x != 0; i++)
|
||||
x = x >> 8;
|
||||
l = i;
|
||||
if (l == 0)
|
||||
l = 1;
|
||||
} else
|
||||
l = data_len;
|
||||
*((unsigned char *) (wpt++)) = l;
|
||||
for (i = 0; i < l; i++)
|
||||
*((unsigned char *) (wpt++)) = data >> (8 * (l - i - 1));
|
||||
*result_len = l + 1;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
|
||||
int buffer_len, int flag)
|
||||
{
|
||||
int i;
|
||||
|
||||
*data = 0;
|
||||
*data_len = ((unsigned char *) buffer)[0];
|
||||
if (*data_len > buffer_len - 1)
|
||||
*data_len = buffer_len - 1;
|
||||
for (i = 1; i <= *data_len; i++)
|
||||
*data = (*data << 8) | ((unsigned char *) buffer)[i];
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_util_dec_to_uint32(char *dec, uint32_t *value, int flag)
|
||||
{
|
||||
double num;
|
||||
|
||||
sscanf(dec, "%lf", &num);
|
||||
if (num < 0 || num > 4294967295.0)
|
||||
return 0;
|
||||
*value = num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
|
||||
int flag)
|
||||
{
|
||||
static char *allowed = {"0123456789ABCDEFabcdef"};
|
||||
char b[3];
|
||||
int i;
|
||||
unsigned int u;
|
||||
|
||||
b[2] = 0;
|
||||
*bin_count = 0;
|
||||
for (i = 0; i < bin_size; i++) {
|
||||
b[0] = hex[2 * i];
|
||||
b[1] = hex[2 * i + 1];
|
||||
if (strchr(allowed, b[0]) == NULL || strchr(allowed, b[1]) == NULL)
|
||||
break;
|
||||
sscanf(b, "%x", &u);
|
||||
((unsigned char *) bin)[i] = u;
|
||||
(*bin_count)++;
|
||||
}
|
||||
return (*bin_count > 0);
|
||||
}
|
||||
|
||||
|
||||
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag)
|
||||
{
|
||||
static char *magic[] = {"",
|
||||
"libisofs_checksum_tag_v1",
|
||||
"libisofs_sb_checksum_tag_v1",
|
||||
"libisofs_tree_checksum_tag_v1",
|
||||
"libisofs_rlsb32_checksum_tag_v1"};
|
||||
static int magic_len[]= {0, 24, 27, 29, 31};
|
||||
static int magic_max = 4;
|
||||
|
||||
*tag_magic = NULL;
|
||||
*len = 0;
|
||||
if (tag_type < 0 || tag_type > magic_max)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
*tag_magic = magic[tag_type];
|
||||
*len = magic_len[tag_type];
|
||||
return magic_max;
|
||||
}
|
||||
|
||||
|
||||
int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
|
||||
uint32_t *range_start, uint32_t *range_size,
|
||||
uint32_t *next_tag, char md5[16], int flag)
|
||||
{
|
||||
int ret, bin_count, i, mode, magic_first = 1, magic_last = 4;
|
||||
int magic_len = 0;
|
||||
char *cpt, self_md5[16], tag_md5[16], *tag_magic;
|
||||
void *ctx = NULL;
|
||||
|
||||
*next_tag = 0;
|
||||
mode = flag & 255;
|
||||
if (mode > magic_last)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
if (mode > 0)
|
||||
magic_first = magic_last = mode;
|
||||
for (i = magic_first; i <= magic_last; i++) {
|
||||
iso_util_tag_magic(i, &tag_magic, &magic_len, 0);
|
||||
if (strncmp(data, tag_magic, magic_len) == 0)
|
||||
break;
|
||||
}
|
||||
if (i > magic_last )
|
||||
return 0;
|
||||
*tag_type = i;
|
||||
cpt = data + magic_len + 1;
|
||||
if (strncmp(cpt, "pos=", 4) != 0)
|
||||
return 0;
|
||||
cpt+= 4;
|
||||
ret = iso_util_dec_to_uint32(cpt, pos, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
cpt = strstr(cpt, "range_start=");
|
||||
if (cpt == NULL)
|
||||
return(0);
|
||||
ret = iso_util_dec_to_uint32(cpt + 12, range_start, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
cpt = strstr(cpt, "range_size=");
|
||||
if (cpt == NULL)
|
||||
return(0);
|
||||
ret = iso_util_dec_to_uint32(cpt + 11, range_size, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
if (*tag_type == 2 || *tag_type == 3) {
|
||||
cpt = strstr(cpt, "next=");
|
||||
if (cpt == NULL)
|
||||
return(0);
|
||||
ret = iso_util_dec_to_uint32(cpt + 5, next_tag, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
} else if (*tag_type == 4) {
|
||||
cpt = strstr(cpt, "session_start=");
|
||||
if (cpt == NULL)
|
||||
return(0);
|
||||
ret = iso_util_dec_to_uint32(cpt + 14, next_tag, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
}
|
||||
cpt = strstr(cpt, "md5=");
|
||||
if (cpt == NULL)
|
||||
return(0);
|
||||
ret = iso_util_hex_to_bin(cpt + 4, md5, 16, &bin_count, 0);
|
||||
if (ret <= 0 || bin_count != 16)
|
||||
return 0;
|
||||
|
||||
cpt += 4 + 32;
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
iso_md5_compute(ctx, data , cpt - data);
|
||||
iso_md5_end(&ctx, tag_md5);
|
||||
cpt = strstr(cpt, "self=");
|
||||
if (cpt == NULL)
|
||||
return(0);
|
||||
ret = iso_util_hex_to_bin(cpt + 5, self_md5, 16, &bin_count, 0);
|
||||
if (ret <= 0 || bin_count != 16)
|
||||
return 0;
|
||||
for(i= 0; i < 16; i++)
|
||||
if(self_md5[i] != tag_md5[i])
|
||||
return ISO_MD5_AREA_CORRUPTED;
|
||||
if (*(cpt + 5 + 32) != '\n')
|
||||
return 0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
|
||||
void *ctx, uint32_t ctx_start_lba,
|
||||
int *tag_type, uint32_t *next_tag, int flag)
|
||||
{
|
||||
int decode_ret, ret;
|
||||
char md5[16], cloned_md5[16];
|
||||
uint32_t pos, range_start, range_size;
|
||||
void *cloned_ctx = NULL;
|
||||
|
||||
*tag_type = 0;
|
||||
decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos,
|
||||
&range_start, &range_size, next_tag, md5, 0);
|
||||
if (decode_ret != 1 && decode_ret != ISO_MD5_AREA_CORRUPTED)
|
||||
return 0;
|
||||
if (*tag_type > 30)
|
||||
goto unexpected_type;
|
||||
|
||||
if (decode_ret == ISO_MD5_AREA_CORRUPTED) {
|
||||
ret = decode_ret;
|
||||
goto ex;
|
||||
} else if (!((1 << *tag_type) & desired)) {
|
||||
unexpected_type:;
|
||||
iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL);
|
||||
ret = 0;
|
||||
goto ex;
|
||||
} else if(pos != lba) {
|
||||
ret = ISO_MD5_TAG_MISPLACED;
|
||||
goto ex;
|
||||
} else if(range_start != ctx_start_lba) {
|
||||
ret = ISO_MD5_TAG_MISPLACED;
|
||||
}
|
||||
ret = iso_md5_clone(ctx, &cloned_ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
iso_md5_end(&cloned_ctx, cloned_md5);
|
||||
if (! iso_md5_match(cloned_md5, md5)) {
|
||||
ret = ISO_MD5_TAG_MISMATCH;
|
||||
goto ex;
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (ret < 0)
|
||||
iso_msg_submit(-1, ret, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -246,11 +246,32 @@ time_t iso_datetime_read_17(const uint8_t *buf);
|
||||
*/
|
||||
int iso_eaccess(const char *path);
|
||||
|
||||
#ifdef NIX
|
||||
/* <<< Buggy and not used any more */
|
||||
|
||||
/**
|
||||
* Copy up to \p len chars from \p buf and return this newly allocated
|
||||
* string. The new string is null-terminated.
|
||||
* Note:
|
||||
* Trailing blanks will be removed. But the first one of an all blank string
|
||||
* persists. It is unclear whether this is a bug or a feature.
|
||||
*/
|
||||
char *strcopy(const char *buf, size_t len);
|
||||
|
||||
#endif /* NIX */
|
||||
|
||||
/**
|
||||
* Copy up to \p len chars from \p buf and return this newly allocated
|
||||
* string. The new string is null-terminated.
|
||||
*/
|
||||
char *strcopy(const char *buf, size_t len);
|
||||
char *iso_util_strcopy(const char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Copy up to \p len chars from \p buf and return this newly allocated
|
||||
* string. The new string is null-terminated.
|
||||
* Any trailing blanks will be removed.
|
||||
*/
|
||||
char *iso_util_strcopy_untail(const char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Copy up to \p max characters from \p src to \p dest. If \p src has less than
|
||||
@ -440,4 +461,68 @@ void iso_htable_destroy(IsoHTable *table, hfree_data_t free_data);
|
||||
*/
|
||||
unsigned int iso_str_hash(const void *key);
|
||||
|
||||
/**
|
||||
* Encode an integer as LEN,BYTES for being a component in certain AAIP
|
||||
* attribute values.
|
||||
*/
|
||||
int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len,
|
||||
int *result_len, int flag);
|
||||
|
||||
/**
|
||||
* Decode an integer as LEN,BYTES for being a component in certain AAIP
|
||||
* attribute values.
|
||||
* @param data returns the decoded value
|
||||
* @param buffer contains the encoded value
|
||||
* @param data_len returns the number of value bytes (without len byte)
|
||||
* @param buffer_len tells the number of valid buffer bytes
|
||||
*/
|
||||
int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
|
||||
int buffer_len, int flag);
|
||||
|
||||
|
||||
/* Evaluate a data block whether it is a libisofs session checksum tag of
|
||||
desired type and eventually use it to verify the MD5 checksum computed
|
||||
so far.
|
||||
@param block The data block to be evaluated
|
||||
@param desired Bit map which tells what tag types are expected
|
||||
(0 to 30)
|
||||
@param lba The address from where block was read
|
||||
@param ctx The checksum context computed so far
|
||||
@param ctx_start_lba The block address where checksum computing started
|
||||
@param tag_type Returns the tag type (0 means invalid tag type)
|
||||
@param flag Bitfield for control purposes, unused yet, submit 0
|
||||
@return 1= tag is desired and matches
|
||||
0= not a recognizable tag or a undesired tag
|
||||
<0 is error or mismatch
|
||||
*/
|
||||
int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
|
||||
void *ctx, uint32_t ctx_start_lba,
|
||||
int *tag_type, uint32_t *next_tag, int flag);
|
||||
|
||||
|
||||
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* In md5.h these function prototypes would be neighbors of (Ecma119Image *)
|
||||
which needs inclusion of ecma119.h and more. So, being generic, they ended
|
||||
up here.
|
||||
*/
|
||||
|
||||
/* Function to identify and manage md5sum indice of the old image.
|
||||
* data is supposed to be a 4 byte integer, bit 31 shall be 0,
|
||||
* value 0 of this integer means that it is not a valid index.
|
||||
*/
|
||||
int checksum_cx_xinfo_func(void *data, int flag);
|
||||
|
||||
/* Function to identify and manage md5 sums of unspecified providence stored
|
||||
* directly in this xinfo. This is supposed to override any other recorded
|
||||
* MD5 of the node unless data get copied and checksummed during that copying.
|
||||
*/
|
||||
int checksum_md5_xinfo_func(void *data, int flag);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#endif /*LIBISO_UTIL_H_*/
|
||||
|
@ -198,7 +198,11 @@ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item)
|
||||
}
|
||||
}
|
||||
|
||||
comp = tree->compare(q->data, data);
|
||||
if (q->data == data) {
|
||||
comp = 0;
|
||||
} else {
|
||||
comp = tree->compare(q->data, data);
|
||||
}
|
||||
|
||||
/* Stop if found */
|
||||
if (comp == 0) {
|
||||
|
Reference in New Issue
Block a user