1 /*
2 Copyright (C) 2003-2008, 2011-2015, 2017 Rocky Bernstein <rocky@gnu.org>
3 Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /* iso9660 filesystem-based routines */
19
20 /* FIXME: _cdio_list_free for iso9660 statbuf is insufficient because it doesn't
21 free bits that are allocated inside the data. */
22
23
24 #if defined(HAVE_CONFIG_H) && !defined(__CDIO_CONFIG_H__)
25 #include "config.h"
26 #define __CDIO_CONFIG_H__ 1
27 #endif
28
29 #ifdef HAVE_STDBOOL_H
30 # include <stdbool.h>
31 #endif
32
33 #ifdef HAVE_STDIO_H
34 #include <stdio.h>
35 #endif
36
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40
41 #ifdef HAVE_ERRNO_H
42 #include <errno.h>
43 #endif
44
45 #ifdef HAVE_LANGINFO_CODESET
46 #include <langinfo.h>
47 #endif
48
49 #include <cdio/cdio.h>
50 #include <cdio/bytesex.h>
51 #include <cdio/iso9660.h>
52 #include <cdio/util.h>
53 #include <cdio/utf8.h>
54
55 /* Private headers */
56 #include "cdio_assert.h"
57 #include "_cdio_stdio.h"
58 #include "cdio_private.h"
59
60 /** Implementation of iso9660_t type */
61 struct _iso9660_s {
62 CdioDataSource_t *stream; /**< Stream pointer */
63 bool_3way_t b_xa; /**< true if has XA attributes. */
64 bool_3way_t b_mode2; /**< true if has mode 2, false for mode 1. */
65 uint8_t u_joliet_level; /**< 0 = no Joliet extensions.
66 1-3: Joliet level. */
67 iso9660_pvd_t pvd;
68 iso9660_svd_t svd;
69 iso_extension_mask_t iso_extension_mask; /**< What extensions we
70 tolerate. */
71 uint32_t i_datastart; /**< Usually 0 when i_framesize is ISO_BLOCKSIZE.
72 This is the normal condition. But in a fuzzy
73 read we may be reading a CD-image
74 and not a true ISO 9660 image this might be
75 CDIO_CD_SYNC_SIZE
76 */
77 uint32_t i_framesize; /**< Usually ISO_BLOCKSIZE (2048), but in a
78 fuzzy read, we may be reading a CD-image
79 and not a true ISO 9660 image this might
80 be CDIO_CD_FRAMESIZE_RAW (2352) or
81 M2RAW_SECTOR_SIZE (2336).
82 */
83 int i_fuzzy_offset; /**< Adjustment in bytes to make ISO_STANDARD_ID
84 ("CD001") come out as ISO_PVD_SECTOR
85 (frame 16). Normally this should be 0
86 for an ISO 9660 image, but if one is
87 say reading a BIN/CUE or cdrdao BIN/TOC
88 without having the CUE or TOC and
89 trying to extract an ISO-9660
90 filesystem inside that it may be
91 different.
92 */
93 bool b_have_superblock; /**< Superblock has been read in? */
94
95 };
96
97 static long int iso9660_seek_read_framesize (const iso9660_t *p_iso,
98 void *ptr, lsn_t start,
99 long int size,
100 uint16_t i_framesize);
101
102 /* Adjust the p_iso's i_datastart, i_byte_offset and i_framesize
103 based on whether we find a frame header or not.
104 */
105 static void
adjust_fuzzy_pvd(iso9660_t * p_iso)106 adjust_fuzzy_pvd( iso9660_t *p_iso )
107 {
108 long int i_byte_offset;
109
110 if (!p_iso) return;
111
112 i_byte_offset = (ISO_PVD_SECTOR * p_iso->i_framesize)
113 + p_iso->i_fuzzy_offset + p_iso->i_datastart;
114
115 /* If we have a raw 2352-byte frame then we should expect to see a sync
116 frame and a header.
117 */
118 if (CDIO_CD_FRAMESIZE_RAW == p_iso->i_framesize) {
119 char buf[CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE];
120
121 i_byte_offset -= CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;
122
123 if ( DRIVER_OP_SUCCESS != cdio_stream_seek (p_iso->stream, i_byte_offset,
124 SEEK_SET) )
125 return;
126 if (sizeof(buf) == cdio_stream_read (p_iso->stream, buf, sizeof(buf), 1)) {
127 /* Does the sector frame header suggest Mode 1 format? */
128 if (!memcmp(CDIO_SECTOR_SYNC_HEADER, buf+CDIO_CD_SUBHEADER_SIZE,
129 CDIO_CD_SYNC_SIZE)) {
130 if (buf[14+CDIO_CD_SUBHEADER_SIZE] != 0x16) {
131 cdio_warn ("Expecting the PVD sector header MSF to be 0x16, is: %x",
132 buf[14]);
133 }
134 if (buf[15+CDIO_CD_SUBHEADER_SIZE] != 0x1) {
135 cdio_warn ("Expecting the PVD sector mode to be Mode 1 is: %x",
136 buf[15]);
137 }
138 p_iso->b_mode2 = nope;
139 p_iso->b_xa = nope;
140 } else if (!memcmp(CDIO_SECTOR_SYNC_HEADER, buf, CDIO_CD_SYNC_SIZE)) {
141 /* Frame header indicates Mode 2 Form 1*/
142 if (buf[14] != 0x16) {
143 cdio_warn ("Expecting the PVD sector header MSF to be 0x16, is: %x",
144 buf[14]);
145 }
146 if (buf[15] != 0x2) {
147 cdio_warn ("Expecting the PVD sector mode to be Mode 2 is: %x",
148 buf[15]);
149 }
150 p_iso->b_mode2 = yep;
151 /* Do do: check Mode 2 Form 2? */
152 } else {
153 /* Has no frame header */
154 p_iso->i_framesize = M2RAW_SECTOR_SIZE;
155 p_iso->i_fuzzy_offset = (CDIO_CD_FRAMESIZE_RAW - M2RAW_SECTOR_SIZE)
156 * ISO_PVD_SECTOR + p_iso->i_fuzzy_offset + p_iso->i_datastart;
157 p_iso->i_datastart = 0;
158 }
159 }
160 }
161
162
163 }
164
165 /*!
166 Open an ISO 9660 image for reading in either fuzzy mode or not.
167 */
168 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)169 iso9660_open_ext_private (const char *psz_path,
170 iso_extension_mask_t iso_extension_mask,
171 uint16_t i_fuzz, bool b_fuzzy)
172 {
173 iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(iso9660_t)) ;
174
175 if (!p_iso) return NULL;
176
177 p_iso->stream = cdio_stdio_new( psz_path );
178 if (NULL == p_iso->stream)
179 goto error;
180
181 p_iso->i_framesize = ISO_BLOCKSIZE;
182
183 p_iso->b_have_superblock = (b_fuzzy)
184 ? iso9660_ifs_fuzzy_read_superblock(p_iso, iso_extension_mask, i_fuzz)
185 : iso9660_ifs_read_superblock(p_iso, iso_extension_mask) ;
186
187 if ( ! p_iso->b_have_superblock ) goto error;
188
189 /* Determine if image has XA attributes. */
190
191 p_iso->b_xa = strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET,
192 ISO_XA_MARKER_STRING,
193 sizeof (ISO_XA_MARKER_STRING))
194 ? nope : yep;
195
196 p_iso->iso_extension_mask = iso_extension_mask;
197 return p_iso;
198
199 error:
200 if (p_iso && p_iso->stream) cdio_stdio_destroy(p_iso->stream);
201 free(p_iso);
202
203 return NULL;
204 }
205
206 /*!
207 Open an ISO 9660 image for reading. Maybe in the future we will have
208 a mode. NULL is returned on error.
209
210 @param psz_path full path of ISO9660 file.
211
212 @return a IS9660 structure is unconditionally returned. The caller
213 should call iso9660_close() when done.
214 */
215 iso9660_t *
iso9660_open(const char * psz_path)216 iso9660_open (const char *psz_path /*, mode*/)
217 {
218 return iso9660_open_ext(psz_path, ISO_EXTENSION_NONE);
219 }
220
221 /*!
222 Open an ISO 9660 image for reading allowing various ISO 9660
223 extensions. Maybe in the future we will have a mode. NULL is
224 returned on error.
225
226 @see iso9660_open_fuzzy
227 */
228 iso9660_t *
iso9660_open_ext(const char * psz_path,iso_extension_mask_t iso_extension_mask)229 iso9660_open_ext (const char *psz_path,
230 iso_extension_mask_t iso_extension_mask)
231 {
232 return iso9660_open_ext_private(psz_path, iso_extension_mask, 0, false);
233 }
234
235
236 /*! Open an ISO 9660 image for "fuzzy" reading. This means that we
237 will try to guess various internal offset based on internal
238 checks. This may be useful when trying to read an ISO 9660 image
239 contained in a file format that libiso9660 doesn't know natively
240 (or knows imperfectly.)
241
242 Some tolerence allowed for positioning the ISO 9660 image. We scan
243 for STANDARD_ID and use that to set the eventual offset to adjust
244 by (as long as that is <= i_fuzz).
245
246 Maybe in the future we will have a mode. NULL is returned on error.
247
248 @see iso9660_open, @see iso9660_fuzzy_ext
249 */
250 iso9660_t *
iso9660_open_fuzzy(const char * psz_path,uint16_t i_fuzz)251 iso9660_open_fuzzy (const char *psz_path, uint16_t i_fuzz /*, mode*/)
252 {
253 return iso9660_open_fuzzy_ext(psz_path, ISO_EXTENSION_NONE, i_fuzz);
254 }
255
256 /*!
257 Open an ISO 9660 image for reading with some tolerence for positioning
258 of the ISO9660 image. We scan for ISO_STANDARD_ID and use that to set
259 the eventual offset to adjust by (as long as that is <= i_fuzz).
260
261 Maybe in the future we will have a mode. NULL is returned on error.
262
263 @see iso9660_open_ext @see iso9660_open_fuzzy
264 */
265 iso9660_t *
iso9660_open_fuzzy_ext(const char * psz_path,iso_extension_mask_t iso_extension_mask,uint16_t i_fuzz)266 iso9660_open_fuzzy_ext (const char *psz_path,
267 iso_extension_mask_t iso_extension_mask,
268 uint16_t i_fuzz)
269 {
270 return iso9660_open_ext_private(psz_path, iso_extension_mask, i_fuzz,
271 true);
272 }
273
274 /*! Close previously opened ISO 9660 image and free resources
275 associated with the image. Call this when done using using an ISO
276 9660 image.
277
278 @return true is unconditionally returned. If there was an error
279 false would be returned.
280 */
281 bool
iso9660_close(iso9660_t * p_iso)282 iso9660_close (iso9660_t *p_iso)
283 {
284 if (NULL != p_iso) {
285 cdio_stdio_destroy(p_iso->stream);
286 p_iso->stream = NULL;
287 free(p_iso);
288 }
289 return true;
290 }
291
292 static bool
check_pvd(const iso9660_pvd_t * p_pvd,cdio_log_level_t log_level)293 check_pvd (const iso9660_pvd_t *p_pvd, cdio_log_level_t log_level)
294 {
295 if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) {
296 cdio_log (log_level, "unexpected PVD type %d", p_pvd->type);
297 return false;
298 }
299
300 if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID)))
301 {
302 cdio_log (log_level, "unexpected ID encountered (expected `"
303 ISO_STANDARD_ID "', got `%.5s')", p_pvd->id);
304 return false;
305 }
306 return true;
307 }
308
309
310 /*!
311 Core procedure for the iso9660_ifs_get_###_id() calls.
312 pvd_member/svd_member is a pointer to an achar_t or dchar_t
313 ID string which we can superset as char.
314 If the Joliet converted string is the same as the achar_t/dchar_t
315 one, we fall back to using the latter, as it may be longer.
316 */
317 static inline bool
get_member_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_member_id,char * pvd_member,char * svd_member,size_t max_size)318 get_member_id(iso9660_t *p_iso, cdio_utf8_t **p_psz_member_id,
319 char* pvd_member, char* svd_member, size_t max_size)
320 {
321 int j;
322 bool strip;
323
324 if (!p_iso) {
325 *p_psz_member_id = NULL;
326 return false;
327 }
328 #ifdef HAVE_JOLIET
329 if (p_iso->u_joliet_level) {
330 /* Translate USC-2 string from Secondary Volume Descriptor */
331 if (cdio_charset_to_utf8(svd_member, max_size,
332 p_psz_member_id, "UCS-2BE")) {
333 /* NB: *p_psz_member_id is never NULL on success. */
334 if (strncmp(*p_psz_member_id, pvd_member,
335 strlen(*p_psz_member_id)) != 0) {
336 /* Strip trailing spaces */
337 for (j = strlen(*p_psz_member_id)-1; j >= 0; j--) {
338 if ((*p_psz_member_id)[j] != ' ')
339 break;
340 (*p_psz_member_id)[j] = '\0';
341 }
342 if ((*p_psz_member_id)[0] != 0) {
343 /* Joliet string is not empty and differs from
344 non Joliet one => use it */
345 return true;
346 }
347 }
348 /* Joliet string was either empty or same */
349 free(*p_psz_member_id);
350 }
351 }
352 #endif /*HAVE_JOLIET*/
353 *p_psz_member_id = calloc(max_size+1, sizeof(cdio_utf8_t));
354 if (!*p_psz_member_id) {
355 cdio_warn("Memory allocation error");
356 return false;
357 }
358 /* Copy string while removing trailing spaces */
359 (*p_psz_member_id)[max_size] = 0;
360 for (strip=true, j=max_size-1; j>=0; j--) {
361 if (strip && (pvd_member[j] == ' '))
362 continue;
363 strip = false;
364 (*p_psz_member_id)[j] = pvd_member[j];
365 }
366 if (strlen(*p_psz_member_id) == 0) {
367 free(*p_psz_member_id);
368 *p_psz_member_id = NULL;
369 return false;
370 }
371 return true;
372 }
373
374
375 /*!
376 Return the application ID. NULL is returned in psz_app_id if there
377 is some problem in getting this.
378 */
379 bool
iso9660_ifs_get_application_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_app_id)380 iso9660_ifs_get_application_id(iso9660_t *p_iso,
381 /*out*/ cdio_utf8_t **p_psz_app_id)
382 {
383 return get_member_id(p_iso, p_psz_app_id,
384 (char*)p_iso->pvd.application_id,
385 (char*)p_iso->svd.application_id,
386 ISO_MAX_APPLICATION_ID);
387 }
388
389 /*!
390 Return the Joliet level recognized for p_iso.
391 */
iso9660_ifs_get_joliet_level(iso9660_t * p_iso)392 uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso)
393 {
394 if (!p_iso) return 0;
395 return p_iso->u_joliet_level;
396 }
397
398 /*!
399 Return a string containing the preparer id with trailing
400 blanks removed.
401 */
402 bool
iso9660_ifs_get_preparer_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_preparer_id)403 iso9660_ifs_get_preparer_id(iso9660_t *p_iso,
404 /*out*/ cdio_utf8_t **p_psz_preparer_id)
405 {
406 return get_member_id(p_iso, p_psz_preparer_id,
407 (char*)p_iso->pvd.preparer_id,
408 (char*)p_iso->svd.preparer_id,
409 ISO_MAX_PREPARER_ID);
410 }
411
412 /*!
413 Return a string containing the PVD's publisher id with trailing
414 blanks removed.
415 */
iso9660_ifs_get_publisher_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_publisher_id)416 bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso,
417 /*out*/ cdio_utf8_t **p_psz_publisher_id)
418 {
419 return get_member_id(p_iso, p_psz_publisher_id,
420 (char*)p_iso->pvd.publisher_id,
421 (char*)p_iso->svd.publisher_id,
422 ISO_MAX_PUBLISHER_ID);
423 }
424
425 /*!
426 Return a string containing the PVD's publisher id with trailing
427 blanks removed.
428 */
iso9660_ifs_get_system_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_system_id)429 bool iso9660_ifs_get_system_id(iso9660_t *p_iso,
430 /*out*/ cdio_utf8_t **p_psz_system_id)
431 {
432 return get_member_id(p_iso, p_psz_system_id,
433 (char*)p_iso->pvd.system_id,
434 (char*)p_iso->svd.system_id,
435 ISO_MAX_SYSTEM_ID);
436 }
437
438 /*!
439 Return a string containing the PVD's publisher id with trailing
440 blanks removed.
441 */
iso9660_ifs_get_volume_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_volume_id)442 bool iso9660_ifs_get_volume_id(iso9660_t *p_iso,
443 /*out*/ cdio_utf8_t **p_psz_volume_id)
444 {
445 return get_member_id(p_iso, p_psz_volume_id,
446 (char*)p_iso->pvd.volume_id,
447 (char*)p_iso->svd.volume_id,
448 ISO_MAX_VOLUME_ID);
449 }
450
451 /*!
452 Return a string containing the PVD's publisher id with trailing
453 blanks removed.
454 */
iso9660_ifs_get_volumeset_id(iso9660_t * p_iso,cdio_utf8_t ** p_psz_volumeset_id)455 bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso,
456 /*out*/ cdio_utf8_t **p_psz_volumeset_id)
457 {
458 return get_member_id(p_iso, p_psz_volumeset_id,
459 (char*)p_iso->pvd.volume_set_id,
460 (char*)p_iso->svd.volume_set_id,
461 ISO_MAX_VOLUMESET_ID);
462 }
463
464
465 /*!
466 Read the Primary Volume Descriptor for an ISO 9660 image.
467 True is returned if read, and false if there was an error.
468 */
469 static bool
iso9660_ifs_read_pvd_loglevel(const iso9660_t * p_iso,iso9660_pvd_t * p_pvd,cdio_log_level_t log_level)470 iso9660_ifs_read_pvd_loglevel (const iso9660_t *p_iso,
471 /*out*/ iso9660_pvd_t *p_pvd,
472 cdio_log_level_t log_level)
473 {
474 if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) {
475 cdio_log ( log_level, "error reading PVD sector (%d)", ISO_PVD_SECTOR );
476 return false;
477 }
478 return check_pvd(p_pvd, log_level);
479 }
480
481 /*!
482 Read the Primary Volume Descriptor for an ISO 9660 image.
483 True is returned if read, and false if there was an error.
484 */
485 bool
iso9660_ifs_read_pvd(const iso9660_t * p_iso,iso9660_pvd_t * p_pvd)486 iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd)
487 {
488 return iso9660_ifs_read_pvd_loglevel(p_iso, p_pvd, CDIO_LOG_WARN);
489 }
490
491
492 /*!
493 Read the Super block of an ISO 9660 image. This is the
494 Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume
495 Descriptor if (Joliet) extensions are acceptable.
496 */
497 bool
iso9660_ifs_read_superblock(iso9660_t * p_iso,iso_extension_mask_t iso_extension_mask)498 iso9660_ifs_read_superblock (iso9660_t *p_iso,
499 iso_extension_mask_t iso_extension_mask)
500 {
501 iso9660_svd_t p_svd; /* Secondary volume descriptor. */
502 int i;
503
504 if (!p_iso || !iso9660_ifs_read_pvd(p_iso, &(p_iso->pvd)))
505 return false;
506
507 p_iso->u_joliet_level = 0;
508
509 /* There may be multiple Secondary Volume Descriptors (eg. El Torito + Joliet) */
510 for (i=1; (0 != iso9660_iso_seek_read (p_iso, &p_svd, ISO_PVD_SECTOR+i, 1)); i++) {
511 if (ISO_VD_END == from_711(p_svd.type) ) /* Last SVD */
512 break;
513 if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd.type) ) {
514 /* We're only interested in Joliet => make sure the SVD isn't overwritten */
515 if (p_iso->u_joliet_level == 0)
516 memcpy(&(p_iso->svd), &p_svd, sizeof(iso9660_svd_t));
517 if (p_svd.escape_sequences[0] == 0x25
518 && p_svd.escape_sequences[1] == 0x2f) {
519 switch (p_svd.escape_sequences[2]) {
520 case 0x40:
521 if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1)
522 p_iso->u_joliet_level = 1;
523 break;
524 case 0x43:
525 if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2)
526 p_iso->u_joliet_level = 2;
527 break;
528 case 0x45:
529 if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3)
530 p_iso->u_joliet_level = 3;
531 break;
532 default:
533 cdio_info("Supplementary Volume Descriptor found, but not Joliet");
534 }
535 if (p_iso->u_joliet_level > 0) {
536 cdio_info("Found Extension: Joliet Level %d", p_iso->u_joliet_level);
537 }
538 }
539 }
540 }
541
542 return true;
543 }
544
545 /*!
546 Read the Super block of an ISO 9660 image but determine framesize
547 and datastart and a possible additional offset. Generally here we are
548 not reading an ISO 9660 image but a CD-Image which contains an ISO 9660
549 filesystem.
550 */
551 bool
iso9660_ifs_fuzzy_read_superblock(iso9660_t * p_iso,iso_extension_mask_t iso_extension_mask,uint16_t i_fuzz)552 iso9660_ifs_fuzzy_read_superblock (iso9660_t *p_iso,
553 iso_extension_mask_t iso_extension_mask,
554 uint16_t i_fuzz)
555 {
556 /* Got some work to do to find ISO_STANDARD_ID ("CD001") */
557 unsigned int i;
558
559 for (i=0; i<i_fuzz; i++) {
560 unsigned int j;
561 char *pvd = NULL;
562
563 for (j = 0; j <= 1; j++ ) {
564 lsn_t lsn;
565 uint16_t k;
566 const uint16_t framesizes[] = { ISO_BLOCKSIZE, CDIO_CD_FRAMESIZE_RAW,
567 M2RAW_SECTOR_SIZE } ;
568
569 /* We don't need to loop over a zero offset twice*/
570 if (0==i && j)
571 continue;
572
573 lsn = (j) ? ISO_PVD_SECTOR - i : ISO_PVD_SECTOR + i;
574
575 for (k=0; k < 3; k++) {
576 char *p, *q;
577 char frame[CDIO_CD_FRAMESIZE_RAW] = {'\0',};
578 p_iso->i_framesize = framesizes[k];
579 p_iso->i_datastart = (ISO_BLOCKSIZE == framesizes[k]) ?
580 0 : CDIO_CD_SYNC_SIZE;
581 p_iso->i_fuzzy_offset = 0;
582 if (0 == iso9660_seek_read_framesize (p_iso, frame, lsn, 1,
583 p_iso->i_framesize)) {
584 return false;
585 }
586
587 q = memchr(frame, 'C', p_iso->i_framesize);
588 for ( p=q; p && p < frame + p_iso->i_framesize ; p=q+1 ) {
589 q = memchr(p, 'C', p_iso->i_framesize - (p - frame));
590 if ( !q || (pvd = strstr(q, ISO_STANDARD_ID)) )
591 break;
592 }
593
594 if (pvd) {
595 /* Yay! Found something */
596 p_iso->i_fuzzy_offset = (pvd - frame - 1) -
597 ((ISO_PVD_SECTOR-lsn)*p_iso->i_framesize) ;
598 /* But is it *really* a PVD? */
599 if ( iso9660_ifs_read_pvd_loglevel(p_iso, &(p_iso->pvd),
600 CDIO_LOG_DEBUG) ) {
601 adjust_fuzzy_pvd(p_iso);
602 return true;
603 }
604
605 }
606 }
607 }
608 }
609 return false;
610 }
611
612
613 /*!
614 Read the Primary Volume Descriptor for of CD.
615 */
616 bool
iso9660_fs_read_pvd(const CdIo_t * p_cdio,iso9660_pvd_t * p_pvd)617 iso9660_fs_read_pvd(const CdIo_t *p_cdio, /*out*/ iso9660_pvd_t *p_pvd)
618 {
619 /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/
620 char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
621 driver_return_code_t driver_return =
622 cdio_read_data_sectors (p_cdio, buf, ISO_PVD_SECTOR, ISO_BLOCKSIZE, 1);
623
624 if (DRIVER_OP_SUCCESS != driver_return) {
625 cdio_warn ("error reading PVD sector (%d) error %d", ISO_PVD_SECTOR,
626 driver_return);
627 return false;
628 }
629
630 /* The size of a PVD or SVD is smaller than a sector. So we
631 allocated a bigger block above (buf) and now we'll copy just
632 the part we need to save.
633 */
634 cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t));
635 memcpy(p_pvd, buf, sizeof(iso9660_pvd_t));
636
637 return check_pvd(p_pvd, CDIO_LOG_WARN);
638 }
639
640
641 /*!
642 Read the Super block of an ISO 9660 image. This is the
643 Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume
644 Descriptor if (Joliet) extensions are acceptable.
645 */
646 bool
iso9660_fs_read_superblock(CdIo_t * p_cdio,iso_extension_mask_t iso_extension_mask)647 iso9660_fs_read_superblock (CdIo_t *p_cdio,
648 iso_extension_mask_t iso_extension_mask)
649 {
650 if (!p_cdio) return false;
651
652 {
653 generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
654 iso9660_pvd_t *p_pvd = &(p_env->pvd);
655 iso9660_svd_t *p_svd = &(p_env->svd);
656 char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
657 driver_return_code_t driver_return;
658
659 if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) )
660 return false;
661
662 p_env->u_joliet_level = 0;
663
664 driver_return =
665 cdio_read_data_sectors ( p_cdio, buf, ISO_PVD_SECTOR+1, ISO_BLOCKSIZE,
666 1 );
667
668 if (DRIVER_OP_SUCCESS == driver_return) {
669 /* The size of a PVD or SVD is smaller than a sector. So we
670 allocated a bigger block above (buf) and now we'll copy just
671 the part we need to save.
672 */
673 cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t));
674 memcpy(p_svd, buf, sizeof(iso9660_svd_t));
675
676 if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) {
677 if (p_svd->escape_sequences[0] == 0x25
678 && p_svd->escape_sequences[1] == 0x2f) {
679 switch (p_svd->escape_sequences[2]) {
680 case 0x40:
681 if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1)
682 p_env->u_joliet_level = 1;
683 break;
684 case 0x43:
685 if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2)
686 p_env->u_joliet_level = 2;
687 break;
688 case 0x45:
689 if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3)
690 p_env->u_joliet_level = 3;
691 break;
692 default:
693 cdio_info("Supplementary Volume Descriptor found, but not Joliet");
694 }
695 if (p_env->u_joliet_level > 0) {
696 cdio_info("Found Extension: Joliet Level %d",
697 p_env->u_joliet_level);
698 }
699 }
700 }
701 }
702 }
703
704 return true;
705 }
706
707 /*!
708 Seek to a position and then read n blocks. Size read is returned.
709 */
710 static long int
iso9660_seek_read_framesize(const iso9660_t * p_iso,void * ptr,lsn_t start,long int size,uint16_t i_framesize)711 iso9660_seek_read_framesize (const iso9660_t *p_iso, void *ptr,
712 lsn_t start, long int size,
713 uint16_t i_framesize)
714 {
715 long int ret;
716 int64_t i_byte_offset;
717
718 if (!p_iso) return 0;
719 i_byte_offset = (start * (int64_t)(p_iso->i_framesize))
720 + p_iso->i_fuzzy_offset + p_iso->i_datastart;
721
722 ret = cdio_stream_seek (p_iso->stream, i_byte_offset, SEEK_SET);
723 if (ret!=0) return 0;
724 return cdio_stream_read (p_iso->stream, ptr, i_framesize, size);
725 }
726
727 /*!
728 Seek to a position and then read n blocks. Size read is returned.
729 */
730 long int
iso9660_iso_seek_read(const iso9660_t * p_iso,void * ptr,lsn_t start,long int size)731 iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start,
732 long int size)
733 {
734 return iso9660_seek_read_framesize(p_iso, ptr, start, size, ISO_BLOCKSIZE);
735 }
736
737
738
739 /*!
740 Check for the end of a directory record list in a single directory
741 block. If at the end, set the offset to start of the next block and
742 return "true". The caller often skips actions only when at the end
743 of a record list.
744 */
745 static bool
iso9660_check_dir_block_end(iso9660_dir_t * p_iso9660_dir,unsigned * offset)746 iso9660_check_dir_block_end(iso9660_dir_t *p_iso9660_dir, unsigned *offset)
747 {
748 if (!iso9660_get_dir_len(p_iso9660_dir))
749 {
750 /*
751 Length 0 indicates that no more directory records are in this
752 block. This matches how Linux and libburn's libisofs work.
753
754 Note that assignment below does not exactly round up.
755 If (offset % ISO_BLOCKSIZE) == 0 then offset is incremented
756 by ISO_BLOCKSIZE, i.e. the block is skipped.
757 */
758 *offset += ISO_BLOCKSIZE - (*offset % ISO_BLOCKSIZE);
759 return true;
760 }
761
762 if ((*offset + iso9660_get_dir_len(p_iso9660_dir) - 1) / ISO_BLOCKSIZE
763 != *offset / ISO_BLOCKSIZE)
764 {
765 /*
766 Directory record spans over block limit.
767 Hop to next block where a new record is supposed to begin,
768 if it is not after the end of the directory data.
769 */
770 *offset += ISO_BLOCKSIZE - (*offset % ISO_BLOCKSIZE);
771 return true;
772 }
773
774 return false;
775 }
776
777
778
779 static iso9660_stat_t *
_iso9660_dir_to_statbuf(iso9660_dir_t * p_iso9660_dir,bool_3way_t b_xa,uint8_t u_joliet_level)780 _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa,
781 uint8_t u_joliet_level)
782 {
783 uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir);
784 iso711_t i_fname;
785 unsigned int stat_len;
786 iso9660_stat_t *p_stat = NULL;
787
788 if (!dir_len) return NULL;
789
790 i_fname = from_711(p_iso9660_dir->filename.len);
791
792 /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */
793 stat_len = sizeof(iso9660_stat_t)+i_fname+2;
794
795 p_stat = calloc(1, stat_len);
796 if (!p_stat)
797 {
798 cdio_warn("Couldn't calloc(1, %d)", stat_len);
799 return NULL;
800 }
801 p_stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY)
802 ? _STAT_DIR : _STAT_FILE;
803 p_stat->lsn = from_733 (p_iso9660_dir->extent);
804 p_stat->size = from_733 (p_iso9660_dir->size);
805 p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE);
806 p_stat->rr.b3_rock = dunno; /*FIXME should do based on mask */
807 p_stat->b_xa = false;
808
809 {
810 char rr_fname[256] = "";
811
812 int i_rr_fname =
813 #ifdef HAVE_ROCK
814 get_rock_ridge_filename(p_iso9660_dir, rr_fname, p_stat);
815 #else
816 0;
817 #endif
818
819 if (i_rr_fname > 0) {
820 if (i_rr_fname > i_fname) {
821 /* realloc gives valgrind errors */
822 iso9660_stat_t *p_stat_new =
823 calloc(1, sizeof(iso9660_stat_t)+i_rr_fname+2);
824 if (!p_stat_new)
825 {
826 cdio_warn("Couldn't calloc(1, %d)", (int)(sizeof(iso9660_stat_t)+i_rr_fname+2));
827 free(p_stat);
828 return NULL;
829 }
830 memcpy(p_stat_new, p_stat, stat_len);
831 free(p_stat);
832 p_stat = p_stat_new;
833 }
834 strncpy(p_stat->filename, rr_fname, i_rr_fname+1);
835 } else {
836 if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
837 strncpy (p_stat->filename, ".", strlen(".")+1);
838 else if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
839 strncpy (p_stat->filename, "..", strlen("..")+1);
840 #ifdef HAVE_JOLIET
841 else if (u_joliet_level) {
842 int i_inlen = i_fname;
843 cdio_utf8_t *p_psz_out = NULL;
844 if (cdio_charset_to_utf8(&p_iso9660_dir->filename.str[1], i_inlen,
845 &p_psz_out, "UCS-2BE")) {
846 strncpy(p_stat->filename, p_psz_out, i_fname);
847 free(p_psz_out);
848 }
849 else {
850 free(p_stat);
851 return NULL;
852 }
853 }
854 #endif /*HAVE_JOLIET*/
855 else {
856 strncpy (p_stat->filename, &p_iso9660_dir->filename.str[1], i_fname);
857 }
858 }
859 }
860
861
862 iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm));
863
864 if (dir_len < sizeof (iso9660_dir_t)) {
865 iso9660_stat_free(p_stat);
866 return NULL;
867 }
868
869
870 {
871 int su_length = iso9660_get_dir_len(p_iso9660_dir)
872 - sizeof (iso9660_dir_t);
873 su_length -= i_fname;
874
875 if (su_length % 2)
876 su_length--;
877
878 if (su_length < 0 || su_length < sizeof (iso9660_xa_t))
879 return p_stat;
880
881 if (nope == b_xa) {
882 return p_stat;
883 } else {
884 iso9660_xa_t *xa_data =
885 (void *) (((char *) p_iso9660_dir)
886 + (iso9660_get_dir_len(p_iso9660_dir) - su_length));
887 cdio_log_level_t loglevel = (yep == b_xa)
888 ? CDIO_LOG_WARN : CDIO_LOG_INFO;
889
890 if (xa_data->signature[0] != 'X'
891 || xa_data->signature[1] != 'A')
892 {
893 cdio_log (loglevel,
894 "XA signature not found in ISO9660's system use area;"
895 " ignoring XA attributes for this file entry.");
896 cdio_debug ("%d %d %d, '%c%c' (%d, %d)",
897 iso9660_get_dir_len(p_iso9660_dir),
898 i_fname,
899 su_length,
900 xa_data->signature[0], xa_data->signature[1],
901 xa_data->signature[0], xa_data->signature[1]);
902 return p_stat;
903 }
904 p_stat->b_xa = true;
905 p_stat->xa = *xa_data;
906 }
907 }
908 return p_stat;
909
910 }
911
912 /*!
913 Return the directory name stored in the iso9660_dir_t
914
915 A string is allocated: the caller must deallocate. This routine
916 can return NULL if memory allocation fails.
917 */
918 char *
iso9660_dir_to_name(const iso9660_dir_t * iso9660_dir)919 iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir)
920 {
921 uint8_t len=iso9660_get_dir_len(iso9660_dir);
922
923 if (!len) return NULL;
924
925 cdio_assert (len >= sizeof (iso9660_dir_t));
926
927 /* (iso9660_dir->file_flags & ISO_DIRECTORY) */
928
929 if (iso9660_dir->filename.str[1] == '\0')
930 return strdup(".");
931 else if (iso9660_dir->filename.str[1] == '\1')
932 return strdup("..");
933 else {
934 return strdup(&iso9660_dir->filename.str[1]);
935 }
936 }
937
938 /*
939 Return a pointer to a ISO 9660 stat buffer or NULL if there's an error
940 */
941 static iso9660_stat_t *
_fs_stat_root(CdIo_t * p_cdio)942 _fs_stat_root (CdIo_t *p_cdio)
943 {
944
945 if (!p_cdio) return NULL;
946
947 {
948 iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
949 generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
950 iso9660_dir_t *p_iso9660_dir;
951 iso9660_stat_t *p_stat;
952 bool_3way_t b_xa;
953
954 if (!p_env->u_joliet_level)
955 iso_extension_mask &= ~ISO_EXTENSION_JOLIET;
956
957 /* FIXME try also with Joliet.*/
958 if ( !iso9660_fs_read_superblock (p_cdio, iso_extension_mask) ) {
959 cdio_warn("Could not read ISO-9660 Superblock.");
960 return NULL;
961 }
962
963 switch(cdio_get_discmode(p_cdio)) {
964 case CDIO_DISC_MODE_CD_XA:
965 b_xa = yep;
966 break;
967 case CDIO_DISC_MODE_CD_DATA:
968 b_xa = nope;
969 break;
970 default:
971 b_xa = dunno;
972 }
973
974 #ifdef HAVE_JOLIET
975 p_iso9660_dir = p_env->u_joliet_level
976 ? &(p_env->svd.root_directory_record)
977 : &(p_env->pvd.root_directory_record) ;
978 #else
979 p_iso9660_dir = &(p_env->pvd.root_directory_record) ;
980 #endif
981
982 p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_xa,
983 p_env->u_joliet_level);
984 return p_stat;
985 }
986
987 }
988
989 static iso9660_stat_t *
_ifs_stat_root(iso9660_t * p_iso)990 _ifs_stat_root (iso9660_t *p_iso)
991 {
992 iso9660_stat_t *p_stat;
993 iso9660_dir_t *p_iso9660_dir;
994
995 #ifdef HAVE_JOLIET
996 p_iso9660_dir = p_iso->u_joliet_level
997 ? &(p_iso->svd.root_directory_record)
998 : &(p_iso->pvd.root_directory_record) ;
999 #else
1000 p_iso9660_dir = &(p_iso->pvd.root_directory_record) ;
1001 #endif
1002
1003 p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa,
1004 p_iso->u_joliet_level);
1005 return p_stat;
1006 }
1007
1008 static iso9660_stat_t *
_fs_stat_traverse(const CdIo_t * p_cdio,const iso9660_stat_t * _root,char ** splitpath)1009 _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root,
1010 char **splitpath)
1011 {
1012 unsigned offset = 0;
1013 uint8_t *_dirbuf = NULL;
1014 iso9660_stat_t *p_stat;
1015 generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
1016
1017 if (!splitpath[0])
1018 {
1019 unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1;
1020 p_stat = calloc(1, len);
1021 cdio_assert (p_stat != NULL);
1022 memcpy(p_stat, _root, len);
1023 p_stat->rr.psz_symlink = calloc(1, p_stat->rr.i_symlink_max);
1024 cdio_assert (p_stat->rr.psz_symlink != NULL);
1025 memcpy(p_stat->rr.psz_symlink, _root->rr.psz_symlink,
1026 p_stat->rr.i_symlink_max);
1027 return p_stat;
1028 }
1029
1030 if (_root->type == _STAT_FILE)
1031 return NULL;
1032
1033 cdio_assert (_root->type == _STAT_DIR);
1034
1035 _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE);
1036 if (!_dirbuf)
1037 {
1038 cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE);
1039 return NULL;
1040 }
1041
1042 if (cdio_read_data_sectors (p_cdio, _dirbuf, _root->lsn, ISO_BLOCKSIZE,
1043 _root->secsize))
1044 return NULL;
1045
1046 while (offset < (_root->secsize * ISO_BLOCKSIZE))
1047 {
1048 iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
1049 iso9660_stat_t *p_iso9660_stat;
1050 int cmp;
1051
1052 if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
1053 continue;
1054
1055 p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, dunno,
1056 p_env->u_joliet_level);
1057
1058 cmp = strcmp(splitpath[0], p_iso9660_stat->filename);
1059
1060 if ( 0 != cmp && 0 == p_env->u_joliet_level
1061 && yep != p_iso9660_stat->rr.b3_rock ) {
1062 char *trans_fname = NULL;
1063 unsigned int i_trans_fname=strlen(p_iso9660_stat->filename);
1064
1065 if (i_trans_fname) {
1066 trans_fname = calloc(1, i_trans_fname+1);
1067 if (!trans_fname) {
1068 cdio_warn("can't allocate %lu bytes",
1069 (long unsigned int) strlen(p_iso9660_stat->filename));
1070 free(p_iso9660_stat);
1071 return NULL;
1072 }
1073 iso9660_name_translate_ext(p_iso9660_stat->filename, trans_fname,
1074 p_env->u_joliet_level);
1075 cmp = strcmp(splitpath[0], trans_fname);
1076 free(trans_fname);
1077 }
1078 }
1079
1080 if (!cmp) {
1081 iso9660_stat_t *ret_stat
1082 = _fs_stat_traverse (p_cdio, p_iso9660_stat, &splitpath[1]);
1083 iso9660_stat_free(p_iso9660_stat);
1084 free (_dirbuf);
1085 return ret_stat;
1086 }
1087
1088 iso9660_stat_free(p_iso9660_stat);
1089
1090 offset += iso9660_get_dir_len(p_iso9660_dir);
1091 }
1092
1093 cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE));
1094
1095 /* not found */
1096 free (_dirbuf);
1097 return NULL;
1098 }
1099
1100 static iso9660_stat_t *
_fs_iso_stat_traverse(iso9660_t * p_iso,const iso9660_stat_t * _root,char ** splitpath)1101 _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root,
1102 char **splitpath)
1103 {
1104 unsigned offset = 0;
1105 uint8_t *_dirbuf = NULL;
1106 int ret;
1107
1108 if (!splitpath[0])
1109 {
1110 iso9660_stat_t *p_stat;
1111 unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1;
1112 p_stat = calloc(1, len);
1113 cdio_assert (p_stat != NULL);
1114 memcpy(p_stat, _root, len);
1115 p_stat->rr.psz_symlink = calloc(1, p_stat->rr.i_symlink_max);
1116 cdio_assert (p_stat->rr.psz_symlink != NULL);
1117 memcpy(p_stat->rr.psz_symlink, _root->rr.psz_symlink,
1118 p_stat->rr.i_symlink_max);
1119 return p_stat;
1120 }
1121
1122 if (_root->type == _STAT_FILE)
1123 return NULL;
1124
1125 cdio_assert (_root->type == _STAT_DIR);
1126
1127 _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE);
1128 if (!_dirbuf)
1129 {
1130 cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE);
1131 return NULL;
1132 }
1133
1134 ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize);
1135 if (ret!=ISO_BLOCKSIZE*_root->secsize) {
1136 free(_dirbuf);
1137 return NULL;
1138 }
1139
1140 while (offset < (_root->secsize * ISO_BLOCKSIZE))
1141 {
1142 iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
1143 iso9660_stat_t *p_stat;
1144 int cmp;
1145
1146 if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
1147 continue;
1148
1149 p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa,
1150 p_iso->u_joliet_level);
1151
1152 if (!p_stat) {
1153 cdio_warn("Bad directory information for %s", splitpath[0]);
1154 free(_dirbuf);
1155 return NULL;
1156 }
1157
1158 cmp = strcmp(splitpath[0], p_stat->filename);
1159
1160 if ( 0 != cmp && 0 == p_iso->u_joliet_level
1161 && yep != p_stat->rr.b3_rock ) {
1162 char *trans_fname = NULL;
1163 unsigned int i_trans_fname=strlen(p_stat->filename);
1164
1165 if (i_trans_fname) {
1166 trans_fname = calloc(1, i_trans_fname+1);
1167 if (!trans_fname) {
1168 cdio_warn("can't allocate %lu bytes",
1169 (long unsigned int) strlen(p_stat->filename));
1170 free(p_stat);
1171 return NULL;
1172 }
1173 iso9660_name_translate_ext(p_stat->filename, trans_fname,
1174 p_iso->u_joliet_level);
1175 cmp = strcmp(splitpath[0], trans_fname);
1176 free(trans_fname);
1177 }
1178 }
1179
1180 if (!cmp) {
1181 iso9660_stat_t *ret_stat
1182 = _fs_iso_stat_traverse (p_iso, p_stat, &splitpath[1]);
1183 iso9660_stat_free(p_stat);
1184 free (_dirbuf);
1185 return ret_stat;
1186 }
1187 iso9660_stat_free(p_stat);
1188
1189 offset += iso9660_get_dir_len(p_iso9660_dir);
1190 }
1191
1192 cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE));
1193
1194 /* not found */
1195 free (_dirbuf);
1196 return NULL;
1197 }
1198
1199 /*!
1200 Return file status for psz_path. NULL is returned on error.
1201
1202 @param p_cdio the CD object to read from
1203
1204 @param psz_path filename path to look up and get information about
1205
1206 @return ISO 9660 file information
1207
1208 Important note:
1209
1210 You make get different results looking up "/" versus "/." and the
1211 latter may give more complete information. "/" will take information
1212 from the PVD only, whereas "/." will force a directory read of "/" and
1213 find "." and in that Rock-Ridge information might be found which fills
1214 in more stat information. Ideally iso9660_fs_stat should be fixed.
1215 Patches anyone?
1216 */
1217 iso9660_stat_t *
iso9660_fs_stat(CdIo_t * p_cdio,const char psz_path[])1218 iso9660_fs_stat (CdIo_t *p_cdio, const char psz_path[])
1219 {
1220 iso9660_stat_t *p_root;
1221 char **p_psz_splitpath;
1222 iso9660_stat_t *p_stat;
1223
1224 if (!p_cdio) return NULL;
1225 if (!psz_path) return NULL;
1226
1227 p_root = _fs_stat_root (p_cdio);
1228
1229 if (!p_root) return NULL;
1230
1231 p_psz_splitpath = _cdio_strsplit (psz_path, '/');
1232 p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath);
1233 free(p_root);
1234 _cdio_strfreev (p_psz_splitpath);
1235
1236 return p_stat;
1237 }
1238
1239 typedef iso9660_stat_t * (stat_root_t) (void *p_image);
1240 typedef iso9660_stat_t * (stat_traverse_t)
1241 (const void *p_image, const iso9660_stat_t *_root, char **splitpath);
1242
1243 /*!
1244 Get file status for psz_path into stat. NULL is returned on error.
1245 pathname version numbers in the ISO 9660
1246 name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names
1247 are lowercased.
1248 */
1249 static iso9660_stat_t *
fs_stat_translate(void * p_image,stat_root_t stat_root,stat_traverse_t stat_traverse,const char psz_path[])1250 fs_stat_translate (void *p_image, stat_root_t stat_root,
1251 stat_traverse_t stat_traverse,
1252 const char psz_path[])
1253 {
1254 iso9660_stat_t *p_root;
1255 char **p_psz_splitpath;
1256 iso9660_stat_t *p_stat;
1257
1258 if (!p_image) return NULL;
1259 if (!psz_path) return NULL;
1260
1261 p_root = stat_root (p_image);
1262 if (!p_root) return NULL;
1263
1264 p_psz_splitpath = _cdio_strsplit (psz_path, '/');
1265 p_stat = stat_traverse (p_image, p_root, p_psz_splitpath);
1266 free(p_root);
1267 _cdio_strfreev (p_psz_splitpath);
1268
1269 return p_stat;
1270 }
1271
1272 /*!
1273 Return file status for path name psz_path. NULL is returned on error.
1274 pathname version numbers in the ISO 9660 name are dropped, i.e. ;1
1275 is removed and if level 1 ISO-9660 names are lowercased.
1276
1277 @param p_cdio the CD object to read from
1278
1279 @param psz_path filename path to look up and get information about
1280
1281 @return ISO 9660 file information. The caller must free the
1282 returned result using iso9660_stat_free().
1283
1284 */
1285 iso9660_stat_t *
iso9660_fs_stat_translate(CdIo_t * p_cdio,const char psz_path[])1286 iso9660_fs_stat_translate (CdIo_t *p_cdio, const char psz_path[])
1287 {
1288 return fs_stat_translate(p_cdio, (stat_root_t *) _fs_stat_root,
1289 (stat_traverse_t *) _fs_stat_traverse,
1290 psz_path);
1291 }
1292
1293 /*!
1294 @param p_iso the ISO-9660 file image to get data from
1295
1296 @param psz_path filename path translate
1297
1298 @return file status for path name psz_path. NULL is returned on
1299 error. pathname version numbers in the ISO 9660 name are dropped,
1300 i.e. ;1 is removed and if level 1 ISO-9660 names are lowercased.
1301 The caller must free the returned result using iso9660_stat_free().
1302 */
1303 iso9660_stat_t *
iso9660_ifs_stat_translate(iso9660_t * p_iso,const char psz_path[])1304 iso9660_ifs_stat_translate (iso9660_t *p_iso, const char psz_path[])
1305 {
1306 return fs_stat_translate(p_iso, (stat_root_t *) _ifs_stat_root,
1307 (stat_traverse_t *) _fs_iso_stat_traverse,
1308 psz_path);
1309 }
1310
1311
1312 /*!
1313
1314 @param p_cdio the CD object to read from
1315
1316 @param pzs_path path the look up
1317
1318 @return file status for pathname. NULL is returned on error.
1319 The caller must free the returned result using iso9660_stat_free().
1320 */
1321 iso9660_stat_t *
iso9660_ifs_stat(iso9660_t * p_iso,const char psz_path[])1322 iso9660_ifs_stat (iso9660_t *p_iso, const char psz_path[])
1323 {
1324 iso9660_stat_t *p_root;
1325 char **splitpath;
1326 iso9660_stat_t *stat;
1327
1328 if (!p_iso) return NULL;
1329 if (!psz_path) return NULL;
1330
1331 p_root = _ifs_stat_root (p_iso);
1332 if (!p_root) return NULL;
1333
1334 splitpath = _cdio_strsplit (psz_path, '/');
1335 stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath);
1336 free(p_root);
1337 _cdio_strfreev (splitpath);
1338
1339 return stat;
1340 }
1341
1342 /*!
1343 Read psz_path (a directory) and return a list of iso9660_stat_t
1344 pointers for the files inside that directory.
1345
1346 @param p_cdio the CD object to read from
1347
1348 @param pzs_path path the read the directory from.
1349
1350 @return file status for psz_path. The caller must free the
1351 The caller must free the returned result using iso9660_stat_free().
1352 */
1353 CdioISO9660FileList_t *
iso9660_fs_readdir(CdIo_t * p_cdio,const char psz_path[])1354 iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[])
1355 {
1356 generic_img_private_t *p_env;
1357 iso9660_stat_t *p_stat;
1358
1359 if (!p_cdio) return NULL;
1360 if (!psz_path) return NULL;
1361
1362 p_env = (generic_img_private_t *) p_cdio->env;
1363
1364 p_stat = iso9660_fs_stat (p_cdio, psz_path);
1365 if (!p_stat) return NULL;
1366
1367 if (p_stat->type != _STAT_DIR) {
1368 iso9660_stat_free(p_stat);
1369 return NULL;
1370 }
1371
1372 {
1373 unsigned offset = 0;
1374 uint8_t *_dirbuf = NULL;
1375 CdioISO9660DirList_t *retval = _cdio_list_new ();
1376
1377 _dirbuf = calloc(1, p_stat->secsize * ISO_BLOCKSIZE);
1378 if (!_dirbuf)
1379 {
1380 cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize * ISO_BLOCKSIZE);
1381 iso9660_stat_free(p_stat);
1382 iso9660_dirlist_free(retval);
1383 return NULL;
1384 }
1385
1386 if (cdio_read_data_sectors (p_cdio, _dirbuf, p_stat->lsn,
1387 ISO_BLOCKSIZE, p_stat->secsize)) {
1388 iso9660_stat_free(p_stat);
1389 iso9660_dirlist_free(retval);
1390 return NULL;
1391 }
1392
1393 while (offset < (p_stat->secsize * ISO_BLOCKSIZE))
1394 {
1395 iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
1396 iso9660_stat_t *p_iso9660_stat;
1397
1398 if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
1399 continue;
1400
1401 p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, dunno,
1402 p_env->u_joliet_level);
1403 _cdio_list_append (retval, p_iso9660_stat);
1404
1405 offset += iso9660_get_dir_len(p_iso9660_dir);
1406 }
1407
1408 cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE));
1409
1410 free(_dirbuf);
1411 iso9660_stat_free(p_stat);
1412 return retval;
1413 }
1414 }
1415
1416 /*!
1417 Read psz_path (a directory) and return a list of iso9660_stat_t
1418 of the files inside that. The caller must free the returned result.
1419 */
1420 CdioISO9660FileList_t *
iso9660_ifs_readdir(iso9660_t * p_iso,const char psz_path[])1421 iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[])
1422 {
1423 iso9660_stat_t *p_stat;
1424
1425 if (!p_iso) return NULL;
1426 if (!psz_path) return NULL;
1427
1428 p_stat = iso9660_ifs_stat (p_iso, psz_path);
1429 if (!p_stat) return NULL;
1430
1431 if (p_stat->type != _STAT_DIR) {
1432 iso9660_stat_free(p_stat);
1433 return NULL;
1434 }
1435
1436 {
1437 long int ret;
1438 unsigned offset = 0;
1439 uint8_t *_dirbuf = NULL;
1440 CdioList_t *retval = _cdio_list_new ();
1441 const size_t dirbuf_len = p_stat->secsize * ISO_BLOCKSIZE;
1442
1443
1444 if (!dirbuf_len)
1445 {
1446 cdio_warn("Invalid directory buffer sector size %u", p_stat->secsize);
1447 iso9660_stat_free(p_stat);
1448 _cdio_list_free (retval, true, NULL);
1449 return NULL;
1450 }
1451
1452 _dirbuf = calloc(1, dirbuf_len);
1453 if (!_dirbuf)
1454 {
1455 cdio_warn("Couldn't calloc(1, %lu)", (unsigned long)dirbuf_len);
1456 iso9660_stat_free(p_stat);
1457 _cdio_list_free (retval, true, NULL);
1458 return NULL;
1459 }
1460
1461 ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize);
1462 if (ret != dirbuf_len) {
1463 _cdio_list_free (retval, true, NULL);
1464 iso9660_stat_free(p_stat);
1465 free (_dirbuf);
1466 return NULL;
1467 }
1468
1469 while (offset < (dirbuf_len))
1470 {
1471 iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
1472 iso9660_stat_t *p_iso9660_stat;
1473
1474 if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
1475 continue;
1476
1477 p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, p_iso->b_xa,
1478 p_iso->u_joliet_level);
1479
1480 if (p_iso9660_stat)
1481 _cdio_list_append (retval, p_iso9660_stat);
1482 else {
1483 cdio_warn("Invalid directory stat at offset %lu", (unsigned long)offset);
1484 break;
1485 }
1486
1487 offset += iso9660_get_dir_len(p_iso9660_dir);
1488 }
1489
1490 free (_dirbuf);
1491 iso9660_stat_free(p_stat);
1492
1493 if (offset != dirbuf_len) {
1494 _cdio_list_free (retval, true, (CdioDataFree_t) iso9660_stat_free);
1495 return NULL;
1496 }
1497
1498 return retval;
1499 }
1500 }
1501
1502 typedef CdioISO9660FileList_t * (iso9660_readdir_t)
1503 (void *p_image, const char * psz_path);
1504
1505 CdioISO9660FileList_t *
iso9660_filelist_new(void)1506 iso9660_filelist_new(void) {
1507 return (CdioISO9660FileList_t *) _cdio_list_new ();
1508 }
1509
1510 CdioISO9660DirList_t *
iso9660_dirlist_new(void)1511 iso9660_dirlist_new(void) {
1512 return (CdioISO9660FileList_t *) _cdio_list_new ();
1513 }
1514
1515 static iso9660_stat_t *
find_lsn_recurse(void * p_image,iso9660_readdir_t iso9660_readdir,const char psz_path[],lsn_t lsn,char ** ppsz_full_filename)1516 find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir,
1517 const char psz_path[], lsn_t lsn,
1518 /*out*/ char **ppsz_full_filename)
1519 {
1520 CdioISO9660FileList_t *entlist = iso9660_readdir (p_image, psz_path);
1521 CdioISO9660DirList_t *dirlist = iso9660_filelist_new();
1522 CdioListNode_t *entnode;
1523
1524 cdio_assert (entlist != NULL);
1525
1526 /* iterate over each entry in the directory */
1527
1528 _CDIO_LIST_FOREACH (entnode, entlist)
1529 {
1530 iso9660_stat_t *statbuf = _cdio_list_node_data (entnode);
1531 const char *psz_filename = (char *) statbuf->filename;
1532 unsigned int len = strlen(psz_path) + strlen(psz_filename)+2;
1533
1534 if (*ppsz_full_filename != NULL) free(*ppsz_full_filename);
1535 *ppsz_full_filename = calloc(1, len);
1536 snprintf (*ppsz_full_filename, len, "%s%s/", psz_path, psz_filename);
1537
1538 if (statbuf->type == _STAT_DIR
1539 && strcmp ((char *) statbuf->filename, ".")
1540 && strcmp ((char *) statbuf->filename, "..")) {
1541 snprintf (*ppsz_full_filename, len, "%s%s/", psz_path, psz_filename);
1542 _cdio_list_append (dirlist, strdup(*ppsz_full_filename));
1543 }
1544
1545 if (statbuf->lsn == lsn) {
1546 const unsigned int len2 = sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1;
1547 iso9660_stat_t *ret_stat = calloc(1, len2);
1548 if (!ret_stat)
1549 {
1550 iso9660_dirlist_free(dirlist);
1551 cdio_warn("Couldn't calloc(1, %d)", len2);
1552 free(*ppsz_full_filename);
1553 *ppsz_full_filename = NULL;
1554 return NULL;
1555 }
1556 memcpy(ret_stat, statbuf, len2);
1557 iso9660_filelist_free (entlist);
1558 iso9660_dirlist_free(dirlist);
1559 return ret_stat;
1560 }
1561
1562 }
1563
1564 iso9660_filelist_free (entlist);
1565
1566 /* now recurse/descend over directories encountered */
1567
1568 _CDIO_LIST_FOREACH (entnode, dirlist)
1569 {
1570 char *psz_path_prefix = _cdio_list_node_data (entnode);
1571 iso9660_stat_t *ret_stat;
1572 free(*ppsz_full_filename);
1573 *ppsz_full_filename = NULL;
1574 ret_stat = find_lsn_recurse (p_image, iso9660_readdir,
1575 psz_path_prefix, lsn,
1576 ppsz_full_filename);
1577
1578 if (NULL != ret_stat) {
1579 iso9660_dirlist_free(dirlist);
1580 return ret_stat;
1581 }
1582 }
1583
1584 if (*ppsz_full_filename != NULL) {
1585 free(*ppsz_full_filename);
1586 *ppsz_full_filename = NULL;
1587 }
1588 iso9660_dirlist_free(dirlist);
1589 return NULL;
1590 }
1591
1592 /*!
1593 Given a directory pointer, find the filesystem entry that contains
1594 lsn and return information about it.
1595
1596 Returns stat_t of entry if we found lsn, or NULL otherwise.
1597 */
1598 iso9660_stat_t *
iso9660_fs_find_lsn(CdIo_t * p_cdio,lsn_t i_lsn)1599 iso9660_fs_find_lsn(CdIo_t *p_cdio, lsn_t i_lsn)
1600 {
1601 char *psz_full_filename = NULL;
1602 iso9660_stat_t * p_statbuf;
1603 p_statbuf = find_lsn_recurse (p_cdio, (iso9660_readdir_t *) iso9660_fs_readdir,
1604 "/", i_lsn, &psz_full_filename);
1605 if (psz_full_filename != NULL)
1606 free(psz_full_filename);
1607 return p_statbuf;
1608 }
1609
1610 /*!
1611 Given a directory pointer, find the filesystem entry that contains
1612 LSN and return information about it.
1613
1614 @param p_iso the ISO-9660 file image to get data from.
1615 @param i_lsn the LSN to find
1616 @param ppsz_full_filename the place to store the name of the path that has LSN.
1617 On entry this should point to NULL. If not, the value will be freed.
1618 On exit a value is malloc'd and the caller is responsible for
1619 freeing the result.
1620
1621 @return stat_t of entry if we found lsn, or NULL otherwise.
1622 Caller must free return value using iso9660_stat_free().
1623 */
1624 iso9660_stat_t *
iso9660_fs_find_lsn_with_path(CdIo_t * p_cdio,lsn_t i_lsn,char ** ppsz_full_filename)1625 iso9660_fs_find_lsn_with_path(CdIo_t *p_cdio, lsn_t i_lsn,
1626 /*out*/ char **ppsz_full_filename)
1627 {
1628 return find_lsn_recurse (p_cdio, (iso9660_readdir_t *) iso9660_fs_readdir,
1629 "/", i_lsn, ppsz_full_filename);
1630 }
1631
1632 /*!
1633 Given a directory pointer, find the filesystem entry that contains
1634 lsn and return information about it.
1635
1636 @param p_iso the ISO-9660 file image to get data from.
1637
1638 @param i_lsn the LSN to find
1639
1640 @return stat_t of entry if we found lsn, or NULL otherwise.
1641 Caller must free return value using iso9660_stat_free().
1642 */
1643 iso9660_stat_t *
iso9660_ifs_find_lsn(iso9660_t * p_iso,lsn_t i_lsn)1644 iso9660_ifs_find_lsn(iso9660_t *p_iso, lsn_t i_lsn)
1645 {
1646 char *psz_full_filename = NULL;
1647 iso9660_stat_t *ret =
1648 find_lsn_recurse (p_iso, (iso9660_readdir_t *) iso9660_ifs_readdir,
1649 "/", i_lsn, &psz_full_filename);
1650 if (psz_full_filename != NULL)
1651 free(psz_full_filename);
1652 return ret;
1653 }
1654
1655 /*!
1656 Given a directory pointer, find the filesystem entry that contains
1657 lsn and return information about it.
1658
1659 @param p_iso pointer to iso_t
1660
1661 @param i_lsn LSN to find
1662
1663 @param ppsz_path full path of lsn filename. On entry *ppsz_path should be
1664 NULL. On return it will be allocated an point to the full path of the
1665 file at lsn or NULL if the lsn is not found. You should deallocate
1666 *ppsz_path when you are done using it.
1667
1668 @return stat_t of entry if we found lsn, or NULL otherwise.
1669 Caller must free return value using iso9660_stat_free().
1670 */
1671 iso9660_stat_t *
iso9660_ifs_find_lsn_with_path(iso9660_t * p_iso,lsn_t i_lsn,char ** ppsz_full_filename)1672 iso9660_ifs_find_lsn_with_path(iso9660_t *p_iso, lsn_t i_lsn,
1673 /*out*/ char **ppsz_full_filename)
1674 {
1675 return find_lsn_recurse (p_iso, (iso9660_readdir_t *) iso9660_ifs_readdir,
1676 "/", i_lsn, ppsz_full_filename);
1677 }
1678
1679 /*!
1680 Free the passed iso9660_stat_t structure.
1681
1682 @param p_stat iso9660 stat buffer to free.
1683
1684 */
1685 void
iso9660_stat_free(iso9660_stat_t * p_stat)1686 iso9660_stat_free(iso9660_stat_t *p_stat)
1687 {
1688 if (p_stat != NULL) {
1689 if (p_stat->rr.psz_symlink) {
1690 CDIO_FREE_IF_NOT_NULL(p_stat->rr.psz_symlink);
1691 }
1692 free(p_stat);
1693 }
1694 }
1695
1696 /*!
1697 Free the passed CdioISOC9660FileList_t structure.
1698 */
1699 void
iso9660_filelist_free(CdioISO9660FileList_t * p_filelist)1700 iso9660_filelist_free(CdioISO9660FileList_t *p_filelist) {
1701 _cdio_list_free(p_filelist, true, (CdioDataFree_t) iso9660_stat_free);
1702 }
1703
1704 /*!
1705 Free the passed CdioISOC9660DirList_t structure.
1706 */
1707 void
iso9660_dirlist_free(CdioISO9660DirList_t * p_filelist)1708 iso9660_dirlist_free(CdioISO9660DirList_t *p_filelist) {
1709 _cdio_list_free(p_filelist, true, free);
1710 }
1711
1712
1713 /*!
1714 Return true if ISO 9660 image has extended attrributes (XA).
1715 */
1716 bool
iso9660_ifs_is_xa(const iso9660_t * p_iso)1717 iso9660_ifs_is_xa (const iso9660_t * p_iso)
1718 {
1719 if (!p_iso) return false;
1720 return yep == p_iso->b_xa;
1721 }
1722
1723 static bool_3way_t
iso_have_rr_traverse(iso9660_t * p_iso,const iso9660_stat_t * _root,char ** splitpath,uint64_t * pu_file_limit)1724 iso_have_rr_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root,
1725 char **splitpath, uint64_t *pu_file_limit)
1726 {
1727 unsigned offset = 0;
1728 uint8_t *_dirbuf = NULL;
1729 int ret;
1730 bool_3way_t have_rr = nope;
1731
1732 if (!splitpath[0]) return false;
1733
1734 if (_root->type == _STAT_FILE) return nope;
1735 if (*pu_file_limit == 0) return dunno;
1736
1737 cdio_assert (_root->type == _STAT_DIR);
1738
1739 _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE);
1740 if (!_dirbuf)
1741 {
1742 cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE);
1743 return dunno;
1744 }
1745
1746 ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize);
1747 if (ret!=ISO_BLOCKSIZE*_root->secsize) {
1748 free(_dirbuf);
1749 return false;
1750 }
1751
1752 while (offset < (_root->secsize * ISO_BLOCKSIZE))
1753 {
1754 iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
1755 iso9660_stat_t *p_stat;
1756 unsigned int i_last_component = 1;
1757
1758 if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
1759 continue;
1760
1761 p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa,
1762 p_iso->u_joliet_level);
1763 have_rr = p_stat->rr.b3_rock;
1764 if ( have_rr != yep) {
1765 if (strlen(splitpath[0]) == 0)
1766 have_rr = false;
1767 else
1768 have_rr = iso_have_rr_traverse (p_iso, p_stat, &splitpath[i_last_component],
1769 pu_file_limit);
1770 }
1771 free(p_stat);
1772 if (have_rr != nope) {
1773 free (_dirbuf);
1774 return have_rr;
1775 }
1776
1777 offset += iso9660_get_dir_len(p_iso9660_dir);
1778 *pu_file_limit = (*pu_file_limit)-1;
1779 if ((*pu_file_limit) == 0) {
1780 free (_dirbuf);
1781 return dunno;
1782 }
1783 }
1784
1785 cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE));
1786
1787 /* not found */
1788 free (_dirbuf);
1789 return nope;
1790 }
1791
1792 /*!
1793 Return "yup" if any file has Rock-Ridge extensions. Warning: this can
1794 be time consuming. On an ISO 9600 image with lots of files but no Rock-Ridge
1795 extensions, the entire directory structure will be scanned up to u_file_limit.
1796
1797 @param p_iso the ISO-9660 file image to get data from
1798
1799 @param u_file_limit the maximimum number of (non-rock-ridge) files
1800 to consider before giving up and returning "dunno".
1801
1802 "dunno" can also be returned if there was some error encountered
1803 such as not being able to allocate memory in processing.
1804
1805 */
1806 extern bool_3way_t
iso9660_have_rr(iso9660_t * p_iso,uint64_t u_file_limit)1807 iso9660_have_rr(iso9660_t *p_iso, uint64_t u_file_limit)
1808 {
1809 iso9660_stat_t *p_root;
1810 char *p_psz_splitpath[2] = {strdup("/"), strdup("")};
1811 bool_3way_t is_rr = nope;
1812
1813 if (!p_iso) return false;
1814
1815 p_root = _ifs_stat_root (p_iso);
1816 if (!p_root) return dunno;
1817
1818 if (u_file_limit == 0) u_file_limit = UINT64_MAX;
1819
1820 is_rr = iso_have_rr_traverse (p_iso, p_root, p_psz_splitpath, &u_file_limit);
1821 free(p_root);
1822 free(p_psz_splitpath[0]);
1823 free(p_psz_splitpath[1]);
1824
1825 return is_rr;
1826 }
1827