Coverage Report

Created: 2024-06-17 06:31

/src/libsndfile/src/sd2.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** Copyright (C) 2001-2020 Erik de Castro Lopo <erikd@mega-nerd.com>
3
** Copyright (C) 2004 Paavo Jumppanen
4
**
5
** This program is free software; you can redistribute it and/or modify
6
** it under the terms of the GNU Lesser General Public License as published by
7
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14
**
15
** You should have received a copy of the GNU Lesser General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
*/
19
20
/*
21
** The sd2 support implemented in this file was partially sponsored
22
** (financially) by Paavo Jumppanen.
23
*/
24
25
/*
26
** Documentation on the Mac resource fork was obtained here :
27
** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
28
*/
29
30
#include  "sfconfig.h"
31
32
#include  <stdio.h>
33
#include  <stdlib.h>
34
#include  <string.h>
35
#include  <ctype.h>
36
37
#include  "sndfile.h"
38
#include  "sfendian.h"
39
#include  "common.h"
40
41
/*------------------------------------------------------------------------------
42
 * Markers.
43
*/
44
45
#define Sd2f_MARKER     MAKE_MARKER ('S', 'd', '2', 'f')
46
#define Sd2a_MARKER     MAKE_MARKER ('S', 'd', '2', 'a')
47
#define ALCH_MARKER     MAKE_MARKER ('A', 'L', 'C', 'H')
48
#define lsf1_MARKER     MAKE_MARKER ('l', 's', 'f', '1')
49
50
0
#define STR_MARKER      MAKE_MARKER ('S', 'T', 'R', ' ')
51
#define sdML_MARKER     MAKE_MARKER ('s', 'd', 'M', 'L')
52
53
enum
54
{ RSRC_STR = 111,
55
  RSRC_BIN
56
} ;
57
58
typedef struct
59
{ unsigned char * rsrc_data ;
60
  int rsrc_len ;
61
  int need_to_free_rsrc_data ;
62
63
  int data_offset, data_length ;
64
  int map_offset, map_length ;
65
66
  int type_count, type_offset ;
67
  int item_offset ;
68
69
  int str_index, str_count ;
70
71
  int string_offset ;
72
73
  /* All the above just to get these three. */
74
  int sample_size, sample_rate, channels ;
75
} SD2_RSRC ;
76
77
typedef struct
78
{ int type ;
79
  int id ;
80
  char name [32] ;
81
  char value [32] ;
82
  int value_len ;
83
} STR_RSRC ;
84
85
/*------------------------------------------------------------------------------
86
 * Private static functions.
87
*/
88
89
static int sd2_close  (SF_PRIVATE *psf) ;
90
91
static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ;
92
static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ;
93
94
static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ;
95
96
/*------------------------------------------------------------------------------
97
** Public functions.
98
*/
99
100
int
101
sd2_open (SF_PRIVATE *psf)
102
0
{ int subformat, error = 0, valid ;
103
104
  /* SD2 is always big endian. */
105
0
  psf->endian = SF_ENDIAN_BIG ;
106
107
0
  if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->rsrclength > 0))
108
0
  { psf_use_rsrc (psf, SF_TRUE) ;
109
0
    valid = psf_file_valid (psf) ;
110
0
    psf_use_rsrc (psf, SF_FALSE) ;
111
0
    if (! valid)
112
0
    { psf_log_printf (psf, "sd2_open : psf->rsrc.filedes < 0\n") ;
113
0
      return SFE_SD2_BAD_RSRC ;
114
0
      } ;
115
116
0
    error = sd2_parse_rsrc_fork (psf) ;
117
118
0
    if (error)
119
0
      goto error_cleanup ;
120
0
    } ;
121
122
0
  if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SD2)
123
0
  { error = SFE_BAD_OPEN_FORMAT ;
124
0
    goto error_cleanup ;
125
0
    } ;
126
127
0
  subformat = SF_CODEC (psf->sf.format) ;
128
0
  psf->dataoffset = 0 ;
129
130
  /* Only open and write the resource in RDWR mode is its current length is zero. */
131
0
  if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->rsrclength == 0))
132
0
  { psf->rsrc.mode = psf->file.mode ;
133
0
    psf_open_rsrc (psf) ;
134
135
0
    error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
136
137
0
    if (error)
138
0
      goto error_cleanup ;
139
140
    /* Not needed. */
141
0
    psf->write_header = NULL ;
142
0
    } ;
