2
$Id: iso9660.c,v 1.24 2004/10/30 02:55:17 rocky Exp $
4
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
5
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include "iso9660_private.h"
24
#include "cdio_assert.h"
27
#include <cdio/bytesex.h>
28
#include <cdio/iso9660.h>
29
#include <cdio/util.h>
40
static const char _rcsid[] = "$Id: iso9660.c,v 1.24 2004/10/30 02:55:17 rocky Exp $";
42
/* some parameters... */
43
#define SYSTEM_ID "CD-RTOS CD-BRIDGE"
44
#define VOLUME_SET_ID ""
47
Change trailing blanks in str to nulls. Str has a maximum size of
51
strip_trail (const char str[], size_t n)
53
static char buf[1024];
56
cdio_assert (n < 1024);
58
strncpy (buf, str, n);
61
for (j = strlen (buf) - 1; j >= 0; j--)
73
pathtable_get_size_and_entries(const void *pt, unsigned int *size,
74
unsigned int *entries);
77
Get time structure from structure in an ISO 9660 directory index
78
record. Even though tm_wday and tm_yday fields are not explicitly in
79
idr_date, the are calculated from the other fields.
81
If tm is to reflect the localtime set b_localtime true, otherwise
82
tm will reported in GMT.
85
iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime,
86
/*out*/ struct tm *p_tm)
91
if (!idr_date) return;
93
memset(p_tm, 0, sizeof(struct tm));
94
p_tm->tm_year = idr_date->dt_year;
95
p_tm->tm_mon = idr_date->dt_month - 1;
96
p_tm->tm_mday = idr_date->dt_day;
97
p_tm->tm_hour = idr_date->dt_hour;
98
p_tm->tm_min = idr_date->dt_minute;
99
p_tm->tm_sec = idr_date->dt_second;
101
#if defined(HAVE_TM_GMTOFF) && defined(HAVE_TZSET)
104
#if defined(HAVE_TZNAME)
105
p_tm->tm_zone = (char *) tzname;
107
#if defined(HAVE_DAYLIGHT)
108
p_tm->tm_isdst = daylight;
109
p_tm->tm_gmtoff = timezone;
114
/* Recompute tm_wday and tm_yday via mktime. */
118
p_temp_tm = localtime(&t);
120
p_temp_tm = gmtime(&t);
122
memcpy(p_tm, p_temp_tm, sizeof(struct tm));
126
Set time in format used in ISO 9660 directory index record
127
from a Unix time structure. */
129
iso9660_set_dtime (const struct tm *p_tm, /*out*/ iso9660_dtime_t *p_idr_date)
131
memset (p_idr_date, 0, 7);
135
p_idr_date->dt_year = p_tm->tm_year;
136
p_idr_date->dt_month = p_tm->tm_mon + 1;
137
p_idr_date->dt_day = p_tm->tm_mday;
138
p_idr_date->dt_hour = p_tm->tm_hour;
139
p_idr_date->dt_minute = p_tm->tm_min;
140
p_idr_date->dt_second = p_tm->tm_sec;
142
#ifdef HAVE_TM_GMTOFF
143
/* The ISO 9660 timezone is in the range -48..+52 and each unit
144
represents a 15-minute interval. */
145
p_idr_date->dt_gmtoff = p_tm->tm_gmtoff / (15 * 60);
147
if (p_tm->tm_isdst) p_idr_date->dt_gmtoff -= 4;
149
if (p_idr_date->dt_gmtoff < -48 ) {
151
cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted",
152
p_idr_date->dt_gmtoff);
153
p_idr_date->dt_gmtoff = -48;
154
} else if (p_idr_date->dt_gmtoff > 52) {
155
cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted",
156
p_idr_date->dt_gmtoff);
157
p_idr_date->dt_gmtoff = 52;
160
p_idr_date->dt_gmtoff = 0;
165
Set "long" time in format used in ISO 9660 primary volume descriptor
166
from a Unix time structure. */
168
iso9660_set_ltime (const struct tm *_tm, /*out*/ iso9660_ltime_t *pvd_date)
170
char *_pvd_date = (char *) pvd_date;
172
memset (_pvd_date, '0', 16);
173
_pvd_date[16] = (int8_t) 0; /* tz */
177
snprintf(_pvd_date, 17,
178
"%4.4d%2.2d%2.2d" "%2.2d%2.2d%2.2d" "%2.2d",
179
_tm->tm_year + 1900, _tm->tm_mon + 1, _tm->tm_mday,
180
_tm->tm_hour, _tm->tm_min, _tm->tm_sec,
181
0 /* 1/100 secs */ );
183
_pvd_date[16] = (int8_t) 0; /* tz */
187
Convert ISO-9660 file name that stored in a directory entry into
188
what's usually listed as the file name in a listing.
189
Lowercase name, and remove trailing ;1's or .;1's and
190
turn the other ;'s into version numbers.
192
The length of the translated string is returned.
195
iso9660_name_translate(const char *old, char *new)
197
return iso9660_name_translate_ext(old, new, 0);
201
Convert ISO-9660 file name that stored in a directory entry into
202
what's usually listed as the file name in a listing. Lowercase
203
name if not using Joliet extension. Remove trailing ;1's or .;1's and
204
turn the other ;'s into version numbers.
206
The length of the translated string is returned.
209
iso9660_name_translate_ext(const char *old, char *new, uint8_t i_joliet_level)
211
int len = strlen(old);
214
for (i = 0; i < len; i++) {
215
unsigned char c = old[i];
219
/* Lower case, unless we have Joliet extensions. */
220
if (!i_joliet_level && isupper(c)) c = tolower(c);
222
/* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
223
if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
226
/* Drop trailing ';1' */
227
if (c == ';' && i == len - 2 && old[i + 1] == '1')
230
/* Convert remaining ';' to '.' */
241
Pad string src with spaces to size len and copy this to dst. If
242
len is less than the length of src, dst will be truncated to the
243
first len characters of src.
245
src can also be scanned to see if it contains only ACHARs, DCHARs,
246
7-bit ASCII chars depending on the enumeration _check.
248
In addition to getting changed, dst is the return value.
249
Note: this string might not be NULL terminated.
252
iso9660_strncpy_pad(char dst[], const char src[], size_t len,
253
enum strncpy_pad_check _check)
257
cdio_assert (dst != NULL);
258
cdio_assert (src != NULL);
259
cdio_assert (len > 0);
264
case ISO9660_NOCHECK:
268
for (idx = 0; src[idx]; idx++)
269
if ((int8_t) src[idx] < 0)
271
cdio_warn ("string '%s' fails 7bit constraint (pos = %d)",
278
for (idx = 0; src[idx]; idx++)
279
if (!iso9660_isachar (src[idx]))
281
cdio_warn ("string '%s' fails a-character constraint (pos = %d)",
288
for (idx = 0; src[idx]; idx++)
289
if (!iso9660_isdchar (src[idx]))
291
cdio_warn ("string '%s' fails d-character constraint (pos = %d)",
298
cdio_assert_not_reached ();
305
cdio_warn ("string '%s' is getting truncated to %d characters",
306
src, (unsigned int) len);
308
strncpy (dst, src, len);
310
memset(dst+rlen, ' ', len-rlen);
315
Return true if c is a DCHAR - a valid ISO-9660 level 1 character.
316
These are the ASCSII capital letters A-Z, the digits 0-9 and an
320
iso9660_isdchar (int c)
322
if (!IN (c, 0x30, 0x5f)
323
|| IN (c, 0x3a, 0x40)
324
|| IN (c, 0x5b, 0x5e))
332
Return true if c is an ACHAR -
333
These are the DCHAR's plus some ASCII symbols including the space
337
iso9660_isachar (int c)
339
if (!IN (c, 0x20, 0x5f)
340
|| IN (c, 0x23, 0x24)
342
|| IN (c, 0x5b, 0x5e))
349
iso9660_set_evd(void *pd)
351
struct iso_volume_descriptor ied;
353
cdio_assert (sizeof(struct iso_volume_descriptor) == ISO_BLOCKSIZE);
355
cdio_assert (pd != NULL);
357
memset(&ied, 0, sizeof(ied));
359
ied.type = to_711(ISO_VD_END);
360
iso9660_strncpy_pad (ied.id, ISO_STANDARD_ID, sizeof(ied.id), ISO9660_DCHARS);
361
ied.version = to_711(ISO_VERSION);
363
memcpy(pd, &ied, sizeof(ied));
367
iso9660_set_pvd(void *pd,
368
const char volume_id[],
369
const char publisher_id[],
370
const char preparer_id[],
371
const char application_id[],
373
const void *root_dir,
374
uint32_t path_table_l_extent,
375
uint32_t path_table_m_extent,
376
uint32_t path_table_size,
377
const time_t *pvd_time
382
cdio_assert (sizeof(iso9660_pvd_t) == ISO_BLOCKSIZE);
384
cdio_assert (pd != NULL);
385
cdio_assert (volume_id != NULL);
386
cdio_assert (application_id != NULL);
388
memset(&ipd,0,sizeof(ipd)); /* paranoia? */
390
/* magic stuff ... thatis CD XA marker... */
391
strcpy(((char*)&ipd)+ISO_XA_MARKER_OFFSET, ISO_XA_MARKER_STRING);
393
ipd.type = to_711(ISO_VD_PRIMARY);
394
iso9660_strncpy_pad (ipd.id, ISO_STANDARD_ID, 5, ISO9660_DCHARS);
395
ipd.version = to_711(ISO_VERSION);
397
iso9660_strncpy_pad (ipd.system_id, SYSTEM_ID, 32, ISO9660_ACHARS);
398
iso9660_strncpy_pad (ipd.volume_id, volume_id, 32, ISO9660_DCHARS);
400
ipd.volume_space_size = to_733(iso_size);
402
ipd.volume_set_size = to_723(1);
403
ipd.volume_sequence_number = to_723(1);
404
ipd.logical_block_size = to_723(ISO_BLOCKSIZE);
406
ipd.path_table_size = to_733(path_table_size);
407
ipd.type_l_path_table = to_731(path_table_l_extent);
408
ipd.type_m_path_table = to_732(path_table_m_extent);
410
/* root_directory_record doesn't contain the 1-byte filename,
411
so we add one for that. */
412
cdio_assert (sizeof(ipd.root_directory_record) == 33);
413
memcpy(&(ipd.root_directory_record), root_dir,
414
sizeof(ipd.root_directory_record));
415
ipd.root_directory_filename='\0';
416
ipd.root_directory_record.length = 33+1;
417
iso9660_strncpy_pad (ipd.volume_set_id, VOLUME_SET_ID, 128, ISO9660_DCHARS);
419
iso9660_strncpy_pad (ipd.publisher_id, publisher_id, 128, ISO9660_ACHARS);
420
iso9660_strncpy_pad (ipd.preparer_id, preparer_id, 128, ISO9660_ACHARS);
421
iso9660_strncpy_pad (ipd.application_id, application_id, 128, ISO9660_ACHARS);
423
iso9660_strncpy_pad (ipd.copyright_file_id , "", 37, ISO9660_DCHARS);
424
iso9660_strncpy_pad (ipd.abstract_file_id , "", 37, ISO9660_DCHARS);
425
iso9660_strncpy_pad (ipd.bibliographic_file_id, "", 37, ISO9660_DCHARS);
427
iso9660_set_ltime (gmtime (pvd_time), &(ipd.creation_date));
428
iso9660_set_ltime (gmtime (pvd_time), &(ipd.modification_date));
429
iso9660_set_ltime (NULL, &(ipd.expiration_date));
430
iso9660_set_ltime (NULL, &(ipd.effective_date));
432
ipd.file_structure_version = to_711(1);
434
/* we leave ipd.application_data = 0 */
436
memcpy(pd, &ipd, sizeof(ipd)); /* copy stuff to arg ptr */
440
iso9660_dir_calc_record_size(unsigned int namelen, unsigned int su_len)
444
length = sizeof(iso9660_dir_t);
446
if (length % 2) /* pad to word boundary */
449
if (length % 2) /* pad to word boundary again */
456
iso9660_dir_add_entry_su(void *dir,
457
const char filename[],
462
unsigned int su_size,
463
const time_t *entry_time)
465
iso9660_dir_t *idr = dir;
467
unsigned int offset = 0;
468
uint32_t dsize = from_733(idr->size);
469
int length, su_offset;
470
cdio_assert (sizeof(iso9660_dir_t) == 33);
472
if (!dsize && !idr->length)
473
dsize = ISO_BLOCKSIZE; /* for when dir lacks '.' entry */
475
cdio_assert (dsize > 0 && !(dsize % ISO_BLOCKSIZE));
476
cdio_assert (dir != NULL);
477
cdio_assert (extent > 17);
478
cdio_assert (filename != NULL);
479
cdio_assert (strlen(filename) <= MAX_ISOPATHNAME);
481
length = sizeof(iso9660_dir_t);
482
length += strlen(filename);
483
length = _cdio_ceil2block (length, 2); /* pad to word boundary */
486
length = _cdio_ceil2block (length, 2); /* pad to word boundary again */
488
/* find the last entry's end */
490
unsigned int ofs_last_rec = 0;
493
while (offset < dsize)
501
offset += dir8[offset];
502
ofs_last_rec = offset;
505
cdio_assert (offset == dsize);
507
offset = ofs_last_rec;
510
/* be sure we don't cross sectors boundaries */
511
offset = _cdio_ofs_add (offset, length, ISO_BLOCKSIZE);
514
cdio_assert (offset + length <= dsize);
516
idr = (iso9660_dir_t *) &dir8[offset];
518
cdio_assert (offset+length < dsize);
520
memset(idr, 0, length);
522
idr->length = to_711(length);
523
idr->extent = to_733(extent);
524
idr->size = to_733(size);
526
iso9660_set_dtime (gmtime(entry_time), &(idr->recording_time));
528
idr->file_flags = to_711(file_flags);
530
idr->volume_sequence_number = to_723(1);
532
idr->filename_len = to_711(strlen(filename)
533
? strlen(filename) : 1); /* working hack! */
535
memcpy(idr->filename, filename, from_711(idr->filename_len));
536
memcpy(&dir8[offset] + su_offset, su_data, su_size);
540
iso9660_dir_init_new (void *dir,
545
const time_t *dir_time)
547
iso9660_dir_init_new_su (dir, self, ssize, NULL, 0, parent, psize, NULL,
552
iso9660_dir_init_new_su (void *dir,
555
const void *ssu_data,
556
unsigned int ssu_size,
559
const void *psu_data,
560
unsigned int psu_size,
561
const time_t *dir_time)
563
cdio_assert (ssize > 0 && !(ssize % ISO_BLOCKSIZE));
564
cdio_assert (psize > 0 && !(psize % ISO_BLOCKSIZE));
565
cdio_assert (dir != NULL);
567
memset (dir, 0, ssize);
569
/* "\0" -- working hack due to padding */
570
iso9660_dir_add_entry_su (dir, "\0", self, ssize, ISO_DIRECTORY, ssu_data,
573
iso9660_dir_add_entry_su (dir, "\1", parent, psize, ISO_DIRECTORY, psu_data,
577
/* Zero's out pathable. Do this first. */
579
iso9660_pathtable_init (void *pt)
581
cdio_assert (sizeof (struct iso_path_table) == 8);
583
cdio_assert (pt != NULL);
585
memset (pt, 0, ISO_BLOCKSIZE); /* fixme */
588
static const struct iso_path_table*
589
pathtable_get_entry (const void *pt, unsigned int entrynum)
591
const uint8_t *tmp = pt;
592
unsigned int offset = 0;
593
unsigned int count = 0;
595
cdio_assert (pt != NULL);
597
while (from_711 (*tmp))
599
if (count == entrynum)
602
cdio_assert (count < entrynum);
604
offset += sizeof (struct iso_path_table);
605
offset += from_711 (*tmp);
608
tmp = (uint8_t *)pt + offset;
612
if (!from_711 (*tmp))
615
return (const void *) tmp;
619
pathtable_get_size_and_entries (const void *pt,
621
unsigned int *entries)
623
const uint8_t *tmp = pt;
624
unsigned int offset = 0;
625
unsigned int count = 0;
627
cdio_assert (pt != NULL);
629
while (from_711 (*tmp))
631
offset += sizeof (struct iso_path_table);
632
offset += from_711 (*tmp);
635
tmp = (uint8_t *)pt + offset;
647
iso9660_pathtable_get_size (const void *pt)
649
unsigned int size = 0;
650
pathtable_get_size_and_entries (pt, &size, NULL);
655
iso9660_pathtable_l_add_entry (void *pt,
660
struct iso_path_table *ipt =
661
(struct iso_path_table*)((char *)pt + iso9660_pathtable_get_size (pt));
662
size_t name_len = strlen (name) ? strlen (name) : 1;
663
unsigned int entrynum = 0;
665
cdio_assert (iso9660_pathtable_get_size (pt) < ISO_BLOCKSIZE); /*fixme */
667
memset (ipt, 0, sizeof (struct iso_path_table) + name_len); /* paranoia */
669
ipt->name_len = to_711 (name_len);
670
ipt->extent = to_731 (extent);
671
ipt->parent = to_721 (parent);
672
memcpy (ipt->name, name, name_len);
674
pathtable_get_size_and_entries (pt, NULL, &entrynum);
678
const struct iso_path_table *ipt2
679
= pathtable_get_entry (pt, entrynum - 2);
681
cdio_assert (ipt2 != NULL);
683
cdio_assert (from_721 (ipt2->parent) <= parent);
690
iso9660_pathtable_m_add_entry (void *pt,
695
struct iso_path_table *ipt =
696
(struct iso_path_table*)((char *)pt + iso9660_pathtable_get_size (pt));
697
size_t name_len = strlen (name) ? strlen (name) : 1;
698
unsigned int entrynum = 0;
700
cdio_assert (iso9660_pathtable_get_size(pt) < ISO_BLOCKSIZE); /* fixme */
702
memset(ipt, 0, sizeof (struct iso_path_table) + name_len); /* paranoia */
704
ipt->name_len = to_711 (name_len);
705
ipt->extent = to_732 (extent);
706
ipt->parent = to_722 (parent);
707
memcpy (ipt->name, name, name_len);
709
pathtable_get_size_and_entries (pt, NULL, &entrynum);
713
const struct iso_path_table *ipt2
714
= pathtable_get_entry (pt, entrynum - 2);
716
cdio_assert (ipt2 != NULL);
718
cdio_assert (from_722 (ipt2->parent) <= parent);
725
Check that pathname is a valid ISO-9660 directory name.
727
A valid directory name should not start out with a slash (/),
728
dot (.) or null byte, should be less than 37 characters long,
729
have no more than 8 characters in a directory component
730
which is separated by a /, and consist of only DCHARs.
733
iso9660_dirname_valid_p (const char pathname[])
735
const char *p = pathname;
738
cdio_assert (pathname != NULL);
740
if (*p == '/' || *p == '.' || *p == '\0')
743
if (strlen (pathname) > MAX_ISOPATHNAME)
748
if (iso9660_isdchar (*p))
761
return false; /* unexpected char */
764
return false; /* last char may not be '/' */
770
Check that pathname is a valid ISO-9660 pathname.
772
A valid pathname contains a valid directory name, if one appears and
773
the filename portion should be no more than 8 characters for the
774
file prefix and 3 characters in the extension (or portion after a
775
dot). There should be exactly one dot somewhere in the filename
776
portion and the filename should be composed of only DCHARs.
778
True is returned if pathname is valid.
781
iso9660_pathname_valid_p (const char pathname[])
783
const char *p = NULL;
785
cdio_assert (pathname != NULL);
787
if ((p = strrchr (pathname, '/')))
790
char *_tmp = strdup (pathname);
792
*strrchr (_tmp, '/') = '\0';
794
rc = iso9660_dirname_valid_p (_tmp);
806
if (strlen (pathname) > (MAX_ISOPATHNAME - 6))
814
if (iso9660_isdchar (*p))
817
if (dots == 0 ? len > 8 : len > 3)
840
Take pathname and a version number and turn that into a ISO-9660
841
pathname. (That's just the pathname followd by ";" and the version
842
number. For example, mydir/file.ext -> mydir/file.ext;1 for version
843
1. The resulting ISO-9660 pathname is returned.
846
iso9660_pathname_isofy (const char pathname[], uint16_t version)
848
char tmpbuf[1024] = { 0, };
850
cdio_assert (strlen (pathname) < (sizeof (tmpbuf) - sizeof (";65535")));
852
snprintf (tmpbuf, sizeof(tmpbuf), "%s;%d", pathname, version);
854
return strdup (tmpbuf);
858
Return the PVD's application ID.
859
NULL is returned if there is some problem in getting this.
862
iso9660_get_application_id(iso9660_pvd_t *p_pvd)
864
if (NULL==p_pvd) return NULL;
865
return strdup(strip_trail(p_pvd->application_id, ISO_MAX_APPLICATION_ID));
870
iso9660_get_dir_extent(const iso9660_dir_t *idr)
872
if (NULL == idr) return 0;
873
return from_733(idr->extent);
878
iso9660_get_dir_len(const iso9660_dir_t *idr)
880
if (NULL == idr) return 0;
886
iso9660_get_dir_size(const iso9660_dir_t *idr)
888
if (NULL == idr) return 0;
889
return from_733(idr->size);
894
iso9660_get_pvd_type(const iso9660_pvd_t *pvd)
896
if (NULL == pvd) return 255;
901
iso9660_get_pvd_id(const iso9660_pvd_t *pvd)
903
if (NULL == pvd) return "ERR";
908
iso9660_get_pvd_space_size(const iso9660_pvd_t *pvd)
910
if (NULL == pvd) return 0;
911
return from_733(pvd->volume_space_size);
915
iso9660_get_pvd_block_size(const iso9660_pvd_t *pvd)
917
if (NULL == pvd) return 0;
918
return from_723(pvd->logical_block_size);
921
/*! Return the primary volume id version number (of pvd).
922
If there is an error 0 is returned.
925
iso9660_get_pvd_version(const iso9660_pvd_t *pvd)
927
if (NULL == pvd) return 0;
931
/*! Return the LSN of the root directory for pvd.
932
If there is an error CDIO_INVALID_LSN is returned.
935
iso9660_get_root_lsn(const iso9660_pvd_t *pvd)
938
return CDIO_INVALID_LSN;
940
const iso9660_dir_t *idr = &(pvd->root_directory_record);
941
if (NULL == idr) return CDIO_INVALID_LSN;
942
return(from_733 (idr->extent));
947
Return a string containing the preparer id with trailing
951
iso9660_get_preparer_id(const iso9660_pvd_t *pvd)
953
if (NULL==pvd) return NULL;
954
return strdup(strip_trail(pvd->preparer_id, ISO_MAX_PREPARER_ID));
958
Return a string containing the publisher id with trailing
962
iso9660_get_publisher_id(const iso9660_pvd_t *pvd)
964
if (NULL==pvd) return NULL;
965
return strdup(strip_trail(pvd->publisher_id, ISO_MAX_PUBLISHER_ID));
969
Return a string containing the PVD's system id with trailing
973
iso9660_get_system_id(const iso9660_pvd_t *pvd)
975
if (NULL==pvd) return NULL;
976
return strdup(strip_trail(pvd->system_id, ISO_MAX_SYSTEM_ID));
980
Return the PVD's volume ID.
983
iso9660_get_volume_id(const iso9660_pvd_t *pvd)
985
if (NULL == pvd) return NULL;
986
return strdup(strip_trail(pvd->volume_id, ISO_MAX_VOLUME_ID));
990
Return the PVD's volumeset ID.
991
NULL is returned if there is some problem in getting this.
994
iso9660_get_volumeset_id(const iso9660_pvd_t *pvd)
996
if ( NULL == pvd ) return NULL;
997
return strdup(strip_trail(pvd->volume_set_id, ISO_MAX_VOLUMESET_ID));
1003
* c-file-style: "gnu"
1005
* indent-tabs-mode: nil