Add routine for extracing ISO 9660 long time format and probably correct

the short-time format a little.

Handle Rock-Ridge time and be able to display it.
This pretty much completes the bulk of handling Rock-Ridge extensions.
This commit is contained in:
rocky
2005-02-22 02:02:46 +00:00
parent ec0564dfee
commit a2fccc90c4
5 changed files with 183 additions and 105 deletions

View File

@@ -1,5 +1,5 @@
/*
$Id: iso9660.h,v 1.71 2005/02/21 09:00:53 rocky Exp $
$Id: iso9660.h,v 1.72 2005/02/22 02:02:46 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -49,6 +49,7 @@ 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 */
@@ -232,7 +233,9 @@ typedef struct iso9660_dtime_s iso9660_dtime_t;
/*!
\brief ISO-9660 longer-format time structure.
Section 8.4.26.1 of ECMA 119
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
*/
@@ -244,14 +247,17 @@ struct iso9660_ltime_s {
1..12. Note starts
at 1, not 0 like a
tm struct. */
char lt_day [_delta( 7, 8)];
char lt_hour [_delta( 9, 10)];
char lt_minute [_delta( 11, 12)];
char lt_second [_delta( 13, 14)];
char lt_hsecond [_delta( 15, 16)]; /**<! The value is in
char lt_day [_delta( 7, 8)]; /**< Day of month: 1..31 */
char lt_hour [_delta( 9, 10)]; /**< hour: 0..23 */
char lt_minute [_delta( 11, 12)]; /**< minute: 0..59 */
char lt_second [_delta( 13, 14)]; /**< second: 0..59 */
char lt_hsecond [_delta( 15, 16)]; /**< The value is in
units of 1/100's of
a second */
int8_t lt_gmtoff [_delta( 17, 17)];
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;
@@ -693,10 +699,17 @@ typedef struct _iso9660_s iso9660_t;
If tm is to reflect the localtime, set "use_localtime" true, otherwise
tm will reported in GMT.
*/
void iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool use_localtime,
bool iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool use_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);
/*====================================================
Characters used in file and directory and manipulation
====================================================*/

View File