143
144
0
  psf->container_close = sd2_close ;
145
146
0
  psf->blockwidth = psf->bytewidth * psf->sf.channels ;
147
148
0
  switch (subformat)
149
0
  { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
150
0
    case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
151
0
    case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
152
0
    case SF_FORMAT_PCM_32 : /* 32-bit linear PCM */
153
0
        error = pcm_init (psf) ;
154
0
        break ;
155
156
0
    default :
157
0
        error = SFE_UNIMPLEMENTED ;
158
0
        break ;
159
0
    } ;
160
161
0
  psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
162
163
0
error_cleanup:
164
165
  /* Close the resource fork regardless. We won't need it again. */
166
0
  psf_close_rsrc (psf) ;
167
168
0
  return error ;
169
0
} /* sd2_open */
170
171
/*------------------------------------------------------------------------------
172
*/
173
174
static int
175
sd2_close (SF_PRIVATE *psf)
176
0
{
177
0
  if (psf->file.mode == SFM_WRITE)
178
0
  { /*  Now we know for certain the audio_length of the file we can re-write
179
    **  correct values for the FORM, 8SVX and BODY chunks.
180
    */
181
182
0
    } ;
183
184
0
  return 0 ;
185
0
} /* sd2_close */
186
187
/*------------------------------------------------------------------------------
188
*/
189
190
static int
191
sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
192
0
{ SD2_RSRC rsrc ;
193
0
  STR_RSRC str_rsrc [] =
194
0
  { { RSRC_STR, 1000, "_sample-size", "", 0 },
195
0
    { RSRC_STR, 1001, "_sample-rate", "", 0 },
196
0
    { RSRC_STR, 1002, "_channels", "", 0 },
197
0
    { RSRC_BIN, 1000, "_Markers", "", 8 }
198
0
    } ;
199
200
0
  int k, str_offset, data_offset, next_str ;
201
202
0
  psf_use_rsrc (psf, SF_TRUE) ;
203
204
0
  memset (&rsrc, 0, sizeof (rsrc)) ;
205
206
0
  rsrc.sample_rate = psf->sf.samplerate ;
207
0
  rsrc.sample_size = psf->bytewidth ;
208
0
  rsrc.channels = psf->sf.channels ;
209
210
0
  rsrc.rsrc_data = psf->header.ptr ;
211
0
  rsrc.rsrc_len = psf->header.len ;
212
0
  memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ;
213
214
0
  snprintf (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ;
215
0
  snprintf (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ;
216
0
  snprintf (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ;
217
218
0
  for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
219
0
  { if (str_rsrc [k].value_len == 0)
220
0
    { str_rsrc [k].value_len = strlen (str_rsrc [k].value) ;
221
0
      str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ;
222
0
      } ;
223
224
    /* Turn name string into a pascal string. */
225
0
    str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ;
226
0
    } ;
227
228
0
  rsrc.data_offset = 0x100 ;
229
230
  /*
231
  ** Calculate data length :
232
  **    length of strings, plus the length of the sdML chunk.
233
  */
234
0
  rsrc.data_length = 0 ;
235
0
  for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
236
0
    rsrc.data_length += str_rsrc [k].value_len + 4 ;
237
238
0
  rsrc.map_offset = rsrc.data_offset + rsrc.data_length ;
239
240
  /* Very start of resource fork. */
241
0
  psf_binheader_writef (psf, "E444", BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ;
242
243
0
  psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name)) ;
244
0
  psf_binheader_writef (psf, "Eo2mm", BHWo (0x50), BHW2 (0), BHWm (Sd2f_MARKER), BHWm (lsf1_MARKER)) ;
245
246
  /* Very start of resource map. */
247
0
  psf_binheader_writef (psf, "E4444", BHW4 (rsrc.map_offset), BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ;
248
249
  /* These I don't currently understand. */
250
0
  if (1)
251
0
  { psf_binheader_writef (psf, "Eo1422", BHWo (rsrc.map_offset + 16), BHW1 (1), BHW4 (0x12345678), BHW2 (0xabcd), BHW2 (0)) ;
252
0
    } ;
253
254
  /* Resource type offset. */
255
0
  rsrc.type_offset = rsrc.map_offset + 30 ;
256
0
  psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 24), BHW2 (rsrc.type_offset - rsrc.map_offset - 2)) ;
257
258
  /* Type index max. */
259
0
  rsrc.type_count = 2 ;
260
0
  psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 28), BHW2 (rsrc.type_count - 1)) ;
