📄 iso9660_fs.c
字号:
/* $Id: iso9660_fs.c,v 1.7 2006/12/08 16:26:10 mshopf Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef HAVE_CONFIG_H# include "config.h"#endif#ifdef HAVE_STRING_H# include <string.h>#endif#ifdef HAVE_ERRNO_H# include <errno.h>#endif#ifdef HAVE_ICONV# include <iconv.h>#endif#ifdef HAVE_NL_LANGINFO#include <langinfo.h>#endif#include <cdio/cdio.h>#include <cdio/bytesex.h>#include <cdio/iso9660.h>#include <cdio/util.h>/* Private headers */#include "cdio_assert.h"#include "_cdio_stdio.h"#include "cdio_private.h"#include <stdio.h>static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.7 2006/12/08 16:26:10 mshopf Exp $";/* Implementation of iso9660_t type */struct _iso9660 { CdioDataSource *stream; /* Stream pointer */ bool b_xa; /* true if has XA attributes. */ 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. */};/*! 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 *pathname /*, mode*/){ return iso9660_open_ext(pathname, 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 *pathname, iso_extension_mask_t iso_extension_mask){ iso9660_t *p_iso = (iso9660_t *) _cdio_malloc(sizeof(struct _iso9660)) ; if (NULL == p_iso) return NULL; p_iso->stream = cdio_stdio_new( pathname ); if (NULL == p_iso->stream) goto error; if ( !iso9660_ifs_read_superblock(p_iso, iso_extension_mask) ) 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, strlen (ISO_XA_MARKER_STRING)); p_iso->iso_extension_mask = iso_extension_mask; return p_iso; error: free(p_iso); return NULL;}/*! 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 boolcheck_pvd (const iso9660_pvd_t *p_pvd) { if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) { cdio_warn ("unexpected PVD type %d", p_pvd->type); return false; } if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID))) { cdio_warn ("unexpected ID encountered (expected `" ISO_STANDARD_ID "', got `%.5s'", p_pvd->id); return false; } return true;}#ifdef HAVE_JOLIETstatic boolucs2be_to_locale(ICONV_CONST char *psz_ucs2be, size_t i_inlen, char **p_psz_out, size_t i_outlen){ iconv_t ic = #if defined(HAVE_NL_LANGINFO) iconv_open(nl_langinfo(CODESET), "UCS-2BE");#else iconv_open("ASCII", "UCS-2BE");#endif int rc; char *psz_buf = NULL; char *psz_buf2; int i_outlen_max = i_outlen; int i_outlen_actual; if (-1 == (size_t) ic) {#if defined(HAVE_NL_LANGINFO) cdio_info("Failed to get conversion table for locale, trying ASCII"); ic = iconv_open("ASCII", "UCS-2BE"); if (-1 == (size_t) ic) { cdio_info("Failed to get conversion table for ASCII too"); return false; }#else cdio_info("Failed to get conversion table for locale"); return false;#endif } psz_buf = (char *) realloc(psz_buf, i_outlen); psz_buf2 = psz_buf; if (!psz_buf) { /* XXX: report out of memory error */ goto error; } rc = iconv(ic, &psz_ucs2be, &i_inlen, &psz_buf2, &i_outlen); iconv_close(ic); if ((rc == -1) && (errno != E2BIG)) { /* conversion failed */ goto error; } i_outlen_actual = i_outlen_max - i_outlen; *p_psz_out = malloc(i_outlen_actual + 1); memcpy(*p_psz_out, psz_buf, i_outlen_actual); *(*p_psz_out + i_outlen_actual) = '\0'; free(psz_buf); return true; error: free(psz_buf); *p_psz_out = NULL; return false;}#endif /*HAVE_JOLIET*//*! Return the application ID. NULL is returned in psz_app_id if there is some problem in getting this.*/booliso9660_ifs_get_application_id(iso9660_t *p_iso, /*out*/ char **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 ( ucs2be_to_locale(p_iso->svd.application_id, ISO_MAX_APPLICATION_ID, p_psz_app_id, ISO_MAX_APPLICATION_ID)) 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.*/booliso9660_ifs_get_preparer_id(iso9660_t *p_iso, /*out*/ char **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 ( ucs2be_to_locale(p_iso->svd.preparer_id, ISO_MAX_PREPARER_ID, p_psz_preparer_id, ISO_MAX_PREPARER_ID) ) 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*/ char **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( ucs2be_to_locale(p_iso->svd.publisher_id, ISO_MAX_PUBLISHER_ID, p_psz_publisher_id, ISO_MAX_PUBLISHER_ID) ) 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*/ char **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 ( ucs2be_to_locale(p_iso->svd.system_id, ISO_MAX_SYSTEM_ID, p_psz_system_id, ISO_MAX_SYSTEM_ID) ) 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*/ char **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 ( ucs2be_to_locale(p_iso->svd.volume_id, ISO_MAX_VOLUME_ID, p_psz_volume_id, ISO_MAX_VOLUME_ID) ) 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*/ char **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 ( ucs2be_to_locale(p_iso->svd.volume_set_id, ISO_MAX_VOLUMESET_ID, p_psz_volumeset_id, ISO_MAX_VOLUMESET_ID) ) return true; }#endif /*HAVE_JOLIET*/ *p_psz_volumeset_id = iso9660_get_volume_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.*/bool iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd){ if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) { cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); return false; } return check_pvd(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_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)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -