diff --git a/_autogen.sh b/autogen.sh similarity index 100% rename from _autogen.sh rename to autogen.sh diff --git a/configure b/configure index e66fa286..7fd4c4ec 100644 --- a/configure +++ b/configure @@ -3463,6 +3463,10 @@ $as_echo "#define _GNU_SOURCE /**/" >>confdefs.h # AC_MSG_ERROR([unsupported development environment]) #esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling Large File Support (for ISO images)" >&5 +$as_echo "enabling Large File Support (for ISO images)" >&6; } +AM_CFLAGS="-D_FILE_OFFSET_BITS=64 -D_OFF_T_DEFINED -D_OFF_T_ -D_off_t=off64_t -Doff_t=off64_t" + # Clang needs an explicit WIN32_WINNT defined else it produces warnings # in msapi_utf8.h - including winver.h only doesn't work AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x501 -D_WIN32_IE=0x501 -D_WIN32_WINNT=0x501" @@ -3550,6 +3554,12 @@ ac_config_files="$ac_config_files src/syslinux/libfat/Makefile" ac_config_files="$ac_config_files src/syslinux/libinstaller/Makefile" +ac_config_files="$ac_config_files src/libcdio/iso9660/Makefile" + +ac_config_files="$ac_config_files src/libcdio/udf/Makefile" + +ac_config_files="$ac_config_files src/libcdio/driver/Makefile" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -4284,6 +4294,9 @@ do "src/ms-sys/Makefile") CONFIG_FILES="$CONFIG_FILES src/ms-sys/Makefile" ;; "src/syslinux/libfat/Makefile") CONFIG_FILES="$CONFIG_FILES src/syslinux/libfat/Makefile" ;; "src/syslinux/libinstaller/Makefile") CONFIG_FILES="$CONFIG_FILES src/syslinux/libinstaller/Makefile" ;; + "src/libcdio/iso9660/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/iso9660/Makefile" ;; + "src/libcdio/udf/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/udf/Makefile" ;; + "src/libcdio/driver/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/driver/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; esac diff --git a/configure.ac b/configure.ac index 6b4ffb1a..450bbbb7 100644 --- a/configure.ac +++ b/configure.ac @@ -32,6 +32,9 @@ AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) # AC_MSG_ERROR([unsupported development environment]) #esac +AC_MSG_RESULT([enabling Large File Support (for ISO images)]) +AM_CFLAGS="-D_FILE_OFFSET_BITS=64 -D_OFF_T_DEFINED -D_OFF_T_ -D_off_t=off64_t -Doff_t=off64_t" + # Clang needs an explicit WIN32_WINNT defined else it produces warnings # in msapi_utf8.h - including winver.h only doesn't work AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x501 -D_WIN32_IE=0x501 -D_WIN32_WINNT=0x501" @@ -89,4 +92,7 @@ AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([src/ms-sys/Makefile]) AC_CONFIG_FILES([src/syslinux/libfat/Makefile]) AC_CONFIG_FILES([src/syslinux/libinstaller/Makefile]) +AC_CONFIG_FILES([src/libcdio/iso9660/Makefile]) +AC_CONFIG_FILES([src/libcdio/udf/Makefile]) +AC_CONFIG_FILES([src/libcdio/driver/Makefile]) AC_OUTPUT diff --git a/rufus_2010.sln b/rufus_2010.sln deleted file mode 100644 index 127f43f9..00000000 --- a/rufus_2010.sln +++ /dev/null @@ -1,59 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{11411DA5-63FE-49DC-8D5C-CA379B95FF3C}") = "rufus", "src\.msvc\rufus_2010.vcxproj", "{731858A7-0303-4988-877B-9C0DD6471864}" - ProjectSection(ProjectDependencies) = postProject - {2B1D078D-8EB4-4398-9CA4-23457265A7F6} = {2B1D078D-8EB4-4398-9CA4-23457265A7F6} - EndProjectSection -EndProject -Project("{11411DA5-63FE-49DC-8D5C-CA379B95FF3C}") = "ms-sys", "src\ms-sys\.msvc\ms-sys.vcxproj", "{2B1D078D-8EB4-4398-9CA4-23457265A7F6}" -EndProject -Project("{11411DA5-63FE-49DC-8D5C-CA379B95FF3C}") = "syslinux-libfat", "src\syslinux\libfat\.msvc\libfat.vcxproj", "{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}" -EndProject -Project("{11411DA5-63FE-49DC-8D5C-CA379B95FF3C}") = "syslinux-libinstaller", "src\syslinux\libinstaller\.msvc\libinstaller.vcxproj", "{266502AC-CD74-4581-B707-938A7D05AD7A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {731858A7-0303-4988-877B-9C0DD6471864}.Debug|Win32.ActiveCfg = Debug|Win32 - {731858A7-0303-4988-877B-9C0DD6471864}.Debug|Win32.Build.0 = Debug|Win32 - {731858A7-0303-4988-877B-9C0DD6471864}.Debug|x64.ActiveCfg = Debug|x64 - {731858A7-0303-4988-877B-9C0DD6471864}.Debug|x64.Build.0 = Debug|x64 - {731858A7-0303-4988-877B-9C0DD6471864}.Release|Win32.ActiveCfg = Release|Win32 - {731858A7-0303-4988-877B-9C0DD6471864}.Release|Win32.Build.0 = Release|Win32 - {731858A7-0303-4988-877B-9C0DD6471864}.Release|x64.ActiveCfg = Release|x64 - {731858A7-0303-4988-877B-9C0DD6471864}.Release|x64.Build.0 = Release|x64 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|Win32.ActiveCfg = Debug|Win32 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|Win32.Build.0 = Debug|Win32 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x64.ActiveCfg = Debug|x64 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x64.Build.0 = Debug|x64 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|Win32.ActiveCfg = Release|Win32 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|Win32.Build.0 = Release|Win32 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x64.ActiveCfg = Release|x64 - {2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x64.Build.0 = Release|x64 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|Win32.ActiveCfg = Debug|Win32 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|Win32.Build.0 = Debug|Win32 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x64.ActiveCfg = Debug|x64 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x64.Build.0 = Debug|x64 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|Win32.ActiveCfg = Release|Win32 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|Win32.Build.0 = Release|Win32 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x64.ActiveCfg = Release|x64 - {8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x64.Build.0 = Release|x64 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|Win32.ActiveCfg = Debug|Win32 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|Win32.Build.0 = Debug|Win32 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x64.ActiveCfg = Debug|x64 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x64.Build.0 = Debug|x64 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Release|Win32.ActiveCfg = Release|Win32 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Release|Win32.Build.0 = Release|Win32 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x64.ActiveCfg = Release|x64 - {266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/.msvc/rufus_2010.vcxproj b/src/.msvc/rufus_2010.vcxproj index 91c14209..e44c7d7f 100644 --- a/src/.msvc/rufus_2010.vcxproj +++ b/src/.msvc/rufus_2010.vcxproj @@ -77,10 +77,10 @@ - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions) + _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug Level3 - ..\ms-sys\inc;..\syslinux;..\syslinux\libinstaller;..\syslinux\libfat;%(AdditionalIncludeDirectories) + ..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;%(AdditionalIncludeDirectories) setupapi.lib;comctl32.lib;%(AdditionalDependencies) @@ -99,8 +99,8 @@ X64 - ..\ms-sys\inc;..\syslinux;..\syslinux\libinstaller;..\syslinux\libfat;%(AdditionalIncludeDirectories) - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions) + ..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;%(AdditionalIncludeDirectories) + _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug Level3 ProgramDatabase @@ -119,10 +119,10 @@ - _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions) + _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded Level3 - ..\ms-sys\inc;..\syslinux;..\syslinux\libinstaller;..\syslinux\libfat;%(AdditionalIncludeDirectories) + ..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;%(AdditionalIncludeDirectories) setupapi.lib;comctl32.lib;%(AdditionalDependencies) @@ -141,10 +141,10 @@ X64 - _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions) + _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded Level3 - ..\ms-sys\inc;..\syslinux;..\syslinux\libinstaller;..\syslinux\libfat;%(AdditionalIncludeDirectories) + ..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;%(AdditionalIncludeDirectories) setupapi.lib;comctl32.lib;%(AdditionalDependencies) @@ -163,6 +163,7 @@ + @@ -172,6 +173,10 @@ + + + + @@ -189,6 +194,15 @@ + + {fa1b1093-ba86-410a-b7a0-7a54c605f812} + + + {d4e80f35-2604-40ac-b436-97b052ecb572} + + + {0cec40a6-a195-4be5-a88b-0ab00eb142ec} + {2b1d078d-8eb4-4398-9ca4-23457265a7f6} diff --git a/src/.msvc/rufus_2010.vcxproj.filters b/src/.msvc/rufus_2010.vcxproj.filters index 181eab37..0b9d20a7 100644 --- a/src/.msvc/rufus_2010.vcxproj.filters +++ b/src/.msvc/rufus_2010.vcxproj.filters @@ -42,6 +42,9 @@ Source Files + + Source Files + @@ -71,6 +74,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/.msvc/rufus_sources b/src/.msvc/rufus_sources index a94ae3fa..d1119e31 100644 --- a/src/.msvc/rufus_sources +++ b/src/.msvc/rufus_sources @@ -3,7 +3,7 @@ TARGETTYPE=PROGRAM UMTYPE=windows UMENTRY=winmain -INCLUDES=$(DDK_INC_PATH);.\ms-sys\inc;.\syslinux;.\syslinux\libfat;.\syslinux\libinstaller +INCLUDES=$(DDK_INC_PATH);.\ms-sys\inc;.\syslinux\libfat;.\syslinux\libinstaller;.\msvc-missing;.\libcdio C_DEFINES = $(C_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED !IFNDEF MSC_WARNING_LEVEL @@ -20,7 +20,10 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ $(SDK_LIB_PATH)\shell32.lib \ .\ms-sys\ms-sys.lib \ .\syslinux\libfat\libfat.lib \ - .\syslinux\libinstaller\libinstaller.lib + .\syslinux\libinstaller\libinstaller.lib \ + .\libcdio\iso9660\iso9660.lib \ + .\libcdio\udf\udf.lib \ + .\libcdio\driver\driver.lib # http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/ SXS_APPLICATION_MANIFEST=..\common_controls_and_elevation.manifest @@ -29,6 +32,7 @@ SOURCES=rufus.c \ format.c \ stdio.c \ stdlg.c \ + iso.c \ dos.c \ dos_locale.c \ badblocks.c \ diff --git a/src/Makefile.am b/src/Makefile.am index 09b4263b..a9f001f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller +SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/udf libcdio/driver noinst_PROGRAMS = rufus @@ -9,7 +9,8 @@ pkg_v_rc_0 = @echo " RC $@"; %_rc.o: %.rc $(pkg_v_rc)$(WINDRES) $(AM_RCFLAGS) -i $< -o $@ -rufus_SOURCES = drive.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c -rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller $(AM_CFLAGS) +rufus_SOURCES = drive.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c +rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows -rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a -lsetupapi -lole32 -lgdi32 +rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ + libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 diff --git a/src/Makefile.in b/src/Makefile.in index 0f1cb9ca..ec3eb872 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -43,14 +43,16 @@ mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) -am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-dos.$(OBJEXT) \ - rufus-dos_locale.$(OBJEXT) rufus-badblocks.$(OBJEXT) \ - rufus-syslinux.$(OBJEXT) rufus-format.$(OBJEXT) \ - rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \ - rufus-rufus.$(OBJEXT) +am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-iso.$(OBJEXT) \ + rufus-dos.$(OBJEXT) rufus-dos_locale.$(OBJEXT) \ + rufus-badblocks.$(OBJEXT) rufus-syslinux.$(OBJEXT) \ + rufus-format.$(OBJEXT) rufus-stdio.$(OBJEXT) \ + rufus-stdlg.$(OBJEXT) rufus-rufus.$(OBJEXT) rufus_OBJECTS = $(am_rufus_OBJECTS) rufus_DEPENDENCIES = rufus_rc.o ms-sys/libmssys.a \ - syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a + syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ + libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a \ + libcdio/driver/libdriver.a rufus_LINK = $(CCLD) $(rufus_CFLAGS) $(CFLAGS) $(rufus_LDFLAGS) \ $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ @@ -178,14 +180,16 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller +SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/udf libcdio/driver pkg_v_rc = $(pkg_v_rc_$(V)) pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) pkg_v_rc_0 = @echo " RC $@"; -rufus_SOURCES = drive.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c -rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller $(AM_CFLAGS) +rufus_SOURCES = drive.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c +rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows -rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a -lsetupapi -lole32 -lgdi32 +rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ + libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 + all: all-recursive .SUFFIXES: @@ -249,6 +253,14 @@ rufus-drive.obj: drive.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-drive.obj `if test -f 'drive.c'; then $(CYGPATH_W) 'drive.c'; else $(CYGPATH_W) '$(srcdir)/drive.c'; fi` +rufus-iso.o: iso.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.o `test -f 'iso.c' || echo '$(srcdir)/'`iso.c + +rufus-iso.obj: iso.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.obj `if test -f 'iso.c'; then $(CYGPATH_W) 'iso.c'; else $(CYGPATH_W) '$(srcdir)/iso.c'; fi` + rufus-dos.o: dos.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-dos.o `test -f 'dos.c' || echo '$(srcdir)/'`dos.c diff --git a/src/iso.c b/src/iso.c new file mode 100644 index 00000000..a2a35e4c --- /dev/null +++ b/src/iso.c @@ -0,0 +1,265 @@ +/* + * Rufus: The Reliable USB Formatting Utility + * ISO file extraction + * Copyright (c) 2011-2012 Pete Batard + * Based on libcdio's iso & udf samples: + * Copyright (c) 2003-2011 Rocky Bernstein + * + * 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 3 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, see . + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "rufus.h" + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define print_vd_info(title, fn) \ + if (fn(p_iso, &psz_str)) { \ + uprintf(title ": %s\n", psz_str); \ + } \ + free(psz_str); \ + psz_str = NULL; + +/* Needed for UDF ISO access */ +// TODO: should be able to elmininate those with an alternate approach +CdIo_t* cdio_open (const char *psz_source, driver_id_t driver_id) {return NULL;} +void cdio_destroy (CdIo_t *p_cdio) {} + +const char *psz_extract_dir = "D:/tmp/iso"; + +// TODO: Unicode support, progress computation, timestamp preservation + +static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path) +{ + FILE *fd = NULL; + int i_length; + char* psz_fullpath; + const char* psz_basename; + udf_dirent_t *p_udf_dirent2; + uint8_t buf[UDF_BLOCKSIZE]; + int64_t i_read, i_file_length; + + if ((p_udf_dirent == NULL) || (psz_path == NULL)) + return 1; + + while (udf_readdir(p_udf_dirent)) { + psz_basename = udf_get_filename(p_udf_dirent); + i_length = (int)(3 + strlen(psz_path) + strlen(psz_basename) + strlen(psz_extract_dir)); + psz_fullpath = (char*)calloc(sizeof(char), i_length); + if (psz_fullpath == NULL) { + uprintf("Error allocating file name\n"); + goto out; + } + i_length = _snprintf(psz_fullpath, i_length, "%s%s/%s", psz_extract_dir, psz_path, psz_basename); + if (i_length < 0) { + goto out; + } + uprintf("Extracting: %s\n", psz_fullpath); + if (udf_is_dir(p_udf_dirent)) { + _mkdir(psz_fullpath); + p_udf_dirent2 = udf_opendir(p_udf_dirent); + if (p_udf_dirent2 != NULL) { + if (udf_extract_files(p_udf, p_udf_dirent2, &psz_fullpath[strlen(psz_extract_dir)])) + goto out; + } + } else { + fd = fopen(psz_fullpath, "wb"); + if (fd == NULL) { + uprintf(" Unable to create file\n"); + goto out; + } + i_file_length = udf_get_file_length(p_udf_dirent); + while (i_file_length > 0) { + memset(buf, 0, UDF_BLOCKSIZE); + i_read = udf_read_block(p_udf_dirent, buf, 1); + if (i_read < 0) { + uprintf(" Error reading UDF file %s\n", &psz_fullpath[strlen(psz_extract_dir)]); + goto out; + } + fwrite(buf, (size_t)MIN(i_file_length, i_read), 1, fd); + if (ferror(fd)) { + uprintf(" Error writing file\n"); + goto out; + } + i_file_length -= i_read; + } + fclose(fd); + fd = NULL; + } + free(psz_fullpath); + } + return 0; + +out: + if (fd != NULL) + fclose(fd); + free(psz_fullpath); + return 1; +} + +static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) +{ + FILE *fd = NULL; + int i_length, r = 1; + char psz_fullpath[4096], *psz_basename; + const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; + unsigned char buf[ISO_BLOCKSIZE]; + CdioListNode_t* p_entnode; + iso9660_stat_t *p_statbuf; + CdioList_t* p_entlist; + size_t i; + lsn_t lsn; + int64_t i_file_length; + + if ((p_iso == NULL) || (psz_path == NULL)) + return 1; + + i_length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path); + if (i_length < 0) + return 1; + psz_basename = &psz_fullpath[i_length]; + + p_entlist = iso9660_ifs_readdir(p_iso, psz_path); + if (!p_entlist) + return 1; + + _CDIO_LIST_FOREACH (p_entnode, p_entlist) { + p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); + /* Eliminate . and .. entries */ + if ( (strcmp(p_statbuf->filename, ".") == 0) + || (strcmp(p_statbuf->filename, "..") == 0) ) + continue; + iso9660_name_translate(p_statbuf->filename, psz_basename); + if (p_statbuf->type == _STAT_DIR) { + _mkdir(psz_fullpath); + if (iso_extract_files(p_iso, psz_iso_name)) + goto out; + } else { + uprintf("Extracting: %s\n", psz_fullpath); + fd = fopen(psz_fullpath, "wb"); + if (fd == NULL) { + uprintf(" Unable to create file\n"); + goto out; + } + i_file_length = p_statbuf->size; + for (i = 0; i_file_length > 0; i++) { + memset(buf, 0, ISO_BLOCKSIZE); + lsn = p_statbuf->lsn + (lsn_t)i; + if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { + uprintf(" Error reading ISO9660 file %s at LSN %lu\n", + psz_iso_name, (long unsigned int)lsn); + goto out; + } + fwrite(buf, (size_t)MIN(i_file_length, ISO_BLOCKSIZE), 1, fd); + if (ferror(fd)) { + uprintf(" Error writing file\n"); + goto out; + } + i_file_length -= ISO_BLOCKSIZE; + } + fclose(fd); + fd = NULL; + } + } + r = 0; + +out: + if (fd != NULL) + fclose(fd); + _cdio_list_free(p_entlist, true); + return r; +} + +BOOL ExtractISO(const char* src_iso, const char* dest_dir) +{ + BOOL r = FALSE; + iso9660_t* p_iso = NULL; + udf_t* p_udf = NULL; + udf_dirent_t* p_udf_root; + char *psz_str = NULL; + char vol_id[UDF_VOLID_SIZE] = ""; + char volset_id[UDF_VOLSET_ID_SIZE+1] = ""; + + cdio_loglevel_default = CDIO_LOG_DEBUG; + + /* First try to open as UDF - fallback to ISO if it failed */ + p_udf = udf_open(src_iso); + if (p_udf == NULL) + goto try_iso; + + p_udf_root = udf_get_root(p_udf, true, 0); + if (p_udf_root == NULL) { + uprintf("Couldn't locate UDF root directory\n"); + goto out; + } + vol_id[0] = 0; volset_id[0] = 0; + + /* Show basic UDF Volume info */ + if (udf_get_volume_id(p_udf, vol_id, sizeof(vol_id)) > 0) + uprintf("Volume id: %s\n", vol_id); + if (udf_get_volume_id(p_udf, volset_id, sizeof(volset_id)) >0 ) { + volset_id[UDF_VOLSET_ID_SIZE]='\0'; + uprintf("Volume set id: %s\n", volset_id); + } + uprintf("Partition number: %d\n", udf_get_part_number(p_udf)); + + /* Recursively extract files */ + r = udf_extract_files(p_udf, p_udf_root, ""); + + goto out; + +try_iso: + p_iso = iso9660_open(src_iso); + if (p_iso == NULL) { + uprintf("Unable to open image '%s'.\n", src_iso); + goto out; + } + + /* Show basic ISO9660 info from the Primary Volume Descriptor. */ + print_vd_info("Application", iso9660_ifs_get_application_id); + print_vd_info("Preparer ", iso9660_ifs_get_preparer_id); + print_vd_info("Publisher ", iso9660_ifs_get_publisher_id); + print_vd_info("System ", iso9660_ifs_get_system_id); + print_vd_info("Volume ", iso9660_ifs_get_volume_id); + print_vd_info("Volume Set ", iso9660_ifs_get_volumeset_id); + + r = iso_extract_files(p_iso, ""); + +out: + if (p_iso != NULL) + iso9660_close(p_iso); + if (p_udf != NULL) + udf_close(p_udf); + + return r; +} diff --git a/src/libcdio/cdio/audio.h b/src/libcdio/cdio/audio.h new file mode 100644 index 00000000..e51ba3d2 --- /dev/null +++ b/src/libcdio/cdio/audio.h @@ -0,0 +1,146 @@ +/* -*- c -*- + Copyright (C) 2005, 2007, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +/** \file audio.h + * + * \brief The top-level header for CD audio-related libcdio + * calls. These control playing of the CD-ROM through its + * line-out jack. + */ +#ifndef __CDIO_AUDIO_H__ +#define __CDIO_AUDIO_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! This struct is used by the cdio_audio_read_subchannel */ + typedef struct cdio_subchannel_s + { + uint8_t format; + uint8_t audio_status; + uint8_t address: 4; + uint8_t control: 4; + uint8_t track; + uint8_t index; + msf_t abs_addr; + msf_t rel_addr; + } cdio_subchannel_t; + + /*! This struct is used by cdio_audio_get_volume and cdio_audio_set_volume */ + typedef struct cdio_audio_volume_s + { + uint8_t level[4]; + } cdio_audio_volume_t; + + + /*! This struct is used by the CDROMPLAYTRKIND ioctl */ + typedef struct cdio_track_index_s + { + uint8_t i_start_track; /**< start track */ + uint8_t i_start_index; /**< start index */ + uint8_t i_end_track; /**< end track */ + uint8_t i_end_index; /**< end index */ + } cdio_track_index_t; + + /*! + Get volume of an audio CD. + + @param p_cdio the CD object to be acted upon. + @param p_volume place to put the list of volume outputs levels + + p_volume can be NULL in which case we return only whether the driver + has the ability to get the volume or not. + + */ + driver_return_code_t cdio_audio_get_volume (CdIo_t *p_cdio, /*out*/ + cdio_audio_volume_t *p_volume); + + /*! + Return the number of seconds (discarding frame portion) of an MSF + */ + uint32_t cdio_audio_get_msf_seconds(msf_t *p_msf); + + /*! + Pause playing CD through analog output + + @param p_cdio the CD object to be acted upon. + */ + driver_return_code_t cdio_audio_pause (CdIo_t *p_cdio); + + /*! + Playing CD through analog output at the given MSF. + + @param p_cdio the CD object to be acted upon. + @param p_start_msf pointer to staring MSF + @param p_end_msf pointer to ending MSF + */ + driver_return_code_t cdio_audio_play_msf (CdIo_t *p_cdio, + /*in*/msf_t *p_start_msf, + /*in*/ msf_t *p_end_msf); + + /*! + Playing CD through analog output at the desired track and index + + @param p_cdio the CD object to be acted upon. + @param p_track_index location to start/end. + */ + driver_return_code_t cdio_audio_play_track_index + ( CdIo_t *p_cdio, cdio_track_index_t *p_track_index); + + /*! + Get subchannel information. + + @param p_cdio the CD object to be acted upon. + @param p_subchannel place for returned subchannel information + */ + driver_return_code_t cdio_audio_read_subchannel (CdIo_t *p_cdio, + /*out*/ cdio_subchannel_t *p_subchannel); + + /*! + Resume playing an audio CD. + + @param p_cdio the CD object to be acted upon. + + */ + driver_return_code_t cdio_audio_resume (CdIo_t *p_cdio); + + /*! + Set volume of an audio CD. + + @param p_cdio the CD object to be acted upon. + @param p_volume place for returned volume-level information + + */ + driver_return_code_t cdio_audio_set_volume (CdIo_t *p_cdio, /*out*/ + cdio_audio_volume_t *p_volume); + + /*! + Stop playing an audio CD. + + @param p_cdio the CD object to be acted upon. + + */ + driver_return_code_t cdio_audio_stop (CdIo_t *p_cdio); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_AUDIO_H__ */ diff --git a/src/libcdio/cdio/bytesex.h b/src/libcdio/cdio/bytesex.h new file mode 100644 index 00000000..a85b965e --- /dev/null +++ b/src/libcdio/cdio/bytesex.h @@ -0,0 +1,220 @@ +/* + $Id: bytesex.h,v 1.5 2008/03/25 15:59:08 karl Exp $ + + Copyright (C) 2000, 2004 Herbert Valerio Riedel + Copyright (C) 2005, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +/** \file bytesex.h + * \brief Generic Byte-swapping routines. + * + * Note: this header will is slated to get removed and libcdio will + * use glib.h routines instead. +*/ + +#ifndef __CDIO_BYTESEX_H__ +#define __CDIO_BYTESEX_H__ + +#include +#include /* also defines CDIO_INLINE */ +#include + +/** 16-bit big-endian to little-endian */ +#define UINT16_SWAP_LE_BE_C(val) ((uint16_t) ( \ + (((uint16_t) (val) & (uint16_t) 0x00ffU) << 8) | \ + (((uint16_t) (val) & (uint16_t) 0xff00U) >> 8))) + +/** 32-bit big-endian to little-endian */ +#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))) + +/** 64-bit big-endian to little-endian */ +#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 + +static CDIO_INLINE +uint16_t uint16_swap_le_be (const uint16_t val) +{ + return UINT16_SWAP_LE_BE (val); +} + +static CDIO_INLINE +uint32_t uint32_swap_le_be (const uint32_t val) +{ + return UINT32_SWAP_LE_BE (val); +} + +static CDIO_INLINE +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 CDIO_INLINE uint ## bits ## _t \ + uint ## bits ## _to_be (uint ## bits ## _t val) \ + { return UINT ## bits ## _TO_BE (val); } \ + static CDIO_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 field conversion routines */ + +/** Convert from uint8_t to ISO 9660 7.1.1 format */ +#define to_711(i) uint8_to_le(i) + +/** Convert from ISO 9660 7.1.1 format to uint8_t */ +#define from_711(i) uint8_from_le(i) + +/** Convert from uint16_t to ISO 9669 7.2.1 format */ +#define to_721(i) uint16_to_le(i) + +/** Convert from ISO 9660 7.2.1 format to uint16_t */ +#define from_721(i) uint16_from_le(i) + +/** Convert from uint16_t to ISO 9669 7.2.2 format */ +#define to_722(i) uint16_to_be(i) + +/** Convert from ISO 9660 7.2.2 format to uint16_t */ +#define from_722(i) uint16_from_be(i) + +/** Convert from uint16_t to ISO 9669 7.2.3 format */ +static CDIO_INLINE uint32_t +to_723(uint16_t i) +{ + return uint32_swap_le_be(i) | i; +} + +/** Convert from ISO 9660 7.2.3 format to uint16_t */ +static CDIO_INLINE uint16_t +from_723 (uint32_t p) +{ + if (uint32_swap_le_be (p) != p) + cdio_warn ("from_723: broken byte order"); + + return (0xFFFF & p); +} + +/** Convert from uint16_t to ISO 9669 7.3.1 format */ +#define to_731(i) uint32_to_le(i) + +/** Convert from ISO 9660 7.3.1 format to uint32_t */ +#define from_731(i) uint32_from_le(i) + +/** Convert from uint32_t to ISO 9669 7.3.2 format */ +#define to_732(i) uint32_to_be(i) + +/** Convert from ISO 9660 7.3.2 format to uint32_t */ +#define from_732(i) uint32_from_be(i) + +/** Convert from uint16_t to ISO 9669 7.3.3 format */ +static CDIO_INLINE uint64_t +to_733(uint32_t i) +{ + return uint64_swap_le_be(i) | i; +} + +/** Convert from ISO 9660 7.3.3 format to uint32_t */ +static CDIO_INLINE uint32_t +from_733 (uint64_t p) +{ + if (uint64_swap_le_be (p) != p) + cdio_warn ("from_733: broken byte order"); + + return (UINT32_C(0xFFFFFFFF) & p); +} + +#endif /* __CDIO_BYTESEX_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/bytesex_asm.h b/src/libcdio/cdio/bytesex_asm.h new file mode 100644 index 00000000..5a1ce6ac --- /dev/null +++ b/src/libcdio/cdio/bytesex_asm.h @@ -0,0 +1,142 @@ +/* + $Id: bytesex_asm.h,v 1.3 2008/03/25 15:59:08 karl Exp $ + + Copyright (C) 2008 Rocky Bernstein + 2001, 2004, 2005 Herbert Valerio Riedel + 2001 Sven Ottemann + + 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 3 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, see . +*/ + +/** \file bytesex_asm.h + * \brief Assembly code to handle byte-swapping. + + Note: this header will is slated to get removed and libcdio will use + glib.h routines instead. +*/ + +#ifndef __CDIO_BYTESEX_ASM_H__ +#define __CDIO_BYTESEX_ASM_H__ +#if !defined(DISABLE_ASM_OPTIMIZE) + +#include + +#if !defined CDIO_INLINE +#if defined(__cplusplus) || defined(inline) +#define CDIO_INLINE inline +#elif defined(__GNUC__) +#define CDIO_INLINE __inline__ +#elif defined(_MSC_VER) +#define CDIO_INLINE __inline +#else +#define CDIO_INLINE +#endif +#endif /* CDIO_INLINE */ + +#if defined(__powerpc__) && defined(__GNUC__) + +static CDIO_INLINE +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; +} + +static CDIO_INLINE +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__) + +static CDIO_INLINE +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); +} + +static CDIO_INLINE +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__) + +static CDIO_INLINE +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); +} + +static CDIO_INLINE +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 /* __CDIO_BYTESEX_ASM_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/cdio.h b/src/libcdio/cdio/cdio.h new file mode 100644 index 00000000..f0d8b840 --- /dev/null +++ b/src/libcdio/cdio/cdio.h @@ -0,0 +1,73 @@ +/* -*- c -*- + Copyright (C) 2003, 2004, 2005, 2008, 2009 Rocky Bernstein + Copyright (C) 2001 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +/** \file cdio.h + * + * \brief The top-level header for libcdio: the CD Input and Control + * library. Applications include this for anything regarding libcdio. + */ + + +#ifndef __CDIO_H__ +#define __CDIO_H__ + +/** Application Interface or Protocol version number. If the public + * interface changes, we increase this number. + */ +#define CDIO_API_VERSION 5 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* For compatibility. */ +#define CdIo CdIo_t + + /** This is an opaque structure for the CD object. */ + typedef struct _CdIo CdIo_t; + + typedef struct cdtext_s cdtext_t; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/* Drive(r)/Device-related functions. Perhaps we should break out + Driver from device? +*/ +#include + +/* Disc-related functions. */ +#include + +/* Sector (frame, or block)-related functions. Uses driver_return_code_t + from so it should come after that. +*/ +#include + +/* CD-Text-related functions. */ +#include + +/* Track-related functions. */ +#include + +#endif /* __CDIO_H__ */ diff --git a/src/libcdio/cdio/cdtext.h b/src/libcdio/cdio/cdtext.h new file mode 100644 index 00000000..1298328f --- /dev/null +++ b/src/libcdio/cdio/cdtext.h @@ -0,0 +1 @@ +/* Empty placeholder */ \ No newline at end of file diff --git a/src/libcdio/cdio/device.h b/src/libcdio/cdio/device.h new file mode 100644 index 00000000..71ef38b3 --- /dev/null +++ b/src/libcdio/cdio/device.h @@ -0,0 +1,1058 @@ +/* -*- c -*- + + Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011 Rocky Bernstein + + + 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 3 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, see . +*/ + +/** + * \file device.h + * + * \brief C header for driver- or device-related libcdio + * calls. ("device" includes CD-image reading devices). + */ +#ifndef __CDIO_DEVICE_H__ +#define __CDIO_DEVICE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + + /** The type of an drive capability bit mask. See below for values*/ + typedef uint32_t cdio_drive_read_cap_t; + typedef uint32_t cdio_drive_write_cap_t; + typedef uint32_t cdio_drive_misc_cap_t; + + /** + \brief Drive capability bits returned by cdio_get_drive_cap() + NOTE: Setting a bit here means the presence of a capability. + */ + + /** Miscellaneous capabilities. */ + typedef enum { + CDIO_DRIVE_CAP_ERROR = 0x40000, /**< Error */ + CDIO_DRIVE_CAP_UNKNOWN = 0x80000, /**< Dunno. It can be on if we + have only partial information + or are not completely certain + */ + CDIO_DRIVE_CAP_MISC_CLOSE_TRAY = 0x00001, /**< caddy systems can't + close... */ + CDIO_DRIVE_CAP_MISC_EJECT = 0x00002, /**< but can eject. */ + CDIO_DRIVE_CAP_MISC_LOCK = 0x00004, /**< disable manual eject */ + CDIO_DRIVE_CAP_MISC_SELECT_SPEED = 0x00008, /**< programmable speed */ + CDIO_DRIVE_CAP_MISC_SELECT_DISC = 0x00010, /**< select disc from + juke-box */ + CDIO_DRIVE_CAP_MISC_MULTI_SESSION= 0x00020, /**< read sessions>1 */ + CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED= 0x00080, /**< media changed */ + CDIO_DRIVE_CAP_MISC_RESET = 0x00100, /**< hard reset device */ + CDIO_DRIVE_CAP_MISC_FILE = 0x20000 /**< drive is really a file, + i.e a CD file image */ + } cdio_drive_cap_misc_t; + + /** Reading masks.. */ + typedef enum { + CDIO_DRIVE_CAP_READ_AUDIO = 0x00001, /**< drive can play CD audio */ + CDIO_DRIVE_CAP_READ_CD_DA = 0x00002, /**< drive can read CD-DA */ + CDIO_DRIVE_CAP_READ_CD_G = 0x00004, /**< drive can read CD+G */ + CDIO_DRIVE_CAP_READ_CD_R = 0x00008, /**< drive can read CD-R */ + CDIO_DRIVE_CAP_READ_CD_RW = 0x00010, /**< drive can read CD-RW */ + CDIO_DRIVE_CAP_READ_DVD_R = 0x00020, /**< drive can read DVD-R */ + CDIO_DRIVE_CAP_READ_DVD_PR = 0x00040, /**< drive can read DVD+R */ + CDIO_DRIVE_CAP_READ_DVD_RAM = 0x00080, /**< drive can read DVD-RAM */ + CDIO_DRIVE_CAP_READ_DVD_ROM = 0x00100, /**< drive can read DVD-ROM */ + CDIO_DRIVE_CAP_READ_DVD_RW = 0x00200, /**< drive can read DVD-RW */ + CDIO_DRIVE_CAP_READ_DVD_RPW = 0x00400, /**< drive can read DVD+RW */ + CDIO_DRIVE_CAP_READ_C2_ERRS = 0x00800, /**< has C2 error correction */ + CDIO_DRIVE_CAP_READ_MODE2_FORM1 = 0x01000, /**< can read mode 2 form 1 */ + CDIO_DRIVE_CAP_READ_MODE2_FORM2 = 0x02000, /**< can read mode 2 form 2 */ + CDIO_DRIVE_CAP_READ_MCN = 0x04000, /**< can read MCN */ + CDIO_DRIVE_CAP_READ_ISRC = 0x08000 /**< can read ISRC */ + } cdio_drive_cap_read_t; + + /** Writing masks.. */ + typedef enum { + CDIO_DRIVE_CAP_WRITE_CD_R = 0x00001, /**< drive can write CD-R */ + CDIO_DRIVE_CAP_WRITE_CD_RW = 0x00002, /**< drive can write CD-RW */ + CDIO_DRIVE_CAP_WRITE_DVD_R = 0x00004, /**< drive can write DVD-R */ + CDIO_DRIVE_CAP_WRITE_DVD_PR = 0x00008, /**< drive can write DVD+R */ + CDIO_DRIVE_CAP_WRITE_DVD_RAM = 0x00010, /**< drive can write DVD-RAM */ + CDIO_DRIVE_CAP_WRITE_DVD_RW = 0x00020, /**< drive can write DVD-RW */ + CDIO_DRIVE_CAP_WRITE_DVD_RPW = 0x00040, /**< drive can write DVD+RW */ + CDIO_DRIVE_CAP_WRITE_MT_RAINIER = 0x00080, /**< Mount Rainier */ + CDIO_DRIVE_CAP_WRITE_BURN_PROOF = 0x00100, /**< burn proof */ + CDIO_DRIVE_CAP_WRITE_CD = + (CDIO_DRIVE_CAP_WRITE_CD_R | CDIO_DRIVE_CAP_WRITE_CD_RW), + /**< Has some sort of CD writer ability */ + + CDIO_DRIVE_CAP_WRITE_DVD = + (CDIO_DRIVE_CAP_WRITE_DVD_R | CDIO_DRIVE_CAP_WRITE_DVD_PR + | CDIO_DRIVE_CAP_WRITE_DVD_RAM | CDIO_DRIVE_CAP_WRITE_DVD_RW + | CDIO_DRIVE_CAP_WRITE_DVD_RPW ), + /**< Has some sort of DVD writer ability */ + + CDIO_DRIVE_CAP_WRITE = + (CDIO_DRIVE_CAP_WRITE_CD | CDIO_DRIVE_CAP_WRITE_DVD) + /**< Has some sort of DVD or CD writing ability */ + } cdio_drive_cap_write_t; + +/** Size of fields returned by an INQUIRY command */ + typedef enum { + CDIO_MMC_HW_VENDOR_LEN = 8, /**< length of vendor field */ + CDIO_MMC_HW_MODEL_LEN = 16, /**< length of model field */ + CDIO_MMC_HW_REVISION_LEN = 4 /**< length of revision field */ + } cdio_mmc_hw_len_t; + + + /** \brief Structure to return CD vendor, model, and revision-level + strings obtained via the INQUIRY command */ + typedef struct cdio_hwinfo + { + char psz_vendor [CDIO_MMC_HW_VENDOR_LEN+1]; + char psz_model [CDIO_MMC_HW_MODEL_LEN+1]; + char psz_revision[CDIO_MMC_HW_REVISION_LEN+1]; + } cdio_hwinfo_t; + + + /** Flags specifying the category of device to open or is opened. */ + typedef enum { + CDIO_SRC_IS_DISK_IMAGE_MASK = 0x0001, /**< Read source is a CD image. */ + CDIO_SRC_IS_DEVICE_MASK = 0x0002, /**< Read source is a CD device. */ + CDIO_SRC_IS_SCSI_MASK = 0x0004, /**< Read source SCSI device. */ + CDIO_SRC_IS_NATIVE_MASK = 0x0008 + } cdio_src_category_mask_t; + + + /** + * The driver_id_t enumerations may be used to tag a specific driver + * that is opened or is desired to be opened. Note that this is + * different than what is available on a given host. + * + * Order should not be changed lightly because it breaks the ABI. + * One is not supposed to iterate over the values, but iterate over the + * cdio_drivers and cdio_device_drivers arrays. + * + * NOTE: IF YOU MODIFY ENUM MAKE SURE INITIALIZATION IN CDIO.C AGREES. + * + */ + typedef enum { + DRIVER_UNKNOWN, /**< Used as input when we don't care what kind + of driver to use. */ + DRIVER_AIX, /**< AIX driver */ + DRIVER_BSDI, /**< BSDI driver */ + DRIVER_FREEBSD, /**< FreeBSD driver - includes CAM and ioctl access */ + DRIVER_NETBSD, /**< NetBSD Driver. */ + DRIVER_LINUX, /**< GNU/Linux Driver */ + DRIVER_SOLARIS, /**< Sun Solaris Driver */ + DRIVER_OS2, /**< IBM OS/2 Driver */ + DRIVER_OSX, /**< Apple OSX Driver */ + DRIVER_WIN32, /**< Microsoft Windows Driver. Includes ASPI and + ioctl access. */ + DRIVER_CDRDAO, /**< cdrdao format CD image. This is listed + before BIN/CUE, to make the code prefer cdrdao + over BIN/CUE when both exist. */ + DRIVER_BINCUE, /**< CDRWIN BIN/CUE format CD image. This is + listed before NRG, to make the code prefer + BIN/CUE over NRG when both exist. */ + DRIVER_NRG, /**< Nero NRG format CD image. */ + DRIVER_DEVICE /**< Is really a set of the above; should come last */ + } driver_id_t; + + /** + A null-terminated (that is DRIVER_UNKNOWN-terminated) ordered (in + order of preference) array of drivers. + */ + extern const driver_id_t cdio_drivers[]; + + /** + A null-terminated (that is DRIVER_UNKNOWN-terminated) ordered (in + order of preference) array of device drivers. + */ + extern const driver_id_t cdio_device_drivers[]; + + /** + There will generally be only one hardware for a given + build/platform from the list above. You can use the variable + below to determine which you've got. If the build doesn't make an + hardware driver, then the value will be DRIVER_UNKNOWN. + */ + extern const driver_id_t cdio_os_driver; + + + /** + Those are deprecated; use cdio_drivers or cdio_device_drivers to + iterate over all drivers or only the device drivers. + Make sure what's listed for CDIO_MIN_DRIVER is the last + enumeration in driver_id_t. Since we have a bogus (but useful) 0th + entry above we don't have to add one. + */ +#define CDIO_MIN_DRIVER DRIVER_AIX +#define CDIO_MIN_DEVICE_DRIVER CDIO_MIN_DRIVER +#define CDIO_MAX_DRIVER DRIVER_NRG +#define CDIO_MAX_DEVICE_DRIVER DRIVER_WIN32 + + /** + The following are status codes for completion of a given cdio + operation. By design 0 is successful completion and -1 is error + completion. This is compatable with ioctl so those routines that + call ioctl can just pass the value the get back (cast as this + enum). Also, by using negative numbers for errors, the + enumeration values below can be used in places where a positive + value is expected when things complete successfully. For example, + get_blocksize returns the blocksize, but on error uses the error + codes below. So note that this enumeration is often cast to an + integer. C seems to tolerate this. + */ + typedef enum { + DRIVER_OP_SUCCESS = 0, /**< in cases where an int is + returned, like cdio_set_speed, + more the negative return codes are + for errors and the positive ones + for success. */ + DRIVER_OP_ERROR = -1, /**< operation returned an error */ + DRIVER_OP_UNSUPPORTED = -2, /**< returned when a particular driver + doesn't support a particular operation. + For example an image driver which doesn't + really "eject" a CD. + */ + DRIVER_OP_UNINIT = -3, /**< returned when a particular driver + hasn't been initialized or a null + pointer has been passed. + */ + DRIVER_OP_NOT_PERMITTED = -4, /**< Operation not permitted. + For example might be a permission + problem. + */ + DRIVER_OP_BAD_PARAMETER = -5, /**< Bad parameter passed */ + DRIVER_OP_BAD_POINTER = -6, /**< Bad pointer to memory area */ + DRIVER_OP_NO_DRIVER = -7, /**< Operation called on a driver + not available on this OS */ + DRIVER_OP_MMC_SENSE_DATA = -8, /**< MMC operation returned sense data, + but no other error above recorded. */ + } driver_return_code_t; + + /** + Close media tray in CD drive if there is a routine to do so. + + @param psz_drive the name of CD-ROM to be closed. If NULL, we will + use the default device. + @param p_driver_id is the driver to be used or that got used if + it was DRIVER_UNKNOWN or DRIVER_DEVICE; If this is NULL, we won't + report back the driver used. + */ + driver_return_code_t cdio_close_tray (const char *psz_drive, + /*in/out*/ driver_id_t *p_driver_id); + + /** + @param drc the return code you want interpreted. + @return the string information about drc + */ + const char *cdio_driver_errmsg(driver_return_code_t drc); + + /** + Eject media in CD drive if there is a routine to do so. + + @param p_cdio the CD object to be acted upon. + If the CD is ejected *p_cdio is free'd and p_cdio set to NULL. + */ + driver_return_code_t cdio_eject_media (CdIo_t **p_cdio); + + /** + Eject media in CD drive if there is a routine to do so. + + @param psz_drive the name of the device to be acted upon. + If NULL is given as the drive, we'll use the default driver device. + */ + driver_return_code_t cdio_eject_media_drive (const char *psz_drive); + + /** + Free device list returned by cdio_get_devices or + cdio_get_devices_with_cap. + + @param device_list list returned by cdio_get_devices or + cdio_get_devices_with_cap + + @see cdio_get_devices, cdio_get_devices_with_cap + + */ + void cdio_free_device_list (char * device_list[]); + + /** + Get the default CD device. + if p_cdio is NULL (we haven't initialized a specific device driver), + then find a suitable one and return the default device for that. + + @param p_cdio the CD object queried + @return a string containing the default CD device or NULL is + if we couldn't get a default device. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + char * cdio_get_default_device (const CdIo_t *p_cdio); + + /** + Return a string containing the default CD device if none is specified. + if p_driver_id is DRIVER_UNKNOWN or DRIVER_DEVICE + then find a suitable one set the default device for that. + + NULL is returned if we couldn't get a default device. + */ + char * cdio_get_default_device_driver (/*in/out*/ driver_id_t *p_driver_id); + + /** Return an array of device names. If you want a specific + devices for a driver, give that device. If you want hardware + devices, give DRIVER_DEVICE and if you want all possible devices, + image drivers and hardware drivers give DRIVER_UNKNOWN. + + NULL is returned if we couldn't return a list of devices. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + char ** cdio_get_devices (driver_id_t driver_id); + + /** + Get an array of device names in search_devices that have at least + the capabilities listed by the capabities parameter. If + search_devices is NULL, then we'll search all possible CD drives. + + Capabilities have two parts to them, a "filesystem" part and an + "analysis" part. + + The filesystem part is mutually exclusive. For example either the + filesystem is at most one of the High-Sierra, UFS, or HFS, + ISO9660, fileystems. Valid combinations of say HFS and ISO9660 + are specified as a separate "filesystem". + + Capabilities on the other hand are not mutually exclusive. For + example a filesystem may have none, either, or both of the XA or + Rock-Ridge extension properties. + + If "b_any" is set false then every capability listed in the + analysis portion of capabilities (i.e. not the basic filesystem) + must be satisified. If no analysis capabilities are specified, + that's a match. + + If "b_any" is set true, then if any of the analysis capabilities + matches, we call that a success. + + In either case, in the filesystem portion different filesystem + either specify 0 to match any filesystem or the specific + filesystem type. + + To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL. + + @return the array of device names or NULL if we couldn't get a + default device. It is also possible to return a non NULL but + after dereferencing the the value is NULL. This also means nothing + was found. + */ + char ** cdio_get_devices_with_cap (/*in*/ char *ppsz_search_devices[], + cdio_fs_anal_t capabilities, bool b_any); + + /** + Like cdio_get_devices_with_cap but we return the driver we found + as well. This is because often one wants to search for kind of drive + and then *open* it afterwards. Giving the driver back facilitates this, + and speeds things up for libcdio as well. + */ + char ** cdio_get_devices_with_cap_ret (/*in*/ char* ppsz_search_devices[], + cdio_fs_anal_t capabilities, + bool b_any, + /*out*/ driver_id_t *p_driver_id); + + /** + Like cdio_get_devices, but we may change the p_driver_id if we + were given DRIVER_DEVICE or DRIVER_UNKNOWN. This is because often + one wants to get a drive name and then *open* it + afterwards. Giving the driver back facilitates this, and speeds + things up for libcdio as well. + */ + + char ** cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id); + + /** + Get the what kind of device we've got. + + @param p_cdio the CD object queried + @param p_read_cap pointer to return read capabilities + @param p_write_cap pointer to return write capabilities + @param p_misc_cap pointer to return miscellaneous other capabilities + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it. In this situation capabilities will show up as + NULL even though there isa hardware CD-ROM. + */ + void cdio_get_drive_cap (const CdIo_t *p_cdio, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); + + /** + Get the drive capabilities for a specified device. + + Return a list of device capabilities. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it. In this situation capabilities will show up as + NULL even though there isa hardware CD-ROM. + */ + void cdio_get_drive_cap_dev (const char *device, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); + + /** + Get a string containing the name of the driver in use. + + @return a string with driver name or NULL if CdIo_t is NULL (we + haven't initialized a specific device. + */ + const char * cdio_get_driver_name (const CdIo_t *p_cdio); + + /** + Get the driver id. + if CdIo_t is NULL (we haven't initialized a specific device driver), + then return DRIVER_UNKNOWN. + + @return the driver id.. + */ + driver_id_t cdio_get_driver_id (const CdIo_t *p_cdio); + + /** + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. + */ + bool cdio_get_hwinfo ( const CdIo_t *p_cdio, + /*out*/ cdio_hwinfo_t *p_hw_info ); + + + /** + Get the LSN of the first track of the last session of + on the CD. + + @param p_cdio the CD object to be acted upon. + @param i_last_session pointer to the session number to be returned. + */ + driver_return_code_t cdio_get_last_session (CdIo_t *p_cdio, + /*out*/ lsn_t *i_last_session); + + /** + Find out if media has changed since the last call. + @param p_cdio the CD object to be acted upon. + @return 1 if media has changed since last call, 0 if not. Error + return codes are the same as driver_return_code_t + */ + int cdio_get_media_changed(CdIo_t *p_cdio); + + /** True if CD-ROM understand ATAPI commands. */ + bool_3way_t cdio_have_atapi (CdIo_t *p_cdio); + + /** Like cdio_have_xxx but uses an enumeration instead. */ + bool cdio_have_driver (driver_id_t driver_id); + + /** + Free any resources associated with p_cdio. Call this when done + using p_cdio and using CD reading/control operations. + + @param p_cdio the CD object to eliminated. + */ + void cdio_destroy (CdIo_t *p_cdio); + + /** + Get a string decribing driver_id. + + @param driver_id the driver you want the description for + @return a string of driver description + */ + const char *cdio_driver_describe (driver_id_t driver_id); + + /** + Sets up to read from place specified by psz_source and + driver_id. This or cdio_open_* should be called before using any + other routine, except cdio_init or any routine that accesses the + CD-ROM drive by name. cdio_open will call cdio_init, if that + hasn't been done previously. + + @return the cdio object or NULL on error or no device. If NULL + is given as the source, we'll use the default driver device. + */ + CdIo_t * cdio_open (const char *psz_source, driver_id_t driver_id); + + /** + Sets up to read from place specified by psz_source, driver_id and + access mode. This or cdio_open* should be called before using any + other routine, except cdio_init or any routine that accesses the + CD-ROM drive by name. This will call cdio_init, if that hasn't + been done previously. + + If NULL is given as the source, we'll use the default driver device. + + @return the cdio object or NULL on error or no device. + */ + CdIo_t * cdio_open_am (const char *psz_source, + driver_id_t driver_id, const char *psz_access_mode); + + /** + Set up BIN/CUE CD disk-image for reading. Source is the .bin or + .cue file + + @return the cdio object or NULL on error or no device. + */ + CdIo_t * cdio_open_bincue (const char *psz_cue_name); + + /** + Set up BIN/CUE CD disk-image for reading. Source is the .bin or + .cue file + + @return the cdio object or NULL on error or no device.. + */ + CdIo_t * cdio_open_am_bincue (const char *psz_cue_name, + const char *psz_access_mode); + + /** + Set up cdrdao CD disk-image for reading. Source is the .toc file + + @return the cdio object or NULL on error or no device. + */ + CdIo_t * cdio_open_cdrdao (const char *psz_toc_name); + + /** + Set up cdrdao CD disk-image for reading. Source is the .toc file + + @return the cdio object or NULL on error or no device.. + */ + CdIo_t * cdio_open_am_cdrdao (const char *psz_toc_name, + const char *psz_access_mode); + + /** + Return a string containing the default CUE file that would + be used when none is specified. + + @return the cdio object or NULL on error or no device. + */ + char * cdio_get_default_device_bincue(void); + + char **cdio_get_devices_bincue(void); + + /** + @return string containing the default CUE file that would be + used when none is specified. NULL is returned on error or there + is no device. + */ + char * cdio_get_default_device_cdrdao(void); + + char **cdio_get_devices_cdrdao(void); + + /** + Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. + */ + CdIo_t * cdio_open_cd (const char *device_name); + + /** + Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. + */ + CdIo_t * cdio_open_am_cd (const char *psz_device, + const char *psz_access_mode); + + /** + CDRWIN BIN/CUE CD disc-image routines. Source is the .cue file + + @return the cdio object for subsequent operations. + NULL on error. + */ + CdIo_t * cdio_open_cue (const char *cue_name); + + /** + Set up CD-ROM for reading using the AIX driver. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no AIX driver. + + @see cdio_open + */ + CdIo_t * cdio_open_am_aix (const char *psz_source, + const char *psz_access_mode); + + /** + Set up CD-ROM for reading using the AIX driver. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no AIX driver. + + @see cdio_open + */ + CdIo_t * cdio_open_aix (const char *psz_source); + + /** + Return a string containing the default device name that the AIX + driver would use when none is specified. + + @return the cdio object for subsequent operations. + NULL on error or there is no AIX driver. + + @see cdio_open_cd, cdio_open + */ + char * cdio_get_default_device_aix(void); + + /** + Return a list of all of the CD-ROM devices that the AIX driver + can find. + + In some situations of drivers or OS's we can't find a CD device + if there is no media in it and it is possible for this routine to + return NULL even though there may be a hardware CD-ROM. + */ + char **cdio_get_devices_aix(void); + + /** + Set up CD-ROM for reading using the BSDI driver. The device_name + is the some sort of device name. + + @param psz_source the name of the device to open + @return the cdio object for subsequent operations. + NULL on error or there is no BSDI driver. + + @see cdio_open + */ + CdIo_t * cdio_open_bsdi (const char *psz_source); + + /** + Set up CD-ROM for reading using the BSDI driver. The device_name + is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no BSDI driver. + + @see cdio_open + */ + CdIo_t * cdio_open_am_bsdi (const char *psz_source, + const char *psz_access_mode); + + /** + Return a string containing the default device name that the BSDI + driver would use when none is specified. + + @return the cdio object for subsequent operations. + NULL on error or there is no BSDI driver. + + @see cdio_open_cd, cdio_open + */ + char * cdio_get_default_device_bsdi(void); + + /** + Return a list of all of the CD-ROM devices that the BSDI driver + can find. + + In some situations of drivers or OS's we can't find a CD device + if there is no media in it and it is possible for this routine to + return NULL even though there may be a hardware CD-ROM. + */ + char **cdio_get_devices_bsdi(void); + + /** + Set up CD-ROM for reading using the FreeBSD driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no FreeBSD driver. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_freebsd (const char *paz_psz_source); + + /** + Set up CD-ROM for reading using the FreeBSD driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no FreeBSD driver. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_am_freebsd (const char *psz_source, + const char *psz_access_mode); + + /** + Return a string containing the default device name that the + FreeBSD driver would use when none is specified. + + NULL is returned on error or there is no CD-ROM device. + */ + char * cdio_get_default_device_freebsd(void); + + /** + Return a list of all of the CD-ROM devices that the FreeBSD + driver can find. + */ + char **cdio_get_devices_freebsd(void); + + /** + Set up CD-ROM for reading using the GNU/Linux driver. The + device_name is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no GNU/Linux driver. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + CdIo_t * cdio_open_linux (const char *psz_source); + + /** + Set up CD-ROM for reading using the GNU/Linux driver. The + device_name is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no GNU/Linux driver. + */ + CdIo_t * cdio_open_am_linux (const char *psz_source, + const char *access_mode); + + /** + Return a string containing the default device name that the + GNU/Linux driver would use when none is specified. A scan is made + for CD-ROM drives with CDs in them. + + NULL is returned on error or there is no CD-ROM device. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open + */ + char * cdio_get_default_device_linux(void); + + /** + Return a list of all of the CD-ROM devices that the GNU/Linux + driver can find. + */ + char **cdio_get_devices_linux(void); + + /** + Set up CD-ROM for reading using the Sun Solaris driver. The + device_name is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no Solaris driver. + */ + CdIo_t * cdio_open_solaris (const char *psz_source); + + /** + Set up CD-ROM for reading using the Sun Solaris driver. The + device_name is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no Solaris driver. + */ + CdIo_t * cdio_open_am_solaris (const char *psz_source, + const char *psz_access_mode); + + /** + Return a string containing the default device name that the + Solaris driver would use when none is specified. A scan is made + for CD-ROM drives with CDs in them. + + NULL is returned on error or there is no CD-ROM device. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open + */ + char * cdio_get_default_device_solaris(void); + + /** + Return a list of all of the CD-ROM devices that the Solaris + driver can find. + */ + char **cdio_get_devices_solaris(void); + + /** + Set up CD-ROM for reading using the Apple OSX driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no OSX driver. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_osx (const char *psz_source); + + /** + Set up CD-ROM for reading using the Apple OSX driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no OSX driver. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_am_osx (const char *psz_source, + const char *psz_access_mode); + + /** + Return a string containing the default device name that the OSX + driver would use when none is specified. A scan is made for + CD-ROM drives with CDs in them. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + char * cdio_get_default_device_osx(void); + + /** + Return a list of all of the CD-ROM devices that the OSX driver + can find. + */ + char **cdio_get_devices_osx(void); + + /** + Set up CD-ROM for reading using the Microsoft Windows driver. The + device_name is the some sort of device name. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + CdIo_t * cdio_open_win32 (const char *psz_source); + + /** + Set up CD-ROM for reading using the Microsoft Windows driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no Microsof Windows driver. + */ + CdIo_t * cdio_open_am_win32 (const char *psz_source, + const char *psz_access_mode); + + /** + Return a string containing the default device name that the + Win32 driver would use when none is specified. A scan is made + for CD-ROM drives with CDs in them. + + In some situations of drivers or OS's we can't find a CD device + if there is no media in it and it is possible for this routine to + return NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open + */ + char * cdio_get_default_device_win32(void); + + char **cdio_get_devices_win32(void); + + /** + Set up CD-ROM for reading using the IBM OS/2 driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no OS/2 driver. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_os2 (const char *psz_source); + + /** + Set up CD-ROM for reading using the IBM OS/2 driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no OS/2 driver. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_am_os2 (const char *psz_source, + const char *psz_access_mode); + + /** + Return a string containing the default device name that the OS/2 + driver would use when none is specified. A scan is made for + CD-ROM drives with CDs in them. + + In some situations of drivers or OS's we can't find a CD device + if there is no media in it and it is possible for this routine to + return NULL even though there may be a hardware CD-ROM. + */ + char * cdio_get_default_device_os2(void); + + /** +Return a list of all of the CD-ROM devices that the OS/2 driver + can find. + */ + char **cdio_get_devices_os2(void); + + /** + Set up CD-ROM for reading using the Nero driver. The device_name + is the some sort of device name. + + @return true on success; NULL on error or there is no Nero driver. + */ + CdIo_t * cdio_open_nrg (const char *psz_source); + + /** + Set up CD-ROM for reading using the Nero driver. The device_name + is the some sort of device name. + + @return true on success; NULL on error or there is no Nero driver. + */ + CdIo_t * cdio_open_am_nrg (const char *psz_source, + const char *psz_access_mode); + + /** + Get a string containing the default device name that the NRG + driver would use when none is specified. A scan is made for NRG + disk images in the current directory. + + @return string containing the default device. NULL on error or + there is no CD-ROM device. + */ + char * cdio_get_default_device_nrg(void); + + char **cdio_get_devices_nrg(void); + + /** + + Determine if bin_name is the bin file part of a CDRWIN CD disk image. + + @param bin_name location of presumed CDRWIN bin image file. + @return the corresponding CUE file if bin_name is a BIN file or + NULL if not a BIN file. + */ + char *cdio_is_binfile(const char *bin_name); + + /** + Determine if cue_name is the cue sheet for a CDRWIN CD disk image. + + @return corresponding BIN file if cue_name is a CDRWIN cue file or + NULL if not a CUE file. + */ + char *cdio_is_cuefile(const char *cue_name); + + /** + Determine if psg_nrg is a Nero CD disc image. + + @param psz_nrg location of presumed NRG image file. + @return true if psz_nrg is a Nero NRG image or false + if not a NRG image. + */ + bool cdio_is_nrg(const char *psz_nrg); + + /** + Determine if psz_toc is a TOC file for a cdrdao CD disc image. + + @param psz_toc location of presumed TOC image file. + @return true if toc_name is a cdrdao TOC file or false + if not a TOC file. + */ + bool cdio_is_tocfile(const char *psz_toc); + + /** + Determine if psz_source refers to a real hardware CD-ROM. + + @param psz_source location name of object + @param driver_id driver for reading object. Use DRIVER_UNKNOWN if you + don't know what driver to use. + @return true if psz_source is a device; If false is returned we + could have a CD disk image. + */ + bool cdio_is_device(const char *psz_source, driver_id_t driver_id); + + /** + Set the blocksize for subsequent reads. + */ + driver_return_code_t cdio_set_blocksize ( const CdIo_t *p_cdio, + int i_blocksize ); + + /** + Set the drive speed. + + @param p_cdio CD structure set by cdio_open(). + + @param i_drive_speed speed in CD-ROM speed units. Note this not + Kbs as would be used in the MMC spec or in + mmc_set_speed(). To convert CD-ROM speed + units to Kbs, multiply the number by 176 (for + raw data) and by 150 (for filesystem + data). On many CD-ROM drives, specifying a + value too large will result in using the + fastest speed. + + @see mmc_set_speed and mmc_set_drive_speed + */ + driver_return_code_t cdio_set_speed ( const CdIo_t *p_cdio, + int i_drive_speed ); + + /** + Get the value associatied with key. + + @param p_cdio the CD object queried + @param key the key to retrieve + @return the value associatd with "key" or NULL if p_cdio is NULL + or "key" does not exist. + */ + const char * cdio_get_arg (const CdIo_t *p_cdio, const char key[]); + + /** + Set the arg "key" with "value" in "p_cdio". + + @param p_cdio the CD object to set + @param key the key to set + @param value the value to assocaiate with key + */ + driver_return_code_t cdio_set_arg (CdIo_t *p_cdio, const char key[], + const char value[]); + + /** + Initialize CD Reading and control routines. Should be called first. + */ + bool cdio_init(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** + The below variables are trickery to force the above enum symbol + values to be recorded in debug symbol tables. They are used to + allow one to refer to the enumeration value names in the typedefs + above in a debugger and debugger expressions. */ +extern cdio_drive_cap_misc_t debug_cdio_drive_cap_misc; +extern cdio_drive_cap_read_t debug_cdio_drive_cap_read_t; +extern cdio_drive_cap_write_t debug_drive_cap_write_t; +extern cdio_mmc_hw_len_t debug_cdio_mmc_hw_len; +extern cdio_src_category_mask_t debug_cdio_src_category_mask; + +#endif /* __CDIO_DEVICE_H__ */ diff --git a/src/libcdio/cdio/disc.h b/src/libcdio/cdio/disc.h new file mode 100644 index 00000000..638c0320 --- /dev/null +++ b/src/libcdio/cdio/disc.h @@ -0,0 +1,136 @@ +/* -*- c -*- + + Copyright (C) 2004, 2005, 2006, 2008, 2010 Rocky Bernstein + + + 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 3 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, see . +*/ + +/** + \file disc.h + \brief The top-level header for disc-related libcdio calls. + */ +#ifndef __CDIO_DISC_H__ +#define __CDIO_DISC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /** + disc modes. The first combined from MMC-5 6.33.3.13 (Send + CUESHEET), "DVD Book" from MMC-5 Table 400, page 419. and + GNU/Linux /usr/include/linux/cdrom.h and we've added DVD. + */ + typedef enum { + CDIO_DISC_MODE_CD_DA, /**< CD-DA */ + CDIO_DISC_MODE_CD_DATA, /**< CD-ROM form 1 */ + CDIO_DISC_MODE_CD_XA, /**< CD-ROM XA form2 */ + CDIO_DISC_MODE_CD_MIXED, /**< Some combo of above. */ + CDIO_DISC_MODE_DVD_ROM, /**< DVD ROM (e.g. movies) */ + CDIO_DISC_MODE_DVD_RAM, /**< DVD-RAM */ + CDIO_DISC_MODE_DVD_R, /**< DVD-R */ + CDIO_DISC_MODE_DVD_RW, /**< DVD-RW */ + CDIO_DISC_MODE_HD_DVD_ROM, /**< HD DVD-ROM */ + CDIO_DISC_MODE_HD_DVD_RAM, /**< HD DVD-RAM */ + CDIO_DISC_MODE_HD_DVD_R, /**< HD DVD-R */ + CDIO_DISC_MODE_DVD_PR, /**< DVD+R */ + CDIO_DISC_MODE_DVD_PRW, /**< DVD+RW */ + CDIO_DISC_MODE_DVD_PRW_DL, /**< DVD+RW DL */ + CDIO_DISC_MODE_DVD_PR_DL, /**< DVD+R DL */ + CDIO_DISC_MODE_DVD_OTHER, /**< Unknown/unclassified DVD type */ + CDIO_DISC_MODE_NO_INFO, + CDIO_DISC_MODE_ERROR, + CDIO_DISC_MODE_CD_I /**< CD-i. */ + } discmode_t; + + extern const char *discmode2str[]; + /** + Get binary CD-Text information for a CdIo_t object. + + @param p_cdio the CD object that may contain CD-Text information. + @return malloc'd pointer to raw CD-Text data as stored on the disc + or NULL if p_cdio is NULL or CD-Text information does not exist. + Return value should be freed when done with it and not NULL. + */ + uint8_t * cdio_get_cdtext_raw (CdIo_t *p_cdio); + + /** + Get CD-Text information for a CdIo_t object. + + @param p_cdio the CD object that may contain CD-Text information. + @return the CD-Text object or NULL if p_cdio is NULL + or CD-Text information does not exist. + */ + cdtext_t *cdio_get_cdtext (CdIo_t *p_cdio); + + /** + Get disc mode - the kind of CD (CD-DA, CD-ROM mode 1, CD-MIXED, etc. + that we've got. The notion of "CD" is extended a little to include + DVD's. + */ + discmode_t cdio_get_discmode (CdIo_t *p_cdio); + + /** + Get the lsn of the end of the CD + + @return the lsn. On error 0 or CDIO_INVALD_LSN. + */ + lsn_t cdio_get_disc_last_lsn(const CdIo_t *p_cdio); + + /** + Return the Joliet level recognized for p_cdio. + */ + uint8_t cdio_get_joliet_level(const CdIo_t *p_cdio); + + /** + Get the media catalog number (MCN) from the CD. + + @return the media catalog number or NULL if there is none or we + don't have the ability to get it. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. + + */ + char * cdio_get_mcn (const CdIo_t *p_cdio); + + /** + Get the number of tracks on the CD. + + @return the number of tracks, or CDIO_INVALID_TRACK if there is + an error. + */ + track_t cdio_get_num_tracks (const CdIo_t *p_cdio); + + /** + Return true if discmode is some sort of CD. + */ + bool cdio_is_discmode_cdrom (discmode_t discmode); + + /** + Return true if discmode is some sort of DVD. + */ + bool cdio_is_discmode_dvd (discmode_t discmode); + + /** + cdio_stat_size is deprecated. @see cdio_get_disc_last_lsn + */ +#define cdio_stat_size cdio_get_disc_last_lsn + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_DISC_H__ */ diff --git a/src/libcdio/cdio/ds.h b/src/libcdio/cdio/ds.h new file mode 100644 index 00000000..447e30df --- /dev/null +++ b/src/libcdio/cdio/ds.h @@ -0,0 +1,98 @@ +/* + $Id: ds.h,v 1.5 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2005, 2008 Rocky Bernstein + Copyright (C) 2000, 2004 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +/** \file ds.h + * \brief The top-level header for list-related data structures. + + Note: this header will is slated to get removed and libcdio will use + glib.h routines instead. +*/ + + +#ifndef __CDIO_DS_H__ +#define __CDIO_DS_H__ + +#include + +/** opaque types... */ +typedef struct _CdioList CdioList_t; +typedef struct _CdioListNode CdioListNode_t; + +typedef int (*_cdio_list_cmp_func_t) (void *p_data1, void *p_data2); +typedef int (*_cdio_list_iterfunc_t) (void *p_data, void *p_user_data); + +/** The below are given compatibility with old code. Please use + the above type names, not these. */ +#define CdioList CdioList_t +#define CdioListNode CdioListNode_t +#define _cdio_list_cmp_func _cdio_list_cmp_func_t +#define _cdio_list_iterfunc _cdio_list_iterfunc_t + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** methods */ +CdioList_t *_cdio_list_new (void); + +void _cdio_list_free (CdioList_t *p_list, int free_data); + +unsigned _cdio_list_length (const CdioList_t *list); + +void _cdio_list_prepend (CdioList_t *p_list, void *p_data); + +void _cdio_list_append (CdioList_t *p_list, void *p_data); + +void _cdio_list_foreach (CdioList_t *p_list, _cdio_list_iterfunc_t func, + void *p_user_data); + +CdioListNode_t *_cdio_list_find (CdioList_t *p_list, + _cdio_list_iterfunc_t cmp_func, + void *p_user_data); + +#define _CDIO_LIST_FOREACH(node, list) \ + for (node = _cdio_list_begin (list); node; node = _cdio_list_node_next (node)) + +/** node operations */ + +CdioListNode_t *_cdio_list_begin (const CdioList_t *p_list); + +CdioListNode_t *_cdio_list_end (CdioList_t *p_list); + +CdioListNode_t *_cdio_list_node_next (CdioListNode_t *p_node); + +void _cdio_list_node_free (CdioListNode_t *p_node, int i_free_data); + +void *_cdio_list_node_data (CdioListNode_t *p_node); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_DS_H__ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ + diff --git a/src/libcdio/cdio/dvd.h b/src/libcdio/cdio/dvd.h new file mode 100644 index 00000000..8bb83e12 --- /dev/null +++ b/src/libcdio/cdio/dvd.h @@ -0,0 +1,127 @@ +/* + Copyright (C) 2004, 2010 Rocky Bernstein + Modeled after GNU/Linux definitions in linux/cdrom.h + + 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 3 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, see . +*/ + +/** + \file dvd.h + \brief Definitions for DVD access. + + The documents we make use of are described Multi-Media Commands + (MMC). This document generally has a numeric level number + appended. For example MMC-5 refers to ``Multi-Media Commands - 5' + which is the current version in 2010. + +*/ + +#ifndef __CDIO_DVD_H__ +#define __CDIO_DVD_H__ + +#include + +/** + Values used in a READ DVD STRUCTURE + */ + +#define CDIO_DVD_STRUCT_PHYSICAL 0x00 +#define CDIO_DVD_STRUCT_COPYRIGHT 0x01 +#define CDIO_DVD_STRUCT_DISCKEY 0x02 +#define CDIO_DVD_STRUCT_BCA 0x03 +#define CDIO_DVD_STRUCT_MANUFACT 0x04 + +/** + Media definitions for "DVD Book" from MMC-5 Table 400, page 419. +*/ +#define CDIO_DVD_BOOK_DVD_ROM 0x0 /**< DVD-ROM */ +#define CDIO_DVD_BOOK_DVD_RAM 0x1 /**< DVD-RAM */ +#define CDIO_DVD_BOOK_DVD_R 0x2 /**< DVD-R */ +#define CDIO_DVD_BOOK_DVD_RW 0x3 /**< DVD-RW */ +#define CDIO_DVD_BOOK_HD_DVD_ROM 0x4 /**< HD DVD-ROM */ +#define CDIO_DVD_BOOK_HD_DVD_RAM 0x5 /**< HD DVD-RAM */ +#define CDIO_DVD_BOOK_HD_DVD_R 0x6 /**< HD DVD-R */ +#define CDIO_DVD_BOOK_DVD_PRW 0x9 /**< DVD+RW */ +#define CDIO_DVD_BOOK_DVD_PR 0xa /**< DVD+R */ +#define CDIO_DVD_BOOK_DVD_PRW_DL 0xd /**< DVD+RW DL */ +#define CDIO_DVD_BOOK_DVD_PR_DL 0xe /**< DVD+R DL */ + +typedef struct cdio_dvd_layer { + unsigned int book_version : 4; + unsigned int book_type : 4; + unsigned int min_rate : 4; + unsigned int disc_size : 4; + unsigned int layer_type : 4; + unsigned int track_path : 1; + unsigned int nlayers : 2; + unsigned int track_density : 4; + unsigned int linear_density : 4; + unsigned int bca : 1; + uint32_t start_sector; + uint32_t end_sector; + uint32_t end_sector_l0; +} cdio_dvd_layer_t; + +/** + Maximum number of layers in a DVD. + */ +#define CDIO_DVD_MAX_LAYERS 4 + +typedef struct cdio_dvd_physical { + uint8_t type; + uint8_t layer_num; + cdio_dvd_layer_t layer[CDIO_DVD_MAX_LAYERS]; +} cdio_dvd_physical_t; + +typedef struct cdio_dvd_copyright { + uint8_t type; + + uint8_t layer_num; + uint8_t cpst; + uint8_t rmi; +} cdio_dvd_copyright_t; + +typedef struct cdio_dvd_disckey { + uint8_t type; + + unsigned agid : 2; + uint8_t value[2048]; +} cdio_dvd_disckey_t; + +typedef struct cdio_dvd_bca { + uint8_t type; + + int len; + uint8_t value[188]; +} cdio_dvd_bca_t; + +typedef struct cdio_dvd_manufact { + uint8_t type; + + uint8_t layer_num; + int len; + uint8_t value[2048]; +} cdio_dvd_manufact_t; + +typedef union { + uint8_t type; + + cdio_dvd_physical_t physical; + cdio_dvd_copyright_t copyright; + cdio_dvd_disckey_t disckey; + cdio_dvd_bca_t bca; + cdio_dvd_manufact_t manufact; +} cdio_dvd_struct_t; + +#endif /* __CDIO_DVD_H__ */ diff --git a/src/libcdio/cdio/ecma_167.h b/src/libcdio/cdio/ecma_167.h new file mode 100644 index 00000000..b97cba79 --- /dev/null +++ b/src/libcdio/cdio/ecma_167.h @@ -0,0 +1,1018 @@ +/* + Copyright (c) 2005, 2006, 2008 Rocky Bernstein + Copyright (c) 2001-2002 Ben Fennema + + 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 3 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, see . +*/ +/* + * Some portions taken from FreeBSD ecma167-udf.h which states: + * Copyright (c) 2001, 2002 Scott Long + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*! + * \file ecma_167.h + * + * \brief Definitions based on ECMA-167 3rd edition (June 1997) + * See http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-167.pdf +*/ + +#ifndef _ECMA_167_H +#define _ECMA_167_H 1 + +#include + +/** + Imagine the below enum values as \#define'd values rather than + distinct values of an enum. +*/ +typedef enum { + VSD_STD_ID_SIZE = 5, /** Volume Structure Descriptor (ECMA 167r3 + 2/9.1) */ + UDF_REGID_ID_SIZE = 23, /**< See identifier (ECMA 167r3 1/7.4) */ + UDF_VOLID_SIZE = 32, + UDF_FID_SIZE = 38, + UDF_VOLSET_ID_SIZE = 128 +} ecma_167_enum1_t ; + +/** Tag Identifier (ECMA 167r3 3/7.2.1) */ + +typedef enum { + TAGID_PRI_VOL = 0x0001, + TAGID_ANCHOR = 0x0002, + TAGID_VOL = 0x0003, + TAGID_IMP_VOL = 0x0004, + TAGID_PARTITION = 0x0005, + TAGID_LOGVOL = 0x0006, + TAGID_UNALLOC_SPACE = 0x0007, + TAGID_TERM = 0x0008, + TAGID_LOGVOL_INTEGRITY = 0x0009, + TAGID_FSD = 0x0100, + TAGID_FID = 0x0101, + TAGID_AED = 0x0102, + TAGID_IE = 0x0103, + TAGID_TE = 0x0104, + TAGID_FILE_ENTRY = 0x0105, + TAGID_EAHD = 0x0106, + TAGID_USE = 0x0107, + TAGID_SBD = 0x0108, + TAGID_PIE = 0x0109, + TAGID_EFE = 0x010A, +} tag_id_t ; + +/** Character Set Type (ECMA 167r3 1/7.2.1.1) */ +typedef enum { + CHARSPEC_TYPE_CS0 = 0x00, /**< Section 1/7.2.2 */ + CHARSPEC_TYPE_CS1 = 0x01, /**< Section 1/7.2.3 */ + CHARSPEC_TYPE_CS2 = 0x02, /**< Section 1/7.2.4 */ + CHARSPEC_TYPE_CS3 = 0x03, /**< Section 1/7.2.5 */ + CHARSPEC_TYPE_CS4 = 0x04, /**< Section 1/7.2.6 */ + CHARSPEC_TYPE_CS5 = 0x05, /**< Section 1/7.2.7 */ + CHARSPEC_TYPE_CS6 = 0x06, /**< Section 1/7.2.8 */ + CHARSPEC_TYPE_CS7 = 0x07, /**< Section 1/7.2.9 */ + + CHARSPEC_TYPE_CS8 = 0x08, /**< Section 1/7.2.10 */ +} udf_charspec_enum_t; + +typedef uint8_t udf_Uint8_t; /*! Section 1/7/1.1 */ +typedef uint16_t udf_Uint16_t; /*! Section 1/7.1.3 */ +typedef uint32_t udf_Uint32_t; /*! Section 1/7.1.5 */ +typedef uint64_t udf_Uint64_t; /*! Section 1/7.1.7 */ +typedef char udf_dstring; /*! Section 1/7.1.12 */ + +#define UDF_LENGTH_MASK 0x3fffffff + +PRAGMA_BEGIN_PACKED + +/** Character set specification (ECMA 167r3 1/7.2.1) */ +struct udf_charspec_s +{ + udf_Uint8_t charset_type; + udf_Uint8_t charset_info[63]; +} GNUC_PACKED; + +typedef struct udf_charspec_s udf_charspec_t; + +/** Timestamp (ECMA 167r3 1/7.3) */ +struct udf_timestamp_s +{ + udf_Uint16_t type_tz; + udf_Uint16_t year; + udf_Uint8_t month; + udf_Uint8_t day; + udf_Uint8_t hour; + udf_Uint8_t minute; + udf_Uint8_t second; + udf_Uint8_t centiseconds; + udf_Uint8_t hundreds_of_microseconds; + udf_Uint8_t microseconds; +} GNUC_PACKED; + +typedef struct udf_timestamp_s udf_timestamp_t; + +/** Type and Time Zone (ECMA 167r3 1/7.3.1) + + Imagine the below enum values as \#define'd values rather than + distinct values of an enum. +*/ +typedef enum { + TIMESTAMP_TYPE_CUT = 0x0000, + TIMESTAMP_TYPE_LOCAL = 0x1000, + TIMESTAMP_TYPE_AGREEMENT = 0x2000, + TIMESTAMP_TYPE_MASK = 0xF000, + TIMESTAMP_TIMEZONE_MASK = 0x0FFF, +} ecma_167_timezone_enum_t ; + + +#define TIMESTAMP_TYPE_MASK 0xF000 +#define TIMESTAMP_TYPE_CUT 0x0000 +#define TIMESTAMP_TYPE_LOCAL 0x1000 +#define TIMESTAMP_TYPE_AGREEMENT 0x2000 +#define TIMESTAMP_TIMEZONE_MASK 0x0FFF + +struct udf_id_suffix_s +{ + udf_Uint16_t udf_revision; + udf_Uint8_t os_class; + udf_Uint8_t os_identifier; + udf_Uint8_t reserved[4]; +} GNUC_PACKED; + +typedef struct udf_id_suffix_s udf_id_suffix_t; + +/** Entity identifier (ECMA 167r3 1/7.4) */ +struct udf_regid_s +{ + udf_Uint8_t flags; + udf_Uint8_t id[UDF_REGID_ID_SIZE]; + udf_id_suffix_t id_suffix; +} GNUC_PACKED; + +typedef struct udf_regid_s udf_regid_t; + +/** Flags (ECMA 167r3 1/7.4.1) */ +#define ENTITYID_FLAGS_DIRTY 0x00 +#define ENTITYID_FLAGS_PROTECTED 0x01 + +/** Volume Structure Descriptor (ECMA 167r3 2/9.1) */ +struct vol_struct_desc_s +{ + udf_Uint8_t struct_type; + udf_Uint8_t std_id[VSD_STD_ID_SIZE]; + udf_Uint8_t struct_version; + udf_Uint8_t struct_data[2041]; +} GNUC_PACKED; + +/** Standard Identifier (EMCA 167r2 2/9.1.2) */ +#define VSD_STD_ID_NSR02 "NSR02" /* (3/9.1) */ + +/** Standard Identifier (ECMA 167r3 2/9.1.2) */ + +/* The below const definitions are to faciltate debugging of the + values #define'd below. */ +extern const char VSD_STD_ID_BEA01[sizeof("BEA01")-1]; +extern const char VSD_STD_ID_BOOT2[sizeof("BOOT2")-1]; +extern const char VSD_STD_ID_CD001[sizeof("CD001")-1]; +extern const char VSD_STD_ID_CDW01[sizeof("CDW02")-1]; +extern const char VSD_STD_ID_NSR03[sizeof("NSR03")-1]; +extern const char VSD_STD_ID_TEA01[sizeof("TEA01")-1]; + +#define VSD_STD_ID_BEA01 "BEA01" /**< ECMA-167 2/9.2 */ +#define VSD_STD_ID_BOOT2 "BOOT2" /**< ECMA-167 2/9.4 */ +#define VSD_STD_ID_CD001 "CD001" /**< ECMA-119 */ +#define VSD_STD_ID_CDW02 "CDW02" /**< ECMA-168 */ +#define VSD_STD_ID_NSR02 "NSR02" /**< ECMA-167, 3/9.1 + NOTE: ECMA-167, 2nd edition */ +#define VSD_STD_ID_NSR03 "NSR03" /**< ECMA-167 3/9.1 */ +#define VSD_STD_ID_TEA01 "TEA01" /**< ECMA-168 2/9.3 */ + +/** Beginning Extended Area Descriptor (ECMA 167r3 2/9.2) */ +struct beginning_extended_area_desc_s +{ + udf_Uint8_t struct_type; + udf_Uint8_t std_id[VSD_STD_ID_SIZE]; + udf_Uint8_t struct_version; + udf_Uint8_t struct_data[2041]; +} GNUC_PACKED; + +/** Terminating Extended Area Descriptor (ECMA 167r3 2/9.3) */ +struct terminating_extended_area_desc_s +{ + udf_Uint8_t struct_type; + udf_Uint8_t std_id[VSD_STD_ID_SIZE]; + udf_Uint8_t struct_version; + udf_Uint8_t struct_data[2041]; +} GNUC_PACKED; + +/** Boot Descriptor (ECMA 167r3 2/9.4) */ +struct boot_desc_s +{ + udf_Uint8_t struct_type; + udf_Uint8_t std_ident[VSD_STD_ID_SIZE]; + udf_Uint8_t struct_version; + udf_Uint8_t reserved1; + udf_regid_t arch_type; + udf_regid_t boot_ident; + udf_Uint32_t bool_ext_location; + udf_Uint32_t bool_ext_length; + udf_Uint64_t load_address; + udf_Uint64_t start_address; + udf_timestamp_t desc_creation_time; + udf_Uint16_t flags; + udf_Uint8_t reserved2[32]; + udf_Uint8_t boot_use[1906]; +} GNUC_PACKED; + +/** Flags (ECMA 167r3 2/9.4.12) */ +#define BOOT_FLAGS_ERASE 0x01 + +/** Extent Descriptor (ECMA 167r3 3/7.1) */ +struct udf_extent_ad_s +{ + udf_Uint32_t len; + udf_Uint32_t loc; +} GNUC_PACKED; + +typedef struct udf_extent_ad_s udf_extent_ad_t; + +/** Descriptor Tag (ECMA 167r3 3/7.2) */ +struct udf_tag_s +{ + udf_Uint16_t id; + udf_Uint16_t desc_version; + udf_Uint8_t cksum; + udf_Uint8_t reserved; + udf_Uint16_t i_serial; + udf_Uint16_t desc_CRC; + udf_Uint16_t desc_CRC_len; + udf_Uint32_t loc; +} GNUC_PACKED; + +typedef struct udf_tag_s udf_tag_t; + +/** NSR Descriptor (ECMA 167r3 3/9.1) */ +struct NSR_desc_s +{ + udf_Uint8_t struct_type; + udf_Uint8_t std_id[VSD_STD_ID_SIZE]; + udf_Uint8_t struct_version; + udf_Uint8_t reserved; + udf_Uint8_t struct_data[2040]; +} GNUC_PACKED; + +/** Primary Volume Descriptor (ECMA 167r3 3/10.1) */ +struct udf_pvd_s +{ + udf_tag_t tag; + udf_Uint32_t vol_desc_seq_num; + udf_Uint32_t primary_vol_desc_num; + udf_dstring vol_ident[UDF_VOLID_SIZE]; + udf_Uint16_t vol_seq_num; + udf_Uint16_t max_vol_seqnum; + udf_Uint16_t interchange_lvl; + udf_Uint16_t max_interchange_lvl; + udf_Uint32_t charset_list; + udf_Uint32_t max_charset_list; + udf_dstring volset_id[UDF_VOLSET_ID_SIZE]; + udf_charspec_t desc_charset; + udf_charspec_t explanatory_charset; + udf_extent_ad_t vol_abstract; + udf_extent_ad_t vol_copyright; + udf_regid_t app_ident; + udf_timestamp_t recording_time; + udf_regid_t imp_ident; + udf_Uint8_t imp_use[64]; + udf_Uint32_t predecessor_vol_desc_seq_location; + udf_Uint16_t flags; + udf_Uint8_t reserved[22]; +} GNUC_PACKED; + +typedef struct udf_pvd_s udf_pvd_t; + +/** Flags (ECMA 167r3 3/10.1.21) */ +#define PVD_FLAGS_VSID_COMMON 0x0001 + +/** Anchor Volume Descriptor Pointer (ECMA 167r3 3/10.2) */ +struct anchor_vol_desc_ptr_s +{ + udf_tag_t tag; + udf_extent_ad_t main_vol_desc_seq_ext; + udf_extent_ad_t reserve_vol_desc_seq_ext; + udf_Uint8_t reserved[480]; +} GNUC_PACKED; + +typedef struct anchor_vol_desc_ptr_s anchor_vol_desc_ptr_t; + +/** Volume Descriptor Pointer (ECMA 167r3 3/10.3) */ +struct vol_desc_ptr_s +{ + udf_tag_t tag; + udf_Uint32_t vol_desc_seq_num; + udf_extent_ad_t next_vol_desc_set_ext; + udf_Uint8_t reserved[484]; +} GNUC_PACKED; + +/** Implementation Use Volume Descriptor (ECMA 167r3 3/10.4) */ +struct imp_use_vol_desc_s +{ + udf_tag_t tag; + udf_Uint32_t vol_desc_seq_num; + udf_regid_t imp_id; + udf_Uint8_t imp_use[460]; +} GNUC_PACKED; + +/** Partition Descriptor (ECMA 167r3 3/10.5) */ +struct partition_desc_s +{ + udf_tag_t tag; + udf_Uint32_t vol_desc_seq_num; + udf_Uint16_t flags; + udf_Uint16_t number; /**< Partition number */ + udf_regid_t contents; + udf_Uint8_t contents_use[128]; + udf_Uint32_t access_type; + udf_Uint32_t start_loc; + udf_Uint32_t part_len; + udf_regid_t imp_id; + udf_Uint8_t imp_use[128]; + udf_Uint8_t reserved[156]; +} GNUC_PACKED; + +typedef struct partition_desc_s partition_desc_t; + +/** Partition Flags (ECMA 167r3 3/10.5.3) */ +#define PD_PARTITION_FLAGS_ALLOC 0x0001 + +/** Partition Contents (ECMA 167r2 3/10.5.3) */ +#define PD_PARTITION_CONTENTS_NSR02 "+NSR02" + +/** Partition Contents (ECMA 167r3 3/10.5.5) */ +#define PD_PARTITION_CONTENTS_FDC01 "+FDC01" +#define PD_PARTITION_CONTENTS_CD001 "+CD001" +#define PD_PARTITION_CONTENTS_CDW02 "+CDW02" +#define PD_PARTITION_CONTENTS_NSR03 "+NSR03" + +/** Access Type (ECMA 167r3 3/10.5.7) */ +#define PD_ACCESS_TYPE_NONE 0x00000000 +#define PD_ACCESS_TYPE_READ_ONLY 0x00000001 +#define PD_ACCESS_TYPE_WRITE_ONCE 0x00000002 +#define PD_ACCESS_TYPE_REWRITABLE 0x00000003 +#define PD_ACCESS_TYPE_OVERWRITABLE 0x00000004 + +/** Recorded Address (ECMA 167r3 4/7.1) */ +struct udf_lb_addr_s +{ + udf_Uint32_t lba; + udf_Uint16_t partitionReferenceNum; +} GNUC_PACKED; + +typedef struct udf_lb_addr_s udf_lb_addr_t; + +/** Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ +struct udf_short_ad_s +{ + udf_Uint32_t len; + udf_Uint32_t pos; +} GNUC_PACKED; + +typedef struct udf_short_ad_s udf_short_ad_t; + +/** Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ +struct udf_long_ad_s +{ + udf_Uint32_t len; + udf_lb_addr_t loc; + udf_Uint8_t imp_use[6]; +} GNUC_PACKED; + +typedef struct udf_long_ad_s udf_long_ad_t; + +/** Logical Volume Descriptor (ECMA 167r3 3/10.6) */ +struct logical_vol_desc_s +{ + udf_tag_t tag; + udf_Uint32_t seq_num; + udf_charspec_t desc_charset; + udf_dstring logvol_id[128]; + udf_Uint32_t logical_blocksize; + udf_regid_t domain_id; + union { + udf_long_ad_t fsd_loc; + udf_Uint8_t logvol_content_use[16]; + } lvd_use; + udf_Uint8_t logvol_contents_use[16]; + udf_Uint32_t maptable_len; + udf_Uint32_t i_partition_maps; + udf_regid_t imp_id; + udf_Uint8_t imp_use[128]; + udf_extent_ad_t integrity_seq_ext; + udf_Uint8_t partition_maps[0]; +} GNUC_PACKED; + +typedef struct logical_vol_desc_s logical_vol_desc_t; + +/** Generic Partition Map (ECMA 167r3 3/10.7.1) */ +struct generic_partition_map +{ + udf_Uint8_t partition_map_type; + udf_Uint8_t partition_map_length; + udf_Uint8_t partition_mapping[0]; +} GNUC_PACKED; + +/** Partition Map Type (ECMA 167r3 3/10.7.1.1) */ +#define GP_PARTITION_MAP_TYPE_UNDEF 0x00 +#define GP_PARTIITON_MAP_TYPE_1 0x01 +#define GP_PARTITION_MAP_TYPE_2 0x02 + +/** Type 1 Partition Map (ECMA 167r3 3/10.7.2) */ +struct generic_partition_map1 +{ + udf_Uint8_t partition_map_type; + udf_Uint8_t partition_map_length; + udf_Uint16_t vol_seq_num; + udf_Uint16_t i_partition; +} GNUC_PACKED; + +/** Type 2 Partition Map (ECMA 167r3 3/10.7.3) */ +struct generic_partition_map2 +{ + udf_Uint8_t partition_map_type; + udf_Uint8_t partition_map_length; + udf_Uint8_t partition_id[62]; +} GNUC_PACKED; + +/** Unallocated Space Descriptor (ECMA 167r3 3/10.8) */ +struct unalloc_space_desc_s +{ + udf_tag_t tag; + udf_Uint32_t vol_desc_seq_num; + udf_Uint32_t i_alloc_descs; + udf_extent_ad_t allocDescs[0]; +} GNUC_PACKED; + +/** Terminating Descriptor (ECMA 167r3 3/10.9) */ +struct terminating_desc_s +{ + udf_tag_t tag; + udf_Uint8_t reserved[496]; +} GNUC_PACKED; + +/** Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */ +struct logvol_integrity_desc_s +{ + udf_tag_t tag; + udf_timestamp_t recording_time; + udf_Uint32_t integrity_type; + udf_extent_ad_t next_integrity_ext; + udf_Uint8_t logvol_contents_use[32]; + udf_Uint32_t i_partitions; + udf_Uint32_t imp_use_len; + union { /* MSVC workaround for multiple zero sized arrays */ + udf_Uint32_t freespace_table[0]; + udf_Uint32_t size_table[0]; + udf_Uint8_t imp_use[0]; + } u; +} GNUC_PACKED; + +/** Integrity Type (ECMA 167r3 3/10.10.3) */ +#define LVID_INTEGRITY_TYPE_OPEN 0x00000000 +#define LVID_INTEGRITY_TYPE_CLOSE 0x00000001 + +/** Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ +struct udf_ext_ad_s +{ + udf_Uint32_t len; + udf_Uint32_t recorded_len; + udf_Uint32_t information_len; + udf_lb_addr_t ext_loc; +} GNUC_PACKED; + +typedef struct udf_ext_ad_s udf_ext_ad_t; + +/** Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */ + +/** Tag Identifier (ECMA 167r3 4/7.2.1) */ + +/** File Set Descriptor (ECMA 167r3 4/14.1) */ +struct udf_fsd_s +{ + udf_tag_t tag; + udf_timestamp_t recording_time; + udf_Uint16_t interchange_lvl; + udf_Uint16_t maxInterchange_lvl; + udf_Uint32_t charset_list; + udf_Uint32_t max_charset_list; + udf_Uint32_t fileset_num; + udf_Uint32_t udf_fsd_num; + udf_charspec_t logical_vol_id_charset; + udf_dstring logical_vol_id[128]; + udf_charspec_t fileset_charset; + udf_dstring fileSet_id[32]; + udf_dstring copyright_file_id[32]; + udf_dstring abstract_file_id[32]; + udf_long_ad_t root_icb; + udf_regid_t domain_id; + udf_long_ad_t next_ext; + udf_long_ad_t stream_directory_ICB; + udf_Uint8_t reserved[32]; +} GNUC_PACKED; + +typedef struct udf_fsd_s udf_fsd_t; + +/** Partition Header Descriptor (ECMA 167r3 4/14.3) */ +struct partition_header_desc_s +{ + udf_short_ad_t unalloc_space_table; + udf_short_ad_t unalloc_space_bitmap; + udf_short_ad_t partition_integrity_table; + udf_short_ad_t freed_space_table; + udf_short_ad_t freed_space_bitmap; + udf_Uint8_t reserved[88]; +} GNUC_PACKED; + +typedef struct partition_header_desc_s partition_header_desc_t; + +/** File Identifier Descriptor (ECMA 167r3 4/14.4) */ +struct udf_fileid_desc_s +{ + udf_tag_t tag; + udf_Uint16_t file_version_num; + udf_Uint8_t file_characteristics; + udf_Uint8_t i_file_id; + udf_long_ad_t icb; + udf_Uint16_t i_imp_use; + union { /* MSVC workaround for multiple zero sized arrays */ + udf_Uint8_t imp_use[0]; + udf_Uint8_t file_id[0]; + udf_Uint8_t padding[0]; + } u; +} GNUC_PACKED; + +typedef struct udf_fileid_desc_s udf_fileid_desc_t; + +/** File Characteristics (ECMA 167r3 4/14.4.3) + + Imagine the below enumeration values are \#defines to be used in a + bitmask rather than distinct values of an enum. +*/ +typedef enum { + UDF_FILE_HIDDEN = (1 << 0), + UDF_FILE_DIRECTORY = (1 << 1), + UDF_FILE_DELETED = (1 << 2), + UDF_FILE_PARENT = (1 << 3), + UDF_FILE_METADATA = (1 << 4) +} file_characteristics_t; + +/** Allocation Ext Descriptor (ECMA 167r3 4/14.5) */ +struct allocExtDesc +{ + udf_tag_t tag; + udf_Uint32_t previous_alloc_ext_loc; + udf_Uint32_t i_alloc_descs; +} GNUC_PACKED; + +/** ICB Tag (ECMA 167r3 4/14.6) */ +struct udf_icbtag_s +{ + udf_Uint32_t prev_num_dirs; + udf_Uint16_t strat_type; + udf_Uint16_t strat_param; + udf_Uint16_t max_num_entries; + udf_Uint8_t reserved; + udf_Uint8_t file_type; + udf_lb_addr_t parent_ICB; + udf_Uint16_t flags; +} GNUC_PACKED; + +typedef struct udf_icbtag_s udf_icbtag_t; + +#define UDF_ICB_TAG_FLAGS_SETUID 0x40 +#define UDF_ICB_TAG_FLAGS_SETGID 0x80 +#define UDF_ICB_TAG_FLAGS_STICKY 0x100 + +/** Strategy Type (ECMA 167r3 4/14.6.2) which helpfully points + largely to 4/A.x */ +#define ICBTAG_STRATEGY_TYPE_UNDEF 0x0000 +#define ICBTAG_STRATEGY_TYPE_1 0x0001 /**< 4/A.2 Direct entries Uint16 */ +#define ICBTAG_STRATEGY_TYPE_2 0x0002 /**< 4/A.3 List of ICB direct entries */ +#define ICBTAG_STRATEGY_TYPE_3 0x0003 /**< 4/A.4 */ +#define ICBTAG_STRATEGY_TYPE_4 0x0004 /**< 4/A.5 Hierarchy having one + single ICB with one direct entry. + This is what's most often used. + */ + +/** File Type (ECMA 167r3 4/14.6.6) + + Imagine the below enum values as \#define'd values rather than + distinct values of an enum. +*/ +typedef enum { + ICBTAG_FILE_TYPE_UNDEF = 0x00, + ICBTAG_FILE_TYPE_USE = 0x01, + ICBTAG_FILE_TYPE_PIE = 0x02, + ICBTAG_FILE_TYPE_IE = 0x03, + ICBTAG_FILE_TYPE_DIRECTORY = 0x04, + ICBTAG_FILE_TYPE_REGULAR = 0x05, + ICBTAG_FILE_TYPE_BLOCK = 0x06, + ICBTAG_FILE_TYPE_CHAR = 0x07, + ICBTAG_FILE_TYPE_EA = 0x08, + ICBTAG_FILE_TYPE_FIFO = 0x09, + ICBTAG_FILE_TYPE_SOCKET = 0x0A, + ICBTAG_FILE_TYPE_TE = 0x0B, + ICBTAG_FILE_TYPE_SYMLINK = 0x0C, + ICBTAG_FILE_TYPE_STREAMDIR = 0x0D +} icbtag_file_type_enum_t; + +/** Flags (ECMA 167r3 4/14.6.8) */ +typedef enum { + ICBTAG_FLAG_AD_MASK = 0x0007, /**< "&" this to get below address + flags */ + ICBTAG_FLAG_AD_SHORT = 0x0000, /**< The allocation descriptor + field is filled with + short_ad's. If the + offset is beyond the + current extent, look for + the next extent. */ + ICBTAG_FLAG_AD_LONG = 0x0001, /**< The allocation descriptor + field is filled with + long_ad's If the offset + is beyond the current + extent, look for the next + extent. */ + ICBTAG_FLAG_AD_EXTENDED = 0x0002, + ICBTAG_FLAG_AD_IN_ICB = 0x0003, /**< This type means that the + file *data* is stored in + the allocation descriptor + field of the file entry. */ + ICBTAG_FLAG_SORTED = 0x0008, + ICBTAG_FLAG_NONRELOCATABLE = 0x0010, + ICBTAG_FLAG_ARCHIVE = 0x0020, + ICBTAG_FLAG_SETUID = 0x0040, + ICBTAG_FLAG_SETGID = 0x0080, + ICBTAG_FLAG_STICKY = 0x0100, + ICBTAG_FLAG_CONTIGUOUS = 0x0200, + ICBTAG_FLAG_SYSTEM = 0x0400, + ICBTAG_FLAG_TRANSFORMED = 0x0800, + ICBTAG_FLAG_MULTIVERSIONS = 0x1000, + ICBTAG_FLAG_STREAM = 0x2000 +} icbtag_flag_enum_t; + +/** Indirect Entry (ECMA 167r3 4/14.7) */ +struct indirect_entry_s +{ + udf_tag_t tag; + udf_icbtag_t icb_tag; + udf_long_ad_t indirect_ICB; +} GNUC_PACKED; + +/** Terminal Entry (ECMA 167r3 4/14.8) */ +struct terminal_entry_s +{ + udf_tag_t tag; + udf_icbtag_t icb_tag; +} GNUC_PACKED; + +/** File Entry (ECMA 167r3 4/14.9) */ +struct udf_file_entry_s +{ + udf_tag_t tag; + udf_icbtag_t icb_tag; /**< 4/14.9.2 */ + udf_Uint32_t uid; /**< 4/14.9.3 */ + udf_Uint32_t gid; /**< 4/14.9.4 */ + udf_Uint32_t permissions; /**< 4/14.9.5 */ + udf_Uint16_t link_count; /**< 4/14.9.6 */ + udf_Uint8_t rec_format; /**< 4/14.9.7 */ + udf_Uint8_t rec_disp_attr; /**< 4/14.9.8 */ + udf_Uint32_t rec_len; /**< 4/14.9.9 */ + udf_Uint64_t info_len; /**< 4/14.9.10 */ + udf_Uint64_t logblks_recorded; /**< 4/14.9.11 */ + udf_timestamp_t access_time; /**< 4/14.9.12 - last access to + any stream of file prior to + recording file entry */ + udf_timestamp_t modification_time; /**< 4/14.9.13 - last access to + modification to any stream of + file */ + udf_timestamp_t attribute_time; + udf_Uint32_t checkpoint; + udf_long_ad_t ext_attr_ICB; + udf_regid_t imp_id; + udf_Uint64_t unique_ID; + udf_Uint32_t i_extended_attr; + udf_Uint32_t i_alloc_descs; + /* The following union allows file entry reuse without worrying + about overflows, by ensuring the struct is always the + maximum possible size allowed by the specs: one UDF block. */ + union { + udf_Uint8_t ext_attr[0]; + udf_Uint8_t alloc_descs[0]; + udf_Uint8_t pad_to_one_block[2048-176]; + } u; +} GNUC_PACKED; + +typedef struct udf_file_entry_s udf_file_entry_t; + +#define UDF_FENTRY_SIZE 176 +#define UDF_FENTRY_PERM_USER_MASK 0x07 +#define UDF_FENTRY_PERM_GRP_MASK 0xE0 +#define UDF_FENTRY_PERM_OWNER_MASK 0x1C00 + +/** Permissions (ECMA 167r3 4/14.9.5) */ +#define FE_PERM_O_EXEC 0x00000001U +#define FE_PERM_O_WRITE 0x00000002U +#define FE_PERM_O_READ 0x00000004U +#define FE_PERM_O_CHATTR 0x00000008U +#define FE_PERM_O_DELETE 0x00000010U +#define FE_PERM_G_EXEC 0x00000020U +#define FE_PERM_G_WRITE 0x00000040U +#define FE_PERM_G_READ 0x00000080U +#define FE_PERM_G_CHATTR 0x00000100U +#define FE_PERM_G_DELETE 0x00000200U +#define FE_PERM_U_EXEC 0x00000400U +#define FE_PERM_U_WRITE 0x00000800U +#define FE_PERM_U_READ 0x00001000U +#define FE_PERM_U_CHATTR 0x00002000U +#define FE_PERM_U_DELETE 0x00004000U + +/** Record Format (ECMA 167r3 4/14.9.7) */ +#define FE_RECORD_FMT_UNDEF 0x00 +#define FE_RECORD_FMT_FIXED_PAD 0x01 +#define FE_RECORD_FMT_FIXED 0x02 +#define FE_RECORD_FMT_VARIABLE8 0x03 +#define FE_RECORD_FMT_VARIABLE16 0x04 +#define FE_RECORD_FMT_VARIABLE16_MSB 0x05 +#define FE_RECORD_FMT_VARIABLE32 0x06 +#define FE_RECORD_FMT_PRINT 0x07 +#define FE_RECORD_FMT_LF 0x08 +#define FE_RECORD_FMT_CR 0x09 +#define FE_RECORD_FMT_CRLF 0x0A +#define FE_RECORD_FMT_LFCR 0x0B + +/** Record Display Attributes (ECMA 167r3 4/14.9.8) */ +#define FE_RECORD_DISPLAY_ATTR_UNDEF 0x00 +#define FE_RECORD_DISPLAY_ATTR_1 0x01 +#define FE_RECORD_DISPLAY_ATTR_2 0x02 +#define FE_RECORD_DISPLAY_ATTR_3 0x03 + +/** Extended Attribute Header Descriptor (ECMA 167r3 4/14.10.1) */ +struct extended_attr_header_desc_s +{ + udf_tag_t tag; + udf_Uint32_t imp_attr_location; + udf_Uint32_t app_attr_location; +} GNUC_PACKED; + +/** Generic Format (ECMA 167r3 4/14.10.2) */ +struct generic_format_s +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint8_t attrData[0]; +} GNUC_PACKED; + +/** Character Set Information (ECMA 167r3 4/14.10.3) */ +struct charSet_info_s +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint32_t escapeSeqLength; + udf_Uint8_t charSetType; + udf_Uint8_t escapeSeq[0]; +} GNUC_PACKED; + +/* Alternate Permissions (ECMA 167r3 4/14.10.4) */ +struct alt_perms_s +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint16_t owner_id; + udf_Uint16_t group_id; + udf_Uint16_t permission; +} GNUC_PACKED; + +/** File Times Extended Attribute (ECMA 167r3 4/14.10.5) */ +struct filetimes_ext_attr_s +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint32_t dataLength; + udf_Uint32_t fileTimeExistence; + udf_Uint8_t fileTimes; +} GNUC_PACKED; + +/** FileTimeExistence (ECMA 167r3 4/14.10.5.6) */ +#define FTE_CREATION 0x00000001 +#define FTE_DELETION 0x00000004 +#define FTE_EFFECTIVE 0x00000008 +#define FTE_BACKUP 0x00000002 + +/** Information Times Extended Attribute (ECMA 167r3 4/14.10.6) */ +struct infoTimesExtAttr +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint32_t dataLength; + udf_Uint32_t infoTimeExistence; + udf_Uint8_t infoTimes[0]; +} GNUC_PACKED; + +/** Device Specification (ECMA 167r3 4/14.10.7) */ +struct deviceSpec +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint32_t imp_useLength; + udf_Uint32_t majorDevice_id; + udf_Uint32_t minorDevice_id; + udf_Uint8_t imp_use[0]; +} GNUC_PACKED; + +/** Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */ +struct impUseExtAttr +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint32_t imp_useLength; + udf_regid_t imp_id; + udf_Uint8_t imp_use[0]; +} GNUC_PACKED; + +/** Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */ +struct appUseExtAttr +{ + udf_Uint32_t attr_type; + udf_Uint8_t attr_subtype; + udf_Uint8_t reserved[3]; + udf_Uint32_t attrLength; + udf_Uint32_t appUseLength; + udf_regid_t app_id; + udf_Uint8_t appUse[0]; +} GNUC_PACKED; + +#define EXTATTR_CHAR_SET 1 +#define EXTATTR_ALT_PERMS 3 +#define EXTATTR_FILE_TIMES 5 +#define EXTATTR_INFO_TIMES 6 +#define EXTATTR_DEV_SPEC 12 +#define EXTATTR_IMP_USE 2048 +#define EXTATTR_APP_USE 65536 + + +/** Unallocated Space Entry (ECMA 167r3 4/14.11) */ +struct unallocSpaceEntry +{ + udf_tag_t tag; + udf_icbtag_t icb_tag; + udf_Uint32_t lengthAllocDescs; + udf_Uint8_t allocDescs[0]; +} GNUC_PACKED; + +/** Space Bitmap Descriptor (ECMA 167r3 4/14.12) */ +struct spaceBitmapDesc +{ + udf_tag_t tag; + udf_Uint32_t i_bits; + udf_Uint32_t i_bytes; + udf_Uint8_t bitmap[0]; +} GNUC_PACKED; + +/** Partition Integrity Entry (ECMA 167r3 4/14.13) */ +struct partitionIntegrityEntry +{ + udf_tag_t tag; + udf_icbtag_t icb_tag; + udf_timestamp_t recording_time; + udf_Uint8_t integrityType; + udf_Uint8_t reserved[175]; + udf_regid_t imp_id; + udf_Uint8_t imp_use[256]; +} GNUC_PACKED; + +/** Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ + +/** Extent Length (ECMA 167r3 4/14.14.1.1) */ +#define EXT_RECORDED_ALLOCATED 0x00000000 +#define EXT_NOT_RECORDED_ALLOCATED 0x40000000 +#define EXT_NOT_RECORDED_NOT_ALLOCATED 0x80000000 +#define EXT_NEXT_EXTENT_ALLOCDECS 0xC0000000 + +/** Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ + +/** Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ + +/** Logical Volume Header Descriptor (ECMA 167r3 4/14.15) */ +struct logical_vol_header_desc_s +{ + udf_Uint64_t uniqueID; + udf_Uint8_t reserved[24]; +} GNUC_PACKED; + +typedef struct logical_vol_header_desc_s logical_vol_header_desc_t; + +/** Path Component (ECMA 167r3 4/14.16.1) */ +struct pathComponent +{ + udf_Uint8_t component_type; + udf_Uint8_t lengthComponent_id; + udf_Uint16_t componentFileVersionNum; + udf_dstring component_id[0]; +} GNUC_PACKED; + +/** File Entry (ECMA 167r3 4/14.17) */ +struct extended_file_entry +{ + udf_tag_t tag; /**< 4/14.17.1 - id = 266 */ + udf_icbtag_t icb_tag; /**< 4/14.17.2 & 4/14.9.2 */ + udf_Uint32_t uid; /**< 4/14.17.3 & 4/14.9.3 */ + udf_Uint32_t gid; /**< 4/14.17.4 & 4/14.9.4 */ + udf_Uint32_t permissions; /**< 4/14.17.5 & 4/14.9.5 */ + udf_Uint16_t link_count; /**< 4/14.17.6 & 4/14.9.6 */ + udf_Uint8_t rec_format; /**< 4/14.17.7 & 4/14.9.7 */ + udf_Uint8_t rec_display_attr; /**< 4/14.17.8 & 4/14.9.8 */ + udf_Uint32_t record_len; /**< 4/14.17.9 & 4/14.9.9 */ + udf_Uint64_t info_len; /**< 4/14.17.10 & 4/14.9.10 */ + udf_Uint64_t object_size; /**< 4/14.17.11 */ + udf_Uint64_t logblks_recorded; /**< 4/14.17.12 & 4/14.9.11 */ + udf_timestamp_t access_time; /**< 4/14.17.13 & 4/14.9.12 - last + access to any stream of file */ + udf_timestamp_t modification_time; /**< 4/14.17.14 & 4/14.9.13 - last + modification to any stream of + file*/ + udf_timestamp_t create_time; /**< 4/14.17.15 */ + udf_timestamp_t attribute_time; /**< 4/14.17.16 & 4/14.9.14 - + most recent create or modify + time */ + udf_Uint32_t checkpoint; + udf_Uint32_t reserved; /**< #00 bytes */ + udf_long_ad_t ext_attr_ICB; + udf_long_ad_t stream_directory_ICB; + udf_regid_t imp_id; + udf_Uint64_t unique_ID; + udf_Uint32_t length_extended_attr; + udf_Uint32_t length_alloc_descs; + union { /* MSVC workaround for multiple zero sized arrays */ + udf_Uint8_t ext_attr[0]; + udf_Uint8_t alloc_descs[0]; + } u; +} GNUC_PACKED; + +PRAGMA_END_PACKED + +/** The below variables are trickery to force the above enum symbol + values to be recorded in debug symbol tables. They are used to + allow one refer to the enumeration value names in the typedefs + above in a debugger and in debugger expressions. +*/ +extern tag_id_t debug_tagid; +extern file_characteristics_t debug_file_characteristics; +extern icbtag_file_type_enum_t debug_icbtag_file_type_enum; +extern icbtag_flag_enum_t debug_flag_enum; +extern ecma_167_enum1_t debug_ecma_167_enum1; +extern ecma_167_timezone_enum_t debug_ecma_167_timezone_enum; + +#endif /* _ECMA_167_H */ diff --git a/src/libcdio/cdio/iso9660.h b/src/libcdio/cdio/iso9660.h new file mode 100644 index 00000000..942c52d8 --- /dev/null +++ b/src/libcdio/cdio/iso9660.h @@ -0,0 +1,1144 @@ +/* + $Id: iso9660.h,v 1.102 2008/07/16 00:28:54 rocky Exp $ + + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + See also iso9660.h by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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 3 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, see . +*/ +/*! + * \file iso9660.h + * + * \brief The top-level interface header for libiso9660: the ISO-9660 + * filesystem library; applications include this. + * + * See also the ISO-9660 specification. The freely available European + * equivalant standard is called ECMA-119. +*/ + + +#ifndef __CDIO_ISO9660_H__ +#define __CDIO_ISO9660_H__ + +#include + +#include +#include +#include + +/** \brief ISO 9660 Integer and Character types + +These are described in the section 7 of the ISO 9660 (or ECMA 119) +specification. +*/ + +typedef uint8_t iso711_t; /*! See section 7.1.1 */ +typedef int8_t iso712_t; /*! See section 7.1.2 */ +typedef uint16_t iso721_t; /*! See section 7.2.1 */ +typedef uint16_t iso722_t; /*! See section 7.2.2 */ +typedef uint32_t iso723_t; /*! See section 7.2.3 */ +typedef uint32_t iso731_t; /*! See section 7.3.1 */ +typedef uint32_t iso732_t; /*! See section 7.3.2 */ +typedef uint64_t iso733_t; /*! See section 7.3.3 */ + +typedef char achar_t; /*! See section 7.4.1 */ +typedef char dchar_t; /*! See section 7.4.1 */ + +#ifndef EMPTY_ARRAY_SIZE +#define EMPTY_ARRAY_SIZE 0 +#endif + +#include +#include + +#ifdef ISODCL +#undef ISODCL +#endif +/* This part borrowed from the bsd386 isofs */ +#define ISODCL(from, to) ((to) - (from) + 1) + +#define MIN_TRACK_SIZE 4*75 +#define MIN_ISO_SIZE MIN_TRACK_SIZE + +/*! The below isn't really an enumeration one would really use in a + program; things are done this way so that in a debugger one can to + refer to the enumeration value names such as in a debugger + expression and get something. With the more common a \#define + mechanism, the name/value assocation is lost at run time. + */ +extern enum iso_enum1_s { + ISO_PVD_SECTOR = 16, /**< Sector of Primary Volume Descriptor. */ + ISO_EVD_SECTOR = 17, /**< Sector of End Volume Descriptor. */ + LEN_ISONAME = 31, /**< Size in bytes of the filename + portion + null byte. */ + ISO_MAX_SYSTEM_ID = 32, /**< Maximum number of characters in a system + id. */ + MAX_ISONAME = 37, /**< Size in bytes of the filename + portion + null byte. */ + ISO_MAX_PREPARER_ID = 128, /**< Maximum number of characters in a + preparer id. */ + MAX_ISOPATHNAME = 255, /**< Maximum number of characters in the + entire ISO 9660 filename. */ + ISO_BLOCKSIZE = 2048 /**< Number of bytes in an ISO 9660 block. */ + +} iso_enums1; + +/*! An enumeration for some of the ISO_* \#defines below. This isn't + really an enumeration one would really use in a program it is here + to be helpful in debuggers where wants just to refer to the + ISO_*_ names and get something. + */ + +/*! ISO 9660 directory flags. */ +extern enum iso_flag_enum_s { + ISO_FILE = 0, /**< Not really a flag... */ + ISO_EXISTENCE = 1, /**< Do not make existence known (hidden) */ + ISO_DIRECTORY = 2, /**< This file is a directory */ + ISO_ASSOCIATED = 4, /**< This file is an associated file */ + ISO_RECORD = 8, /**< Record format in extended attr. != 0 */ + ISO_PROTECTION = 16, /**< No read/execute perm. in ext. attr. */ + ISO_DRESERVED1 = 32, /**<, Reserved bit 5 */ + ISO_DRESERVED2 = 64, /**<, Reserved bit 6 */ + ISO_MULTIEXTENT = 128, /**< Not final entry of a mult. ext. file */ +} iso_flag_enums; + +/*! Volume descriptor types */ +extern enum iso_vd_enum_s { + ISO_VD_BOOT_RECORD = 0, /**< CD is bootable */ + ISO_VD_PRIMARY = 1, /**< Is in any ISO-9660 */ + ISO_VD_SUPPLEMENTARY = 2, /**< Used by Joliet, for example */ + ISO_VD_PARITION = 3, /**< Indicates a partition of a CD */ + ISO_VD_END = 255 +} iso_vd_enums; + + +/*! + An ISO filename is: + abcd.eee -> + filename.ext;version# + + For ISO-9660 Level 1, the maximum needed string length is: + +@code + 30 chars (filename + ext) + + 2 chars ('.' + ';') + + 5 chars (strlen("32767")) + + 1 null byte + ================================ + = 38 chars +@endcode + +*/ + +/*! \brief Maximum number of characters in a publisher id. */ +#define ISO_MAX_PUBLISHER_ID 128 + +/*! \brief Maximum number of characters in an application id. */ +#define ISO_MAX_APPLICATION_ID 128 + +/*! \brief Maximum number of characters in a volume id. */ +#define ISO_MAX_VOLUME_ID 32 + +/*! \brief Maximum number of characters in a volume-set id. */ +#define ISO_MAX_VOLUMESET_ID 128 + +/*! String inside frame which identifies an ISO 9660 filesystem. This + string is the "id" field of an iso9660_pvd_t or an iso9660_svd_t. +*/ +extern const char ISO_STANDARD_ID[sizeof("CD001")-1]; + +#define ISO_STANDARD_ID "CD001" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef enum strncpy_pad_check { + ISO9660_NOCHECK = 0, + ISO9660_7BIT, + ISO9660_ACHARS, + ISO9660_DCHARS +} strncpy_pad_check_t; + +PRAGMA_BEGIN_PACKED + +/*! + \brief ISO-9660 shorter-format time structure. See ECMA 9.1.5. + + @see iso9660_dtime + */ +struct iso9660_dtime_s { + iso711_t dt_year; /**< Number of years since 1900 */ + iso711_t dt_month; /**< Has value in range 1..12. Note starts + at 1, not 0 like a tm struct. */ + iso711_t dt_day; /**< Day of the month from 1 to 31 */ + iso711_t dt_hour; /**< Hour of the day from 0 to 23 */ + iso711_t dt_minute; /**< Minute of the hour from 0 to 59 */ + iso711_t dt_second; /**< Second of the minute from 0 to 59 */ + iso712_t dt_gmtoff; /**< GMT values -48 .. + 52 in 15 minute + intervals */ +} GNUC_PACKED; + +typedef struct iso9660_dtime_s iso9660_dtime_t; + +/*! + \brief ISO-9660 longer-format time structure. + + Section 8.4.26.1 of ECMA 119. All values are encoded as character + arrays, eg. '1', '9', '5', '5' for the year 1955 (no null terminated + byte). + + @see iso9660_ltime + */ +struct iso9660_ltime_s { + char lt_year [ISODCL( 1, 4)]; /**< Add 1900 to value + for the Julian + year */ + char lt_month [ISODCL( 5, 6)]; /**< Has value in range + 1..12. Note starts + at 1, not 0 like a + tm struct. */ + char lt_day [ISODCL( 7, 8)]; /**< Day of month: 1..31 */ + char lt_hour [ISODCL( 9, 10)]; /**< hour: 0..23 */ + char lt_minute [ISODCL( 11, 12)]; /**< minute: 0..59 */ + char lt_second [ISODCL( 13, 14)]; /**< second: 0..59 */ + char lt_hsecond [ISODCL( 15, 16)]; /**< The value is in + units of 1/100's of + a second */ + iso712_t lt_gmtoff; /**< Offset from Greenwich Mean Time in number + of 15 min intervals from -48 (West) to +52 + (East) recorded according to 7.1.2 numerical + value */ +} GNUC_PACKED; + +typedef struct iso9660_ltime_s iso9660_ltime_t; +typedef struct iso9660_dir_s iso9660_dir_t; +typedef struct iso9660_stat_s iso9660_stat_t; + +#include + +/*! \brief Format of an ISO-9660 directory record + + Section 9.1 of ECMA 119. + + This structure may have an odd length depending on how many + characters there are in the filename! Some compilers (e.g. on + Sun3/mc68020) pad the structures to an even length. For this reason, + we cannot use sizeof (struct iso_path_table) or sizeof (struct + iso_directory_record) to compute on disk sizes. Instead, we use + offsetof(..., name) and add the name size. See mkisofs.h of the + cdrtools package. + + @see iso9660_stat +*/ +struct iso9660_dir_s { + iso711_t length; /*! Length of Directory record (9.1.1) */ + iso711_t xa_length; /*! XA length if XA is used. Otherwise + zero. (9.1.2) */ + iso733_t extent; /*! LBA of first local block allocated + to the extent */ + iso733_t size; /*! data length of File Section. This + does not include the length of + any XA Records. (9.1.2) */ + iso9660_dtime_t recording_time; /*! Recording date and time (9.1.3) */ + uint8_t file_flags; /*! If no XA then zero. If a directory, + then bits 2,3 and 7 are zero. + (9.1.6) */ + iso711_t file_unit_size; /*! File Unit size for the File + Section if the File Section + is recorded in interleaved + mode. Otherwise zero. (9.1.7) */ + iso711_t interleave_gap; /*! Interleave Gap size for the + File Section if the File + Section is interleaved. Otherwise + zero. (9.1.8) */ + iso723_t volume_sequence_number; /*! Ordinal number of the volume + in the Volume Set on which + the Extent described by this + Directory Record is + recorded. (9.1.9) */ +/*! MSVC compilers cannot handle a zero sized array in the middle + of a struct, and iso9660_dir_s is reused within iso9660_pvd_s. + Therefore, instead of defining: + iso711_t filename_len; + char filename[]; + we leverage the fact that iso711_t and char are the same size + and use an union. The only gotcha is that the actual string + payload of filename.str[] starts at 1, not 0. */ + union { + iso711_t len; + char str[1]; + } filename; +} GNUC_PACKED; + +/*! + \brief ISO-9660 Primary Volume Descriptor. + */ +struct iso9660_pvd_s { + iso711_t type; /**< ISO_VD_PRIMARY - 1 */ + char id[5]; /**< ISO_STANDARD_ID "CD001" + */ + iso711_t version; /**< value 1 for ECMA 119 */ + char unused1[1]; /**< unused - value 0 */ + achar_t system_id[ISO_MAX_SYSTEM_ID]; /**< each char is an achar */ + dchar_t volume_id[ISO_MAX_VOLUME_ID]; /**< each char is a dchar */ + uint8_t unused2[8]; /**< unused - value 0 */ + iso733_t volume_space_size; /**< total number of + sectors */ + uint8_t unused3[32]; /**< unused - value 0 */ + iso723_t volume_set_size; /**< often 1 */ + iso723_t volume_sequence_number; /**< often 1 */ + iso723_t logical_block_size; /**< sector size, e.g. 2048 */ + iso733_t path_table_size; /**< bytes in path table */ + iso731_t type_l_path_table; /**< first sector of L Path + Table */ + iso731_t opt_type_l_path_table; /**< first sector of optional + L Path Table */ + iso732_t type_m_path_table; /**< first sector of M Path + table */ + iso732_t opt_type_m_path_table; /**< first sector of optional + M Path table */ + iso9660_dir_t root_directory_record; /**< See 8.4.18 and + section 9.1 of + ISO 9660 spec. */ + char root_directory_filename; /**< Is '\\0' or root + directory. Also pads previous + field to 34 bytes */ + dchar_t volume_set_id[ISO_MAX_VOLUMESET_ID]; /**< Volume Set of + which the volume is + a member. See + section 8.4.19 */ + achar_t publisher_id[ISO_MAX_PUBLISHER_ID]; /**< Publisher of + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no publisher + is specified. See + section 8.4.20 of + ECMA 119 */ + achar_t preparer_id[ISO_MAX_PREPARER_ID]; /**< preparer of + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no preparer + is specified. + See section 8.4.21 + of ECMA 119 */ + achar_t application_id[ISO_MAX_APPLICATION_ID]; /**< application + use to create the + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no application + is specified. + See section of 8.4.22 + of ECMA 119 */ + dchar_t copyright_file_id[37]; /**< Name of file for + copyright info. If + all bytes are " " + (0x20), then no file + is identified. See + section 8.4.23 of ECMA 119 + 9660 spec. */ + dchar_t abstract_file_id[37]; /**< See section 8.4.24 of + ECMA 119. */ + dchar_t bibliographic_file_id[37]; /**< See section 7.5 of + ISO 9660 spec. */ + iso9660_ltime_t creation_date; /**< date and time of volume + creation. See section 8.4.26.1 + of the ISO 9660 spec. */ + iso9660_ltime_t modification_date; /**< date and time of the most + recent modification. + See section 8.4.27 of the + ISO 9660 spec. */ + iso9660_ltime_t expiration_date; /**< date and time when volume + expires. See section 8.4.28 + of the ISO 9660 spec. */ + iso9660_ltime_t effective_date; /**< date and time when volume + is effective. See section + 8.4.29 of the ISO 9660 + spec. */ + iso711_t file_structure_version; /**< value 1 for ECMA 119 */ + uint8_t unused4[1]; /**< unused - value 0 */ + char application_data[512]; /**< Application can put + whatever it wants here. */ + uint8_t unused5[653]; /**< Unused - value 0 */ +} GNUC_PACKED; + +typedef struct iso9660_pvd_s iso9660_pvd_t; + +/*! + \brief ISO-9660 Supplementary Volume Descriptor. + + This is used for Joliet Extentions and is almost the same as the + the primary descriptor but two unused fields, "unused1" and "unused3 + become "flags and "escape_sequences" respectively. +*/ +struct iso9660_svd_s { + iso711_t type; /**< ISO_VD_SUPPLEMENTARY - 2 + */ + char id[5]; /**< ISO_STANDARD_ID "CD001" + */ + iso711_t version; /**< value 1 */ + char flags; /**< Section 8.5.3 */ + achar_t system_id[ISO_MAX_SYSTEM_ID]; /**< Section 8.5.4; each char + is an achar */ + dchar_t volume_id[ISO_MAX_VOLUME_ID]; /**< Section 8.5.5; each char + is a dchar */ + char unused2[8]; + iso733_t volume_space_size; /**< total number of + sectors */ + char escape_sequences[32]; /**< Section 8.5.6 */ + iso723_t volume_set_size; /**< often 1 */ + iso723_t volume_sequence_number; /**< often 1 */ + iso723_t logical_block_size; /**< sector size, e.g. 2048 */ + iso733_t path_table_size; /**< 8.5.7; bytes in path + table */ + iso731_t type_l_path_table; /**< 8.5.8; first sector of + little-endian path table */ + iso731_t opt_type_l_path_table; /**< 8.5.9; first sector of + optional little-endian + path table */ + iso732_t type_m_path_table; /**< 8.5.10; first sector of + big-endian path table */ + iso732_t opt_type_m_path_table; /**< 8.5.11; first sector of + optional big-endian path + table */ + iso9660_dir_t root_directory_record; /**< See section 8.5.12 and + 9.1 of ISO 9660 spec. */ + char root_directory_filename; /**< Is '\\0' or root + directory. Also pads previous + field to 34 bytes */ + dchar_t volume_set_id[ISO_MAX_VOLUMESET_ID]; /**< 8.5.13; + dchars */ + achar_t publisher_id[ISO_MAX_PUBLISHER_ID]; /**< + Publisher of volume. + If the first char- + aracter is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no publisher + is specified. See + section 8.5.14 of + ECMA 119 */ + achar_t preparer_id[ISO_MAX_PREPARER_ID]; /**< + Data preparer of + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no preparer + is specified. + See section 8.5.15 + of ECMA 119 */ + achar_t application_id[ISO_MAX_APPLICATION_ID]; /**< application + use to create the + volume. If the first + character is '_' 0x5F, + the remaining bytes + specify a file + containing the user. + If all bytes are " " + (0x20) no application + is specified. + See section of 8.5.16 + of ECMA 119 */ + dchar_t copyright_file_id[37]; /**< Name of file for + copyright info. If + all bytes are " " + (0x20), then no file + is identified. See + section 8.5.17 of ECMA 119 + 9660 spec. */ + dchar_t abstract_file_id[37]; /**< See section 8.5.18 of + ECMA 119. */ + dchar_t bibliographic_file_id[37]; /**< See section 8.5.19 of + ECMA 119. */ + iso9660_ltime_t creation_date; /**< date and time of volume + creation. See section 8.4.26.1 + of the ECMA 119 spec. */ + iso9660_ltime_t modification_date; /**< date and time of the most + recent modification. + See section 8.4.27 of the + ECMA 119 spec. */ + iso9660_ltime_t expiration_date; /**< date and time when volume + expires. See section 8.4.28 + of the ECMA 119 spec. */ + iso9660_ltime_t effective_date; /**< date and time when volume + is effective. See section + 8.4.29 of the ECMA 119 + spec. */ + iso711_t file_structure_version; /**< value 1 for ECMA 119 */ + uint8_t unused4[1]; /**< unused - value 0 */ + char application_data[512]; /**< 8.5.20 Application can put + whatever it wants here. */ + uint8_t unused5[653]; /**< Unused - value 0 */ +} GNUC_PACKED; + +typedef struct iso9660_svd_s iso9660_svd_t; + +PRAGMA_END_PACKED + +/*! \brief Unix stat-like version of iso9660_dir + + The iso9660_stat structure is not part of the ISO-9660 + specification. We use it for our to communicate information + in a C-library friendly way, e.g struct tm time structures and + a C-style filename string. + + @see iso9660_dir +*/ +struct iso9660_stat_s { /* big endian!! */ + + iso_rock_statbuf_t rr; /**< Rock Ridge-specific fields */ + + struct tm tm; /**< time on entry - FIXME merge with + one of entries above, like ctime? */ + lsn_t lsn; /**< start logical sector number */ + uint32_t size; /**< total size in bytes */ + uint32_t secsize; /**< number of sectors allocated */ + iso9660_xa_t xa; /**< XA attributes */ + enum { _STAT_FILE = 1, _STAT_DIR = 2 } type; + bool b_xa; + char filename[EMPTY_ARRAY_SIZE]; /**< filename */ +}; + +/** A mask used in iso9660_ifs_read_vd which allows what kinds + of extensions we allow, eg. Joliet, Rock Ridge, etc. */ +typedef uint8_t iso_extension_mask_t; + +/*! An enumeration for some of the ISO_EXTENSION_* \#defines below. This isn't + really an enumeration one would really use in a program it is here + to be helpful in debuggers where wants just to refer to the + ISO_EXTENSION_*_ names and get something. + */ +extern enum iso_extension_enum_s { + ISO_EXTENSION_JOLIET_LEVEL1 = 0x01, + ISO_EXTENSION_JOLIET_LEVEL2 = 0x02, + ISO_EXTENSION_JOLIET_LEVEL3 = 0x04, + ISO_EXTENSION_ROCK_RIDGE = 0x08, + ISO_EXTENSION_HIGH_SIERRA = 0x10 +} iso_extension_enums; + + +#define ISO_EXTENSION_ALL 0xFF +#define ISO_EXTENSION_NONE 0x00 +#define ISO_EXTENSION_JOLIET \ + (ISO_EXTENSION_JOLIET_LEVEL1 | \ + ISO_EXTENSION_JOLIET_LEVEL2 | \ + ISO_EXTENSION_JOLIET_LEVEL3 ) + + +/** This is an opaque structure. */ +typedef struct _iso9660_s iso9660_t; + + /*! Close previously opened ISO 9660 image and free resources + associated with the image. Call this when done using using an ISO + 9660 image. + + @return true is unconditionally returned. If there was an error + false would be returned. + */ + bool iso9660_close (iso9660_t * p_iso); + + + /*! + Open an ISO 9660 image for reading. Maybe in the future we will have + a mode. NULL is returned on error. + */ + iso9660_t *iso9660_open (const char *psz_path /*flags, mode */); + + /*! + Open an ISO 9660 image for reading allowing various ISO 9660 + extensions. Maybe in the future we will have a mode. NULL is + returned on error. + + @see iso9660_open_fuzzy + */ + iso9660_t *iso9660_open_ext (const char *psz_path, + iso_extension_mask_t iso_extension_mask); + + /*! Open an ISO 9660 image for "fuzzy" reading. This means that we + will try to guess various internal offset based on internal + checks. This may be useful when trying to read an ISO 9660 image + contained in a file format that libiso9660 doesn't know natively + (or knows imperfectly.) + + Some tolerence allowed for positioning the ISO 9660 image. We scan + for STANDARD_ID and use that to set the eventual offset to adjust + by (as long as that is <= i_fuzz). + + Maybe in the future we will have a mode. NULL is returned on error. + + @see iso9660_open, @see iso9660_fuzzy_ext + */ + iso9660_t *iso9660_open_fuzzy (const char *psz_path /*flags, mode */, + uint16_t i_fuzz); + + /*! + Open an ISO 9660 image for reading with some tolerence for positioning + of the ISO9660 image. We scan for ISO_STANDARD_ID and use that to set + the eventual offset to adjust by (as long as that is <= i_fuzz). + + Maybe in the future we will have a mode. NULL is returned on error. + + @see iso9660_open_ext @see iso9660_open_fuzzy + */ + iso9660_t *iso9660_open_fuzzy_ext (const char *psz_path, + iso_extension_mask_t iso_extension_mask, + uint16_t i_fuzz + /*flags, mode */); + + /*! + Read the Super block of an ISO 9660 image but determine framesize + and datastart and a possible additional offset. Generally here we are + not reading an ISO 9660 image but a CD-Image which contains an ISO 9660 + filesystem. + */ + bool iso9660_ifs_fuzzy_read_superblock (iso9660_t *p_iso, + iso_extension_mask_t iso_extension_mask, + uint16_t i_fuzz); + + /*! + Seek to a position and then read i_size blocks. + + @param p_iso the ISO-9660 file image to get data from + + @param ptr place to put returned data. It should be able to store + a least i_size bytes + + @param start location to start reading from + + @param i_size number of blocks to read. Each block is ISO_BLOCKSIZE bytes + long. + + @return number of bytes (not blocks) read + + */ + long int iso9660_iso_seek_read (const iso9660_t *p_iso, /*out*/ void *ptr, + lsn_t start, long int i_size); + + /*! + Read the Primary Volume Descriptor for a CD. + True is returned if read, and false if there was an error. + */ + bool iso9660_fs_read_pvd ( const CdIo_t *p_cdio, + /*out*/ iso9660_pvd_t *p_pvd ); + + /*! + Read the Primary Volume Descriptor for an ISO 9660 image. + True is returned if read, and false if there was an error. + */ + bool iso9660_ifs_read_pvd (const iso9660_t *p_iso, + /*out*/ iso9660_pvd_t *p_pvd); + + /*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. + */ + bool iso9660_fs_read_superblock (CdIo_t *p_cdio, + iso_extension_mask_t iso_extension_mask); + + /*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. + */ + bool iso9660_ifs_read_superblock (iso9660_t *p_iso, + iso_extension_mask_t iso_extension_mask); + + +/*==================================================== + Time conversion + ====================================================*/ + + /*! + Set time in format used in ISO 9660 directory index record + from a Unix time structure. + */ + void iso9660_set_dtime (const struct tm *tm, + /*out*/ iso9660_dtime_t *idr_date); + + + /*! + Set time in format used in ISO 9660 directory index record + from a Unix time structure. timezone is given as an offset + correction in minutes. + */ + void iso9660_set_dtime_with_timezone (const struct tm *p_tm, + int timezone, + /*out*/ iso9660_dtime_t *p_idr_date); + + /*! + Set "long" time in format used in ISO 9660 primary volume descriptor + from a Unix time structure. */ + void iso9660_set_ltime (const struct tm *_tm, + /*out*/ iso9660_ltime_t *p_pvd_date); + + /*! + Set "long" time in format used in ISO 9660 primary volume descriptor + from a Unix time structure. */ + void iso9660_set_ltime_with_timezone (const struct tm *_tm, + int timezone, + /*out*/ iso9660_ltime_t *p_pvd_date); + + /*! + Get Unix time structure from format use in an ISO 9660 directory index + record. Even though tm_wday and tm_yday fields are not explicitly in + idr_date, they are calculated from the other fields. + + If tm is to reflect the localtime, set "b_localtime" true, otherwise + tm will reported in GMT. + */ + bool iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime, + /*out*/ struct tm *tm); + + + /*! + Get "long" time in format used in ISO 9660 primary volume descriptor + from a Unix time structure. + */ + bool iso9660_get_ltime (const iso9660_ltime_t *p_ldate, + /*out*/ struct tm *p_tm); + + /*==================================================== + Character Classification and String Manipulation + ====================================================*/ + /*! + Return true if c is a DCHAR - a character that can appear in an an + ISO-9600 level 1 directory name. These are the ASCII capital + letters A-Z, the digits 0-9 and an underscore. + */ + bool iso9660_is_dchar (int c); + + /*! + Return true if c is an ACHAR - + These are the DCHAR's plus some ASCII symbols including the space + symbol. + */ + bool iso9660_is_achar (int c); + + /*! + Convert an ISO-9660 file name which is in the format usually stored + in a ISO 9660 directory entry into what's usually listed as the + file name in a listing. Lowercase name, and remove trailing ;1's + or .;1's and turn the other ;'s into version numbers. + + @param psz_oldname the ISO-9660 filename to be translated. + @param psz_newname returned string. The caller allocates this and + it should be at least the size of psz_oldname. + @return length of the translated string is returned. + */ + int iso9660_name_translate(const char *psz_oldname, + /*out*/ char *psz_newname); + + /*! + Convert an ISO-9660 file name which is in the format usually stored + in a ISO 9660 directory entry into what's usually listed as the + file name in a listing. Lowercase name if no Joliet Extension + interpretation. Remove trailing ;1's or .;1's and turn the other + ;'s into version numbers. + + @param psz_oldname the ISO-9660 filename to be translated. + @param psz_newname returned string. The caller allocates this and + it should be at least the size of psz_oldname. + @param i_joliet_level 0 if not using Joliet Extension. Otherwise the + Joliet level. + @return length of the translated string is returned. It will be no greater + than the length of psz_oldname. + */ + int iso9660_name_translate_ext(const char *psz_oldname, char *psz_newname, + uint8_t i_joliet_level); + + /*! + Pad string src with spaces to size len and copy this to dst. If + len is less than the length of src, dst will be truncated to the + first len characters of src. + + src can also be scanned to see if it contains only ACHARs, DCHARs, + 7-bit ASCII chars depending on the enumeration _check. + + In addition to getting changed, dst is the return value. + Note: this string might not be NULL terminated. + */ + char *iso9660_strncpy_pad(char dst[], const char src[], size_t len, + enum strncpy_pad_check _check); + + /*===================================================================== + File and Directory Names + ======================================================================*/ + + /*! + Check that psz_path is a valid ISO-9660 directory name. + + A valid directory name should not start out with a slash (/), + dot (.) or null byte, should be less than 37 characters long, + have no more than 8 characters in a directory component + which is separated by a /, and consist of only DCHARs. + + True is returned if psz_path is valid. + */ + bool iso9660_dirname_valid_p (const char psz_path[]); + + /*! + Take psz_path and a version number and turn that into a ISO-9660 + pathname. (That's just the pathname followd by ";" and the version + number. For example, mydir/file.ext -> MYDIR/FILE.EXT;1 for version + 1. The resulting ISO-9660 pathname is returned. + */ + char *iso9660_pathname_isofy (const char psz_path[], uint16_t i_version); + + /*! + Check that psz_path is a valid ISO-9660 pathname. + + A valid pathname contains a valid directory name, if one appears and + the filename portion should be no more than 8 characters for the + file prefix and 3 characters in the extension (or portion after a + dot). There should be exactly one dot somewhere in the filename + portion and the filename should be composed of only DCHARs. + + True is returned if psz_path is valid. + */ + bool iso9660_pathname_valid_p (const char psz_path[]); + +/*===================================================================== + directory tree +======================================================================*/ + +void +iso9660_dir_init_new (void *dir, uint32_t self, uint32_t ssize, + uint32_t parent, uint32_t psize, + const time_t *dir_time); + +void +iso9660_dir_init_new_su (void *dir, uint32_t self, uint32_t ssize, + const void *ssu_data, unsigned int ssu_size, + uint32_t parent, uint32_t psize, + const void *psu_data, unsigned int psu_size, + const time_t *dir_time); + +void +iso9660_dir_add_entry_su (void *dir, const char filename[], uint32_t extent, + uint32_t size, uint8_t file_flags, + const void *su_data, + unsigned int su_size, const time_t *entry_time); + +unsigned int +iso9660_dir_calc_record_size (unsigned int namelen, unsigned int su_len); + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + @return stat_t of entry if we found lsn, or NULL otherwise. + Caller must free return value. + */ +#define iso9660_fs_find_lsn iso9660_find_fs_lsn +iso9660_stat_t *iso9660_fs_find_lsn(CdIo_t *p_cdio, lsn_t i_lsn); + + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + @return stat_t of entry if we found lsn, or NULL otherwise. + Caller must free return value. + */ +iso9660_stat_t *iso9660_fs_find_lsn_with_path(CdIo_t *p_cdio, lsn_t i_lsn, + /*out*/ char **ppsz_path); + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + @return stat_t of entry if we found lsn, or NULL otherwise. + Caller must free return value. + */ +iso9660_stat_t *iso9660_ifs_find_lsn(iso9660_t *p_iso, lsn_t i_lsn); + + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + @param p_iso pointer to iso_t + @param i_lsn LSN to find + @param ppsz_path full path of lsn filename. On entry *ppsz_path should be + NULL. On return it will be allocated an point to the full path of the + file at lsn or NULL if the lsn is not found. You should deallocate + *ppsz_path when you are done using it. + + @return stat_t of entry if we found lsn, or NULL otherwise. + Caller must free return value. + */ +iso9660_stat_t *iso9660_ifs_find_lsn_with_path(iso9660_t *p_iso, + lsn_t i_lsn, + /*out*/ char **ppsz_path); + + +/*! + Return file status for psz_path. NULL is returned on error. + + @param p_cdio the CD object to read from + + @param psz_path filename path to look up and get information about + + @return ISO 9660 file information + + Important note: + + You make get different results looking up "/" versus "/." and the + latter may give more complete information. "/" will take information + from the PVD only, whereas "/." will force a directory read of "/" and + find "." and in that Rock-Ridge information might be found which fills + in more stat information. Ideally iso9660_fs_stat should be fixed. + Patches anyone? + */ +iso9660_stat_t *iso9660_fs_stat (CdIo_t *p_cdio, const char psz_path[]); + + +/*! + Return file status for path name psz_path. NULL is returned on error. + pathname version numbers in the ISO 9660 name are dropped, i.e. ;1 + is removed and if level 1 ISO-9660 names are lowercased. + + b_mode2 is historical. It is not used. + */ +iso9660_stat_t *iso9660_fs_stat_translate (CdIo_t *p_cdio, + const char psz_path[], + bool b_mode2); + +/*! + Return file status for pathname. NULL is returned on error. + */ +iso9660_stat_t *iso9660_ifs_stat (iso9660_t *p_iso, const char psz_path[]); + + +/*! Return file status for path name psz_path. NULL is returned on + error. pathname version numbers in the ISO 9660 name are dropped, + i.e. ;1 is removed and if level 1 ISO-9660 names are lowercased. + */ +iso9660_stat_t *iso9660_ifs_stat_translate (iso9660_t *p_iso, + const char psz_path[]); + +/*! Read psz_path (a directory) and return a list of iso9660_stat_t + pointers for the files inside that directory. The caller must free the + returned result. + + b_mode2 is historical. It is not used. +*/ +CdioList_t * iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], + bool b_mode2); + +/*! Read psz_path (a directory) and return a list of iso9660_stat_t + pointers for the files inside that directory. The caller must free + the returned result. +*/ +CdioList_t * iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]); + +/*! + Return the PVD's application ID. + NULL is returned if there is some problem in getting this. +*/ +char * iso9660_get_application_id(iso9660_pvd_t *p_pvd); + +/*! + Get the application ID. psz_app_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_application_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_app_id); + +/*! + Return the Joliet level recognized for p_iso. +*/ +uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso); + +uint8_t iso9660_get_dir_len(const iso9660_dir_t *p_idr); + +#ifdef FIXME +uint8_t iso9660_get_dir_size(const iso9660_dir_t *p_idr); + +lsn_t iso9660_get_dir_extent(const iso9660_dir_t *p_idr); +#endif + + /*! + Return the directory name stored in the iso9660_dir_t + + A string is allocated: the caller must deallocate. This routine + can return NULL if memory allocation fails. + */ + char * iso9660_dir_to_name (const iso9660_dir_t *p_iso9660_dir); + + /*! + Returns a POSIX mode for a given p_iso_dirent. + */ + mode_t iso9660_get_posix_filemode(const iso9660_stat_t *p_iso_dirent); + + /*! + Return a string containing the preparer id with trailing + blanks removed. + */ + char *iso9660_get_preparer_id(const iso9660_pvd_t *p_pvd); + + /*! + Get the preparer ID. psz_preparer_id is set to NULL if there + is some problem in getting this and false is returned. + */ + bool iso9660_ifs_get_preparer_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_preparer_id); + + /*! + Return a string containing the PVD's publisher id with trailing + blanks removed. + */ + char *iso9660_get_publisher_id(const iso9660_pvd_t *p_pvd); + + /*! + Get the publisher ID. psz_publisher_id is set to NULL if there + is some problem in getting this and false is returned. + */ + bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_publisher_id); + + uint8_t iso9660_get_pvd_type(const iso9660_pvd_t *p_pvd); + + const char * iso9660_get_pvd_id(const iso9660_pvd_t *p_pvd); + + int iso9660_get_pvd_space_size(const iso9660_pvd_t *p_pvd); + + int iso9660_get_pvd_block_size(const iso9660_pvd_t *p_pvd) ; + + /*! Return the primary volume id version number (of pvd). + If there is an error 0 is returned. + */ + int iso9660_get_pvd_version(const iso9660_pvd_t *pvd) ; + + /*! + Return a string containing the PVD's system id with trailing + blanks removed. + */ + char *iso9660_get_system_id(const iso9660_pvd_t *p_pvd); + + /*! + Get the system ID. psz_system_id is set to NULL if there + is some problem in getting this and false is returned. + */ + bool iso9660_ifs_get_system_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_system_id); + + + /*! Return the LSN of the root directory for pvd. + If there is an error CDIO_INVALID_LSN is returned. + */ + lsn_t iso9660_get_root_lsn(const iso9660_pvd_t *p_pvd); + + /*! + Get the volume ID in the PVD. psz_volume_id is set to NULL if there + is some problem in getting this and false is returned. + */ + char *iso9660_get_volume_id(const iso9660_pvd_t *p_pvd); + + /*! + Get the volume ID in the PVD. psz_volume_id is set to NULL if there + is some problem in getting this and false is returned. + */ + bool iso9660_ifs_get_volume_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_volume_id); + + /*! + Return the volumeset ID in the PVD. + NULL is returned if there is some problem in getting this. + */ + char *iso9660_get_volumeset_id(const iso9660_pvd_t *p_pvd); + + /*! + Get the volumeset ID. psz_systemset_id is set to NULL if there + is some problem in getting this and false is returned. + */ + bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_volumeset_id); + + /* pathtable */ + + /*! Zero's out pathable. Do this first. */ + void iso9660_pathtable_init (void *pt); + + unsigned int iso9660_pathtable_get_size (const void *pt); + + uint16_t iso9660_pathtable_l_add_entry (void *pt, const char name[], + uint32_t extent, uint16_t parent); + + uint16_t iso9660_pathtable_m_add_entry (void *pt, const char name[], + uint32_t extent, uint16_t parent); + + /**===================================================================== + Volume Descriptors + ======================================================================*/ + + void iso9660_set_pvd (void *pd, const char volume_id[], + const char application_id[], + const char publisher_id[], const char preparer_id[], + uint32_t iso_size, const void *root_dir, + uint32_t path_table_l_extent, + uint32_t path_table_m_extent, + uint32_t path_table_size, const time_t *pvd_time); + + void iso9660_set_evd (void *pd); + + /*! + Return true if ISO 9660 image has extended attrributes (XA). + */ + bool iso9660_ifs_is_xa (const iso9660_t * p_iso); + + +#ifndef DO_NOT_WANT_COMPATIBILITY +/** For compatibility with < 0.77 */ +#define iso9660_isdchar iso9660_is_dchar +#define iso9660_isachar iso9660_is_achar +#endif /*DO_NOT_WANT_COMPATIBILITY*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#undef ISODCL +#endif /* __CDIO_ISO9660_H__ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/logging.h b/src/libcdio/cdio/logging.h new file mode 100644 index 00000000..ad1f5d95 --- /dev/null +++ b/src/libcdio/cdio/logging.h @@ -0,0 +1,140 @@ +/* + $Id: logging.h,v 1.11 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2003, 2004, 2008 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +/** \file logging.h + * \brief Header to control logging and level of detail of output. + * + */ + +#ifndef __LOGGING_H__ +#define __LOGGING_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The different log levels supported. + */ +typedef enum { + CDIO_LOG_DEBUG = 1, /**< Debug-level messages - helps debug what's up. */ + CDIO_LOG_INFO, /**< Informational - indicates perhaps something of + interest. */ + CDIO_LOG_WARN, /**< Warning conditions - something that looks funny. */ + CDIO_LOG_ERROR, /**< Error conditions - may terminate program. */ + CDIO_LOG_ASSERT /**< Critical conditions - may abort program. */ +} cdio_log_level_t; + +/** + * The place to save the preference concerning how much verbosity + * is desired. This is used by the internal default log handler, but + * it could be use by applications which provide their own log handler. + */ +extern cdio_log_level_t cdio_loglevel_default; + +/** + * This type defines the signature of a log handler. For every + * message being logged, the handler will receive the log level and + * the message string. + * + * @see cdio_log_set_handler + * @see cdio_log_level_t + * + * @param level The log level. + * @param message The log message. + */ +typedef void (*cdio_log_handler_t) (cdio_log_level_t level, + const char message[]); + +/** + * Set a custom log handler for libcdio. The return value is the log + * handler being replaced. If the provided parameter is NULL, then + * the handler will be reset to the default handler. + * + * @see cdio_log_handler_t + * + * @param new_handler The new log handler. + * @return The previous log handler. + */ +cdio_log_handler_t cdio_log_set_handler (cdio_log_handler_t new_handler); + +/** + * Handle an message with the given log level. + * + * @see cdio_debug + * @see cdio_info + * @see cdio_warn + * @see cdio_error + + * @param level The log level. + * @param format printf-style format string + * @param ... remaining arguments needed by format string + */ +void cdio_log (cdio_log_level_t level, + const char format[], ...) GNUC_PRINTF(2, 3); +#if defined(__GNUC__) +/* See http://clang-analyzer.llvm.org/annotations.html#custom_assertions */ +void cdio_assert_log (const char format[], ...) + GNUC_PRINTF(1, 2) __attribute__((__noreturn__)); +#endif +/** + * Handle a debugging message. + * + * @see cdio_log for a more generic routine + */ +void cdio_debug (const char format[], ...) GNUC_PRINTF(1,2); + +/** + * Handle an informative message. + * + * @see cdio_log for a more generic routine + */ +void cdio_info (const char format[], ...) GNUC_PRINTF(1,2); + +/** + * Handle a warning message. + * + * @see cdio_log for a more generic routine + */ +void cdio_warn (const char format[], ...) GNUC_PRINTF(1,2); + +/** + * Handle an error message. Execution is terminated. + * + * @see cdio_log for a more generic routine. + */ +void cdio_error (const char format[], ...) GNUC_PRINTF(1,2); + +#ifdef __cplusplus +} +#endif + +#endif /* __LOGGING_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/posix.h b/src/libcdio/cdio/posix.h new file mode 100644 index 00000000..89e0ad37 --- /dev/null +++ b/src/libcdio/cdio/posix.h @@ -0,0 +1,43 @@ +/* + $Id: posix.h,v 1.2 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2005, 2008 Rocky Bernstein + + 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 3 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, see . +*/ +/*! + * \file posix.h + * + * \brief various POSIX definitions. +*/ + +#ifndef __CDIO_POSIX_H__ +#define __CDIO_POSIX_H__ + +typedef uint32_t posix_mode_t; +typedef uint32_t posix_nlink_t; +typedef uint32_t posix_uid_t; +typedef uint32_t posix_gid_t; +typedef uint16_t unicode16_t; + +#endif /* __CDIO_POSIX_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/read.h b/src/libcdio/cdio/read.h new file mode 100644 index 00000000..bc13b5f7 --- /dev/null +++ b/src/libcdio/cdio/read.h @@ -0,0 +1,226 @@ +/* + $Id: read.h,v 1.15 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2005, 2006, 2007, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +/** \file read.h + * + * \brief The top-level header for sector (block, frame)-related + * libcdio calls. + */ + +#ifndef __CDIO_READ_H__ +#define __CDIO_READ_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /** All the different ways a block/sector can be read. */ + typedef enum { + CDIO_READ_MODE_AUDIO, /**< CD-DA, audio, Red Book */ + CDIO_READ_MODE_M1F1, /**< Mode 1 Form 1 */ + CDIO_READ_MODE_M1F2, /**< Mode 1 Form 2 */ + CDIO_READ_MODE_M2F1, /**< Mode 2 Form 1 */ + CDIO_READ_MODE_M2F2 /**< Mode 2 Form 2 */ + } cdio_read_mode_t; + + /*! + Reposition read offset + Similar to (if not the same as) libc's fseek() + + @param p_cdio object which gets adjusted + @param offset amount to seek + @param whence like corresponding parameter in libc's fseek, e.g. + SEEK_SET or SEEK_END. + @return (off_t) -1 on error. + */ + + off_t cdio_lseek(const CdIo_t *p_cdio, off_t offset, int whence); + + /*! Reads into buf the next size bytes. Similar to (if not the + same as) libc's read(). This is a "cooked" read, or one handled by + the OS. It probably won't work on audio data. For that use + cdio_read_audio_sector(s). + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least i_size bytes. + @param i_size number of bytes to read + + @return (ssize_t) -1 on error. + */ + ssize_t cdio_read(const CdIo_t *p_cdio, void *p_buf, size_t i_size); + + /*! + Read an audio sector + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least CDIO_FRAMESIZE_RAW + bytes. + @param i_lsn sector to read + */ + driver_return_code_t cdio_read_audio_sector (const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn); + + /*! + Reads audio sectors + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least CDIO_FRAMESIZE_RAW + * i_blocks bytes. + @param i_lsn sector to read + @param i_blocks number of sectors to read + */ + driver_return_code_t cdio_read_audio_sectors (const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn, + uint32_t i_blocks); + + /*! + Read data sectors + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least ISO_BLOCKSIZE, + M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE depending + on the kind of sector getting read. If you don't + know whether you have a Mode 1/2, Form 1/ Form 2/Formless + sector best to reserve space for the maximum, + M2RAW_SECTOR_SIZE. + @param i_lsn sector to read + @param i_blocksize size of block. Should be either CDIO_CD_FRAMESIZE, + M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under p_buf. + + @param i_blocks number of blocks to read + */ + driver_return_code_t cdio_read_data_sectors ( const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn, + uint16_t i_blocksize, + uint32_t i_blocks ); + /*! + Reads a mode 1 sector + + @param p_cdio object to read from + @param p_buf place to read data into. + @param i_lsn sector to read + @param b_form2 true for reading mode 1 form 2 sectors or false for + mode 1 form 1 sectors. + */ + driver_return_code_t cdio_read_mode1_sector (const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn, + bool b_form2); + /*! + Reads mode 1 sectors + + @param p_cdio object to read from + @param p_buf place to read data into + @param i_lsn sector to read + @param b_form2 true for reading mode 1 form 2 sectors or false for + mode 1 form 1 sectors. + @param i_blocks number of sectors to read + */ + driver_return_code_t cdio_read_mode1_sectors (const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn, + bool b_form2, + uint32_t i_blocks); + /*! + Reads a mode 2 sector + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least + M2RAW_SECTOR_SIZE (for form 1) or CDIO_CD_FRAMESIZE (for + form 2) bytes. + @param i_lsn sector to read + @param b_form2 true for reading mode 2 form 2 sectors or false for + mode 2 form 1 sectors. + + @return 0 if no error, nonzero otherwise. + */ + driver_return_code_t cdio_read_mode2_sector (const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn, + bool b_form2); + + /** The special case of reading a single block is a common one so we + provide a routine for that as a convenience. + */ + driver_return_code_t cdio_read_sector(const CdIo_t *p_cdio, void *p_buf, + lsn_t i_lsn, + cdio_read_mode_t read_mode); + /*! + Reads mode 2 sectors + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least + M2RAW_SECTOR_SIZE (for form 1) or CDIO_CD_FRAMESIZE (for + form 2) * i_blocks bytes. + @param i_lsn sector to read + @param b_form2 true for reading mode2 form 2 sectors or false for + mode 2 form 1 sectors. + @param i_blocks number of sectors to read + + @return 0 if no error, nonzero otherwise. + */ + driver_return_code_t cdio_read_mode2_sectors (const CdIo_t *p_cdio, + void *p_buf, lsn_t i_lsn, + bool b_form2, + uint32_t i_blocks); + + /*! + Reads a number of sectors (AKA blocks). + + @param p_cdio cdio object + @param p_buf place to read data into. The caller should make sure + this location is large enough. See below for size information. + @param read_mode the kind of "mode" to use in reading. + @param i_lsn sector to read + @param i_blocks number of sectors to read + @return DRIVER_OP_SUCCESS (0) if no error, other (negative) enumerations + are returned on error. + + If read_mode is CDIO_MODE_AUDIO, + *p_buf should hold at least CDIO_FRAMESIZE_RAW * i_blocks bytes. + + If read_mode is CDIO_MODE_DATA, + *p_buf should hold at least i_blocks times either ISO_BLOCKSIZE, + M1RAW_SECTOR_SIZE or M2F2_SECTOR_SIZE depending on the kind of + sector getting read. If you don't know whether you have a Mode 1/2, + Form 1/ Form 2/Formless sector best to reserve space for the maximum + which is M2RAW_SECTOR_SIZE. + + If read_mode is CDIO_MODE_M2F1, + *p_buf should hold at least M2RAW_SECTOR_SIZE * i_blocks bytes. + + If read_mode is CDIO_MODE_M2F2, + *p_buf should hold at least CDIO_CD_FRAMESIZE * i_blocks bytes. + + */ + driver_return_code_t cdio_read_sectors(const CdIo_t *p_cdio, void *p_buf, + lsn_t i_lsn, + cdio_read_mode_t read_mode, + uint32_t i_blocks); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_TRACK_H__ */ diff --git a/src/libcdio/cdio/rock.h b/src/libcdio/cdio/rock.h new file mode 100644 index 00000000..3a24f911 --- /dev/null +++ b/src/libcdio/cdio/rock.h @@ -0,0 +1,384 @@ +/* + Copyright (C) 2005, 2006 2008 Rocky Bernstein + + See also rock.c by Eric Youngdale (1993) from GNU/Linux + This is Copyright 1993 Yggdrasil Computing, Incorporated + + 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 3 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, see . +*/ +/*! + \file rock.h + \brief Things related to the Rock Ridge Interchange Protocol (RRIP) + + Applications will probably not include this directly but via + the iso9660.h header. +*/ + + +#ifndef __CDIO_ROCK_H__ +#define __CDIO_ROCK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*! An enumeration for some of the ISO_ROCK_* \#defines below. This isn't + really an enumeration one would really use in a program it is to + be helpful in debuggers where wants just to refer to the ISO_ROCK_* + names and get something. +*/ +extern enum iso_rock_enums { + ISO_ROCK_IRUSR = 000400, /**< read permission (owner) */ + ISO_ROCK_IWUSR = 000200, /**< write permission (owner) */ + ISO_ROCK_IXUSR = 000100, /**< execute permission (owner) */ + ISO_ROCK_IRGRP = 000040, /**< read permission (group) */ + ISO_ROCK_IWGRP = 000020, /**< write permission (group) */ + ISO_ROCK_IXGRP = 000010, /**< execute permission (group) */ + ISO_ROCK_IROTH = 000004, /**< read permission (other) */ + ISO_ROCK_IWOTH = 000002, /**< write permission (other) */ + ISO_ROCK_IXOTH = 000001, /**< execute permission (other) */ + + ISO_ROCK_ISUID = 004000, /**< set user ID on execution */ + ISO_ROCK_ISGID = 002000, /**< set group ID on execution */ + ISO_ROCK_ISVTX = 001000, /**< save swapped text even after use */ + + ISO_ROCK_ISSOCK = 0140000, /**< socket */ + ISO_ROCK_ISLNK = 0120000, /**< symbolic link */ + ISO_ROCK_ISREG = 0100000, /**< regular */ + ISO_ROCK_ISBLK = 060000, /**< block special */ + ISO_ROCK_ISCHR = 020000, /**< character special */ + ISO_ROCK_ISDIR = 040000, /**< directory */ + ISO_ROCK_ISFIFO = 010000 /**< pipe or FIFO */ +} iso_rock_enums; + +#define ISO_ROCK_IRUSR 000400 /** read permission (owner) */ +#define ISO_ROCK_IWUSR 000200 /** write permission (owner) */ +#define ISO_ROCK_IXUSR 000100 /** execute permission (owner) */ +#define ISO_ROCK_IRGRP 000040 /** read permission (group) */ +#define ISO_ROCK_IWGRP 000020 /** write permission (group) */ +#define ISO_ROCK_IXGRP 000010 /** execute permission (group) */ +#define ISO_ROCK_IROTH 000004 /** read permission (other) */ +#define ISO_ROCK_IWOTH 000002 /** write permission (other) */ +#define ISO_ROCK_IXOTH 000001 /** execute permission (other) */ + +#define ISO_ROCK_ISUID 004000 /** set user ID on execution */ +#define ISO_ROCK_ISGID 002000 /** set group ID on execution */ +#define ISO_ROCK_ISVTX 001000 /** save swapped text even after use */ + +#define ISO_ROCK_ISSOCK 0140000 /** socket */ +#define ISO_ROCK_ISLNK 0120000 /** symbolic link */ +#define ISO_ROCK_ISREG 0100000 /** regular */ +#define ISO_ROCK_ISBLK 060000 /** block special */ +#define ISO_ROCK_ISCHR 020000 /** character special */ +#define ISO_ROCK_ISDIR 040000 /** directory */ +#define ISO_ROCK_ISFIFO 010000 /** pipe or FIFO */ + +/** Enforced file locking (shared w/set group ID) */ +#define ISO_ROCK_ENFMT ISO_ROCK_ISGID + +PRAGMA_BEGIN_PACKED + +/*! The next two structs are used by the system-use-sharing protocol + (SUSP), in which the Rock Ridge extensions are embedded. It is + quite possible that other extensions are present on the disk, and + this is fine as long as they all use SUSP. */ + +/*! system-use-sharing protocol */ +typedef struct iso_su_sp_s{ + unsigned char magic[2]; + uint8_t skip; +} GNUC_PACKED iso_su_sp_t; + +/*! system-use extension record */ +typedef struct iso_su_er_s { + iso711_t len_id; /**< Identifier length. Value 10?. */ + unsigned char len_des; + unsigned char len_src; + iso711_t ext_ver; /**< Extension version. Value 1? */ + char data[EMPTY_ARRAY_SIZE]; +} GNUC_PACKED iso_su_er_t; + +typedef struct iso_su_ce_s { + char extent[8]; + char offset[8]; + char size[8]; +} iso_su_ce_t; + +/*! POSIX file attributes, PX. See Rock Ridge Section 4.1.2 */ +typedef struct iso_rock_px_s { + iso733_t st_mode; /*! file mode permissions; same as st_mode + of POSIX:5.6.1 */ + iso733_t st_nlinks; /*! number of links to file; same as st_nlinks + of POSIX:5.6.1 */ + iso733_t st_uid; /*! user id owner of file; same as st_uid + of POSIX:5.6.1 */ + iso733_t st_gid; /*! group id of file; same as st_gid of + of POSIX:5.6.1 */ +} GNUC_PACKED iso_rock_px_t ; + +/*! POSIX device number, PN. A PN is mandatory if the file type + recorded in the "PX" File Mode field for a Directory Record + indicates a character or block device (ISO_ROCK_ISCHR | + ISO_ROCK_ISBLK). This entry is ignored for other (non-Direcotry) + file types. No more than one "PN" is recorded in the System Use Area + of a Directory Record. + + See Rock Ridge Section 4.1.2 */ +typedef struct iso_rock_pn_s { + iso733_t dev_high; /**< high-order 32 bits of the 64 bit device number. + 7.2.3 encoded */ + iso733_t dev_low; /**< low-order 32 bits of the 64 bit device number. + 7.2.3 encoded */ +} GNUC_PACKED iso_rock_pn_t ; + +/*! These are the bits and their meanings for flags in the SL structure. */ +typedef enum { + ISO_ROCK_SL_CONTINUE = 1, + ISO_ROCK_SL_CURRENT = 2, + ISO_ROCK_SL_PARENT = 4, + ISO_ROCK_SL_ROOT = 8 +} iso_rock_sl_flag_t; + +#define ISO_ROCK_SL_CONTINUE 1 +#define ISO_ROCK_SL_CURRENT 2 +#define ISO_ROCK_SL_PARENT 4 +#define ISO_ROCK_SL_ROOT 8 + +typedef struct iso_rock_sl_part_s { + uint8_t flags; + uint8_t len; + char text[EMPTY_ARRAY_SIZE]; +} GNUC_PACKED iso_rock_sl_part_t ; + +/*! Symbolic link. See Rock Ridge Section 4.1.3 */ +typedef struct iso_rock_sl_s { + unsigned char flags; + iso_rock_sl_part_t link; +} GNUC_PACKED iso_rock_sl_t ; + +/*! Alternate name. See Rock Ridge Section 4.1.4 */ + +/*! These are the bits and their meanings for flags in the NM structure. */ +typedef enum { + ISO_ROCK_NM_CONTINUE = 1, + ISO_ROCK_NM_CURRENT = 2, + ISO_ROCK_NM_PARENT = 4, +} iso_rock_nm_flag_t; + +#define ISO_ROCK_NM_CONTINUE 1 +#define ISO_ROCK_NM_CURRENT 2 +#define ISO_ROCK_NM_PARENT 4 + + +typedef struct iso_rock_nm_s { + unsigned char flags; + char name[EMPTY_ARRAY_SIZE]; +} GNUC_PACKED iso_rock_nm_t ; + +/*! Child link. See Section 4.1.5.1 */ +typedef struct iso_rock_cl_s { + char location[1]; +} GNUC_PACKED iso_rock_cl_t ; + +/*! Parent link. See Section 4.1.5.2 */ +typedef struct iso_rock_pl_s { + char location[1]; +} GNUC_PACKED iso_rock_pl_t ; + +/*! These are the bits and their meanings for flags in the TF structure. */ +typedef enum { + ISO_ROCK_TF_CREATE = 1, + ISO_ROCK_TF_MODIFY = 2, + ISO_ROCK_TF_ACCESS = 4, + ISO_ROCK_TF_ATTRIBUTES = 8, + ISO_ROCK_TF_BACKUP = 16, + ISO_ROCK_TF_EXPIRATION = 32, + ISO_ROCK_TF_EFFECTIVE = 64, + ISO_ROCK_TF_LONG_FORM = 128 +} iso_rock_tf_flag_t; + +/* These are the bits and their meanings for flags in the TF structure. */ +#define ISO_ROCK_TF_CREATE 1 +#define ISO_ROCK_TF_MODIFY 2 +#define ISO_ROCK_TF_ACCESS 4 +#define ISO_ROCK_TF_ATTRIBUTES 8 +#define ISO_ROCK_TF_BACKUP 16 +#define ISO_ROCK_TF_EXPIRATION 32 +#define ISO_ROCK_TF_EFFECTIVE 64 +#define ISO_ROCK_TF_LONG_FORM 128 + +/*! Time stamp(s) for a file. See Rock Ridge Section 4.1.6 */ +typedef struct iso_rock_tf_s { + uint8_t flags; /**< See ISO_ROCK_TF_* bits above. */ + uint8_t time_bytes[EMPTY_ARRAY_SIZE]; /**< A homogenious array of + iso9660_ltime_t or + iso9660_dtime_t entries + depending on flags & + ISO_ROCK_TF_LONG_FORM. Lacking + a better method, we store + this as an array of bytes + and a cast to the + appropriate type will have + to be made before + extraction. */ +} GNUC_PACKED iso_rock_tf_t ; + +/*! File data in sparse format. See Rock Ridge Section 4.1.7 */ +typedef struct iso_rock_sf_s { + iso733_t virtual_size_high; /**< high-order 32 bits of virtual size */ + iso733_t virtual_size_low; /**< low-order 32 bits of virtual size */ + uint8_t table_depth; +} GNUC_PACKED iso_rock_sf_t ; + +typedef struct iso_extension_record_s { + char signature[2]; /**< signature word; either 'SP', 'CE', 'ER', 'RR', + 'PX', 'PN', 'SL', 'NM', 'CL', 'PL', 'TF', or + 'ZF' */ + iso711_t len; /**< length of system-user area - 44 for PX + 20 for PN, 5+strlen(text) for SL, 21 for + SF, etc. */ + iso711_t version; /**< version number - value 1 */ + union { + iso_su_sp_t SP; /**< system-use-sharing protocol - not + strictly part of Rock Ridge */ + iso_su_er_t ER; /**< system-use extension packet - not + strictly part of Rock Ridge */ + iso_su_ce_t CE; /**< system-use - strictly part of Rock Ridge */ + iso_rock_px_t PX; /**< Rock Ridge POSIX file attributes */ + iso_rock_pn_t PN; /**< Rock Ridge POSIX device number */ + iso_rock_sl_t SL; /**< Rock Ridge symbolic link */ + iso_rock_nm_t NM; /**< Rock Ridge alternate name */ + iso_rock_cl_t CL; /**< Rock Ridge child link */ + iso_rock_pl_t PL; /**< Rock Ridge parent link */ + iso_rock_tf_t TF; /**< Rock Ridge timestamp(s) for a file */ + } u; +} GNUC_PACKED iso_extension_record_t; + +typedef struct iso_rock_time_s { + bool b_used; /**< If true, field has been set and is valid. + Otherwise remaning fields are meaningless. */ + bool b_longdate; /**< If true date format is a iso9660_ltime_t. + Otherwise date is iso9660_dtime_t */ + union + { + iso9660_ltime_t ltime; + iso9660_dtime_t dtime; + } t; +} GNUC_PACKED iso_rock_time_t; + +typedef struct iso_rock_statbuf_s { + bool_3way_t b3_rock; /**< has Rock Ridge extension. + If "yep", then the fields + are used. + */ + posix_mode_t st_mode; /**< protection */ + posix_nlink_t st_nlinks; /**< number of hard links */ + posix_uid_t st_uid; /**< user ID of owner */ + posix_gid_t st_gid; /**< group ID of owner */ + uint8_t s_rock_offset; + int i_symlink; /**< size of psz_symlink */ + int i_symlink_max; /**< max allocated to psz_symlink */ + char *psz_symlink; /**< if symbolic link, name + of pointed to file. */ + iso_rock_time_t create; /**< create time See ISO 9660:9.5.4. */ + iso_rock_time_t modify; /**< time of last modification + ISO 9660:9.5.5. st_mtime field of + POSIX:5.6.1. */ + iso_rock_time_t access; /**< time of last file access st_atime + field of POSIX:5.6.1. */ + iso_rock_time_t attributes; /**< time of last attribute change. + st_ctime field of POSIX:5.6.1. */ + iso_rock_time_t backup; /**< time of last backup. */ + iso_rock_time_t expiration; /**< time of expiration; See ISO + 9660:9.5.6. */ + iso_rock_time_t effective; /**< Effective time; See ISO 9660:9.5.7. + */ + uint32_t i_rdev; /**< the upper 16-bits is major device + number, the lower 16-bits is the + minor device number */ + +} iso_rock_statbuf_t; + +PRAGMA_END_PACKED + +/*! return length of name field; 0: not found, -1: to be ignored */ +int get_rock_ridge_filename(iso9660_dir_t * de, /*out*/ char * retname, + /*out*/ iso9660_stat_t *p_stat); + + int parse_rock_ridge_stat(iso9660_dir_t *de, /*out*/ iso9660_stat_t *p_stat); + + /*! + Returns POSIX mode bitstring for a given file. + */ + mode_t + iso9660_get_posix_filemode_from_rock(const iso_rock_statbuf_t *rr); + +/*! + Returns a string which interpreting the POSIX mode st_mode. + For example: + \verbatim + drwxrws--- + -rw---Sr-- + lrwxrwxrwx + \endverbatim + + A description of the characters in the string follows + The 1st character is either "d" if the entry is a directory, "l" is + a symbolic link or "-" if neither. + + The 2nd to 4th characters refer to permissions for a user while the + the 5th to 7th characters refer to permissions for a group while, and + the 8th to 10h characters refer to permissions for everyone. + + In each of these triplets the first character (2, 5, 8) is "r" if + the entry is allowed to be read. + + The second character of a triplet (3, 6, 9) is "w" if the entry is + allowed to be written. + + The third character of a triplet (4, 7, 10) is "x" if the entry is + executable but not user (for character 4) or group (for characters + 6) settable and "s" if the item has the corresponding user/group set. + + For a directory having an executable property on ("x" or "s") means + the directory is allowed to be listed or "searched". If the execute + property is not allowed for a group or user but the corresponding + group/user is set "S" indicates this. If none of these properties + holds the "-" indicates this. +*/ +const char *iso9660_get_rock_attr_str(posix_mode_t st_mode); + +/** These variables are not used, but are defined to facilatate debugging + by letting us use enumerations values (which also correspond to + \#define's inside a debugged program. + */ +extern iso_rock_nm_flag_t iso_rock_nm_flag; +extern iso_rock_sl_flag_t iso_rock_sl_flag; +extern iso_rock_tf_flag_t iso_rock_tf_flag; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ISO_ROCK_H__ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/sector.h b/src/libcdio/cdio/sector.h new file mode 100644 index 00000000..6e308338 --- /dev/null +++ b/src/libcdio/cdio/sector.h @@ -0,0 +1,286 @@ +/* + $Id: sector.h,v 1.38 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2003, 2004, 2005, 2006, 2008 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ +/*! + \file sector.h + \brief Things related to CD-ROM layout: tracks, sector sizes, MSFs, LBAs. + + A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, + 2340, or 2352 bytes long. + + Sector types of the standard CD-ROM data formats: + +\verbatim + format sector type user data size (bytes) + ----------------------------------------------------------------------------- + 1 (Red Book) CD-DA 2352 (CDIO_CD_FRAMESIZE_RAW) + 2 (Yellow Book) Mode1 Form1 2048 (CDIO_CD_FRAMESIZE) + 3 (Yellow Book) Mode1 Form2 2336 (M2RAW_SECTOR_SIZE) + 4 (Green Book) Mode2 Form1 2048 (CDIO_CD_FRAMESIZE) + 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) + + + The layout of the standard CD-ROM data formats: + ----------------------------------------------------------------------------- + - audio (red): | audio_sample_bytes | + | 2352 | + + - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | + | 12 - 4 - 2048 - 4 - 8 - 276 | + + - data (yellow, mode2): | sync - head - data | + | 12 - 4 - 2336 | + + - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | + | 12 - 4 - 8 - 2048 - 4 - 276 | + + - XA data (green, mode2 form2): | sync - head - sub - data - Spare | + | 12 - 4 - 8 - 2324 - 4 | +\endverbatim + + +*/ + +#ifndef _CDIO_SECTOR_H_ +#define _CDIO_SECTOR_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include + + /*! Information that can be obtained through a Read Subchannel + command. + */ +#define CDIO_SUBCHANNEL_SUBQ_DATA 0 +#define CDIO_SUBCHANNEL_CURRENT_POSITION 1 +#define CDIO_SUBCHANNEL_MEDIA_CATALOG 2 +#define CDIO_SUBCHANNEL_TRACK_ISRC 3 + + /*! track flags + * Q Sub-channel Control Field (4.2.3.3) + */ + typedef enum { + NONE = 0x00, /* no flags set */ + PRE_EMPHASIS = 0x01, /* audio track recorded with pre-emphasis */ + COPY_PERMITTED = 0x02, /* digital copy permitted */ + DATA = 0x04, /* data track */ + FOUR_CHANNEL_AUDIO = 0x08, /* 4 audio channels */ + SCMS = 0x10 /* SCMS (5.29.2.7) */ + } flag_t; + +#define CDIO_PREGAP_SECTORS 150 +#define CDIO_POSTGAP_SECTORS 150 + + /*! An enumeration for some of the CDIO_CD \#defines below. This isn't + really an enumeration one would really use in a program it is to + be helpful in debuggers where wants just to refer to the CDIO_CD_ + names and get something. + */ + extern enum cdio_cd_enums { + CDIO_CD_MINS = 74, /**< max. minutes per CD, not really + a limit */ + CDIO_CD_SECS_PER_MIN = 60, /**< seconds per minute */ + CDIO_CD_FRAMES_PER_SEC = 75, /**< frames per second */ + CDIO_CD_SYNC_SIZE = 12, /**< 12 sync bytes per raw data + frame */ + CDIO_CD_CHUNK_SIZE = 24, /**< lowest-level "data bytes + piece" */ + CDIO_CD_NUM_OF_CHUNKS = 98, /**< chunks per frame */ + CDIO_CD_FRAMESIZE_SUB = 96, /**< subchannel data "frame" size */ + CDIO_CD_HEADER_SIZE = 4, /**< header (address) bytes per raw + frame */ + CDIO_CD_SUBHEADER_SIZE = 8, /**< subheader bytes per raw XA data + frame */ + CDIO_CD_ECC_SIZE = 276, /**< bytes ECC per most raw data + frame types */ + CDIO_CD_FRAMESIZE = 2048, /**< bytes per frame, "cooked" + mode */ + CDIO_CD_FRAMESIZE_RAW = 2352, /**< bytes per frame, "raw" mode */ + CDIO_CD_FRAMESIZE_RAWER = 2646, /**< The maximum possible + returned */ + CDIO_CD_FRAMESIZE_RAW1 = 2340, + CDIO_CD_FRAMESIZE_RAW0 = 2336, + CDIO_CD_MAX_SESSIONS = 99, + CDIO_CD_MIN_SESSION_NO = 1, /**<, Smallest CD session number */ + CDIO_CD_MAX_LSN = 450150, /**< Largest LSN in a CD */ + CDIO_CD_MIN_LSN = -450150, /**< Smallest LSN in a CD */ + } cdio_cd_enums; + + /*! + Some generally useful CD-ROM information -- mostly based on the above. + This is from linux.h - not to slight other OS's. This was the first + place I came across such useful stuff. + */ +#define CDIO_CD_MINS 74 /**< max. minutes per CD, not really + a limit */ +#define CDIO_CD_SECS_PER_MIN 60 /**< seconds per minute */ +#define CDIO_CD_FRAMES_PER_SEC 75 /**< frames per second */ +#define CDIO_CD_SYNC_SIZE 12 /**< 12 sync bytes per raw data frame */ +#define CDIO_CD_CHUNK_SIZE 24 /**< lowest-level "data bytes piece" */ +#define CDIO_CD_NUM_OF_CHUNKS 98 /**< chunks per frame */ +#define CDIO_CD_FRAMESIZE_SUB 96 /**< subchannel data "frame" size */ +#define CDIO_CD_HEADER_SIZE 4 /**< header (address) bytes per raw + data frame */ +#define CDIO_CD_SUBHEADER_SIZE 8 /**< subheader bytes per raw XA data + frame */ +#define CDIO_CD_EDC_SIZE 4 /**< bytes EDC per most raw data + frame types */ +#define CDIO_CD_M1F1_ZERO_SIZE 8 /**< bytes zero per yellow book mode + 1 frame */ +#define CDIO_CD_ECC_SIZE 276 /**< bytes ECC per most raw data frame + types */ +#define CDIO_CD_FRAMESIZE 2048 /**< bytes per frame, "cooked" mode */ +#define CDIO_CD_FRAMESIZE_RAW 2352 /**< bytes per frame, "raw" mode */ +#define CDIO_CD_FRAMESIZE_RAWER 2646 /**< The maximum possible returned + bytes */ +#define CDIO_CD_FRAMESIZE_RAW1 (CDIO_CD_CD_FRAMESIZE_RAW-CDIO_CD_SYNC_SIZE) /*2340*/ +#define CDIO_CD_FRAMESIZE_RAW0 (CDIO_CD_FRAMESIZE_RAW-CDIO_CD_SYNC_SIZE-CDIO_CD_HEADER_SIZE) /*2336*/ + + /*! "before data" part of raw XA (green, mode2) frame */ +#define CDIO_CD_XA_HEADER (CDIO_CD_HEADER_SIZE+CDIO_CD_SUBHEADER_SIZE) + + /*! "after data" part of raw XA (green, mode2 form1) frame */ +#define CDIO_CD_XA_TAIL (CDIO_CD_EDC_SIZE+CDIO_CD_ECC_SIZE) + + /*! "before data" sync bytes + header of XA (green, mode2) frame */ +#define CDIO_CD_XA_SYNC_HEADER (CDIO_CD_SYNC_SIZE+CDIO_CD_XA_HEADER) + + /*! String of bytes used to identify the beginning of a Mode 1 or + Mode 2 sector. */ + extern const uint8_t CDIO_SECTOR_SYNC_HEADER[CDIO_CD_SYNC_SIZE]; + /**< + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}; + */ + + /*! An enumeration for some of the M2*_SECTOR_SIZE \#defines + below. This isn't really an enumeration one would really use in a + program it is to be helpful in debuggers where wants just to refer + to the M2*_SECTOR_SIZE names and get something. + */ + extern enum m2_sector_enums { + M2F2_SECTOR_SIZE = 2324, + M2SUB_SECTOR_SIZE = 2332, + M2RAW_SECTOR_SIZE = 2336 + } m2_sector_enums; + +#define M2F2_SECTOR_SIZE 2324 +#define M2SUB_SECTOR_SIZE 2332 +#define M2RAW_SECTOR_SIZE 2336 + + /*! Largest CD session number */ +#define CDIO_CD_MAX_SESSIONS 99 + /*! Smallest CD session number */ +#define CDIO_CD_MIN_SESSION_NO 1 + + /*! Largest LSN in a CD */ +#define CDIO_CD_MAX_LSN 450150 + /*! Smallest LSN in a CD */ +#define CDIO_CD_MIN_LSN -450150 + + +#define CDIO_CD_FRAMES_PER_MIN \ + (CDIO_CD_FRAMES_PER_SEC*CDIO_CD_SECS_PER_MIN) + +#define CDIO_CD_74MIN_SECTORS (UINT32_C(74)*CDIO_CD_FRAMES_PER_MIN) +#define CDIO_CD_80MIN_SECTORS (UINT32_C(80)*CDIO_CD_FRAMES_PER_MIN) +#define CDIO_CD_90MIN_SECTORS (UINT32_C(90)*CDIO_CD_FRAMES_PER_MIN) + +#define CDIO_CD_MAX_SECTORS \ + (UINT32_C(100)*CDIO_CD_FRAMES_PER_MIN-CDIO_PREGAP_SECTORS) + +#define msf_t_SIZEOF 3 + + /*! + Convert an LBA into a string representation of the MSF. + \warning cdio_lba_to_msf_str returns new allocated string */ + char *cdio_lba_to_msf_str (lba_t i_lba); + + /*! + Convert an MSF into a string representation of the MSF. + \warning cdio_msf_to_msf_str returns new allocated string */ + char *cdio_msf_to_str (const msf_t *p_msf); + + /*! + Convert an LBA into the corresponding LSN. + */ + lba_t cdio_lba_to_lsn (lba_t i_lba); + + /*! + Convert an LBA into the corresponding MSF. + */ + void cdio_lba_to_msf(lba_t i_lba, msf_t *p_msf); + + /*! + Convert an LSN into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. + */ + lba_t cdio_lsn_to_lba (lsn_t i_lsn); + + /*! + Convert an LSN into the corresponding MSF. + */ + void cdio_lsn_to_msf (lsn_t i_lsn, msf_t *p_msf); + + /*! + Convert a MSF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. + */ + lba_t cdio_msf_to_lba (const msf_t *p_msf); + + /*! + Convert a MSF into the corresponding LSN. + CDIO_INVALID_LSN is returned if there is an error. + */ + lsn_t cdio_msf_to_lsn (const msf_t *p_msf); + + /*! + Convert a MSF - broken out as 3 integer components into the + corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. + */ + lba_t cdio_msf3_to_lba (unsigned int minutes, unsigned int seconds, + unsigned int frames); + + /*! + Convert a string of the form MM:SS:FF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. + */ + lba_t cdio_mmssff_to_lba (const char *psz_mmssff); + +#ifdef __cplusplus + } +#endif + +#ifndef DO_NOT_WANT_PARANOIA_COMPATIBILITY +/** For compatibility with good ol' paranoia */ +#define CD_FRAMESIZE_RAW CDIO_CD_FRAMESIZE_RAW +#endif /*DO_NOT_WANT_PARANOIA_COMPATIBILITY*/ + +#endif /* _CDIO_SECTOR_H_ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/track.h b/src/libcdio/cdio/track.h new file mode 100644 index 00000000..8eccfdd8 --- /dev/null +++ b/src/libcdio/cdio/track.h @@ -0,0 +1,256 @@ +/* + $Id: track.h,v 1.14 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2005, 2006, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +/** \file track.h + * \brief The top-level header for track-related libcdio calls. + */ +#ifndef __CDIO_TRACK_H__ +#define __CDIO_TRACK_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! Printable tags for track_format_t enumeration. */ + extern const char *track_format2str[6]; + + typedef enum { + TRACK_FORMAT_AUDIO, /**< Audio track, e.g. CD-DA */ + TRACK_FORMAT_CDI, /**< CD-i. How this is different from DATA below? */ + TRACK_FORMAT_XA, /**< Mode2 of some sort */ + TRACK_FORMAT_DATA, /**< Mode1 of some sort */ + TRACK_FORMAT_PSX, /**< Playstation CD. Like audio but only 2336 bytes + * of user data. + */ + TRACK_FORMAT_ERROR /**< Dunno what is, or some other error. */ + } track_format_t; + + typedef enum { + CDIO_TRACK_FLAG_FALSE, + CDIO_TRACK_FLAG_TRUE, + CDIO_TRACK_FLAG_ERROR, + CDIO_TRACK_FLAG_UNKNOWN + } track_flag_t; + + /*! \brief Structure containing attributes associated with a track */ + typedef struct { + track_flag_t preemphasis; /**< Linear preemphasis on an audio track */ + track_flag_t copy_permit; /**< Whether copying is permitted */ + int channels; /**< Number of audio channels, 2, 4. -2 if not + implemented or -1 for error. + */ + } track_flags_t; + + /*! The leadout track is always 0xAA, regardless of # of tracks on + disc, or what value may be used internally. For example although + OS X uses a different value for the lead-out track internally than + given below, programmers should use CDIO_CDROM_LEADOUT_TRACK and + not worry about this. + */ + + /*! An enumeration for some of the CDIO_CDROM_* \#defines below. This + isn't really an enumeration one would really use in a program; it + is to be helpful in debuggers where wants just to refer to the + CDIO_CDROM_* names and get something. + */ + extern enum cdio_track_enums { + CDIO_CDROM_LBA = 0x01, /**< "logical block": first frame is #0 */ + CDIO_CDROM_MSF = 0x02, /**< "minute-second-frame": binary, not + BCD here! */ + CDIO_CDROM_DATA_TRACK = 0x04, + CDIO_CDROM_CDI_TRACK = 0x10, + CDIO_CDROM_XA_TRACK = 0x20, + CDIO_CD_MAX_TRACKS = 99, /**< Largest CD track number */ + CDIO_CDROM_LEADOUT_TRACK = 0xAA, /**< Lead-out track number */ + CDIO_INVALID_TRACK = 0xFF, /**< Constant for invalid track number */ + + } cdio_track_enums; + +#define CDIO_CD_MIN_TRACK_NO 1 /**< Smallest CD track number */ + + /*! track modes (Table 350) + reference: MMC-3 draft revsion - 10g + */ + typedef enum { + AUDIO, /**< 2352 byte block length */ + MODE1, /**< 2048 byte block length */ + MODE1_RAW, /**< 2352 byte block length */ + MODE2, /**< 2336 byte block length */ + MODE2_FORM1, /**< 2048 byte block length */ + MODE2_FORM2, /**< 2324 byte block length */ + MODE2_FORM_MIX, /**< 2336 byte block length */ + MODE2_RAW /**< 2352 byte block length */ + } trackmode_t; + + /*! + Get the number of the first track. + + @return the track number or CDIO_INVALID_TRACK + on error. + */ + track_t cdio_get_first_track_num(const CdIo_t *p_cdio); + + /*! + Return the last track number. + CDIO_INVALID_TRACK is returned on error. + */ + track_t cdio_get_last_track_num (const CdIo_t *p_cdio); + + + /*! Find the track which contains lsn. + CDIO_INVALID_TRACK is returned if the lsn outside of the CD or + if there was some error. + + If the lsn is before the pregap of the first track 0 is returned. + Otherwise we return the track that spans the lsn. + */ + track_t cdio_get_track(const CdIo_t *p_cdio, lsn_t lsn); + + /*! Return number of channels in track: 2 or 4; -2 if not + implemented or -1 for error. + Not meaningful if track is not an audio track. + */ + int cdio_get_track_channels(const CdIo_t *p_cdio, track_t i_track); + + /*! Return copy protection status on a track. Is this meaningful + if not an audio track? + */ + track_flag_t cdio_get_track_copy_permit(const CdIo_t *p_cdio, + track_t i_track); + + /*! + Get the format (audio, mode2, mode1) of track. + */ + track_format_t cdio_get_track_format(const CdIo_t *p_cdio, track_t i_track); + + /*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? + */ + bool cdio_get_track_green(const CdIo_t *p_cdio, track_t i_track); + + /*! + Return the ending LSN for track number + i_track in cdio. CDIO_INVALID_LSN is returned on error. + */ + lsn_t cdio_get_track_last_lsn(const CdIo_t *p_cdio, track_t i_track); + + /*! + Get the starting LBA for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + + The "leadout" track is specified either by + using i_track CDIO_CDROM_LEADOUT_TRACK or the total tracks+1. + + @param p_cdio object to get information from + @param i_track the track number we want the LSN for + @return the starting LBA or CDIO_INVALID_LBA on error. + */ + lba_t cdio_get_track_lba(const CdIo_t *p_cdio, track_t i_track); + + /*! + Return the starting LSN for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + + The "leadout" track is specified either by + using i_track CDIO_CDROM_LEADOUT_TRACK or the total tracks+1. + + @param p_cdio object to get information from + @param i_track the track number we want the LSN for + @return the starting LSN or CDIO_INVALID_LSN on error. + */ + lsn_t cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track); + + /*! + Return the starting LBA for the pregap for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + + @param p_cdio object to get information from + @param i_track the track number we want the LBA for + @return the starting LBA or CDIO_INVALID_LBA on error. + */ + lba_t cdio_get_track_pregap_lba(const CdIo_t *p_cdio, track_t i_track); + + /*! + Return the starting LSN for the pregap for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + + @param p_cdio object to get information from + @param i_track the track number we want the LSN for + @return the starting LSN or CDIO_INVALID_LSN on error. + */ + lsn_t cdio_get_track_pregap_lsn(const CdIo_t *p_cdio, track_t i_track); + + /*! + Get the International Standard Recording Code (ISRC) for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + + @return the International Standard Recording Code (ISRC) or NULL + if there is none or we don't have the ability to get it. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. + + */ + char * cdio_get_track_isrc (const CdIo_t *p_cdio, track_t i_track); + + /*! + Return the starting MSF (minutes/secs/frames) for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + + The "leadout" track is specified either by + using i_track CDIO_CDROM_LEADOUT_TRACK or the total tracks+1. + + @return true if things worked or false if there is no track entry. + */ + bool cdio_get_track_msf(const CdIo_t *p_cdio, track_t i_track, + /*out*/ msf_t *msf); + + /*! Get linear preemphasis status on an audio track + This is not meaningful if not an audio track? + */ + track_flag_t cdio_get_track_preemphasis(const CdIo_t *p_cdio, + track_t i_track); + + /*! + Get the number of sectors between this track an the next. This + includes any pregap sectors before the start of the next track. + Track numbers usually start at something + greater than 0, usually 1. + + @return the number of sectors or 0 if there is an error. + */ + unsigned int cdio_get_track_sec_count(const CdIo_t *p_cdio, track_t i_track); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_TRACK_H__ */ + diff --git a/src/libcdio/cdio/types.h b/src/libcdio/cdio/types.h new file mode 100644 index 00000000..2a6a70d8 --- /dev/null +++ b/src/libcdio/cdio/types.h @@ -0,0 +1,336 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008 + Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +/** \file types.h + * \brief Common type definitions used pervasively in libcdio. + */ + + +#ifndef __CDIO_TYPES_H__ +#define __CDIO_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* If is not available on your platform please + contact the libcdio mailing list so that we can fix it! */ +#if !defined(ARE_THERE_STILL_ENVS_WITHOUT_SYS_TYPES) +#include +#endif + +#if defined(AMIGA) +typedef u_int8_t uint8_t; +typedef u_int16_t uint16_t; +typedef u_int32_t uint32_t; +typedef u_int64_t uint64_t; +#else +/* If is not available on your platform please + contact the libcdio mailing list so that we can fix it! + For MSVC, you can find both a public domain stdint.h and + inttypes.h in the MSVC/missing directory of libcdio. */ +#include +#endif + +typedef uint8_t ubyte; + +/* MSVC does not define mode_t and ssize_t by default. The way + to compensate for missing UNIX types is to include a custom + unistd.h that defines them. Such a file is provided with + the libcdio source, in the MSVC/missing directory */ +#if defined(_MSC_VER) +#include +#endif + + /* default HP/UX macros are broken */ +#if defined(__hpux__) +# undef UINT16_C +# undef UINT32_C +# undef UINT64_C +# undef INT64_C +#endif + + /* if it's still not defined, take a good guess... should work for + most 32bit and 64bit archs */ + +#ifndef UINT16_C +# define UINT16_C(c) c ## U +#endif + +#ifndef UINT32_C +# if defined (SIZEOF_INT) && SIZEOF_INT == 4 +# define UINT32_C(c) c ## U +# elif defined (SIZEOF_LONG) && SIZEOF_LONG == 4 +# define UINT32_C(c) c ## UL +# else +# define UINT32_C(c) c ## U +# endif +#endif + +#ifndef UINT64_C +# if defined (SIZEOF_LONG) && SIZEOF_LONG == 8 +# define UINT64_C(c) c ## UL +# elif defined (SIZEOF_INT) && SIZEOF_INT == 8 +# define UINT64_C(c) c ## U +# else +# define UINT64_C(c) c ## ULL +# endif +#endif + +#ifndef INT64_C +# if defined (SIZEOF_LONG) && SIZEOF_LONG == 8 +# define INT64_C(c) c ## L +# elif defined (SIZEOF_INT) && SIZEOF_INT == 8 +# define INT64_C(c) c +# else +# define INT64_C(c) c ## LL +# endif +#endif + +#ifndef __cplusplus + +/* All the stdbool.h seem to define those */ +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined 1 + +#undef bool +#undef true +#undef false + +#ifdef _Bool +#define bool _Bool +#else +#define bool int +#endif +#define true 1 +#define false 0 + +#endif /* __bool_true_false_are_defined */ +#endif /*C++*/ + + /* some GCC optimizations -- gcc 2.5+ */ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((format (printf, format_idx, arg_idx))) +#define GNUC_SCANF( format_idx, arg_idx ) \ + __attribute__((format (scanf, format_idx, arg_idx))) +#define GNUC_FORMAT( arg_idx ) \ + __attribute__((format_arg (arg_idx))) +#define GNUC_NORETURN \ + __attribute__((noreturn)) +#define GNUC_CONST \ + __attribute__((const)) +#define GNUC_UNUSED \ + __attribute__((unused)) +#define GNUC_PACKED \ + __attribute__((packed)) +#else /* !__GNUC__ */ +#define GNUC_PRINTF( format_idx, arg_idx ) +#define GNUC_SCANF( format_idx, arg_idx ) +#define GNUC_FORMAT( arg_idx ) +#define GNUC_NORETURN +#define GNUC_CONST +#define GNUC_UNUSED +#define GNUC_PACKED +#endif /* !__GNUC__ */ + +#if defined(__GNUC__) + /* for GCC we try to use GNUC_PACKED */ +# define PRAGMA_BEGIN_PACKED +# define PRAGMA_END_PACKED +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + /* should work with most EDG-frontend based compilers */ +# define PRAGMA_BEGIN_PACKED _Pragma("pack(1)") +# define PRAGMA_END_PACKED _Pragma("pack()") +#elif defined(_MSC_VER) +# define PRAGMA_BEGIN_PACKED __pragma(pack(push, 1)) +# define PRAGMA_END_PACKED __pragma(pack(pop)) +#else /* neither gcc nor _Pragma() available... */ + /* ...so let's be naive and hope the regression testsuite is run... */ +# define PRAGMA_BEGIN_PACKED +# define PRAGMA_END_PACKED +#endif + + /* + * user directed static branch prediction gcc 2.96+ + */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) +# define GNUC_LIKELY(x) __builtin_expect((x),true) +# define GNUC_UNLIKELY(x) __builtin_expect((x),false) +#else +# define GNUC_LIKELY(x) (x) +# define GNUC_UNLIKELY(x) (x) +#endif + +#ifndef NULL +# define NULL ((void*) 0) +#endif + + /* our own offsetof()-like macro */ +#define __cd_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + + /*! + \brief MSF (minute/second/frame) structure + + One CD-ROMs addressing scheme especially used in audio formats + (Red Book) is an address by minute, sector and frame which + BCD-encoded in three bytes. An alternative format is an lba_t. + + Note: the fields in this structure are BCD encoded. Use + cdio_to_bcd8() or cdio_from_bcd8() to convert an integer into or + out of this format. The format specifier %x (not %d) can be used + if you need to format or print values in this structure. + + @see lba_t + */ + PRAGMA_BEGIN_PACKED + struct msf_s { + uint8_t m, s, f; /* BCD encoded! */ + } GNUC_PACKED; + PRAGMA_END_PACKED + + typedef struct msf_s msf_t; + +#define msf_t_SIZEOF 3 + + /*! + \brief UTF-8 char definition + + Type to denote UTF-8 strings. + */ + + typedef char cdio_utf8_t; + + typedef enum { + nope = 0, + yep = 1, + dunno = 2 + } bool_3way_t; + + /* type used for bit-fields in structs (1 <= bits <= 8) */ +#if defined(__GNUC__) + /* this is strict ISO C99 which allows only 'unsigned int', 'signed + int' and '_Bool' explicitly as bit-field type */ + typedef unsigned int bitfield_t; +#else + /* other compilers might increase alignment requirements to match the + 'unsigned int' type -- fixme: find out how unalignment accesses can + be pragma'ed on non-gcc compilers */ + typedef uint8_t bitfield_t; +#endif + + /*! The type of a Logical Block Address. We allow for an lba to be + negative to be consistent with an lba, although I'm not sure this + this is possible. + + */ + typedef int32_t lba_t; + + /*! The type of a Logical Sector Number. Note that an lba can be negative + and the MMC3 specs allow for a conversion of a negative lba. + + @see msf_t + */ + typedef int32_t lsn_t; + + /* Address in either MSF or logical format */ + union cdio_cdrom_addr + { + msf_t msf; + lba_t lba; + }; + + /*! The type of a track number 0..99. */ + typedef uint8_t track_t; + + /*! The type of a session number 0..99. */ + typedef uint8_t session_t; + + /*! + Constant for invalid session number + */ +#define CDIO_INVALID_SESSION 0xFF + + /*! + Constant for invalid LBA. It is 151 less than the most negative + LBA -45150. This provide slack for the 150-frame offset in + LBA to LSN 150 conversions + */ +#define CDIO_INVALID_LBA -45301 + + /*! + Constant for invalid LSN + */ +#define CDIO_INVALID_LSN CDIO_INVALID_LBA + + /*! + Number of ASCII bytes in a media catalog number (MCN). + We include an extra 0 byte so these can be used as C strings. + */ +#define CDIO_MCN_SIZE 13 + + /*! + Type to hold ASCII bytes in a media catalog number (MCN). + We include an extra 0 byte so these can be used as C strings. + */ + typedef char cdio_mcn_t[CDIO_MCN_SIZE+1]; + + + /*! + Number of ASCII bytes in International Standard Recording Codes (ISRC) + */ +#define CDIO_ISRC_SIZE 12 + + /*! + Type to hold ASCII bytes in a ISRC. + We include an extra 0 byte so these can be used as C strings. + */ + typedef char cdio_isrc_t[CDIO_ISRC_SIZE+1]; + + typedef int cdio_fs_anal_t; + + /*! + track flags + Q Sub-channel Control Field (4.2.3.3) + */ + typedef enum { + CDIO_TRACK_FLAG_NONE = 0x00, /**< no flags set */ + CDIO_TRACK_FLAG_PRE_EMPHASIS = 0x01, /**< audio track recorded with + pre-emphasis */ + CDIO_TRACK_FLAG_COPY_PERMITTED = 0x02, /**< digital copy permitted */ + CDIO_TRACK_FLAG_DATA = 0x04, /**< data track */ + CDIO_TRACK_FLAG_FOUR_CHANNEL_AUDIO = 0x08, /**< 4 audio channels */ + CDIO_TRACK_FLAG_SCMS = 0x10 /**< SCMS (5.29.2.7) */ +} cdio_track_flag; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_TYPES_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/udf.h b/src/libcdio/cdio/udf.h new file mode 100644 index 00000000..2d87e9e3 --- /dev/null +++ b/src/libcdio/cdio/udf.h @@ -0,0 +1,190 @@ +/* + Copyright (C) 2005, 2006, 2008, 2010 Rocky Bernstein + + 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 3 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, see . +*/ + +/*! + * \file udf.h + * + * \brief The top-level interface header for libudf: UDF filesystem + * library; applications include this. + * +*/ + +#ifndef UDF_H +#define UDF_H + +#include +#include +#include + +typedef uint16_t partition_num_t; + +/** Opaque structures. */ +typedef struct udf_s udf_t; +typedef struct udf_file_s udf_file_t; + +typedef struct udf_dirent_s { + char *psz_name; + bool b_dir; /* true if this entry is a directory. */ + bool b_parent; /* True if has parent directory (e.g. not root + directory). If not set b_dir will probably + be true. */ + udf_t *p_udf; + uint32_t i_part_start; + uint32_t i_loc, i_loc_end; + uint64_t dir_left; + uint8_t *sector; + udf_fileid_desc_t *fid; + + /* This field has to come last because it is variable in length. */ + udf_file_entry_t fe; +} udf_dirent_t; + + + +/** + Imagine the below a \#define'd value rather than distinct values of + an enum. +*/ +typedef enum { + UDF_BLOCKSIZE = 2048 +} udf_enum1_t; + +/** This variable is trickery to force the above enum symbol value to + be recorded in debug symbol tables. It is used to allow one refer + to above enumeration values in a debugger and debugger + expressions */ +extern udf_enum1_t debug_udf_enum1; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! + Close UDF and free resources associated with p_udf. + */ + bool udf_close (udf_t *p_udf); + + /*! + Seek to a position i_start and then read i_blocks. Number of + blocks read is returned. One normally expects the return to be + equal to i_blocks. + */ + + driver_return_code_t udf_read_sectors (const udf_t *p_udf, void *ptr, + lsn_t i_start, long int i_blocks); + + /*! + Open an UDF for reading. Maybe in the future we will have + a mode. NULL is returned on error. + + Caller must free result - use udf_close for that. + */ + udf_t *udf_open (const char *psz_path); + + /*! + Return the partition number of the the opened udf handle. -1 + Is returned if we have an error. + */ + int16_t udf_get_part_number(const udf_t *p_udf); + + /*! + Get the root in p_udf. If b_any_partition is false then + the root must be in the given partition. + NULL is returned if the partition is not found or a root is not found or + there is on error. + + Caller must free result - use udf_file_free for that. + */ + udf_dirent_t *udf_get_root (udf_t *p_udf, bool b_any_partition, + partition_num_t i_partition); + + /** + * Gets the Volume Identifier string, in 8bit unicode (latin-1) + * psz_volid, place to put the string + * i_volid_size, size of the buffer volid points to + * returns the size of buffer needed for all data + */ + int udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, + unsigned int i_volid); + + /** + * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) + * WARNING This is not a null terminated string + * volsetid, place to put the data + * volsetid_size, size of the buffer volsetid points to + * the buffer should be >=128 bytes to store the whole volumesetidentifier + * returns the size of the available volsetid information (128) + * or 0 on error + */ + int udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid, + unsigned int i_volsetid); + + /*! + Return a file pointer matching psz_name. + */ + udf_dirent_t *udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name); + + /*! udf_mode_string - fill in string PSZ_STR with an ls-style ASCII + representation of the i_mode. PSZ_STR is returned. + + 10 characters are stored in PSZ_STR; a terminating null byte is added. + The characters stored in PSZ_STR are: + + 0 File type. 'd' for directory, 'c' for character + special, 'b' for block special, 'm' for multiplex, + 'l' for symbolic link, 's' for socket, 'p' for fifo, + '-' for regular, '?' for any other file type + + 1 'r' if the owner may read, '-' otherwise. + + 2 'w' if the owner may write, '-' otherwise. + + 3 'x' if the owner may execute, 's' if the file is + set-user-id, '-' otherwise. + 'S' if the file is set-user-id, but the execute + bit isn't set. + + 4 'r' if group members may read, '-' otherwise. + + 5 'w' if group members may write, '-' otherwise. + + 6 'x' if group members may execute, 's' if the file is + set-group-id, '-' otherwise. + 'S' if it is set-group-id but not executable. + + 7 'r' if any user may read, '-' otherwise. + + 8 'w' if any user may write, '-' otherwise. + + 9 'x' if any user may execute, 't' if the file is "sticky" + (will be retained in swap space after execution), '-' + otherwise. + 'T' if the file is sticky but not executable. */ + + char *udf_mode_string (mode_t i_mode, char *psz_str); + + bool udf_get_lba(const udf_file_entry_t *p_udf_fe, + /*out*/ uint32_t *start, /*out*/ uint32_t *end); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include +#include + +#endif /*UDF_H*/ diff --git a/src/libcdio/cdio/udf_file.h b/src/libcdio/cdio/udf_file.h new file mode 100644 index 00000000..625e448b --- /dev/null +++ b/src/libcdio/cdio/udf_file.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2005, 2006, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +/** + * \file udf_file.h + * + * \brief Routines involving UDF file operations + * +*/ + +#ifndef UDF_FILE_H +#define UDF_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /** + Return the file id descriptor of the given file. + */ + bool udf_get_fileid_descriptor(const udf_dirent_t *p_udf_dirent, + /*out*/ udf_fileid_desc_t *p_udf_fid); + + /** + Return the name of the file + */ + const char *udf_get_filename(const udf_dirent_t *p_udf_dirent); + + /** + Return the name of the file + */ + bool udf_get_file_entry(const udf_dirent_t *p_udf_dirent, + /*out*/ udf_file_entry_t *p_udf_fe); + + /** + Return the number of hard links of the file. Return 0 if error. + */ + uint16_t udf_get_link_count(const udf_dirent_t *p_udf_dirent); + + /** + Return the file length the file. Return 2147483647L if error. + */ + uint64_t udf_get_file_length(const udf_dirent_t *p_udf_dirent); + + /** + Returns a POSIX mode for a given p_udf_dirent. + */ + mode_t udf_get_posix_filemode(const udf_dirent_t *p_udf_dirent); + + /** + Return the next subdirectory. + */ + udf_dirent_t *udf_opendir(const udf_dirent_t *p_udf_dirent); + + /** + Attempts to read up to count bytes from UDF directory entry + p_udf_dirent into the buffer starting at buf. buf should be a + multiple of UDF_BLOCKSIZE bytes. Reading continues after the + point at which we last read or from the beginning the first time. + + If count is zero, read() returns zero and has no other results. If + count is greater than SSIZE_MAX, the result is unspecified. + + If there is an error, cast the result to driver_return_code_t for + the specific error code. + */ + /** + Attempts to read up to count bytes from file descriptor fd into + the buffer starting at buf. + + If count is zero, read() returns zero and has no other results. If + count is greater than SSIZE_MAX, the result is unspecified. + */ + ssize_t udf_read_block(const udf_dirent_t *p_udf_dirent, + void * buf, size_t count); + + /** + Advances p_udf_direct to the the next directory entry in the + pointed to by p_udf_dir. It also returns this as the value. NULL + is returned on reaching the end-of-file or if an error. Also + p_udf_dirent is free'd. If the end of is not reached the caller + must call udf_dirent_free() with p_udf_dirent when done with it to + release resources. + */ + udf_dirent_t *udf_readdir(udf_dirent_t *p_udf_dirent); + + /** + free free resources associated with p_udf_dirent. + */ + bool udf_dirent_free(udf_dirent_t *p_udf_dirent); + + /** + Return true if the file is a directory. + */ + bool udf_is_dir(const udf_dirent_t *p_udf_dirent); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*UDF_FILE_H*/ diff --git a/src/libcdio/cdio/udf_time.h b/src/libcdio/cdio/udf_time.h new file mode 100644 index 00000000..289a8de3 --- /dev/null +++ b/src/libcdio/cdio/udf_time.h @@ -0,0 +1,87 @@ +/* + $Id: udf_time.h,v 1.5 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2005, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +/*! + * \file udf_time.h + * + * \brief UDF time conversion and access files. + * +*/ + +#ifndef UDF_TIME_H +#define UDF_TIME_H + +#include + +#if defined(__MINGW32__) && !defined(__MINGW64__) +struct timespec { + time_t tv_sec; /* Seconds */ + long tv_nsec; /* Nanoseconds */ +}; +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! + Return the access time of the file. + */ + time_t udf_get_access_time(const udf_dirent_t *p_udf_dirent); + + /*! + Return the attribute (most recent create or access) time of the file + */ + time_t udf_get_attribute_time(const udf_dirent_t *p_udf_dirent); + + /*! + Return the modification time of the file. + */ + time_t udf_get_modification_time(const udf_dirent_t *p_udf_dirent); + + /*! + Return the access timestamp of the file + */ + udf_timestamp_t *udf_get_access_timestamp(const udf_dirent_t *p_udf_dirent); + + /*! + Return the modification timestamp of the file + */ + udf_timestamp_t *udf_get_modification_timestamp(const udf_dirent_t + *p_udf_dirent); + + /*! + Return the attr timestamp of the file + */ + udf_timestamp_t *udf_get_attr_timestamp(const udf_dirent_t *p_udf_dirent); + + /*! + Convert a UDF timestamp to a time_t. If microseconds are desired, + use dest_usec. The return value is the same as dest. */ + time_t *udf_stamp_to_time(time_t *dest, long int *dest_usec, + const udf_timestamp_t src); + + udf_timestamp_t *udf_timespec_to_stamp(const struct timespec ts, + udf_timestamp_t *dest); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*UDF_TIME_H*/ diff --git a/src/libcdio/cdio/utf8.h b/src/libcdio/cdio/utf8.h new file mode 100644 index 00000000..236105e9 --- /dev/null +++ b/src/libcdio/cdio/utf8.h @@ -0,0 +1,92 @@ +/* + $Id: utf8.h,v 1.2 2008/03/25 15:59:09 karl Exp $ + + Copyright (C) 2008 Rocky Bernstein + Copyright (C) 2006 Burkhard Plaum + + 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 3 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, see . +*/ +/* UTF-8 support */ + + +#include + +/** \brief Opaque characterset converter + */ + +typedef struct cdio_charset_coverter_s cdio_charset_coverter_t; + +/** \brief Create a charset converter + * \param src_charset Source charset + * \param dst_charset Destination charset + * \returns A newly allocated charset converter + */ + +cdio_charset_coverter_t * +cdio_charset_converter_create(const char * src_charset, + const char * dst_charset); + +/** \brief Destroy a characterset converter + * \param cnv A characterset converter + */ + +void cdio_charset_converter_destroy(cdio_charset_coverter_t*cnv); + +/** \brief Convert a string from one character set to another + * \param cnv A charset converter + * \param src Source string + * \param src_len Length of source string + * \param dst Returns destination string + * \param dst_len If non NULL, returns the length of the destination string + * \returns true if conversion was sucessful, false else. + * + * The destination string must be freed by the caller with free(). + * If you pass -1 for src_len, strlen() will be used. + */ + +bool cdio_charset_convert(cdio_charset_coverter_t*cnv, + char * src, int src_len, + char ** dst, int * dst_len); + +/** \brief Convert a string from UTF-8 to another charset + * \param src Source string (0 terminated) + * \param dst Returns destination string + * \param dst_len If non NULL, returns the length of the destination string + * \param dst_charset The characterset to convert to + * \returns true if conversion was sucessful, false else. + * + * This is a convenience function, which creates a charset converter, + * converts one string and destroys the charset converter. + */ + + +bool cdio_charset_from_utf8(cdio_utf8_t * src, char ** dst, + int * dst_len, const char * dst_charset); + +/** \brief Convert a string from another charset to UTF-8 + * \param src Source string + * \param src_len Length of the source string + * \param dst Returns destination string (0 terminated) + * \param src_charset The characterset to convert from + * \returns true if conversion was sucessful, false else. + * + * This is a convenience function, which creates a charset converter, + * converts one string and destroys the charset converter. If you pass -1 + * for src_len, strlen() will be used. + */ + + +bool cdio_charset_to_utf8(char *src, size_t src_len, cdio_utf8_t **dst, + const char * src_charset); + diff --git a/src/libcdio/cdio/util.h b/src/libcdio/cdio/util.h new file mode 100644 index 00000000..6ebf35f4 --- /dev/null +++ b/src/libcdio/cdio/util.h @@ -0,0 +1,134 @@ +/* + Copyright (C) 2004, 2005, 2006, 2008, 2010 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifndef __CDIO_UTIL_H__ +#define __CDIO_UTIL_H__ + +/*! + \file util.h + \brief Miscellaneous utility functions. + + Warning: this will probably get removed/replaced by using glib.h +*/ +#include +#include + +#if !defined CDIO_INLINE +#if defined(__cplusplus) || defined(inline) +#define CDIO_INLINE inline +#elif defined(__GNUC__) +#define CDIO_INLINE __inline__ +#elif defined(_MSC_VER) +#define CDIO_INLINE __inline +#else +#define CDIO_INLINE +#endif +#endif /* CDIO_INLINE */ + +#undef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#undef IN +#define IN(x, low, high) ((x) >= (low) && (x) <= (high)) + +#undef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +static CDIO_INLINE uint32_t +_cdio_len2blocks (uint32_t i_len, uint16_t i_blocksize) +{ + uint32_t i_blocks; + + i_blocks = i_len / (uint32_t) i_blocksize; + if (i_len % i_blocksize) + i_blocks++; + + return i_blocks; +} + +/* round up to next block boundary */ +static CDIO_INLINE unsigned +_cdio_ceil2block (unsigned offset, uint16_t i_blocksize) +{ + return _cdio_len2blocks (offset, i_blocksize) * i_blocksize; +} + +static CDIO_INLINE unsigned int +_cdio_ofs_add (unsigned offset, unsigned length, uint16_t i_blocksize) +{ + if (i_blocksize - (offset % i_blocksize) < length) + offset = _cdio_ceil2block (offset, i_blocksize); + + offset += length; + + return offset; +} + +static CDIO_INLINE const char * +_cdio_bool_str (bool b) +{ + return b ? "yes" : "no"; +} + +#ifdef __cplusplus +extern "C" { +#endif + +void * +_cdio_memdup (const void *mem, size_t count); + +char * +_cdio_strdup_upper (const char str[]); + +void +_cdio_strfreev(char **strv); + +size_t +_cdio_strlenv(char **str_array); + +char ** +_cdio_strsplit(const char str[], char delim); + +uint8_t cdio_to_bcd8(uint8_t n); +uint8_t cdio_from_bcd8(uint8_t p); + +/*! cdio_realpath() same as POSIX.1-2001 realpath if that's +around. If not we do poor-man's simulation of that behavior. */ +char *cdio_realpath (const char *psz_src, char *psz_dst); + +#ifdef WANT_FOLLOW_SYMLINK_COMPATIBILITY +# define cdio_follow_symlink cdio_realpath +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CDIO_UTIL_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/cdio/version.h b/src/libcdio/cdio/version.h new file mode 100644 index 00000000..0e5db066 --- /dev/null +++ b/src/libcdio/cdio/version.h @@ -0,0 +1,20 @@ +/* $Id: version.h.in,v 1.6 2005/01/29 20:54:20 rocky Exp $ */ +/** \file version.h + * + * \brief A file containing the libcdio package version + * number (84) and OS build name. + */ + +/*! CDIO_VERSION is a C-Preprocessor macro of a string that shows what + version is used. cdio_version_string has the same value, but it is a + constant variable that can be accessed at run time. */ +#define CDIO_VERSION "0.84git i686-pc-mingw32" +extern const char *cdio_version_string; /**< = CDIO_VERSION */ + +/*! LIBCDIO_VERSION_NUM is a C-Preprocessor macro that can be used for + testing in the C preprocessor. libcdio_version_num has the same + value, but it is a constant variable that can be accessed at run + time. */ +#define LIBCDIO_VERSION_NUM 84 + +extern const unsigned int libcdio_version_num; /**< = LIBCDIO_VERSION_NUM */ diff --git a/src/libcdio/cdio/xa.h b/src/libcdio/cdio/xa.h new file mode 100644 index 00000000..13b21c8f --- /dev/null +++ b/src/libcdio/cdio/xa.h @@ -0,0 +1,179 @@ +/* + $Id: xa.h,v 1.19 2008/03/25 15:59:10 karl Exp $ + + Copyright (C) 2003, 2004, 2005, 2006, 2008 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + See also iso9660.h by Eric Youngdale (1993) and in cdrtools. These are + + Copyright 1993 Yggdrasil Computing, Incorporated + Copyright (c) 1999,2000 J. Schilling + + 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 3 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, see . +*/ +/*! + \file xa.h + \brief Things related to the ISO-9660 XA (Extended Attributes) format + + Applications will probably not include this directly but via + the iso9660.h header. +*/ + + +#ifndef __CDIO_XA_H__ +#define __CDIO_XA_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! An enumeration for some of the XA_* \#defines below. This isn't + really an enumeration one would really use in a program it is to + be helpful in debuggers where wants just to refer to the XA_* + names and get something. + */ + typedef enum { + ISO_XA_MARKER_OFFSET = 1024, + XA_PERM_RSYS = 0x0001, /**< System Group Read */ + XA_PERM_XSYS = 0x0004, /**< System Group Execute */ + + XA_PERM_RUSR = 0x0010, /**< User (owner) Read */ + XA_PERM_XUSR = 0x0040, /**< User (owner) Execute */ + + XA_PERM_RGRP = 0x0100, /**< Group Read */ + XA_PERM_XGRP = 0x0400, /**< Group Execute */ + + XA_PERM_ROTH = 0x1000, /**< Other (world) Read */ + XA_PERM_XOTH = 0x4000, /**< Other (world) Execute */ + + XA_ATTR_MODE2FORM1 = (1 << 11), + XA_ATTR_MODE2FORM2 = (1 << 12), + XA_ATTR_INTERLEAVED = (1 << 13), + XA_ATTR_CDDA = (1 << 14), + XA_ATTR_DIRECTORY = (1 << 15), + + XA_PERM_ALL_READ = (XA_PERM_RUSR | XA_PERM_RSYS | XA_PERM_RGRP), + XA_PERM_ALL_EXEC = (XA_PERM_XUSR | XA_PERM_XSYS | XA_PERM_XGRP), + XA_PERM_ALL_ALL = (XA_PERM_ALL_READ | XA_PERM_ALL_EXEC), + + XA_FORM1_DIR = (XA_ATTR_DIRECTORY | XA_ATTR_MODE2FORM1 | XA_PERM_ALL_ALL), + XA_FORM1_FILE = (XA_ATTR_MODE2FORM1 | XA_PERM_ALL_ALL), + XA_FORM2_FILE = (XA_ATTR_MODE2FORM2 | XA_PERM_ALL_ALL) + } xa_misc_enum_t; + +extern const char ISO_XA_MARKER_STRING[sizeof("CD-XA001")-1]; + +#define ISO_XA_MARKER_STRING "CD-XA001" + +/*! \brief "Extended Architecture" according to the Philips Yellow Book. + +CD-ROM EXtended Architecture is a modification to the CD-ROM +specification that defines two new types of sectors. CD-ROM XA was +developed jointly by Sony, Philips, and Microsoft, and announced in +August 1988. Its specifications were published in an extension to the +Yellow Book. CD-i, Photo CD, Video CD and CD-EXTRA have all +subsequently been based on CD-ROM XA. + +CD-XA defines another way of formatting sectors on a CD-ROM, including +headers in the sectors that describe the type (audio, video, data) and +some additional info (markers, resolution in case of a video or audio +sector, file numbers, etc). + +The data written on a CD-XA is consistent with and can be in ISO-9660 +file system format and therefore be readable by ISO-9660 file system +translators. But also a CD-I player can also read CD-XA discs even if +its own `Green Book' file system only resembles ISO 9660 and isn't +fully compatible. + + Note structure is big-endian. +*/ +typedef struct iso9660_xa_s +{ + uint16_t group_id; /**< 0 */ + uint16_t user_id; /**< 0 */ + uint16_t attributes; /**< XA_ATTR_ */ + char signature[2]; /**< { 'X', 'A' } */ + uint8_t filenum; /**< file number, see also XA subheader */ + uint8_t reserved[5]; /**< zero */ +} GNUC_PACKED iso9660_xa_t; + + + /*! + Returns POSIX mode bitstring for a given file. + */ + posix_mode_t iso9660_get_posix_filemode_from_xa(uint16_t i_perms); + +/*! + Returns a string interpreting the extended attribute xa_attr. + For example: + \verbatim + d---1xrxrxr + ---2--r-r-r + -a--1xrxrxr + \endverbatim + + A description of the characters in the string follows. + The 1st character is either "d" if the entry is a directory, or "-" if not + The 2nd character is either "a" if the entry is CDDA (audio), or "-" if not + The 3rd character is either "i" if the entry is interleaved, or "-" if not + The 4th character is either "2" if the entry is mode2 form2 or "-" if not + The 5th character is either "1" if the entry is mode2 form1 or "-" if not + Note that an entry will either be in mode2 form1 or mode form2. That + is you will either see "2-" or "-1" in the 4th & 5th positions. + + The 6th and 7th characters refer to permissions for a user while the + the 8th and 9th characters refer to permissions for a group while, and + the 10th and 11th characters refer to permissions for everyone. + + In each of these pairs the first character (6, 8, 10) is "x" if the + entry is executable. For a directory this means the directory is + allowed to be listed or "searched". + The second character of a pair (7, 9, 11) is "r" if the entry is allowed + to be read. +*/ +const char * +iso9660_get_xa_attr_str (uint16_t xa_attr); + +/*! + Allocates and initalizes a new iso9600_xa_t variable and returns + it. The caller should free the returned result. + + @see iso9660_xa +*/ +iso9660_xa_t * +iso9660_xa_init (iso9660_xa_t *_xa, uint16_t uid, uint16_t gid, uint16_t attr, + uint8_t filenum); + +#ifdef __cplusplus +} + +/** The below variables are trickery to force the above enum symbol + values to be recorded in debug symbol tables. They are used to + allow one to refer to the enumeration value names in the typedefs + above in a debugger and debugger expressions. +*/ +extern xa_misc_enum_t debugger_xa_misc_enum; + + +#endif /* __cplusplus */ + +#endif /* __CDIO_XA_H__ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/.msvc/driver.vcxproj b/src/libcdio/driver/.msvc/driver.vcxproj new file mode 100644 index 00000000..d4e9f209 --- /dev/null +++ b/src/libcdio/driver/.msvc/driver.vcxproj @@ -0,0 +1,188 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {FA1B1093-BA86-410A-B7A0-7A54C605F812} + Win32Proj + driver + libcdio-driver + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)x86_32\$(Configuration)\ + $(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_32\$(Configuration)\ + $(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_64\$(Configuration)\ + $(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_64\$(Configuration)\ + $(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\ + false + false + false + false + + + + + + Level3 + Disabled + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreadedDebug + ProgramDatabase + + + Windows + true + + + MachineX86 + + + + + Level3 + + + MaxSpeed + true + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + ..;..\..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreaded + ProgramDatabase + + + MachineX86 + + + + + + + Level3 + Disabled + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreadedDebug + ProgramDatabase + + + Windows + true + + + MachineX64 + + + + + Level3 + + + MaxSpeed + true + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + ..;..\..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreaded + ProgramDatabase + + + Windows + true + true + true + + + MachineX64 + + + + + + \ No newline at end of file diff --git a/src/libcdio/driver/.msvc/driver.vcxproj.filters b/src/libcdio/driver/.msvc/driver.vcxproj.filters new file mode 100644 index 00000000..b2ef477e --- /dev/null +++ b/src/libcdio/driver/.msvc/driver.vcxproj.filters @@ -0,0 +1,89 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/src/libcdio/driver/.msvc/driver_sources b/src/libcdio/driver/.msvc/driver_sources new file mode 100644 index 00000000..50926212 --- /dev/null +++ b/src/libcdio/driver/.msvc/driver_sources @@ -0,0 +1,25 @@ +TARGETNAME=driver +TARGETTYPE=LIBRARY + +INCLUDES=$(DDK_INC_PATH);.;..;..\..\msvc-missing +LIBCDIO_DEFINES = /DHAVE_CONFIG_H /D_OFF_T_DEFINED /D_off_t=__int64 /Doff_t=_off_t /D_FILE_OFFSET_BITS=64 +C_DEFINES=$(C_DEFINES) $(LIBCDIO_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED + +!IFNDEF MSC_WARNING_LEVEL +MSC_WARNING_LEVEL=/W3 +!ENDIF +USE_MSVCRT=1 + +TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ + $(SDK_LIB_PATH)\user32.lib + +SOURCES=disc.c \ + ds.c \ + logging.c \ + read.c \ + sector.c \ + track.c \ + util.c \ + utf8.c \ + _cdio_stdio.c \ + _cdio_stream.c \ No newline at end of file diff --git a/src/libcdio/driver/Makefile.am b/src/libcdio/driver/Makefile.am new file mode 100644 index 00000000..43082829 --- /dev/null +++ b/src/libcdio/driver/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libdriver.a +libdriver_a_SOURCES = disc.c ds.c logging.c read.c sector.c track.c util.c _cdio_stdio.c _cdio_stream.c utf8.c +# Boy do you NOT want to have HAVE_CONFIG_H set before $(AM_CFLAGS) with Clang! +libdriver_a_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -I. -I.. diff --git a/src/libcdio/driver/Makefile.in b/src/libcdio/driver/Makefile.in new file mode 100644 index 00000000..b6a2308d --- /dev/null +++ b/src/libcdio/driver/Makefile.in @@ -0,0 +1,476 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = src/libcdio/driver +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libdriver_a_AR = $(AR) $(ARFLAGS) +libdriver_a_LIBADD = +am_libdriver_a_OBJECTS = libdriver_a-disc.$(OBJEXT) \ + libdriver_a-ds.$(OBJEXT) libdriver_a-logging.$(OBJEXT) \ + libdriver_a-read.$(OBJEXT) libdriver_a-sector.$(OBJEXT) \ + libdriver_a-track.$(OBJEXT) libdriver_a-util.$(OBJEXT) \ + libdriver_a-_cdio_stdio.$(OBJEXT) \ + libdriver_a-_cdio_stream.$(OBJEXT) libdriver_a-utf8.$(OBJEXT) +libdriver_a_OBJECTS = $(am_libdriver_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__depfiles_maybe = +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libdriver_a_SOURCES) +ETAGS = etags +CTAGS = ctags +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_LDFLAGS = @AM_LDFLAGS@ +AM_RCFLAGS = @AM_RCFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EXEEXT = @EXEEXT@ +EXESUFFIX = @EXESUFFIX@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +RM = @RM@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +WINDRES = @WINDRES@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LIBRARIES = libdriver.a +libdriver_a_SOURCES = disc.c ds.c logging.c read.c sector.c track.c util.c _cdio_stdio.c _cdio_stream.c utf8.c +# Boy do you NOT want to have HAVE_CONFIG_H set before $(AM_CFLAGS) with Clang! +libdriver_a_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -I. -I.. +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps src/libcdio/driver/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps src/libcdio/driver/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libdriver.a: $(libdriver_a_OBJECTS) $(libdriver_a_DEPENDENCIES) + $(AM_V_at)-rm -f libdriver.a + $(AM_V_AR)$(libdriver_a_AR) libdriver.a $(libdriver_a_OBJECTS) $(libdriver_a_LIBADD) + $(AM_V_at)$(RANLIB) libdriver.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC) @AM_BACKSLASH@ + $(COMPILE) -c $< + +.c.obj: + $(AM_V_CC) @AM_BACKSLASH@ + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +libdriver_a-disc.o: disc.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-disc.o `test -f 'disc.c' || echo '$(srcdir)/'`disc.c + +libdriver_a-disc.obj: disc.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-disc.obj `if test -f 'disc.c'; then $(CYGPATH_W) 'disc.c'; else $(CYGPATH_W) '$(srcdir)/disc.c'; fi` + +libdriver_a-ds.o: ds.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-ds.o `test -f 'ds.c' || echo '$(srcdir)/'`ds.c + +libdriver_a-ds.obj: ds.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-ds.obj `if test -f 'ds.c'; then $(CYGPATH_W) 'ds.c'; else $(CYGPATH_W) '$(srcdir)/ds.c'; fi` + +libdriver_a-logging.o: logging.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-logging.o `test -f 'logging.c' || echo '$(srcdir)/'`logging.c + +libdriver_a-logging.obj: logging.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-logging.obj `if test -f 'logging.c'; then $(CYGPATH_W) 'logging.c'; else $(CYGPATH_W) '$(srcdir)/logging.c'; fi` + +libdriver_a-read.o: read.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-read.o `test -f 'read.c' || echo '$(srcdir)/'`read.c + +libdriver_a-read.obj: read.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-read.obj `if test -f 'read.c'; then $(CYGPATH_W) 'read.c'; else $(CYGPATH_W) '$(srcdir)/read.c'; fi` + +libdriver_a-sector.o: sector.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-sector.o `test -f 'sector.c' || echo '$(srcdir)/'`sector.c + +libdriver_a-sector.obj: sector.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-sector.obj `if test -f 'sector.c'; then $(CYGPATH_W) 'sector.c'; else $(CYGPATH_W) '$(srcdir)/sector.c'; fi` + +libdriver_a-track.o: track.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-track.o `test -f 'track.c' || echo '$(srcdir)/'`track.c + +libdriver_a-track.obj: track.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-track.obj `if test -f 'track.c'; then $(CYGPATH_W) 'track.c'; else $(CYGPATH_W) '$(srcdir)/track.c'; fi` + +libdriver_a-util.o: util.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-util.o `test -f 'util.c' || echo '$(srcdir)/'`util.c + +libdriver_a-util.obj: util.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-util.obj `if test -f 'util.c'; then $(CYGPATH_W) 'util.c'; else $(CYGPATH_W) '$(srcdir)/util.c'; fi` + +libdriver_a-_cdio_stdio.o: _cdio_stdio.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-_cdio_stdio.o `test -f '_cdio_stdio.c' || echo '$(srcdir)/'`_cdio_stdio.c + +libdriver_a-_cdio_stdio.obj: _cdio_stdio.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-_cdio_stdio.obj `if test -f '_cdio_stdio.c'; then $(CYGPATH_W) '_cdio_stdio.c'; else $(CYGPATH_W) '$(srcdir)/_cdio_stdio.c'; fi` + +libdriver_a-_cdio_stream.o: _cdio_stream.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-_cdio_stream.o `test -f '_cdio_stream.c' || echo '$(srcdir)/'`_cdio_stream.c + +libdriver_a-_cdio_stream.obj: _cdio_stream.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-_cdio_stream.obj `if test -f '_cdio_stream.c'; then $(CYGPATH_W) '_cdio_stream.c'; else $(CYGPATH_W) '$(srcdir)/_cdio_stream.c'; fi` + +libdriver_a-utf8.o: utf8.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-utf8.o `test -f 'utf8.c' || echo '$(srcdir)/'`utf8.c + +libdriver_a-utf8.obj: utf8.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdriver_a_CFLAGS) $(CFLAGS) -c -o libdriver_a-utf8.obj `if test -f 'utf8.c'; then $(CYGPATH_W) 'utf8.c'; else $(CYGPATH_W) '$(srcdir)/utf8.c'; fi` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcdio/driver/_cdio_stdio.c b/src/libcdio/driver/_cdio_stdio.c new file mode 100644 index 00000000..d89625af --- /dev/null +++ b/src/libcdio/driver/_cdio_stdio.c @@ -0,0 +1,260 @@ +/* + Copyright (C) 2003, 2004, 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include +#include "_cdio_stream.h" +#include "_cdio_stdio.h" + +/* On 32 bit platforms, fseek can only access streams of 2 GB or less. + Prefer fseeko/fseeko64, that take a 64 bit offset when LFS is enabled */ +#if defined(HAVE_FSEEKO64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) +#define CDIO_FSEEK fseeko64 +#elif defined(HAVE_FSEEKO) +#define CDIO_FSEEK fseeko +#else +#define CDIO_FSEEK fseek +#endif + +/* Use _stati64 if needed, on platforms that don't have transparent LFS support */ +#if defined(HAVE__STATI64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) +#define CDIO_STAT _stati64 +#else +#define CDIO_STAT stat +#endif + +#define _STRINGIFY(a) #a +#define STRINGIFY(a) _STRINGIFY(a) + +static const char _rcsid[] = "$Id: _cdio_stdio.c,v 1.6 2008/04/22 15:29:11 karl Exp $"; + +#define CDIO_STDIO_BUFSIZE (128*1024) + +typedef struct { + char *pathname; + FILE *fd; + char *fd_buf; + off_t st_size; /* used only for source */ +} _UserData; + +static int +_stdio_open (void *user_data) +{ + _UserData *const ud = user_data; + + if ((ud->fd = fopen (ud->pathname, "rb"))) + { + ud->fd_buf = calloc (1, CDIO_STDIO_BUFSIZE); + setvbuf (ud->fd, ud->fd_buf, _IOFBF, CDIO_STDIO_BUFSIZE); + } + + return (ud->fd == NULL); +} + +static int +_stdio_close(void *user_data) +{ + _UserData *const ud = user_data; + + if (fclose (ud->fd)) + cdio_error ("fclose (): %s", strerror (errno)); + + ud->fd = NULL; + + free (ud->fd_buf); + ud->fd_buf = NULL; + + return 0; +} + +static void +_stdio_free(void *user_data) +{ + _UserData *const ud = user_data; + + if (ud->pathname) + free(ud->pathname); + + if (ud->fd) /* should be NULL anyway... */ + _stdio_close(user_data); + + free(ud); +} + +/*! + Like fseek/fseeko(3) and in fact may be the same. + + This function sets the file position indicator for the stream + pointed to by stream. The new position, measured in bytes, is obtained + by adding offset bytes to the position specified by whence. If whence + is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to + the start of the file, the current position indicator, or end-of-file, + respectively. A successful call to the fseek function clears the end- + of-file indicator for the stream and undoes any effects of the + ungetc(3) function on the same stream. + + @return upon successful completion, DRIVER_OP_SUCCESS, else, + DRIVER_OP_ERROR is returned and the global variable errno is set to + indicate the error. +*/ +static int +_stdio_seek(void *p_user_data, off_t i_offset, int whence) +{ + _UserData *const ud = p_user_data; + int ret; +#if !defined(HAVE_FSEEKO) && !defined(HAVE_FSEEKO64) + /* Detect if off_t is lossy-truncated to long to avoid data corruption */ + if ( (sizeof(off_t) > sizeof(long)) && (i_offset != (off_t)((long)i_offset)) ) { + cdio_error ( STRINGIFY(CDIO_FSEEK) " (): lossy truncation detected!"); + errno = EFBIG; + return DRIVER_OP_ERROR; + } +#endif + + if ( (ret=CDIO_FSEEK (ud->fd, i_offset, whence)) ) { + cdio_error ( STRINGIFY(CDIO_FSEEK) " (): %s", strerror (errno)); + } + + return ret; +} + +static off_t +_stdio_stat(void *p_user_data) +{ + const _UserData *const ud = p_user_data; + + return ud->st_size; +} + +/*! + Like fread(3) and in fact is about the same. + + DESCRIPTION: + The function fread reads nmemb elements of data, each size bytes long, + from the stream pointed to by stream, storing them at the location + given by ptr. + + RETURN VALUE: + return the number of items successfully read or written (i.e., + not the number of characters). If an error occurs, or the + end-of-file is reached, the return value is a short item count + (or zero). + + We do not distinguish between end-of-file and error, and callers + must use feof(3) and ferror(3) to determine which occurred. + */ +static ssize_t +_stdio_read(void *user_data, void *buf, size_t count) +{ + _UserData *const ud = user_data; + long read_count; + + read_count = fread(buf, 1, count, ud->fd); + + if (read_count != count) + { /* fixme -- ferror/feof */ + if (feof (ud->fd)) + { + cdio_debug ("fread (): EOF encountered"); + clearerr (ud->fd); + } + else if (ferror (ud->fd)) + { + cdio_error ("fread (): %s", strerror (errno)); + clearerr (ud->fd); + } + else + cdio_debug ("fread (): short read and no EOF?!?"); + } + + return read_count; +} + +/*! + Deallocate resources assocaited with obj. After this obj is unusable. +*/ +void +cdio_stdio_destroy(CdioDataSource_t *p_obj) +{ + cdio_stream_destroy(p_obj); +} + +CdioDataSource_t * +cdio_stdio_new(const char pathname[]) +{ + CdioDataSource_t *new_obj = NULL; + cdio_stream_io_functions funcs = { NULL, NULL, NULL, NULL, NULL, NULL }; + _UserData *ud = NULL; + struct CDIO_STAT statbuf; + + if (CDIO_STAT (pathname, &statbuf) == -1) + { + cdio_warn ("could not retrieve file info for `%s': %s", + pathname, strerror (errno)); + return NULL; + } + + ud = calloc (1, sizeof (_UserData)); + + ud->pathname = strdup(pathname); + ud->st_size = statbuf.st_size; /* let's hope it doesn't change... */ + + funcs.open = _stdio_open; + funcs.seek = _stdio_seek; + funcs.stat = _stdio_stat; + funcs.read = _stdio_read; + funcs.close = _stdio_close; + funcs.free = _stdio_free; + + new_obj = cdio_stream_new(ud, &funcs); + + return new_obj; +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/_cdio_stdio.h b/src/libcdio/driver/_cdio_stdio.h new file mode 100644 index 00000000..a2cd4c02 --- /dev/null +++ b/src/libcdio/driver/_cdio_stdio.h @@ -0,0 +1,51 @@ +/* + $Id: _cdio_stdio.h,v 1.3 2008/04/22 15:29:11 karl Exp $ + + Copyright (C) 2003, 2008 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + + +#ifndef __CDIO_STDIO_H__ +#define __CDIO_STDIO_H__ + +#include "_cdio_stream.h" + +/*! + Initialize a new stdio stream reading from pathname. + A pointer to the stream is returned or NULL if there was an error. + + cdio_stream_free should be called on the returned value when you + don't need the stream any more. No other finalization is needed. + */ +CdioDataSource_t * cdio_stdio_new(const char psz_path[]); + +/*! + Deallocate resources assocaited with obj. After this obj is unusable. +*/ +void cdio_stdio_destroy(CdioDataSource_t *p_obj); + + +#endif /* __CDIO_STREAM_STDIO_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/_cdio_stream.c b/src/libcdio/driver/_cdio_stream.c new file mode 100644 index 00000000..f3c453c2 --- /dev/null +++ b/src/libcdio/driver/_cdio_stream.c @@ -0,0 +1,222 @@ +/* + Copyright (C) 2005, 2006, 2008, 2011 Rocky Bernstein + Copyright (C) 2000, 2004, 2005 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#include "cdio_assert.h" + +/* #define STREAM_DEBUG */ + +#include +#include +#include "_cdio_stream.h" + +static const char _rcsid[] = "$Id: _cdio_stream.c,v 1.9 2008/04/22 15:29:11 karl Exp $"; + +/* + * DataSource implementations + */ + +struct _CdioDataSource { + void* user_data; + cdio_stream_io_functions op; + int is_open; + off_t position; +}; + +void +cdio_stream_close(CdioDataSource_t *p_obj) +{ + if (!p_obj) return; + + if (p_obj->is_open) { + cdio_debug ("closed source..."); + p_obj->op.close(p_obj->user_data); + p_obj->is_open = 0; + p_obj->position = 0; + } +} + +void +cdio_stream_destroy(CdioDataSource_t *p_obj) +{ + if (!p_obj) return; + + cdio_stream_close(p_obj); + + p_obj->op.free(p_obj->user_data); + + free(p_obj); +} + +/** + Like 3 fgetpos. + + This function gets the current file position indicator for the stream + pointed to by stream. + + @return unpon successful completion, return value is positive, else, + the global variable errno is set to indicate the error. +*/ +off_t +cdio_stream_getpos(CdioDataSource_t* p_obj, /*out*/ off_t *i_offset) +{ + if (!p_obj || !p_obj->is_open) return DRIVER_OP_UNINIT; + return *i_offset = p_obj->position; +} + +CdioDataSource_t * +cdio_stream_new(void *user_data, const cdio_stream_io_functions *funcs) +{ + CdioDataSource_t *new_obj; + + new_obj = calloc (1, sizeof (CdioDataSource_t)); + + new_obj->user_data = user_data; + memcpy(&(new_obj->op), funcs, sizeof(cdio_stream_io_functions)); + + return new_obj; +} + +/* + Open if not already open. + Return false if we hit an error. Errno should be set for that error. +*/ +static bool +_cdio_stream_open_if_necessary(CdioDataSource_t *p_obj) +{ + if (!p_obj) return false; + + if (!p_obj->is_open) { + if (p_obj->op.open(p_obj->user_data)) { + cdio_warn ("could not open input stream..."); + return false; + } else { + cdio_debug ("opened source..."); + p_obj->is_open = 1; + p_obj->position = 0; + } + } + return true; +} + +/** + Like fread(3) and in fact may be the same. + + DESCRIPTION: + The function fread reads nmemb elements of data, each size bytes long, + from the stream pointed to by stream, storing them at the location + given by ptr. + + RETURN VALUE: + return the number of items successfully read or written (i.e., + not the number of characters). If an error occurs, or the + end-of-file is reached, the return value is a short item count + (or zero). + + We do not distinguish between end-of-file and error, and callers + must use feof(3) and ferror(3) to determine which occurred. +*/ +ssize_t +cdio_stream_read(CdioDataSource_t* p_obj, void *ptr, size_t size, size_t nmemb) +{ + long read_bytes; + + if (!p_obj) return 0; + if (!_cdio_stream_open_if_necessary(p_obj)) return 0; + + read_bytes = (p_obj->op.read)(p_obj->user_data, ptr, size*nmemb); + p_obj->position += read_bytes; + + return read_bytes; +} + +/** + Like 3 fseek and in fact may be the same. + + This function sets the file position indicator for the stream + pointed to by stream. The new position, measured in bytes, is obtained + by adding offset bytes to the position specified by whence. If whence + is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to + the start of the file, the current position indicator, or end-of-file, + respectively. A successful call to the fseek function clears the end- + of-file indicator for the stream and undoes any effects of the + ungetc(3) function on the same stream. + + @return unpon successful completion, return value is positive, else, + the global variable errno is set to indicate the error. +*/ +int +cdio_stream_seek(CdioDataSource_t* p_obj, off_t offset, int whence) +{ + if (!p_obj) return DRIVER_OP_UNINIT; + + if (!_cdio_stream_open_if_necessary(p_obj)) + /* errno is set by _cdio_stream_open_if necessary. */ + return DRIVER_OP_ERROR; + + if (offset < 0) return DRIVER_OP_ERROR; + if (p_obj->position < 0) return DRIVER_OP_ERROR; + + if (p_obj->position != offset) { +#ifdef STREAM_DEBUG + cdio_warn("had to reposition DataSource from %ld to %ld!", p_obj->position, offset); +#endif + p_obj->position = offset; + return p_obj->op.seek(p_obj->user_data, offset, whence); + } + + return 0; +} + +/** + Return whatever size of stream reports, I guess unit size is bytes. + On error return -1; + */ +off_t +cdio_stream_stat(CdioDataSource_t *p_obj) +{ + if (!p_obj) return -1; + if (!_cdio_stream_open_if_necessary(p_obj)) return -1; + + return p_obj->op.stat(p_obj->user_data); +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/_cdio_stream.h b/src/libcdio/driver/_cdio_stream.h new file mode 100644 index 00000000..9bc77311 --- /dev/null +++ b/src/libcdio/driver/_cdio_stream.h @@ -0,0 +1,139 @@ +/* + $Id: _cdio_stream.h,v 1.5 2008/04/22 15:29:11 karl Exp $ + + Copyright (C) 2003, 2004, 2005, 2006, 2008 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + + +#ifndef __CDIO_STREAM_H__ +#define __CDIO_STREAM_H__ + +#include +#include "cdio_private.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /* typedef'ed IO functions prototypes */ + + typedef int(*cdio_data_open_t)(void *user_data); + + typedef ssize_t(*cdio_data_read_t)(void *user_data, void *buf, size_t count); + + typedef int(*cdio_data_seek_t)(void *user_data, off_t offset, + int whence); + + typedef off_t(*cdio_data_stat_t)(void *user_data); + + typedef int(*cdio_data_close_t)(void *user_data); + + typedef void(*cdio_data_free_t)(void *user_data); + + + /* abstract data source */ + + typedef struct { + cdio_data_open_t open; + cdio_data_seek_t seek; + cdio_data_stat_t stat; + cdio_data_read_t read; + cdio_data_close_t close; + cdio_data_free_t free; + } cdio_stream_io_functions; + + /** + Like 3 fgetpos. + + This function gets the current file position indicator for the stream + pointed to by stream. + + @return unpon successful completion, return value is positive, else, + the global variable errno is set to indicate the error. + */ + off_t cdio_stream_getpos(CdioDataSource_t* p_obj, + /*out*/ off_t *i_offset); + + CdioDataSource_t * + cdio_stream_new(void *user_data, const cdio_stream_io_functions *funcs); + + /** + Like fread(3) and in fact may be the same. + + DESCRIPTION: + The function fread reads nmemb elements of data, each size bytes long, + from the stream pointed to by stream, storing them at the location + given by ptr. + + RETURN VALUE: + return the number of items successfully read or written (i.e., + not the number of characters). If an error occurs, or the + end-of-file is reached, the return value is a short item count + (or zero). + + We do not distinguish between end-of-file and error, and callers + must use feof(3) and ferror(3) to determine which occurred. + */ + ssize_t cdio_stream_read(CdioDataSource_t* p_obj, void *ptr, size_t i_size, + size_t nmemb); + + /** + Like fseek(3)/fseeko(3) and in fact may be the same. + + This function sets the file position indicator for the stream + pointed to by stream. The new position, measured in bytes, is obtained + by adding offset bytes to the position specified by whence. If whence + is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to + the start of the file, the current position indicator, or end-of-file, + respectively. A successful call to the fseek function clears the end- + of-file indicator for the stream and undoes any effects of the + ungetc(3) function on the same stream. + + @return upon successful completion, DRIVER_OP_SUCCESS, else, + DRIVER_OP_ERROR is returned and the global variable errno is set to + indicate the error. + */ + int cdio_stream_seek(CdioDataSource_t *p_obj, off_t i_offset, + int whence); + + /** + Return whatever size of stream reports, I guess unit size is bytes. + On error return -1; + */ + off_t cdio_stream_stat(CdioDataSource_t *p_obj); + + /** + Deallocate resources associated with p_obj. After this p_obj is unusable. + */ + void cdio_stream_destroy(CdioDataSource_t *p_obj); + + void cdio_stream_close(CdioDataSource_t *p_obj); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_STREAM_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/cdio_assert.h b/src/libcdio/driver/cdio_assert.h new file mode 100644 index 00000000..d9f4f811 --- /dev/null +++ b/src/libcdio/driver/cdio_assert.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2008, 2011 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifndef __CDIO_ASSERT_H__ +#define __CDIO_ASSERT_H__ + +#if defined(__GNUC__) && !defined(__MINGW32__) + +#if defined(HAVE_CONFIG_H) && !defined(__CDIO_CONFIG_H__) +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#include + +#define cdio_assert(expr) \ + { \ + if (GNUC_UNLIKELY (!(expr))) cdio_log (CDIO_LOG_ASSERT, \ + "file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + } + +#define cdio_assert_not_reached() \ + { \ + cdio_log (CDIO_LOG_ASSERT, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + } + +#else /* non GNU C or MinGW */ + +#include + +#define cdio_assert(expr) \ + assert(expr) + +#define cdio_assert_not_reached() \ + assert(0) + +#endif + +#endif /* __CDIO_ASSERT_H__ */ diff --git a/src/libcdio/driver/cdio_private.h b/src/libcdio/driver/cdio_private.h new file mode 100644 index 00000000..53568f06 --- /dev/null +++ b/src/libcdio/driver/cdio_private.h @@ -0,0 +1,562 @@ +/* + Copyright (C) 2003, 2004, 2005, 2008, 2009, 2011 + Rocky Bernstein + + 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 3 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, see . +*/ + +/* Internal routines for CD I/O drivers. */ + + +#ifndef __CDIO_PRIVATE_H__ +#define __CDIO_PRIVATE_H__ + +#if defined(HAVE_CONFIG_H) && !defined(LIBCDIO_CONFIG_H) +# include "config.h" +#endif + +#include +#include +#include +//#include "mmc/mmc_private.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + extern const char * cdio_dirname(const char *fname); + extern const char *cdio_abspath(const char *cwd, const char *fname); + + /* Opaque type */ + typedef struct _CdioDataSource CdioDataSource_t; + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ + +#include "generic.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + typedef struct { + + /*! + Get volume of an audio CD. + + @param p_env the CD object to be acted upon. + + */ + driver_return_code_t (*audio_get_volume) + (void *p_env, /*out*/ cdio_audio_volume_t *p_volume); + + /*! + Pause playing CD through analog output + + @param p_env the CD object to be acted upon. + */ + driver_return_code_t (*audio_pause) (void *p_env); + + /*! + Playing CD through analog output + + @param p_env the CD object to be acted upon. + */ + driver_return_code_t (*audio_play_msf) ( void *p_env, + msf_t *p_start_msf, + msf_t *p_end_msf ); + + /*! + Playing CD through analog output + + @param p_env the CD object to be acted upon. + */ + driver_return_code_t (*audio_play_track_index) + ( void *p_env, cdio_track_index_t *p_track_index ); + + /*! + Get subchannel information. + + @param p_env the CD object to be acted upon. + */ + driver_return_code_t (*audio_read_subchannel) + ( void *p_env, cdio_subchannel_t *subchannel ); + + /*! + Resume playing an audio CD. + + @param p_env the CD object to be acted upon. + + */ + driver_return_code_t (*audio_resume) ( void *p_env ); + + /*! + Set volume of an audio CD. + + @param p_env the CD object to be acted upon. + + */ + driver_return_code_t (*audio_set_volume) + ( void *p_env, cdio_audio_volume_t *p_volume ); + + /*! + Stop playing an audio CD. + + @param p_env the CD object to be acted upon. + + */ + driver_return_code_t (*audio_stop) ( void *p_env ); + + /*! + Eject media in CD drive. If successful, as a side effect we + also free p_env. + + @param p_env the CD object to be acted upon. + If the CD is ejected *p_env is freed and p_env set to NULL. + */ + driver_return_code_t (*eject_media) ( void *p_env ); + + /*! + Release and free resources associated with cd. + */ + void (*free) (void *p_env); + + /*! + Return the value associated with the key "arg". + */ + const char * (*get_arg) (void *p_env, const char key[]); + + /*! + Get the block size for subsequest read requests, via a SCSI MMC + MODE_SENSE 6 command. + */ + int (*get_blocksize) ( void *p_env ); + + /*! + Get cdtext information for a CdIo object. + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. + */ + cdtext_t * (*get_cdtext) ( void *p_env ); + + /*! + Get raw cdtext information as on the disc for a CdIo object + + @param obj the CD object that may contain CD-TEXT information. + @return pointer to the raw CD-TEXT data or NULL if obj is NULL + or no CD-TEXT information present on the disc. + + free when done and not NULL. + */ + uint8_t * (*get_cdtext_raw) ( void *p_env ); + + /*! + Return an array of device names. if CdIo is NULL (we haven't + initialized a specific device driver), then find a suitable device + driver. + + NULL is returned if we couldn't return a list of devices. + */ + char ** (*get_devices) ( void ); + + /*! + Get the default CD device. + + @return a string containing the default CD device or NULL is + if we couldn't get a default device. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + char * (*get_default_device) ( void ); + + /*! + Return the size of the CD in logical block address (LBA) units. + @return the lsn. On error 0 or CDIO_INVALD_LSN. + */ + lsn_t (*get_disc_last_lsn) ( void *p_env ); + + /*! + Get disc mode associated with cd_obj. + */ + discmode_t (*get_discmode) ( void *p_env ); + + /*! + Return the what kind of device we've got. + + See cd_types.h for a list of bitmasks for the drive type; + */ + void (*get_drive_cap) (const void *p_env, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); + /*! + Return the number of of the first track. + CDIO_INVALID_TRACK is returned on error. + */ + track_t (*get_first_track_num) ( void *p_env ); + + /*! + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. + */ + bool (*get_hwinfo) + ( const CdIo_t *p_cdio, /* out*/ cdio_hwinfo_t *p_hw_info ); + + /*! Get the LSN of the first track of the last session of + on the CD. + + @param p_cdio the CD object to be acted upon. + @param i_last_session pointer to the session number to be returned. + */ + driver_return_code_t (*get_last_session) + ( void *p_env, /*out*/ lsn_t *i_last_session ); + + /*! + Find out if media has changed since the last call. + @param p_env the CD object to be acted upon. + @return 1 if media has changed since last call, 0 if not. Error + return codes are the same as driver_return_code_t + */ + int (*get_media_changed) ( const void *p_env ); + + /*! + Return the media catalog number MCN from the CD or NULL if + there is none or we don't have the ability to get it. + */ + char * (*get_mcn) ( const void *p_env ); + + /*! + Return the number of tracks in the current medium. + CDIO_INVALID_TRACK is returned on error. + */ + track_t (*get_num_tracks) ( void *p_env ); + + /*! Return number of channels in track: 2 or 4; -2 if not + implemented or -1 for error. + Not meaningful if track is not an audio track. + */ + int (*get_track_channels) ( const void *p_env, track_t i_track ); + + /*! Return 0 if track is copy protected, 1 if not, or -1 for error + or -2 if not implimented (yet). Is this meaningful if not an + audio track? + */ + track_flag_t (*get_track_copy_permit) ( void *p_env, track_t i_track ); + + /*! + Return the starting LBA for track number + i_track in p_env. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + CDIO_INVALID_LBA is returned on error. + */ + lba_t (*get_track_lba) ( void *p_env, track_t i_track ); + + /*! + Return the starting LBA for the pregap for track number + i_track in p_env. Tracks numbers start at 1. + CDIO_INVALID_LBA is returned on error. + */ + lba_t (*get_track_pregap_lba) ( const void *p_env, track_t i_track ); + + /*! + Return the International Standard Recording Code (ISRC) for track number + i_track in p_cdio. Track numbers start at 1. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. + */ + char * (*get_track_isrc) ( const void *p_env, track_t i_track ); + + /*! + Get format of track. + */ + track_format_t (*get_track_format) ( void *p_env, track_t i_track ); + + /*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? + */ + bool (*get_track_green) ( void *p_env, track_t i_track ); + + /*! + Return the starting MSF (minutes/secs/frames) for track number + i_track in p_env. Tracks numbers start at 1. + The "leadout" track is specified either by + using i_track LEADOUT_TRACK or the total tracks+1. + False is returned on error. + */ + bool (*get_track_msf) ( void *p_env, track_t i_track, msf_t *p_msf ); + + /*! Return 1 if track has pre-emphasis, 0 if not, or -1 for error + or -2 if not implimented (yet). Is this meaningful if not an + audio track? + */ + track_flag_t (*get_track_preemphasis) + ( const void *p_env, track_t i_track ); + + /*! + lseek - reposition read/write file offset + Returns (off_t) -1 on error. + Similar to libc's lseek() + */ + off_t (*lseek) ( void *p_env, off_t offset, int whence ); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Similar to libc's read() + */ + ssize_t (*read) ( void *p_env, void *p_buf, size_t i_size ); + + /*! + Reads a single mode2 sector from cd device into buf starting + from lsn. Returns 0 if no error. + */ + int (*read_audio_sectors) ( void *p_env, void *p_buf, lsn_t i_lsn, + unsigned int i_blocks ); + + /*! + Read a data sector + + @param p_env environment to read from + + @param p_buf place to read data into. The caller should make sure + this location can store at least CDIO_CD_FRAMESIZE, + M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE depending + on the kind of sector getting read. If you don't + know whether you have a Mode 1/2, Form 1/ Form 2/Formless + sector best to reserve space for the maximum, + M2RAW_SECTOR_SIZE. + + @param i_lsn sector to read + @param i_blocksize size of block. Should be either CDIO_CD_FRAMESIZE, + M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under p_buf. + */ + driver_return_code_t (*read_data_sectors) + ( void *p_env, void *p_buf, lsn_t i_lsn, uint16_t i_blocksize, + uint32_t i_blocks ); + + /*! + Reads a single mode2 sector from cd device into buf starting + from lsn. Returns 0 if no error. + */ + int (*read_mode2_sector) + ( void *p_env, void *p_buf, lsn_t i_lsn, bool b_mode2_form2 ); + + /*! + Reads i_blocks of mode2 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ + int (*read_mode2_sectors) + ( void *p_env, void *p_buf, lsn_t i_lsn, bool b_mode2_form2, + unsigned int i_blocks ); + + /*! + Reads a single mode1 sector from cd device into buf starting + from lsn. Returns 0 if no error. + */ + int (*read_mode1_sector) + ( void *p_env, void *p_buf, lsn_t i_lsn, bool mode1_form2 ); + + /*! + Reads i_blocks of mode1 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ + int (*read_mode1_sectors) + ( void *p_env, void *p_buf, lsn_t i_lsn, bool mode1_form2, + unsigned int i_blocks ); + + bool (*read_toc) ( void *p_env ) ; + + /*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout_ms time in milliseconds we will wait for the command + to complete. + cdb_len number of bytes in cdb (6, 10, or 12). + cdb CDB bytes. All values that are needed should be set on + input. + b_return_data TRUE if the command expects data to be returned in + the buffer + len Size of buffer + buf Buffer for data, both sending and receiving + + Returns 0 if command completed successfully. + */ +// mmc_run_cmd_fn_t run_mmc_cmd; + + /*! + Set the arg "key" with "value" in the source device. + */ + int (*set_arg) ( void *p_env, const char key[], const char value[] ); + + /*! + Set the blocksize for subsequent reads. + */ + driver_return_code_t (*set_blocksize) ( void *p_env, + uint16_t i_blocksize ); + + /*! + Set the drive speed. + + @return 0 if everything went okay, -1 if we had an error. is -2 + returned if this is not implemented for the current driver. + */ + int (*set_speed) ( void *p_env, int i_speed ); + + } cdio_funcs_t; + + + /*! Implementation of CdIo type */ + struct _CdIo { + driver_id_t driver_id; /**< Particular driver opened. */ + cdio_funcs_t op; /**< driver-specific routines handling + implementation*/ + void *env; /**< environment. Passed to routine above. */ + }; + + /* This is used in drivers that must keep their own internal + position pointer for doing seeks. Stream-based drivers (like bincue, + nrg, toc, network) would use this. + */ + typedef struct + { + off_t buff_offset; /* buffer offset in disk-image seeks. */ + track_t index; /* Current track index in tocent. */ + lba_t lba; /* Current LBA */ + } internal_position_t; + + CdIo_t * cdio_new (generic_img_private_t *p_env, cdio_funcs_t *p_funcs); + + /* The below structure describes a specific CD Input driver */ + typedef struct + { + driver_id_t id; + unsigned int flags; + const char *name; + const char *describe; + bool (*have_driver) (void); + CdIo_t *(*driver_open) (const char *psz_source_name); + CdIo_t *(*driver_open_am) (const char *psz_source_name, + const char *psz_access_mode); + char *(*get_default_device) (void); + bool (*is_device) (const char *psz_source_name); + char **(*get_devices) (void); + driver_return_code_t (*close_tray) (const char *psz_device); + } CdIo_driver_t; + + /* The below array gives of the drivers that are currently available for + on a particular host. */ + extern CdIo_driver_t CdIo_driver[]; + + /* The last valid entry of Cdio_driver. -1 means uninitialzed. -2 + means some sort of error. + */ + extern int CdIo_last_driver; + + /* The below array gives all drivers that can possibly appear. + on a particular host. */ + extern CdIo_driver_t CdIo_all_drivers[]; + + /*! + Add/allocate a drive to the end of drives. + Use cdio_free_device_list() to free this device_list. + */ + void cdio_add_device_list(char **device_list[], const char *psz_drive, + unsigned int *i_drives); + + driver_return_code_t close_tray_bsdi (const char *psz_drive); + driver_return_code_t close_tray_freebsd (const char *psz_drive); + driver_return_code_t close_tray_linux (const char *psz_drive); + driver_return_code_t close_tray_netbsd (const char *psz_drive); + driver_return_code_t close_tray_os2 (const char *psz_drive); + driver_return_code_t close_tray_osx (const char *psz_drive); + driver_return_code_t close_tray_solaris (const char *psz_drive); + driver_return_code_t close_tray_win32 (const char *psz_drive); + + bool cdio_have_netbsd(void); + CdIo_t * cdio_open_netbsd (const char *psz_source); + char * cdio_get_default_device_netbsd(void); + char **cdio_get_devices_netbsd(void); + /*! Set up CD-ROM for reading using the NetBSD driver. The device_name is + the some sort of device name. + + NULL is returned on error or there is no FreeBSD driver. + + @see cdio_open_cd, cdio_open + */ + CdIo_t * cdio_open_am_netbsd (const char *psz_source, + const char *psz_access_mode); + + /*! DEPRICATED: use cdio_have_driver(). + True if AIX driver is available. */ + bool cdio_have_aix (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if BSDI driver is available. */ + bool cdio_have_bsdi (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if FreeBSD driver is available. */ + bool cdio_have_freebsd (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if GNU/Linux driver is available. */ + bool cdio_have_linux (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if Sun Solaris driver is available. */ + bool cdio_have_solaris (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if IBM OS2 driver is available. */ + bool cdio_have_os2 (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if Apple OSX driver is available. */ + bool cdio_have_osx (void); + + /*! DEPRICATED: use cdio_have_driver(). + True if Microsoft Windows driver is available. */ + bool cdio_have_win32 (void); + + /*! True if Nero driver is available. */ + bool cdio_have_nrg (void); + + /*! True if BIN/CUE driver is available. */ + bool cdio_have_bincue (void); + + /*! True if cdrdao CDRDAO driver is available. */ + bool cdio_have_cdrdao (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_PRIVATE_H__ */ diff --git a/src/libcdio/driver/disc.c b/src/libcdio/driver/disc.c new file mode 100644 index 00000000..3c66ea95 --- /dev/null +++ b/src/libcdio/driver/disc.c @@ -0,0 +1,164 @@ +/* + Copyright (C) 2003, 2004, 2005, 2008, 2011 + Rocky Bernstein + Copyright (C) 2001 Herbert Valerio Riedel + + 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 3 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, see . +*/ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#include "cdio_private.h" + +/* Must match discmode enumeration */ +const char *discmode2str[] = { + "CD-DA", + "CD-DATA (Mode 1)", + "CD DATA (Mode 2)", + "CD-ROM Mixed", + "DVD-ROM", + "DVD-RAM", + "DVD-R", + "DVD-RW", + "HD DVD ROM", + "HD_DVD RAM", + "HD DVD-R", + "DVD+R", + "DVD+RW", + "DVD+RW DL", + "DVD+R DL", + "Unknown/unclassified DVD", + "No information", + "Error in getting information", + "CD-i" +}; + +/*! + Get cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. +*/ +cdtext_t * +cdio_get_cdtext (CdIo *obj) +{ + if (obj == NULL) return NULL; + + if (NULL != obj->op.get_cdtext) { + return obj->op.get_cdtext (obj->env); + } else { + return NULL; + } +} + +/*! + Get binary cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return pointer to allocated memory area holding the raw CD-TEXT + or NULL if obj is NULL or CD-TEXT does not exist. + free() when done. +*/ +uint8_t * +cdio_get_cdtext_raw (CdIo *obj) +{ + if (obj == NULL) return NULL; + + if (NULL != obj->op.get_cdtext_raw) { + return obj->op.get_cdtext_raw (obj->env); + } else { + return NULL; + } +} + +/*! + Get the size of the CD in logical block address (LBA) units. + + @param p_cdio the CD object queried + @return the lsn. On error 0 or CDIO_INVALD_LSN. +*/ +lsn_t +cdio_get_disc_last_lsn(const CdIo_t *p_cdio) +{ + if (!p_cdio) return CDIO_INVALID_LSN; + return p_cdio->op.get_disc_last_lsn (p_cdio->env); +} + +/*! + Get medium associated with cd_obj. +*/ +discmode_t +cdio_get_discmode (CdIo_t *cd_obj) +{ + if (!cd_obj) return CDIO_DISC_MODE_ERROR; + + if (cd_obj->op.get_discmode) { + return cd_obj->op.get_discmode (cd_obj->env); + } else { + return CDIO_DISC_MODE_NO_INFO; + } +} + +/*! + Return a string containing the name of the driver in use. + if CdIo is NULL (we haven't initialized a specific device driver), + then return NULL. +*/ +char * +cdio_get_mcn (const CdIo_t *p_cdio) +{ + if (p_cdio->op.get_mcn) { + return p_cdio->op.get_mcn (p_cdio->env); + } else { + return NULL; + } +} + +bool +cdio_is_discmode_cdrom(discmode_t discmode) +{ + switch (discmode) { + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_NO_INFO: + return true; + default: + return false; + } +} + +bool +cdio_is_discmode_dvd(discmode_t discmode) +{ + switch (discmode) { + case CDIO_DISC_MODE_DVD_ROM: + case CDIO_DISC_MODE_DVD_RAM: + case CDIO_DISC_MODE_DVD_R: + case CDIO_DISC_MODE_DVD_RW: + case CDIO_DISC_MODE_DVD_PR: + case CDIO_DISC_MODE_DVD_PRW: + case CDIO_DISC_MODE_DVD_OTHER: + return true; + default: + return false; + } +} diff --git a/src/libcdio/driver/ds.c b/src/libcdio/driver/ds.c new file mode 100644 index 00000000..74936bb8 --- /dev/null +++ b/src/libcdio/driver/ds.c @@ -0,0 +1,254 @@ +/* + Copyright (C) 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include +#include +#include +#include "cdio_assert.h" + +static const char _rcsid[] = "$Id: ds.c,v 1.4 2008/04/22 15:29:12 karl Exp $"; + +struct _CdioList +{ + unsigned length; + + CdioListNode_t *begin; + CdioListNode_t *end; +}; + +struct _CdioListNode +{ + CdioList_t *list; + + CdioListNode_t *next; + + void *data; +}; + +/* impl */ + +CdioList_t * +_cdio_list_new (void) +{ + CdioList_t *p_new_obj = calloc (1, sizeof (CdioList_t)); + + return p_new_obj; +} + +void +_cdio_list_free (CdioList_t *p_list, int free_data) +{ + while (_cdio_list_length (p_list)) + _cdio_list_node_free (_cdio_list_begin (p_list), free_data); + + free (p_list); +} + +unsigned +_cdio_list_length (const CdioList_t *p_list) +{ + cdio_assert (p_list != NULL); + + return p_list->length; +} + +void +_cdio_list_prepend (CdioList_t *p_list, void *p_data) +{ + CdioListNode_t *p_new_node; + + cdio_assert (p_list != NULL); + + p_new_node = calloc (1, sizeof (CdioListNode_t)); + + p_new_node->list = p_list; + p_new_node->next = p_list->begin; + p_new_node->data = p_data; + + p_list->begin = p_new_node; + if (p_list->length == 0) + p_list->end = p_new_node; + + p_list->length++; +} + +void +_cdio_list_append (CdioList_t *p_list, void *p_data) +{ + cdio_assert (p_list != NULL); + + if (p_list->length == 0) + { + _cdio_list_prepend (p_list, p_data); + } + else + { + CdioListNode_t *p_new_node = calloc (1, sizeof (CdioListNode_t)); + + p_new_node->list = p_list; + p_new_node->next = NULL; + p_new_node->data = p_data; + + p_list->end->next = p_new_node; + p_list->end = p_new_node; + + p_list->length++; + } +} + +void +_cdio_list_foreach (CdioList_t *p_list, _cdio_list_iterfunc_t func, + void *p_user_data) +{ + CdioListNode_t *node; + + cdio_assert (p_list != NULL); + cdio_assert (func != 0); + + for (node = _cdio_list_begin (p_list); + node != NULL; + node = _cdio_list_node_next (node)) + func (_cdio_list_node_data (node), p_user_data); +} + +CdioListNode_t * +_cdio_list_find (CdioList_t *p_list, _cdio_list_iterfunc_t cmp_func, + void *p_user_data) +{ + CdioListNode_t *p_node; + + cdio_assert (p_list != NULL); + cdio_assert (cmp_func != 0); + + for (p_node = _cdio_list_begin (p_list); + p_node != NULL; + p_node = _cdio_list_node_next (p_node)) + if (cmp_func (_cdio_list_node_data (p_node), p_user_data)) + break; + + return p_node; +} + +CdioListNode_t * +_cdio_list_begin (const CdioList_t *p_list) +{ + cdio_assert (p_list != NULL); + + return p_list->begin; +} + +CdioListNode_t * +_cdio_list_end (CdioList_t *p_list) +{ + cdio_assert (p_list != NULL); + + return p_list->end; +} + +CdioListNode_t * +_cdio_list_node_next (CdioListNode_t *p_node) +{ + if (p_node) + return p_node->next; + + return NULL; +} + +void +_cdio_list_node_free (CdioListNode_t *p_node, int free_data) +{ + CdioList_t *p_list; + CdioListNode_t *prev_node; + + cdio_assert (p_node != NULL); + + p_list = p_node->list; + + cdio_assert (_cdio_list_length (p_list) > 0); + + if (free_data) + free (_cdio_list_node_data (p_node)); + + if (_cdio_list_length (p_list) == 1) + { + cdio_assert (p_list->begin == p_list->end); + + p_list->end = p_list->begin = NULL; + p_list->length = 0; + free (p_node); + return; + } + + cdio_assert (p_list->begin != p_list->end); + + if (p_list->begin == p_node) + { + p_list->begin = p_node->next; + free (p_node); + p_list->length--; + return; + } + + for (prev_node = p_list->begin; prev_node->next; prev_node = prev_node->next) + if (prev_node->next == p_node) + break; + + cdio_assert (prev_node->next != NULL); + + if (p_list->end == p_node) + p_list->end = prev_node; + + prev_node->next = p_node->next; + + p_list->length--; + + free (p_node); +} + +void * +_cdio_list_node_data (CdioListNode_t *p_node) +{ + if (p_node) + return p_node->data; + + return NULL; +} + +/* eof */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ + diff --git a/src/libcdio/driver/filemode.h b/src/libcdio/driver/filemode.h new file mode 100644 index 00000000..7ca25ba7 --- /dev/null +++ b/src/libcdio/driver/filemode.h @@ -0,0 +1,134 @@ +/* + filemode.h -- file modes common definitions + + Copyright (C) 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 1985, 1990, 1993, 1998-2000 Free Software Foundation, Inc. + + 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 3 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, see . +*/ + +#ifndef __FILEMODE_H__ +#define __FILEMODE_H__ + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifndef S_IRUSR +# ifdef S_IREAD +# define S_IRUSR S_IREAD +# else +# define S_IRUSR 00400 +# endif +#endif + +#ifndef S_IWUSR +# ifdef S_IWRITE +# define S_IWUSR S_IWRITE +# else +# define S_IWUSR 00200 +# endif +#endif + +#ifndef S_IXUSR +# ifdef S_IEXEC +# define S_IXUSR S_IEXEC +# else +# define S_IXUSR 00100 +# endif +#endif + +#ifndef S_IRGRP +# define S_IRGRP (S_IRUSR >> 3) +#endif +#ifndef S_IWGRP +# define S_IWGRP (S_IWUSR >> 3) +#endif +#ifndef S_IXGRP +# define S_IXGRP (S_IXUSR >> 3) +#endif +#ifndef S_IROTH +# define S_IROTH (S_IRUSR >> 6) +#endif +#ifndef S_IWOTH +# define S_IWOTH (S_IWUSR >> 6) +#endif +#ifndef S_IXOTH +# define S_IXOTH (S_IXUSR >> 6) +#endif + +#ifdef STAT_MACROS_BROKEN +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISLNK +# undef S_ISMPB +# undef S_ISMPC +# undef S_ISNWK +# undef S_ISREG +# undef S_ISSOCK +#endif /* STAT_MACROS_BROKEN. */ + +#if !defined S_IFBLK && defined _WIN32 +# define S_IFBLK 0x3000 +#endif +#if !defined S_IFIFO && defined _WIN32 +# define S_IFIFO 0x1000 +#endif + +#if !defined S_ISBLK && defined S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#endif +#if !defined S_ISCHR && defined S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#endif +#if !defined S_ISDIR && defined S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#if !defined S_ISREG && defined S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif +#if !defined S_ISFIFO && defined S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#endif +#if !defined HAVE_S_ISLNK +# if !defined S_ISLNK && defined S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) ((void)m, 0) +# endif +#endif +#if !defined HAVE_S_ISSOCK +# if !defined S_ISSOCK && defined S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) ((void)m, 0) +# endif +#endif +#if !defined S_ISMPB && defined S_IFMPB /* V7 */ +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +#endif +#if !defined S_ISNWK && defined S_IFNWK /* HP/UX */ +# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +#endif +#if !defined S_ISDOOR && defined S_IFDOOR /* Solaris 2.5 and up */ +# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR) +#endif +#if !defined S_ISCTG && defined S_IFCTG /* MassComp */ +# define S_ISCTG(m) (((m) & S_IFMT) == S_IFCTG) +#endif + +#endif /* __FILEMODE_H__ */ diff --git a/src/libcdio/driver/generic.h b/src/libcdio/driver/generic.h new file mode 100644 index 00000000..e0dd2618 --- /dev/null +++ b/src/libcdio/driver/generic.h @@ -0,0 +1,249 @@ +/* + Copyright (C) 2004, 2005, 2006, 2008, 2009 Rocky Bernstein + + 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 3 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, see . +*/ + +/* Internal routines for CD I/O drivers. */ + + +#ifndef __CDIO_GENERIC_H__ +#define __CDIO_GENERIC_H__ + +#if defined(HAVE_CONFIG_H) && !defined(LIBCDIO_CONFIG_H) +# include "config.h" +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! + Things common to private device structures. Even though not all + devices may have some of these fields, by listing common ones + we facilitate writing generic routines and even cut-and-paste + code. + */ + typedef struct { + char *source_name; /**< Name used in open. */ + bool init; /**< True if structure has been initialized */ + bool toc_init; /**< True if TOC read in */ + bool b_cdtext_error; /**< True if trouble reading CD-Text */ + + int ioctls_debugged; /**< for debugging */ + + /* Only one of data_source or fd is used; fd is for CD-ROM + devices and the data_source for stream reading (bincue, nrg, toc, + network). + */ + CdioDataSource_t *data_source; + int fd; /**< File descriptor of device */ + track_t i_first_track; /**< The starting track number. */ + track_t i_tracks; /**< The number of tracks. */ + + uint8_t i_joliet_level; /**< 0 = no Joliet extensions. + 1-3: Joliet level. */ + iso9660_pvd_t pvd; + iso9660_svd_t svd; + CdIo_t *cdio; /**< a way to call general cdio routines. */ + cdtext_t *cdtext; /**< CD-Text for disc. */ + track_flags_t track_flags[CDIO_CD_MAX_TRACKS+1]; + + /* Memorized sense reply of the most recent SCSI command. + Recorded by driver implementations of cdio_funcs_t.run_mmc_cmd(). + Read by API function mmc_get_cmd_scsi_sense(). + */ + unsigned char scsi_mmc_sense[263]; /* See SPC-3 4.5.3 : 252 bytes legal + but 263 bytes possible */ + int scsi_mmc_sense_valid; /* Number of valid sense bytes */ + + /* Memorized eventual system specific SCSI address tuple text. + Empty text means that there is no such text defined for the drive. + NULL means that the driver does not support "scsi-tuple". + To be read by cdio_get_arg("scsi-tuple"). + System specific suffixes to the key may demand and eventually + guarantee a further specified format. + E.g. "scsi-tuple-linux" guarantees either "Bus,Host,Channel,Target,Lun", + or empty text, or NULL. No other forms. + */ + char *scsi_tuple; + } generic_img_private_t; + + /*! + Bogus eject media when there is no ejectable media, e.g. a disk image + We always return 2. Should we also free resources? + */ + driver_return_code_t cdio_generic_unimplemented_eject_media (void *p_env); + + /*! + Set the blocksize for subsequent reads. + + @return -2 since it's not implemented. + */ + driver_return_code_t + cdio_generic_unimplemented_set_blocksize (void *p_user_data, + uint16_t i_blocksize); + + /*! + Set the drive speed. + + @return -2 since it's not implemented. + */ + driver_return_code_t cdio_generic_unimplemented_set_speed (void *p_user_data, + int i_speed); + + /*! + Release and free resources associated with cd. + */ + void cdio_generic_free (void *p_env); + + /*! + Initialize CD device. + */ + bool cdio_generic_init (void *p_env, int open_mode); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). + */ + off_t cdio_generic_lseek (void *p_env, off_t offset, int whence); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). + */ + ssize_t cdio_generic_read (void *p_env, void *p_buf, size_t size); + + /*! + Reads a single form1 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ + int cdio_generic_read_form1_sector (void * user_data, void *data, + lsn_t lsn); + + /*! + Release and free resources associated with stream or disk image. + */ + void cdio_generic_stdio_free (void *env); + + /*! + Return true if source_name could be a device containing a CD-ROM on + Win32 + */ + bool cdio_is_device_win32(const char *source_name); + + /*! + Return true if source_name could be a device containing a CD-ROM on + OS/2 + */ + bool cdio_is_device_os2(const char *source_name); + + + /*! + Return true if source_name could be a device containing a CD-ROM on + most Unix servers with block and character devices. + */ + bool cdio_is_device_generic(const char *source_name); + + + /*! + Like above, but don't give a warning device doesn't exist. + */ + bool cdio_is_device_quiet_generic(const char *source_name); + + /*! + Get cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. + */ + cdtext_t *get_cdtext_generic (void *p_user_data); + + /*! + Return the number of of the first track. + CDIO_INVALID_TRACK is returned on error. + */ + track_t get_first_track_num_generic(void *p_user_data); + + /*! + Return the number of tracks in the current medium. + */ + track_t get_num_tracks_generic(void *p_user_data); + + /*! + Get disc type associated with cd object. + */ + discmode_t get_discmode_generic (void *p_user_data ); + + /*! + Same as above but only handles CD cases + */ + discmode_t get_discmode_cd_generic (void *p_user_data ); + + /*! Return number of channels in track: 2 or 4; -2 if not + implemented or -1 for error. + Not meaningful if track is not an audio track. + */ + int get_track_channels_generic(const void *p_user_data, track_t i_track); + + /*! Return 1 if copy is permitted on the track, 0 if not, or -1 for error. + Is this meaningful if not an audio track? + */ + track_flag_t get_track_copy_permit_generic(void *p_user_data, + track_t i_track); + + /*! Return 1 if track has pre-emphasis, 0 if not, or -1 for error. + Is this meaningful if not an audio track? + + pre-emphasis is a non linear frequency response. + */ + track_flag_t get_track_preemphasis_generic(const void *p_user_data, + track_t i_track); + + /*! + Read cdtext information for a CdIo object . + + return true on success, false on error or CD-Text information does + not exist. + */ + uint8_t * read_cdtext_generic (void *p_env); + + void set_track_flags(track_flags_t *p_track_flag, uint8_t flag); + + /*! Read mode 1 or mode2 sectors (using cooked mode). */ + driver_return_code_t read_data_sectors_generic (void *p_user_data, + void *p_buf, lsn_t i_lsn, + uint16_t i_blocksize, + uint32_t i_blocks); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_GENERIC_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/logging.c b/src/libcdio/driver/logging.c new file mode 100644 index 00000000..82114fa0 --- /dev/null +++ b/src/libcdio/driver/logging.c @@ -0,0 +1,147 @@ +/* + Copyright (C) 2003, 2004, 2008, 2011 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_STDIO_H +#include +#endif + +#include +#include "cdio_assert.h" +#include "portable.h" + +static const char _rcsid[] = "$Id: logging.c,v 1.2 2008/04/22 15:29:12 karl Exp $"; + +cdio_log_level_t cdio_loglevel_default = CDIO_LOG_WARN; + +static void +default_cdio_log_handler (cdio_log_level_t level, const char message[]) +{ + switch (level) + { + case CDIO_LOG_ERROR: + if (level >= cdio_loglevel_default) { + fprintf (stderr, "**ERROR: %s\n", message); + fflush (stderr); + } + exit (EXIT_FAILURE); + break; + case CDIO_LOG_DEBUG: + if (level >= cdio_loglevel_default) { + fprintf (stdout, "--DEBUG: %s\n", message); + } + break; + case CDIO_LOG_WARN: + if (level >= cdio_loglevel_default) { + fprintf (stdout, "++ WARN: %s\n", message); + } + break; + case CDIO_LOG_INFO: + if (level >= cdio_loglevel_default) { + fprintf (stdout, " INFO: %s\n", message); + } + break; + case CDIO_LOG_ASSERT: + if (level >= cdio_loglevel_default) { + fprintf (stderr, "!ASSERT: %s\n", message); + fflush (stderr); + } + abort (); + break; + default: + cdio_assert_not_reached (); + break; + } + + fflush (stdout); +} + +static cdio_log_handler_t _handler = default_cdio_log_handler; + +cdio_log_handler_t +cdio_log_set_handler (cdio_log_handler_t new_handler) +{ + cdio_log_handler_t old_handler = _handler; + + _handler = new_handler; + + return old_handler; +} + +static void +cdio_logv (cdio_log_level_t level, const char format[], va_list args) +{ + char buf[1024] = { 0, }; + static int in_recursion = 0; + + if (in_recursion) + cdio_assert_not_reached (); + + in_recursion = 1; + + vsnprintf(buf, sizeof(buf)-1, format, args); + + _handler(level, buf); + + in_recursion = 0; +} + +void +cdio_log (cdio_log_level_t level, const char format[], ...) +{ + va_list args; + va_start (args, format); + cdio_logv (level, format, args); + va_end (args); +} + +#define CDIO_LOG_TEMPLATE(level, LEVEL) \ +void \ +cdio_ ## level (const char format[], ...) \ +{ \ + va_list args; \ + va_start (args, format); \ + cdio_logv (CDIO_LOG_ ## LEVEL, format, args); \ + va_end (args); \ +} + +CDIO_LOG_TEMPLATE(debug, DEBUG) +CDIO_LOG_TEMPLATE(info, INFO) +CDIO_LOG_TEMPLATE(warn, WARN) +CDIO_LOG_TEMPLATE(error, ERROR) + +#undef CDIO_LOG_TEMPLATE + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/portable.h b/src/libcdio/driver/portable.h new file mode 100644 index 00000000..f0516d65 --- /dev/null +++ b/src/libcdio/driver/portable.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2006, 2008, 2011 Rocky Bernstein + + 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 3 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, see . +*/ + +/* + This file contains definitions to fill in for differences or + deficiencies to OS or compiler irregularities. If this file is + included other routines can be more portable. +*/ + +#ifndef __CDIO_PORTABLE_H__ +#define __CDIO_PORTABLE_H__ + +#if defined(HAVE_CONFIG_H) && !defined(__CDIO_CONFIG_H__) +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#if !defined(HAVE_FTRUNCATE) +# if defined (_WIN32) +# define ftruncate chsize +# endif +#endif /*HAVE_FTRUNCATE*/ + +#if !defined(HAVE_SNPRINTF) +# if defined (_MSC_VER) +# define snprintf _snprintf +# endif +#endif /*HAVE_SNPRINTF*/ + +#if !defined(HAVE_VSNPRINTF) +# if defined (_MSC_VER) +# define vsnprintf _vsnprintf +# endif +#endif /*HAVE_SNPRINTF*/ + +#if !defined(HAVE_DRAND48) && defined(HAVE_RAND) +# define drand48() (rand() / (double)RAND_MAX) +#endif + +#endif /* __CDIO_PORTABLE_H__ */ diff --git a/src/libcdio/driver/read.c b/src/libcdio/driver/read.c new file mode 100644 index 00000000..fd7134e0 --- /dev/null +++ b/src/libcdio/driver/read.c @@ -0,0 +1,328 @@ +/* + Copyright (C) 2005, 2008, 2011 Rocky Bernstein + + 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 3 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, see . +*/ +/** \file read.h + * + * \brief sector (block, frame)-related libcdio routines. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#include +#include "cdio_private.h" +#include "cdio_assert.h" + +#ifdef HAVE_STRING_H +#include +#endif + +#define check_read_parms(p_cdio, p_buf, i_lsn) \ + if (!p_cdio) return DRIVER_OP_UNINIT; \ + if (!p_buf || CDIO_INVALID_LSN == i_lsn) \ + return DRIVER_OP_ERROR; + +#define check_lsn(i_lsn) \ + check_read_parms(p_cdio, p_buf, i_lsn); \ + { \ + lsn_t end_lsn = \ + cdio_get_track_lsn(p_cdio, CDIO_CDROM_LEADOUT_TRACK); \ + if ( i_lsn > end_lsn ) { \ + cdio_info("Trying to access past end of disk lsn: %ld, end lsn: %ld", \ + (long int) i_lsn, (long int) end_lsn); \ + return DRIVER_OP_ERROR; \ + } \ + } + +#define check_lsn_blocks(i_lsn, i_blocks) \ + check_read_parms(p_cdio, p_buf, i_lsn); \ + { \ + lsn_t end_lsn = \ + cdio_get_track_lsn(p_cdio, CDIO_CDROM_LEADOUT_TRACK); \ + if ( i_lsn > end_lsn ) { \ + cdio_info("Trying to access past end of disk lsn: %ld, end lsn: %ld", \ + (long int) i_lsn, (long int) end_lsn); \ + return DRIVER_OP_ERROR; \ + } \ + /* Care is used in the expression below to be correct with */ \ + /* respect to unsigned integers. */ \ + if ( i_lsn + i_blocks > end_lsn + 1 ) { \ + cdio_info("Request truncated to end disk; lsn: %ld, end lsn: %ld", \ + (long int) i_lsn, (long int) end_lsn); \ + i_blocks = end_lsn - i_lsn + 1; \ + } \ + } + +/*! + lseek - reposition read/write file offset + Returns (off_t) -1 on error. + Similar to (if not the same as) libc's lseek() +*/ +off_t +cdio_lseek (const CdIo_t *p_cdio, off_t offset, int whence) +{ + if (!p_cdio) return DRIVER_OP_UNINIT; + + if (p_cdio->op.lseek) + return (p_cdio->op.lseek) (p_cdio->env, offset, whence); + return DRIVER_OP_UNSUPPORTED; +} + +/*! Reads into buf the next size bytes. Similar to (if not the + same as) libc's read(). This is a "cooked" read, or one handled by + the OS. It probably won't work on audio data. For that use + cdio_read_audio_sector(s). + + @param p_cdio object to read from + @param p_buf place to read data into. The caller should make sure + this location can store at least i_size bytes. + @param i_size number of bytes to read + + @return (ssize_t) -1 on error. +*/ +ssize_t +cdio_read (const CdIo_t *p_cdio, void *p_buf, size_t i_size) +{ + if (!p_cdio) return DRIVER_OP_UNINIT; + + if (p_cdio->op.read) + return (p_cdio->op.read) (p_cdio->env, p_buf, i_size); + return DRIVER_OP_UNSUPPORTED; +} + +/*! + Reads an audio sector from cd device into data starting + from lsn. Returns DRIVER_OP_SUCCESS if no error. +*/ +driver_return_code_t +cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn) +{ + check_lsn(i_lsn); + if (p_cdio->op.read_audio_sectors) + return p_cdio->op.read_audio_sectors (p_cdio->env, p_buf, i_lsn, 1); + return DRIVER_OP_UNSUPPORTED; +} + +/*! + Reads audio sectors from cd device into data starting + from lsn. Returns DRIVER_OP_SUCCESS if no error. +*/ +driver_return_code_t +cdio_read_audio_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + uint32_t i_blocks) +{ + check_lsn_blocks(i_lsn, i_blocks); + + if (0 == i_blocks) return DRIVER_OP_SUCCESS; + + if (p_cdio->op.read_audio_sectors) + return (p_cdio->op.read_audio_sectors) (p_cdio->env, p_buf, i_lsn, + i_blocks); + return DRIVER_OP_UNSUPPORTED; +} + +/*! + Reads an audio sector from cd device into data starting + from lsn. Returns DRIVER_OP_SUCCESS if no error. +*/ +driver_return_code_t +cdio_read_data_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + uint16_t i_blocksize, uint32_t i_blocks) +{ + check_lsn(i_lsn); + + if (0 == i_blocks) return DRIVER_OP_SUCCESS; + + if (p_cdio->op.read_data_sectors) + return p_cdio->op.read_data_sectors (p_cdio->env, p_buf, i_lsn, + i_blocksize, i_blocks); + return DRIVER_OP_UNSUPPORTED; +} + + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +/*! + Reads a single mode1 form1 or form2 sector from cd device + into data starting from lsn. Returns DRIVER_OP_SUCCESS if no error. + */ +driver_return_code_t +cdio_read_mode1_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2) +{ + uint32_t size = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; + + check_lsn(i_lsn); + if (p_cdio->op.read_mode1_sector) { + return p_cdio->op.read_mode1_sector(p_cdio->env, p_buf, i_lsn, b_form2); + } else if (p_cdio->op.lseek && p_cdio->op.read) { + char buf[M2RAW_SECTOR_SIZE] = { 0, }; + if (0 > cdio_lseek(p_cdio, CDIO_CD_FRAMESIZE*i_lsn, SEEK_SET)) + return -1; + if (0 > cdio_read(p_cdio, buf, CDIO_CD_FRAMESIZE)) + return -1; + memcpy (p_buf, buf, size); + return DRIVER_OP_SUCCESS; + } + + return DRIVER_OP_UNSUPPORTED; +} + +/*! + Reads mode 1 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 1 form 2 sectors or false for + mode 1 form 1 sectors. + @param i_blocks number of sectors to read +*/ +driver_return_code_t +cdio_read_mode1_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2, uint32_t i_blocks) +{ + check_lsn_blocks(i_lsn, i_blocks); + + if (0 == i_blocks) return DRIVER_OP_SUCCESS; + + if (p_cdio->op.read_mode1_sectors) + return (p_cdio->op.read_mode1_sectors) (p_cdio->env, p_buf, i_lsn, b_form2, + i_blocks); + return DRIVER_OP_UNSUPPORTED; +} + +/*! + Reads a mode 2 sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 2 form 2 sectors or false for + mode 2 form 1 sectors. +*/ +driver_return_code_t +cdio_read_mode2_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2) +{ + check_lsn(i_lsn); + if (p_cdio->op.read_mode2_sector) + return p_cdio->op.read_mode2_sector (p_cdio->env, p_buf, i_lsn, b_form2); + + /* fallback */ + if (p_cdio->op.read_mode2_sectors != NULL) + return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, b_form2, 1); + return DRIVER_OP_UNSUPPORTED; +} + +/*! + Reads mode 2 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode2 form 2 sectors or false for + mode 2 form 1 sectors. + @param i_blocks number of sectors to read +*/ +driver_return_code_t +cdio_read_mode2_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2, uint32_t i_blocks) +{ + check_lsn_blocks(i_lsn, i_blocks); + + if (0 == i_blocks) return DRIVER_OP_SUCCESS; + + if (p_cdio->op.read_mode2_sectors) + return (p_cdio->op.read_mode2_sectors) (p_cdio->env, p_buf, i_lsn, + b_form2, i_blocks); + return DRIVER_OP_UNSUPPORTED; + +} + + +/** The special case of reading a single block is a common one so we + provide a routine for that as a convenience. +*/ +driver_return_code_t +cdio_read_sector(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + cdio_read_mode_t read_mode) +{ + return cdio_read_sectors(p_cdio, p_buf, i_lsn, read_mode, 1); +} + +/*! + Reads a number of sectors (AKA blocks). + + @param p_buf place to read data into. The caller should make sure + this location is large enough. See below for size information. + @param read_mode the kind of "mode" to use in reading. + @param i_lsn sector to read + @param i_blocks number of sectors to read + @return DRIVER_OP_SUCCESS (0) if no error, other (negative) enumerations + are returned on error. + + If read_mode is CDIO_MODE_AUDIO, + *p_buf should hold at least CDIO_FRAMESIZE_RAW * i_blocks bytes. + + If read_mode is CDIO_MODE_DATA, + *p_buf should hold at least i_blocks times either ISO_BLOCKSIZE, + M1RAW_SECTOR_SIZE or M2F2_SECTOR_SIZE depending on the kind of + sector getting read. If you don't know whether you have a Mode 1/2, + Form 1/ Form 2/Formless sector best to reserve space for the maximum + which is M2RAW_SECTOR_SIZE. + + If read_mode is CDIO_MODE_M2F1, + *p_buf should hold at least M2RAW_SECTOR_SIZE * i_blocks bytes. + + If read_mode is CDIO_MODE_M2F2, + *p_buf should hold at least CDIO_CD_FRAMESIZE * i_blocks bytes. + + +*/ +driver_return_code_t +cdio_read_sectors(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + cdio_read_mode_t read_mode, uint32_t i_blocks) +{ + switch(read_mode) { + case CDIO_READ_MODE_AUDIO: + return cdio_read_audio_sectors (p_cdio, p_buf, i_lsn, i_blocks); + case CDIO_READ_MODE_M1F1: + return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); + case CDIO_READ_MODE_M1F2: + return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, true, i_blocks); + case CDIO_READ_MODE_M2F1: + return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); + case CDIO_READ_MODE_M2F2: + return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, true, i_blocks); + } + /* Can't happen. Just to shut up gcc. */ + return DRIVER_OP_ERROR; +} + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/sector.c b/src/libcdio/driver/sector.c new file mode 100644 index 00000000..930b8b21 --- /dev/null +++ b/src/libcdio/driver/sector.c @@ -0,0 +1,270 @@ +/* + Copyright (C) 2004, 2005, 2011 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#include +#include +#include "cdio_assert.h" +#include "portable.h" + +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include + +static const char _rcsid[] = "$Id: sector.c,v 1.5 2005/02/06 04:20:25 rocky Exp $"; + +/*! String of bytes used to identify the beginning of a Mode 1 or + Mode 2 sector. */ +const uint8_t CDIO_SECTOR_SYNC_HEADER[CDIO_CD_SYNC_SIZE] = + {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}; + +/* Variables to hold debugger-helping enumerations */ +enum cdio_cd_enums; +enum m2_sector_enums; + +lba_t +cdio_lba_to_lsn (lba_t lba) +{ + if (CDIO_INVALID_LBA == lba) return CDIO_INVALID_LSN; + return lba - CDIO_PREGAP_SECTORS; +} + +/* + The below is adapted from cdparanoia code which claims it is + straight from the MMC3 spec. +*/ + +void +cdio_lsn_to_msf (lsn_t lsn, msf_t *msf) +{ + int m, s, f; + + cdio_assert (msf != 0); + + if ( lsn >= -CDIO_PREGAP_SECTORS ){ + m = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_MIN; + lsn -= m * CDIO_CD_FRAMES_PER_MIN; + s = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_SEC; + lsn -= s * CDIO_CD_FRAMES_PER_SEC; + f = lsn + CDIO_PREGAP_SECTORS; + } else { + m = (lsn + CDIO_CD_MAX_LSN) / CDIO_CD_FRAMES_PER_MIN; + lsn -= m * (CDIO_CD_FRAMES_PER_MIN); + s = (lsn+CDIO_CD_MAX_LSN) / CDIO_CD_FRAMES_PER_SEC; + lsn -= s * CDIO_CD_FRAMES_PER_SEC; + f = lsn + CDIO_CD_MAX_LSN; + } + + if (m > 99) { + cdio_warn ("number of minutes (%d) truncated to 99.", m); + m = 99; + } + + msf->m = cdio_to_bcd8 (m); + msf->s = cdio_to_bcd8 (s); + msf->f = cdio_to_bcd8 (f); +} + +/*! + Convert an LBA into a string representation of the MSF. + \warning cdio_lba_to_msf_str returns new allocated string */ +char * +cdio_lba_to_msf_str (lba_t lba) +{ + + if (CDIO_INVALID_LBA == lba) { + return strdup("*INVALID"); + } else { + msf_t msf; + msf.m = msf.s = msf.f = 0; + cdio_lba_to_msf (lba, &msf); + return cdio_msf_to_str(&msf); + } +} + +/*! + Convert an LSN into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t +cdio_lsn_to_lba (lsn_t lsn) +{ + if (CDIO_INVALID_LSN == lsn) return CDIO_INVALID_LBA; + return lsn + CDIO_PREGAP_SECTORS; +} + +/*! + Convert an LBA into the corresponding MSF. +*/ +void +cdio_lba_to_msf (lba_t lba, msf_t *msf) +{ + cdio_assert (msf != 0); + cdio_lsn_to_msf(cdio_lba_to_lsn(lba), msf); +} + +/*! + Convert a MSF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t +cdio_msf_to_lba (const msf_t *msf) +{ + uint32_t lba = 0; + + cdio_assert (msf != 0); + + lba = cdio_from_bcd8 (msf->m); + lba *= CDIO_CD_SECS_PER_MIN; + + lba += cdio_from_bcd8 (msf->s); + lba *= CDIO_CD_FRAMES_PER_SEC; + + lba += cdio_from_bcd8 (msf->f); + + return lba; +} + +/*! + Convert a MSF into the corresponding LSN. + CDIO_INVALID_LSN is returned if there is an error. +*/ +lba_t +cdio_msf_to_lsn (const msf_t *msf) +{ + return cdio_lba_to_lsn(cdio_msf_to_lba (msf)); +} + +/*! + Convert an LBA into a string representation of the MSF. + \warning cdio_lba_to_msf_str returns new allocated string */ +char * +cdio_msf_to_str (const msf_t *msf) +{ + char buf[16]; + + snprintf (buf, sizeof (buf), "%2.2x:%2.2x:%2.2x", msf->m, msf->s, msf->f); + return strdup (buf); +} + +/*! + Convert a MSF - broken out as 3 integer components into the + corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t +cdio_msf3_to_lba (unsigned int minutes, unsigned int seconds, + unsigned int frames) +{ + return ((minutes * CDIO_CD_SECS_PER_MIN + seconds) * CDIO_CD_FRAMES_PER_SEC + + frames); +} + +/*! + Convert a string of the form MM:SS:FF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t +cdio_mmssff_to_lba (const char *psz_mmssff) +{ + int psz_field; + lba_t ret; + char c; + + if (0 == strcmp (psz_mmssff, "0")) + return 0; + + c = *psz_mmssff++; + if(c >= '0' && c <= '9') + psz_field = (c - '0'); + else + return CDIO_INVALID_LBA; + while(':' != (c = *psz_mmssff++)) { + if(c >= '0' && c <= '9') + psz_field = psz_field * 10 + (c - '0'); + else + return CDIO_INVALID_LBA; + } + + ret = cdio_msf3_to_lba (psz_field, 0, 0); + + c = *psz_mmssff++; + if(c >= '0' && c <= '9') + psz_field = (c - '0'); + else + return CDIO_INVALID_LBA; + if(':' != (c = *psz_mmssff++)) { + if(c >= '0' && c <= '9') { + psz_field = psz_field * 10 + (c - '0'); + c = *psz_mmssff++; + if(c != ':') + return CDIO_INVALID_LBA; + } + else + return CDIO_INVALID_LBA; + } + + if(psz_field >= CDIO_CD_SECS_PER_MIN) + return CDIO_INVALID_LBA; + + ret += cdio_msf3_to_lba (0, psz_field, 0); + + c = *psz_mmssff++; + if (isdigit(c)) + psz_field = (c - '0'); + else + return -1; + if('\0' != (c = *psz_mmssff++)) { + if (isdigit(c)) { + psz_field = psz_field * 10 + (c - '0'); + c = *psz_mmssff++; + } + else + return CDIO_INVALID_LBA; + } + + if('\0' != c) + return CDIO_INVALID_LBA; + + if(psz_field >= CDIO_CD_FRAMES_PER_SEC) + return CDIO_INVALID_LBA; + + ret += psz_field; + + return ret; +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/driver/track.c b/src/libcdio/driver/track.c new file mode 100644 index 00000000..31fd423f --- /dev/null +++ b/src/libcdio/driver/track.c @@ -0,0 +1,360 @@ +/* + Copyright (C) 2003, 2004, 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 2001 Herbert Valerio Riedel + + 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 3 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, see . +*/ +/*! Track-related routines. */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#include "cdio_private.h" + +const char *track_format2str[6] = + { + "audio", "CD-i", "XA", "data", "PSX", "error" + }; + +/* Variables to hold debugger-helping enumerations */ +enum cdio_track_enums; + +/*! + Return the number of the first track. + CDIO_INVALID_TRACK is returned on error. +*/ +track_t +cdio_get_first_track_num (const CdIo_t *p_cdio) +{ + if (NULL == p_cdio) return CDIO_INVALID_TRACK; + + if (p_cdio->op.get_first_track_num) { + return p_cdio->op.get_first_track_num (p_cdio->env); + } else { + return CDIO_INVALID_TRACK; + } +} + +/*! + Return the last track number. + CDIO_INVALID_TRACK is returned on error. +*/ +track_t +cdio_get_last_track_num (const CdIo_t *p_cdio) +{ + if (NULL == p_cdio) return CDIO_INVALID_TRACK; + { + const track_t i_first_track = cdio_get_first_track_num(p_cdio); + if ( CDIO_INVALID_TRACK != i_first_track ) { + const track_t i_tracks = cdio_get_num_tracks(p_cdio); + if ( CDIO_INVALID_TRACK != i_tracks ) + return i_first_track + i_tracks - 1; + } + return CDIO_INVALID_TRACK; + } +} + +/*! Return number of channels in track: 2 or 4; -2 if not + implemented or -1 for error. + Not meaningful if track is not an audio track. +*/ +int +cdio_get_track_channels(const CdIo_t *p_cdio, track_t i_track) +{ + if (p_cdio->op.get_track_channels) { + return p_cdio->op.get_track_channels (p_cdio->env, i_track); + } else { + return -2; + } +} + +/*! Return copy protection status on a track. Is this meaningful + if not an audio track? +*/ +track_flag_t +cdio_get_track_copy_permit(const CdIo_t *p_cdio, track_t i_track) +{ + if (p_cdio->op.get_track_copy_permit) { + return p_cdio->op.get_track_copy_permit (p_cdio->env, i_track); + } else { + return CDIO_TRACK_FLAG_UNKNOWN; + } +} + +/*! + Get format of track. +*/ +track_format_t +cdio_get_track_format(const CdIo_t *p_cdio, track_t i_track) +{ + if (!p_cdio) return TRACK_FORMAT_ERROR; + + if (p_cdio->op.get_track_format) { + return p_cdio->op.get_track_format (p_cdio->env, i_track); + } else { + return TRACK_FORMAT_ERROR; + } +} +/*! + Return the Joliet level recognized for p_cdio. +*/ +uint8_t +cdio_get_joliet_level(const CdIo_t *p_cdio) +{ + if (!p_cdio) return 0; + { + const generic_img_private_t *p_env + = (generic_img_private_t *) (p_cdio->env); + return p_env->i_joliet_level; + } +} + +/*! + Return the number of tracks in the current medium. + CDIO_INVALID_TRACK is returned on error. +*/ +track_t +cdio_get_num_tracks (const CdIo_t *p_cdio) +{ + if (p_cdio == NULL) return CDIO_INVALID_TRACK; + + if (p_cdio->op.get_num_tracks) { + return p_cdio->op.get_num_tracks (p_cdio->env); + } else { + return CDIO_INVALID_TRACK; + } +} + +/*! Find the track which contans lsn. + CDIO_INVALID_TRACK is returned if the lsn outside of the CD or + if there was some error. + + If the lsn is before the pregap of the first track 0 is returned. + Otherwise we return the track that spans the lsn. +*/ +track_t +cdio_get_track(const CdIo_t *p_cdio, lsn_t lsn) +{ + if (!p_cdio) return CDIO_INVALID_TRACK; + + { + track_t i_low_track = cdio_get_first_track_num(p_cdio); + track_t i_high_track = cdio_get_last_track_num(p_cdio)+1; /* LEADOUT */ + + if (CDIO_INVALID_TRACK == i_low_track + || CDIO_INVALID_TRACK == i_high_track ) return CDIO_INVALID_TRACK; + + if (lsn < cdio_get_track_lsn(p_cdio, i_low_track)) + return 0; /* We're in the pre-gap of first track */ + + if (lsn > cdio_get_track_lsn(p_cdio, i_high_track)) + return CDIO_INVALID_TRACK; /* We're beyond the end. */ + + do { + const track_t i_mid = (i_low_track + i_high_track) / 2; + const lsn_t i_mid_lsn = cdio_get_track_lsn(p_cdio, i_mid); + if (lsn <= i_mid_lsn) i_high_track = i_mid - 1; + if (lsn >= i_mid_lsn) i_low_track = i_mid + 1; + } while ( i_low_track <= i_high_track ); + + return (i_low_track > i_high_track + 1) + ? i_high_track + 1 : i_high_track; + } +} + +/*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? +*/ +bool +cdio_get_track_green(const CdIo_t *p_cdio, track_t i_track) +{ + if (p_cdio == NULL) { + return false; + } + + if (p_cdio->op.get_track_green) { + return p_cdio->op.get_track_green (p_cdio->env, i_track); + } else { + return false; + } +} + +/*! + Return the starting LBA for track number + track_num in cdio. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + CDIO_INVALID_LBA is returned on error. +*/ +lba_t +cdio_get_track_lba(const CdIo_t *p_cdio, track_t i_track) +{ + if (!p_cdio) return CDIO_INVALID_LBA; + + if (p_cdio->op.get_track_lba) { + return p_cdio->op.get_track_lba (p_cdio->env, i_track); + } else { + msf_t msf; + if (p_cdio->op.get_track_msf) + if (cdio_get_track_msf(p_cdio, i_track, &msf)) + return cdio_msf_to_lba(&msf); + return CDIO_INVALID_LBA; + } +} + +/*! + Return the starting LSN for track number + i_track in cdio. Tracks numbers start at 1. + The "leadout" track is specified either by + using i_track LEADOUT_TRACK or the total tracks+1. + CDIO_INVALID_LSN is returned on error. +*/ +lsn_t +cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track) +{ + if (p_cdio == NULL) return CDIO_INVALID_LSN; + + if (p_cdio->op.get_track_lba) { + return cdio_lba_to_lsn(p_cdio->op.get_track_lba (p_cdio->env, i_track)); + } else { + msf_t msf; + if (cdio_get_track_msf(p_cdio, i_track, &msf)) + return cdio_msf_to_lsn(&msf); + return CDIO_INVALID_LSN; + } +} + +/*! + Return the International Standard Recording Code (ISRC) for track number + i_track in p_cdio. Track numbers start at 1. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. +*/ +char * +cdio_get_track_isrc (const CdIo_t *p_cdio, track_t i_track) +{ + if (p_cdio == NULL) return NULL; + + if (p_cdio->op.get_track_isrc) { + return p_cdio->op.get_track_isrc (p_cdio->env, i_track); + } else { + return NULL; + } +} + +/*! + Return the starting LBA for the pregap for track number + i_track in cdio. Track numbers start at 1. + CDIO_INVALID_LBA is returned on error. +*/ +lba_t +cdio_get_track_pregap_lba(const CdIo_t *p_cdio, track_t i_track) +{ + if (p_cdio == NULL) return CDIO_INVALID_LBA; + + if (p_cdio->op.get_track_pregap_lba) { + return p_cdio->op.get_track_pregap_lba (p_cdio->env, i_track); + } else { + return CDIO_INVALID_LBA; + } +} + +/*! + Return the starting LSN for the pregap for track number + i_track in cdio. Track numbers start at 1. + CDIO_INVALID_LSN is returned on error. +*/ +lsn_t +cdio_get_track_pregap_lsn(const CdIo_t *p_cdio, track_t i_track) +{ + return cdio_lba_to_lsn(cdio_get_track_pregap_lba(p_cdio, i_track)); +} + +/*! + Return the ending LSN for track number + i_track in cdio. CDIO_INVALID_LSN is returned on error. +*/ +lsn_t +cdio_get_track_last_lsn(const CdIo_t *p_cdio, track_t i_track) +{ + lsn_t lsn = cdio_get_track_lsn(p_cdio, i_track+1); + + if (CDIO_INVALID_LSN == lsn) return CDIO_INVALID_LSN; + /* Safe, we've always the leadout. */ + return lsn - 1; +} + +/*! + Return the starting MSF (minutes/secs/frames) for track number + i_track in cdio. Track numbers start at 1. + The "leadout" track is specified either by + using i_track LEADOUT_TRACK or the total tracks+1. + False is returned if there is no track entry. +*/ +bool +cdio_get_track_msf(const CdIo_t *p_cdio, track_t i_track, /*out*/ msf_t *msf) +{ + if (!p_cdio) return false; + + if (p_cdio->op.get_track_msf) { + return p_cdio->op.get_track_msf (p_cdio->env, i_track, msf); + } else if (p_cdio->op.get_track_lba) { + lba_t lba = p_cdio->op.get_track_lba (p_cdio->env, i_track); + if (lba == CDIO_INVALID_LBA) return false; + cdio_lba_to_msf(lba, msf); + return true; + } else { + return false; + } +} + +/*! Return copy protection status on a track. Is this meaningful + if not an audio track? +*/ +track_flag_t +cdio_get_track_preemphasis(const CdIo *p_cdio, track_t i_track) +{ + if (p_cdio->op.get_track_preemphasis) { + return p_cdio->op.get_track_preemphasis (p_cdio->env, i_track); + } else { + return CDIO_TRACK_FLAG_UNKNOWN; + } +} + +/*! + Return the number of sectors between this track an the next. This + includes any pregap sectors before the start of the next track. + Tracks start at 1. + 0 is returned if there is an error. +*/ +unsigned int +cdio_get_track_sec_count(const CdIo_t *p_cdio, track_t i_track) +{ + const track_t i_tracks = cdio_get_num_tracks(p_cdio); + + if (i_track >=1 && i_track <= i_tracks) + return ( cdio_get_track_lba(p_cdio, i_track+1) + - cdio_get_track_lba(p_cdio, i_track) ); + return 0; +} diff --git a/src/libcdio/driver/utf8.c b/src/libcdio/driver/utf8.c new file mode 100644 index 00000000..5ae9adc3 --- /dev/null +++ b/src/libcdio/driver/utf8.c @@ -0,0 +1,301 @@ +/* + Copyright (C) 2006, 2008 Burkhard Plaum + Copyright (C) 2011 Rocky Bernstein + Copyright (C) 2012 Pete Batard + + 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 3 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, see . +*/ +/* UTF-8 support */ + +#ifdef HAVE_CONFIG_H +# define __CDIO_CONFIG_H__ 1 +# include "config.h" +#endif + +#ifdef HAVE_JOLIET +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include + +#ifdef HAVE_STDIO_H +#include +#endif + +// TODO: also remove the need for iconv on MinGW +#ifdef HAVE_ICONV +#include +struct cdio_charset_coverter_s + { + iconv_t ic; + }; + +cdio_charset_coverter_t * +cdio_charset_converter_create(const char * src_charset, + const char * dst_charset) + { + cdio_charset_coverter_t * ret; + ret = calloc(1, sizeof(*ret)); + ret->ic = iconv_open(dst_charset, src_charset); + return ret; + } + +#if 0 +static void bgav_hexdump(uint8_t * data, int len, int linebreak) + { + int i; + int bytes_written = 0; + int imax; + + while(bytes_written < len) + { + imax = (bytes_written + linebreak > len) ? len - bytes_written : linebreak; + for(i = 0; i < imax; i++) + fprintf(stderr, "%02x ", data[bytes_written + i]); + for(i = imax; i < linebreak; i++) + fprintf(stderr, " "); + for(i = 0; i < imax; i++) + { + if(!(data[bytes_written + i] & 0x80) && (data[bytes_written + i] >= 32)) + fprintf(stderr, "%c", data[bytes_written + i]); + else + fprintf(stderr, "."); + } + bytes_written += imax; + fprintf(stderr, "\n"); + } + } +#endif + +void cdio_charset_converter_destroy(cdio_charset_coverter_t*cnv) + { + iconv_close(cnv->ic); + free(cnv); + } + +#define BYTES_INCREMENT 16 + +static bool +do_convert(iconv_t cd, char * src, int src_len, + char ** dst, int *dst_len) + { + char * ret; + + char *inbuf; + char *outbuf; + int alloc_size; + int output_pos; + size_t inbytesleft; + size_t outbytesleft; + + if(src_len < 0) + src_len = strlen(src); +#if 0 + fprintf(stderr, "Converting:\n"); + bgav_hexdump(src, src_len, 16); +#endif + alloc_size = src_len + BYTES_INCREMENT; + + inbytesleft = src_len; + + /* We reserve space here to add a final '\0' */ + outbytesleft = alloc_size-1; + + ret = malloc(alloc_size); + + inbuf = src; + outbuf = ret; + + while(1) + { + + if(iconv(cd, (ICONV_CONST char **)&inbuf, &inbytesleft, + &outbuf, &outbytesleft) == (size_t)-1) + { + switch(errno) + { + case E2BIG: + output_pos = (int)(outbuf - ret); + + alloc_size += BYTES_INCREMENT; + outbytesleft += BYTES_INCREMENT; + + ret = realloc(ret, alloc_size); + if (ret == NULL) + { + cdio_warn("Can't realloc(%d).", alloc_size); + return false; + } + outbuf = ret + output_pos; + break; + default: + cdio_warn("Iconv failed: %s", strerror(errno)); + if (ret != NULL) + free(ret); + return false; + break; + } + } + if(!inbytesleft) + break; + } + /* Zero terminate */ + *outbuf = '\0'; + + /* Set return values */ + *dst = ret; + if(dst_len) + *dst_len = (int)(outbuf - ret); +#if 0 + fprintf(stderr, "Conversion done, src:\n"); + bgav_hexdump(src, src_len, 16); + fprintf(stderr, "dst:\n"); + bgav_hexdump((uint8_t*)(ret), (int)(outbuf - ret), 16); +#endif + return true; + } + +bool cdio_charset_convert(cdio_charset_coverter_t*cnv, + char * src, int src_len, + char ** dst, int * dst_len) + { + return do_convert(cnv->ic, src, src_len, dst, dst_len); + } + + + +bool cdio_charset_from_utf8(cdio_utf8_t * src, char ** dst, + int * dst_len, const char * dst_charset) + { + iconv_t ic; + bool result; + ic = iconv_open(dst_charset, "UTF-8"); + result = do_convert(ic, src, -1, dst, dst_len); + iconv_close(ic); + return result; + } + + + + +bool cdio_charset_to_utf8(char *src, size_t src_len, cdio_utf8_t **dst, + const char * src_charset) + { + iconv_t ic; + bool result; + ic = iconv_open("UTF-8", src_charset); + result = do_convert(ic, src, src_len, dst, NULL); + iconv_close(ic); + return result; + } +#elif defined(_WIN32) +#include + +#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \ + WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL) +#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \ + MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size) + +/* + * Converts an UTF-16 string to UTF8 (allocate returned string) + * Returns NULL on error + */ +static __inline char* wchar_to_utf8(const wchar_t* wstr) +{ + int size = 0; + char* str = NULL; + + /* Find out the size we need to allocate for our converted string */ + size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); + if (size <= 1) // An empty string would be size 1 + return NULL; + + if ((str = (char*)calloc(size, 1)) == NULL) + return NULL; + + if (wchar_to_utf8_no_alloc(wstr, str, size) != size) { + free(str); + return NULL; + } + + return str; +} + +/* + * Converts an UTF8 string to UTF-16 (allocate returned string) + * Returns NULL on error + */ +static __inline wchar_t* utf8_to_wchar(const char* str) +{ + int size = 0; + wchar_t* wstr = NULL; + + /* Find out the size we need to allocate for our converted string */ + size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + if (size <= 1) // An empty string would be size 1 + return NULL; + + if ((wstr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL) + return NULL; + + if (utf8_to_wchar_no_alloc(str, wstr, size) != size) { + free(wstr); + return NULL; + } + return wstr; +} + +bool cdio_charset_to_utf8(char *src, size_t src_len, cdio_utf8_t **dst, + const char * src_charset) +{ + wchar_t* le_src; + + if (src == NULL || dst == NULL || src_charset == NULL || strcmp(src_charset, "UCS-2BE") != 0) + return false; + + if (src_len == (size_t)-1) { + for (src_len = 0; ((uint16_t*)src)[src_len] !=0; src_len++); + src_len <<=2; + } + + /* zero lenght is a headache (LCMapString doesn't support it) + => eliminate this case first */ + if (src_len == 0) { + *dst = (cdio_utf8_t*)malloc(1); + *dst[0] = 0; + return true; + } + + le_src = (wchar_t*)malloc(src_len+2); + /* WideCharToMultiByte only takes UCS-2LE, and we are fed UCS-2BE + => perform byte reversal */ + LCMapStringW(0, LCMAP_BYTEREV, (LPCWSTR)src, src_len, le_src, src_len); + *dst = wchar_to_utf8(le_src); + free(le_src); + + return (*dst != NULL); +} +#endif /* HAVE_ICONV */ + +#endif /* HAVE_JOLIET */ diff --git a/src/libcdio/driver/util.c b/src/libcdio/driver/util.c new file mode 100644 index 00000000..d2a295f6 --- /dev/null +++ b/src/libcdio/driver/util.c @@ -0,0 +1,163 @@ +/* + Copyright (C) 2003, 2004, 2005, 2008, 2009, 2010, 2011 + Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include "inttypes.h" +#endif + +#include "cdio_assert.h" +#include +#include +#include + +size_t +_cdio_strlenv(char **str_array) +{ + size_t n = 0; + + cdio_assert (str_array != NULL); + + while(str_array[n]) + n++; + + return n; +} + +void +_cdio_strfreev(char **strv) +{ + int n; + + cdio_assert (strv != NULL); + + for(n = 0; strv[n]; n++) + free(strv[n]); + + free(strv); +} + +char ** +_cdio_strsplit(const char str[], char delim) /* fixme -- non-reentrant */ +{ + int n; + char **strv = NULL; + char *_str, *p; + char _delim[2] = { 0, 0 }; + + cdio_assert (str != NULL); + + _str = strdup(str); + _delim[0] = delim; + + cdio_assert (_str != NULL); + + n = 1; + p = _str; + while(*p) + if (*(p++) == delim) + n++; + + strv = calloc (1, sizeof (char *) * (n+1)); + + n = 0; + while((p = strtok(n ? NULL : _str, _delim)) != NULL) + strv[n++] = strdup(p); + + free(_str); + + return strv; +} + +void * +_cdio_memdup (const void *mem, size_t count) +{ + void *new_mem = NULL; + + if (mem) + { + new_mem = calloc (1, count); + memcpy (new_mem, mem, count); + } + + return new_mem; +} + +char * +_cdio_strdup_upper (const char str[]) +{ + char *new_str = NULL; + + if (str) + { + char *p; + + p = new_str = strdup (str); + + while (*p) + { + *p = toupper (*p); + p++; + } + } + + return new_str; +} + +uint8_t +cdio_to_bcd8 (uint8_t n) +{ + /*cdio_assert (n < 100);*/ + + return ((n/10)<<4) | (n%10); +} + +uint8_t +cdio_from_bcd8(uint8_t p) +{ + return (0xf & p)+(10*(p >> 4)); +} + +const char *cdio_version_string = CDIO_VERSION; +const unsigned int libcdio_version_num = LIBCDIO_VERSION_NUM; + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/iso9660/.msvc/iso9660.vcxproj b/src/libcdio/iso9660/.msvc/iso9660.vcxproj new file mode 100644 index 00000000..512ffd8b --- /dev/null +++ b/src/libcdio/iso9660/.msvc/iso9660.vcxproj @@ -0,0 +1,180 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + {D4E80F35-2604-40AC-B436-97B052ECB572} + Win32Proj + iso9660 + libcdio-iso9660 + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)x86_32\$(Configuration)\ + $(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_32\$(Configuration)\ + $(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_64\$(Configuration)\ + $(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_64\$(Configuration)\ + $(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\ + false + false + false + false + + + + + + Level3 + Disabled + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreadedDebug + ProgramDatabase + + + Windows + true + + + MachineX86 + + + + + Level3 + + + MaxSpeed + true + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreaded + ProgramDatabase + + + MachineX86 + + + + + + + Level3 + Disabled + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreadedDebug + ProgramDatabase + + + Windows + true + + + MachineX64 + + + + + Level3 + + + MaxSpeed + true + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreaded + ProgramDatabase + + + Windows + true + true + true + + + MachineX64 + + + + + + \ No newline at end of file diff --git a/src/libcdio/iso9660/.msvc/iso9660.vcxproj.filters b/src/libcdio/iso9660/.msvc/iso9660.vcxproj.filters new file mode 100644 index 00000000..d49402f2 --- /dev/null +++ b/src/libcdio/iso9660/.msvc/iso9660.vcxproj.filters @@ -0,0 +1,65 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/libcdio/iso9660/.msvc/iso9660_sources b/src/libcdio/iso9660/.msvc/iso9660_sources new file mode 100644 index 00000000..53681832 --- /dev/null +++ b/src/libcdio/iso9660/.msvc/iso9660_sources @@ -0,0 +1,19 @@ +TARGETNAME=iso9660 +TARGETTYPE=LIBRARY + +INCLUDES=$(DDK_INC_PATH);.;..;..\driver;..\..\msvc-missing +LIBCDIO_DEFINES = /DHAVE_CONFIG_H /D_OFF_T_DEFINED /D_off_t=__int64 /Doff_t=_off_t /D_FILE_OFFSET_BITS=64 +C_DEFINES=$(C_DEFINES) $(LIBCDIO_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED + +!IFNDEF MSC_WARNING_LEVEL +MSC_WARNING_LEVEL=/W3 +!ENDIF +USE_MSVCRT=1 + +TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ + $(SDK_LIB_PATH)\user32.lib + +SOURCES=iso9660.c \ + iso9660_fs.c \ + rock.c \ + xa.c \ No newline at end of file diff --git a/src/libcdio/iso9660/Makefile.am b/src/libcdio/iso9660/Makefile.am new file mode 100644 index 00000000..61690208 --- /dev/null +++ b/src/libcdio/iso9660/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libiso9660.a +libiso9660_a_SOURCES = iso9660.c iso9660_fs.c rock.c xa.c +# Boy do you NOT want to have HAVE_CONFIG_H set before $(AM_CFLAGS) with Clang! +libiso9660_a_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -I. -I.. -I../driver diff --git a/src/libcdio/iso9660/Makefile.in b/src/libcdio/iso9660/Makefile.in new file mode 100644 index 00000000..508f00cb --- /dev/null +++ b/src/libcdio/iso9660/Makefile.in @@ -0,0 +1,425 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = src/libcdio/iso9660 +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libiso9660_a_AR = $(AR) $(ARFLAGS) +libiso9660_a_LIBADD = +am_libiso9660_a_OBJECTS = libiso9660_a-iso9660.$(OBJEXT) \ + libiso9660_a-iso9660_fs.$(OBJEXT) libiso9660_a-rock.$(OBJEXT) \ + libiso9660_a-xa.$(OBJEXT) +libiso9660_a_OBJECTS = $(am_libiso9660_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__depfiles_maybe = +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libiso9660_a_SOURCES) +ETAGS = etags +CTAGS = ctags +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_LDFLAGS = @AM_LDFLAGS@ +AM_RCFLAGS = @AM_RCFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EXEEXT = @EXEEXT@ +EXESUFFIX = @EXESUFFIX@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +RM = @RM@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +WINDRES = @WINDRES@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LIBRARIES = libiso9660.a +libiso9660_a_SOURCES = iso9660.c iso9660_fs.c rock.c xa.c +# Boy do you NOT want to have HAVE_CONFIG_H set before $(AM_CFLAGS) with Clang! +libiso9660_a_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -I. -I.. -I../driver +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps src/libcdio/iso9660/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps src/libcdio/iso9660/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libiso9660.a: $(libiso9660_a_OBJECTS) $(libiso9660_a_DEPENDENCIES) + $(AM_V_at)-rm -f libiso9660.a + $(AM_V_AR)$(libiso9660_a_AR) libiso9660.a $(libiso9660_a_OBJECTS) $(libiso9660_a_LIBADD) + $(AM_V_at)$(RANLIB) libiso9660.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC) @AM_BACKSLASH@ + $(COMPILE) -c $< + +.c.obj: + $(AM_V_CC) @AM_BACKSLASH@ + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +libiso9660_a-iso9660.o: iso9660.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-iso9660.o `test -f 'iso9660.c' || echo '$(srcdir)/'`iso9660.c + +libiso9660_a-iso9660.obj: iso9660.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-iso9660.obj `if test -f 'iso9660.c'; then $(CYGPATH_W) 'iso9660.c'; else $(CYGPATH_W) '$(srcdir)/iso9660.c'; fi` + +libiso9660_a-iso9660_fs.o: iso9660_fs.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-iso9660_fs.o `test -f 'iso9660_fs.c' || echo '$(srcdir)/'`iso9660_fs.c + +libiso9660_a-iso9660_fs.obj: iso9660_fs.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-iso9660_fs.obj `if test -f 'iso9660_fs.c'; then $(CYGPATH_W) 'iso9660_fs.c'; else $(CYGPATH_W) '$(srcdir)/iso9660_fs.c'; fi` + +libiso9660_a-rock.o: rock.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-rock.o `test -f 'rock.c' || echo '$(srcdir)/'`rock.c + +libiso9660_a-rock.obj: rock.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-rock.obj `if test -f 'rock.c'; then $(CYGPATH_W) 'rock.c'; else $(CYGPATH_W) '$(srcdir)/rock.c'; fi` + +libiso9660_a-xa.o: xa.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-xa.o `test -f 'xa.c' || echo '$(srcdir)/'`xa.c + +libiso9660_a-xa.obj: xa.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiso9660_a_CFLAGS) $(CFLAGS) -c -o libiso9660_a-xa.obj `if test -f 'xa.c'; then $(CYGPATH_W) 'xa.c'; else $(CYGPATH_W) '$(srcdir)/xa.c'; fi` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcdio/iso9660/iso9660.c b/src/libcdio/iso9660/iso9660.c new file mode 100644 index 00000000..fd589d6d --- /dev/null +++ b/src/libcdio/iso9660/iso9660.c @@ -0,0 +1,1268 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + +/*! String inside frame which identifies an ISO 9660 filesystem. This + string is the "id" field of an iso9660_pvd_t or an iso9660_svd_t. + Note should come *before* #include which does + a #define of this name. +*/ +const char ISO_STANDARD_ID[] = {'C', 'D', '0', '0', '1'}; + +/* Private headers */ +#include "iso9660_private.h" +#include "cdio_assert.h" + +/* Public headers */ +#include +#include +#include + +#include +#include +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifndef HAVE_SETENV +static int +setenv(const char *envname, const char *envval, int overwrite) +{ + return -1; +} +#endif + +#ifndef HAVE_UNSETENV +static int +unsetenv(const char *envname) +{ + return -1; +} +#endif + +#ifndef HAVE_TIMEGM +static time_t +timegm(struct tm *tm) +{ + time_t ret; + char *tz; + + tz = getenv("TZ"); + setenv("TZ", "UTC", 1); + tzset(); + ret = mktime(tm); + if (tz) + setenv("TZ", tz, 1); + else + unsetenv("TZ"); + tzset(); + return ret; +} +#endif + +#ifndef HAVE_GMTIME_R +static struct tm * +gmtime_r(const time_t *timer, struct tm *result) +{ + struct tm *tmp = gmtime(timer); + + if (tmp) { + *result = *tmp; + return result; + } + return tmp; +} +#endif + +#ifndef HAVE_LOCALTIME_R +static struct tm * +localtime_r(const time_t *timer, struct tm *result) +{ + struct tm *tmp = localtime(timer); + + if (tmp) { + *result = *tmp; + return result; + } + return tmp; +} +#endif + +static const char _rcsid[] = "$Id: iso9660.c,v 1.41 2008/06/25 08:01:54 rocky Exp $"; + +/* Variables to hold debugger-helping enumerations */ +enum iso_enum1_s iso_enums1; +enum iso_flag_enum_s iso_flag_enums; +enum iso_vd_enum_s iso_vd_enums; +enum iso_extension_enum_s iso_extension_enums; + +/* some parameters... */ +#define SYSTEM_ID "CD-RTOS CD-BRIDGE" +#define VOLUME_SET_ID "" + +/*! + Change trailing blanks in str to nulls. Str has a maximum size of + n characters. +*/ +static char * +strip_trail (const char str[], size_t n) +{ + static char buf[1025]; + int j; + + cdio_assert (n < 1024); + + strncpy (buf, str, n); + buf[n] = '\0'; + + for (j = strlen (buf) - 1; j >= 0; j--) + { + if (buf[j] != ' ') + break; + + buf[j] = '\0'; + } + + return buf; +} + +static void +pathtable_get_size_and_entries(const void *pt, unsigned int *size, + unsigned int *entries); + +/*! + Get time structure from structure in an ISO 9660 directory index + record. Even though tm_wday and tm_yday fields are not explicitly in + idr_date, the are calculated from the other fields. + + If tm is to reflect the localtime set b_localtime true, otherwise + tm will reported in GMT. +*/ +bool +iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime, + /*out*/ struct tm *p_tm) +{ + if (!idr_date) return false; + + /* + Section 9.1.5 of ECMA 119 says: + If all seven numbers are zero, it shall mean that the date and + time are not specified. + + HACK: However we've seen it happen that everything except gmtoff + is zero and the expected date is the beginning of the epoch. So + we accept 6 numbers being zero. I'm also not sure if using the + beginning of the Epoch is also the right thing to do either. + */ + + if ( 0 == idr_date->dt_year && 0 == idr_date->dt_month && + 0 == idr_date->dt_day && 0 == idr_date->dt_hour && + 0 == idr_date->dt_minute && 0 == idr_date->dt_second ) { + time_t t = 0; + struct tm temp_tm; + localtime_r(&t, &temp_tm); + + memcpy(p_tm, &temp_tm, sizeof(struct tm)); + return true; + } + + memset(p_tm, 0, sizeof(struct tm)); + + p_tm->tm_year = idr_date->dt_year; + p_tm->tm_mon = idr_date->dt_month - 1; + p_tm->tm_mday = idr_date->dt_day; + p_tm->tm_hour = idr_date->dt_hour; + p_tm->tm_min = idr_date->dt_minute; + p_tm->tm_sec = idr_date->dt_second - idr_date->dt_gmtoff * (15 * 60); + p_tm->tm_isdst = -1; /* information not available */ + + /* Recompute tm_wday and tm_yday via mktime. mktime will also renormalize + date values to account for the timezone offset. */ + { + time_t t = 0; + struct tm temp_tm; + + t = timegm(p_tm); + + if (b_localtime) + localtime_r(&t, &temp_tm); + else + gmtime_r(&t, &temp_tm); + + memcpy(p_tm, &temp_tm, sizeof(struct tm)); + } + + + return true; +} + +/* + A note regarding the strange strtol() testing below as pointed out SMS. + From man strtol: + + If an underflow occurs, strtol() returns LONG_MIN. If an overflow + occurs, strtol() returns LONG_MAX. In both cases, errno is set to + ERANGE. + + This implies that one should only look at errno if the value is + LONG_MIN or LONG_MAX. +*/ + +#define set_ltime_field(TM_FIELD, LT_FIELD, ADD_CONSTANT) \ + { \ + char num[10]; long tmp; \ + memcpy(num, p_ldate->LT_FIELD, sizeof(p_ldate->LT_FIELD)); \ + num[sizeof(p_ldate->LT_FIELD)] = '\0'; \ + errno = 0; \ + tmp = strtol(num, \ + (char **)NULL, 10); \ + if ( tmp < INT_MIN || tmp > INT_MAX || \ + ((unsigned long)tmp + ADD_CONSTANT) > INT_MAX || \ + (tmp + ADD_CONSTANT) < INT_MIN ) \ + return false; \ + p_tm->TM_FIELD = tmp + ADD_CONSTANT; \ + } + +/*! + Get "long" time in format used in ISO 9660 primary volume descriptor + from a Unix time structure. +*/ +bool +iso9660_get_ltime (const iso9660_ltime_t *p_ldate, + /*out*/ struct tm *p_tm) +{ + if (!p_tm) return false; + memset(p_tm, 0, sizeof(struct tm)); + set_ltime_field(tm_year, lt_year, -1900); + set_ltime_field(tm_mon, lt_month, -1); + set_ltime_field(tm_mday, lt_day, 0); + set_ltime_field(tm_hour, lt_hour, 0); + set_ltime_field(tm_min, lt_minute, 0); + set_ltime_field(tm_sec, lt_second, 0); + p_tm->tm_isdst= -1; /* information not available */ +#ifndef HAVE_TM_GMTOFF + p_tm->tm_sec += p_ldate->lt_gmtoff * (15 * 60); +#endif + + /* Recompute tm_wday and tm_yday via mktime. mktime will also renormalize + date values to account for the timezone offset. */ + { + time_t t; + struct tm temp_tm; + + t = mktime(p_tm); + + localtime_r(&t, &temp_tm); + + memcpy(p_tm, &temp_tm, sizeof(struct tm)); + } + p_tm->tm_isdst= -1; /* information not available */ +#ifdef HAVE_TM_GMTOFF + p_tm->tm_gmtoff = -p_ldate->lt_gmtoff * (15 * 60); +#endif + return true; +} + +/*! + Set time in format used in ISO 9660 directory index record + from a Unix time structure. timezone is given as an offset + correction in minutes. +*/ +void +iso9660_set_dtime_with_timezone (const struct tm *p_tm, + int time_zone, + /*out*/ iso9660_dtime_t *p_idr_date) +{ + memset (p_idr_date, 0, 7); + + if (!p_tm) return; + + p_idr_date->dt_year = p_tm->tm_year; + p_idr_date->dt_month = p_tm->tm_mon + 1; + p_idr_date->dt_day = p_tm->tm_mday; + p_idr_date->dt_hour = p_tm->tm_hour; + p_idr_date->dt_minute = p_tm->tm_min; + p_idr_date->dt_second = p_tm->tm_sec; + + /* The ISO 9660 timezone is in the range -48..+52 and each unit + represents a 15-minute interval. */ + p_idr_date->dt_gmtoff = time_zone / 15; + + if (p_idr_date->dt_gmtoff < -48 ) { + + cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", + p_idr_date->dt_gmtoff); + p_idr_date->dt_gmtoff = -48; + } else if (p_idr_date->dt_gmtoff > 52) { + cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", + p_idr_date->dt_gmtoff); + p_idr_date->dt_gmtoff = 52; + } +} + +/*! + Set time in format used in ISO 9660 directory index record + from a Unix time structure. */ +void +iso9660_set_dtime (const struct tm *p_tm, /*out*/ iso9660_dtime_t *p_idr_date) +{ + int time_zone; +#ifdef HAVE_TM_GMTOFF + /* Convert seconds to minutes */ + time_zone = p_tm->tm_gmtoff / 60; +#else + time_zone = (p_tm->tm_isdst > 0) ? -60 : 0; +#endif + iso9660_set_dtime_with_timezone (p_tm, time_zone, p_idr_date); +} + +/*! + Set "long" time in format used in ISO 9660 primary volume descriptor + from a Unix time structure. timezone is given as an offset + correction in minutes. +*/ +void +iso9660_set_ltime_with_timezone (const struct tm *p_tm, + int time_zone, + /*out*/ iso9660_ltime_t *pvd_date) +{ + char *_pvd_date = (char *) pvd_date; + + memset (_pvd_date, '0', 16); + pvd_date->lt_gmtoff = (iso712_t) 0; /* Start out with time zone GMT. */ + + if (!p_tm) return; + + snprintf(_pvd_date, 17, + "%4.4d%2.2d%2.2d" "%2.2d%2.2d%2.2d" "%2.2d", + p_tm->tm_year + 1900, p_tm->tm_mon + 1, p_tm->tm_mday, + p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec, + 0 /* 1/100 secs */ ); + + /* Set time zone in 15-minute interval encoding. */ + pvd_date->lt_gmtoff -= (time_zone / 15); + if (pvd_date->lt_gmtoff < -48 ) { + + cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", + (int) pvd_date->lt_gmtoff); + pvd_date->lt_gmtoff = -48; + } else if (pvd_date->lt_gmtoff > 52) { + cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", + (int) pvd_date->lt_gmtoff); + pvd_date->lt_gmtoff = 52; + } +} + +/*! + Set "long" time in format used in ISO 9660 primary volume descriptor + from a Unix time structure. */ +void +iso9660_set_ltime (const struct tm *p_tm, /*out*/ iso9660_ltime_t *pvd_date) +{ + int time_zone; +#ifdef HAVE_TM_GMTOFF + /* Set time zone in 15-minute interval encoding. */ + time_zone = p_tm->tm_gmtoff / 60; +#else + time_zone = (p_tm->tm_isdst > 0) ? -60 : 0; +#endif + iso9660_set_ltime_with_timezone (p_tm, time_zone, pvd_date); +} + +/*! + Convert an ISO-9660 file name which is in the format usually stored + in a ISO 9660 directory entry into what's usually listed as the + file name in a listing. Lowercase name, and remove trailing ;1's + or .;1's and turn the other ;'s into version numbers. + + @param psz_oldname the ISO-9660 filename to be translated. + @param psz_newname returned string. The caller allocates this and + it should be at least the size of psz_oldname. + @return length of the translated string is returned. It will be no greater + than the length of psz_oldname. +*/ +int +iso9660_name_translate(const char *psz_oldname, char *psz_newname) +{ + return iso9660_name_translate_ext(psz_oldname, psz_newname, 0); +} + +/*! + Convert an ISO-9660 file name which is in the format usually stored + in a ISO 9660 directory entry into what's usually listed as the + file name in a listing. Lowercase name if no Joliet Extension + interpretation. Remove trailing ;1's or .;1's and turn the other + ;'s into version numbers. + + @param psz_oldname the ISO-9660 filename to be translated. + @param psz_newname returned string. The caller allocates this and + it should be at least the size of psz_oldname. + @param i_joliet_level 0 if not using Joliet Extension. Otherwise the + Joliet level. + @return length of the translated string is returned. It will be no greater + than the length of psz_oldname. +*/ +int +iso9660_name_translate_ext(const char *psz_oldname, char *psz_newname, + uint8_t i_joliet_level) +{ + int len = strlen(psz_oldname); + int i; + + if (0 == len) return 0; + for (i = 0; i < len; i++) { + unsigned char c = psz_oldname[i]; + if (!c) + break; + + /* Lower case, unless we have Joliet extensions. */ + if (!i_joliet_level && isupper(c)) c = tolower(c); + + /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */ + if (c == '.' && i == len - 3 + && psz_oldname[i + 1] == ';' && psz_oldname[i + 2] == '1') + break; + + /* Drop trailing ';1' */ + if (c == ';' && i == len - 2 && psz_oldname[i + 1] == '1') + break; + + /* Convert remaining ';' to '.' */ + if (c == ';') + c = '.'; + + psz_newname[i] = c; + } + psz_newname[i] = '\0'; + return i; +} + +/*! + Pad string src with spaces to size len and copy this to dst. If + len is less than the length of src, dst will be truncated to the + first len characters of src. + + src can also be scanned to see if it contains only ACHARs, DCHARs, + 7-bit ASCII chars depending on the enumeration _check. + + In addition to getting changed, dst is the return value. + Note: this string might not be NULL terminated. + */ +char * +iso9660_strncpy_pad(char dst[], const char src[], size_t len, + enum strncpy_pad_check _check) +{ + size_t rlen; + + cdio_assert (dst != NULL); + cdio_assert (src != NULL); + cdio_assert (len > 0); + + switch (_check) + { + int idx; + case ISO9660_NOCHECK: + break; + + case ISO9660_7BIT: + for (idx = 0; src[idx]; idx++) + if ((int8_t) src[idx] < 0) + { + cdio_warn ("string '%s' fails 7bit constraint (pos = %d)", + src, idx); + break; + } + break; + + case ISO9660_ACHARS: + for (idx = 0; src[idx]; idx++) + if (!iso9660_is_achar (src[idx])) + { + cdio_warn ("string '%s' fails a-character constraint (pos = %d)", + src, idx); + break; + } + break; + + case ISO9660_DCHARS: + for (idx = 0; src[idx]; idx++) + if (!iso9660_is_dchar (src[idx])) + { + cdio_warn ("string '%s' fails d-character constraint (pos = %d)", + src, idx); + break; + } + break; + + default: + cdio_assert_not_reached (); + break; + } + + rlen = strlen (src); + + if (rlen > len) + cdio_warn ("string '%s' is getting truncated to %d characters", + src, (unsigned int) len); + + strncpy (dst, src, len); + if (rlen < len) + memset(dst+rlen, ' ', len-rlen); + return dst; +} + +/*! + Return true if c is a DCHAR - a valid ISO-9660 level 1 character. + These are the ASCSII capital letters A-Z, the digits 0-9 and an + underscore. +*/ +bool +iso9660_is_dchar (int c) +{ + if (!IN (c, 0x30, 0x5f) + || IN (c, 0x3a, 0x40) + || IN (c, 0x5b, 0x5e)) + return false; + + return true; +} + + +/*! + Return true if c is an ACHAR - + These are the DCHAR's plus some ASCII symbols including the space + symbol. +*/ +bool +iso9660_is_achar (int c) +{ + if (!IN (c, 0x20, 0x5f) + || IN (c, 0x23, 0x24) + || c == 0x40 + || IN (c, 0x5b, 0x5e)) + return false; + + return true; +} + +void +iso9660_set_evd(void *pd) +{ + iso_volume_descriptor_t ied; + + cdio_assert (sizeof(iso_volume_descriptor_t) == ISO_BLOCKSIZE); + + cdio_assert (pd != NULL); + + memset(&ied, 0, sizeof(ied)); + + ied.type = to_711(ISO_VD_END); + iso9660_strncpy_pad (ied.id, ISO_STANDARD_ID, sizeof(ied.id), + ISO9660_DCHARS); + ied.version = to_711(ISO_VERSION); + + memcpy(pd, &ied, sizeof(ied)); +} + +void +iso9660_set_pvd(void *pd, + const char volume_id[], + const char publisher_id[], + const char preparer_id[], + const char application_id[], + uint32_t iso_size, + const void *root_dir, + uint32_t path_table_l_extent, + uint32_t path_table_m_extent, + uint32_t path_table_size, + const time_t *pvd_time + ) +{ + iso9660_pvd_t ipd; + struct tm temp_tm; + + cdio_assert (sizeof(iso9660_pvd_t) == ISO_BLOCKSIZE); + + cdio_assert (pd != NULL); + cdio_assert (volume_id != NULL); + cdio_assert (application_id != NULL); + + memset(&ipd,0,sizeof(ipd)); /* paranoia? */ + + /* magic stuff ... thatis CD XA marker... */ + strncpy(((char*)&ipd)+ISO_XA_MARKER_OFFSET, ISO_XA_MARKER_STRING, + sizeof(ISO_XA_MARKER_STRING)); + + ipd.type = to_711(ISO_VD_PRIMARY); + iso9660_strncpy_pad (ipd.id, ISO_STANDARD_ID, 5, ISO9660_DCHARS); + ipd.version = to_711(ISO_VERSION); + + iso9660_strncpy_pad (ipd.system_id, SYSTEM_ID, 32, ISO9660_ACHARS); + iso9660_strncpy_pad (ipd.volume_id, volume_id, 32, ISO9660_DCHARS); + + ipd.volume_space_size = to_733(iso_size); + + ipd.volume_set_size = to_723(1); + ipd.volume_sequence_number = to_723(1); + ipd.logical_block_size = to_723(ISO_BLOCKSIZE); + + ipd.path_table_size = to_733(path_table_size); + ipd.type_l_path_table = to_731(path_table_l_extent); + ipd.type_m_path_table = to_732(path_table_m_extent); + + /* root_directory_record doesn't contain the 1-byte filename, + so we add one for that. */ + cdio_assert (sizeof(ipd.root_directory_record) == 33); + memcpy(&(ipd.root_directory_record), root_dir, + sizeof(ipd.root_directory_record)); + ipd.root_directory_filename='\0'; + ipd.root_directory_record.length = sizeof(ipd.root_directory_record)+1; + iso9660_strncpy_pad (ipd.volume_set_id, VOLUME_SET_ID, + ISO_MAX_VOLUMESET_ID, ISO9660_DCHARS); + + iso9660_strncpy_pad (ipd.publisher_id, publisher_id, ISO_MAX_PUBLISHER_ID, + ISO9660_ACHARS); + iso9660_strncpy_pad (ipd.preparer_id, preparer_id, ISO_MAX_PREPARER_ID, + ISO9660_ACHARS); + iso9660_strncpy_pad (ipd.application_id, application_id, + ISO_MAX_APPLICATION_ID, ISO9660_ACHARS); + + iso9660_strncpy_pad (ipd.copyright_file_id , "", 37, ISO9660_DCHARS); + iso9660_strncpy_pad (ipd.abstract_file_id , "", 37, ISO9660_DCHARS); + iso9660_strncpy_pad (ipd.bibliographic_file_id, "", 37, ISO9660_DCHARS); + + gmtime_r(pvd_time, &temp_tm); + iso9660_set_ltime (&temp_tm, &(ipd.creation_date)); + gmtime_r(pvd_time, &temp_tm); + iso9660_set_ltime (&temp_tm, &(ipd.modification_date)); + iso9660_set_ltime (&temp_tm, &(ipd.expiration_date)); + iso9660_set_ltime (&temp_tm, &(ipd.effective_date)); + + ipd.file_structure_version = to_711(1); + + /* we leave ipd.application_data = 0 */ + + memcpy(pd, &ipd, sizeof(ipd)); /* copy stuff to arg ptr */ +} + +unsigned int +iso9660_dir_calc_record_size(unsigned int namelen, unsigned int su_len) +{ + unsigned int length; + + length = sizeof(iso9660_dir_t); + length += namelen; + if (length % 2) /* pad to word boundary */ + length++; + length += su_len; + if (length % 2) /* pad to word boundary again */ + length++; + + return length; +} + +void +iso9660_dir_add_entry_su(void *dir, + const char filename[], + uint32_t extent, + uint32_t size, + uint8_t file_flags, + const void *su_data, + unsigned int su_size, + const time_t *entry_time) +{ + iso9660_dir_t *idr = dir; + uint8_t *dir8 = dir; + unsigned int offset = 0; + uint32_t dsize = from_733(idr->size); + int length, su_offset; + struct tm temp_tm; + cdio_assert (sizeof(iso9660_dir_t) == 33); + + if (!dsize && !idr->length) + dsize = ISO_BLOCKSIZE; /* for when dir lacks '.' entry */ + + cdio_assert (dsize > 0 && !(dsize % ISO_BLOCKSIZE)); + cdio_assert (dir != NULL); + cdio_assert (extent > 17); + cdio_assert (filename != NULL); + cdio_assert (strlen(filename) <= MAX_ISOPATHNAME); + + length = sizeof(iso9660_dir_t); + length += strlen(filename); + length = _cdio_ceil2block (length, 2); /* pad to word boundary */ + su_offset = length; + length += su_size; + length = _cdio_ceil2block (length, 2); /* pad to word boundary again */ + + /* find the last entry's end */ + { + unsigned int ofs_last_rec = 0; + + offset = 0; + while (offset < dsize) + { + if (!dir8[offset]) + { + offset++; + continue; + } + + offset += dir8[offset]; + ofs_last_rec = offset; + } + + cdio_assert (offset == dsize); + + offset = ofs_last_rec; + } + + /* be sure we don't cross sectors boundaries */ + offset = _cdio_ofs_add (offset, length, ISO_BLOCKSIZE); + offset -= length; + + cdio_assert (offset + length <= dsize); + + idr = (iso9660_dir_t *) &dir8[offset]; + + cdio_assert (offset+length < dsize); + + memset(idr, 0, length); + + idr->length = to_711(length); + idr->extent = to_733(extent); + idr->size = to_733(size); + + gmtime_r(entry_time, &temp_tm); + iso9660_set_dtime (&temp_tm, &(idr->recording_time)); + + idr->file_flags = to_711(file_flags); + + idr->volume_sequence_number = to_723(1); + + idr->filename.len = to_711(strlen(filename) + ? strlen(filename) : 1); /* working hack! */ + + memcpy(&idr->filename.str[1], filename, from_711(idr->filename.len)); + memcpy(&dir8[offset] + su_offset, su_data, su_size); +} + +void +iso9660_dir_init_new (void *dir, + uint32_t self, + uint32_t ssize, + uint32_t parent, + uint32_t psize, + const time_t *dir_time) +{ + iso9660_dir_init_new_su (dir, self, ssize, NULL, 0, parent, psize, NULL, + 0, dir_time); +} + +void +iso9660_dir_init_new_su (void *dir, + uint32_t self, + uint32_t ssize, + const void *ssu_data, + unsigned int ssu_size, + uint32_t parent, + uint32_t psize, + const void *psu_data, + unsigned int psu_size, + const time_t *dir_time) +{ + cdio_assert (ssize > 0 && !(ssize % ISO_BLOCKSIZE)); + cdio_assert (psize > 0 && !(psize % ISO_BLOCKSIZE)); + cdio_assert (dir != NULL); + + memset (dir, 0, ssize); + + /* "\0" -- working hack due to padding */ + iso9660_dir_add_entry_su (dir, "\0", self, ssize, ISO_DIRECTORY, ssu_data, + ssu_size, dir_time); + + iso9660_dir_add_entry_su (dir, "\1", parent, psize, ISO_DIRECTORY, psu_data, + psu_size, dir_time); +} + +/* Zero's out pathable. Do this first. */ +void +iso9660_pathtable_init (void *pt) +{ + cdio_assert (sizeof (iso_path_table_t) == 8); + + cdio_assert (pt != NULL); + + memset (pt, 0, ISO_BLOCKSIZE); /* fixme */ +} + +/*! + Returns POSIX mode bitstring for a given file. +*/ +mode_t +iso9660_get_posix_filemode(const iso9660_stat_t *p_iso_dirent) +{ + mode_t mode = 0; + +#ifdef HAVE_ROCK + if (yep == p_iso_dirent->rr.b3_rock) { + return iso9660_get_posix_filemode_from_rock(&p_iso_dirent->rr); + } else +#endif + if (p_iso_dirent->b_xa) { + return iso9660_get_posix_filemode_from_xa(p_iso_dirent->xa.attributes); + } + return mode; +} + +static const iso_path_table_t * +pathtable_get_entry (const void *pt, unsigned int entrynum) +{ + const uint8_t *tmp = pt; + unsigned int offset = 0; + unsigned int count = 0; + + cdio_assert (pt != NULL); + + while (from_711 (*tmp)) + { + if (count == entrynum) + break; + + cdio_assert (count < entrynum); + + offset += sizeof (iso_path_table_t); + offset += from_711 (*tmp); + if (offset % 2) + offset++; + tmp = (uint8_t *)pt + offset; + count++; + } + + if (!from_711 (*tmp)) + return NULL; + + return (const void *) tmp; +} + +void +pathtable_get_size_and_entries (const void *pt, + unsigned int *size, + unsigned int *entries) +{ + const uint8_t *tmp = pt; + unsigned int offset = 0; + unsigned int count = 0; + + cdio_assert (pt != NULL); + + while (from_711 (*tmp)) + { + offset += sizeof (iso_path_table_t); + offset += from_711 (*tmp); + if (offset % 2) + offset++; + tmp = (uint8_t *)pt + offset; + count++; + } + + if (size) + *size = offset; + + if (entries) + *entries = count; +} + +unsigned int +iso9660_pathtable_get_size (const void *pt) +{ + unsigned int size = 0; + pathtable_get_size_and_entries (pt, &size, NULL); + return size; +} + +uint16_t +iso9660_pathtable_l_add_entry (void *pt, + const char name[], + uint32_t extent, + uint16_t parent) +{ + iso_path_table_t *ipt = + (iso_path_table_t *)((char *)pt + iso9660_pathtable_get_size (pt)); + size_t name_len = strlen (name) ? strlen (name) : 1; + unsigned int entrynum = 0; + + cdio_assert (iso9660_pathtable_get_size (pt) < ISO_BLOCKSIZE); /*fixme */ + + memset (ipt, 0, sizeof (iso_path_table_t) + name_len); /* paranoia */ + + ipt->name_len = to_711 (name_len); + ipt->extent = to_731 (extent); + ipt->parent = to_721 (parent); + memcpy (ipt->name, name, name_len); + + pathtable_get_size_and_entries (pt, NULL, &entrynum); + + if (entrynum > 1) + { + const iso_path_table_t *ipt2 + = pathtable_get_entry (pt, entrynum - 2); + + cdio_assert (ipt2 != NULL); + + cdio_assert (from_721 (ipt2->parent) <= parent); + } + + return entrynum; +} + +uint16_t +iso9660_pathtable_m_add_entry (void *pt, + const char name[], + uint32_t extent, + uint16_t parent) +{ + iso_path_table_t *ipt = + (iso_path_table_t *)((char *)pt + iso9660_pathtable_get_size (pt)); + size_t name_len = strlen (name) ? strlen (name) : 1; + unsigned int entrynum = 0; + + cdio_assert (iso9660_pathtable_get_size(pt) < ISO_BLOCKSIZE); /* fixme */ + + memset(ipt, 0, sizeof (iso_path_table_t) + name_len); /* paranoia */ + + ipt->name_len = to_711 (name_len); + ipt->extent = to_732 (extent); + ipt->parent = to_722 (parent); + memcpy (ipt->name, name, name_len); + + pathtable_get_size_and_entries (pt, NULL, &entrynum); + + if (entrynum > 1) + { + const iso_path_table_t *ipt2 + = pathtable_get_entry (pt, entrynum - 2); + + cdio_assert (ipt2 != NULL); + + cdio_assert (from_722 (ipt2->parent) <= parent); + } + + return entrynum; +} + +/*! + Check that pathname is a valid ISO-9660 directory name. + + A valid directory name should not start out with a slash (/), + dot (.) or null byte, should be less than 37 characters long, + have no more than 8 characters in a directory component + which is separated by a /, and consist of only DCHARs. + */ +bool +iso9660_dirname_valid_p (const char pathname[]) +{ + const char *p = pathname; + int len; + + cdio_assert (pathname != NULL); + + if (*p == '/' || *p == '.' || *p == '\0') + return false; + + if (strlen (pathname) > MAX_ISOPATHNAME) + return false; + + len = 0; + for (; *p; p++) + if (iso9660_is_dchar (*p)) + { + len++; + if (len > 8) + return false; + } + else if (*p == '/') + { + if (!len) + return false; + len = 0; + } + else + return false; /* unexpected char */ + + if (!len) + return false; /* last char may not be '/' */ + + return true; +} + +/*! + Check that pathname is a valid ISO-9660 pathname. + + A valid pathname contains a valid directory name, if one appears and + the filename portion should be no more than 8 characters for the + file prefix and 3 characters in the extension (or portion after a + dot). There should be exactly one dot somewhere in the filename + portion and the filename should be composed of only DCHARs. + + True is returned if pathname is valid. + */ +bool +iso9660_pathname_valid_p (const char pathname[]) +{ + const char *p = NULL; + + cdio_assert (pathname != NULL); + + if ((p = strrchr (pathname, '/'))) + { + bool rc; + char *_tmp = strdup (pathname); + + *strrchr (_tmp, '/') = '\0'; + + rc = iso9660_dirname_valid_p (_tmp); + + free (_tmp); + + if (!rc) + return false; + + p++; + } + else + p = pathname; + + if (strlen (pathname) > (MAX_ISOPATHNAME - 6)) + return false; + + { + int len = 0; + int dots = 0; + + for (; *p; p++) + if (iso9660_is_dchar (*p)) + { + len++; + if (dots == 0 ? len > 8 : len > 3) + return false; + } + else if (*p == '.') + { + dots++; + if (dots > 1) + return false; + if (!len) + return false; + len = 0; + } + else + return false; + + if (dots != 1) + return false; + } + + return true; +} + +/*! + Take pathname and a version number and turn that into a ISO-9660 + pathname. (That's just the pathname followd by ";" and the version + number. For example, mydir/file.ext -> mydir/file.ext;1 for version + 1. The resulting ISO-9660 pathname is returned. +*/ +char * +iso9660_pathname_isofy (const char pathname[], uint16_t version) +{ + char tmpbuf[1024] = { 0, }; + + cdio_assert (strlen (pathname) < (sizeof (tmpbuf) - sizeof (";65535"))); + + snprintf (tmpbuf, sizeof(tmpbuf), "%s;%d", pathname, version); + + return strdup (tmpbuf); +} + +/*! + Return the PVD's application ID. + NULL is returned if there is some problem in getting this. +*/ +char * +iso9660_get_application_id(iso9660_pvd_t *p_pvd) +{ + if (NULL==p_pvd) return NULL; + return strdup(strip_trail(p_pvd->application_id, ISO_MAX_APPLICATION_ID)); +} + +#ifdef FIXME +lsn_t +iso9660_get_dir_extent(const iso9660_dir_t *idr) +{ + if (NULL == idr) return 0; + return from_733(idr->extent); +} +#endif + +uint8_t +iso9660_get_dir_len(const iso9660_dir_t *idr) +{ + if (NULL == idr) return 0; + return idr->length; +} + +#ifdef FIXME +uint8_t +iso9660_get_dir_size(const iso9660_dir_t *idr) +{ + if (NULL == idr) return 0; + return from_733(idr->size); +} +#endif + +uint8_t +iso9660_get_pvd_type(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return 255; + return(pvd->type); +} + +const char * +iso9660_get_pvd_id(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return "ERR"; + return(pvd->id); +} + +int +iso9660_get_pvd_space_size(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return 0; + return from_733(pvd->volume_space_size); +} + +int +iso9660_get_pvd_block_size(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return 0; + return from_723(pvd->logical_block_size); +} + +/*! Return the primary volume id version number (of pvd). + If there is an error 0 is returned. + */ +int +iso9660_get_pvd_version(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return 0; + return pvd->version; +} + +/*! Return the LSN of the root directory for pvd. + If there is an error CDIO_INVALID_LSN is returned. + */ +lsn_t +iso9660_get_root_lsn(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) + return CDIO_INVALID_LSN; + else { + const iso9660_dir_t *idr = &(pvd->root_directory_record); + if (NULL == idr) return CDIO_INVALID_LSN; + return(from_733 (idr->extent)); + } +} + +/*! + Return a string containing the preparer id with trailing + blanks removed. +*/ +char * +iso9660_get_preparer_id(const iso9660_pvd_t *pvd) +{ + if (NULL==pvd) return NULL; + return strdup(strip_trail(pvd->preparer_id, ISO_MAX_PREPARER_ID)); +} + +/*! + Return a string containing the publisher id with trailing + blanks removed. +*/ +char * +iso9660_get_publisher_id(const iso9660_pvd_t *pvd) +{ + if (NULL==pvd) return NULL; + return strdup(strip_trail(pvd->publisher_id, ISO_MAX_PUBLISHER_ID)); +} + +/*! + Return a string containing the PVD's system id with trailing + blanks removed. +*/ +char * +iso9660_get_system_id(const iso9660_pvd_t *pvd) +{ + if (NULL==pvd) return NULL; + return strdup(strip_trail(pvd->system_id, ISO_MAX_SYSTEM_ID)); +} + +/*! + Return the PVD's volume ID. +*/ +char * +iso9660_get_volume_id(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return NULL; + return strdup(strip_trail(pvd->volume_id, ISO_MAX_VOLUME_ID)); +} + +/*! + Return the PVD's volumeset ID. + NULL is returned if there is some problem in getting this. +*/ +char * +iso9660_get_volumeset_id(const iso9660_pvd_t *pvd) +{ + if ( NULL == pvd ) return NULL; + return strdup(strip_trail(pvd->volume_set_id, ISO_MAX_VOLUMESET_ID)); +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/iso9660/iso9660_fs.c b/src/libcdio/iso9660/iso9660_fs.c new file mode 100644 index 00000000..cf7c2577 --- /dev/null +++ b/src/libcdio/iso9660/iso9660_fs.c @@ -0,0 +1,1541 @@ +/* + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011 + Rocky Bernstein + Copyright (C) 2001 Herbert Valerio Riedel + + 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 3 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, see . +*/ +/* iso9660 filesystem-based routines */ + +#if defined(HAVE_CONFIG_H) && !defined(__CDIO_CONFIG_H__) +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_ERRNO_H +# include +#endif + +#ifdef HAVE_LANGINFO_CODESET +#include +#endif + +#include +#include +#include +#include +#include + +/* Private headers */ +#include "cdio_assert.h" +#include "_cdio_stdio.h" +#include "cdio_private.h" + +#include + +static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.47 2008/04/18 16:02:09 karl Exp $"; + +/* Implementation of iso9660_t type */ +struct _iso9660_s { + CdioDataSource_t *stream; /* Stream pointer */ + bool_3way_t b_xa; /* true if has XA attributes. */ + bool_3way_t b_mode2; /* true if has mode 2, false for mode 1. */ + uint8_t i_joliet_level; /* 0 = no Joliet extensions. + 1-3: Joliet level. */ + iso9660_pvd_t pvd; + iso9660_svd_t svd; + iso_extension_mask_t iso_extension_mask; /* What extensions we + tolerate. */ + uint32_t i_datastart; /* Usually 0 when i_framesize is ISO_BLOCKSIZE. + This is the normal condition. But in a fuzzy + read we may be reading a CD-image + and not a true ISO 9660 image this might be + CDIO_CD_SYNC_SIZE + */ + uint32_t i_framesize; /* Usually ISO_BLOCKSIZE (2048), but in a + fuzzy read, we may be reading a CD-image + and not a true ISO 9660 image this might + be CDIO_CD_FRAMESIZE_RAW (2352) or + M2RAW_SECTOR_SIZE (2336). + */ + int i_fuzzy_offset; /* Adjustment in bytes to make ISO_STANDARD_ID + ("CD001") come out as ISO_PVD_SECTOR + (frame 16). Normally this should be 0 + for an ISO 9660 image, but if one is + say reading a BIN/CUE or cdrdao BIN/TOC + without having the CUE or TOC and + trying to extract an ISO-9660 + filesystem inside that it may be + different. + */ +}; + +static long int iso9660_seek_read_framesize (const iso9660_t *p_iso, + void *ptr, lsn_t start, + long int size, + uint16_t i_framesize); + +/* Adjust the p_iso's i_datastart, i_byte_offset and i_framesize + based on whether we find a frame header or not. +*/ +static void +adjust_fuzzy_pvd( iso9660_t *p_iso ) +{ + long int i_byte_offset; + + if (!p_iso) return; + + i_byte_offset = (ISO_PVD_SECTOR * p_iso->i_framesize) + + p_iso->i_fuzzy_offset + p_iso->i_datastart; + + /* If we have a raw 2352-byte frame then we should expect to see a sync + frame and a header. + */ + if (CDIO_CD_FRAMESIZE_RAW == p_iso->i_framesize) { + char buf[CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE]; + + i_byte_offset -= CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; + + if ( DRIVER_OP_SUCCESS != cdio_stream_seek (p_iso->stream, i_byte_offset, + SEEK_SET) ) + return; + if (sizeof(buf) == cdio_stream_read (p_iso->stream, buf, sizeof(buf), 1)) { + /* Does the sector frame header suggest Mode 1 format? */ + if (!memcmp(CDIO_SECTOR_SYNC_HEADER, buf+CDIO_CD_SUBHEADER_SIZE, + CDIO_CD_SYNC_SIZE)) { + if (buf[14+CDIO_CD_SUBHEADER_SIZE] != 0x16) { + cdio_warn ("Expecting the PVD sector header MSF to be 0x16, is: %x", + buf[14]); + } + if (buf[15+CDIO_CD_SUBHEADER_SIZE] != 0x1) { + cdio_warn ("Expecting the PVD sector mode to be Mode 1 is: %x", + buf[15]); + } + p_iso->b_mode2 = nope; + p_iso->b_xa = nope; + } else if (!memcmp(CDIO_SECTOR_SYNC_HEADER, buf, CDIO_CD_SYNC_SIZE)) { + /* Frame header indicates Mode 2 Form 1*/ + if (buf[14] != 0x16) { + cdio_warn ("Expecting the PVD sector header MSF to be 0x16, is: %x", + buf[14]); + } + if (buf[15] != 0x2) { + cdio_warn ("Expecting the PVD sector mode to be Mode 2 is: %x", + buf[15]); + } + p_iso->b_mode2 = yep; + /* Do do: check Mode 2 Form 2? */ + } else { + /* Has no frame header */ + p_iso->i_framesize = M2RAW_SECTOR_SIZE; + p_iso->i_fuzzy_offset = (CDIO_CD_FRAMESIZE_RAW - M2RAW_SECTOR_SIZE) + * ISO_PVD_SECTOR + p_iso->i_fuzzy_offset + p_iso->i_datastart; + p_iso->i_datastart = 0; + } + } + } + + +} + +/*! + Open an ISO 9660 image for reading in either fuzzy mode or not. +*/ +static iso9660_t * +iso9660_open_ext_private (const char *psz_path, + iso_extension_mask_t iso_extension_mask, + uint16_t i_fuzz, bool b_fuzzy) +{ + iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(iso9660_t)) ; + bool b_have_superblock; + + if (!p_iso) return NULL; + + p_iso->stream = cdio_stdio_new( psz_path ); + if (NULL == p_iso->stream) + goto error; + + p_iso->i_framesize = ISO_BLOCKSIZE; + + b_have_superblock = (b_fuzzy) + ? iso9660_ifs_fuzzy_read_superblock(p_iso, iso_extension_mask, i_fuzz) + : iso9660_ifs_read_superblock(p_iso, iso_extension_mask) ; + + if ( ! b_have_superblock ) goto error; + + /* Determine if image has XA attributes. */ + + p_iso->b_xa = strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET, + ISO_XA_MARKER_STRING, + sizeof (ISO_XA_MARKER_STRING)) + ? nope : yep; + + p_iso->iso_extension_mask = iso_extension_mask; + return p_iso; + + error: + if (p_iso && p_iso->stream) cdio_stdio_destroy(p_iso->stream); + free(p_iso); + + return NULL; +} + +/*! + Open an ISO 9660 image for reading. Maybe in the future we will have + a mode. NULL is returned on error. +*/ +iso9660_t * +iso9660_open (const char *psz_path /*, mode*/) +{ + return iso9660_open_ext(psz_path, ISO_EXTENSION_NONE); +} + +/*! + Open an ISO 9660 image for reading. Maybe in the future we will have + a mode. NULL is returned on error. +*/ +iso9660_t * +iso9660_open_ext (const char *psz_path, + iso_extension_mask_t iso_extension_mask) +{ + return iso9660_open_ext_private(psz_path, iso_extension_mask, 0, false); +} + + +/*! + Open an ISO 9660 image for reading. Maybe in the future we will have + a mode. NULL is returned on error. +*/ +iso9660_t * +iso9660_open_fuzzy (const char *psz_path, uint16_t i_fuzz /*, mode*/) +{ + return iso9660_open_fuzzy_ext(psz_path, ISO_EXTENSION_NONE, i_fuzz); +} + +/*! + Open an ISO 9660 image for reading. Maybe in the future we will have + a mode. NULL is returned on error. +*/ +iso9660_t * +iso9660_open_fuzzy_ext (const char *psz_path, + iso_extension_mask_t iso_extension_mask, + uint16_t i_fuzz) +{ + return iso9660_open_ext_private(psz_path, iso_extension_mask, i_fuzz, + true); +} + +/*! + Close previously opened ISO 9660 image. + True is unconditionally returned. If there was an error false would + be returned. +*/ +bool +iso9660_close (iso9660_t *p_iso) +{ + if (NULL != p_iso) { + cdio_stdio_destroy(p_iso->stream); + free(p_iso); + } + return true; +} + +static bool +check_pvd (const iso9660_pvd_t *p_pvd, cdio_log_level_t log_level) +{ + if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) { + cdio_log (log_level, "unexpected PVD type %d", p_pvd->type); + return false; + } + + if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID))) + { + cdio_log (log_level, "unexpected ID encountered (expected `" + ISO_STANDARD_ID "', got `%.5s'", p_pvd->id); + return false; + } + return true; +} + +/*! + Return the application ID. NULL is returned in psz_app_id if there + is some problem in getting this. +*/ +bool +iso9660_ifs_get_application_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_app_id) +{ + if (!p_iso) { + *p_psz_app_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( cdio_charset_to_utf8(p_iso->svd.application_id, + ISO_MAX_APPLICATION_ID, + p_psz_app_id, "UCS-2BE")) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_app_id = iso9660_get_application_id( &(p_iso->pvd) ); + return *p_psz_app_id != NULL && strlen(*p_psz_app_id); +} + +/*! + Return the Joliet level recognaized for p_iso. +*/ +uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso) +{ + if (!p_iso) return 0; + return p_iso->i_joliet_level; +} + +/*! + Return a string containing the preparer id with trailing + blanks removed. +*/ +bool +iso9660_ifs_get_preparer_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_preparer_id) +{ + if (!p_iso) { + *p_psz_preparer_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( cdio_charset_to_utf8(p_iso->svd.preparer_id, ISO_MAX_PREPARER_ID, + p_psz_preparer_id, "UCS-2BE") ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_preparer_id = iso9660_get_preparer_id( &(p_iso->pvd) ); + return *p_psz_preparer_id != NULL && strlen(*p_psz_preparer_id); +} + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_publisher_id) +{ + if (!p_iso) { + *p_psz_publisher_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if( cdio_charset_to_utf8(p_iso->svd.publisher_id, ISO_MAX_PUBLISHER_ID, + p_psz_publisher_id, "UCS-2BE") ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_publisher_id = iso9660_get_publisher_id( &(p_iso->pvd) ); + return *p_psz_publisher_id != NULL && strlen(*p_psz_publisher_id); +} + + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_system_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_system_id) +{ + if (!p_iso) { + *p_psz_system_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( cdio_charset_to_utf8(p_iso->svd.system_id, ISO_MAX_SYSTEM_ID, + p_psz_system_id, "UCS-2BE") ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_system_id = iso9660_get_system_id( &(p_iso->pvd) ); + return *p_psz_system_id != NULL && strlen(*p_psz_system_id); +} + + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_volume_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_volume_id) +{ + if (!p_iso) { + *p_psz_volume_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( cdio_charset_to_utf8(p_iso->svd.volume_id, ISO_MAX_VOLUME_ID, + p_psz_volume_id, "UCS-2BE") ) + return true; + } +#endif /* HAVE_JOLIET */ + *p_psz_volume_id = iso9660_get_volume_id( &(p_iso->pvd) ); + return *p_psz_volume_id != NULL && strlen(*p_psz_volume_id); +} + + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso, + /*out*/ cdio_utf8_t **p_psz_volumeset_id) +{ + if (!p_iso) { + *p_psz_volumeset_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( cdio_charset_to_utf8(p_iso->svd.volume_set_id, + ISO_MAX_VOLUMESET_ID, + p_psz_volumeset_id, + "UCS-2BE") ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_volumeset_id = iso9660_get_volumeset_id( &(p_iso->pvd) ); + return *p_psz_volumeset_id != NULL && strlen(*p_psz_volumeset_id); +} + + +/*! + Read the Primary Volume Descriptor for an ISO 9660 image. + True is returned if read, and false if there was an error. +*/ +static bool +iso9660_ifs_read_pvd_loglevel (const iso9660_t *p_iso, + /*out*/ iso9660_pvd_t *p_pvd, + cdio_log_level_t log_level) +{ + if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) { + cdio_log ( log_level, "error reading PVD sector (%d)", ISO_PVD_SECTOR ); + return false; + } + return check_pvd(p_pvd, log_level); +} + +/*! + Read the Primary Volume Descriptor for an ISO 9660 image. + True is returned if read, and false if there was an error. +*/ +bool +iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd) +{ + return iso9660_ifs_read_pvd_loglevel(p_iso, p_pvd, CDIO_LOG_WARN); +} + + +/*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. +*/ +bool +iso9660_ifs_read_superblock (iso9660_t *p_iso, + iso_extension_mask_t iso_extension_mask) +{ + iso9660_svd_t *p_svd; /* Secondary volume descriptor. */ + + if (!p_iso || !iso9660_ifs_read_pvd(p_iso, &(p_iso->pvd))) + return false; + + p_svd = &(p_iso->svd); + p_iso->i_joliet_level = 0; + + if (0 != iso9660_iso_seek_read (p_iso, p_svd, ISO_PVD_SECTOR+1, 1)) { + if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { + if (p_svd->escape_sequences[0] == 0x25 + && p_svd->escape_sequences[1] == 0x2f) { + switch (p_svd->escape_sequences[2]) { + case 0x40: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) + p_iso->i_joliet_level = 1; + break; + case 0x43: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) + p_iso->i_joliet_level = 2; + break; + case 0x45: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) + p_iso->i_joliet_level = 3; + break; + default: + cdio_info("Supplementary Volume Descriptor found, but not Joliet"); + } + if (p_iso->i_joliet_level > 0) { + cdio_info("Found Extension: Joliet Level %d", p_iso->i_joliet_level); + } + } + } + } + + return true; +} + +/*! + Read the Super block of an ISO 9660 image but determine framesize + and datastart and a possible additional offset. Generally here we are + not reading an ISO 9660 image but a CD-Image which contains an ISO 9660 + filesystem. +*/ +bool +iso9660_ifs_fuzzy_read_superblock (iso9660_t *p_iso, + iso_extension_mask_t iso_extension_mask, + uint16_t i_fuzz) +{ + /* Got some work to do to find ISO_STANDARD_ID ("CD001") */ + unsigned int i; + + for (i=0; ii_framesize = framesizes[k]; + p_iso->i_datastart = (ISO_BLOCKSIZE == framesizes[k]) ? + 0 : CDIO_CD_SYNC_SIZE; + p_iso->i_fuzzy_offset = 0; + if (0 == iso9660_seek_read_framesize (p_iso, frame, lsn, 1, + p_iso->i_framesize)) { + return false; + } + + q = memchr(frame, 'C', p_iso->i_framesize); + for ( p=q; p && p < frame + p_iso->i_framesize ; p=q+1 ) { + q = memchr(p, 'C', p_iso->i_framesize - (p - frame)); + if ( !q || (pvd = strstr(q, ISO_STANDARD_ID)) ) + break; + } + + if (pvd) { + /* Yay! Found something */ + p_iso->i_fuzzy_offset = (pvd - frame - 1) - + ((ISO_PVD_SECTOR-lsn)*p_iso->i_framesize) ; + /* But is it *really* a PVD? */ + if ( iso9660_ifs_read_pvd_loglevel(p_iso, &(p_iso->pvd), + CDIO_LOG_DEBUG) ) { + adjust_fuzzy_pvd(p_iso); + return true; + } + + } + } + } + } + return false; +} + + +/*! + Read the Primary Volume Descriptor for of CD. +*/ +bool +iso9660_fs_read_pvd(const CdIo_t *p_cdio, /*out*/ iso9660_pvd_t *p_pvd) +{ + /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + driver_return_code_t driver_return = + cdio_read_data_sectors (p_cdio, buf, ISO_PVD_SECTOR, ISO_BLOCKSIZE, 1); + + if (DRIVER_OP_SUCCESS != driver_return) { + cdio_warn ("error reading PVD sector (%d) error %d", ISO_PVD_SECTOR, + driver_return); + return false; + } + + /* The size of a PVD or SVD is smaller than a sector. So we + allocated a bigger block above (buf) and now we'll copy just + the part we need to save. + */ + cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t)); + memcpy(p_pvd, buf, sizeof(iso9660_pvd_t)); + + return check_pvd(p_pvd, CDIO_LOG_WARN); +} + + +/*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. +*/ +bool +iso9660_fs_read_superblock (CdIo_t *p_cdio, + iso_extension_mask_t iso_extension_mask) +{ + if (!p_cdio) return false; + + { + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; + iso9660_pvd_t *p_pvd = &(p_env->pvd); + iso9660_svd_t *p_svd = &(p_env->svd); + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + driver_return_code_t driver_return; + + if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) ) + return false; + + p_env->i_joliet_level = 0; + + driver_return = + cdio_read_data_sectors ( p_cdio, buf, ISO_PVD_SECTOR+1, ISO_BLOCKSIZE, + 1 ); + + if (DRIVER_OP_SUCCESS == driver_return) { + /* The size of a PVD or SVD is smaller than a sector. So we + allocated a bigger block above (buf) and now we'll copy just + the part we need to save. + */ + cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t)); + memcpy(p_svd, buf, sizeof(iso9660_svd_t)); + + if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { + if (p_svd->escape_sequences[0] == 0x25 + && p_svd->escape_sequences[1] == 0x2f) { + switch (p_svd->escape_sequences[2]) { + case 0x40: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) + p_env->i_joliet_level = 1; + break; + case 0x43: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) + p_env->i_joliet_level = 2; + break; + case 0x45: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) + p_env->i_joliet_level = 3; + break; + default: + cdio_info("Supplementary Volume Descriptor found, but not Joliet"); + } + if (p_env->i_joliet_level > 0) { + cdio_info("Found Extension: Joliet Level %d", + p_env->i_joliet_level); + } + } + } + } + } + + return true; +} + +/*! + Seek to a position and then read n blocks. Size read is returned. +*/ +static long int +iso9660_seek_read_framesize (const iso9660_t *p_iso, void *ptr, + lsn_t start, long int size, + uint16_t i_framesize) +{ + long int ret; + long int i_byte_offset; + + if (!p_iso) return 0; + i_byte_offset = (start * p_iso->i_framesize) + p_iso->i_fuzzy_offset + + p_iso->i_datastart; + + ret = cdio_stream_seek (p_iso->stream, i_byte_offset, SEEK_SET); + if (ret!=0) return 0; + return cdio_stream_read (p_iso->stream, ptr, i_framesize, size); +} + +/*! + Seek to a position and then read n blocks. Size read is returned. +*/ +long int +iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start, + long int size) +{ + return iso9660_seek_read_framesize(p_iso, ptr, start, size, ISO_BLOCKSIZE); +} + + + +static iso9660_stat_t * +_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, + uint8_t i_joliet_level) +{ + uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); + iso711_t i_fname; + unsigned int stat_len; + iso9660_stat_t *p_stat; + + if (!dir_len) return NULL; + + i_fname = from_711(p_iso9660_dir->filename.len); + + /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */ + stat_len = sizeof(iso9660_stat_t)+i_fname+2; + + p_stat = calloc(1, stat_len); + if (!p_stat) + { + cdio_warn("Couldn't calloc(1, %d)", stat_len); + return NULL; + } + p_stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) + ? _STAT_DIR : _STAT_FILE; + p_stat->lsn = from_733 (p_iso9660_dir->extent); + p_stat->size = from_733 (p_iso9660_dir->size); + p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE); + p_stat->rr.b3_rock = dunno; /*FIXME should do based on mask */ + p_stat->b_xa = false; + + { + char rr_fname[256] = ""; + + int i_rr_fname = +#ifdef HAVE_ROCK + get_rock_ridge_filename(p_iso9660_dir, rr_fname, p_stat); +#else + 0; +#endif + + if (i_rr_fname > 0) { + if (i_rr_fname > i_fname) { + /* realloc gives valgrind errors */ + iso9660_stat_t *p_stat_new = + calloc(1, sizeof(iso9660_stat_t)+i_rr_fname+2); + if (!p_stat_new) + { + cdio_warn("Couldn't calloc(1, %d)", (int)(sizeof(iso9660_stat_t)+i_rr_fname+2)); + return NULL; + } + memcpy(p_stat_new, p_stat, stat_len); + free(p_stat); + p_stat = p_stat_new; + } + strncpy(p_stat->filename, rr_fname, i_rr_fname+1); + } else { + if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname) + strncpy (p_stat->filename, ".", sizeof(".")); + else if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname) + strncpy (p_stat->filename, "..", sizeof("..")); +#ifdef HAVE_JOLIET + else if (i_joliet_level) { + int i_inlen = i_fname; + cdio_utf8_t *p_psz_out = NULL; + if (cdio_charset_to_utf8(&p_iso9660_dir->filename.str[1], i_inlen, + &p_psz_out, "UCS-2BE")) { + strncpy(p_stat->filename, p_psz_out, i_fname); + free(p_psz_out); + } + else { + free(p_stat); + return NULL; + } + } +#endif /*HAVE_JOLIET*/ + else { + strncpy (p_stat->filename, &p_iso9660_dir->filename.str[1], i_fname); + } + } + } + + + iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm)); + + if (dir_len < sizeof (iso9660_dir_t)) { + free(p_stat->rr.psz_symlink); + free(p_stat); + return NULL; + } + + + { + int su_length = iso9660_get_dir_len(p_iso9660_dir) + - sizeof (iso9660_dir_t); + su_length -= i_fname; + + if (su_length % 2) + su_length--; + + if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) + return p_stat; + + if (nope == b_xa) { + return p_stat; + } else { + iso9660_xa_t *xa_data = + (void *) (((char *) p_iso9660_dir) + + (iso9660_get_dir_len(p_iso9660_dir) - su_length)); + cdio_log_level_t loglevel = (yep == b_xa) + ? CDIO_LOG_WARN : CDIO_LOG_INFO; + + if (xa_data->signature[0] != 'X' + || xa_data->signature[1] != 'A') + { + cdio_log (loglevel, + "XA signature not found in ISO9660's system use area;" + " ignoring XA attributes for this file entry."); + cdio_debug ("%d %d %d, '%c%c' (%d, %d)", + iso9660_get_dir_len(p_iso9660_dir), + i_fname, + su_length, + xa_data->signature[0], xa_data->signature[1], + xa_data->signature[0], xa_data->signature[1]); + return p_stat; + } + p_stat->b_xa = true; + p_stat->xa = *xa_data; + } + } + return p_stat; + +} + +/*! + Return the directory name stored in the iso9660_dir_t + + A string is allocated: the caller must deallocate. This routine + can return NULL if memory allocation fails. + */ +char * +iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir) +{ + uint8_t len=iso9660_get_dir_len(iso9660_dir); + + if (!len) return NULL; + + cdio_assert (len >= sizeof (iso9660_dir_t)); + + /* (iso9660_dir->file_flags & ISO_DIRECTORY) */ + + if (iso9660_dir->filename.str[1] == '\0') + return strdup("."); + else if (iso9660_dir->filename.str[1] == '\1') + return strdup(".."); + else { + return strdup(&iso9660_dir->filename.str[1]); + } +} + +/* + Return a pointer to a ISO 9660 stat buffer or NULL if there's an error +*/ +static iso9660_stat_t * +_fs_stat_root (CdIo_t *p_cdio) +{ + + if (!p_cdio) return NULL; + + { + iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL; + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; + iso9660_dir_t *p_iso9660_dir; + iso9660_stat_t *p_stat; + bool_3way_t b_xa; + + if (!p_env->i_joliet_level) + iso_extension_mask &= ~ISO_EXTENSION_JOLIET; + + /* FIXME try also with Joliet.*/ + if ( !iso9660_fs_read_superblock (p_cdio, iso_extension_mask) ) { + cdio_warn("Could not read ISO-9660 Superblock."); + return NULL; + } + + switch(cdio_get_discmode(p_cdio)) { + case CDIO_DISC_MODE_CD_XA: + b_xa = yep; + break; + case CDIO_DISC_MODE_CD_DATA: + b_xa = nope; + break; + default: + b_xa = dunno; + } + +#ifdef HAVE_JOLIET + p_iso9660_dir = p_env->i_joliet_level + ? &(p_env->svd.root_directory_record) + : &(p_env->pvd.root_directory_record) ; +#else + p_iso9660_dir = &(p_env->pvd.root_directory_record) ; +#endif + + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_xa, + p_env->i_joliet_level); + return p_stat; + } + +} + +static iso9660_stat_t * +_ifs_stat_root (iso9660_t *p_iso) +{ + iso9660_stat_t *p_stat; + iso9660_dir_t *p_iso9660_dir; + +#ifdef HAVE_JOLIET + p_iso9660_dir = p_iso->i_joliet_level + ? &(p_iso->svd.root_directory_record) + : &(p_iso->pvd.root_directory_record) ; +#else + p_iso9660_dir = &(p_iso->pvd.root_directory_record) ; +#endif + + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa, + p_iso->i_joliet_level); + return p_stat; +} + +static iso9660_stat_t * +_fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, + char **splitpath) +{ + unsigned offset = 0; + uint8_t *_dirbuf = NULL; + iso9660_stat_t *p_stat; + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; + + if (!splitpath[0]) + { + unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; + p_stat = calloc(1, len); + memcpy(p_stat, _root, len); + p_stat->rr.psz_symlink = calloc(1, p_stat->rr.i_symlink_max); + memcpy(p_stat->rr.psz_symlink, _root->rr.psz_symlink, + p_stat->rr.i_symlink_max); + return p_stat; + } + + if (_root->type == _STAT_FILE) + return NULL; + + cdio_assert (_root->type == _STAT_DIR); + + _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); + if (!_dirbuf) + { + cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); + return NULL; + } + + if (cdio_read_data_sectors (p_cdio, _dirbuf, _root->lsn, ISO_BLOCKSIZE, + _root->secsize)) + return NULL; + + while (offset < (_root->secsize * ISO_BLOCKSIZE)) + { + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_iso9660_stat; + int cmp; + + if (!iso9660_get_dir_len(p_iso9660_dir)) + { + offset++; + continue; + } + + p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, dunno, + p_env->i_joliet_level); + + cmp = strcmp(splitpath[0], p_iso9660_stat->filename); + + if ( 0 != cmp && 0 == p_env->i_joliet_level + && yep != p_iso9660_stat->rr.b3_rock ) { + char *trans_fname = NULL; + unsigned int i_trans_fname=strlen(p_iso9660_stat->filename); + + if (i_trans_fname) { + trans_fname = calloc(1, i_trans_fname+1); + if (!trans_fname) { + cdio_warn("can't allocate %lu bytes", + (long unsigned int) strlen(p_iso9660_stat->filename)); + free(p_iso9660_stat); + return NULL; + } + iso9660_name_translate_ext(p_iso9660_stat->filename, trans_fname, + p_env->i_joliet_level); + cmp = strcmp(splitpath[0], trans_fname); + free(trans_fname); + } + } + + if (!cmp) { + iso9660_stat_t *ret_stat + = _fs_stat_traverse (p_cdio, p_iso9660_stat, &splitpath[1]); + free(p_iso9660_stat->rr.psz_symlink); + free(p_iso9660_stat); + free (_dirbuf); + return ret_stat; + } + + free(p_iso9660_stat->rr.psz_symlink); + free(p_iso9660_stat); + + offset += iso9660_get_dir_len(p_iso9660_dir); + } + + cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); + + /* not found */ + free (_dirbuf); + return NULL; +} + +static iso9660_stat_t * +_fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, + char **splitpath) +{ + unsigned offset = 0; + uint8_t *_dirbuf = NULL; + int ret; + + if (!splitpath[0]) + { + iso9660_stat_t *p_stat; + unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; + p_stat = calloc(1, len); + if (!p_stat) + { + cdio_warn("Couldn't calloc(1, %d)", len); + return NULL; + } + memcpy(p_stat, _root, len); + p_stat->rr.psz_symlink = calloc(1, p_stat->rr.i_symlink_max); + memcpy(p_stat->rr.psz_symlink, _root->rr.psz_symlink, + p_stat->rr.i_symlink_max); + return p_stat; + } + + if (_root->type == _STAT_FILE) + return NULL; + + cdio_assert (_root->type == _STAT_DIR); + + _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); + if (!_dirbuf) + { + cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); + return NULL; + } + + ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize); + if (ret!=ISO_BLOCKSIZE*_root->secsize) return NULL; + + while (offset < (_root->secsize * ISO_BLOCKSIZE)) + { + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_stat; + int cmp; + + if (!iso9660_get_dir_len(p_iso9660_dir)) + { + offset++; + continue; + } + + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa, + p_iso->i_joliet_level); + + cmp = strcmp(splitpath[0], p_stat->filename); + + if ( 0 != cmp && 0 == p_iso->i_joliet_level + && yep != p_stat->rr.b3_rock ) { + char *trans_fname = NULL; + unsigned int i_trans_fname=strlen(p_stat->filename); + + if (i_trans_fname) { + trans_fname = calloc(1, i_trans_fname+1); + if (!trans_fname) { + cdio_warn("can't allocate %lu bytes", + (long unsigned int) strlen(p_stat->filename)); + free(p_stat); + return NULL; + } + iso9660_name_translate_ext(p_stat->filename, trans_fname, + p_iso->i_joliet_level); + cmp = strcmp(splitpath[0], trans_fname); + free(trans_fname); + } + } + + if (!cmp) { + iso9660_stat_t *ret_stat + = _fs_iso_stat_traverse (p_iso, p_stat, &splitpath[1]); + free(p_stat->rr.psz_symlink); + free(p_stat); + free (_dirbuf); + return ret_stat; + } + + free(p_stat->rr.psz_symlink); + free(p_stat); + + offset += iso9660_get_dir_len(p_iso9660_dir); + } + + cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); + + /* not found */ + free (_dirbuf); + return NULL; +} + +/*! + Get file status for psz_path into stat. NULL is returned on error. + */ +iso9660_stat_t * +iso9660_fs_stat (CdIo_t *p_cdio, const char psz_path[]) +{ + iso9660_stat_t *p_root; + char **p_psz_splitpath; + iso9660_stat_t *p_stat; + + if (!p_cdio) return NULL; + if (!psz_path) return NULL; + + p_root = _fs_stat_root (p_cdio); + + if (!p_root) return NULL; + + p_psz_splitpath = _cdio_strsplit (psz_path, '/'); + p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath); + free(p_root); + _cdio_strfreev (p_psz_splitpath); + + return p_stat; +} + +typedef iso9660_stat_t * (stat_root_t) (void *p_image); +typedef iso9660_stat_t * (stat_traverse_t) + (const void *p_image, const iso9660_stat_t *_root, char **splitpath); + +/*! + Get file status for psz_path into stat. NULL is returned on error. + pathname version numbers in the ISO 9660 + name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names + are lowercased. + */ +static iso9660_stat_t * +fs_stat_translate (void *p_image, stat_root_t stat_root, + stat_traverse_t stat_traverse, + const char psz_path[]) +{ + iso9660_stat_t *p_root; + char **p_psz_splitpath; + iso9660_stat_t *p_stat; + + if (!p_image) return NULL; + if (!psz_path) return NULL; + + p_root = stat_root (p_image); + if (!p_root) return NULL; + + p_psz_splitpath = _cdio_strsplit (psz_path, '/'); + p_stat = stat_traverse (p_image, p_root, p_psz_splitpath); + free(p_root); + _cdio_strfreev (p_psz_splitpath); + + return p_stat; +} + +iso9660_stat_t * +iso9660_fs_stat_translate (CdIo_t *p_cdio, const char psz_path[], + bool b_mode2) +{ + return fs_stat_translate(p_cdio, (stat_root_t *) _fs_stat_root, + (stat_traverse_t *) _fs_stat_traverse, + psz_path); +} + +/*! + Get file status for psz_path into stat. NULL is returned on error. + pathname version numbers in the ISO 9660 + name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names + are lowercased. + */ +iso9660_stat_t * +iso9660_ifs_stat_translate (iso9660_t *p_iso, const char psz_path[]) +{ + return fs_stat_translate(p_iso, (stat_root_t *) _ifs_stat_root, + (stat_traverse_t *) _fs_iso_stat_traverse, + psz_path); +} + + +/*! + Get file status for psz_path into stat. NULL is returned on error. + */ +iso9660_stat_t * +iso9660_ifs_stat (iso9660_t *p_iso, const char psz_path[]) +{ + iso9660_stat_t *p_root; + char **splitpath; + iso9660_stat_t *stat; + + if (!p_iso) return NULL; + if (!psz_path) return NULL; + + p_root = _ifs_stat_root (p_iso); + if (!p_root) return NULL; + + splitpath = _cdio_strsplit (psz_path, '/'); + stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath); + free(p_root); + _cdio_strfreev (splitpath); + + return stat; +} + +/*! + Read psz_path (a directory) and return a list of iso9660_stat_t + of the files inside that. The caller must free the returned result. + + b_mode2 is historical. It is not used. +*/ +CdioList_t * +iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) +{ + generic_img_private_t *p_env; + iso9660_stat_t *p_stat; + + if (!p_cdio) return NULL; + if (!psz_path) return NULL; + + p_env = (generic_img_private_t *) p_cdio->env; + + p_stat = iso9660_fs_stat (p_cdio, psz_path); + if (!p_stat) return NULL; + + if (p_stat->type != _STAT_DIR) { + free(p_stat->rr.psz_symlink); + free(p_stat); + return NULL; + } + + { + unsigned offset = 0; + uint8_t *_dirbuf = NULL; + CdioList_t *retval = _cdio_list_new (); + + _dirbuf = calloc(1, p_stat->secsize * ISO_BLOCKSIZE); + if (!_dirbuf) + { + cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize * ISO_BLOCKSIZE); + return NULL; + } + + if (cdio_read_data_sectors (p_cdio, _dirbuf, p_stat->lsn, + ISO_BLOCKSIZE, p_stat->secsize)) + return NULL; + + while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) + { + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_iso9660_stat; + + if (!iso9660_get_dir_len(p_iso9660_dir)) + { + offset++; + continue; + } + + p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, dunno, + p_env->i_joliet_level); + _cdio_list_append (retval, p_iso9660_stat); + + offset += iso9660_get_dir_len(p_iso9660_dir); + } + + cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); + + free (_dirbuf); + free (p_stat); + return retval; + } +} + +/*! + Read psz_path (a directory) and return a list of iso9660_stat_t + of the files inside that. The caller must free the returned result. +*/ +CdioList_t * +iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) +{ + iso9660_stat_t *p_stat; + + if (!p_iso) return NULL; + if (!psz_path) return NULL; + + p_stat = iso9660_ifs_stat (p_iso, psz_path); + if (!p_stat) return NULL; + + if (p_stat->type != _STAT_DIR) { + free(p_stat->rr.psz_symlink); + free(p_stat); + return NULL; + } + + { + long int ret; + unsigned offset = 0; + uint8_t *_dirbuf = NULL; + CdioList_t *retval = _cdio_list_new (); + + _dirbuf = calloc(1, p_stat->secsize * ISO_BLOCKSIZE); + if (!_dirbuf) + { + cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize * ISO_BLOCKSIZE); + return NULL; + } + + ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize); + if (ret != ISO_BLOCKSIZE*p_stat->secsize) + { + free (_dirbuf); + return NULL; + } + + while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) + { + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_iso9660_stat; + + if (!iso9660_get_dir_len(p_iso9660_dir)) + { + offset++; + continue; + } + + p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, p_iso->b_xa, + p_iso->i_joliet_level); + + if (p_iso9660_stat) + _cdio_list_append (retval, p_iso9660_stat); + + offset += iso9660_get_dir_len(p_iso9660_dir); + } + + free (_dirbuf); + + if (offset != (p_stat->secsize * ISO_BLOCKSIZE)) { + free (p_stat); + _cdio_list_free (retval, true); + return NULL; + } + + free (p_stat->rr.psz_symlink); + free (p_stat); + return retval; + } +} + +typedef CdioList_t * (iso9660_readdir_t) + (void *p_image, const char * psz_path); + +static iso9660_stat_t * +find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir, + const char psz_path[], lsn_t lsn, + /*out*/ char **ppsz_full_filename) +{ + CdioList_t *entlist = iso9660_readdir (p_image, psz_path); + CdioList_t *dirlist = _cdio_list_new (); + CdioListNode_t *entnode; + + cdio_assert (entlist != NULL); + + /* iterate over each entry in the directory */ + + _CDIO_LIST_FOREACH (entnode, entlist) + { + iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); + const char *psz_filename = (char *) statbuf->filename; + unsigned int len = strlen(psz_path) + strlen(psz_filename)+2; + + if (*ppsz_full_filename != NULL) free(*ppsz_full_filename); + *ppsz_full_filename = calloc(1, len); + snprintf (*ppsz_full_filename, len, "%s%s/", psz_path, psz_filename); + + if (statbuf->type == _STAT_DIR + && strcmp ((char *) statbuf->filename, ".") + && strcmp ((char *) statbuf->filename, "..")) { + _cdio_list_append (dirlist, strdup(*ppsz_full_filename)); + } + + if (statbuf->lsn == lsn) { + iso9660_stat_t *ret_stat = calloc(1, len); + len = sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1; + if (!ret_stat) + { + cdio_warn("Couldn't calloc(1, %d)", len); + return NULL; + } + memcpy(ret_stat, statbuf, len); + _cdio_list_free (entlist, true); + _cdio_list_free (dirlist, true); + return ret_stat; + } + + } + + _cdio_list_free (entlist, true); + + /* now recurse/descend over directories encountered */ + + _CDIO_LIST_FOREACH (entnode, dirlist) + { + char *psz_path_prefix = _cdio_list_node_data (entnode); + iso9660_stat_t *ret_stat; + free(*ppsz_full_filename); + *ppsz_full_filename = NULL; + ret_stat = find_lsn_recurse (p_image, iso9660_readdir, + psz_path_prefix, lsn, + ppsz_full_filename); + + if (NULL != ret_stat) { + _cdio_list_free (dirlist, true); + return ret_stat; + } + } + + if (*ppsz_full_filename != NULL) { + free(*ppsz_full_filename); + *ppsz_full_filename = NULL; + } + _cdio_list_free (dirlist, true); + return NULL; +} + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + Returns stat_t of entry if we found lsn, or NULL otherwise. + */ +iso9660_stat_t * +iso9660_fs_find_lsn(CdIo_t *p_cdio, lsn_t i_lsn) +{ + char *psz_full_filename = NULL; + return find_lsn_recurse (p_cdio, (iso9660_readdir_t *) iso9660_fs_readdir, + "/", i_lsn, &psz_full_filename); +} + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + Returns stat_t of entry if we found lsn, or NULL otherwise. + */ +iso9660_stat_t * +iso9660_fs_find_lsn_with_path(CdIo_t *p_cdio, lsn_t i_lsn, + /*out*/ char **ppsz_full_filename) +{ + return find_lsn_recurse (p_cdio, (iso9660_readdir_t *) iso9660_fs_readdir, + "/", i_lsn, ppsz_full_filename); +} + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + Returns stat_t of entry if we found lsn, or NULL otherwise. + */ +iso9660_stat_t * +iso9660_ifs_find_lsn(iso9660_t *p_iso, lsn_t i_lsn) +{ + char *psz_full_filename = NULL; + return find_lsn_recurse (p_iso, (iso9660_readdir_t *) iso9660_ifs_readdir, + "/", i_lsn, &psz_full_filename); +} + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it. + + Returns stat_t of entry if we found lsn, or NULL otherwise. + */ +iso9660_stat_t * +iso9660_ifs_find_lsn_with_path(iso9660_t *p_iso, lsn_t i_lsn, + /*out*/ char **ppsz_full_filename) +{ + return find_lsn_recurse (p_iso, (iso9660_readdir_t *) iso9660_ifs_readdir, + "/", i_lsn, ppsz_full_filename); +} + +/*! + Return true if ISO 9660 image has extended attrributes (XA). +*/ +bool +iso9660_ifs_is_xa (const iso9660_t * p_iso) +{ + if (!p_iso) return false; + return yep == p_iso->b_xa; +} diff --git a/src/libcdio/iso9660/iso9660_private.h b/src/libcdio/iso9660/iso9660_private.h new file mode 100644 index 00000000..20ea2b4e --- /dev/null +++ b/src/libcdio/iso9660/iso9660_private.h @@ -0,0 +1,83 @@ +/* + Copyright (C) 2003, 2004, 2005, 2008, 2011 + Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + See also iso9660.h by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + Copyright (c) 1999,2000 J. Schilling + + 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 3 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, see . +*/ + +#ifndef __CDIO_ISO9660_PRIVATE_H__ +#define __CDIO_ISO9660_PRIVATE_H__ + +#if defined(HAVE_CONFIG_H) && !defined(__CDIO_CONFIG_H__) +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include + +#define ISO_VERSION 1 + +PRAGMA_BEGIN_PACKED + +typedef struct iso_volume_descriptor_s { + uint8_t type; /**< 7.1.1 */ + char id[5]; /**< "CD001" (ISO_STANDARD_ID) */ + uint8_t version; /**< 7.1.1 */ + char data[2041]; +} GNUC_PACKED iso_volume_descriptor_t; + +#define iso_volume_descriptor_t_SIZEOF ISO_BLOCKSIZE + +#define iso9660_pvd_t_SIZEOF ISO_BLOCKSIZE + +/* + * XXX JS: The next structure has an odd length! + * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. + * For this reason, we cannot use sizeof (struct iso_path_table) or + * sizeof (struct iso_directory_record) to compute on disk sizes. + * Instead, we use offsetof(..., name) and add the name size. + * See mkisofs.h + */ + +/** We use this to help us look up the parent inode numbers. */ +typedef struct iso_path_table_s { + uint8_t name_len; /**< 7.1.1 */ + uint8_t xa_len; /**< 7.1.1 */ + uint32_t extent; /**< 7.3.1/7.3.2 */ + uint16_t parent; /**< 7.2.1/7.2.2 */ + char name[EMPTY_ARRAY_SIZE]; +} GNUC_PACKED iso_path_table_t; + +#define iso_path_table_t_SIZEOF 8 + +#define iso9660_dir_t_SIZEOF 33 + +PRAGMA_END_PACKED + +#endif /* __CDIO_ISO9660_PRIVATE_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/iso9660/rock.c b/src/libcdio/iso9660/rock.c new file mode 100644 index 00000000..8dc000a8 --- /dev/null +++ b/src/libcdio/iso9660/rock.c @@ -0,0 +1,619 @@ +/* + Copyright (C) 2005, 2008, 2010, 2011 Rocky Bernstein + Adapted from GNU/Linux fs/isofs/rock.c (C) 1992, 1993 Eric Youngdale + + 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 3 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, see . +*/ +/* Rock Ridge Extensions to iso9660 */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STDLIB_H +# include +#endif + +#ifdef HAVE_SYS_STAT_H +# include +#endif + +#include +#include +#include +#include "filemode.h" + +#define CDIO_MKDEV(ma,mi) ((ma)<<16 | (mi)) + +enum iso_rock_enums iso_rock_enums; +iso_rock_nm_flag_t iso_rock_nm_flag; +iso_rock_sl_flag_t iso_rock_sl_flag; +iso_rock_tf_flag_t iso_rock_tf_flag; + +/* Our own realloc routine tailored for the iso9660_stat_t symlink + field. I can't figure out how to make realloc() work without + valgrind complaint. +*/ +static bool +realloc_symlink(/*in/out*/ iso9660_stat_t *p_stat, uint8_t i_grow) +{ + if (!p_stat->rr.i_symlink) { + const uint16_t i_max = 2*i_grow+1; + p_stat->rr.psz_symlink = (char *) calloc(1, i_max); + p_stat->rr.i_symlink_max = i_max; + return (NULL != p_stat->rr.psz_symlink); + } else { + unsigned int i_needed = p_stat->rr.i_symlink + i_grow ; + if ( i_needed <= p_stat->rr.i_symlink_max) + return true; + else { + char * psz_newsymlink = (char *) calloc(1, 2*i_needed); + if (!psz_newsymlink) return false; + p_stat->rr.i_symlink_max = 2*i_needed; + memcpy(psz_newsymlink, p_stat->rr.psz_symlink, p_stat->rr.i_symlink); + free(p_stat->rr.psz_symlink); + p_stat->rr.psz_symlink = psz_newsymlink; + return true; + } + } +} + +/* These functions are designed to read the system areas of a directory record + * and extract relevant information. There are different functions provided + * depending upon what information we need at the time. One function fills + * out an inode structure, a second one extracts a filename, a third one + * returns a symbolic link name, and a fourth one returns the extent number + * for the file. */ + +#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */ + + +/* This is a way of ensuring that we have something in the system + use fields that is compatible with Rock Ridge */ +#define CHECK_SP(FAIL) \ + if(rr->u.SP.magic[0] != 0xbe) FAIL; \ + if(rr->u.SP.magic[1] != 0xef) FAIL; \ + p_stat->rr.s_rock_offset = rr->u.SP.skip; +/* We define a series of macros because each function must do exactly the + same thing in certain places. We use the macros to ensure that everything + is done correctly */ + +#define CONTINUE_DECLS \ + int cont_extent = 0, cont_offset = 0, cont_size = 0; \ + void *buffer = NULL + +#define CHECK_CE \ + { cont_extent = from_733(*rr->u.CE.extent); \ + cont_offset = from_733(*rr->u.CE.offset); \ + cont_size = from_733(*rr->u.CE.size); \ + (void)cont_extent; (void)cont_offset, (void)cont_size; } + +#define SETUP_ROCK_RIDGE(DE,CHR,LEN) \ + { \ + LEN= sizeof(iso9660_dir_t) + DE->filename.len; \ + if(LEN & 1) LEN++; \ + CHR = ((unsigned char *) DE) + LEN; \ + LEN = *((unsigned char *) DE) - LEN; \ + if (0xff != p_stat->rr.s_rock_offset) \ + { \ + LEN -= p_stat->rr.s_rock_offset; \ + CHR += p_stat->rr.s_rock_offset; \ + if (LEN<0) LEN=0; \ + } \ + } + +/* Copy a long or short time from the iso_rock_tf_t into + the specified field of a iso_rock_statbuf_t. + non-paramater variables are p_stat, rr, and cnt. +*/ +#define add_time(FLAG, TIME_FIELD) \ + if (rr->u.TF.flags & FLAG) { \ + p_stat->rr.TIME_FIELD.b_used = true; \ + p_stat->rr.TIME_FIELD.b_longdate = \ + (0 != (rr->u.TF.flags & ISO_ROCK_TF_LONG_FORM)); \ + if (p_stat->rr.TIME_FIELD.b_longdate) { \ + memcpy(&(p_stat->rr.TIME_FIELD.t.ltime), \ + &(rr->u.TF.time_bytes[cnt]), \ + sizeof(iso9660_ltime_t)); \ + cnt += sizeof(iso9660_ltime_t); \ + } else { \ + memcpy(&(p_stat->rr.TIME_FIELD.t.dtime), \ + &(rr->u.TF.time_bytes[cnt]), \ + sizeof(iso9660_dtime_t)); \ + cnt += sizeof(iso9660_dtime_t); \ + } \ + } + +/*! + Get + @return length of name field; 0: not found, -1: to be ignored +*/ +int +get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, + /*out*/ char * psz_name, + /*in/out*/ iso9660_stat_t *p_stat) +{ + int len; + unsigned char *chr; + int symlink_len = 0; + CONTINUE_DECLS; + int i_namelen = 0; + int truncate=0; + + if (!p_stat || nope == p_stat->rr.b3_rock) return 0; + *psz_name = 0; + + SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); + /*repeat:*/ + { + iso_extension_record_t * rr; + int sig; + int rootflag; + + while (len > 1){ /* There may be one byte for padding somewhere */ + rr = (iso_extension_record_t *) chr; + if (rr->len == 0) goto out; /* Something got screwed up here */ + sig = *chr+(*(chr+1) << 8); + chr += rr->len; + len -= rr->len; + + switch(sig){ + case SIG('S','P'): + CHECK_SP(goto out); + break; + case SIG('C','E'): + { + iso711_t i_fname = from_711(p_iso9660_dir->filename.len); + if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname) + break; + if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname) + break; + } + CHECK_CE; + break; + case SIG('E','R'): + p_stat->rr.b3_rock = yep; + cdio_debug("ISO 9660 Extensions: "); + { + int p; + for(p=0;pu.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); + } + break; + case SIG('N','M'): + /* Alternate name */ + p_stat->rr.b3_rock = yep; + if (truncate) break; + if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) { + i_namelen = sizeof(".."); + strncat(psz_name, "..", i_namelen); + } else if (rr->u.NM.flags & ISO_ROCK_NM_CURRENT) { + i_namelen = sizeof("."); + strncat(psz_name, ".", i_namelen); + break; + } + + if (rr->u.NM.flags & ~1) { + cdio_info("Unsupported NM flag settings (%d)",rr->u.NM.flags); + break; + } + if((strlen(psz_name) + rr->len - 5) >= 254) { + truncate = 1; + break; + } + strncat(psz_name, rr->u.NM.name, rr->len - 5); + i_namelen += rr->len - 5; + break; + case SIG('P','X'): + /* POSIX file attributes */ + p_stat->rr.st_mode = from_733(rr->u.PX.st_mode); + p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); + p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); + p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); + p_stat->rr.b3_rock = yep; + break; + case SIG('S','L'): + { + /* Symbolic link */ + uint8_t slen; + iso_rock_sl_part_t * p_sl; + iso_rock_sl_part_t * p_oldsl; + slen = rr->len - 5; + p_sl = &rr->u.SL.link; + p_stat->rr.i_symlink = symlink_len; + while (slen > 1){ + rootflag = 0; + switch(p_sl->flags &~1){ + case 0: + realloc_symlink(p_stat, p_sl->len); + memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]), + p_sl->text, p_sl->len); + p_stat->rr.i_symlink += p_sl->len; + break; + case 4: + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; + /* continue into next case. */ + case 2: + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; + break; + case 8: + rootflag = 1; + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; + break; + default: + cdio_warn("Symlink component flag not implemented"); + } + slen -= p_sl->len + 2; + p_oldsl = p_sl; + p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); + + if (slen < 2) { + if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) + p_stat->rr.i_symlink += 1; + break; + } + + /* + * If this component record isn't continued, then append a '/'. + */ + if (!rootflag && (p_oldsl->flags & 1) == 0) { + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; + } + } + } + symlink_len = p_stat->rr.i_symlink; + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[symlink_len]='\0'; + break; + case SIG('R','E'): + free(buffer); + return -1; + case SIG('T','F'): + /* Time stamp(s) for a file */ + { + int cnt = 0; + add_time(ISO_ROCK_TF_CREATE, create); + add_time(ISO_ROCK_TF_MODIFY, modify); + add_time(ISO_ROCK_TF_ACCESS, access); + add_time(ISO_ROCK_TF_ATTRIBUTES, attributes); + add_time(ISO_ROCK_TF_BACKUP, backup); + add_time(ISO_ROCK_TF_EXPIRATION, expiration); + add_time(ISO_ROCK_TF_EFFECTIVE, effective); + p_stat->rr.b3_rock = yep; + break; + } + default: + break; + } + } + } + free(buffer); + return i_namelen; /* If 0, this file did not have a NM field */ + out: + free(buffer); + return 0; +} + +static int +parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, + iso9660_stat_t *p_stat, int regard_xa) +{ + int len; + unsigned char * chr; + int symlink_len = 0; + CONTINUE_DECLS; + + if (nope == p_stat->rr.b3_rock) return 0; + + SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); + if (regard_xa) + { + chr+=14; + len-=14; + if (len<0) len=0; + } + + /* repeat:*/ + { + int sig; + iso_extension_record_t * rr; + int rootflag; + + while (len > 1){ /* There may be one byte for padding somewhere */ + rr = (iso_extension_record_t *) chr; + if (rr->len == 0) goto out; /* Something got screwed up here */ + sig = from_721(*chr); + chr += rr->len; + len -= rr->len; + + switch(sig){ + case SIG('S','P'): + CHECK_SP(goto out); + break; + case SIG('C','E'): + CHECK_CE; + break; + case SIG('E','R'): + p_stat->rr.b3_rock = yep; + cdio_debug("ISO 9660 Extensions: "); + { int p; + for(p=0;pu.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); + } + break; + case SIG('P','X'): + p_stat->rr.st_mode = from_733(rr->u.PX.st_mode); + p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); + p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); + p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); + break; + case SIG('P','N'): + /* Device major,minor number */ + { int32_t high, low; + high = from_733(rr->u.PN.dev_high); + low = from_733(rr->u.PN.dev_low); + /* + * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, + * then the high field is unused, and the device number is completely + * stored in the low field. Some writers may ignore this subtlety, + * and as a result we test to see if the entire device number is + * stored in the low field, and use that. + */ + if((low & ~0xff) && high == 0) { + p_stat->rr.i_rdev = CDIO_MKDEV(low >> 8, low & 0xff); + } else { + p_stat->rr.i_rdev = CDIO_MKDEV(high, low); + } + } + break; + case SIG('T','F'): + /* Time stamp(s) for a file */ + { + int cnt = 0; + add_time(ISO_ROCK_TF_CREATE, create); + add_time(ISO_ROCK_TF_MODIFY, modify); + add_time(ISO_ROCK_TF_ACCESS, access); + add_time(ISO_ROCK_TF_ATTRIBUTES, attributes); + add_time(ISO_ROCK_TF_BACKUP, backup); + add_time(ISO_ROCK_TF_EXPIRATION, expiration); + add_time(ISO_ROCK_TF_EFFECTIVE, effective); + p_stat->rr.b3_rock = yep; + break; + } + case SIG('S','L'): + { + /* Symbolic link */ + uint8_t slen; + iso_rock_sl_part_t * p_sl; + iso_rock_sl_part_t * p_oldsl; + slen = rr->len - 5; + p_sl = &rr->u.SL.link; + p_stat->rr.i_symlink = symlink_len; + while (slen > 1){ + rootflag = 0; + switch(p_sl->flags &~1){ + case 0: + realloc_symlink(p_stat, p_sl->len); + memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]), + p_sl->text, p_sl->len); + p_stat->rr.i_symlink += p_sl->len; + break; + case 4: + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; + /* continue into next case. */ + case 2: + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.'; + break; + case 8: + rootflag = 1; + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; + p_stat->rr.i_symlink++; + break; + default: + cdio_warn("Symlink component flag not implemented"); + } + slen -= p_sl->len + 2; + p_oldsl = p_sl; + p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); + + if (slen < 2) { + if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) + p_stat->rr.i_symlink += 1; + break; + } + + /* + * If this component record isn't continued, then append a '/'. + */ + if (!rootflag && (p_oldsl->flags & 1) == 0) { + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/'; + } + } + } + symlink_len = p_stat->rr.i_symlink; + realloc_symlink(p_stat, 1); + p_stat->rr.psz_symlink[symlink_len]='\0'; + break; + case SIG('R','E'): + cdio_warn("Attempt to read p_stat for relocated directory"); + goto out; +#ifdef FINISHED + case SIG('C','L'): + { + iso9660_stat_t * reloc; + ISOFS_I(p_stat)->i_first_extent = from_733(rr->u.CL.location); + reloc = isofs_iget(p_stat->rr.i_sb, p_stat->rr.i_first_extent, 0); + if (!reloc) + goto out; + p_stat->rr.st_mode = reloc->st_mode; + p_stat->rr.st_nlinks = reloc->st_nlinks; + p_stat->rr.st_uid = reloc->st_uid; + p_stat->rr.st_gid = reloc->st_gid; + p_stat->rr.i_rdev = reloc->i_rdev; + p_stat->rr.i_symlink = reloc->i_symlink; + p_stat->rr.i_blocks = reloc->i_blocks; + p_stat->rr.i_atime = reloc->i_atime; + p_stat->rr.i_ctime = reloc->i_ctime; + p_stat->rr.i_mtime = reloc->i_mtime; + iput(reloc); + } + break; +#endif + default: + break; + } + } + } + out: + free(buffer); + return 0; +} + +int +parse_rock_ridge_stat(iso9660_dir_t *p_iso9660_dir, + /*out*/ iso9660_stat_t *p_stat) +{ + int result; + + if (!p_stat) return 0; + + result = parse_rock_ridge_stat_internal(p_iso9660_dir, p_stat, 0); + /* if Rock-Ridge flag was reset and we didn't look for attributes + * behind eventual XA attributes, have a look there */ + if (0xFF == p_stat->rr.s_rock_offset && nope != p_stat->rr.b3_rock) { + result = parse_rock_ridge_stat_internal(p_iso9660_dir, p_stat, 14); + } + return result; +} + +#define BUF_COUNT 16 +#define BUF_SIZE sizeof("drwxrwxrwx") + +/* Return a pointer to a internal free buffer */ +static char * +_getbuf (void) +{ + static char _buf[BUF_COUNT][BUF_SIZE]; + static int _i = -1; + + _i++; + _i %= BUF_COUNT; + + memset (_buf[_i], 0, BUF_SIZE); + + return _buf[_i]; +} + +/*! + Returns a string which interpreting the POSIX mode st_mode. + For example: + \verbatim + drwxrws--- + -rw-rw-r-- + lrwxrwxrwx + \endverbatim + + A description of the characters in the string follows + The 1st character is either "b" for a block device, + "c" for a character device, "d" if the entry is a directory, "l" for + a symbolic link, "p" for a pipe or FIFO, "s" for a "socket", + or "-" if none of the these. + + The 2nd to 4th characters refer to permissions for a user while the + the 5th to 7th characters refer to permissions for a group while, and + the 8th to 10h characters refer to permissions for everyone. + + In each of these triplets the first character (2, 5, 8) is "r" if + the entry is allowed to be read. + + The second character of a triplet (3, 6, 9) is "w" if the entry is + allowed to be written. + + The third character of a triplet (4, 7, 10) is "x" if the entry is + executable but not user (for character 4) or group (for characters + 6) settable and "s" if the item has the corresponding user/group set. + + For a directory having an executable property on ("x" or "s") means + the directory is allowed to be listed or "searched". If the execute + property is not allowed for a group or user but the corresponding + group/user is set "S" indicates this. If none of these properties + holds the "-" indicates this. +*/ +const char * +iso9660_get_rock_attr_str(posix_mode_t st_mode) +{ + char *result = _getbuf(); + + if (S_ISBLK(st_mode)) + result[ 0] = 'b'; + else if (S_ISDIR(st_mode)) + result[ 0] = 'd'; + else if (S_ISCHR(st_mode)) + result[ 0] = 'c'; + else if (S_ISLNK(st_mode)) + result[ 0] = 'l'; + else if (S_ISFIFO(st_mode)) + result[ 0] = 'p'; + else if (S_ISSOCK(st_mode)) + result[ 0] = 's'; + /* May eventually fill in others.. */ + else + result[ 0] = '-'; + + result[ 1] = (st_mode & ISO_ROCK_IRUSR) ? 'r' : '-'; + result[ 2] = (st_mode & ISO_ROCK_IWUSR) ? 'w' : '-'; + + if (st_mode & ISO_ROCK_ISUID) + result[ 3] = (st_mode & ISO_ROCK_IXUSR) ? 's' : 'S'; + else + result[ 3] = (st_mode & ISO_ROCK_IXUSR) ? 'x' : '-'; + + result[ 4] = (st_mode & ISO_ROCK_IRGRP) ? 'r' : '-'; + result[ 5] = (st_mode & ISO_ROCK_IWGRP) ? 'w' : '-'; + + if (st_mode & ISO_ROCK_ISGID) + result[ 6] = (st_mode & ISO_ROCK_IXGRP) ? 's' : 'S'; + else + result[ 6] = (st_mode & ISO_ROCK_IXGRP) ? 'x' : '-'; + + result[ 7] = (st_mode & ISO_ROCK_IROTH) ? 'r' : '-'; + result[ 8] = (st_mode & ISO_ROCK_IWOTH) ? 'w' : '-'; + result[ 9] = (st_mode & ISO_ROCK_IXOTH) ? 'x' : '-'; + + result[11] = '\0'; + + return result; +} + +/*! + Returns POSIX mode bitstring for a given file. +*/ +mode_t +iso9660_get_posix_filemode_from_rock(const iso_rock_statbuf_t *rr) +{ + return (mode_t) rr->st_mode; +} + + diff --git a/src/libcdio/iso9660/xa.c b/src/libcdio/iso9660/xa.c new file mode 100644 index 00000000..9af5a09d --- /dev/null +++ b/src/libcdio/iso9660/xa.c @@ -0,0 +1,183 @@ +/* + Copyright (C) 2003, 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 2000 Herbert Valerio Riedel + + 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 3 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, see . +*/ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +/*! String inside frame which identifies XA attributes. Note should + come *before* public headers which does a #define of + this name. +*/ +const char ISO_XA_MARKER_STRING[] = {'C', 'D', '-', 'X', 'A', '0', '0', '1'}; + +/* Public headers */ +#include +#include +#include + +/* Private headers */ +#include "cdio_assert.h" +#include "filemode.h" + +/** The below variable is trickery to force enum symbol values to be + recorded in debug symbol tables. It is used to allow one to refer + to the enumeration value names in the typedefs above in a debugger + and debugger expressions. +*/ +xa_misc_enum_t debugger_xa_misc_enum; + +#define BUF_COUNT 16 +#define BUF_SIZE 80 + +/* Return a pointer to a internal free buffer */ +static char * +_getbuf (void) +{ + static char _buf[BUF_COUNT][BUF_SIZE]; + static int _num = -1; + + _num++; + _num %= BUF_COUNT; + + memset (_buf[_num], 0, BUF_SIZE); + + return _buf[_num]; +} + +/*! + Returns a string which interpreting the extended attribute xa_attr. + For example: + \verbatim + d---1xrxrxr + ---2--r-r-r + -a--1xrxrxr + \endverbatim + + A description of the characters in the string follows + The 1st character is either "d" if the entry is a directory, or "-" if not. + The 2nd character is either "a" if the entry is CDDA (audio), or "-" if not. + The 3rd character is either "i" if the entry is interleaved, or "-" if not. + The 4th character is either "2" if the entry is mode2 form2 or "-" if not. + The 5th character is either "1" if the entry is mode2 form1 or "-" if not. + Note that an entry will either be in mode2 form1 or mode form2. That + is you will either see "2-" or "-1" in the 4th & 5th positions. + + The 6th and 7th characters refer to permissions for a user while the + the 8th and 9th characters refer to permissions for a group while, and + the 10th and 11th characters refer to permissions for a others. + + In each of these pairs the first character (6, 8, 10) is "x" if the + entry is executable. For a directory this means the directory is + allowed to be listed or "searched". + The second character of a pair (7, 9, 11) is "r" if the entry is allowed + to be read. +*/ + +const char * +iso9660_get_xa_attr_str (uint16_t xa_attr) +{ + char *result = _getbuf(); + + xa_attr = uint16_from_be (xa_attr); + + result[ 0] = (xa_attr & XA_ATTR_DIRECTORY) ? 'd' : '-'; + result[ 1] = (xa_attr & XA_ATTR_CDDA) ? 'a' : '-'; + result[ 2] = (xa_attr & XA_ATTR_INTERLEAVED) ? 'i' : '-'; + result[ 3] = (xa_attr & XA_ATTR_MODE2FORM2) ? '2' : '-'; + result[ 4] = (xa_attr & XA_ATTR_MODE2FORM1) ? '1' : '-'; + + result[ 5] = (xa_attr & XA_PERM_XUSR) ? 'x' : '-'; + result[ 6] = (xa_attr & XA_PERM_RUSR) ? 'r' : '-'; + + result[ 7] = (xa_attr & XA_PERM_XGRP) ? 'x' : '-'; + result[ 8] = (xa_attr & XA_PERM_RGRP) ? 'r' : '-'; + + /* Hack alert: wonder if this should be ROTH and XOTH? */ + result[ 9] = (xa_attr & XA_PERM_XSYS) ? 'x' : '-'; + result[10] = (xa_attr & XA_PERM_RSYS) ? 'r' : '-'; + + result[11] = '\0'; + + return result; +} + +iso9660_xa_t * +iso9660_xa_init (iso9660_xa_t *_xa, uint16_t uid, uint16_t gid, uint16_t attr, + uint8_t filenum) +{ + cdio_assert (_xa != NULL); + + _xa->user_id = uint16_to_be (uid); + _xa->group_id = uint16_to_be (gid); + _xa->attributes = uint16_to_be (attr); + + _xa->signature[0] = 'X'; + _xa->signature[1] = 'A'; + + _xa->filenum = filenum; + + _xa->reserved[0] + = _xa->reserved[1] + = _xa->reserved[2] + = _xa->reserved[3] + = _xa->reserved[4] = 0x00; + + return _xa; +} + +/*! + Returns POSIX mode bitstring for a given file. +*/ +posix_mode_t +iso9660_get_posix_filemode_from_xa(uint16_t i_perms) +{ + posix_mode_t mode = 0; + + if (i_perms & XA_PERM_RUSR) mode |= S_IRUSR; + if (i_perms & XA_PERM_XUSR) mode |= S_IXUSR; + +#ifdef S_IRGRP + if (i_perms & XA_PERM_RGRP) mode |= S_IRGRP; +#endif +#ifdef S_IXGRP + if (i_perms & XA_PERM_XGRP) mode |= S_IXGRP; +#endif + +#ifdef S_IROTH + if (i_perms & XA_PERM_ROTH) mode |= S_IROTH; +#endif +#ifdef S_IXOTH + if (i_perms & XA_PERM_XOTH) mode |= S_IXOTH; +#endif + + if (i_perms & XA_ATTR_DIRECTORY) mode |= S_IFDIR; + + return mode; +} + diff --git a/src/libcdio/udf/.msvc/udf.vcxproj b/src/libcdio/udf/.msvc/udf.vcxproj new file mode 100644 index 00000000..5899df79 --- /dev/null +++ b/src/libcdio/udf/.msvc/udf.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + {0CEC40A6-A195-4BE5-A88B-0AB00EB142EC} + Win32Proj + udf + libcdio-udf + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)x86_32\$(Configuration)\ + $(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_32\$(Configuration)\ + $(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_64\$(Configuration)\ + $(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\ + $(SolutionDir)x86_64\$(Configuration)\ + $(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\ + false + false + false + false + + + + + + Level3 + Disabled + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreadedDebug + ProgramDatabase + + + Windows + true + + + MachineX86 + + + + + Level3 + + + MaxSpeed + true + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreaded + ProgramDatabase + + + MachineX86 + + + + + + + Level3 + Disabled + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreadedDebug + ProgramDatabase + + + Windows + true + + + MachineX64 + + + + + Level3 + + + MaxSpeed + true + HAVE_CONFIG_H;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + ..;..\..;..\..\driver;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) + MultiThreaded + ProgramDatabase + + + Windows + true + true + true + + + MachineX64 + + + + + + \ No newline at end of file diff --git a/src/libcdio/udf/.msvc/udf.vcxproj.filters b/src/libcdio/udf/.msvc/udf.vcxproj.filters new file mode 100644 index 00000000..c3996225 --- /dev/null +++ b/src/libcdio/udf/.msvc/udf.vcxproj.filters @@ -0,0 +1,53 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/src/libcdio/udf/.msvc/udf_sources b/src/libcdio/udf/.msvc/udf_sources new file mode 100644 index 00000000..624862c5 --- /dev/null +++ b/src/libcdio/udf/.msvc/udf_sources @@ -0,0 +1,20 @@ +TARGETNAME=udf +TARGETTYPE=LIBRARY + +INCLUDES=$(DDK_INC_PATH);.;..;..\driver;..\..\msvc-missing +LIBCDIO_DEFINES = /DHAVE_CONFIG_H /D_OFF_T_DEFINED /D_off_t=__int64 /Doff_t=_off_t /D_FILE_OFFSET_BITS=64 +C_DEFINES=$(C_DEFINES) $(LIBCDIO_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED + +!IFNDEF MSC_WARNING_LEVEL +MSC_WARNING_LEVEL=/W3 +!ENDIF +USE_MSVCRT=1 + +TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ + $(SDK_LIB_PATH)\user32.lib + +SOURCES=udf.c \ + udf_file.c \ + udf_fs.c \ + udf_time.c \ + filemode.c \ No newline at end of file diff --git a/src/libcdio/udf/Makefile.am b/src/libcdio/udf/Makefile.am new file mode 100644 index 00000000..5e101028 --- /dev/null +++ b/src/libcdio/udf/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libudf.a +libudf_a_SOURCES = udf.c udf_file.c udf_fs.c udf_time.c filemode.c +# Boy do you NOT want to have HAVE_CONFIG_H set before $(AM_CFLAGS) with Clang! +libudf_a_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -I. -I.. -I../driver diff --git a/src/libcdio/udf/Makefile.in b/src/libcdio/udf/Makefile.in new file mode 100644 index 00000000..f5b2592b --- /dev/null +++ b/src/libcdio/udf/Makefile.in @@ -0,0 +1,433 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = src/libcdio/udf +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libudf_a_AR = $(AR) $(ARFLAGS) +libudf_a_LIBADD = +am_libudf_a_OBJECTS = libudf_a-udf.$(OBJEXT) \ + libudf_a-udf_file.$(OBJEXT) libudf_a-udf_fs.$(OBJEXT) \ + libudf_a-udf_time.$(OBJEXT) libudf_a-filemode.$(OBJEXT) +libudf_a_OBJECTS = $(am_libudf_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__depfiles_maybe = +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libudf_a_SOURCES) +ETAGS = etags +CTAGS = ctags +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_LDFLAGS = @AM_LDFLAGS@ +AM_RCFLAGS = @AM_RCFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EXEEXT = @EXEEXT@ +EXESUFFIX = @EXESUFFIX@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +RM = @RM@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +WINDRES = @WINDRES@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LIBRARIES = libudf.a +libudf_a_SOURCES = udf.c udf_file.c udf_fs.c udf_time.c filemode.c +# Boy do you NOT want to have HAVE_CONFIG_H set before $(AM_CFLAGS) with Clang! +libudf_a_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -I. -I.. -I../driver +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps src/libcdio/udf/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps src/libcdio/udf/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libudf.a: $(libudf_a_OBJECTS) $(libudf_a_DEPENDENCIES) + $(AM_V_at)-rm -f libudf.a + $(AM_V_AR)$(libudf_a_AR) libudf.a $(libudf_a_OBJECTS) $(libudf_a_LIBADD) + $(AM_V_at)$(RANLIB) libudf.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC) @AM_BACKSLASH@ + $(COMPILE) -c $< + +.c.obj: + $(AM_V_CC) @AM_BACKSLASH@ + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +libudf_a-udf.o: udf.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf.o `test -f 'udf.c' || echo '$(srcdir)/'`udf.c + +libudf_a-udf.obj: udf.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf.obj `if test -f 'udf.c'; then $(CYGPATH_W) 'udf.c'; else $(CYGPATH_W) '$(srcdir)/udf.c'; fi` + +libudf_a-udf_file.o: udf_file.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf_file.o `test -f 'udf_file.c' || echo '$(srcdir)/'`udf_file.c + +libudf_a-udf_file.obj: udf_file.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf_file.obj `if test -f 'udf_file.c'; then $(CYGPATH_W) 'udf_file.c'; else $(CYGPATH_W) '$(srcdir)/udf_file.c'; fi` + +libudf_a-udf_fs.o: udf_fs.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf_fs.o `test -f 'udf_fs.c' || echo '$(srcdir)/'`udf_fs.c + +libudf_a-udf_fs.obj: udf_fs.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf_fs.obj `if test -f 'udf_fs.c'; then $(CYGPATH_W) 'udf_fs.c'; else $(CYGPATH_W) '$(srcdir)/udf_fs.c'; fi` + +libudf_a-udf_time.o: udf_time.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf_time.o `test -f 'udf_time.c' || echo '$(srcdir)/'`udf_time.c + +libudf_a-udf_time.obj: udf_time.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-udf_time.obj `if test -f 'udf_time.c'; then $(CYGPATH_W) 'udf_time.c'; else $(CYGPATH_W) '$(srcdir)/udf_time.c'; fi` + +libudf_a-filemode.o: filemode.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-filemode.o `test -f 'filemode.c' || echo '$(srcdir)/'`filemode.c + +libudf_a-filemode.obj: filemode.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libudf_a_CFLAGS) $(CFLAGS) -c -o libudf_a-filemode.obj `if test -f 'filemode.c'; then $(CYGPATH_W) 'filemode.c'; else $(CYGPATH_W) '$(srcdir)/filemode.c'; fi` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcdio/udf/filemode.c b/src/libcdio/udf/filemode.c new file mode 100644 index 00000000..f24e25f5 --- /dev/null +++ b/src/libcdio/udf/filemode.c @@ -0,0 +1,200 @@ +/* + filemode.c -- make a string describing file modes + + Copyright (C) 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 1985, 1990, 1993, 1998-2000 Free Software Foundation, Inc. + + 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 3 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, see . +*/ + +#if HAVE_CONFIG_H +# include +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#include +#include "filemode.h" + + +/* Set the 's' and 't' flags in file attributes string CHARS, + according to the file mode BITS. */ + +static void +setst (mode_t bits, char *chars) +{ +#ifdef S_ISUID + if (bits & S_ISUID) + { + if (chars[3] != 'x') + /* Set-uid, but not executable by owner. */ + chars[3] = 'S'; + else + chars[3] = 's'; + } +#endif +#ifdef S_ISGID + if (bits & S_ISGID) + { + if (chars[6] != 'x') + /* Set-gid, but not executable by group. */ + chars[6] = 'S'; + else + chars[6] = 's'; + } +#endif +#ifdef S_ISVTX + if (bits & S_ISVTX) + { + if (chars[9] != 'x') + /* Sticky, but not executable by others. */ + chars[9] = 'T'; + else + chars[9] = 't'; + } +#endif +} + +/* Return a character indicating the type of file described by + file mode BITS: + 'd' for directories + 'D' for doors + 'b' for block special files + 'c' for character special files + 'n' for network special files + 'm' for multiplexor files + 'M' for an off-line (regular) file + 'l' for symbolic links + 's' for sockets + 'p' for fifos + 'C' for contigous data files + '-' for regular files + '?' for any other file type. */ + +static char +ftypelet (mode_t bits) +{ +#ifdef S_ISBLK + if (S_ISBLK (bits)) + return 'b'; +#endif + if (S_ISCHR (bits)) + return 'c'; + if (S_ISDIR (bits)) + return 'd'; + if (S_ISREG (bits)) + return '-'; +#ifdef S_ISFIFO + if (S_ISFIFO (bits)) + return 'p'; +#endif +#ifdef S_ISLNK + if (S_ISLNK (bits)) + return 'l'; +#endif +#ifdef S_ISSOCK + if (S_ISSOCK (bits)) + return 's'; +#endif +#ifdef S_ISMPC + if (S_ISMPC (bits)) + return 'm'; +#endif +#ifdef S_ISNWK + if (S_ISNWK (bits)) + return 'n'; +#endif +#ifdef S_ISDOOR + if (S_ISDOOR (bits)) + return 'D'; +#endif +#ifdef S_ISCTG + if (S_ISCTG (bits)) + return 'C'; +#endif + + /* The following two tests are for Cray DMF (Data Migration + Facility), which is a HSM file system. A migrated file has a + `st_dm_mode' that is different from the normal `st_mode', so any + tests for migrated files should use the former. */ + +#ifdef S_ISOFD + if (S_ISOFD (bits)) + /* off line, with data */ + return 'M'; +#endif +#ifdef S_ISOFL + /* off line, with no data */ + if (S_ISOFL (bits)) + return 'M'; +#endif + return '?'; +} + +/*! udf_mode_string - fill in string STR with an ls-style ASCII + representation of the st_mode field of file stats block STATP. + 10 characters are stored in STR; no terminating null is added. + The characters stored in STR are: + + 0 File type. 'd' for directory, 'c' for character + special, 'b' for block special, 'm' for multiplex, + 'l' for symbolic link, 's' for socket, 'p' for fifo, + '-' for regular, '?' for any other file type + + 1 'r' if the owner may read, '-' otherwise. + + 2 'w' if the owner may write, '-' otherwise. + + 3 'x' if the owner may execute, 's' if the file is + set-user-id, '-' otherwise. + 'S' if the file is set-user-id, but the execute + bit isn't set. + + 4 'r' if group members may read, '-' otherwise. + + 5 'w' if group members may write, '-' otherwise. + + 6 'x' if group members may execute, 's' if the file is + set-group-id, '-' otherwise. + 'S' if it is set-group-id but not executable. + + 7 'r' if any user may read, '-' otherwise. + + 8 'w' if any user may write, '-' otherwise. + + 9 'x' if any user may execute, 't' if the file is "sticky" + (will be retained in swap space after execution), '-' + otherwise. + 'T' if the file is sticky but not executable. */ + +char * +udf_mode_string (mode_t i_mode, char *psz_str) +{ + psz_str[ 0] = ftypelet (i_mode); + psz_str[ 1] = i_mode & S_IRUSR ? 'r' : '-'; + psz_str[ 2] = i_mode & S_IWUSR ? 'w' : '-'; + psz_str[ 3] = i_mode & S_IXUSR ? 'x' : '-'; + psz_str[ 4] = i_mode & S_IRGRP ? 'r' : '-'; + psz_str[ 5] = i_mode & S_IWGRP ? 'w' : '-'; + psz_str[ 6] = i_mode & S_IXGRP ? 'x' : '-'; + psz_str[ 7] = i_mode & S_IROTH ? 'r' : '-'; + psz_str[ 8] = i_mode & S_IWOTH ? 'w' : '-'; + psz_str[ 9] = i_mode & S_IXOTH ? 'x' : '-'; + psz_str[10] = '\0'; + setst (i_mode, psz_str); + return psz_str; +} diff --git a/src/libcdio/udf/udf.c b/src/libcdio/udf/udf.c new file mode 100644 index 00000000..42cb8a5e --- /dev/null +++ b/src/libcdio/udf/udf.c @@ -0,0 +1,127 @@ +/* + Copyright (C) 2005, 2008, 2010 Rocky Bernstein + + 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 3 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, see . +*/ +/* Access routines */ + +/* udf_private.h has to come first else _FILE_OFFSET_BITS are redefined in + say opensolaris. */ +#include "udf_private.h" +#include +#include "filemode.h" + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_SYS_STAT_H +# include +#endif + +/** The below variables are trickery to force enum symbol values to be + recorded in debug symbol tables. They are used to allow one to refer + to the enumeration value names in the typedefs above in a debugger + and debugger expressions +*/ +tag_id_t debug_tagid; +file_characteristics_t debug_file_characteristics; +icbtag_file_type_enum_t debug_icbtag_file_type_enum; +icbtag_flag_enum_t debug_flag_enum; +ecma_167_enum1_t debug_ecma_167_enum1; +ecma_167_timezone_enum_t debug_ecma_167_timezone_enum; +udf_enum1_t debug_udf_enum1; + + +/*! + Returns POSIX mode bitstring for a given file. +*/ +mode_t +udf_get_posix_filemode(const udf_dirent_t *p_udf_dirent) +{ + udf_file_entry_t udf_fe; + mode_t mode = 0; + + if (udf_get_file_entry(p_udf_dirent, &udf_fe)) { + uint32_t i_perms; +#ifdef S_ISUID + uint16_t i_flags; + + i_flags = uint16_from_le(udf_fe.icb_tag.flags); +#endif + i_perms = uint32_from_le(udf_fe.permissions); + + if (i_perms & FE_PERM_U_READ) mode |= S_IRUSR; + if (i_perms & FE_PERM_U_WRITE) mode |= S_IWUSR; + if (i_perms & FE_PERM_U_EXEC) mode |= S_IXUSR; + +#ifdef S_IRGRP + if (i_perms & FE_PERM_G_READ) mode |= S_IRGRP; + if (i_perms & FE_PERM_G_WRITE) mode |= S_IWGRP; + if (i_perms & FE_PERM_G_EXEC) mode |= S_IXGRP; +#endif + +#ifdef S_IROTH + if (i_perms & FE_PERM_O_READ) mode |= S_IROTH; + if (i_perms & FE_PERM_O_WRITE) mode |= S_IWOTH; + if (i_perms & FE_PERM_O_EXEC) mode |= S_IXOTH; +#endif + + switch (udf_fe.icb_tag.file_type) { + case ICBTAG_FILE_TYPE_DIRECTORY: + mode |= S_IFDIR; + break; + case ICBTAG_FILE_TYPE_REGULAR: + mode |= S_IFREG; + break; +#ifdef S_IFLNK + case ICBTAG_FILE_TYPE_SYMLINK: + mode |= S_IFLNK; + break; +#endif + case ICBTAG_FILE_TYPE_CHAR: + mode |= S_IFCHR; + break; +#ifdef S_IFSOCK + case ICBTAG_FILE_TYPE_SOCKET: + mode |= S_IFSOCK; + break; +#endif + case ICBTAG_FILE_TYPE_BLOCK: + mode |= S_IFBLK; + break; + default: ; + }; + +#ifdef S_ISUID + if (i_flags & ICBTAG_FLAG_SETUID) mode |= S_ISUID; + if (i_flags & ICBTAG_FLAG_SETGID) mode |= S_ISGID; + if (i_flags & ICBTAG_FLAG_STICKY) mode |= S_ISVTX; +#endif + } + + return mode; + +} + +/*! + Return the partition number of the the opened udf handle. -1 + Is returned if we have an error. +*/ +int16_t udf_get_part_number(const udf_t *p_udf) +{ + if (!p_udf) return -1; + return p_udf->i_partition; +} + diff --git a/src/libcdio/udf/udf_file.c b/src/libcdio/udf/udf_file.c new file mode 100644 index 00000000..c9b29a33 --- /dev/null +++ b/src/libcdio/udf/udf_file.c @@ -0,0 +1,267 @@ +/* + Copyright (C) 2005, 2006, 2008, 2010 Rocky Bernstein + + 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 3 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, see . +*/ +/* Access routines */ + +/* udf_private.h has to come first else _FILE_OFFSET_BITS are redefined in + say opensolaris. */ +#include "udf_private.h" +#include +#include "udf_fs.h" + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STDIO_H +#include /* Remove when adding cdio/logging.h */ +#endif + +/* Useful defines */ + +#define MIN(a, b) (au.alloc_descs[offset] + +const char * +udf_get_filename(const udf_dirent_t *p_udf_dirent) +{ + if (!p_udf_dirent) return NULL; + if (!p_udf_dirent->psz_name) return ".."; + return p_udf_dirent->psz_name; +} + +/* Copy an UDF File Entry into a Directory Entry structure. */ +bool +udf_get_file_entry(const udf_dirent_t *p_udf_dirent, + /*out*/ udf_file_entry_t *p_udf_fe) +{ + if (!p_udf_dirent) return false; + memcpy(p_udf_fe, &p_udf_dirent->fe, sizeof(udf_file_entry_t)); + return true; +} + +/*! + Return the file id descriptor of the given file. +*/ +bool udf_get_fileid_descriptor(const udf_dirent_t *p_udf_dirent, + /*out*/ udf_fileid_desc_t *p_udf_fid) +{ + + if (!p_udf_dirent) return false; + if (!p_udf_dirent->fid) { + /* FIXME do something about trying to get the descriptor. */ + return false; + } + memcpy(p_udf_fid, p_udf_dirent->fid, sizeof(udf_fileid_desc_t)); + return true; +} + + +/*! + Return the number of hard links of the file. Return 0 if error. +*/ +uint16_t udf_get_link_count(const udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent) { + return uint16_from_le(p_udf_dirent->fe.link_count); + } + return 0; /* Error. Non-error case handled above. */ +} + +/*! + Return the file length the file. Return 2147483647L if error. +*/ +uint64_t udf_get_file_length(const udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent) { + return uint64_from_le(p_udf_dirent->fe.info_len); + } + return 2147483647L; /* Error. Non-error case handled above. */ +} + +/*! + Return true if the file is a directory. +*/ +bool +udf_is_dir(const udf_dirent_t *p_udf_dirent) +{ + return p_udf_dirent->b_dir; +} + +/* + * Translate a file offset into a logical block and then into a physical + * block. + */ +static lba_t +offset_to_lba(const udf_dirent_t *p_udf_dirent, off_t i_offset, + /*out*/ lba_t *pi_lba, /*out*/ uint32_t *pi_max_size) +{ + udf_t *p_udf = p_udf_dirent->p_udf; + const udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) + &p_udf_dirent->fe; + const udf_icbtag_t *p_icb_tag = &p_udf_fe->icb_tag; + const uint16_t strat_type= uint16_from_le(p_icb_tag->strat_type); + + if (i_offset < 0) { + cdio_warn("Negative offset value"); + return CDIO_INVALID_LBA; + } + + switch (strat_type) { + case 4096: + cdio_warn("Cannot deal with strategy4096 yet!"); + return CDIO_INVALID_LBA; + break; + case ICBTAG_STRATEGY_TYPE_4: + { + off_t icblen = 0; + uint64_t lsector; + int ad_offset, ad_num = 0; + uint16_t addr_ilk = uint16_from_le(p_icb_tag->flags&ICBTAG_FLAG_AD_MASK); + + switch (addr_ilk) { + case ICBTAG_FLAG_AD_SHORT: + { + udf_short_ad_t *p_icb; + /* + * The allocation descriptor field is filled with short_ad's. + * If the offset is beyond the current extent, look for the + * next extent. + */ + do { + i_offset -= icblen; + ad_offset = sizeof(udf_short_ad_t) * ad_num; + if (ad_offset > uint32_from_le(p_udf_fe->i_alloc_descs)) { + cdio_warn("File offset out of bounds"); + return CDIO_INVALID_LBA; + } + p_icb = (udf_short_ad_t *) + GETICB( uint32_from_le(p_udf_fe->i_extended_attr) + + ad_offset ); + icblen = p_icb->len; + ad_num++; + } while(i_offset >= icblen); + + lsector = (i_offset / UDF_BLOCKSIZE) + p_icb->pos; + + *pi_max_size = p_icb->len; + } + break; + case ICBTAG_FLAG_AD_LONG: + { + /* + * The allocation descriptor field is filled with long_ad's + * If the i_offset is beyond the current extent, look for the + * next extent. + */ + udf_long_ad_t *p_icb; + do { + i_offset -= icblen; + ad_offset = sizeof(udf_long_ad_t) * ad_num; + if (ad_offset > uint32_from_le(p_udf_fe->i_alloc_descs)) { + cdio_warn("File offset out of bounds"); + return CDIO_INVALID_LBA; + } + p_icb = (udf_long_ad_t *) + GETICB( uint32_from_le(p_udf_fe->i_extended_attr) + + ad_offset ); + icblen = p_icb->len; + ad_num++; + } while(i_offset >= icblen); + + lsector = (i_offset / UDF_BLOCKSIZE) + + uint32_from_le(((udf_long_ad_t *)(p_icb))->loc.lba); + + *pi_max_size = p_icb->len; + } + break; + case ICBTAG_FLAG_AD_IN_ICB: + /* + * This type means that the file *data* is stored in the + * allocation descriptor field of the file entry. + */ + *pi_max_size = 0; + cdio_warn("Don't know how to data in ICB handle yet"); + return CDIO_INVALID_LBA; + case ICBTAG_FLAG_AD_EXTENDED: + cdio_warn("Don't know how to handle extended addresses yet"); + return CDIO_INVALID_LBA; + default: + cdio_warn("Unsupported allocation descriptor %d", addr_ilk); + return CDIO_INVALID_LBA; + } + + *pi_lba = (lba_t)lsector + p_udf->i_part_start; + if (*pi_lba < 0) { + cdio_warn("Negative LBA value"); + return CDIO_INVALID_LBA; + } + return *pi_lba; + } + default: + cdio_warn("Unknown strategy type %d", strat_type); + return DRIVER_OP_ERROR; + } +} + +/** + Attempts to read up to count bytes from UDF directory entry + p_udf_dirent into the buffer starting at buf. buf should be a + multiple of UDF_BLOCKSIZE bytes. Reading continues after the point + at which we last read or from the beginning the first time. + + If count is zero, read() returns zero and has no other results. If + count is greater than SSIZE_MAX, the result is unspecified. + + It is the caller's responsibility to ensure that count is less + than the number of blocks recorded via p_udf_dirent. + + If there is an error, cast the result to driver_return_code_t for + the specific error code. +*/ +ssize_t +udf_read_block(const udf_dirent_t *p_udf_dirent, void * buf, size_t count) +{ + if (count == 0) return 0; + else { + driver_return_code_t ret; + uint32_t i_max_size=0; + udf_t *p_udf = p_udf_dirent->p_udf; + lba_t i_lba = offset_to_lba(p_udf_dirent, p_udf->i_position, &i_lba, + &i_max_size); + if (i_lba != CDIO_INVALID_LBA) { + uint32_t i_max_blocks = CEILING(i_max_size, UDF_BLOCKSIZE); + if ( i_max_blocks < count ) { + cdio_warn("read count %u is larger than %u extent size.", + (unsigned int)count, i_max_blocks); + cdio_warn("read count truncated to %u", (unsigned int)count); + count = i_max_blocks; + } + ret = udf_read_sectors(p_udf, buf, i_lba, count); + if (DRIVER_OP_SUCCESS == ret) { + ssize_t i_read_len = MIN(i_max_size, count * UDF_BLOCKSIZE); + p_udf->i_position += i_read_len; + return i_read_len; + } + return ret; + } else { + return DRIVER_OP_ERROR; + } + } +} diff --git a/src/libcdio/udf/udf_fs.c b/src/libcdio/udf/udf_fs.c new file mode 100644 index 00000000..98830cf7 --- /dev/null +++ b/src/libcdio/udf/udf_fs.c @@ -0,0 +1,706 @@ +/* + Copyright (C) 2005, 2006, 2008, 2011 Rocky Bernstein + + 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 3 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, see . +*/ +/* + * Portions copyright (c) 2001, 2002 Scott Long + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STDLIB_H +# include +#endif + +/* These definitions are also to make debugging easy. Note that they + have to come *before* #include which sets + #defines for these. +*/ +const char VSD_STD_ID_BEA01[] = {'B', 'E', 'A', '0', '1'}; +const char VSD_STD_ID_BOOT2[] = {'B', 'O', 'O', 'T', '2'}; +const char VSD_STD_ID_CD001[] = {'C', 'D', '0', '0', '1'}; +const char VSD_STD_ID_CDW01[] = {'C', 'D', 'W', '0', '2'}; +const char VSD_STD_ID_NSR03[] = {'N', 'S', 'R', '0', '3'}; +const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'}; + +#include +#include "udf_private.h" +#include "udf_fs.h" +#include "cdio_assert.h" + +/* + * The UDF specs are pretty clear on how each data structure is made + * up, but not very clear on how they relate to each other. Here is + * the skinny... This demostrates a filesystem with one file in the + * root directory. Subdirectories are treated just as normal files, + * but they have File Id Descriptors of their children as their file + * data. As for the Anchor Volume Descriptor Pointer, it can exist in + * two of the following three places: sector 256, sector n (the max + * sector of the disk), or sector n - 256. It's a pretty good bet + * that one will exist at sector 256 though. One caveat is unclosed + * CD media. For that, sector 256 cannot be written, so the Anchor + * Volume Descriptor Pointer can exist at sector 512 until the media + * is closed. + * + * Sector: + * 256: + * n: Anchor Volume Descriptor Pointer + * n - 256: | + * | + * |-->Main Volume Descriptor Sequence + * | | + * | | + * | |-->Logical Volume Descriptor + * | | + * |-->Partition Descriptor | + * | | + * | | + * |-->Fileset Descriptor + * | + * | + * |-->Root Dir File Entry + * | + * | + * |-->File data: + * File Id Descriptor + * | + * | + * |-->File Entry + * | + * | + * |-->File data + */ + +static udf_dirent_t * +udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t *p_udf, + const char *psz_name, bool b_dir, bool b_parent); + +/** + * Check the descriptor tag for both the correct id and correct checksum. + * Return zero if all is good, -1 if not. + */ +int +udf_checktag(const udf_tag_t *p_tag, udf_Uint16_t tag_id) +{ + uint8_t *itag; + uint8_t i; + uint8_t cksum = 0; + + itag = (uint8_t *)p_tag; + + if (p_tag->id != tag_id) + return -1; + + for (i = 0; i < 15; i++) + cksum = cksum + itag[i]; + cksum = cksum - itag[4]; + + if (cksum == p_tag->cksum) + return 0; + + return -1; +} + +bool +udf_get_lba(const udf_file_entry_t *p_udf_fe, + /*out*/ uint32_t *start, /*out*/ uint32_t *end) +{ + if (! p_udf_fe->i_alloc_descs) + return false; + + switch (p_udf_fe->icb_tag.flags & ICBTAG_FLAG_AD_MASK) { + case ICBTAG_FLAG_AD_SHORT: + { + /* The allocation descriptor field is filled with short_ad's. */ + udf_short_ad_t *p_ad = (udf_short_ad_t *) + (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr); + + *start = uint32_from_le(p_ad->pos); + *end = *start + + ((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE; + return true; + } + break; + case ICBTAG_FLAG_AD_LONG: + { + /* The allocation descriptor field is filled with long_ad's */ + udf_long_ad_t *p_ad = (udf_long_ad_t *) + (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr); + + *start = uint32_from_le(p_ad->loc.lba); /* ignore partition number */ + *end = *start + + ((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE; + return true; + } + break; + case ICBTAG_FLAG_AD_EXTENDED: + { + udf_ext_ad_t *p_ad = (udf_ext_ad_t *) + (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr); + + *start = uint32_from_le(p_ad->ext_loc.lba); /* ignore partition number */ + *end = *start + + ((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE; + return true; + } + break; + default: + return false; + } + return false; +} + +#define udf_PATH_DELIMITERS "/\\" + +/* Searches p_udf_dirent a directory entry called psz_token. + Note p_udf_dirent is continuously updated. If the entry is + not found p_udf_dirent is useless and thus the caller should + not use it afterwards. +*/ +static +udf_dirent_t * +udf_ff_traverse(udf_dirent_t *p_udf_dirent, char *psz_token) +{ + while (udf_readdir(p_udf_dirent)) { + if (strcmp(psz_token, p_udf_dirent->psz_name) == 0) { + char *next_tok = strtok(NULL, udf_PATH_DELIMITERS); + + if (!next_tok) + return p_udf_dirent; /* found */ + else if (p_udf_dirent->b_dir) { + udf_dirent_t * p_udf_dirent2 = udf_opendir(p_udf_dirent); + + if (p_udf_dirent2) { + udf_dirent_t * p_udf_dirent3 = + udf_ff_traverse(p_udf_dirent2, next_tok); + + /* if p_udf_dirent3 is null p_udf_dirent2 is free'd. */ + return p_udf_dirent3; + } + } + } + } + free(p_udf_dirent->psz_name); + return NULL; +} + +/* FIXME! */ +#define udf_MAX_PATHLEN 2048 + +udf_dirent_t * +udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name) +{ + udf_dirent_t *p_udf_file = NULL; + + if (p_udf_root) { + char tokenline[udf_MAX_PATHLEN]; + char *psz_token; + + /* file position must be reset when accessing a new file */ + p_udf_root->p_udf->i_position = 0; + + strncpy(tokenline, psz_name, udf_MAX_PATHLEN); + psz_token = strtok(tokenline, udf_PATH_DELIMITERS); + if (psz_token) { + /*** FIXME??? udf_dirent can be variable size due to the + extended attributes and descriptors. Given that, is this + correct? + */ + udf_dirent_t *p_udf_dirent = + udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf, + p_udf_root->psz_name, p_udf_root->b_dir, + p_udf_root->b_parent); + p_udf_file = udf_ff_traverse(p_udf_dirent, psz_token); + udf_dirent_free(p_udf_dirent); + } + else if ( 0 == strncmp("/", psz_name, sizeof("/")) ) { + return udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf, + p_udf_root->psz_name, p_udf_root->b_dir, + p_udf_root->b_parent); + } + } + return p_udf_file; +} + +/* Convert unicode16 to 8-bit char by dripping MSB. + Wonder if iconv can be used here +*/ +static int +unicode16_decode( const uint8_t *data, int i_len, char *target ) +{ + int p = 1, i = 0; + + if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { + if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ + if( p < i_len ) { + target[ i++ ] = data[ p++ ]; + } + } while( p < i_len ); + + target[ i ] = '\0'; + return 0; +} + + +static udf_dirent_t * +udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t *p_udf, + const char *psz_name, bool b_dir, bool b_parent) +{ + udf_dirent_t *p_udf_dirent = (udf_dirent_t *) + calloc(1, sizeof(udf_dirent_t)); + if (!p_udf_dirent) return NULL; + + p_udf_dirent->psz_name = strdup(psz_name); + p_udf_dirent->b_dir = b_dir; + p_udf_dirent->b_parent = b_parent; + p_udf_dirent->p_udf = p_udf; + p_udf_dirent->i_part_start = p_udf->i_part_start; + p_udf_dirent->dir_left = uint64_from_le(p_udf_fe->info_len); + + memcpy(&(p_udf_dirent->fe), p_udf_fe, + sizeof(udf_file_entry_t)); + udf_get_lba( p_udf_fe, &(p_udf_dirent->i_loc), + &(p_udf_dirent->i_loc_end) ); + return p_udf_dirent; +} + +/*! + Seek to a position i_start and then read i_blocks. Number of blocks read is + returned. One normally expects the return to be equal to i_blocks. +*/ +driver_return_code_t +udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start, + long i_blocks) +{ + driver_return_code_t ret; + long i_read; + off_t i_byte_offset; + + if (!p_udf) return 0; + /* Without the cast, i_start * UDF_BLOCKSIZE may be evaluated as 32 bit */ + i_byte_offset = ((off_t)i_start) * UDF_BLOCKSIZE; + /* Since we're using SEEK_SET, the value must be positive */ + if (i_byte_offset < 0) { + if (sizeof(off_t) <= 4) /* probably missing LFS */ + cdio_warn("Large File Support is required to access streams of 2 GB or more"); + return DRIVER_OP_BAD_PARAMETER; + } + + if (p_udf->b_stream) { + ret = cdio_stream_seek (p_udf->stream, i_byte_offset, SEEK_SET); + if (DRIVER_OP_SUCCESS != ret) return ret; + i_read = cdio_stream_read (p_udf->stream, ptr, UDF_BLOCKSIZE, i_blocks); + if (i_read) return DRIVER_OP_SUCCESS; + return DRIVER_OP_ERROR; + } else { + return cdio_read_data_sectors(p_udf->cdio, ptr, i_start, UDF_BLOCKSIZE, + i_blocks); + } +} + +/*! + Open an UDF for reading. Maybe in the future we will have + a mode. NULL is returned on error. + + Caller must free result - use udf_close for that. +*/ +udf_t * +udf_open (const char *psz_path) +{ + udf_t *p_udf = (udf_t *) calloc(1, sizeof(udf_t)) ; + uint8_t data[UDF_BLOCKSIZE]; + + if (!p_udf) return NULL; + + /* Sanity check */ + cdio_assert(sizeof(udf_file_entry_t) == UDF_BLOCKSIZE); + + p_udf->cdio = cdio_open(psz_path, DRIVER_UNKNOWN); + if (!p_udf->cdio) { + /* Not a CD-ROM drive or CD Image. Maybe it's a UDF file not + encapsulated as a CD-ROM Image (e.g. often .UDF or (sic) .ISO) + */ + p_udf->stream = cdio_stdio_new( psz_path ); + if (!p_udf->stream) + goto error; + p_udf->b_stream = true; + } + + /* + * Look for an Anchor Volume Descriptor Pointer at sector 256. + */ + if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, &data, 256, 1) ) + goto error; + + memcpy(&(p_udf->anchor_vol_desc_ptr), &data, sizeof(anchor_vol_desc_ptr_t)); + + if (udf_checktag((udf_tag_t *)&(p_udf->anchor_vol_desc_ptr), TAGID_ANCHOR)) + goto error; + + /* + * Then try to find a reference to a Primary Volume Descriptor. + */ + { + const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr; + const uint32_t mvds_start = + uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc); + const uint32_t mvds_end = mvds_start + + (uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE; + + uint32_t i_lba; + + for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) { + + udf_pvd_t *p_pvd = (udf_pvd_t *) &data; + + if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_pvd, i_lba, 1) ) + goto error; + + if (!udf_checktag(&p_pvd->tag, TAGID_PRI_VOL)) { + p_udf->pvd_lba = i_lba; + break; + } + + } + + /* + * If we couldn't find a reference, bail out. + */ + if (i_lba == mvds_end) + goto error; + } + + return p_udf; + + error: + cdio_stdio_destroy(p_udf->stream); + free(p_udf); + return NULL; +} + +/** + * Gets the Volume Identifier string, in 8bit unicode (latin-1) + * psz_volid, place to put the string + * i_volid_size, size of the buffer volid points to + * returns the size of buffer needed for all data + */ +int +udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid) +{ + uint8_t data[UDF_BLOCKSIZE]; + const udf_pvd_t *p_pvd = (udf_pvd_t *) &data; + unsigned int volid_len; + + /* get primary volume descriptor */ + if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, p_udf->pvd_lba, 1) ) + return 0; + + volid_len = p_pvd->vol_ident[UDF_VOLID_SIZE-1]; + if(volid_len > UDF_VOLID_SIZE-1) { + /* this field is only UDF_VOLID_SIZE bytes something is wrong */ + volid_len = UDF_VOLID_SIZE-1; + } + if(i_volid > volid_len) { + i_volid = volid_len; + } + unicode16_decode((uint8_t *) p_pvd->vol_ident, i_volid, psz_volid); + + return volid_len; +} + +/** + * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) + * WARNING This is not a null terminated string + * volsetid, place to put the data + * volsetid_size, size of the buffer volsetid points to + * the buffer should be >=128 bytes to store the whole volumesetidentifier + * returns the size of the available volsetid information (128) + * or 0 on error + */ +int +udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid, + unsigned int i_volsetid) +{ + uint8_t data[UDF_BLOCKSIZE]; + const udf_pvd_t *p_pvd = (udf_pvd_t *) &data; + + /* get primary volume descriptor */ + if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, p_udf->pvd_lba, 1) ) + return 0; + + if (i_volsetid > UDF_VOLSET_ID_SIZE) { + i_volsetid = UDF_VOLSET_ID_SIZE; + } + + memcpy(volsetid, p_pvd->volset_id, i_volsetid); + + return UDF_VOLSET_ID_SIZE; +} + +/*! + Get the root in p_udf. If b_any_partition is false then + the root must be in the given partition. + NULL is returned if the partition is not found or a root is not found or + there is on error. + + Caller must free result - use udf_dirent_free for that. +*/ +udf_dirent_t * +udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition) +{ + const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr; + const uint32_t mvds_start = + uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc); + const uint32_t mvds_end = mvds_start + + (uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE; + uint32_t i_lba; + uint8_t data[UDF_BLOCKSIZE]; + + /* + Now we have the joy of finding the Partition Descriptor and the + Logical Volume Descriptor for the Main Volume Descriptor + Sequence. Once we've got that, we use the Logical Volume + Descriptor to get a Fileset Descriptor and that has the Root + Directory File Entry. + */ + for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) { + uint8_t data2[UDF_BLOCKSIZE]; + + partition_desc_t *p_partition = (partition_desc_t *) &data2; + + if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_partition, i_lba, 1) ) + return NULL; + + if (!udf_checktag(&p_partition->tag, TAGID_PARTITION)) { + const partition_num_t i_partition_check + = uint16_from_le(p_partition->number); + if (b_any_partition || i_partition_check == i_partition) { + /* Squirrel away some data regarding partition */ + p_udf->i_partition = uint16_from_le(p_partition->number); + p_udf->i_part_start = uint32_from_le(p_partition->start_loc); + if (p_udf->lvd_lba) break; + } + } else if (!udf_checktag(&p_partition->tag, TAGID_LOGVOL)) { + /* Get fileset descriptor */ + logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data2; + bool b_valid = + UDF_BLOCKSIZE == uint32_from_le(p_logvol->logical_blocksize); + + if (b_valid) { + p_udf->lvd_lba = i_lba; + p_udf->fsd_offset = + uint32_from_le(p_logvol->lvd_use.fsd_loc.loc.lba); + if (p_udf->i_part_start) break; + } + } + } + if (p_udf->lvd_lba && p_udf->i_part_start) { + udf_fsd_t *p_fsd = (udf_fsd_t *) &data; + + driver_return_code_t ret = + udf_read_sectors(p_udf, p_fsd, p_udf->i_part_start + p_udf->fsd_offset, + 1); + + if (DRIVER_OP_SUCCESS == ret && !udf_checktag(&p_fsd->tag, TAGID_FSD)) { + udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) &data; + const uint32_t parent_icb = uint32_from_le(p_fsd->root_icb.loc.lba); + + /* Check partition numbers match of last-read block? */ + + ret = udf_read_sectors(p_udf, p_udf_fe, + p_udf->i_part_start + parent_icb, 1); + if (ret == DRIVER_OP_SUCCESS && + !udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) { + + /* Check partition numbers match of last-read block? */ + + /* We win! - Save root directory information. */ + return udf_new_dirent(p_udf_fe, p_udf, "/", true, false ); + } + } + } + + return NULL; +} + +#define free_and_null(x) \ + free(x); \ + x=NULL + +/*! + Close UDF and free resources associated with p_udf. +*/ +bool +udf_close (udf_t *p_udf) +{ + if (!p_udf) return true; + if (p_udf->b_stream) { + cdio_stdio_destroy(p_udf->stream); + } else { + cdio_destroy(p_udf->cdio); + } + + /* Get rid of root directory if allocated. */ + + free_and_null(p_udf); + return true; +} + +udf_dirent_t * +udf_opendir(const udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent->b_dir && !p_udf_dirent->b_parent && p_udf_dirent->fid) { + udf_t *p_udf = p_udf_dirent->p_udf; + udf_file_entry_t udf_fe; + + driver_return_code_t i_ret = + udf_read_sectors(p_udf, &udf_fe, p_udf->i_part_start + + p_udf_dirent->fid->icb.loc.lba, 1); + + if (DRIVER_OP_SUCCESS == i_ret + && !udf_checktag(&udf_fe.tag, TAGID_FILE_ENTRY)) { + + if (ICBTAG_FILE_TYPE_DIRECTORY == udf_fe.icb_tag.file_type) { + udf_dirent_t *p_udf_dirent_new = + udf_new_dirent(&udf_fe, p_udf, p_udf_dirent->psz_name, true, true); + return p_udf_dirent_new; + } + } + } + return NULL; +} + +udf_dirent_t * +udf_readdir(udf_dirent_t *p_udf_dirent) +{ + udf_t *p_udf; + + if (p_udf_dirent->dir_left <= 0) { + udf_dirent_free(p_udf_dirent); + return NULL; + } + + /* file position must be reset when accessing a new file */ + p_udf = p_udf_dirent->p_udf; + p_udf->i_position = 0; + + if (p_udf_dirent->fid) { + /* advance to next File Identifier Descriptor */ + /* FIXME: need to advance file entry (fe) as well. */ + uint32_t ofs = 4 * + ((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->i_imp_use + + p_udf_dirent->fid->i_file_id + 3) / 4); + + p_udf_dirent->fid = + (udf_fileid_desc_t *)((uint8_t *)p_udf_dirent->fid + ofs); + } + + if (!p_udf_dirent->fid) { + uint32_t i_sectors = + (p_udf_dirent->i_loc_end - p_udf_dirent->i_loc + 1); + uint32_t size = UDF_BLOCKSIZE * i_sectors; + driver_return_code_t i_ret; + + if (!p_udf_dirent->sector) + p_udf_dirent->sector = (uint8_t*) malloc(size); + i_ret = udf_read_sectors(p_udf, p_udf_dirent->sector, + p_udf_dirent->i_part_start+p_udf_dirent->i_loc, + i_sectors); + if (DRIVER_OP_SUCCESS == i_ret) + p_udf_dirent->fid = (udf_fileid_desc_t *) p_udf_dirent->sector; + else + p_udf_dirent->fid = NULL; + } + + if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID)) + { + uint32_t ofs = + 4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->i_imp_use + + p_udf_dirent->fid->i_file_id + 3) / 4); + + p_udf_dirent->dir_left -= ofs; + p_udf_dirent->b_dir = + (p_udf_dirent->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0; + p_udf_dirent->b_parent = + (p_udf_dirent->fid->file_characteristics & UDF_FILE_PARENT) != 0; + + { + const unsigned int i_len = p_udf_dirent->fid->i_file_id; + + if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start + + p_udf_dirent->fid->icb.loc.lba, 1)) + return NULL; + + if (strlen(p_udf_dirent->psz_name) < i_len) + p_udf_dirent->psz_name = (char *) + realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1); + + unicode16_decode(p_udf_dirent->fid->u.imp_use + + p_udf_dirent->fid->i_imp_use, + i_len, p_udf_dirent->psz_name); + } + return p_udf_dirent; + } + return NULL; +} + +/*! + free free resources associated with p_udf_dirent. +*/ +bool +udf_dirent_free(udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent) { + p_udf_dirent->fid = NULL; + free_and_null(p_udf_dirent->psz_name); + free_and_null(p_udf_dirent->sector); + free_and_null(p_udf_dirent); + } + return true; +} diff --git a/src/libcdio/udf/udf_fs.h b/src/libcdio/udf/udf_fs.h new file mode 100644 index 00000000..80e99554 --- /dev/null +++ b/src/libcdio/udf/udf_fs.h @@ -0,0 +1,39 @@ +/* + $Id: udf_fs.h,v 1.3 2008/04/18 16:02:10 karl Exp $ + + Copyright (C) 2006, 2008 Rocky Bernstein + + 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 3 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, see . +*/ + +#ifndef __CDIO_UDF_FS_H__ +#define __CDIO_UDF_FS_H__ + +#include +/** + * Check the descriptor tag for both the correct id and correct checksum. + * Return zero if all is good, -1 if not. + */ +int udf_checktag(const udf_tag_t *p_tag, udf_Uint16_t tag_id); + +#endif /* __CDIO_UDF_FS_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/udf/udf_private.h b/src/libcdio/udf/udf_private.h new file mode 100644 index 00000000..cfc40763 --- /dev/null +++ b/src/libcdio/udf/udf_private.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2005, 2006, 2008, 2011 Rocky Bernstein + + 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 3 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, see . +*/ + +#ifndef __CDIO_UDF_PRIVATE_H__ +#define __CDIO_UDF_PRIVATE_H__ + +#if defined(HAVE_CONFIG_H) && !defined(LIBCDIO_CONFIG_H) && !defined(__CDIO_CONFIG_H__) +# include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#include +#include +#include +#include "_cdio_stdio.h" + +/* Implementation of opaque types */ + +struct udf_s { + bool b_stream; /* Use stream pointer, else use p_cdio */ + off_t i_position; /* Position in file if positive */ + CdioDataSource_t *stream; /* Stream pointer if stream */ + CdIo_t *cdio; /* Cdio pointer if read device */ + anchor_vol_desc_ptr_t anchor_vol_desc_ptr; + uint32_t pvd_lba; /* sector of Primary Volume Descriptor */ + partition_num_t i_partition; /* partition number */ + uint32_t i_part_start; /* start of Partition Descriptor */ + uint32_t lvd_lba; /* sector of Logical Volume Descriptor */ + uint32_t fsd_offset; /* lba of fileset descriptor */ +}; + +#endif /* __CDIO_UDF_PRIVATE_H__ */ + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/libcdio/udf/udf_time.c b/src/libcdio/udf/udf_time.c new file mode 100644 index 00000000..3d8a9f5f --- /dev/null +++ b/src/libcdio/udf/udf_time.c @@ -0,0 +1,254 @@ +/* + Copyright (C) 2005, 2008, 2011 Rocky Bernstein + Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. + + Modified From part of the GNU C Library. + Contributed by Paul Eggert. + + 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 3 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, see . +*/ + +/* Some history from the GNU/Linux kernel from which this is also taken... + dgb 10/02/98: ripped this from glibc source to help convert + timestamps to unix time + + 10/04/98: added new table-based lookup after seeing how ugly the + gnu code is + + blf 09/27/99: ripped out all the old code and inserted new table from + John Brockmeyer (without leap second corrections) + rewrote udf_stamp_to_time and fixed timezone + accounting in udf_timespec_to_stamp. +*/ + +/* + * We don't take into account leap seconds. This may be correct or incorrect. + * For more NIST information (especially dealing with leap seconds), see: + * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +# define __CDIO_CONFIG_H__ 1 +#endif + +#ifdef NEED_TIMEZONEVAR +#define timezonevar 1 +#endif + +#include "udf_private.h" +#include + +/** + Imagine the below enum values as #define'd or constant values + rather than distinct values of an enum. +*/ +enum { + HOURS_PER_DAY = 24, + SECS_PER_MINUTE = 60, + MAX_YEAR_SECONDS = 69, + DAYS_PER_YEAR = 365, /* That is, in most of the years. */ + EPOCH_YEAR = 1970, + SECS_PER_HOUR = (60 * SECS_PER_MINUTE), + SECS_PER_DAY = SECS_PER_HOUR * HOURS_PER_DAY +} debug_udf_time_enum; + +#ifndef __isleap +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +#define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) +#endif + +/* How many days come before each month (0-12). */ +static const unsigned short int __mon_yday[2][13] = + { + /* Normal years. */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, DAYS_PER_YEAR }, + /* Leap years. */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, DAYS_PER_YEAR+1 } + }; + +#define SPY(y,l,s) (SECS_PER_DAY * (DAYS_PER_YEAR*y+l)+s) /* Seconds per year */ + +static time_t year_seconds[MAX_YEAR_SECONDS]= { + /*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0), + /*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0), + /*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0), + /*1982*/ SPY(12, 3,0), SPY(13, 3,0), SPY(14, 3,0), SPY(15, 4,0), + /*1986*/ SPY(16, 4,0), SPY(17, 4,0), SPY(18, 4,0), SPY(19, 5,0), + /*1990*/ SPY(20, 5,0), SPY(21, 5,0), SPY(22, 5,0), SPY(23, 6,0), + /*1994*/ SPY(24, 6,0), SPY(25, 6,0), SPY(26, 6,0), SPY(27, 7,0), + /*1998*/ SPY(28, 7,0), SPY(29, 7,0), SPY(30, 7,0), SPY(31, 8,0), + /*2002*/ SPY(32, 8,0), SPY(33, 8,0), SPY(34, 8,0), SPY(35, 9,0), + /*2006*/ SPY(36, 9,0), SPY(37, 9,0), SPY(38, 9,0), SPY(39,10,0), + /*2010*/ SPY(40,10,0), SPY(41,10,0), SPY(42,10,0), SPY(43,11,0), + /*2014*/ SPY(44,11,0), SPY(45,11,0), SPY(46,11,0), SPY(47,12,0), + /*2018*/ SPY(48,12,0), SPY(49,12,0), SPY(50,12,0), SPY(51,13,0), + /*2022*/ SPY(52,13,0), SPY(53,13,0), SPY(54,13,0), SPY(55,14,0), + /*2026*/ SPY(56,14,0), SPY(57,14,0), SPY(58,14,0), SPY(59,15,0), + /*2030*/ SPY(60,15,0), SPY(61,15,0), SPY(62,15,0), SPY(63,16,0), + /*2034*/ SPY(64,16,0), SPY(65,16,0), SPY(66,16,0), SPY(67,17,0), + /*2038*/ SPY(68,17,0) +}; + +#if defined(HAVE_TIMEZONE_VAR) && !defined(_WIN32) +extern long timezone; +#endif + +time_t * +udf_stamp_to_time(time_t *dest, long int *dest_usec, + const udf_timestamp_t src) +{ + int yday; + uint8_t type = src.type_tz >> 12; + int16_t offset; + + if (type == 1) { + offset = src.type_tz << 4; + /* sign extent offset */ + offset = (offset >> 4); + if (offset == -2047) /* unspecified offset */ + offset = 0; + } + else + offset = 0; + + if ((src.year < EPOCH_YEAR) || + (src.year >= EPOCH_YEAR+MAX_YEAR_SECONDS)) + { + *dest = -1; + *dest_usec = -1; + return NULL; + } + *dest = year_seconds[src.year - EPOCH_YEAR]; + *dest -= offset * SECS_PER_MINUTE; + + yday = ((__mon_yday[__isleap (src.year)] + [src.month-1]) + (src.day-1)); + *dest += src.second + + ( SECS_PER_MINUTE * + ( ( (yday* HOURS_PER_DAY) + src.hour ) * 60 + src.minute ) ); + + *dest_usec = src.microseconds + + (src.centiseconds * 10000) + + (src.hundreds_of_microseconds * 100); + return dest; +} + +#ifdef HAVE_STRUCT_TIMESPEC +/*! + Convert a UDF timestamp to a time_t. If microseconds are desired, + use dest_usec. The return value is the same as dest. */ +udf_timestamp_t * +udf_timespec_to_stamp(const struct timespec ts, udf_timestamp_t *dest) +{ + long int days, rem, y; + const unsigned short int *ip; + int16_t offset = 0; + int16_t tv_sec; + +#ifdef HAVE_TIMEZONE_VAR + offset = -timezone; +#endif + + if (!dest) + return dest; + + dest->type_tz = 0x1000 | (offset & 0x0FFF); + + tv_sec = ts.tv_sec + (offset * SECS_PER_MINUTE); + days = tv_sec / SECS_PER_DAY; + rem = tv_sec % SECS_PER_DAY; + dest->hour = rem / SECS_PER_HOUR; + rem %= SECS_PER_HOUR; + dest->minute = rem / SECS_PER_MINUTE; + dest->second = rem % SECS_PER_MINUTE; + y = EPOCH_YEAR; + +#define DIV(a,b) ((a) / (b) - ((a) % (b) < 0)) +#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) + + while (days < 0 || days >= (__isleap(y) ? DAYS_PER_YEAR+1 : DAYS_PER_YEAR)) { + long int yg = y + days / DAYS_PER_YEAR - (days % DAYS_PER_YEAR < 0); + + /* Adjust DAYS and Y to match the guessed year. */ + days -= ((yg - y) * DAYS_PER_YEAR + + LEAPS_THRU_END_OF (yg - 1) + - LEAPS_THRU_END_OF (y - 1)); + y = yg; + } + dest->year = y; + ip = __mon_yday[__isleap(y)]; + for (y = 11; days < (long int) ip[y]; --y) + continue; + days -= ip[y]; + dest->month = y + 1; + dest->day = days + 1; + + dest->centiseconds = ts.tv_nsec / 10000000; + dest->hundreds_of_microseconds = ( (ts.tv_nsec / 1000) + - (dest->centiseconds * 10000) ) / 100; + dest->microseconds = ( (ts.tv_nsec / 1000) + - (dest->centiseconds * 10000) + - (dest->hundreds_of_microseconds * 100) ); + return dest; +} +#endif + +/*! + Return the modification time of the file. + */ +time_t +udf_get_modification_time(const udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent) { + time_t ret_time; + long int usec; + udf_stamp_to_time(&ret_time, &usec, p_udf_dirent->fe.modification_time); + return ret_time; + } + return 0; +} + +/*! + Return the access time of the file. + */ +time_t +udf_get_access_time(const udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent) { + time_t ret_time; + long int usec; + udf_stamp_to_time(&ret_time, &usec, p_udf_dirent->fe.access_time); + return ret_time; + } + return 0; +} + +/*! + Return the attribute (most recent create or access) time of the file + */ +time_t +udf_get_attribute_time(const udf_dirent_t *p_udf_dirent) +{ + if (p_udf_dirent) { + time_t ret_time; + long int usec; + udf_stamp_to_time(&ret_time, &usec, p_udf_dirent->fe.attribute_time); + return ret_time; + } + return 0; +} + diff --git a/src/license.h b/src/license.h index 505506ca..d819d446 100644 --- a/src/license.h +++ b/src/license.h @@ -30,6 +30,10 @@ const char* additional_copyrights = "http://www.freedos.org\r\n" "GNU General Public License (GPL) v2 or later, with binary redistribution allowed\r\n" "\r\n" +"ISO extraction support from libcdio by Rocky Bernstein et al:\r\n" +"http://www.gnu.org/software/libcdio\r\n" +"GNU General Public License (GPL) v3 or later\r\n" +"\r\n" "Syslinux support from Syslinux by H. Peter Anvin et al:\r\n" "http://www.syslinux.org\r\n" "GNU General Public License (GPL) v2 or later\r\n" diff --git a/src/ms-sys/.msvc/ms-sys.vcxproj b/src/ms-sys/.msvc/ms-sys.vcxproj index 5c559a75..5d16e7a6 100644 --- a/src/ms-sys/.msvc/ms-sys.vcxproj +++ b/src/ms-sys/.msvc/ms-sys.vcxproj @@ -122,7 +122,7 @@ Level3 Disabled - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) ../inc;%(AdditionalIncludeDirectories) MultiThreadedDebug ProgramDatabase @@ -142,7 +142,7 @@ MaxSpeed true - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ../inc;%(AdditionalIncludeDirectories) MultiThreaded ProgramDatabase @@ -157,7 +157,7 @@ Level3 Disabled - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) ../inc;%(AdditionalIncludeDirectories) MultiThreadedDebug ProgramDatabase @@ -177,7 +177,7 @@ MaxSpeed true - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ../inc;%(AdditionalIncludeDirectories) MultiThreaded ProgramDatabase diff --git a/src/syslinux/inttypes.h b/src/msvc-missing/inttypes.h similarity index 93% rename from src/syslinux/inttypes.h rename to src/msvc-missing/inttypes.h index 892b5bc6..6d8c418b 100644 --- a/src/syslinux/inttypes.h +++ b/src/msvc-missing/inttypes.h @@ -1,301 +1,299 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file was original part of the w64 mingw-runtime package. - */ - -/* - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * Modified for libusb/MSVC: Pete Batard - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Date: 2010-04-02 - */ - -#ifndef _MSC_VER -#error This header should only be used with Microsoft compilers -#endif - -/* 7.8 Format conversion of integer types */ - -#ifndef _INTTYPES_H_ -#define _INTTYPES_H_ - -#include -/* SysLinux types addon */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - intmax_t quot; - intmax_t rem; - } imaxdiv_t; - - -#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) - -/* 7.8.1 Macros for format specifiers - * - * MS runtime does not yet understand C9x standard "ll" - * length specifier. It appears to treat "ll" as "l". - * The non-standard I64 length specifier causes warning in GCC, - * but understood by MS runtime functions. - */ - -/* fprintf macros for signed types */ -#define PRId8 "d" -#define PRId16 "d" -#define PRId32 "d" -#define PRId64 "I64d" - -#define PRIdLEAST8 "d" -#define PRIdLEAST16 "d" -#define PRIdLEAST32 "d" -#define PRIdLEAST64 "I64d" - -#define PRIdFAST8 "d" -#define PRIdFAST16 "d" -#define PRIdFAST32 "d" -#define PRIdFAST64 "I64d" - -#define PRIdMAX "I64d" - -#define PRIi8 "i" -#define PRIi16 "i" -#define PRIi32 "i" -#define PRIi64 "I64i" - -#define PRIiLEAST8 "i" -#define PRIiLEAST16 "i" -#define PRIiLEAST32 "i" -#define PRIiLEAST64 "I64i" - -#define PRIiFAST8 "i" -#define PRIiFAST16 "i" -#define PRIiFAST32 "i" -#define PRIiFAST64 "I64i" - -#define PRIiMAX "I64i" - -#define PRIo8 "o" -#define PRIo16 "o" -#define PRIo32 "o" -#define PRIo64 "I64o" - -#define PRIoLEAST8 "o" -#define PRIoLEAST16 "o" -#define PRIoLEAST32 "o" -#define PRIoLEAST64 "I64o" - -#define PRIoFAST8 "o" -#define PRIoFAST16 "o" -#define PRIoFAST32 "o" -#define PRIoFAST64 "I64o" - -#define PRIoMAX "I64o" - -/* fprintf macros for unsigned types */ -#define PRIu8 "u" -#define PRIu16 "u" -#define PRIu32 "u" -#define PRIu64 "I64u" - - -#define PRIuLEAST8 "u" -#define PRIuLEAST16 "u" -#define PRIuLEAST32 "u" -#define PRIuLEAST64 "I64u" - -#define PRIuFAST8 "u" -#define PRIuFAST16 "u" -#define PRIuFAST32 "u" -#define PRIuFAST64 "I64u" - -#define PRIuMAX "I64u" - -#define PRIx8 "x" -#define PRIx16 "x" -#define PRIx32 "x" -#define PRIx64 "I64x" - -#define PRIxLEAST8 "x" -#define PRIxLEAST16 "x" -#define PRIxLEAST32 "x" -#define PRIxLEAST64 "I64x" - -#define PRIxFAST8 "x" -#define PRIxFAST16 "x" -#define PRIxFAST32 "x" -#define PRIxFAST64 "I64x" - -#define PRIxMAX "I64x" - -#define PRIX8 "X" -#define PRIX16 "X" -#define PRIX32 "X" -#define PRIX64 "I64X" - -#define PRIXLEAST8 "X" -#define PRIXLEAST16 "X" -#define PRIXLEAST32 "X" -#define PRIXLEAST64 "I64X" - -#define PRIXFAST8 "X" -#define PRIXFAST16 "X" -#define PRIXFAST32 "X" -#define PRIXFAST64 "I64X" - -#define PRIXMAX "I64X" - -/* - * fscanf macros for signed int types - * NOTE: if 32-bit int is used for int_fast8_t and int_fast16_t - * (see stdint.h, 7.18.1.3), FAST8 and FAST16 should have - * no length identifiers - */ - -#define SCNd16 "hd" -#define SCNd32 "d" -#define SCNd64 "I64d" - -#define SCNdLEAST16 "hd" -#define SCNdLEAST32 "d" -#define SCNdLEAST64 "I64d" - -#define SCNdFAST16 "hd" -#define SCNdFAST32 "d" -#define SCNdFAST64 "I64d" - -#define SCNdMAX "I64d" - -#define SCNi16 "hi" -#define SCNi32 "i" -#define SCNi64 "I64i" - -#define SCNiLEAST16 "hi" -#define SCNiLEAST32 "i" -#define SCNiLEAST64 "I64i" - -#define SCNiFAST16 "hi" -#define SCNiFAST32 "i" -#define SCNiFAST64 "I64i" - -#define SCNiMAX "I64i" - -#define SCNo16 "ho" -#define SCNo32 "o" -#define SCNo64 "I64o" - -#define SCNoLEAST16 "ho" -#define SCNoLEAST32 "o" -#define SCNoLEAST64 "I64o" - -#define SCNoFAST16 "ho" -#define SCNoFAST32 "o" -#define SCNoFAST64 "I64o" - -#define SCNoMAX "I64o" - -#define SCNx16 "hx" -#define SCNx32 "x" -#define SCNx64 "I64x" - -#define SCNxLEAST16 "hx" -#define SCNxLEAST32 "x" -#define SCNxLEAST64 "I64x" - -#define SCNxFAST16 "hx" -#define SCNxFAST32 "x" -#define SCNxFAST64 "I64x" - -#define SCNxMAX "I64x" - -/* fscanf macros for unsigned int types */ - -#define SCNu16 "hu" -#define SCNu32 "u" -#define SCNu64 "I64u" - -#define SCNuLEAST16 "hu" -#define SCNuLEAST32 "u" -#define SCNuLEAST64 "I64u" - -#define SCNuFAST16 "hu" -#define SCNuFAST32 "u" -#define SCNuFAST64 "I64u" - -#define SCNuMAX "I64u" - -#ifdef _WIN64 -#define PRIdPTR "I64d" -#define PRIiPTR "I64i" -#define PRIoPTR "I64o" -#define PRIuPTR "I64u" -#define PRIxPTR "I64x" -#define PRIXPTR "I64X" -#define SCNdPTR "I64d" -#define SCNiPTR "I64i" -#define SCNoPTR "I64o" -#define SCNxPTR "I64x" -#define SCNuPTR "I64u" -#else -#define PRIdPTR "d" -#define PRIiPTR "i" -#define PRIoPTR "o" -#define PRIuPTR "u" -#define PRIxPTR "x" -#define PRIXPTR "X" -#define SCNdPTR "d" -#define SCNiPTR "i" -#define SCNoPTR "o" -#define SCNxPTR "x" - #define SCNuPTR "u" -#endif - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -/* - * no length modifier for char types prior to C9x - * MS runtime scanf appears to treat "hh" as "h" - */ - -/* signed char */ -#define SCNd8 "hhd" -#define SCNdLEAST8 "hhd" -#define SCNdFAST8 "hhd" - -#define SCNi8 "hhi" -#define SCNiLEAST8 "hhi" -#define SCNiFAST8 "hhi" - -#define SCNo8 "hho" -#define SCNoLEAST8 "hho" -#define SCNoFAST8 "hho" - -#define SCNx8 "hhx" -#define SCNxLEAST8 "hhx" -#define SCNxFAST8 "hhx" - -/* unsigned char */ -#define SCNu8 "hhu" -#define SCNuLEAST8 "hhu" -#define SCNuFAST8 "hhu" -#endif /* __STDC_VERSION__ >= 199901 */ - -#endif /* !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) */ - - -#ifdef __cplusplus -} -#endif - -#endif /* ndef _INTTYPES_H */ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file was original part of the w64 mingw-runtime package. + */ + +/* + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Modified for libusb/MSVC: Pete Batard + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2010-04-02 + */ + +#ifndef _MSC_VER +#error This header should only be used with Microsoft compilers +#endif + +/* 7.8 Format conversion of integer types */ + +#ifndef _INTTYPES_H_ +#define _INTTYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + intmax_t quot; + intmax_t rem; + } imaxdiv_t; + + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + +/* 7.8.1 Macros for format specifiers + * + * MS runtime does not yet understand C9x standard "ll" + * length specifier. It appears to treat "ll" as "l". + * The non-standard I64 length specifier causes warning in GCC, + * but understood by MS runtime functions. + */ + +/* fprintf macros for signed types */ +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 "I64d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 "I64d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 "d" +#define PRIdFAST32 "d" +#define PRIdFAST64 "I64d" + +#define PRIdMAX "I64d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "I64i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 "I64i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 "i" +#define PRIiFAST32 "i" +#define PRIiFAST64 "I64i" + +#define PRIiMAX "I64i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 "I64o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 "I64o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 "o" +#define PRIoFAST32 "o" +#define PRIoFAST64 "I64o" + +#define PRIoMAX "I64o" + +/* fprintf macros for unsigned types */ +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "I64u" + + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 "I64u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 "u" +#define PRIuFAST32 "u" +#define PRIuFAST64 "I64u" + +#define PRIuMAX "I64u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 "I64x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 "I64x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 "x" +#define PRIxFAST32 "x" +#define PRIxFAST64 "I64x" + +#define PRIxMAX "I64x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 "I64X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 "I64X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 "X" +#define PRIXFAST32 "X" +#define PRIXFAST64 "I64X" + +#define PRIXMAX "I64X" + +/* + * fscanf macros for signed int types + * NOTE: if 32-bit int is used for int_fast8_t and int_fast16_t + * (see stdint.h, 7.18.1.3), FAST8 and FAST16 should have + * no length identifiers + */ + +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 "I64d" + +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 "I64d" + +#define SCNdFAST16 "hd" +#define SCNdFAST32 "d" +#define SCNdFAST64 "I64d" + +#define SCNdMAX "I64d" + +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 "I64i" + +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 "I64i" + +#define SCNiFAST16 "hi" +#define SCNiFAST32 "i" +#define SCNiFAST64 "I64i" + +#define SCNiMAX "I64i" + +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 "I64o" + +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 "I64o" + +#define SCNoFAST16 "ho" +#define SCNoFAST32 "o" +#define SCNoFAST64 "I64o" + +#define SCNoMAX "I64o" + +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 "I64x" + +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 "I64x" + +#define SCNxFAST16 "hx" +#define SCNxFAST32 "x" +#define SCNxFAST64 "I64x" + +#define SCNxMAX "I64x" + +/* fscanf macros for unsigned int types */ + +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 "I64u" + +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 "I64u" + +#define SCNuFAST16 "hu" +#define SCNuFAST32 "u" +#define SCNuFAST64 "I64u" + +#define SCNuMAX "I64u" + +#ifdef _WIN64 +#define PRIdPTR "I64d" +#define PRIiPTR "I64i" +#define PRIoPTR "I64o" +#define PRIuPTR "I64u" +#define PRIxPTR "I64x" +#define PRIXPTR "I64X" +#define SCNdPTR "I64d" +#define SCNiPTR "I64i" +#define SCNoPTR "I64o" +#define SCNxPTR "I64x" +#define SCNuPTR "I64u" +#else +#define PRIdPTR "d" +#define PRIiPTR "i" +#define PRIoPTR "o" +#define PRIuPTR "u" +#define PRIxPTR "x" +#define PRIXPTR "X" +#define SCNdPTR "d" +#define SCNiPTR "i" +#define SCNoPTR "o" +#define SCNxPTR "x" + #define SCNuPTR "u" +#endif + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +/* + * no length modifier for char types prior to C9x + * MS runtime scanf appears to treat "hh" as "h" + */ + +/* signed char */ +#define SCNd8 "hhd" +#define SCNdLEAST8 "hhd" +#define SCNdFAST8 "hhd" + +#define SCNi8 "hhi" +#define SCNiLEAST8 "hhi" +#define SCNiFAST8 "hhi" + +#define SCNo8 "hho" +#define SCNoLEAST8 "hho" +#define SCNoFAST8 "hho" + +#define SCNx8 "hhx" +#define SCNxLEAST8 "hhx" +#define SCNxFAST8 "hhx" + +/* unsigned char */ +#define SCNu8 "hhu" +#define SCNuLEAST8 "hhu" +#define SCNuFAST8 "hhu" +#endif /* __STDC_VERSION__ >= 199901 */ + +#endif /* !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) */ + + +#ifdef __cplusplus +} +#endif + +#endif /* ndef _INTTYPES_H */ diff --git a/src/syslinux/stdint.h b/src/msvc-missing/stdint.h similarity index 96% rename from src/syslinux/stdint.h rename to src/msvc-missing/stdint.h index 7e0746f8..51687f70 100644 --- a/src/syslinux/stdint.h +++ b/src/msvc-missing/stdint.h @@ -1,262 +1,262 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file was originally part of the w64 mingw-runtime package. - */ - -/* ISO C9x 7.18 Integer types - * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * Contributor: Danny Smith - * Modified for libusb/MSVC: Pete Batard - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Date: 2010-04-02 - */ - -#ifndef _MSC_VER -#error This header should only be used with Microsoft compilers -#endif - -#ifndef _STDINT_H -#define _STDINT_H - -#ifndef _INTPTR_T_DEFINED -#define _INTPTR_T_DEFINED -#ifndef __intptr_t_defined -#define __intptr_t_defined -#undef intptr_t -#ifdef _WIN64 - typedef __int64 intptr_t; -#else - typedef int intptr_t; -#endif /* _WIN64 */ -#endif /* __intptr_t_defined */ -#endif /* _INTPTR_T_DEFINED */ - -#ifndef _UINTPTR_T_DEFINED -#define _UINTPTR_T_DEFINED -#ifndef __uintptr_t_defined -#define __uintptr_t_defined -#undef uintptr_t -#ifdef _WIN64 - typedef unsigned __int64 uintptr_t; -#else - typedef unsigned int uintptr_t; -#endif /* _WIN64 */ -#endif /* __uintptr_t_defined */ -#endif /* _UINTPTR_T_DEFINED */ - -#ifndef _PTRDIFF_T_DEFINED -#define _PTRDIFF_T_DEFINED -#ifndef _PTRDIFF_T_ -#define _PTRDIFF_T_ -#undef ptrdiff_t -#ifdef _WIN64 - typedef __int64 ptrdiff_t; -#else - typedef int ptrdiff_t; -#endif /* _WIN64 */ -#endif /* _PTRDIFF_T_ */ -#endif /* _PTRDIFF_T_DEFINED */ - -#ifndef _WCHAR_T_DEFINED -#define _WCHAR_T_DEFINED -#ifndef __cplusplus - typedef unsigned short wchar_t; -#endif /* C++ */ -#endif /* _WCHAR_T_DEFINED */ - -#ifndef _WCTYPE_T_DEFINED -#define _WCTYPE_T_DEFINED -#ifndef _WINT_T -#define _WINT_T - typedef unsigned short wint_t; - typedef unsigned short wctype_t; -#endif /* _WINT_T */ -#endif /* _WCTYPE_T_DEFINED */ - -/* 7.18.1.1 Exact-width integer types */ -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -/* 7.18.1.2 Minimum-width integer types */ -typedef signed char int_least8_t; -typedef unsigned char uint_least8_t; -typedef short int_least16_t; -typedef unsigned short uint_least16_t; -typedef int int_least32_t; -typedef unsigned uint_least32_t; -typedef __int64 int_least64_t; -typedef unsigned __int64 uint_least64_t; - -/* 7.18.1.3 Fastest minimum-width integer types - * Not actually guaranteed to be fastest for all purposes - * Here we use the exact-width types for 8 and 16-bit ints. - */ -typedef __int8 int_fast8_t; -typedef unsigned __int8 uint_fast8_t; -typedef __int16 int_fast16_t; -typedef unsigned __int16 uint_fast16_t; -typedef __int32 int_fast32_t; -typedef unsigned __int32 uint_fast32_t; -typedef __int64 int_fast64_t; -typedef unsigned __int64 uint_fast64_t; - -/* 7.18.1.5 Greatest-width integer types */ -typedef __int64 intmax_t; -typedef unsigned __int64 uintmax_t; - -/* 7.18.2 Limits of specified-width integer types */ -#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS) - -/* 7.18.2.1 Limits of exact-width integer types */ -#define INT8_MIN (-128) -#define INT16_MIN (-32768) -#define INT32_MIN (-2147483647 - 1) -#define INT64_MIN (-9223372036854775807LL - 1) - -#define INT8_MAX 127 -#define INT16_MAX 32767 -#define INT32_MAX 2147483647 -#define INT64_MAX 9223372036854775807LL - -#define UINT8_MAX 255 -#define UINT16_MAX 65535 -#define UINT32_MAX 0xffffffffU /* 4294967295U */ -#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ - -/* 7.18.2.2 Limits of minimum-width integer types */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* 7.18.2.3 Limits of fastest minimum-width integer types */ -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -/* 7.18.2.4 Limits of integer types capable of holding - object pointers */ -#ifdef _WIN64 -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX -#else -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX -#endif - -/* 7.18.2.5 Limits of greatest-width integer types */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* 7.18.3 Limits of other integer types */ -#ifdef _WIN64 -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX -#else -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX -#endif - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#ifndef SIZE_MAX -#ifdef _WIN64 -#define SIZE_MAX UINT64_MAX -#else -#define SIZE_MAX UINT32_MAX -#endif -#endif - -#ifndef WCHAR_MIN /* also in wchar.h */ -#define WCHAR_MIN 0U -#define WCHAR_MAX 0xffffU -#endif - -/* - * wint_t is unsigned short for compatibility with MS runtime - */ -#define WINT_MIN 0U -#define WINT_MAX 0xffffU - -#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */ - - -/* 7.18.4 Macros for integer constants */ -#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS) - -/* 7.18.4.1 Macros for minimum-width integer constants - - Accoding to Douglas Gwyn : - "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC - 9899:1999 as initially published, the expansion was required - to be an integer constant of precisely matching type, which - is impossible to accomplish for the shorter types on most - platforms, because C99 provides no standard way to designate - an integer constant with width less than that of type int. - TC1 changed this to require just an integer constant - *expression* with *promoted* type." - - The trick used here is from Clive D W Feather. -*/ - -#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val)) -#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val)) -#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val)) -/* The 'trick' doesn't work in C89 for long long because, without - suffix, (val) will be evaluated as int, not intmax_t */ -#define INT64_C(val) val##i64 - -#define UINT8_C(val) (val) -#define UINT16_C(val) (val) -#define UINT32_C(val) (val##i32) -#define UINT64_C(val) val##ui64 - -/* 7.18.4.2 Macros for greatest-width integer constants */ -#define INTMAX_C(val) val##i64 -#define UINTMAX_C(val) val##ui64 - -#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */ - -#endif +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file was originally part of the w64 mingw-runtime package. + */ + +/* ISO C9x 7.18 Integer types + * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Contributor: Danny Smith + * Modified for libusb/MSVC: Pete Batard + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2010-04-02 + */ + +#ifndef _MSC_VER +#error This header should only be used with Microsoft compilers +#endif + +#ifndef _STDINT_H +#define _STDINT_H + +#ifndef _INTPTR_T_DEFINED +#define _INTPTR_T_DEFINED +#ifndef __intptr_t_defined +#define __intptr_t_defined +#undef intptr_t +#ifdef _WIN64 + typedef __int64 intptr_t; +#else + typedef int intptr_t; +#endif /* _WIN64 */ +#endif /* __intptr_t_defined */ +#endif /* _INTPTR_T_DEFINED */ + +#ifndef _UINTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED +#ifndef __uintptr_t_defined +#define __uintptr_t_defined +#undef uintptr_t +#ifdef _WIN64 + typedef unsigned __int64 uintptr_t; +#else + typedef unsigned int uintptr_t; +#endif /* _WIN64 */ +#endif /* __uintptr_t_defined */ +#endif /* _UINTPTR_T_DEFINED */ + +#ifndef _PTRDIFF_T_DEFINED +#define _PTRDIFF_T_DEFINED +#ifndef _PTRDIFF_T_ +#define _PTRDIFF_T_ +#undef ptrdiff_t +#ifdef _WIN64 + typedef __int64 ptrdiff_t; +#else + typedef int ptrdiff_t; +#endif /* _WIN64 */ +#endif /* _PTRDIFF_T_ */ +#endif /* _PTRDIFF_T_DEFINED */ + +#ifndef _WCHAR_T_DEFINED +#define _WCHAR_T_DEFINED +#ifndef __cplusplus + typedef unsigned short wchar_t; +#endif /* C++ */ +#endif /* _WCHAR_T_DEFINED */ + +#ifndef _WCTYPE_T_DEFINED +#define _WCTYPE_T_DEFINED +#ifndef _WINT_T +#define _WINT_T + typedef unsigned short wint_t; + typedef unsigned short wctype_t; +#endif /* _WINT_T */ +#endif /* _WCTYPE_T_DEFINED */ + +/* 7.18.1.1 Exact-width integer types */ +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef signed char int_least8_t; +typedef unsigned char uint_least8_t; +typedef short int_least16_t; +typedef unsigned short uint_least16_t; +typedef int int_least32_t; +typedef unsigned uint_least32_t; +typedef __int64 int_least64_t; +typedef unsigned __int64 uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types + * Not actually guaranteed to be fastest for all purposes + * Here we use the exact-width types for 8 and 16-bit ints. + */ +typedef __int8 int_fast8_t; +typedef unsigned __int8 uint_fast8_t; +typedef __int16 int_fast16_t; +typedef unsigned __int16 uint_fast16_t; +typedef __int32 int_fast32_t; +typedef unsigned __int32 uint_fast32_t; +typedef __int64 int_fast64_t; +typedef unsigned __int64 uint_fast64_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64 intmax_t; +typedef unsigned __int64 uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ +#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS) + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647 - 1) +#define INT64_MIN (-9223372036854775807LL - 1) + +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807LL + +#define UINT8_MAX 255 +#define UINT16_MAX 65535 +#define UINT32_MAX 0xffffffffU /* 4294967295U */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding + object pointers */ +#ifdef _WIN64 +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* 7.18.3 Limits of other integer types */ +#ifdef _WIN64 +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#else +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX +#endif + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#ifndef SIZE_MAX +#ifdef _WIN64 +#define SIZE_MAX UINT64_MAX +#else +#define SIZE_MAX UINT32_MAX +#endif +#endif + +#ifndef WCHAR_MIN /* also in wchar.h */ +#define WCHAR_MIN 0U +#define WCHAR_MAX 0xffffU +#endif + +/* + * wint_t is unsigned short for compatibility with MS runtime + */ +#define WINT_MIN 0U +#define WINT_MAX 0xffffU + +#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */ + + +/* 7.18.4 Macros for integer constants */ +#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS) + +/* 7.18.4.1 Macros for minimum-width integer constants + + Accoding to Douglas Gwyn : + "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC + 9899:1999 as initially published, the expansion was required + to be an integer constant of precisely matching type, which + is impossible to accomplish for the shorter types on most + platforms, because C99 provides no standard way to designate + an integer constant with width less than that of type int. + TC1 changed this to require just an integer constant + *expression* with *promoted* type." + + The trick used here is from Clive D W Feather. +*/ + +#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val)) +#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val)) +#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val)) +/* The 'trick' doesn't work in C89 for long long because, without + suffix, (val) will be evaluated as int, not intmax_t */ +#define INT64_C(val) val##i64 + +#define UINT8_C(val) (val) +#define UINT16_C(val) (val) +#define UINT32_C(val) (val##i32) +#define UINT64_C(val) val##ui64 + +/* 7.18.4.2 Macros for greatest-width integer constants */ +#define INTMAX_C(val) val##i64 +#define UINTMAX_C(val) val##ui64 + +#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */ + +#endif diff --git a/src/msvc-missing/unistd.h b/src/msvc-missing/unistd.h new file mode 100644 index 00000000..95c32208 --- /dev/null +++ b/src/msvc-missing/unistd.h @@ -0,0 +1,34 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file was originally part of the w64 mingw-runtime package. + */ + +/* Workaround unistd.h for MS compilers */ + +#ifndef _MSC_VER +#error This header should only be used with Microsoft compilers +#endif + +#include + +#ifndef _UNISTD_H_ +#define _UNISTD_H_ + +/* mode_t is used in the libcdio headers */ +#ifndef _MODE_T_DEFINED +#define _MODE_T_DEFINED +typedef unsigned short mode_t; +#endif /* _MODE_T_DEFINED */ + +/* ssize_t is also not available (copy/paste from MinGW) */ +#ifndef _SSIZE_T_DEFINED +#define _SSIZE_T_DEFINED +#undef ssize_t +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef int ssize_t; +#endif /* _WIN64 */ +#endif /* _SSIZE_T_DEFINED */ + +#endif \ No newline at end of file diff --git a/src/resource.h b/src/resource.h index 49a0caec..7ad7f913 100644 --- a/src/resource.h +++ b/src/resource.h @@ -52,6 +52,7 @@ #define IDC_PROGRESS 1012 #define IDC_DOSTYPE 1013 #define IDC_NBPASSES 1014 +#define IDC_TEST 1015 #define IDC_ABOUT_LICENSE 1030 #define IDC_ABOUT_ICON 1031 #define IDC_RUFUS_BOLD 1032 diff --git a/src/rufus.c b/src/rufus.c index 8c2f44cb..a282d54b 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -1000,6 +1000,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case IDC_ABOUT: CreateAboutBox(); break; + case IDC_TEST: +// ExtractISO("D:\\Incoming\\GRMSDKX_EN_DVD.iso", NULL); +// ExtractISO("D:\\fd11src.iso", NULL); +// ExtractISO("D:\\Incoming\\en_windows_driver_kit_3790.iso", NULL); +// ExtractISO("D:\\Incoming\\en_windows_7_ultimate_with_sp1_x64_dvd_618240.iso", NULL); + ExtractISO("D:\\Incoming\\Windows 8 Preview\\WindowsDeveloperPreview-64bit-English-Developer.iso", NULL); + break; case IDC_DEVICE: switch (HIWORD(wParam)) { case CBN_SELCHANGE: diff --git a/src/rufus.h b/src/rufus.h index 042f237e..4d1b5c47 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -165,6 +165,7 @@ extern void DestroyTooltip(HWND hWnd); extern void DestroyAllTooltips(void); extern BOOL Notification(int type, char* title, char* format, ...); extern BOOL ExtractDOS(const char* path); +extern BOOL ExtractISO(const char* src_iso, const char* dest_dir); extern BOOL InstallSyslinux(DWORD num, const char* drive_name); extern void __cdecl FormatThread(void* param); extern BOOL CreatePartition(HANDLE hDrive); diff --git a/src/rufus.rc b/src/rufus.rc index a4ff50e1..c6f58261 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 278 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.0.7.118" +CAPTION "Rufus v1.0.7.119" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 @@ -56,6 +56,7 @@ BEGIN CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,210,189,9 COMBOBOX IDC_DOSTYPE,118,183,45,30,CBS_DROPDOWNLIST | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_NBPASSES,118,159,45,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Test",IDC_TEST,62,236,20,14 END IDD_ABOUTBOX DIALOGEX 0, 0, 287, 195 @@ -69,7 +70,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.0.7 (Build 118)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.7 (Build 119)",IDC_STATIC,46,19,78,8 PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -207,8 +208,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,7,118 - PRODUCTVERSION 1,0,7,118 + FILEVERSION 1,0,7,119 + PRODUCTVERSION 1,0,7,119 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -225,13 +226,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.7.118" + VALUE "FileVersion", "1.0.7.119" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.0.7.118" + VALUE "ProductVersion", "1.0.7.119" END END BLOCK "VarFileInfo" diff --git a/src/syslinux/libfat/.msvc/libfat.vcxproj b/src/syslinux/libfat/.msvc/libfat.vcxproj index 7262a131..f13c4c0b 100644 --- a/src/syslinux/libfat/.msvc/libfat.vcxproj +++ b/src/syslinux/libfat/.msvc/libfat.vcxproj @@ -96,8 +96,8 @@ Level3 Disabled - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreadedDebug ProgramDatabase @@ -116,8 +116,8 @@ MaxSpeed true - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreaded ProgramDatabase @@ -131,8 +131,8 @@ Level3 Disabled - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreadedDebug ProgramDatabase @@ -151,8 +151,8 @@ MaxSpeed true - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreaded ProgramDatabase diff --git a/src/syslinux/libfat/.msvc/libfat_sources b/src/syslinux/libfat/.msvc/libfat_sources index 858bf26f..49e50780 100644 --- a/src/syslinux/libfat/.msvc/libfat_sources +++ b/src/syslinux/libfat/.msvc/libfat_sources @@ -1,8 +1,8 @@ TARGETNAME=libfat TARGETTYPE=LIBRARY -INCLUDES=$(DDK_INC_PATH);.. -C_DEFINES=$(C_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED +INCLUDES=$(DDK_INC_PATH);..\..\msvc-missing +C_DEFINES=$(C_DEFINES) /Dinline=__inline /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED !IFNDEF MSC_WARNING_LEVEL MSC_WARNING_LEVEL=/W3 diff --git a/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj b/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj index 4a32c72c..2bc9a374 100644 --- a/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj +++ b/src/syslinux/libinstaller/.msvc/libinstaller.vcxproj @@ -94,8 +94,8 @@ Level3 Disabled - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreadedDebug ProgramDatabase @@ -114,8 +114,8 @@ MaxSpeed true - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreaded ProgramDatabase @@ -129,8 +129,8 @@ Level3 Disabled - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreadedDebug ProgramDatabase @@ -149,8 +149,8 @@ MaxSpeed true - _CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_LIB;%(PreprocessorDefinitions) - ..;..\..;%(AdditionalIncludeDirectories) + inline=__inline;%(PreprocessorDefinitions) + ..;..\..\..\msvc-missing;%(AdditionalIncludeDirectories) MultiThreaded ProgramDatabase diff --git a/src/syslinux/libinstaller/.msvc/libinstaller_sources b/src/syslinux/libinstaller/.msvc/libinstaller_sources index 0096225d..10b20516 100644 --- a/src/syslinux/libinstaller/.msvc/libinstaller_sources +++ b/src/syslinux/libinstaller/.msvc/libinstaller_sources @@ -1,8 +1,8 @@ TARGETNAME=libinstaller TARGETTYPE=LIBRARY -INCLUDES=$(DDK_INC_PATH);.. -C_DEFINES=$(C_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED +INCLUDES=$(DDK_INC_PATH);..\..\msvc-missing +C_DEFINES=$(C_DEFINES) /Dinline=__inline /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED !IFNDEF MSC_WARNING_LEVEL MSC_WARNING_LEVEL=/W3 diff --git a/wdk_build.cmd b/wdk_build.cmd index ba1fc0fc..062f4c47 100644 --- a/wdk_build.cmd +++ b/wdk_build.cmd @@ -55,6 +55,51 @@ copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\libinstaller.lib . >NUL 2>&1 if EXIST Makefile.hide ren Makefile.hide Makefile if EXIST sources del sources >NUL 2>&1 +::# libcdio iso9660 Library +cd ..\..\libcdio\iso9660 +if EXIST Makefile ren Makefile Makefile.hide + +copy .msvc\iso9660_sources sources >NUL 2>&1 + +@echo on +%BUILD_CMD% +@echo off +if errorlevel 1 goto builderror +copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\iso9660.lib . >NUL 2>&1 + +if EXIST Makefile.hide ren Makefile.hide Makefile +if EXIST sources del sources >NUL 2>&1 + +::# libcdio udf Library +cd ..\udf +if EXIST Makefile ren Makefile Makefile.hide + +copy .msvc\udf_sources sources >NUL 2>&1 + +@echo on +%BUILD_CMD% +@echo off +if errorlevel 1 goto builderror +copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\udf.lib . >NUL 2>&1 + +if EXIST Makefile.hide ren Makefile.hide Makefile +if EXIST sources del sources >NUL 2>&1 + +::# libcdio driver Library +cd ..\driver +if EXIST Makefile ren Makefile Makefile.hide + +copy .msvc\driver_sources sources >NUL 2>&1 + +@echo on +%BUILD_CMD% +@echo off +if errorlevel 1 goto builderror +copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\driver.lib . >NUL 2>&1 + +if EXIST Makefile.hide ren Makefile.hide Makefile +if EXIST sources del sources >NUL 2>&1 + ::# Rufus Application cd ..\.. if EXIST Makefile ren Makefile Makefile.hide