261
262
0
  rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
263
264
0
  rsrc.str_count = ARRAY_LEN (str_rsrc) ;
265
0
  rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ;
266
0
  psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 26), BHW2 (rsrc.string_offset)) ;
267
268
  /* Write 'STR ' resource type. */
269
0
  rsrc.str_count = 3 ;
270
0
  psf_binheader_writef (psf, "Eom22", BHWo (rsrc.type_offset), BHWm (STR_MARKER), BHW2 (rsrc.str_count - 1), BHW2 (0x12)) ;
271
272
  /* Write 'sdML' resource type. */
273
0
  psf_binheader_writef (psf, "Em22", BHWm (sdML_MARKER), BHW2 (0), BHW2 (0x36)) ;
274
275
0
  str_offset = rsrc.map_offset + rsrc.string_offset ;
276
0
  next_str = 0 ;
277
0
  data_offset = rsrc.data_offset ;
278
0
  for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
279
0
  { psf_binheader_writef (psf, "Eop", BHWo (str_offset), BHWp (str_rsrc [k].name)) ;
280
0
    psf_binheader_writef (psf, "Eo22", BHWo (rsrc.item_offset + k * 12), BHW2 (str_rsrc [k].id), BHW2 (next_str)) ;
281
282
0
    str_offset += strlen (str_rsrc [k].name) ;
283
0
    next_str += strlen (str_rsrc [k].name) ;
284
285
0
    psf_binheader_writef (psf, "Eo4", BHWo (rsrc.item_offset + k * 12 + 4), BHW4 (data_offset - rsrc.data_offset)) ;
286
0
    psf_binheader_writef (psf, "Eo4", BHWo (data_offset), BHW4 (str_rsrc [k].value_len)) ;
287
288
0
    psf_binheader_writef (psf, "Eob", BHWo (data_offset + 4), BHWv (str_rsrc [k].value), BHWz (str_rsrc [k].value_len)) ;
289
0
    data_offset += 4 + str_rsrc [k].value_len ;
290
0
    } ;
291
292
  /* Finally, calculate and set map length. */
293
0
  rsrc.map_length = str_offset - rsrc.map_offset ;
294
0
  psf_binheader_writef (psf, "Eo4o4", BHWo (12), BHW4 (rsrc.map_length),
295
0
              BHWo (rsrc.map_offset + 12), BHW4 (rsrc.map_length)) ;
296
297
0
  psf->header.indx = rsrc.map_offset + rsrc.map_length ;
298
299
0
  psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
300
301
0
  psf_use_rsrc (psf, SF_FALSE) ;
302
303
0
  if (psf->error)
304
0
    return psf->error ;
305
306
0
  return 0 ;
