1 /*
2   Copyright (C) 2003-2006, 2008-2009, 2011-2012, 2014, 2017
3   Rocky Bernstein <rocky@gnu.org>
4   Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>
5 
6   This program is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*! This code implements low-level access functions for the Nero native
20    CD-image format residing inside a disk file (*.nrg).
21 */
22 
23 #include "image.h"
24 
25 #ifdef HAVE_STDIO_H
26 #include <stdio.h>
27 #endif
28 #ifdef HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #endif
34 #ifdef HAVE_GLOB_H
35 #include <glob.h>
36 #endif
37 #ifdef HAVE_WINDOWS_H
38 #include <windows.h>
39 #endif
40 #ifdef HAVE_STDBOOL_H
41 # include <stdbool.h>
42 #endif
43 
44 #include <cdio/bytesex.h>
45 #include <cdio/ds.h>
46 #include <cdio/logging.h>
47 #include <cdio/util.h>
48 #include <cdio/version.h>
49 #include "cdio_assert.h"
50 #include "_cdio_stdio.h"
51 #include "nrg.h"
52 #include "cdtext_private.h"
53 
54 nero_id_t    nero_id;
55 nero_dtype_t nero_dtype;
56 
57 /* reader */
58 #define DEFAULT_CDIO_DEVICE "image.nrg"
59 
60 /*
61    Link element of track structure as a linked list.
62    Possibly redundant with above track_info_t */
63 typedef struct {
64   uint32_t start_lsn;
65   uint32_t sec_count;     /* Number of sectors in track. Does not
66 			     include pregap before next entry. */
67   uint64_t img_offset;    /* Bytes offset from beginning of disk image file.*/
68   uint32_t blocksize;     /* Number of bytes in a block */
69 } _mapping_t;
70 
71 
72 #define NEED_NERO_STRUCT
73 #include "image_common.h"
74 
75 static bool  parse_nrg (_img_private_t *env, const char *psz_cue_name,
76 			const cdio_log_level_t log_level);
77 static lsn_t get_disc_last_lsn_nrg (void *p_user_data);
78 
79 /* Updates internal track TOC, so we can later
80    simulate ioctl(CDROMREADTOCENTRY).
81  */
82 static void
_register_mapping(_img_private_t * env,lsn_t start_lsn,uint32_t sec_count,uint64_t img_offset,uint32_t blocksize,track_format_t track_format,bool track_green)83 _register_mapping (_img_private_t *env, lsn_t start_lsn, uint32_t sec_count,
84 		   uint64_t img_offset, uint32_t blocksize,
85 		   track_format_t track_format, bool track_green)
86 {
87   const int track_num=env->gen.i_tracks;
88   track_info_t  *this_track=&(env->tocent[env->gen.i_tracks]);
89   _mapping_t *_map = calloc(1, sizeof (_mapping_t));
90 
91   _map->start_lsn  = start_lsn;
92   _map->sec_count  = sec_count;
93   _map->img_offset = img_offset;
94   _map->blocksize  = blocksize;
95 
96   if (!env->mapping) env->mapping = _cdio_list_new ();
97   _cdio_list_append (env->mapping, _map);
98 
99   env->size = MAX (env->size, (start_lsn + sec_count));
100 
101   /* Update *this_track and track_num. These structures are
102      in a sense redundant witht the obj->mapping list. Perhaps one
103      or the other can be eliminated.
104    */
105 
106   cdio_lba_to_msf (cdio_lsn_to_lba(start_lsn), &(this_track->start_msf));
107   this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf);
108   this_track->track_num = track_num+1;
109   this_track->blocksize = blocksize;
110   if (env->is_cues)
111     this_track->datastart = img_offset;
112   else
113     this_track->datastart = 0;
114 
115   if (track_green)
116     this_track->datastart += CDIO_CD_SUBHEADER_SIZE;
117 
118   this_track->sec_count = sec_count;
119 
120   this_track->track_format= track_format;
121   this_track->track_green = track_green;
122 
123   switch (this_track->track_format) {
124   case TRACK_FORMAT_AUDIO:
125     this_track->blocksize   = CDIO_CD_FRAMESIZE_RAW;
126     this_track->datasize    = CDIO_CD_FRAMESIZE_RAW;
127     /*this_track->datastart   = 0;*/
128     this_track->endsize     = 0;
129     break;
130   case TRACK_FORMAT_CDI:
131     this_track->datasize=CDIO_CD_FRAMESIZE;
132     break;
133   case TRACK_FORMAT_XA:
134     if (track_green) {
135       this_track->blocksize = CDIO_CD_FRAMESIZE;
136       /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/
137       this_track->datasize  = M2RAW_SECTOR_SIZE;
138       this_track->endsize   = 0;
139     } else {
140       /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE +
141 	CDIO_CD_SUBHEADER_SIZE;*/
142       this_track->datasize  = CDIO_CD_FRAMESIZE;
143       this_track->endsize   = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE;
144     }
145     break;
146   case TRACK_FORMAT_DATA:
147     if (track_green) {
148       /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/
149       this_track->datasize  = CDIO_CD_FRAMESIZE;
150       this_track->endsize   = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE
151 	  + CDIO_CD_ECC_SIZE;
152     } else {
153       /* Is the below correct? */
154       /*this_track->datastart = 0;*/
155       this_track->datasize  = CDIO_CD_FRAMESIZE;
156       this_track->endsize   = 0;
157     }
158     break;
159   default:
160     /*this_track->datasize=CDIO_CD_FRAMESIZE_RAW;*/
161     cdio_warn ("track %d has unknown format %d",
162 	       env->gen.i_tracks, this_track->track_format);
163   }
164 
165   env->gen.i_tracks++;
166 
167   cdio_debug ("start lsn: %lu sector count: %0lu -> %8ld (%08lx)",
168 	      (long unsigned int) start_lsn,
169 	      (long unsigned int) sec_count,
170 	      (long unsigned int) img_offset,
171 	      (long unsigned int) img_offset);
172 }
173 
174 
175 /*
176    Disk and track information for a Nero file are located at the end
177    of the file. This routine extracts that information.
178 
179    FIXME: right now psz_nrg_name is not used. It will be in the future.
180  */
181 static bool
parse_nrg(_img_private_t * p_env,const char * psz_nrg_name,const cdio_log_level_t log_level)182 parse_nrg (_img_private_t *p_env, const char *psz_nrg_name,
183 	   const cdio_log_level_t log_level)
184 {
185   off_t footer_start;
186   off_t size;
187   char *footer_buf = NULL;
188   if (!p_env) return false;
189   size = cdio_stream_stat (p_env->gen.data_source);
190   if (-1 == size) return false;
191 
192   {
193     _footer_t buf;
194     cdio_assert (sizeof (buf) == 12);
195 
196     cdio_stream_seek (p_env->gen.data_source, size - sizeof (buf), SEEK_SET);
197     cdio_stream_read (p_env->gen.data_source, (void *) &buf, sizeof (buf), 1);
198 
199     if (buf.v50.ID == UINT32_TO_BE (NERO_ID)) {
200       cdio_debug ("detected Nero version 5.0 (32-bit offsets) NRG magic");
201       footer_start = uint32_to_be (buf.v50.footer_ofs);
202     } else if (buf.v55.ID == UINT32_TO_BE (NER5_ID)) {
203       cdio_debug ("detected Nero version 5.5.x (64-bit offsets) NRG magic");
204       footer_start = uint64_from_be (buf.v55.footer_ofs);
205     } else {
206       cdio_log (log_level, "Image not recognized as either version 5.0 or "
207 		"version 5.5.x-6.x type NRG");
208       return false;
209     }
210 
211     cdio_debug (".NRG footer start = %ld, length = %ld",
212 	       (long) footer_start, (long) (size - footer_start));
213 
214     cdio_assert ((size - footer_start) <= 4096);
215 
216     footer_buf = calloc(1, (size_t)(size - footer_start));
217 
218     cdio_stream_seek (p_env->gen.data_source, footer_start, SEEK_SET);
219     cdio_stream_read (p_env->gen.data_source, footer_buf,
220 		      (size_t)(size - footer_start), 1);
221   }
222   {
223     int pos = 0;
224 
225     while (pos < size - footer_start) {
226       _chunk_t *chunk = (void *) (footer_buf + pos);
227       uint32_t opcode = UINT32_FROM_BE (chunk->id);
228 
229       bool break_out = false;
230 
231       switch (opcode) {
232 
233       case CUES_ID: /* "CUES" Seems to have sector size 2336 and 150 sector
234 		       pregap seems to be included at beginning of image.
235 		       */
236       case CUEX_ID: /* "CUEX" */
237 	{
238 	  unsigned entries = UINT32_FROM_BE (chunk->len);
239 	  _cuex_array_t *_entries = (void *) chunk->data;
240 
241 	  cdio_assert (p_env->mapping == NULL);
242 
243 	  cdio_assert ( sizeof (_cuex_array_t) == 8 );
244 	  cdio_assert ( UINT32_FROM_BE (chunk->len) % sizeof(_cuex_array_t)
245 			== 0 );
246 
247 	  entries /= sizeof (_cuex_array_t);
248 
249 	  if (CUES_ID == opcode) {
250 	    unsigned int idx;
251 	    unsigned int i = 0;
252 	    lsn_t lsn; /* = UINT32_FROM_BE (_entries[0].lsn); */
253 	    /* CUES LSN has 150 pregap include at beginning? -/
254 	       cdio_assert (lsn == 0?);
255 	    */
256 
257 	    cdio_debug ("CUES type image detected" );
258 
259 	    p_env->is_cues           = true; /* HACK alert. */
260 	    p_env->gen.i_tracks      = 0;
261 	    p_env->gen.i_first_track = 1;
262 	    for (idx = 1; idx < entries-1; idx += 2, i++) {
263 	      lsn_t sec_count;
264 	      int cdte_format = _entries[idx].addr_ctrl / 16;
265 	      int cdte_ctrl   = _entries[idx].type >> 4;
266 
267 	      if ( COPY_PERMITTED & cdte_ctrl ) {
268 		if (p_env) p_env->tocent[i].flags |= COPY_PERMITTED;
269 	      } else {
270 		if (p_env) p_env->tocent[i].flags &= ~COPY_PERMITTED;
271 	      }
272 
273 	      if ( PRE_EMPHASIS & cdte_ctrl ) {
274 		if (p_env) p_env->tocent[i].flags |= PRE_EMPHASIS;
275 	      } else {
276 		if (p_env) p_env->tocent[i].flags &= ~PRE_EMPHASIS;
277 	      }
278 
279 	      if ( FOUR_CHANNEL_AUDIO & cdte_ctrl ) {
280 		if (p_env) p_env->tocent[i].flags |= FOUR_CHANNEL_AUDIO;
281 	      } else {
282 		if (p_env) p_env->tocent[i].flags &= ~FOUR_CHANNEL_AUDIO;
283 	      }
284 
285 	      cdio_assert (_entries[idx].track == _entries[idx + 1].track);
286 
287 	      /* lsn and sec_count*2 aren't correct, but it comes closer on the
288 		 single example I have: svcdgs.nrg
289 		 We are picking up the wrong fields and/or not interpreting
290 		 them correctly.
291 	      */
292 
293 	      switch (cdte_format) {
294 	      case 0:
295 		lsn = UINT32_FROM_BE (_entries[idx].lsn);
296 		break;
297 	      case 1:
298 		{
299 #if 0
300 		  msf_t msf = (msf_t) _entries[idx].lsn;
301 		  lsn = cdio_msf_to_lsn(&msf);
302 #else
303 		  lsn = CDIO_INVALID_LSN;
304 #endif
305 		  cdio_log (log_level,
306 			    "untested (i.e. probably wrong) CUE MSF code");
307 		  break;
308 		}
309 	      default:
310 		lsn = CDIO_INVALID_LSN;
311 		cdio_log(log_level,
312 			 "unknown cdte_format %d", cdte_format);
313 	      }
314 
315 	      sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn);
316 
317 	      _register_mapping (p_env, lsn, sec_count*2,
318 				 (lsn+CDIO_PREGAP_SECTORS) * M2RAW_SECTOR_SIZE,
319 				 M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true);
320 	    }
321 	  } else {
322 	    lsn_t lsn = UINT32_FROM_BE (_entries[0].lsn);
323 	    unsigned int idx;
324 	    unsigned int i = 0;
325 
326 	    cdio_debug ("CUEX type image detected");
327 
328 	    /* LSN must start at -150 (LBA 0)? */
329 	    cdio_assert (lsn == -150);
330 
331 	    for (idx = 2; idx < entries; idx += 2, i++) {
332 	      lsn_t sec_count;
333 	      int cdte_format = _entries[idx].addr_ctrl >> 4;
334 	      int cdte_ctrl   = _entries[idx].type >> 4;
335 
336 	      if ( COPY_PERMITTED & cdte_ctrl ) {
337 		if (p_env) p_env->tocent[i].flags |= COPY_PERMITTED;
338 	      } else {
339 		if (p_env) p_env->tocent[i].flags &= ~COPY_PERMITTED;
340 	      }
341 
342 	      if ( PRE_EMPHASIS & cdte_ctrl ) {
343 		if (p_env) p_env->tocent[i].flags |= PRE_EMPHASIS;
344 	      } else {
345 		if (p_env) p_env->tocent[i].flags &= ~PRE_EMPHASIS;
346 	      }
347 
348 	      if ( FOUR_CHANNEL_AUDIO & cdte_ctrl ) {
349 		if (p_env) p_env->tocent[i].flags |= FOUR_CHANNEL_AUDIO;
350 	      } else {
351 		if (p_env) p_env->tocent[i].flags &= ~FOUR_CHANNEL_AUDIO;
352 	      }
353 
354 	      /* extractnrg.pl has cdte_format for LBA's 0, and
355 		 for MSF 1. ???
356 
357 		 FIXME: Should decode as appropriate for cdte_format.
358 	       */
359 	      cdio_assert ( cdte_format == 0 || cdte_format == 1 );
360 
361 	      cdio_assert (_entries[idx].track != _entries[idx + 1].track);
362 
363 	      lsn       = UINT32_FROM_BE (_entries[idx].lsn);
364 	      sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn);
365 
366 	      _register_mapping (p_env, lsn, sec_count - lsn,
367 				 (lsn + CDIO_PREGAP_SECTORS)*M2RAW_SECTOR_SIZE,
368 				 M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true);
369 	    }
370 	  }
371 	  break;
372 	}
373 
374       case DAOX_ID: /* "DAOX" */
375       case DAOI_ID: /* "DAOI" */
376 	{
377 	  _daox_t *_xentries = NULL;
378 	  _daoi_t *_ientries = NULL;
379 	  _dao_array_common_t *_dao_array_common = NULL;
380 	  _dao_common_t *_dao_common = (void *) chunk->data;
381 	  int disc_mode = _dao_common->unknown[1];
382 	  track_format_t track_format;
383 	  int i;
384 
385 	  /* We include an extra 0 byte so these can be used as C strings.*/
386 	  p_env->psz_mcn = calloc(1, CDIO_MCN_SIZE+1);
387 	  memcpy(p_env->psz_mcn, &(_dao_common->psz_mcn), CDIO_MCN_SIZE);
388 	  p_env->psz_mcn[CDIO_MCN_SIZE] = '\0';
389 
390 	  if (DAOX_ID == opcode) {
391 	    _xentries = (void *) chunk->data;
392 	    p_env->dtyp = _xentries->track_info[0].common.unknown[2];
393 	  } else {
394 	    _ientries = (void *) chunk->data;
395 	    p_env->dtyp = _ientries->track_info[0].common.unknown[2];
396 	  }
397 
398 	  p_env->is_dao = true;
399 	  cdio_debug ("DAO%c tag detected, track format %d, mode %x\n",
400 		      opcode==DAOX_ID ? 'X': 'I', p_env->dtyp, disc_mode);
401 	  switch (p_env->dtyp) {
402 	  case 0:
403 	    /* Mode 1 */
404 	    track_format     = TRACK_FORMAT_DATA;
405 	    p_env->disc_mode = CDIO_DISC_MODE_CD_DATA;
406 	    break;
407 	  case 2:
408 	    /* Mode 2 form 1 */
409 	    disc_mode             = 0;
410 	    track_format     = TRACK_FORMAT_XA;
411 	    p_env->disc_mode = CDIO_DISC_MODE_CD_XA;
412 	    break;
413 	  case 3:
414 	    /* Mode 2 */
415 	    track_format     = TRACK_FORMAT_XA;
416 	    p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */
417 	    break;
418 	  case 0x6:
419 	    /* Mode2 form mix */
420 	    track_format     = TRACK_FORMAT_XA;
421 	    p_env->disc_mode = CDIO_DISC_MODE_CD_MIXED;
422 	    break;
423 	  case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */
424 	    track_format     = TRACK_FORMAT_XA;
425 	    p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */
426 	    break;
427 	  case 0x7:
428 	    track_format     = TRACK_FORMAT_AUDIO;
429 	    p_env->disc_mode = CDIO_DISC_MODE_CD_DA;
430 	    break;
431 	  default:
432 	    cdio_log (log_level, "Unknown track format %x\n",
433 		      p_env->dtyp);
434 	    track_format = TRACK_FORMAT_AUDIO;
435 	  }
436 	  if (0 == disc_mode) {
437 	    for (i=0; i<p_env->gen.i_tracks; i++) {
438 	      p_env->tocent[i].track_format= track_format;
439 	      p_env->tocent[i].datastart   = 0;
440 	      p_env->tocent[i].track_green = false;
441 	      if (TRACK_FORMAT_AUDIO == track_format) {
442 		p_env->tocent[i].blocksize   = CDIO_CD_FRAMESIZE_RAW;
443 		p_env->tocent[i].datasize    = CDIO_CD_FRAMESIZE_RAW;
444 		p_env->tocent[i].endsize     = 0;
445 	      } else {
446 		p_env->tocent[i].datasize    = CDIO_CD_FRAMESIZE;
447 		p_env->tocent[i].datastart  =  0;
448 	      }
449 	    }
450 	  } else if (2 == disc_mode) {
451 	    for (i=0; i<p_env->gen.i_tracks; i++) {
452 	      p_env->tocent[i].track_green = true;
453 	      p_env->tocent[i].track_format= track_format;
454 	      p_env->tocent[i].datasize    = CDIO_CD_FRAMESIZE;
455 	      if (TRACK_FORMAT_XA == track_format) {
456 		p_env->tocent[i].datastart   = CDIO_CD_SYNC_SIZE
457 		  + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;
458 		p_env->tocent[i].endsize     = CDIO_CD_SYNC_SIZE
459 		  + CDIO_CD_ECC_SIZE;
460 	      } else {
461 		p_env->tocent[i].datastart   = CDIO_CD_SYNC_SIZE
462 		  + CDIO_CD_HEADER_SIZE;
463 		p_env->tocent[i].endsize     = CDIO_CD_EDC_SIZE
464 		  + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE;
465 
466 	      }
467 	    }
468 	  } else if (0x20 == disc_mode) {
469 	    cdio_debug ("Mixed mode CD?\n");
470 	  } else {
471 	    /* Mixed mode CD */
472 	    cdio_log (log_level,
473 		      "Don't know if mode 1, mode 2 or mixed: %x\n",
474 		      disc_mode);
475 	  }
476 
477 	  for (i=0; i<p_env->gen.i_tracks; i++) {
478 
479 	    if (DAOX_ID == opcode) {
480 	      _dao_array_common = &_xentries->track_info[i].common;
481 	    } else {
482 	      _dao_array_common = &_ientries->track_info[i].common;
483 	    }
484 	    p_env->tocent[i].isrc = calloc(1, CDIO_ISRC_SIZE+1);
485 	    memcpy(p_env->tocent[i].isrc, _dao_array_common->psz_isrc, CDIO_ISRC_SIZE);
486 	    p_env->tocent[i].isrc[CDIO_ISRC_SIZE] = '\0';
487 	    if (p_env->tocent[i].isrc[0]) {
488 	       cdio_info("nrg isrc has value \"%s\"", p_env->tocent[i].isrc);
489 	    }
490 
491 	    if (!p_env->tocent[i].datasize) {
492 	      continue;
493 	    }
494 	    if (DAOX_ID == opcode) {
495 	       p_env->tocent[i].pregap = (uint64_from_be
496 		(_xentries->track_info[i].index0)) / (p_env->tocent[i].datasize);
497 	    } else {
498 	       p_env->tocent[i].pregap = (uint32_from_be
499 		(_ientries->track_info[i].index0)) / (p_env->tocent[i].datasize);
500 	    }
501 	  }
502 
503 	  break;
504 	}
505       case NERO_ID:
506       case NER5_ID:
507 	cdio_error ("unexpected nrg magic ID NER%c detected",
508 		    opcode==NERO_ID ? 'O': '5');
509 	free(footer_buf);
510 	return false;
511 
512       case END1_ID: /* "END!" */
513 	cdio_debug ("nrg end tag detected");
514 	break_out = true;
515 	break;
516 
517       case ETNF_ID: /* "ETNF" */ {
518 	unsigned entries = UINT32_FROM_BE (chunk->len);
519 	_etnf_array_t *_entries = (void *) chunk->data;
520 
521 	cdio_assert (p_env->mapping == NULL);
522 
523 	cdio_assert ( sizeof (_etnf_array_t) == 20 );
524 	cdio_assert ( UINT32_FROM_BE(chunk->len) % sizeof(_etnf_array_t)
525 		      == 0 );
526 
527 	entries /= sizeof (_etnf_array_t);
528 
529 	cdio_debug ("SAO type image (ETNF) detected");
530 
531 	{
532 	  int idx;
533 	  for (idx = 0; idx < entries; idx++) {
534 	    uint32_t _len = UINT32_FROM_BE (_entries[idx].length);
535 	    uint32_t _start = UINT32_FROM_BE (_entries[idx].start_lsn);
536 	    uint32_t _start2 = UINT32_FROM_BE (_entries[idx].start);
537 	    uint32_t track_mode= uint32_from_be (_entries[idx].type);
538 	    bool     track_green = true;
539 	    track_format_t track_format = TRACK_FORMAT_XA;
540 	    uint16_t  blocksize;
541 
542 	    switch (track_mode) {
543 	    case 0:
544 	      /* Mode 1 */
545 	      track_format   = TRACK_FORMAT_DATA;
546 	      track_green    = false; /* ?? */
547 	      blocksize      = CDIO_CD_FRAMESIZE;
548 	      p_env->disc_mode = CDIO_DISC_MODE_CD_DATA;
549 	      cdio_debug ("Format DATA, blocksize %u", CDIO_CD_FRAMESIZE);
550 	      break;
551 	    case 2:
552 	      /* Mode 2 form 1 */
553 	      track_format   = TRACK_FORMAT_XA;
554 	      track_green    = false; /* ?? */
555 	      blocksize      = CDIO_CD_FRAMESIZE;
556 	      p_env->disc_mode = CDIO_DISC_MODE_CD_XA;
557 	      cdio_debug ("Format XA, blocksize %u", CDIO_CD_FRAMESIZE);
558 	      break;
559 	    case 3:
560 	      /* Mode 2 */
561 	      track_format   = TRACK_FORMAT_XA;
562 	      track_green    = true;
563 	      blocksize      = M2RAW_SECTOR_SIZE;
564 	      p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */
565 	      cdio_debug ("Format XA, blocksize %u", M2RAW_SECTOR_SIZE);
566 	      break;
567 	    case 06:
568 	      /* Mode2 form mix */
569 	      track_format   = TRACK_FORMAT_XA;
570 	      track_green    = true;
571 	      blocksize      = M2RAW_SECTOR_SIZE;
572 	      p_env->disc_mode = CDIO_DISC_MODE_CD_MIXED;
573 	      cdio_debug ("Format MIXED CD, blocksize %u", M2RAW_SECTOR_SIZE);
574 	      break;
575 	    case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */
576 	      track_format   = TRACK_FORMAT_XA;
577 	      track_green    = true;
578 	      blocksize      = M2RAW_SECTOR_SIZE;
579 	      p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */
580 	      cdio_debug ("Format MIXED CD, blocksize %u", M2RAW_SECTOR_SIZE);
581 	      break;
582 	    case 7:
583 	      track_format   = TRACK_FORMAT_AUDIO;
584 	      track_green    = false;
585 	      blocksize      = CDIO_CD_FRAMESIZE_RAW;
586 	      p_env->disc_mode = CDIO_DISC_MODE_CD_DA;
587 	      cdio_debug ("Format CD_DA, blocksize %u", CDIO_CD_FRAMESIZE_RAW);
588 	      break;
589 	    default:
590 	      cdio_log (log_level,
591 			"Don't know how to handle track mode (%lu)?",
592 			(long unsigned int) track_mode);
593 	      free(footer_buf);
594 	      return false;
595 	    }
596 
597 	    cdio_assert (_len % blocksize == 0);
598 
599 	    _len /= blocksize;
600 
601 	    cdio_assert (_start * blocksize == _start2);
602 
603 	    _start += idx * CDIO_PREGAP_SECTORS;
604 	    _register_mapping (p_env, _start, _len, _start2, blocksize,
605 			       track_format, track_green);
606 
607 	  }
608 	}
609 	break;
610       }
611 
612       case ETN2_ID: { /* "ETN2", same as above, but with 64bit stuff instead */
613 	unsigned entries = uint32_from_be (chunk->len);
614 	_etn2_array_t *_entries = (void *) chunk->data;
615 
616 	cdio_assert (p_env->mapping == NULL);
617 
618 	cdio_assert (sizeof (_etn2_array_t) == 32);
619 	cdio_assert (uint32_from_be (chunk->len) % sizeof (_etn2_array_t) == 0);
620 
621 	entries /= sizeof (_etn2_array_t);
622 
623 	cdio_debug ("SAO type image (ETN2) detected");
624 
625 	{
626 	  int idx;
627 	  for (idx = 0; idx < entries; idx++) {
628 	    uint32_t _len = uint64_from_be (_entries[idx].length);
629 	    uint32_t _start = uint32_from_be (_entries[idx].start_lsn);
630 	    uint32_t _start2 = uint64_from_be (_entries[idx].start);
631 	    uint32_t track_mode= uint32_from_be (_entries[idx].type);
632 	    bool     track_green = true;
633 	    track_format_t track_format = TRACK_FORMAT_XA;
634 	    uint16_t  blocksize;
635 
636 
637 	    switch (track_mode) {
638 	    case 0:
639 	      track_format = TRACK_FORMAT_DATA;
640 	      track_green  = false; /* ?? */
641 	      blocksize    = CDIO_CD_FRAMESIZE;
642 	      break;
643 	    case 2:
644 	      track_format = TRACK_FORMAT_XA;
645 	      track_green  = false; /* ?? */
646 	      blocksize    = CDIO_CD_FRAMESIZE;
647 	      break;
648 	    case 3:
649 	      track_format = TRACK_FORMAT_XA;
650 	      track_green  = true;
651 	      blocksize    = M2RAW_SECTOR_SIZE;
652 	      break;
653 	    case 7:
654 	      track_format = TRACK_FORMAT_AUDIO;
655 	      track_green  = false;
656 	      blocksize    = CDIO_CD_FRAMESIZE_RAW;
657 	      break;
658 	    default:
659 	      cdio_log (log_level,
660 			"Don't know how to handle track mode (%lu)?",
661 			(long unsigned int) track_mode);
662 	      free(footer_buf);
663 	      return false;
664 	    }
665 
666 	    if (_len % blocksize != 0) {
667 	      cdio_log (log_level,
668 			"length is not a multiple of blocksize "
669 			 "len %lu, size %d, rem %lu",
670 			 (long unsigned int) _len, blocksize,
671 			 (long unsigned int) _len % blocksize);
672 	      if (0 == _len % CDIO_CD_FRAMESIZE) {
673 		cdio_log(log_level, "Adjusting blocksize to %d",
674 			 CDIO_CD_FRAMESIZE);
675 		blocksize = CDIO_CD_FRAMESIZE;
676 	      } else if (0 == _len % M2RAW_SECTOR_SIZE) {
677 		cdio_log(log_level,
678 			 "Adjusting blocksize to %d", M2RAW_SECTOR_SIZE);
679 		blocksize = M2RAW_SECTOR_SIZE;
680 	      } else if (0 == _len % CDIO_CD_FRAMESIZE_RAW) {
681 		cdio_log(log_level,
682 			 "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW);
683 		blocksize = CDIO_CD_FRAMESIZE_RAW;
684 	      }
685 	    }
686 
687 	    _len /= blocksize;
688 
689 	    if (_start * blocksize != _start2) {
690 	      cdio_log (log_level,
691 			"%lu * %d != %lu",
692 			 (long unsigned int) _start, blocksize,
693 			 (long unsigned int) _start2);
694 	      if (_start * CDIO_CD_FRAMESIZE == _start2) {
695 		cdio_log(log_level,
696 			 "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE);
697 		blocksize = CDIO_CD_FRAMESIZE;
698 	      } else if (_start * M2RAW_SECTOR_SIZE == _start2) {
699 		cdio_log(log_level,
700 			 "Adjusting blocksize to %d", M2RAW_SECTOR_SIZE);
701 		blocksize = M2RAW_SECTOR_SIZE;
702 	      } else if (_start * CDIO_CD_FRAMESIZE_RAW == _start2) {
703 		cdio_log(log_level,
704 			 "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW);
705 		blocksize = CDIO_CD_FRAMESIZE_RAW;
706 	      }
707 	    }
708 
709 	    _start += idx * CDIO_PREGAP_SECTORS;
710 	    _register_mapping (p_env, _start, _len, _start2, blocksize,
711 			       track_format, track_green);
712 	  }
713 	}
714 	break;
715       }
716 
717       case SINF_ID: { /* "SINF" */
718 
719 	uint32_t _sessions;
720 
721 	cdio_assert (UINT32_FROM_BE (chunk->len) == 4);
722 
723 	memcpy(&_sessions, chunk->data, 4);
724 
725 	cdio_debug ("SINF: %lu sessions",
726 		    (long unsigned int) UINT32_FROM_BE (_sessions));
727       }
728 	break;
729 
730       case MTYP_ID: { /* "MTYP" */
731 	uint32_t mtyp_be;
732 	uint32_t mtyp;
733 
734 	cdio_assert (UINT32_FROM_BE (chunk->len) == 4);
735 
736 	memcpy(&mtyp_be, chunk->data, 4);
737 	mtyp = UINT32_FROM_BE (mtyp_be);
738 
739 	cdio_debug ("MTYP: %lu",
740 		    (long unsigned int) mtyp);
741 
742 	if (mtyp != MTYP_AUDIO_CD) {
743 	  cdio_log (log_level,
744 		    "Unknown MTYP value: %u", (unsigned int) mtyp);
745 	}
746 	p_env->mtyp = mtyp;
747       }
748 	break;
749 
750       case CDTX_ID: { /* "CD TEXT" */
751         uint8_t *wdata = (uint8_t *) chunk->data;
752         int len = UINT32_FROM_BE (chunk->len);
753         cdio_assert (len % CDTEXT_LEN_PACK == 0);
754         p_env->gen.cdtext = cdtext_init ();
755         if(0 !=cdtext_data_init (p_env->gen.cdtext, wdata, len))
756         {
757           cdtext_destroy(p_env->gen.cdtext);
758           free(p_env->gen.cdtext);
759           p_env->gen.cdtext = NULL;
760         }
761 
762         break;
763       }
764 
765       default:
766 	cdio_log (log_level,
767 		  "unknown tag %8.8x seen",
768 		  (unsigned int) UINT32_FROM_BE (chunk->id));
769 	break;
770       }
771 
772       if (break_out)
773 	break;
774 
775       pos += 8;
776       pos += UINT32_FROM_BE (chunk->len);
777     }
778   }
779 
780   /* Fake out leadout track. */
781   /* Don't use get_disc_last_lsn_nrg since that will lead to recursion since
782      we haven't fully initialized things yet.
783   */
784   cdio_lsn_to_msf (p_env->size, &p_env->tocent[p_env->gen.i_tracks].start_msf);
785   p_env->tocent[p_env->gen.i_tracks].start_lba = cdio_lsn_to_lba(p_env->size);
786   p_env->tocent[p_env->gen.i_tracks-1].sec_count =
787     cdio_lsn_to_lba(p_env->size - p_env->tocent[p_env->gen.i_tracks-1].start_lba);
788 
789   p_env->gen.b_cdtext_error = false;
790   p_env->gen.toc_init       = true;
791   free(footer_buf);
792   return true;
793 }
794 
795 /*!
796   Initialize image structures.
797  */
798 static bool
_init_nrg(_img_private_t * p_env)799 _init_nrg (_img_private_t *p_env)
800 {
801   if (p_env->gen.init) {
802     cdio_error ("init called more than once");
803     return false;
804   }
805 
806   if (!(p_env->gen.data_source = cdio_stdio_new (p_env->gen.source_name))) {
807     cdio_warn ("can't open nrg image file %s for reading",
808 	       p_env->gen.source_name);
809     return false;
810   }
811 
812   p_env->psz_mcn       = NULL;
813   p_env->disc_mode     = CDIO_DISC_MODE_NO_INFO;
814 
815   if ( !parse_nrg (p_env, p_env->gen.source_name, CDIO_LOG_WARN) ) {
816     cdio_warn ("image file %s is not a Nero image",
817 	       p_env->gen.source_name);
818     return false;
819   }
820 
821   p_env->gen.init = true;
822   return true;
823 
824 }
825 
826 /*!
827   Reads into buf the next size bytes.
828   Returns -1 on error.
829   Would be libc's seek() but we have to adjust for the extra track header
830   information in each sector.
831 */
832 static off_t
_lseek_nrg(void * p_user_data,off_t offset,int whence)833 _lseek_nrg (void *p_user_data, off_t offset, int whence)
834 {
835   _img_private_t *p_env = p_user_data;
836 
837   /* real_offset is the real byte offset inside the disk image
838      The number below was determined empirically.
839   */
840   off_t real_offset= p_env->is_dao ? 0x4b000 : 0;
841 
842   unsigned int i;
843 
844   p_env->pos.lba = 0;
845   for (i=0; i<p_env->gen.i_tracks; i++) {
846     track_info_t  *this_track=&(p_env->tocent[i]);
847     p_env->pos.index = i;
848     if ( (this_track->sec_count*this_track->datasize) >= offset) {
849       int blocks            = (int) (offset / this_track->datasize);
850       int rem               = (int) (offset % this_track->datasize);
851       off_t block_offset    = blocks * this_track->blocksize;
852       real_offset          += block_offset + rem;
853       p_env->pos.buff_offset = rem;
854       p_env->pos.lba        += blocks;
855       break;
856     }
857     real_offset   += this_track->sec_count*this_track->blocksize;
858     offset        -= this_track->sec_count*this_track->datasize;
859     p_env->pos.lba += this_track->sec_count;
860   }
861 
862   if (i==p_env->gen.i_tracks) {
863     cdio_warn ("seeking outside range of disk image");
864     return -1;
865   } else
866     real_offset += p_env->tocent[i].datastart;
867   return cdio_stream_seek(p_env->gen.data_source, real_offset, whence);
868 }
869 
870 /*!
871   Reads into buf the next size bytes.
872   Returns -1 on error.
873   FIXME:
874    At present we assume a read doesn't cross sector or track
875    boundaries.
876 */
877 static ssize_t
_read_nrg(void * p_user_data,void * buf,size_t size)878 _read_nrg (void *p_user_data, void *buf, size_t size)
879 {
880   _img_private_t *p_env = p_user_data;
881   return cdio_stream_read(p_env->gen.data_source, buf, size, 1);
882 }
883 
884 /*!
885   Get the size of the CD in logical block address (LBA) units.
886 
887   @param p_cdio the CD object queried
888   @return the lsn. On error 0 or CDIO_INVALD_LSN.
889 */
890 static lsn_t
get_disc_last_lsn_nrg(void * p_user_data)891 get_disc_last_lsn_nrg (void *p_user_data)
892 {
893   _img_private_t *p_env = p_user_data;
894 
895   return p_env->size;
896 }
897 
898 /*!
899    Reads a single audio sector from CD device into data starting
900    from LSN.
901  */
902 static driver_return_code_t
_read_audio_sectors_nrg(void * p_user_data,void * data,lsn_t lsn,unsigned int nblocks)903 _read_audio_sectors_nrg (void *p_user_data, void *data, lsn_t lsn,
904 			  unsigned int nblocks)
905 {
906   _img_private_t *p_env = p_user_data;
907   CdioListNode_t *node;
908 
909   if (lsn >= p_env->size)
910     {
911       cdio_warn ("trying to read beyond image size (%lu >= %lu)",
912 		 (long unsigned int) lsn, (long unsigned int) p_env->size);
913       return -1;
914     }
915 
916   if (p_env->is_dao) {
917     int ret;
918 
919     ret = cdio_stream_seek (p_env->gen.data_source,
920               (lsn + CDIO_PREGAP_SECTORS) * CDIO_CD_FRAMESIZE_RAW, SEEK_SET);
921     if (ret!=0) return ret;
922 
923     ret = cdio_stream_read (p_env->gen.data_source, data,
924               CDIO_CD_FRAMESIZE_RAW, nblocks);
925 
926     /* ret is number of bytes if okay, but we need to return 0 okay. */
927     return ret == 0;
928   }
929 
930   _CDIO_LIST_FOREACH (node, p_env->mapping) {
931     _mapping_t *_map = _cdio_list_node_data (node);
932 
933     if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) {
934       int ret;
935       long int img_offset = _map->img_offset;
936 
937       img_offset += (lsn - _map->start_lsn) * CDIO_CD_FRAMESIZE_RAW;
938 
939       ret = cdio_stream_seek (p_env->gen.data_source, img_offset,
940 			      SEEK_SET);
941       if (ret!=0) return ret;
942       ret = cdio_stream_read (p_env->gen.data_source, data,
943 			      CDIO_CD_FRAMESIZE_RAW, nblocks);
944       if (ret==0) return ret;
945       break;
946     }
947   }
948 
949   if (!node) cdio_warn ("reading into pre gap (lsn %lu)",
950 			(long unsigned int) lsn);
951 
952   return 0;
953 }
954 
955 static driver_return_code_t
_read_mode1_sector_nrg(void * p_user_data,void * data,lsn_t lsn,bool b_form2)956 _read_mode1_sector_nrg (void *p_user_data, void *data, lsn_t lsn,
957 			 bool b_form2)
958 {
959   _img_private_t *p_env = p_user_data;
960   char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
961 
962   CdioListNode_t *node;
963 
964   if (lsn >= p_env->size)
965     {
966       cdio_warn ("trying to read beyond image size (%lu >= %lu)",
967 		 (long unsigned int) lsn, (long unsigned int) p_env->size);
968       return -1;
969     }
970 
971   _CDIO_LIST_FOREACH (node, p_env->mapping) {
972     _mapping_t *_map = _cdio_list_node_data (node);
973 
974     if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) {
975       int ret;
976       long int img_offset = _map->img_offset;
977 
978       img_offset += (lsn - _map->start_lsn) * _map->blocksize;
979 
980       ret = cdio_stream_seek (p_env->gen.data_source, img_offset,
981 			      SEEK_SET);
982       if (ret!=0) return ret;
983 
984       /* FIXME: Not completely sure the below is correct. */
985       ret = cdio_stream_read (p_env->gen.data_source,
986 			      (M2RAW_SECTOR_SIZE == _map->blocksize)
987 			      ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE)
988 			      : buf,
989 			      _map->blocksize, 1);
990       if (ret==0) return ret;
991       break;
992     }
993   }
994 
995   if (!node)
996     cdio_warn ("reading into pre gap (lsn %lu)", (long unsigned int) lsn);
997 
998   memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE,
999 	  b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
1000 
1001   return 0;
1002 }
1003 
1004 /*!
1005    Reads nblocks of mode2 sectors from cd device into data starting
1006    from lsn.
1007  */
1008 static driver_return_code_t
_read_mode1_sectors_nrg(void * p_user_data,void * data,lsn_t lsn,bool b_form2,unsigned nblocks)1009 _read_mode1_sectors_nrg (void *p_user_data, void *data, lsn_t lsn,
1010 			 bool b_form2, unsigned nblocks)
1011 {
1012   _img_private_t *p_env = p_user_data;
1013   int i;
1014   int retval;
1015   unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
1016 
1017   for (i = 0; i < nblocks; i++) {
1018     if ( (retval = _read_mode1_sector_nrg (p_env,
1019 					    ((char *)data) + (blocksize * i),
1020 					    lsn + i, b_form2)) )
1021       return retval;
1022   }
1023   return 0;
1024 }
1025 
1026 static driver_return_code_t
_read_mode2_sector_nrg(void * p_user_data,void * data,lsn_t lsn,bool b_form2)1027 _read_mode2_sector_nrg (void *p_user_data, void *data, lsn_t lsn,
1028 			bool b_form2)
1029 {
1030   _img_private_t *p_env = p_user_data;
1031   char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
1032 
1033   CdioListNode_t *node;
1034 
1035   if (lsn >= p_env->size)
1036     {
1037       cdio_warn ("trying to read beyond image size (%lu >= %lu)",
1038 		 (long unsigned int) lsn, (long unsigned int) p_env->size);
1039       return -1;
1040     }
1041 
1042   _CDIO_LIST_FOREACH (node, p_env->mapping) {
1043     _mapping_t *_map = _cdio_list_node_data (node);
1044 
1045     if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) {
1046       int ret;
1047       long int img_offset = _map->img_offset;
1048 
1049       img_offset += (lsn - _map->start_lsn) * _map->blocksize;
1050 
1051       ret = cdio_stream_seek (p_env->gen.data_source, img_offset,
1052 			      SEEK_SET);
1053       if (ret!=0) return ret;
1054       ret = cdio_stream_read (p_env->gen.data_source,
1055 			      (M2RAW_SECTOR_SIZE == _map->blocksize)
1056 			      ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE)
1057 			      : buf,
1058 			      _map->blocksize, 1);
1059       if (ret==0) return ret;
1060       break;
1061     }
1062   }
1063 
1064   if (!node)
1065     cdio_warn ("reading into pre gap (lsn %lu)", (long unsigned int) lsn);
1066 
1067   if (b_form2)
1068     memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE,
1069 	    M2RAW_SECTOR_SIZE);
1070   else
1071     memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, CDIO_CD_FRAMESIZE);
1072 
1073   return 0;
1074 }
1075 
1076 /*!
1077    Reads nblocks of mode2 sectors from cd device into data starting
1078    from lsn.
1079    Returns 0 if no error.
1080  */
1081 static driver_return_code_t
_read_mode2_sectors_nrg(void * p_user_data,void * data,lsn_t lsn,bool b_form2,unsigned nblocks)1082 _read_mode2_sectors_nrg (void *p_user_data, void *data, lsn_t lsn,
1083 			 bool b_form2, unsigned nblocks)
1084 {
1085   _img_private_t *p_env = p_user_data;
1086   int i;
1087   int retval;
1088   unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
1089 
1090   for (i = 0; i < nblocks; i++) {
1091     if ( (retval = _read_mode2_sector_nrg (p_env,
1092 					    ((char *)data) + (blocksize * i),
1093 					    lsn + i, b_form2)) )
1094       return retval;
1095   }
1096   return 0;
1097 }
1098 
1099 /*
1100   Free memory resources associated with NRG object.
1101 */
1102 static void
_free_nrg(void * p_user_data)1103 _free_nrg (void *p_user_data)
1104 {
1105   _img_private_t *p_env = p_user_data;
1106 
1107   if (NULL == p_env) return;
1108   if (NULL != p_env->mapping)
1109     _cdio_list_free (p_env->mapping, true, free);
1110 
1111   /* The remaining part of the image is like the other image drivers,
1112      so free that in the same way. */
1113   _free_image(p_user_data);
1114 }
1115 
1116 /*!
1117   Eject media -- there's nothing to do here except free resources.
1118   We always return 2.
1119  */
1120 static driver_return_code_t
_eject_media_nrg(void * obj)1121 _eject_media_nrg(void *obj)
1122 {
1123   _free_nrg (obj);
1124   return DRIVER_OP_UNSUPPORTED;
1125 }
1126 
1127 #if !defined(HAVE_GLOB_H) && defined(_WIN32)
Win32Glob(const char * pattern,const char * szCurPath,char *** drives,unsigned int * num_files)1128 static void Win32Glob(const char* pattern, const char* szCurPath, char ***drives, unsigned int *num_files)
1129 {
1130   char szPath[MAX_PATH];
1131   WIN32_FIND_DATAA ffd;
1132   HANDLE hFind;
1133   BOOL bFound;
1134 
1135   SetCurrentDirectoryA(szCurPath);
1136 
1137   hFind = FindFirstFileA(pattern, &ffd);
1138   bFound = (hFind != INVALID_HANDLE_VALUE);
1139   while (bFound) {
1140     cdio_add_device_list(drives, ffd.cFileName, num_files);
1141     bFound = FindNextFileA(hFind, &ffd);
1142   }
1143   if (hFind != INVALID_HANDLE_VALUE)
1144     FindClose(hFind);
1145 
1146   hFind = FindFirstFileA("*", &ffd);
1147   bFound = (hFind != INVALID_HANDLE_VALUE);
1148   while (bFound) {
1149     if ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
1150          (strcmp(ffd.cFileName, ".") != 0) && (strcmp(ffd.cFileName, "..") != 0) ) {
1151       GetFullPathNameA(ffd.cFileName, sizeof(szPath), szPath, NULL);
1152       Win32Glob(pattern, szPath, drives, num_files);
1153       SetCurrentDirectoryA(szCurPath);
1154     }
1155     bFound = FindNextFileA(hFind, &ffd);
1156   }
1157   if (hFind != INVALID_HANDLE_VALUE)
1158     FindClose(hFind);
1159 }
1160 #endif
1161 
1162 /*!
1163   Return an array of strings giving possible NRG disk images.
1164  */
1165 char **
cdio_get_devices_nrg(void)1166 cdio_get_devices_nrg (void)
1167 {
1168   char **drives = NULL;
1169   unsigned int num_files=0;
1170 #ifdef HAVE_GLOB_H
1171   unsigned int i;
1172   glob_t globbuf;
1173   globbuf.gl_offs = 0;
1174   glob("*.nrg", GLOB_DOOFFS, NULL, &globbuf);
1175   for (i=0; i<globbuf.gl_pathc; i++) {
1176     cdio_add_device_list(&drives, globbuf.gl_pathv[i], &num_files);
1177   }
1178   globfree(&globbuf);
1179 #elif defined(_WIN32)
1180   char szStartDir[MAX_PATH];
1181   GetCurrentDirectoryA(sizeof(szStartDir), szStartDir);
1182   Win32Glob("*.nrg", szStartDir, &drives, &num_files);
1183 #else
1184   cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &num_files);
1185 #endif /*HAVE_GLOB_H*/
1186   cdio_add_device_list(&drives, NULL, &num_files);
1187   return drives;
1188 }
1189 
1190 /*!
1191   Return a string containing the default CD device.
1192  */
1193 char *
cdio_get_default_device_nrg(void)1194 cdio_get_default_device_nrg(void)
1195 {
1196   char **drives = cdio_get_devices_nrg();
1197   char *drive = (drives[0] == NULL) ? NULL : strdup(drives[0]);
1198   cdio_free_device_list(drives);
1199   return drive;
1200 }
1201 
1202 static bool
get_hwinfo_nrg(const CdIo * p_cdio,cdio_hwinfo_t * hw_info)1203 get_hwinfo_nrg ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info)
1204 {
1205   strncpy(hw_info->psz_vendor, "libcdio",
1206 	 sizeof(hw_info->psz_vendor)-1);
1207   hw_info->psz_vendor[sizeof(hw_info->psz_vendor)-1] = '\0';
1208   strncpy(hw_info->psz_model, "Nero",
1209 	  sizeof(hw_info->psz_model)-1);
1210   hw_info->psz_model[sizeof(hw_info->psz_model)-1] = '\0';
1211   strncpy(hw_info->psz_revision, CDIO_VERSION,
1212 	  sizeof(hw_info->psz_revision)-1);
1213   hw_info->psz_revision[sizeof(hw_info->psz_revision)-1] = '\0';
1214   return true;
1215 
1216 }
1217 
1218 /*!
1219   Return the number of tracks in the current medium.
1220   CDIO_INVALID_TRACK is returned on error.
1221 */
1222 static track_format_t
get_track_format_nrg(void * p_user_data,track_t track_num)1223 get_track_format_nrg(void *p_user_data, track_t track_num)
1224 {
1225   _img_private_t *p_env = p_user_data;
1226 
1227   if (track_num > p_env->gen.i_tracks || track_num == 0)
1228     return TRACK_FORMAT_ERROR;
1229 
1230   if ( p_env->dtyp != DTYP_INVALID) {
1231     switch (p_env->dtyp) {
1232     case DTYP_MODE2_XA:
1233       return TRACK_FORMAT_XA;
1234     case DTYP_MODE1:
1235       return TRACK_FORMAT_DATA;
1236     default: ;
1237     }
1238   }
1239 
1240   /*if ( MTYP_AUDIO_CD == p_env->mtyp) return TRACK_FORMAT_AUDIO; */
1241   return p_env->tocent[track_num-1].track_format;
1242 }
1243 
1244 /*!
1245   Return true if we have XA data (green, mode2 form1) or
1246   XA data (green, mode2 form2). That is track begins:
1247   sync - header - subheader
1248   12     4      -  8
1249 
1250   FIXME: there's gotta be a better design for this and get_track_format?
1251 */
1252 static bool
_get_track_green_nrg(void * p_user_data,track_t track_num)1253 _get_track_green_nrg(void *p_user_data, track_t track_num)
1254 {
1255   _img_private_t *p_env = p_user_data;
1256 
1257   if (track_num > p_env->gen.i_tracks || track_num == 0)
1258     return false;
1259 
1260   if ( MTYP_AUDIO_CD == p_env->mtyp) return false;
1261   return p_env->tocent[track_num-1].track_green;
1262 }
1263 
1264 /*!
1265   Check that a NRG file is valid.
1266 */
1267 bool
cdio_is_nrg(const char * psz_nrg)1268 cdio_is_nrg(const char *psz_nrg)
1269 {
1270   _img_private_t *p_env  = calloc(1, sizeof (_img_private_t));
1271   bool is_nrg = false;
1272 
1273   if (psz_nrg == NULL) {
1274     is_nrg = false;
1275     goto exit;
1276   }
1277 
1278   if (!(p_env->gen.data_source = cdio_stdio_new (psz_nrg))) {
1279     cdio_warn ("can't open nrg image file %s for reading", psz_nrg);
1280     is_nrg = false;
1281     goto exit;
1282   }
1283 
1284   if (parse_nrg(p_env, psz_nrg, CDIO_LOG_INFO)) {
1285     is_nrg = true;
1286 #ifdef ALSO_TEST_NAME
1287     size_t psz_len;
1288     psz_len = strlen(psz_nrg);
1289     /* At least 4 characters needed for .nrg extension */
1290     if ( psz_len < 4 ) {
1291       is_nrg = false;
1292       goto exit;
1293     }
1294 
1295     is_nrg = strncasecmp( psz_nrg+(psz_len-3), "nrg", 3 ) == 0;
1296 #endif
1297   }
1298  exit:
1299   _free_nrg(p_env);
1300   return is_nrg;
1301 }
1302 
1303 /*!
1304   Initialization routine. This is the only thing that doesn't
1305   get called via a function pointer. In fact *we* are the
1306   ones to set that up.
1307  */
1308 CdIo *
cdio_open_am_nrg(const char * psz_source_name,const char * psz_access_mode)1309 cdio_open_am_nrg (const char *psz_source_name, const char *psz_access_mode)
1310 {
1311   if (psz_access_mode != NULL && strcmp(psz_access_mode, "image"))
1312     cdio_warn ("there is only one access mode for nrg. Arg %s ignored",
1313 	       psz_access_mode);
1314   return cdio_open_nrg(psz_source_name);
1315 }
1316 
1317 
1318 CdIo *
cdio_open_nrg(const char * psz_source)1319 cdio_open_nrg (const char *psz_source)
1320 {
1321   CdIo *ret;
1322   _img_private_t *_data;
1323 
1324   cdio_funcs_t _funcs;
1325 
1326   memset( &_funcs, 0, sizeof(_funcs) );
1327 
1328   _funcs.eject_media           = _eject_media_nrg;
1329   _funcs.free                  = _free_nrg;
1330   _funcs.get_arg               = _get_arg_image;
1331   _funcs.get_cdtext            = _get_cdtext_image;
1332   _funcs.get_cdtext_raw        = NULL;
1333   _funcs.get_devices           = cdio_get_devices_nrg;
1334   _funcs.get_default_device    = cdio_get_default_device_nrg;
1335   _funcs.get_disc_last_lsn     = get_disc_last_lsn_nrg;
1336   _funcs.get_discmode          = _get_discmode_image;
1337   _funcs.get_drive_cap         = _get_drive_cap_image;
1338   _funcs.get_first_track_num   = _get_first_track_num_image;
1339   _funcs.get_hwinfo            = get_hwinfo_nrg;
1340   _funcs.get_media_changed     = get_media_changed_image;
1341   _funcs.get_mcn               = _get_mcn_image;
1342   _funcs.get_num_tracks        = _get_num_tracks_image;
1343   _funcs.get_track_channels    = get_track_channels_generic;
1344   _funcs.get_track_copy_permit = get_track_copy_permit_image;
1345   _funcs.get_track_format      = get_track_format_nrg;
1346   _funcs.get_track_green       = _get_track_green_nrg;
1347   _funcs.get_track_lba         = NULL; /* Will use generic routine via msf */
1348   _funcs.get_track_msf         = _get_track_msf_image;
1349   _funcs.get_track_preemphasis = get_track_preemphasis_generic;
1350   _funcs.get_track_pregap_lba  = get_track_pregap_lba_image;
1351   _funcs.get_track_isrc        = get_track_isrc_image;
1352   _funcs.lseek                 = _lseek_nrg;
1353   _funcs.read                  = _read_nrg;
1354   _funcs.read_audio_sectors    = _read_audio_sectors_nrg;
1355   _funcs.read_data_sectors     = read_data_sectors_image;
1356   _funcs.read_mode1_sector     = _read_mode1_sector_nrg;
1357   _funcs.read_mode1_sectors    = _read_mode1_sectors_nrg;
1358   _funcs.read_mode2_sector     = _read_mode2_sector_nrg;
1359   _funcs.read_mode2_sectors    = _read_mode2_sectors_nrg;
1360   _funcs.run_mmc_cmd           = NULL;
1361   _funcs.set_arg               = _set_arg_image;
1362 
1363   _data                   = calloc(1, sizeof (_img_private_t));
1364   _data->gen.init         = false;
1365 
1366   _data->gen.i_tracks     = 0;
1367   _data->mtyp             = 0;
1368   _data->dtyp             = DTYP_INVALID;
1369   _data->gen.i_first_track= 1;
1370   _data->is_dao           = false;
1371   _data->is_cues          = false; /* FIXME: remove is_cues. */
1372 
1373   ret = cdio_new ((void *)_data, &_funcs);
1374 
1375   if (ret == NULL) {
1376     free(_data);
1377     return NULL;
1378   }
1379 
1380   ret->driver_id = DRIVER_NRG;
1381   _set_arg_image(_data, "source", (NULL == psz_source)
1382 	       ? DEFAULT_CDIO_DEVICE: psz_source);
1383   _set_arg_image (_data, "access-mode", "Nero");
1384 
1385   _data->psz_cue_name   = strdup(_get_arg_image(_data, "source"));
1386 
1387   if (!cdio_is_nrg(_data->psz_cue_name)) {
1388     cdio_debug ("source name %s is not recognized as a NRG image",
1389 		_data->psz_cue_name);
1390     _free_nrg(_data);
1391     free(ret);
1392     return NULL;
1393   }
1394 
1395   if (_init_nrg(_data))
1396     return ret;
1397   else {
1398     _free_nrg(_data);
1399     free(ret);
1400     return NULL;
1401   }
1402 
1403 }
1404 
1405 bool
cdio_have_nrg(void)1406 cdio_have_nrg (void)
1407 {
1408   return true;
1409 }
1410