Update of /cvsroot/xine/xine-lib/src/input/vcd/libvcd In directory sc8-pr-cvs1:/tmp/cvs-serv25400/src/input/vcd/libvcd Added Files: Makefile.am assert.h bitvec.h bytesex.h bytesex_asm.h data_structures.c data_structures.h dict.h directory.c directory.h files.c image.c image_bincue.c image_cdrdao.c image_nrg.c image_sink.h inf.c info.c info_private.c info_private.h logging.c mpeg.c mpeg.h mpeg_stream.c mpeg_stream.h obj.h pbc.c pbc.h salloc.c salloc.h sector.c sector_private.h stream.c stream.h stream_stdio.c stream_stdio.h util.c util.h vcd.c vcd.h vcd_read.c vcd_read.h Log Message: Add vcdx plugin(CVS) and dependent libs(no CVS, broken API). Ability to use external libs (--with-external-vcdnav), disable vcdx build and build old vcd instead (--disable-vcdx). This last feature is useful since vcdx take /hours/ to start playback, that can help people who don't want vcd navigation. Remove all .la files, even in subdirs (eg: post) --- NEW FILE: Makefile.am --- SUBDIR = libvcd LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic INCLUDES = $(LIBCDIO_CFLAGS) libvcd_SRCS = \ vcd.c \ data_structures.c \ directory.c \ files.c \ image.c \ image_bincue.c \ image_cdrdao.c \ image_nrg.c \ logging.c \ mpeg.c \ mpeg_stream.c \ pbc.c \ salloc.c \ sector.c \ stream.c \ stream_stdio.c \ util.c libvcdinfo_SRCS = \ info.c \ inf.c \ info_private.c \ vcd_read.c if ENABLE_VCDX if HAVE_VCDNAV EXTRA_DIST = $(libvcd_SRCS) $(libvcdinfo_SRCS) else noinst_LTLIBRARIES = libvcd.la libvcdinfo.la libvcd_la_SOURCES = $(libvcd_SRCS) libvcd_la_LDFLAGS = -avoid-version -module libvcd_la_LIBADD = $(LIBCDIO_LIBS) $(LIBISO9660_LIBS) libvcdinfo_la_SOURCES = $(libvcdinfo_SRCS) libvcdinfo_la_LDFLAGS = -avoid-version -module endif endif noinst_HEADERS = \ assert.h \ data_structures.h \ info_private.h \ pbc.h \ stream_stdio.h \ bitvec.h \ dict.h \ mpeg.h \ salloc.h \ util.h \ bytesex_asm.h \ directory.h \ mpeg_stream.h \ sector_private.h \ vcd.h \ bytesex.h \ image_sink.h \ obj.h \ stream.h \ vcd_read.h debug: @list='$(SUBDIRS)'; for subdir in $$list; do \ (cd $$subdir && $(MAKE) $@) || exit;\ done; @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" install-debug: debug @list='$(SUBDIRS)'; for subdir in $$list; do \ (cd $$subdir && $(MAKE) $@) || exit;\ done; @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am mostlyclean-generic: -rm -f *~ \#* .*~ .\#* maintainer-clean-generic: -@echo "This command is intended for maintainers to use;" -@echo "it deletes files that may require special tools to rebuild." -rm -f Makefile.in --- NEW FILE: assert.h --- /* $Id: assert.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VCD_ASSERT_H__ #define __VCD_ASSERT_H__ #if defined(__GNUC__) #include <libvcd/types.h> #include <libvcd/logging.h> #define vcd_assert(expr) \ { \ if (GNUC_UNLIKELY (!(expr))) vcd_log (VCD_LOG_ASSERT, \ "file %s: line %d (%s): assertion failed: (%s)", \ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ } #define vcd_assert_not_reached() \ { \ vcd_log (VCD_LOG_ASSERT, \ "file %s: line %d (%s): should not be reached", \ __FILE__, __LINE__, __PRETTY_FUNCTION__); \ } #else /* non GNU C */ #include <assert.h> #define vcd_assert(expr) \ assert(expr) #define vcd_assert_not_reached() \ assert(0) #endif #endif /* __VCD_ASSERT_H__ */ --- NEW FILE: bitvec.h --- /* $Id: bitvec.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VCD_BITVEC_H__ #define __VCD_BITVEC_H__ #include <libvcd/types.h> #include "assert.h" static inline bool _vcd_bit_set_p (const uint32_t n, const unsigned bit) { return ((n >> bit) & 0x1) == 0x1; } static inline int vcd_bitvec_align (int value, const int boundary) { if (value % boundary) value += (boundary - (value % boundary)); return value; } /* * PEEK */ #define vcd_bitvec_peek_bits16(bitvec, offset) \ vcd_bitvec_peek_bits ((bitvec), (offset), 16) static inline uint32_t vcd_bitvec_peek_bits (const uint8_t bitvec[], const unsigned offset, const unsigned bits) { uint32_t result = 0; unsigned i = offset; vcd_assert (bits > 0 && bits <= 32); #if 0 j = 0; while (j < bits) if (i % 8 || (bits - j) < 8) { result <<= 1; if (_vcd_bit_set_p (bitvec[i >> 3], 7 - (i % 8))) result |= 0x1; j++, i++; } else { result <<= 8; result |= bitvec[i >> 3]; j += 8, i += 8; } #else if (!(offset % 8) && !(bits % 8)) /* optimization */ for (i = offset; i < (offset + bits); i+= 8) { result <<= 8; result |= bitvec[i >> 3]; } else /* general case */ for (i = offset; i < (offset + bits); i++) { result <<= 1; if (_vcd_bit_set_p (bitvec[i >> 3], 7 - (i % 8))) result |= 0x1; } #endif return result; } static inline uint32_t vcd_bitvec_peek_bits32 (const uint8_t bitvec[], unsigned offset) { if (offset % 8) return vcd_bitvec_peek_bits (bitvec, offset, 32); offset >>= 3; return (bitvec[offset] << 24 | bitvec[offset + 1] << 16 | bitvec[offset + 2] << 8 | bitvec[offset + 3]); } /* * READ */ static inline uint32_t vcd_bitvec_read_bits (const uint8_t bitvec[], unsigned *offset, const unsigned bits) { const unsigned i = *offset; *offset += bits; return vcd_bitvec_peek_bits (bitvec, i, bits); } static inline bool vcd_bitvec_read_bit (const uint8_t bitvec[], unsigned *offset) { const unsigned i = (*offset)++; return _vcd_bit_set_p (bitvec[i >> 3], 7 - (i % 8)); } #endif /* __VCD_BITVEC_H__ */ --- NEW FILE: bytesex.h --- /* $Id: bytesex.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VCD_BYTESEX_H__ #define __VCD_BYTESEX_H__ #include <cdio/cdio.h> #include <libvcd/types.h> #include <libvcd/logging.h> /* Private includes */ #include "bytesex_asm.h" /* generic byteswap routines */ #define UINT16_SWAP_LE_BE_C(val) ((uint16_t) ( \ (((uint16_t) (val) & (uint16_t) 0x00ffU) << 8) | \ (((uint16_t) (val) & (uint16_t) 0xff00U) >> 8))) #define UINT32_SWAP_LE_BE_C(val) ((uint32_t) ( \ (((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \ (((uint32_t) (val) & (uint32_t) 0x0000ff00U) << 8) | \ (((uint32_t) (val) & (uint32_t) 0x00ff0000U) >> 8) | \ (((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24))) #define UINT64_SWAP_LE_BE_C(val) ((uint64_t) ( \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x00000000000000ff)) << 56) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x000000000000ff00)) << 40) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x0000000000ff0000)) << 24) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x00000000ff000000)) << 8) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x000000ff00000000)) >> 8) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x0000ff0000000000)) >> 24) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0x00ff000000000000)) >> 40) | \ (((uint64_t) (val) & (uint64_t) UINT64_C(0xff00000000000000)) >> 56))) #ifndef UINT16_SWAP_LE_BE # define UINT16_SWAP_LE_BE UINT16_SWAP_LE_BE_C #endif #ifndef UINT32_SWAP_LE_BE # define UINT32_SWAP_LE_BE UINT32_SWAP_LE_BE_C #endif #ifndef UINT64_SWAP_LE_BE # define UINT64_SWAP_LE_BE UINT64_SWAP_LE_BE_C #endif inline static uint16_t uint16_swap_le_be (const uint16_t val) { return UINT16_SWAP_LE_BE (val); } inline static uint32_t uint32_swap_le_be (const uint32_t val) { return UINT32_SWAP_LE_BE (val); } inline static uint64_t uint64_swap_le_be (const uint64_t val) { return UINT64_SWAP_LE_BE (val); } # define UINT8_TO_BE(val) ((uint8_t) (val)) # define UINT8_TO_LE(val) ((uint8_t) (val)) #ifdef WORDS_BIGENDIAN # define UINT16_TO_BE(val) ((uint16_t) (val)) # define UINT16_TO_LE(val) ((uint16_t) UINT16_SWAP_LE_BE(val)) # define UINT32_TO_BE(val) ((uint32_t) (val)) # define UINT32_TO_LE(val) ((uint32_t) UINT32_SWAP_LE_BE(val)) # define UINT64_TO_BE(val) ((uint64_t) (val)) # define UINT64_TO_LE(val) ((uint64_t) UINT64_SWAP_LE_BE(val)) #else # define UINT16_TO_BE(val) ((uint16_t) UINT16_SWAP_LE_BE(val)) # define UINT16_TO_LE(val) ((uint16_t) (val)) # define UINT32_TO_BE(val) ((uint32_t) UINT32_SWAP_LE_BE(val)) # define UINT32_TO_LE(val) ((uint32_t) (val)) # define UINT64_TO_BE(val) ((uint64_t) UINT64_SWAP_LE_BE(val)) # define UINT64_TO_LE(val) ((uint64_t) (val)) #endif /* symmetric conversions */ #define UINT8_FROM_BE(val) (UINT8_TO_BE (val)) #define UINT8_FROM_LE(val) (UINT8_TO_LE (val)) #define UINT16_FROM_BE(val) (UINT16_TO_BE (val)) #define UINT16_FROM_LE(val) (UINT16_TO_LE (val)) #define UINT32_FROM_BE(val) (UINT32_TO_BE (val)) #define UINT32_FROM_LE(val) (UINT32_TO_LE (val)) #define UINT64_FROM_BE(val) (UINT64_TO_BE (val)) #define UINT64_FROM_LE(val) (UINT64_TO_LE (val)) /* converter function template */ #define CVT_TO_FUNC(bits) \ static inline uint ## bits ## _t \ uint ## bits ## _to_be (uint ## bits ## _t val) \ { return UINT ## bits ## _TO_BE (val); } \ static inline uint ## bits ## _t \ uint ## bits ## _to_le (uint ## bits ## _t val) \ { return UINT ## bits ## _TO_LE (val); } \ CVT_TO_FUNC(8) CVT_TO_FUNC(16) CVT_TO_FUNC(32) CVT_TO_FUNC(64) #undef CVT_TO_FUNC #define uint8_from_be(val) (uint8_to_be (val)) #define uint8_from_le(val) (uint8_to_le (val)) #define uint16_from_be(val) (uint16_to_be (val)) #define uint16_from_le(val) (uint16_to_le (val)) #define uint32_from_be(val) (uint32_to_be (val)) #define uint32_from_le(val) (uint32_to_le (val)) #define uint64_from_be(val) (uint64_to_be (val)) #define uint64_from_le(val) (uint64_to_le (val)) /* ISO9660 related stuff */ #define to_711(i) uint8_to_le(i) #define from_711(i) uint8_from_le(i) #define to_721(i) uint16_to_le(i) #define from_721(i) uint16_from_le(i) #define to_721(i) uint16_to_le(i) #define from_721(i) uint16_from_le(i) #define to_722(i) uint16_to_be(i) #define from_722(i) uint16_from_be(i) static inline uint32_t to_723(uint16_t i) { return uint32_swap_le_be(i) | i; } static inline uint16_t from_723 (uint32_t p) { if (uint32_swap_le_be (p) != p) vcd_warn ("from_723: broken byte order"); return (0xFFFF & p); } #define to_731(i) uint32_to_le(i) #define from_731(i) uint32_from_le(i) #define to_732(i) uint32_to_be(i) #define from_732(i) uint32_from_be(i) static inline uint64_t to_733(uint32_t i) { return uint64_swap_le_be(i) | i; } static inline uint32_t from_733 (uint64_t p) { if (uint64_swap_le_be (p) != p) vcd_warn ("from_733: broken byte order"); return (UINT32_C(0xFFFFFFFF) & p); } #endif /* __VCD_BYTESEX_H__ */ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: bytesex_asm.h --- /* $Id: bytesex_asm.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2001 Sven Ottemann <ac-...@fr...> 2001 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VCD_BYTESEX_ASM_H__ #define __VCD_BYTESEX_ASM_H__ #if !defined(DISABLE_ASM_OPTIMIZE) #include <libvcd/types.h> #if defined(__powerpc__) && defined(__GNUC__) inline static uint32_t uint32_swap_le_be_asm(const uint32_t a) { uint32_t b; __asm__ ("lwbrx %0,0,%1" :"=r"(b) :"r"(&a), "m"(a)); return b; } inline static uint16_t uint16_swap_le_be_asm(const uint16_t a) { uint32_t b; __asm__ ("lhbrx %0,0,%1" :"=r"(b) :"r"(&a), "m"(a)); return b; } #define UINT16_SWAP_LE_BE uint16_swap_le_be_asm #define UINT32_SWAP_LE_BE uint32_swap_le_be_asm #elif defined(__mc68000__) && defined(__STORMGCC__) inline static uint32_t uint32_swap_le_be_asm(uint32_t a __asm__("d0")) { /* __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val)); */ __asm__("move.l %1,d0;rol.w #8,d0;swap d0;rol.w #8,d0;move.l d0,%0" :"=r"(a) :"r"(a)); return(a); } inline static uint16_t uint16_swap_le_be_asm(uint16_t a __asm__("d0")) { __asm__("move.l %1,d0;rol.w #8,d0;move.l d0,%0" :"=r"(a) :"r"(a)); return(a); } #define UINT16_SWAP_LE_BE uint16_swap_le_be_asm #define UINT32_SWAP_LE_BE uint32_swap_le_be_asm #elif 0 && defined(__i386__) && defined(__GNUC__) inline static uint32_t uint32_swap_le_be_asm(uint32_t a) { __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ "rorl $16,%0\n\t" /* swap words */ "xchgb %b0,%h0" /* swap higher bytes */ :"=q" (a) : "0" (a)); return(a); } inline static uint16_t uint16_swap_le_be_asm(uint16_t a) { __asm__("xchgb %b0,%h0" /* swap bytes */ : "=q" (a) : "0" (a)); return(a); } #define UINT16_SWAP_LE_BE uint16_swap_le_be_asm #define UINT32_SWAP_LE_BE uint32_swap_le_be_asm #endif #endif /* !defined(DISABLE_ASM_OPTIMIZE) */ #endif /* __VCD_BYTESEX_ASM_H__ */ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: data_structures.c --- /* $Id: data_structures.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdlib.h> #include <string.h> #include <cdio/cdio.h> /* Public headers */ #include <libvcd/types.h> /* Private headers */ #include "assert.h" #include "data_structures.h" #include "util.h" static const char _rcsid[] = "$Id: data_structures.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $"; struct _VcdList { unsigned length; VcdListNode *begin; VcdListNode *end; }; struct _VcdListNode { VcdList *list; VcdListNode *next; void *data; }; /* impl */ VcdList * _vcd_list_new (void) { VcdList *new_obj = _vcd_malloc (sizeof (VcdList)); return new_obj; } void _vcd_list_free (VcdList *list, int free_data) { while (_vcd_list_length (list)) _vcd_list_node_free (_vcd_list_begin (list), free_data); free (list); } unsigned _vcd_list_length (const VcdList *list) { vcd_assert (list != NULL); return list->length; } static bool _bubble_sort_iteration (VcdList *list, _vcd_list_cmp_func cmp_func) { VcdListNode **pnode; bool changed = false; for (pnode = &(list->begin); (*pnode) != NULL && (*pnode)->next != NULL; pnode = &((*pnode)->next)) { VcdListNode *node = *pnode; if (cmp_func (node->data, node->next->data) <= 0) continue; /* n <= n->next */ /* exch n n->next */ *pnode = node->next; node->next = node->next->next; (*pnode)->next = node; changed = true; if (node->next == NULL) list->end = node; } return changed; } void _vcd_list_sort (VcdList *list, _vcd_list_cmp_func cmp_func) { /* fixme -- this is bubble sort -- worst sorting algo... */ vcd_assert (list != NULL); vcd_assert (cmp_func != 0); while (_bubble_sort_iteration (list, cmp_func)); } void _vcd_list_prepend (VcdList *list, void *data) { VcdListNode *new_node; vcd_assert (list != NULL); new_node = _vcd_malloc (sizeof (VcdListNode)); new_node->list = list; new_node->next = list->begin; new_node->data = data; list->begin = new_node; if (list->length == 0) list->end = new_node; list->length++; } void _vcd_list_append (VcdList *list, void *data) { vcd_assert (list != NULL); if (list->length == 0) { _vcd_list_prepend (list, data); } else { VcdListNode *new_node = _vcd_malloc (sizeof (VcdListNode)); new_node->list = list; new_node->next = NULL; new_node->data = data; list->end->next = new_node; list->end = new_node; list->length++; } } void _vcd_list_foreach (VcdList *list, _vcd_list_iterfunc func, void *user_data) { VcdListNode *node; vcd_assert (list != NULL); vcd_assert (func != 0); for (node = _vcd_list_begin (list); node != NULL; node = _vcd_list_node_next (node)) func (_vcd_list_node_data (node), user_data); } VcdListNode * _vcd_list_find (VcdList *list, _vcd_list_iterfunc cmp_func, void *user_data) { VcdListNode *node; vcd_assert (list != NULL); vcd_assert (cmp_func != 0); for (node = _vcd_list_begin (list); node != NULL; node = _vcd_list_node_next (node)) if (cmp_func (_vcd_list_node_data (node), user_data)) break; return node; } /* node ops */ VcdListNode * _vcd_list_at (VcdList *list, int idx) { VcdListNode *node = _vcd_list_begin (list); if (idx < 0) return _vcd_list_at (list, _vcd_list_length (list) + idx); vcd_assert (idx >= 0); while (node && idx) { node = _vcd_list_node_next (node); idx--; } return node; } VcdListNode * _vcd_list_begin (const VcdList *list) { vcd_assert (list != NULL); return list->begin; } VcdListNode * _vcd_list_end (VcdList *list) { vcd_assert (list != NULL); return list->end; } VcdListNode * _vcd_list_node_next (VcdListNode *node) { if (node) return node->next; return NULL; } void _vcd_list_node_free (VcdListNode *node, int free_data) { VcdList *list; VcdListNode *prev_node; vcd_assert (node != NULL); list = node->list; vcd_assert (_vcd_list_length (list) > 0); if (free_data) free (_vcd_list_node_data (node)); if (_vcd_list_length (list) == 1) { vcd_assert (list->begin == list->end); list->end = list->begin = NULL; list->length = 0; free (node); return; } vcd_assert (list->begin != list->end); if (list->begin == node) { list->begin = node->next; free (node); list->length--; return; } for (prev_node = list->begin; prev_node->next; prev_node = prev_node->next) if (prev_node->next == node) break; vcd_assert (prev_node->next != NULL); if (list->end == node) list->end = prev_node; prev_node->next = node->next; list->length--; free (node); } void * _vcd_list_node_data (VcdListNode *node) { if (node) return node->data; return NULL; } /* * n-way tree based on list -- somewhat inefficent */ struct _VcdTree { VcdTreeNode *root; }; struct _VcdTreeNode { void *data; VcdListNode *listnode; VcdTree *tree; VcdTreeNode *parent; VcdList *children; }; VcdTree * _vcd_tree_new (void *root_data) { VcdTree *new_tree; new_tree = _vcd_malloc (sizeof (VcdTree)); new_tree->root = _vcd_malloc (sizeof (VcdTreeNode)); new_tree->root->data = root_data; new_tree->root->tree = new_tree; new_tree->root->parent = NULL; new_tree->root->children = NULL; new_tree->root->listnode = NULL; return new_tree; } void _vcd_tree_destroy (VcdTree *tree, bool free_data) { _vcd_tree_node_destroy (tree->root, free_data); free (tree->root); free (tree); } void _vcd_tree_node_destroy (VcdTreeNode *node, bool free_data) { VcdTreeNode *child, *nxt_child; vcd_assert (node != NULL); child = _vcd_tree_node_first_child (node); while(child) { nxt_child = _vcd_tree_node_next_sibling (child); _vcd_tree_node_destroy (child, free_data); child = nxt_child; } if (node->children) { vcd_assert (_vcd_list_length (node->children) == 0); _vcd_list_free (node->children, true); node->children = NULL; } if (free_data) free (_vcd_tree_node_set_data (node, NULL)); if (node->parent) _vcd_list_node_free (node->listnode, true); else _vcd_tree_node_set_data (node, NULL); } VcdTreeNode * _vcd_tree_root (VcdTree *tree) { return tree->root; } void * _vcd_tree_node_data (VcdTreeNode *node) { return node->data; } void * _vcd_tree_node_set_data (VcdTreeNode *node, void *new_data) { void *old_data = node->data; node->data = new_data; return old_data; } VcdTreeNode * _vcd_tree_node_append_child (VcdTreeNode *pnode, void *cdata) { VcdTreeNode *nnode; vcd_assert (pnode != NULL); if (!pnode->children) pnode->children = _vcd_list_new (); nnode = _vcd_malloc (sizeof (VcdTreeNode)); _vcd_list_append (pnode->children, nnode); nnode->data = cdata; nnode->parent = pnode; nnode->tree = pnode->tree; nnode->listnode = _vcd_list_end (pnode->children); return nnode; } VcdTreeNode * _vcd_tree_node_first_child (VcdTreeNode *node) { vcd_assert (node != NULL); if (!node->children) return NULL; return _vcd_list_node_data (_vcd_list_begin (node->children)); } VcdTreeNode * _vcd_tree_node_next_sibling (VcdTreeNode *node) { vcd_assert (node != NULL); return _vcd_list_node_data (_vcd_list_node_next (node->listnode)); } void _vcd_tree_node_sort_children (VcdTreeNode *node, _vcd_tree_node_cmp_func cmp_func) { vcd_assert (node != NULL); if (node->children) _vcd_list_sort (node->children, (_vcd_list_cmp_func) cmp_func); } void _vcd_tree_node_traverse (VcdTreeNode *node, _vcd_tree_node_traversal_func trav_func, void *user_data) /* pre-order */ { VcdTreeNode *child; vcd_assert (node != NULL); trav_func (node, user_data); _VCD_CHILD_FOREACH (child, node) { _vcd_tree_node_traverse (child, trav_func, user_data); } } void _vcd_tree_node_traverse_bf (VcdTreeNode *node, _vcd_tree_node_traversal_func trav_func, void *user_data) /* breath-first */ { VcdList *queue; vcd_assert (node != NULL); queue = _vcd_list_new (); _vcd_list_prepend (queue, node); while (_vcd_list_length (queue)) { VcdListNode *lastnode = _vcd_list_end (queue); VcdTreeNode *treenode = _vcd_list_node_data (lastnode); VcdTreeNode *childnode; _vcd_list_node_free (lastnode, false); trav_func (treenode, user_data); _VCD_CHILD_FOREACH (childnode, treenode) { _vcd_list_prepend (queue, childnode); } } _vcd_list_free (queue, false); } VcdTreeNode *_vcd_tree_node_parent (VcdTreeNode *node) { return node->parent; } VcdTreeNode *_vcd_tree_node_root (VcdTreeNode *node) { return node->tree->root; } bool _vcd_tree_node_is_root (VcdTreeNode *node) { return (node->parent == NULL); } /* eof */ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: data_structures.h --- /* $Id: data_structures.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VCD_DATA_STRUCTURES_H__ #define __VCD_DATA_STRUCTURES_H__ #include <libvcd/types.h> /* opaque... */ typedef int (*_vcd_list_cmp_func) (void *data1, void *data2); typedef int (*_vcd_list_iterfunc) (void *data, void *user_data); /* methods */ VcdList *_vcd_list_new (void); void _vcd_list_free (VcdList *list, int free_data); unsigned _vcd_list_length (const VcdList *list); void _vcd_list_sort (VcdList *list, _vcd_list_cmp_func cmp_func); void _vcd_list_prepend (VcdList *list, void *data); void _vcd_list_append (VcdList *list, void *data); void _vcd_list_foreach (VcdList *list, _vcd_list_iterfunc func, void *user_data); VcdListNode *_vcd_list_find (VcdList *list, _vcd_list_iterfunc cmp_func, void *user_data); #define _VCD_LIST_FOREACH(node, list) \ for (node = _vcd_list_begin (list); node; node = _vcd_list_node_next (node)) /* node ops */ VcdListNode *_vcd_list_at (VcdList *list, int idx); VcdListNode *_vcd_list_begin (const VcdList *list); VcdListNode *_vcd_list_end (VcdList *list); VcdListNode *_vcd_list_node_next (VcdListNode *node); void _vcd_list_node_free (VcdListNode *node, int free_data); void *_vcd_list_node_data (VcdListNode *node); /* n-way tree */ typedef struct _VcdTree VcdTree; typedef struct _VcdTreeNode VcdTreeNode; #define _VCD_CHILD_FOREACH(child, parent) \ for (child = _vcd_tree_node_first_child (parent); child; child = _vcd_tree_node_next_sibling (child)) typedef int (*_vcd_tree_node_cmp_func) (VcdTreeNode *node1, VcdTreeNode *node2); typedef void (*_vcd_tree_node_traversal_func) (VcdTreeNode *node, void *user_data); VcdTree *_vcd_tree_new (void *root_data); void _vcd_tree_destroy (VcdTree *tree, bool free_data); VcdTreeNode *_vcd_tree_root (VcdTree *tree); void _vcd_tree_node_sort_children (VcdTreeNode *node, _vcd_tree_node_cmp_func cmp_func); void *_vcd_tree_node_data (VcdTreeNode *node); void _vcd_tree_node_destroy (VcdTreeNode *node, bool free_data); void *_vcd_tree_node_set_data (VcdTreeNode *node, void *new_data); VcdTreeNode *_vcd_tree_node_append_child (VcdTreeNode *pnode, void *cdata); VcdTreeNode *_vcd_tree_node_first_child (VcdTreeNode *node); VcdTreeNode *_vcd_tree_node_next_sibling (VcdTreeNode *node); VcdTreeNode *_vcd_tree_node_parent (VcdTreeNode *node); VcdTreeNode *_vcd_tree_node_root (VcdTreeNode *node); bool _vcd_tree_node_is_root (VcdTreeNode *node); void _vcd_tree_node_traverse (VcdTreeNode *node, _vcd_tree_node_traversal_func trav_func, void *user_data); void _vcd_tree_node_traverse_bf (VcdTreeNode *node, _vcd_tree_node_traversal_func trav_func, void *user_data); #endif /* __VCD_DATA_STRUCTURES_H__ */ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: dict.h --- /* $Id: dict.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VCD_DICT_H__ #define __VCD_DICT_H__ /* Public headers */ #include <libvcd/types.h> /* Private headers */ #include "assert.h" #include "obj.h" #include "util.h" struct _dict_t { char *key; uint32_t sector; uint32_t length; void *buf; uint8_t flags; }; static void _dict_insert (VcdObj *obj, const char key[], uint32_t sector, uint32_t length, uint8_t end_flags) { struct _dict_t *_new_node; vcd_assert (key != NULL); vcd_assert (length > 0); if ((sector =_vcd_salloc (obj->iso_bitmap, sector, length)) == SECTOR_NIL) vcd_assert_not_reached (); _new_node = _vcd_malloc (sizeof (struct _dict_t)); _new_node->key = strdup (key); _new_node->sector = sector; _new_node->length = length; _new_node->buf = _vcd_malloc (length * ISO_BLOCKSIZE); _new_node->flags = end_flags; _vcd_list_prepend (obj->buffer_dict_list, _new_node); } static int _dict_key_cmp (struct _dict_t *a, char *b) { vcd_assert (a != NULL); vcd_assert (b != NULL); return !strcmp (a->key, b); } static int _dict_sector_cmp (struct _dict_t *a, uint32_t *b) { vcd_assert (a != NULL); vcd_assert (b != NULL); return (a->sector <= *b && (*b - a->sector) < a->length); } static const struct _dict_t * _dict_get_bykey (VcdObj *obj, const char key[]) { VcdListNode *node; vcd_assert (obj != NULL); vcd_assert (key != NULL); node = _vcd_list_find (obj->buffer_dict_list, (_vcd_list_iterfunc) _dict_key_cmp, (char *) key); if (node) return _vcd_list_node_data (node); return NULL; } static const struct _dict_t * _dict_get_bysector (VcdObj *obj, uint32_t sector) { VcdListNode *node; vcd_assert (obj != NULL); vcd_assert (sector != SECTOR_NIL); node = _vcd_list_find (obj->buffer_dict_list, (_vcd_list_iterfunc) _dict_sector_cmp, §or); if (node) return _vcd_list_node_data (node); return NULL; } static uint8_t _dict_get_sector_flags (VcdObj *obj, uint32_t sector) { const struct _dict_t *p; vcd_assert (sector != SECTOR_NIL); p = _dict_get_bysector (obj, sector); if (p) return (((sector - p->sector)+1 == p->length) ? p->flags : 0); return 0; } static void * _dict_get_sector (VcdObj *obj, uint32_t sector) { const struct _dict_t *p; vcd_assert (sector != SECTOR_NIL); p = _dict_get_bysector (obj, sector); if (p) return ((char *)p->buf) + ((sector - p->sector) * ISO_BLOCKSIZE); return NULL; } static void _dict_clean (VcdObj *obj) { VcdListNode *node; while ((node = _vcd_list_begin (obj->buffer_dict_list))) { struct _dict_t *p = _vcd_list_node_data (node); free (p->key); free (p->buf); _vcd_list_node_free (node, true); } } #endif /* __VCD_DICT_H__ */ --- NEW FILE: directory.c --- /* $Id: directory.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdlib.h> #include <string.h> /* Public headers */ #include <cdio/iso9660.h> #include <libvcd/logging.h> /* Private headers */ #include "assert.h" #include "bytesex.h" #include "directory.h" #include "util.h" static const char _rcsid[] = "$Id: directory.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $"; /* CD-ROM XA */ /* tree data structure */ typedef struct { bool is_dir; char *name; uint16_t version; uint16_t xa_attributes; uint8_t xa_filenum; uint32_t extent; uint32_t size; unsigned pt_id; } data_t; typedef VcdTreeNode VcdDirNode; #define EXTENT(anode) (DATAP(anode)->extent) #define SIZE(anode) (DATAP(anode)->size) #define PT_ID(anode) (DATAP(anode)->pt_id) #define DATAP(anode) ((data_t*) _vcd_tree_node_data (anode)) /* important date to celebrate (for me at least =) -- until user customization is implemented... */ static const time_t _vcd_time = 269222400L; /* implementation */ static void traverse_get_dirsizes(VcdDirNode *node, void *data) { data_t *d = DATAP(node); unsigned *sum = data; if (d->is_dir) { vcd_assert (d->size % ISO_BLOCKSIZE == 0); *sum += (d->size / ISO_BLOCKSIZE); } } static unsigned get_dirsizes (VcdDirNode* dirnode) { unsigned result = 0; _vcd_tree_node_traverse (dirnode, traverse_get_dirsizes, &result); return result; } static void traverse_update_dirextents (VcdDirNode *dirnode, void *data) { data_t *d = DATAP(dirnode); if (d->is_dir) { VcdDirNode* child; unsigned dirextent = d->extent; vcd_assert (d->size % ISO_BLOCKSIZE == 0); dirextent += d->size / ISO_BLOCKSIZE; _VCD_CHILD_FOREACH (child, dirnode) { data_t *d = DATAP(child); vcd_assert (d != NULL); if (d->is_dir) { d->extent = dirextent; dirextent += get_dirsizes (child); } } } } static void update_dirextents (VcdDirectory *dir, uint32_t extent) { data_t *dirdata = DATAP(_vcd_tree_root (dir)); dirdata->extent = extent; _vcd_tree_node_traverse (_vcd_tree_root (dir), traverse_update_dirextents, NULL); } static void traverse_update_sizes(VcdDirNode *node, void *data) { data_t *dirdata = DATAP(node); if (dirdata->is_dir) { VcdDirNode* child; unsigned offset = 0; offset += iso9660_dir_calc_record_size (1, sizeof(iso9660_xa_t)); /* '.' */ offset += iso9660_dir_calc_record_size (1, sizeof(iso9660_xa_t)); /* '..' */ _VCD_CHILD_FOREACH (child, node) { data_t *d = DATAP(child); unsigned reclen; char *pathname = (d->is_dir ? strdup (d->name) : iso9660_pathname_isofy (d->name, d->version)); vcd_assert (d != NULL); reclen = iso9660_dir_calc_record_size (strlen (pathname), sizeof (iso9660_xa_t)); free (pathname); offset = _vcd_ofs_add (offset, reclen, ISO_BLOCKSIZE); } vcd_assert (offset > 0); dirdata->size = _vcd_ceil2block (offset, ISO_BLOCKSIZE); } } static void update_sizes (VcdDirectory *dir) { _vcd_tree_node_traverse (_vcd_tree_root(dir), traverse_update_sizes, NULL); } /* exported stuff: */ VcdDirectory * _vcd_directory_new (void) { data_t *data; VcdDirectory *dir = NULL; vcd_assert (sizeof(iso9660_xa_t) == 14); data = _vcd_malloc (sizeof (data_t)); dir = _vcd_tree_new (data); data->is_dir = true; data->name = _vcd_memdup("\0", 2); data->xa_attributes = XA_FORM1_DIR; data->xa_filenum = 0x00; return dir; } static void traverse_vcd_directory_done (VcdDirNode *node, void *data) { data_t *dirdata = DATAP (node); free (dirdata->name); } void _vcd_directory_destroy (VcdDirectory *dir) { vcd_assert (dir != NULL); _vcd_tree_node_traverse (_vcd_tree_root (dir), traverse_vcd_directory_done, NULL); _vcd_tree_destroy (dir, true); } static VcdDirNode* lookup_child (VcdDirNode* node, const char name[]) { VcdDirNode* child; _VCD_CHILD_FOREACH (child, node) { data_t *d = DATAP(child); if (!strcmp (d->name, name)) return child; } return child; /* NULL */ } static int _iso_dir_cmp (VcdDirNode *node1, VcdDirNode *node2) { data_t *d1 = DATAP(node1); data_t *d2 = DATAP(node2); int result = 0; result = strcmp (d1->name, d2->name); return result; } int _vcd_directory_mkdir (VcdDirectory *dir, const char pathname[]) { char **splitpath; unsigned level, n; VcdDirNode* pdir = _vcd_tree_root (dir); vcd_assert (dir != NULL); vcd_assert (pathname != NULL); splitpath = _vcd_strsplit (pathname, '/'); level = _vcd_strlenv (splitpath); for (n = 0; n < level-1; n++) if (!(pdir = lookup_child(pdir, splitpath[n]))) { vcd_error("mkdir: parent dir `%s' (level=%d) for `%s' missing!", splitpath[n], n, pathname); vcd_assert_not_reached (); } if (lookup_child (pdir, splitpath[level-1])) { vcd_error ("mkdir: `%s' already exists", pathname); vcd_assert_not_reached (); } { data_t *data = _vcd_malloc (sizeof (data_t)); _vcd_tree_node_append_child (pdir, data); data->is_dir = true; data->name = strdup(splitpath[level-1]); data->xa_attributes = XA_FORM1_DIR; data->xa_filenum = 0x00; /* .. */ } _vcd_tree_node_sort_children (pdir, _iso_dir_cmp); _vcd_strfreev (splitpath); return 0; } int _vcd_directory_mkfile (VcdDirectory *dir, const char pathname[], uint32_t start, uint32_t size, bool form2_flag, uint8_t filenum) { char **splitpath; unsigned level, n; const int file_version = 1; VcdDirNode* pdir = NULL; vcd_assert (dir != NULL); vcd_assert (pathname != NULL); splitpath = _vcd_strsplit (pathname, '/'); level = _vcd_strlenv (splitpath); while (!pdir) { pdir = _vcd_tree_root (dir); for (n = 0; n < level-1; n++) if (!(pdir = lookup_child (pdir, splitpath[n]))) { char *newdir = _vcd_strjoin (splitpath, n+1, "/"); vcd_info ("autocreating directory `%s' for file `%s'", newdir, pathname); _vcd_directory_mkdir (dir, newdir); free (newdir); vcd_assert (pdir == NULL); break; } else if (!DATAP(pdir)->is_dir) { char *newdir = _vcd_strjoin (splitpath, n+1, "/"); vcd_error ("mkfile: `%s' not a directory", newdir); free (newdir); return -1; } } if (lookup_child (pdir, splitpath[level-1])) { vcd_error ("mkfile: `%s' already exists", pathname); return -1; } { data_t *data = _vcd_malloc (sizeof (data_t)); _vcd_tree_node_append_child (pdir, data); data->is_dir = false; data->name = strdup (splitpath[level-1]); data->version = file_version; data->xa_attributes = form2_flag ? XA_FORM2_FILE : XA_FORM1_FILE; data->xa_filenum = filenum; data->size = size; data->extent = start; /* .. */ } _vcd_tree_node_sort_children (pdir, _iso_dir_cmp); _vcd_strfreev (splitpath); return 0; } uint32_t _vcd_directory_get_size (VcdDirectory *dir) { vcd_assert (dir != NULL); update_sizes (dir); return get_dirsizes (_vcd_tree_root (dir)); } static void traverse_vcd_directory_dump_entries (VcdDirNode *node, void *data) { data_t *d = DATAP(node); iso9660_xa_t xa_su; uint32_t root_extent = EXTENT(_vcd_tree_node_root (node)); uint32_t parent_extent = (!_vcd_tree_node_is_root (node)) ? EXTENT(_vcd_tree_node_parent (node)) : EXTENT(node); uint32_t parent_size = (!_vcd_tree_node_is_root (node)) ? SIZE(_vcd_tree_node_parent (node)) : SIZE(node); void *dirbufp = (char*) data + ISO_BLOCKSIZE * (parent_extent - root_extent); iso9660_xa_init (&xa_su, 0, 0, d->xa_attributes, d->xa_filenum); if (!_vcd_tree_node_is_root (node)) { char *pathname = (d->is_dir ? strdup (d->name) : iso9660_pathname_isofy (d->name, d->version)); iso9660_dir_add_entry_su (dirbufp, pathname, d->extent, d->size, d->is_dir ? ISO_DIRECTORY : ISO_FILE, &xa_su, sizeof (xa_su), &_vcd_time); free (pathname); } /* if this is a directory, create the new directory node */ if (d->is_dir) { dirbufp = (char*)data + ISO_BLOCKSIZE * (d->extent - root_extent); iso9660_dir_init_new_su (dirbufp, d->extent, d->size, &xa_su, sizeof (xa_su), parent_extent, parent_size, &xa_su, sizeof (xa_su), &_vcd_time); } } void _vcd_directory_dump_entries (VcdDirectory *dir, void *buf, uint32_t extent) { vcd_assert (dir != NULL); update_sizes (dir); /* better call it one time more than one less */ update_dirextents (dir, extent); _vcd_tree_node_traverse (_vcd_tree_root (dir), traverse_vcd_directory_dump_entries, buf); } typedef struct { void *ptl; void *ptm; } _vcd_directory_dump_pathtables_t; static void _dump_pathtables_helper (_vcd_directory_dump_pathtables_t *args, data_t *d, uint16_t parent_id) { uint16_t id_l, id_m; vcd_assert (args != NULL); vcd_assert (d != NULL); vcd_assert (d->is_dir); id_l = iso9660_pathtable_l_add_entry (args->ptl, d->name, d->extent, parent_id); id_m = iso9660_pathtable_m_add_entry (args->ptm, d->name, d->extent, parent_id); vcd_assert (id_l == id_m); d->pt_id = id_m; } static void traverse_vcd_directory_dump_pathtables (VcdDirNode *node, void *data) { _vcd_directory_dump_pathtables_t *args = data; if (DATAP (node)->is_dir) { VcdDirNode* parent = _vcd_tree_node_parent (node); uint16_t parent_id = parent ? PT_ID (parent) : 1; _dump_pathtables_helper (args, DATAP (node), parent_id); } } void _vcd_directory_dump_pathtables (VcdDirectory *dir, void *ptl, void *ptm) { _vcd_directory_dump_pathtables_t args; vcd_assert (dir != NULL); iso9660_pathtable_init (ptl); iso9660_pathtable_init (ptm); args.ptl = ptl; args.ptm = ptm; _vcd_tree_node_traverse_bf (_vcd_tree_root (dir), traverse_vcd_directory_dump_pathtables, &args); } /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: directory.h --- /* $Id: directory.h,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _DIRECTORY_H_ #define _DIRECTORY_H_ #include <libvcd/types.h> /* Private headers */ #include "data_structures.h" /* opaque data structure representing the ISO directory tree */ typedef VcdTree VcdDirectory; VcdDirectory * _vcd_directory_new (void); void _vcd_directory_destroy (VcdDirectory *dir); int _vcd_directory_mkdir (VcdDirectory *dir, const char pathname[]); int _vcd_directory_mkfile (VcdDirectory *dir, const char pathname[], uint32_t start, uint32_t size, bool form2_flag, uint8_t filenum); uint32_t _vcd_directory_get_size (VcdDirectory *dir); void _vcd_directory_dump_entries (VcdDirectory *dir, void *buf, uint32_t extent); void _vcd_directory_dump_pathtables (VcdDirectory *dir, void *ptl, void *ptm); #endif /* _DIRECTORY_H_ */ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: files.c --- /* $Id: files.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ [...979 lines suppressed...] "-- still assuming HQVCD", _info->version); _type = VCD_TYPE_HQVCD; break; } else vcd_warn ("INFO.SVD: signature not found"); return _type; } /* eof */ /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: image.c --- /* $Id: image.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hv...@gn...> 2002 Rocky Bernstein <ro...@pa...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <cdio/cdio.h> /* Public headers */ #include <libvcd/sector.h> #include <cdio/iso9660.h> /* Private headers */ #include "assert.h" #include "image_sink.h" #include "util.h" static const char _rcsid[] = "$Id: image.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $"; /* * VcdImageSink routines next. */ struct _VcdImageSink { void *user_data; vcd_image_sink_funcs op; }; VcdImageSink * vcd_image_sink_new (void *user_data, const vcd_image_sink_funcs *funcs) { VcdImageSink *new_obj; new_obj = _vcd_malloc (sizeof (VcdImageSink)); new_obj->user_data = user_data; new_obj->op = *funcs; return new_obj; } void vcd_image_sink_destroy (VcdImageSink *obj) { vcd_assert (obj != NULL); obj->op.free (obj->user_data); free (obj); } int vcd_image_sink_set_cuesheet (VcdImageSink *obj, const VcdList *vcd_cue_list) { vcd_assert (obj != NULL); return obj->op.set_cuesheet (obj->user_data, vcd_cue_list); } int vcd_image_sink_write (VcdImageSink *obj, void *buf, uint32_t lsn) { vcd_assert (obj != NULL); return obj->op.write (obj->user_data, buf, lsn); } /*! Set the arg "key" with "value" in the target device. */ int vcd_image_sink_set_arg (VcdImageSink *obj, const char key[], const char value[]) { vcd_assert (obj != NULL); vcd_assert (obj->op.set_arg != NULL); vcd_assert (key != NULL); return obj->op.set_arg (obj->user_data, key, value); } /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */ --- NEW FILE: image_bincue.c --- /* $Id: image_bincue.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdlib.h> #include <string.h> #include <cdio/cdio.h> #include <cdio/iso9660.h> /* Public headers */ #include <libvcd/sector.h> #include <libvcd/logging.h> /* Private headers */ #include "assert.h" #include "bytesex.h" #include "image_sink.h" #include "stream_stdio.h" #include "util.h" static const char _rcsid[] = "$Id: image_bincue.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $"; /* reader */ #define DEFAULT_VCD_DEVICE "videocd.bin" /**************************************************************************** * writer */ typedef struct { bool sector_2336_flag; VcdDataSink *bin_snk; VcdDataSink *cue_snk; char *bin_fname; char *cue_fname; bool init; } _img_bincue_snk_t; static void _sink_init (_img_bincue_snk_t *_obj) { if (_obj->init) return; if (!(_obj->bin_snk = vcd_data_sink_new_stdio (_obj->bin_fname))) vcd_error ("init failed"); if (!(_obj->cue_snk = vcd_data_sink_new_stdio (_obj->cue_fname))) vcd_error ("init failed"); _obj->init = true; } static void _sink_free (void *user_data) { _img_bincue_snk_t *_obj = user_data; vcd_data_sink_destroy (_obj->bin_snk); vcd_data_sink_destroy (_obj->cue_snk); free (_obj->bin_fname); free (_obj->cue_fname); free (_obj); } static int _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) { _img_bincue_snk_t *_obj = user_data; VcdListNode *node; int track_no, index_no; const vcd_cue_t *_last_cue = 0; _sink_init (_obj); vcd_data_sink_printf (_obj->cue_snk, "FILE \"%s\" BINARY\r\n", _obj->bin_fname); track_no = 0; index_no = 0; _VCD_LIST_FOREACH (node, (VcdList *) vcd_cue_list) { const vcd_cue_t *_cue = _vcd_list_node_data (node); msf_t _msf = { 0, 0, 0 }; switch (_cue->type) { case VCD_CUE_TRACK_START: track_no++; index_no = 0; vcd_data_sink_printf (_obj->cue_snk, " TRACK %2.2d MODE2/%d\r\n" " FLAGS DCP\r\n", track_no, (_obj->sector_2336_flag ? 2336 : 2352)); if (_last_cue && _last_cue->type == VCD_CUE_PREGAP_START) { cdio_lba_to_msf (_last_cue->lsn, &_msf); vcd_data_sink_printf (_obj->cue_snk, " INDEX %2.2d %2.2x:%2.2x:%2.2x\r\n", index_no, _msf.m, _msf.s, _msf.f); } index_no++; cdio_lba_to_msf (_cue->lsn, &_msf); vcd_data_sink_printf (_obj->cue_snk, " INDEX %2.2d %2.2x:%2.2x:%2.2x\r\n", index_no, _msf.m, _msf.s, _msf.f); break; case VCD_CUE_PREGAP_START: /* handled in next iteration */ break; case VCD_CUE_SUBINDEX: vcd_assert (_last_cue != 0); index_no++; vcd_assert (index_no < 100); cdio_lba_to_msf (_cue->lsn, &_msf); vcd_data_sink_printf (_obj->cue_snk, " INDEX %2.2d %2.2x:%2.2x:%2.2x\r\n", index_no, _msf.m, _msf.s, _msf.f); break; case VCD_CUE_END: vcd_data_sink_close (_obj->cue_snk); return 0; break; case VCD_CUE_LEADIN: break; } _last_cue = _cue; } vcd_assert_not_reached (); return -1; } static int _vcd_image_bincue_write (void *user_data, const void *data, uint32_t lsn) { const char *buf = data; _img_bincue_snk_t *_obj = user_data; long offset = lsn; _sink_init (_obj); offset *= _obj->sector_2336_flag ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE_RAW; vcd_data_sink_seek(_obj->bin_snk, offset); if (_obj->sector_2336_flag) vcd_data_sink_write(_obj->bin_snk, buf + 12 + 4, M2RAW_SECTOR_SIZE, 1); else vcd_data_sink_write(_obj->bin_snk, buf, CDIO_CD_FRAMESIZE_RAW, 1); return 0; } static int _sink_set_arg (void *user_data, const char key[], const char value[]) { _img_bincue_snk_t *_obj = user_data; if (!strcmp (key, "bin")) { free (_obj->bin_fname); if (!value) return -2; _obj->bin_fname = strdup (value); } else if (!strcmp (key, "cue")) { free (_obj->cue_fname); if (!value) return -2; _obj->cue_fname = strdup (value); } else if (!strcmp (key, "sector")) { if (!strcmp (value, "2336")) _obj->sector_2336_flag = true; else if (!strcmp (value, "2352")) _obj->sector_2336_flag = false; else return -2; } else return -1; return 0; } VcdImageSink * vcd_image_sink_new_bincue (void) { _img_bincue_snk_t *_data; vcd_image_sink_funcs _funcs = { .set_cuesheet = _set_cuesheet, .write = _vcd_image_bincue_write, .free = _sink_free, .set_arg = _sink_set_arg }; _data = _vcd_malloc (sizeof (_img_bincue_snk_t)); _data->bin_fname = strdup ("videocd.bin"); _data->cue_fname = strdup ("videocd.cue"); return vcd_image_sink_new (_data, &_funcs); } --- NEW FILE: image_cdrdao.c --- /* $Id: image_cdrdao.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hv...@gn...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdio.h> #include <stdlib.h> #include <string.h> /* Public headers */ #include <cdio/iso9660.h> #include <libvcd/sector.h> #include <libvcd/logging.h> /* Private headers */ #include "assert.h" #include "bytesex.h" #include "image_sink.h" #include "stream_stdio.h" #include "util.h" #include "vcd.h" static const char _rcsid[] = "$Id: image_cdrdao.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $"; /* reader */ /**************************************************************************** * writer */ typedef struct { bool sector_2336_flag; char *toc_fname; char *img_base; VcdDataSink *last_bin_snk; int last_snk_idx; bool last_pause; VcdList *vcd_cue_list; } _img_cdrdao_snk_t; static void _sink_free (void *user_data) { _img_cdrdao_snk_t *_obj = user_data; /* fixme -- destroy cue list */ vcd_data_sink_destroy (_obj->last_bin_snk); free (_obj->toc_fname); free (_obj->img_base); free (_obj); } static int _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) { _img_cdrdao_snk_t *_obj = user_data; VcdDataSink *toc_snk = vcd_data_sink_new_stdio (_obj->toc_fname); VcdListNode *node; int track_no, index_no; const vcd_cue_t *_last_cue = 0; unsigned last_track_lsn = 0; vcd_data_sink_printf (toc_snk, "// CDRDAO TOC\n" "// generated by %s\n\n" "CD_ROM_XA\n", vcd_version_string (false)); _obj->vcd_cue_list = _vcd_list_new (); index_no = track_no = 0; _VCD_LIST_FOREACH (node, (VcdList *) vcd_cue_list) { const vcd_cue_t *_cue = _vcd_list_node_data (node); /* copy cue list while traversing */ { vcd_cue_t *_cue2 = _vcd_malloc (sizeof (vcd_cue_t)); *_cue2 = *_cue; _vcd_list_append (_obj->vcd_cue_list, _cue2); } switch (_cue->type) { case VCD_CUE_TRACK_START: track_no++; index_no = 0; last_track_lsn = _cue->lsn; vcd_data_sink_printf (toc_snk, "\n// Track %d\n" "TRACK %s\n COPY\n", track_no, (_obj->sector_2336_flag ? "MODE2_FORM_MIX" : "MODE2_RAW")); if (_last_cue && _last_cue->type == VCD_CUE_PREGAP_START) vcd_data_sink_printf (toc_snk, " DATAFILE \"%s_%.2d_pregap.img\"\n" " START\n", _obj->img_base, track_no); index_no++; vcd_data_sink_printf (toc_snk, " DATAFILE \"%s_%.2d.img\"\n", _obj->img_base, track_no); break; case VCD_CUE_PREGAP_START: /* handled in next iteration */ break; case VCD_CUE_SUBINDEX: index_no++; { msf_t _msf = { 0, 0, 0 }; cdio_lba_to_msf (_cue->lsn - last_track_lsn, &_msf); vcd_data_sink_printf (toc_snk, " INDEX %2.2x:%2.2x:%2.2x\n", _msf.m, _msf.s, _msf.f); } break; case VCD_CUE_LEADIN: break; case VCD_CUE_END: vcd_data_sink_printf (toc_snk, "\n// EOF\n"); vcd_data_sink_close (toc_snk); vcd_data_sink_destroy (toc_snk); return 0; break; } _last_cue = _cue; } vcd_assert_not_reached (); return -1; } static int _vcd_image_cdrdao_write (void *user_data, const void *data, uint32_t lsn) { const char *buf = data; _img_cdrdao_snk_t *_obj = user_data; long offset; { VcdListNode *no... [truncated message content] |