307
0
} /* sd2_write_rsrc_fork */
308
309
/*------------------------------------------------------------------------------
310
*/
311
312
static inline int
313
read_rsrc_char (const SD2_RSRC *prsrc, int offset)
314
0
{ const unsigned char * data = prsrc->rsrc_data ;
315
0
  if (offset < 0 || offset >= prsrc->rsrc_len)
316
0
    return 0 ;
317
0
  return data [offset] ;
318
0
} /* read_rsrc_char */
319
320
static inline int
321
read_rsrc_short (const SD2_RSRC *prsrc, int offset)
322
0
{ const unsigned char * data = prsrc->rsrc_data ;
323
0
  if (offset < 0 || offset + 1 >= prsrc->rsrc_len)
324
0
    return 0 ;
325
0
  return (data [offset] << 8) + data [offset + 1] ;
326
0
} /* read_rsrc_short */
327
328
static inline int
329
read_rsrc_int (const SD2_RSRC *prsrc, int offset)
330
0
{ const unsigned char * data = prsrc->rsrc_data ;
331
0
  if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
332
0
    return 0 ;
333
0
  return (((uint32_t) data [offset]) << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
334
0
} /* read_rsrc_int */
335
336
static inline int
337
read_rsrc_marker (const SD2_RSRC *prsrc, int offset)
338
0
{ const unsigned char * data = prsrc->rsrc_data ;
339
340
0
  if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
341
0
    return 0 ;
342
343
0
  if (CPU_IS_BIG_ENDIAN)
344
0
    return (((uint32_t) data [offset]) << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
345
0
  if (CPU_IS_LITTLE_ENDIAN)
346
0
    return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (((uint32_t) data [offset + 3]) << 24) ;
347
348
0
  return 0 ;
349
0
} /* read_rsrc_marker */
350
351
static void
352
read_rsrc_str (const SD2_RSRC *prsrc, int offset, char * buffer, int buffer_len)
353
0
{ const unsigned char * data = prsrc->rsrc_data ;
354
0
  int k ;
355
356
0
  memset (buffer, 0, buffer_len) ;
357
358
0
  if (offset < 0 || offset + buffer_len >= prsrc->rsrc_len)
359
0
    return ;
360
361
0
  for (k = 0 ; k < buffer_len - 1 ; k++)
362
0
  { if (psf_isprint (data [offset + k]) == 0)
363
0
      return ;
364
0
    buffer [k] = data [offset + k] ;
365
0
    } ;
366
0
  return ;
367
0
} /* read_rsrc_str */
368
369
static int
370
sd2_parse_rsrc_fork (SF_PRIVATE *psf)
371
0
{ SD2_RSRC rsrc ;
372
0
  int k, marker, error = 0 ;
373
374
0
  psf_use_rsrc (psf, SF_TRUE) ;
375
376
0
  memset (&rsrc, 0, sizeof (rsrc)) ;
377
378
0
  rsrc.rsrc_len = psf_get_filelen (psf) ;
379
0
  psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ;
380
381
0
  if (rsrc.rsrc_len > psf->header.len)
382
0
  { rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ;
383
0
    rsrc.need_to_free_rsrc_data = SF_TRUE ;
384
0
    }
385
0
  else
386
0
  {
387
0
    rsrc.rsrc_data = psf->header.ptr ;
388
    // rsrc.rsrc_len > psf->header.len ;
389
0
    rsrc.need_to_free_rsrc_data = SF_FALSE ;
390
0
    } ;
391
392
  /* Read in the whole lot. */
393
0
  psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
394
395
  /* Reset the header storage because we have changed to the rsrcdes. */
396
0
  psf->header.indx = psf->header.end = rsrc.rsrc_len ;
397
398
0
  rsrc.data_offset = read_rsrc_int (&rsrc, 0) ;
399
0
  rsrc.map_offset = read_rsrc_int (&rsrc, 4) ;
400
0
  rsrc.data_length = read_rsrc_int (&rsrc, 8) ;
401
0
  rsrc.map_length = read_rsrc_int (&rsrc, 12) ;
402
403
0
  if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000)
404
0
  { psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ;
405
0
    rsrc.data_offset = read_rsrc_int (&rsrc, 0x52 + 0) + 0x52 ;
406
0
    rsrc.map_offset = read_rsrc_int (&rsrc, 0x52 + 4) + 0x52 ;
407
0
    rsrc.data_length = read_rsrc_int (&rsrc, 0x52 + 8) ;
408
0
    rsrc.map_length = read_rsrc_int (&rsrc, 0x52 + 12) ;
409
0
    } ;
410
411
0
  psf_log_printf (psf, "  data offset : 0x%04X\n  map  offset : 0x%04X\n"
412
0
        "  data length : 0x%04X\n  map  length : 0x%04X\n",
413
0
        rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ;
414
415
0
  if (rsrc.data_offset > rsrc.rsrc_len)
416
0
  { psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ;
417
0
    error = SFE_SD2_BAD_DATA_OFFSET ;
418
0
    goto parse_rsrc_fork_cleanup ;
419
0
    } ;
420
421
0
  if (rsrc.map_offset > rsrc.rsrc_len)
422
0
  { psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ;
423
0
    error = SFE_SD2_BAD_MAP_OFFSET ;
424
0
    goto parse_rsrc_fork_cleanup ;
425
0
    } ;
426
427
0
  if (rsrc.data_length > rsrc.rsrc_len)
428
0
  { psf_log_printf (psf, "Error : rsrc.data_length > len\n") ;
429
0
    error = SFE_SD2_BAD_DATA_LENGTH ;
430
0
    goto parse_rsrc_fork_cleanup ;
431
0
    } ;
432
433
0
  if (rsrc.map_length > rsrc.rsrc_len)
434
0
  { psf_log_printf (psf, "Error : rsrc.map_length > len\n") ;
435
0
    error = SFE_SD2_BAD_MAP_LENGTH ;
436
0
    goto parse_rsrc_fork_cleanup ;
437
0
    } ;
438
439
0
  if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len)
440
0
  { psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ;
441
0
    error = SFE_SD2_BAD_RSRC ;
442
0
    goto parse_rsrc_fork_cleanup ;
443
0
    } ;
444
445
0
  if (rsrc.map_offset + 28 >= rsrc.rsrc_len)
446
0
  { psf_log_printf (psf, "Bad map offset (%d + 28 > %d).\n", rsrc.map_offset, rsrc.rsrc_len) ;
447
0
    error = SFE_SD2_BAD_RSRC ;
448
0
    goto parse_rsrc_fork_cleanup ;
449
0
    } ;
450
451
0
  rsrc.string_offset = rsrc.map_offset + read_rsrc_short (&rsrc, rsrc.map_offset + 26) ;
452
0
  if (rsrc.string_offset > rsrc.rsrc_len)
453
0
  { psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ;
454
0
    error = SFE_SD2_BAD_RSRC ;
455
0
    goto parse_rsrc_fork_cleanup ;
456
0
    } ;
457
458
0
  rsrc.type_offset = rsrc.map_offset + 30 ;
459
460
0
  if (rsrc.map_offset + 28 > rsrc.rsrc_len)
461
0
  { psf_log_printf (psf, "Bad map offset.\n") ;
462
0
    goto parse_rsrc_fork_cleanup ;
463
0
    } ;
464
465
0
  rsrc.type_count = read_rsrc_short (&rsrc, rsrc.map_offset + 28) + 1 ;
466
0
  if (rsrc.type_count < 1)
467
0
  { psf_log_printf (psf, "Bad type count.\n") ;
468
0
    error = SFE_SD2_BAD_RSRC ;
469
0
    goto parse_rsrc_fork_cleanup ;
470
0
    } ;
471
472
0
  rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
473
0
  if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len)
474
0
  { psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ;
475
0
    error = SFE_SD2_BAD_RSRC ;
476
0
    goto parse_rsrc_fork_cleanup ;
477
0
    } ;
478
479
0
  rsrc.str_index = -1 ;
480
0
  for (k = 0 ; k < rsrc.type_count ; k ++)
481
0
  { if (rsrc.type_offset + k * 8 > rsrc.rsrc_len)
482
0
    { psf_log_printf (psf, "Bad rsrc marker.\n") ;
483
0
      goto parse_rsrc_fork_cleanup ;
484
0
      } ;
485
486
0
    marker = read_rsrc_marker (&rsrc, rsrc.type_offset + k * 8) ;
487
488
0
    if (marker == STR_MARKER)
489
0
    { rsrc.str_index = k ;
490
0
      rsrc.str_count = read_rsrc_short (&rsrc, rsrc.type_offset + k * 8 + 4) + 1 ;
491
0
      error = parse_str_rsrc (psf, &rsrc) ;
492
0
      goto parse_rsrc_fork_cleanup ;
493
0
      } ;
494
0
    } ;
495
496
0
  psf_log_printf (psf, "No 'STR ' resource.\n") ;
497
0
  error = SFE_SD2_BAD_RSRC ;
498
499
0
parse_rsrc_fork_cleanup :
500
501
0
  psf_use_rsrc (psf, SF_FALSE) ;
502
503
0
  if (rsrc.need_to_free_rsrc_data)
504
0
    free (rsrc.rsrc_data) ;
505
506
0
  return error ;
507
0
} /* sd2_parse_rsrc_fork */
508
509
static int
510
parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
511
0
{ char name [32], value [32] ;
512
0
  int k, str_offset, rsrc_id, data_offset = 0, data_len = 0 ;
513
514
0
  psf_log_printf (psf, "Finding parameters :\n") ;
515
516
0
  str_offset = rsrc->string_offset ;
517
0
  psf_log_printf (psf, "  Offset    RsrcId    dlen    slen    Value\n") ;
518
519
520
0
  for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++)