@@ -1,5 +1,5 @@
/*
$Id: iso9660.c,v 1.5 2005/02/20 17:47:01 rocky Exp $
$Id: iso9660.c,v 1.6 2005/02/22 02:02:46 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -44,7 +44,11 @@ const char ISO_STANDARD_ID[] = {'C', 'D', '0', '0', '1'};
#include <stdio.h>
#endif
static const char _rcsid[] = "$Id: iso9660.c,v 1.5 2005/02/20 17:47:01 rocky Exp $";
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
static const char _rcsid[] = "$Id: iso9660.c,v 1.6 2005/02/22 02:02:46 rocky Exp $";
/* Variables to hold debugger-helping enumerations */
enum iso_enums1 iso_enums1;
@@ -93,14 +97,11 @@ pathtable_get_size_and_entries(const void *pt, unsigned int *size,
If tm is to reflect the localtime set b_localtime true, otherwise
tm will reported in GMT.
*/
void
bool
iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime,
/*out*/ struct tm *p_tm)
{
time_t t;
struct tm *p_temp_tm;
if (!idr_date) return;
if (!idr_date) return false;
memset(p_tm, 0, sizeof(struct tm));
p_tm->tm_year = idr_date->dt_year;
@@ -109,19 +110,14 @@ iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime,
p_tm->tm_hour = idr_date->dt_hour;
p_tm->tm_min = idr_date->dt_minute;
p_tm->tm_sec = idr_date->dt_second;
p_tm->tm_gmtoff = - timezone * 15;
p_tm->tm_isdst = -1; /* information not available */
#if defined(HAVE_TM_GMTOFF) && defined(HAVE_TZSET)
if (b_localtime) {
tzset();
#if defined(HAVE_TZNAME)
p_tm->tm_zone = (char *) tzname;
#endif
#if defined(HAVE_DAYLIGHT)
p_tm->tm_isdst = daylight;
p_tm->tm_gmtoff = timezone;
#endif
}
#endif
{
time_t t;
struct tm *p_temp_tm;
/* Recompute tm_wday and tm_yday via mktime. */
t = mktime(p_tm);
@@ -133,6 +129,49 @@ iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime,
memcpy(p_tm, p_temp_tm, sizeof(struct tm));
}
return true;
}
#define set_ltime_field(TM_FIELD, LT_FIELD, ADD_CONSTANT) \
{ \
p_tm->TM_FIELD = strtol(p_ldate->LT_FIELD, \
(char **)NULL, 10)+ADD_CONSTANT; \
if (0 != errno) return false; \
}
/*!
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, 0);
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 */
p_tm->tm_gmtoff = - timezone * 15;
/* Recompute tm_wday and tm_yday via mktime. */
{
time_t t;
struct tm *p_temp_tm;
t = mktime(p_tm);
p_temp_tm = gmtime(&t);
p_tm->tm_wday = p_temp_tm->tm_wday;
p_tm->tm_yday = p_temp_tm->tm_yday;
}
return true;
}
/*!
Set time in format used in ISO 9660 directory index record

View File

@@ -1,5 +1,5 @@
/*
$Id: rock.c,v 1.9 2005/02/21 09:00:53 rocky Exp $
$Id: rock.c,v 1.10 2005/02/22 02:02:46 rocky Exp $
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
Adapted from GNU/Linux fs/isofs/rock.c (C) 1992, 1993 Eric Youngdale
@@ -117,6 +117,7 @@ realloc_symlink(/*in/out*/ iso9660_stat_t *p_stat, uint8_t i_grow)
*/
#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) { \
@@ -263,8 +264,8 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
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;
if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0))
p_stat->rr.i_symlink += 1;
break;
}
@@ -383,37 +384,24 @@ parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir,
}
break;
#endif
#ifdef TIME_FIXED
case SIG('T','F'):
/* Time stamp(s) for a file */
{
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. */
/*** FIXME:
Test on long format or not and use
iso9660_get_dtime or iso9660_get_ltime - which needs to be
written.
*/
if (rr->u.TF.flags & ISO_ROCK_TF_CREATE) {
p_stat->rr.st_ctime = rr->u.TF.times[cnt++].time;
}
if(rr->u.TF.flags & ISO_ROCK_TF_MODIFY) {
p_stat->rr.st_mtime = rr->u.TF.times[cnt++].time;
}
if(rr->u.TF.flags & ISO_ROCK_TF_ACCESS) {
p_stat->rr.st_atime = rr->u.TF.times[cnt++].time;
}
if(rr->u.TF.flags & ISO_ROCK_TF_ATTRIBUTES) {
p_stat->rr.st_ctime = rr->u.TF.times[cnt++].time;
}
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;
}
#endif
case SIG('S','L'):
/* Symbolic link. */
{
int slen;
/* Symbolic link */
uint8_t slen;
iso_rock_sl_part_t * p_sl;
iso_rock_sl_part_t * p_oldsl;
slen = rr->len - 5;
@@ -423,45 +411,54 @@ parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir,
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;
/*memcpy(psz_rsymlink, p_sl->text, p_sl->len);
psz_rsymlink+=p_sl->len;*/
break;
case 4:
/**psz_rsymlink++='.';*/
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.';
p_stat->rr.i_symlink++;
/* continue into next case. */
break;
case 2:
/**psz_rsymlink++='.';*/
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.';
p_stat->rr.i_symlink++;
break;
case 8:
rootflag = 1;
/**rootflag = 1;*/
p_stat->rr.i_symlink += 1;
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/';
p_stat->rr.i_symlink++;
break;
default:
cdio_info("Symlink component flag not implemented");
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;
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)
p_stat->rr.i_symlink += 1;
if (!rootflag && (p_oldsl->flags & 1) == 0) {
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_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");

View File

@@ -1,5 +1,5 @@
/*
$Id: cd-info.c,v 1.119 2005/02/21 09:00:53 rocky Exp $
$Id: cd-info.c,v 1.120 2005/02/22 02:02:46 rocky Exp $
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
Copyright (C) 1996, 1997, 1998 Gerd Knorr <kraxel@bytesex.org>

View File

@@ -1,5 +1,5 @@
/*
$Id: util.c,v 1.42 2005/02/21 09:00:53 rocky Exp $
$Id: util.c,v 1.43 2005/02/22 02:02:46 rocky Exp $
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -464,13 +464,15 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa,
char date_str[30];
if (yep == p_statbuf->rr.b3_rock && b_rock) {
report (stdout, " %s %d %d %d [LSN %6lu] %9u",
report ( stdout, " %s %3d %d %d [LSN %6lu] %9u",
iso9660_get_rock_attr_str (p_statbuf->rr.st_mode),
p_statbuf->rr.st_nlinks,
p_statbuf->rr.st_uid,
p_statbuf->rr.st_gid,
(long unsigned int) p_statbuf->lsn,
(unsigned int) p_statbuf->size);
S_ISLNK(p_statbuf->rr.st_mode)
? strlen(p_statbuf->rr.psz_symlink)
: (unsigned int) p_statbuf->size );
} else if (b_xa) {
report ( stdout, " %s %d %d [fn %.2d] [LSN %6lu] ",
@@ -492,16 +494,43 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa,
(long unsigned int) p_statbuf->lsn,
(unsigned int) p_statbuf->size );
}
strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M ", &p_statbuf->tm);
report (stdout," %s %s", date_str,
yep == p_statbuf->rr.b3_rock && b_rock
? psz_name_untranslated : psz_name_translated);
if (yep == p_statbuf->rr.b3_rock && b_rock
&& S_ISLNK(p_statbuf->rr.st_mode)) {
if (yep == p_statbuf->rr.b3_rock && b_rock) {
struct tm tm;
strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M ", &p_statbuf->tm);
/* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
Try to handle this correctly for either case. */
if (p_statbuf->rr.create.b_used) {
if (p_statbuf->rr.create.b_longdate) {
iso9660_get_ltime(&p_statbuf->rr.create.t.ltime, &tm);
} else {
iso9660_get_dtime(&p_statbuf->rr.create.t.dtime, true, &tm);
}
strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M ", &p_statbuf->tm);
}
/* Now try the proper field for ctime: attributes */
if (p_statbuf->rr.attributes.b_used) {
if (p_statbuf->rr.create.b_longdate) {
iso9660_get_ltime(&p_statbuf->rr.attributes.t.ltime, &tm);
} else {
iso9660_get_dtime(&p_statbuf->rr.attributes.t.dtime, true, &tm);
}
strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M ", &tm);
}
report (stdout," %s %s", date_str, psz_name_untranslated );
if (S_ISLNK(p_statbuf->rr.st_mode)) {
report(stdout, " -> %s", p_statbuf->rr.psz_symlink);
}
report(stdout, "\n");
} else {
strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M ", &p_statbuf->tm);
report (stdout," %s %s", date_str, psz_name_translated);
}
report(stdout, "\n");
}