Merge in more Rock Ridge code. Not working yet. Hopefully not much
breakage. (But there may be some especially on less-POSIX OS's.)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: iso9660.h,v 1.64 2005/02/13 00:20:05 rocky Exp $
|
$Id: iso9660.h,v 1.65 2005/02/13 22:03:00 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -255,6 +255,8 @@ struct iso9660_ltime_s {
|
|||||||
} GNUC_PACKED;
|
} GNUC_PACKED;
|
||||||
|
|
||||||
typedef struct iso9660_ltime_s iso9660_ltime_t;
|
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 <cdio/rock.h>
|
#include <cdio/rock.h>
|
||||||
|
|
||||||
@@ -302,8 +304,6 @@ struct iso9660_dir_s {
|
|||||||
char filename[EMPTY_ARRAY_SIZE];
|
char filename[EMPTY_ARRAY_SIZE];
|
||||||
} GNUC_PACKED;
|
} GNUC_PACKED;
|
||||||
|
|
||||||
typedef struct iso9660_dir_s iso9660_dir_t;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief ISO-9660 Primary Volume Descriptor.
|
\brief ISO-9660 Primary Volume Descriptor.
|
||||||
*/
|
*/
|
||||||
@@ -521,6 +521,23 @@ PRAGMA_END_PACKED
|
|||||||
@see iso9660_dir
|
@see iso9660_dir
|
||||||
*/
|
*/
|
||||||
struct iso9660_stat_s { /* big endian!! */
|
struct iso9660_stat_s { /* big endian!! */
|
||||||
|
bool b_rock; /**< has Rock Ridge extension.
|
||||||
|
If not true then the next 7 feilds
|
||||||
|
aren't used.
|
||||||
|
*/
|
||||||
|
mode_t st_mode; /**< protection */
|
||||||
|
nlink_t st_nlinks; /**< number of hard links */
|
||||||
|
uid_t st_uid; /**< user ID of owner */
|
||||||
|
gid_t st_gid; /**< group ID of owner */
|
||||||
|
uint8_t s_rock_offset;
|
||||||
|
int i_size;
|
||||||
|
#if 0
|
||||||
|
time_t st_atime; /**< time of last access */
|
||||||
|
time_t st_mtime; /**< time of last modification */
|
||||||
|
time_t st_ctime; /**< time of last change */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Non Ridge-specific fields */
|
||||||
struct tm tm; /**< time on entry */
|
struct tm tm; /**< time on entry */
|
||||||
lsn_t lsn; /**< start logical sector number */
|
lsn_t lsn; /**< start logical sector number */
|
||||||
uint32_t size; /**< total size in bytes */
|
uint32_t size; /**< total size in bytes */
|
||||||
@@ -530,9 +547,6 @@ struct iso9660_stat_s { /* big endian!! */
|
|||||||
char filename[EMPTY_ARRAY_SIZE]; /**< filename */
|
char filename[EMPTY_ARRAY_SIZE]; /**< filename */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct iso9660_stat_s iso9660_stat_t;
|
|
||||||
|
|
||||||
|
|
||||||
/** A mask used in iso9660_ifs_read_vd which allows what kinds
|
/** A mask used in iso9660_ifs_read_vd which allows what kinds
|
||||||
of extensions we allow, eg. Joliet, Rock Ridge, etc. */
|
of extensions we allow, eg. Joliet, Rock Ridge, etc. */
|
||||||
typedef uint8_t iso_extension_mask_t;
|
typedef uint8_t iso_extension_mask_t;
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
$Id: rock.h,v 1.1 2005/02/13 00:20:05 rocky Exp $
|
$Id: rock.h,v 1.2 2005/02/13 22:03:00 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
See also rock.c by Eric Youngdale (1993) from GNU/Linux and in cdrtools.
|
See also rock.c by Eric Youngdale (1993) from GNU/Linux
|
||||||
This is
|
This is Copyright 1993 Yggdrasil Computing, Incorporated
|
||||||
|
|
||||||
Copyright 1993 Yggdrasil Computing, Incorporated
|
|
||||||
|
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
@@ -70,15 +68,41 @@ extern enum cdio_rock_enums {
|
|||||||
|
|
||||||
PRAGMA_BEGIN_PACKED
|
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 Section 4.1.2 */
|
/*! POSIX file attributes, PX. See Section 4.1.2 */
|
||||||
typedef struct iso_rock_px_s {
|
typedef struct iso_rock_px_s {
|
||||||
iso733_t st_mode; /*! file mode permissions; same as st_mode
|
iso733_t st_mode; /*! file mode permissions; same as st_mode
|
||||||
of POSIX:5.6.1 */
|
of POSIX:5.6.1 */
|
||||||
iso733_t st_links; /*! number of links to file; same as st_links
|
iso733_t st_nlinks; /*! number of links to file; same as st_nlinks
|
||||||
of POSIX:5.6.1 */
|
of POSIX:5.6.1 */
|
||||||
iso733_t st_uid; /*! user id owner of file; same as st_uid
|
iso733_t st_uid; /*! user id owner of file; same as st_uid
|
||||||
of POSIX:5.6.1 */
|
of POSIX:5.6.1 */
|
||||||
iso733_t gid; /*! group id of file; same as st_gid of
|
iso733_t st_gid; /*! group id of file; same as st_gid of
|
||||||
of POSIX:5.6.1 */
|
of POSIX:5.6.1 */
|
||||||
} GNUC_PACKED iso_rock_px_t ;
|
} GNUC_PACKED iso_rock_px_t ;
|
||||||
|
|
||||||
@@ -97,11 +121,29 @@ typedef struct iso_rock_pn_s {
|
|||||||
7.2.3 encoded */
|
7.2.3 encoded */
|
||||||
} GNUC_PACKED iso_rock_pn_t ;
|
} GNUC_PACKED iso_rock_pn_t ;
|
||||||
|
|
||||||
/*! Symbolic link. See Section 4.1.3 */
|
/*! These are the bits and their meanings for flags in the SL structure. */
|
||||||
typedef struct iso_rock_sl_s {
|
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 {
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
unsigned char len;
|
unsigned char len;
|
||||||
char text[EMPTY_ARRAY_SIZE];
|
char text[EMPTY_ARRAY_SIZE];
|
||||||
|
} GNUC_PACKED iso_rock_sl_part_t ;
|
||||||
|
|
||||||
|
/*! Symbolic link. See 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 ;
|
} GNUC_PACKED iso_rock_sl_t ;
|
||||||
|
|
||||||
/*! Alternate name. See Section 4.1.4 */
|
/*! Alternate name. See Section 4.1.4 */
|
||||||
@@ -120,7 +162,7 @@ typedef struct iso_rock_pl_s {
|
|||||||
char location[1];
|
char location[1];
|
||||||
} GNUC_PACKED iso_rock_pl_t ;
|
} GNUC_PACKED iso_rock_pl_t ;
|
||||||
|
|
||||||
/* These are the bits and their meanings for flags in the TF structure. */
|
/*! These are the bits and their meanings for flags in the TF structure. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ISO_ROCK_TF_CREATE = 1,
|
ISO_ROCK_TF_CREATE = 1,
|
||||||
ISO_ROCK_TF_MODIFY = 2,
|
ISO_ROCK_TF_MODIFY = 2,
|
||||||
@@ -155,35 +197,38 @@ typedef struct iso_rock_sf_s {
|
|||||||
uint8_t table_depth;
|
uint8_t table_depth;
|
||||||
} GNUC_PACKED iso_rock_sf_t ;
|
} GNUC_PACKED iso_rock_sf_t ;
|
||||||
|
|
||||||
/*! GNU/Linux-specific extension for transparent decompression. */
|
typedef struct iso_extension_record_s {
|
||||||
typedef struct iso_rock_zf_s {
|
|
||||||
char algorithm[2];
|
|
||||||
char parms[2];
|
|
||||||
char real_size[8];
|
|
||||||
} GNUC_PACKED iso_rock_zf_t ;
|
|
||||||
|
|
||||||
typedef struct iso_rock_ridge_s {
|
|
||||||
char signature[2]; /**< signature word; either 'SP', 'CE', 'ER', 'RR',
|
char signature[2]; /**< signature word; either 'SP', 'CE', 'ER', 'RR',
|
||||||
'PX', 'PN', 'SL', 'NM', 'CL', 'PL', 'TF', or
|
'PX', 'PN', 'SL', 'NM', 'CL', 'PL', 'TF', or
|
||||||
'ZF' */
|
'ZF' */
|
||||||
iso711_t len; /** length of system-user area - 44 for PX
|
iso711_t len; /**< length of system-user area - 44 for PX
|
||||||
20 for PN, 5+strlen(text) for SL. */
|
20 for PN, 5+strlen(text) for SL, 21 for
|
||||||
iso711_t version; /** version number - value 1 */
|
SF, etc. */
|
||||||
|
iso711_t version; /**< version number - value 1 */
|
||||||
union{
|
union{
|
||||||
iso_rock_px_t PX;
|
iso_su_sp_t SP; /**< system-use-sharing protocol - not
|
||||||
iso_rock_pn_t PN;
|
strictly part of Rock Ridge */
|
||||||
iso_rock_sl_t SL;
|
iso_su_er_t ER; /**< system-use extension packet - not
|
||||||
iso_rock_nm_t NM;
|
strictly part of Rock Ridge */
|
||||||
iso_rock_cl_t CL;
|
iso_su_ce_t CE; /**< system-use - strictly part of Rock Ridge */
|
||||||
iso_rock_pl_t PL;
|
iso_rock_px_t PX; /**< Rock Ridge POSIX file attributes */
|
||||||
iso_rock_tf_t TF;
|
iso_rock_pn_t PN; /**< Rock Ridge POSIX device number */
|
||||||
iso_rock_zf_t SF;
|
iso_rock_sl_t SL; /**< Rock Ridge symbolic link */
|
||||||
iso_rock_zf_t ZF;
|
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;
|
} u;
|
||||||
} GNUC_PACKED iso_rock_ridge_t;
|
} GNUC_PACKED iso_extension_record_t;
|
||||||
|
|
||||||
PRAGMA_END_PACKED
|
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);
|
||||||
|
|
||||||
#endif /* __ISO_ROCK_H__ */
|
#endif /* __ISO_ROCK_H__ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile.am,v 1.4 2005/01/27 03:26:37 rocky Exp $
|
# $Id: Makefile.am,v 1.5 2005/02/13 22:03:00 rocky Exp $
|
||||||
#
|
#
|
||||||
# Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
# Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
#
|
#
|
||||||
@@ -56,6 +56,7 @@ libiso9660_la_SOURCES = \
|
|||||||
iso9660.c \
|
iso9660.c \
|
||||||
iso9660_private.h \
|
iso9660_private.h \
|
||||||
iso9660_fs.c \
|
iso9660_fs.c \
|
||||||
|
rock.c \
|
||||||
xa.c
|
xa.c
|
||||||
|
|
||||||
libiso9660_la_LIBADD = @LIBCDIO_LIBS@
|
libiso9660_la_LIBADD = @LIBCDIO_LIBS@
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: iso9660_fs.c,v 1.12 2005/02/12 10:23:18 rocky Exp $
|
$Id: iso9660_fs.c,v 1.13 2005/02/13 22:03:00 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
/* iso9660 filesystem-based routines */
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.12 2005/02/12 10:23:18 rocky Exp $";
|
static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.13 2005/02/13 22:03:00 rocky Exp $";
|
||||||
|
|
||||||
/* Implementation of iso9660_t type */
|
/* Implementation of iso9660_t type */
|
||||||
struct _iso9660_s {
|
struct _iso9660_s {
|
||||||
@@ -517,7 +518,7 @@ bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif /*HAVE_JOLIET*/
|
#endif /*HAVE_JOLIET*/
|
||||||
*p_psz_volumeset_id = iso9660_get_volume_id( &(p_iso->pvd) );
|
*p_psz_volumeset_id = iso9660_get_volumeset_id( &(p_iso->pvd) );
|
||||||
return *p_psz_volumeset_id != NULL && strlen(*p_psz_volumeset_id);
|
return *p_psz_volumeset_id != NULL && strlen(*p_psz_volumeset_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
347
lib/iso9660/rock.c
Normal file
347
lib/iso9660/rock.c
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
/*
|
||||||
|
$Id: rock.c,v 1.1 2005/02/13 22:03:00 rocky Exp $
|
||||||
|
|
||||||
|
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
|
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 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
|
||||||
|
*/
|
||||||
|
/* Rock Ridge Extensions to iso9660 */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cdio/iso9660.h>
|
||||||
|
#include <cdio/logging.h>
|
||||||
|
#include <cdio/bytesex.h>
|
||||||
|
|
||||||
|
/* 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->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);}
|
||||||
|
|
||||||
|
#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->s_rock_offset) \
|
||||||
|
{ \
|
||||||
|
LEN -= p_stat->s_rock_offset; \
|
||||||
|
CHR += p_stat->s_rock_offset; \
|
||||||
|
if (LEN<0) LEN=0; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! 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 len;
|
||||||
|
unsigned char *chr;
|
||||||
|
CONTINUE_DECLS;
|
||||||
|
int retnamlen = 0, truncate=0;
|
||||||
|
|
||||||
|
if (!p_stat || !p_stat->b_rock) return 0;
|
||||||
|
*retname = 0;
|
||||||
|
|
||||||
|
SETUP_ROCK_RIDGE(de, chr, len);
|
||||||
|
/* repeat:*/
|
||||||
|
{
|
||||||
|
iso_extension_record_t * rr;
|
||||||
|
int sig;
|
||||||
|
|
||||||
|
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('N','M'):
|
||||||
|
if (truncate) break;
|
||||||
|
/*
|
||||||
|
* If the flags are 2 or 4, this indicates '.' or '..'.
|
||||||
|
* We don't want to do anything with this, because it
|
||||||
|
* screws up the code that calls us. We don't really
|
||||||
|
* care anyways, since we can just use the non-RR
|
||||||
|
* name.
|
||||||
|
*/
|
||||||
|
if (rr->u.NM.flags & 6) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rr->u.NM.flags & ~1) {
|
||||||
|
cdio_info("Unsupported NM flag settings (%d)",rr->u.NM.flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((strlen(retname) + rr->len - 5) >= 254) {
|
||||||
|
truncate = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strncat(retname, rr->u.NM.name, rr->len - 5);
|
||||||
|
retnamlen += rr->len - 5;
|
||||||
|
break;
|
||||||
|
case SIG('R','E'):
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
return retnamlen; /* 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 *de,
|
||||||
|
iso9660_stat_t *p_stat, int regard_xa)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned char * chr;
|
||||||
|
int symlink_len = 0;
|
||||||
|
CONTINUE_DECLS;
|
||||||
|
|
||||||
|
if (!p_stat->b_rock) return 0;
|
||||||
|
|
||||||
|
SETUP_ROCK_RIDGE(de, 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->b_rock = 1;
|
||||||
|
cdio_debug("ISO 9660 Extensions: ");
|
||||||
|
{ int p;
|
||||||
|
for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SIG('P','X'):
|
||||||
|
p_stat->st_mode = from_733(rr->u.PX.st_mode);
|
||||||
|
p_stat->st_nlinks = from_733(rr->u.PX.st_nlinks);
|
||||||
|
p_stat->st_uid = from_733(rr->u.PX.st_uid);
|
||||||
|
p_stat->st_gid = from_733(rr->u.PX.st_gid);
|
||||||
|
break;
|
||||||
|
#ifdef DEV_FINISHED
|
||||||
|
case SIG('P','N'):
|
||||||
|
{ int 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->i_rdev = MKDEV(low >> 8, low & 0xff);
|
||||||
|
} else {
|
||||||
|
p_stat->i_rdev = MKDEV(high, low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if TIME_FINISHED
|
||||||
|
case SIG('T','F'):
|
||||||
|
{
|
||||||
|
int cnt = 0; /* Rock ridge never appears on a High Sierra disk */
|
||||||
|
/* Some RRIP writers incorrectly place ctime in the
|
||||||
|
ISO_ROCK_TF_CREATE field. Try to handle this correctly for
|
||||||
|
either case. */
|
||||||
|
if(rr->u.TF.flags & ISO_ROCK_TF_CREATE) {
|
||||||
|
p_stat->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
|
||||||
|
p_stat->i_ctime.tv_nsec = 0;
|
||||||
|
}
|
||||||
|
if(rr->u.TF.flags & ISO_ROCK_TF_MODIFY) {
|
||||||
|
p_stat->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
|
||||||
|
p_stat->i_mtime.tv_nsec = 0;
|
||||||
|
}
|
||||||
|
if(rr->u.TF.flags & ISO_ROCK_TF_ACCESS) {
|
||||||
|
p_stat->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
|
||||||
|
p_stat->i_atime.tv_nsec = 0;
|
||||||
|
}
|
||||||
|
if(rr->u.TF.flags & ISO_ROCK_TF_ATTRIBUTES) {
|
||||||
|
p_stat->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
|
||||||
|
p_stat->i_ctime.tv_nsec = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* TIME_FINISHED */
|
||||||
|
case SIG('S','L'):
|
||||||
|
{int slen;
|
||||||
|
iso_rock_sl_part_t *slp;
|
||||||
|
iso_rock_sl_part_t *oldslp;
|
||||||
|
slen = rr->len - 5;
|
||||||
|
slp = &rr->u.SL.link;
|
||||||
|
p_stat->i_size = symlink_len;
|
||||||
|
while (slen > 1){
|
||||||
|
rootflag = 0;
|
||||||
|
switch(slp->flags &~1){
|
||||||
|
case 0:
|
||||||
|
p_stat->i_size += slp->len;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
p_stat->i_size += 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
p_stat->i_size += 2;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
rootflag = 1;
|
||||||
|
p_stat->i_size += 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cdio_info("Symlink component flag not implemented");
|
||||||
|
}
|
||||||
|
slen -= slp->len + 2;
|
||||||
|
oldslp = slp;
|
||||||
|
slp = (iso_rock_sl_part_t *) (((char *) slp) + slp->len + 2);
|
||||||
|
|
||||||
|
if(slen < 2) {
|
||||||
|
if( ((rr->u.SL.flags & 1) != 0)
|
||||||
|
&& ((oldslp->flags & 1) == 0) ) p_stat->i_size += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this component record isn't continued, then append a '/'.
|
||||||
|
*/
|
||||||
|
if (!rootflag && (oldslp->flags & 1) == 0)
|
||||||
|
p_stat->i_size += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
symlink_len = p_stat->i_size;
|
||||||
|
break;
|
||||||
|
case SIG('R','E'):
|
||||||
|
cdio_warn("Attempt to read p_stat for relocated directory");
|
||||||
|
goto out;
|
||||||
|
#if 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->i_sb, p_stat->i_first_extent, 0);
|
||||||
|
if (!reloc)
|
||||||
|
goto out;
|
||||||
|
p_stat->st_mode = reloc->st_mode;
|
||||||
|
p_stat->st_nlinks = reloc->st_nlinks;
|
||||||
|
p_stat->st_uid = reloc->st_uid;
|
||||||
|
p_stat->st_gid = reloc->st_gid;
|
||||||
|
p_stat->i_rdev = reloc->i_rdev;
|
||||||
|
p_stat->i_size = reloc->i_size;
|
||||||
|
p_stat->i_blocks = reloc->i_blocks;
|
||||||
|
p_stat->i_atime = reloc->i_atime;
|
||||||
|
p_stat->i_ctime = reloc->i_ctime;
|
||||||
|
p_stat->i_mtime = reloc->i_mtime;
|
||||||
|
iput(reloc);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_rock_ridge_stat(iso9660_dir_t *de, /*out*/ iso9660_stat_t *p_stat)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!p_stat) return 0;
|
||||||
|
|
||||||
|
result = parse_rock_ridge_stat_internal(de, 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->s_rock_offset && p_stat->b_rock) {
|
||||||
|
result = parse_rock_ridge_stat_internal(de, p_stat, 14);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user