521
0
  { int slen ;
522
523
0
    slen = read_rsrc_char (rsrc, str_offset) ;
524
0
    read_rsrc_str (rsrc, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
525
0
    str_offset += slen + 1 ;
526
527
    // work-around for GitHub issue #340
528
0
    int id_offset = rsrc->item_offset + k * 12 ;
529
0
    if (id_offset < 0 || id_offset + 1 >= rsrc->rsrc_len)
530
0
    { psf_log_printf (psf, "Exiting parser on id_offset of %d.\n", id_offset) ;
531
0
      break ;
532
0
      }
533
0
    rsrc_id = read_rsrc_short (rsrc, id_offset) ;
534
535
0
    data_offset = rsrc->data_offset + read_rsrc_int (rsrc, rsrc->item_offset + k * 12 + 4) ;
536
0
    if (data_offset < 0 || data_offset > rsrc->rsrc_len)
537
0
    { psf_log_printf (psf, "Exiting parser on data offset of %d.\n", data_offset) ;
538
0
      break ;
539
0
      } ;
540
541
0
    data_len = read_rsrc_int (rsrc, data_offset) ;
542
0
    if (data_len < 0 || data_len > rsrc->rsrc_len)
543
0
    { psf_log_printf (psf, "Exiting parser on data length of %d.\n", data_len) ;
544
0
      break ;
545
0
      } ;
546
547
0
    slen = read_rsrc_char (rsrc, data_offset + 4) ;
548
0
    read_rsrc_str (rsrc, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
549
550
0
    psf_log_printf (psf, "  0x%04x     %4d     %4d     %3d    '%s'\n", data_offset, rsrc_id, data_len, slen, value) ;
551
552
0
    if (strstr (value, "Photoshop"))
553
0
    { psf_log_printf (psf, "Exiting parser on Photoshop data.\n", data_offset) ;
554
0
      break ;
555
0
      } ;
556
557
0
    if (rsrc_id == 1000 && rsrc->sample_size == 0)
558
0
      rsrc->sample_size = strtol (value, NULL, 10) ;
559
0
    else if (rsrc_id == 1001 && rsrc->sample_rate == 0)
560
0
      rsrc->sample_rate = strtol (value, NULL, 10) ;
561
0
    else if (rsrc_id == 1002 && rsrc->channels == 0)
562
0
      rsrc->channels = strtol (value, NULL, 10) ;
563
0
    } ;
564
565
0
  psf_log_printf (psf, "Found Parameters :\n") ;
566
0
  psf_log_printf (psf, "  sample-size : %d\n", rsrc->sample_size) ;
567
0
  psf_log_printf (psf, "  sample-rate : %d\n", rsrc->sample_rate) ;
568
0
  psf_log_printf (psf, "  channels    : %d\n", rsrc->channels) ;
569
570
0
  if (rsrc->sample_rate <= 4 && rsrc->sample_size > 4)
571
0
  { int temp ;
572
573
0
    psf_log_printf (psf, "Geez!! Looks like sample rate and sample size got switched.\nCorrecting this screw up.\n") ;
574
0
    temp = rsrc->sample_rate ;
575
0
    rsrc->sample_rate = rsrc->sample_size ;
576
0
    rsrc->sample_size = temp ;
577
0
    } ;
578
579
0
  if (rsrc->sample_rate < 0)
580
0
  { psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ;
581
0
    return SFE_SD2_BAD_RSRC ;
582
0
    } ;
583
584
0
  if (rsrc->channels < 0)
585
0
  { psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ;
586
0
    return SFE_SD2_BAD_RSRC ;
587
0
    } ;
588
589
0
  psf->sf.samplerate = rsrc->sample_rate ;
590
0
  psf->sf.channels = rsrc->channels ;
591
0
  psf->bytewidth = rsrc->sample_size ;
592
593
0
  switch (rsrc->sample_size)
594
0
  { case 1 :
595
0
      psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ;
596
0
      break ;
597
598
0
    case 2 :
599
0
      psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ;
600
0
      break ;
601
602
0
    case 3 :
603
0
      psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ;
604
0
      break ;
605
606
0
    case 4 :
607
0
      psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_32 ;
608
0
      break ;
609
610
0
    default :
611
0
      psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ;
612
0
      return SFE_SD2_BAD_SAMPLE_SIZE ;
613
0
    } ;
614
615
0
  psf_log_printf (psf, "ok\n") ;
616
617
0
  return 0 ;
618
0
} /* parse_str_rsrc */
619