1 : /******************************************************************************
2 : * $Id: nitfdes.c 24916 2012-09-05 21:30:41Z hobu $
3 : *
4 : * Project: NITF Read/Write Library
5 : * Purpose: Module responsible for implementation of DE segments.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : **********************************************************************
9 : * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal.h"
31 : #include "nitflib.h"
32 : #include "cpl_vsi.h"
33 : #include "cpl_conv.h"
34 : #include "cpl_string.h"
35 :
36 : CPL_CVSID("$Id: nitfdes.c 24916 2012-09-05 21:30:41Z hobu $");
37 :
38 : /************************************************************************/
39 : /* NITFDESAccess() */
40 : /************************************************************************/
41 :
42 2 : NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )
43 :
44 : {
45 : NITFDES *psDES;
46 : char *pachHeader;
47 : NITFSegmentInfo *psSegInfo;
48 : char szDESID[26];
49 : int nOffset;
50 : int bHasDESOFLW;
51 : int nDESSHL;
52 :
53 : /* -------------------------------------------------------------------- */
54 : /* Verify segment, and return existing DES accessor if there */
55 : /* is one. */
56 : /* -------------------------------------------------------------------- */
57 2 : if( iSegment < 0 || iSegment >= psFile->nSegmentCount )
58 0 : return NULL;
59 :
60 2 : psSegInfo = psFile->pasSegmentInfo + iSegment;
61 :
62 2 : if( !EQUAL(psSegInfo->szSegmentType,"DE") )
63 0 : return NULL;
64 :
65 2 : if( psSegInfo->hAccess != NULL )
66 0 : return (NITFDES *) psSegInfo->hAccess;
67 :
68 : /* -------------------------------------------------------------------- */
69 : /* Read the DES subheader. */
70 : /* -------------------------------------------------------------------- */
71 2 : if (psSegInfo->nSegmentHeaderSize < 200)
72 : {
73 0 : CPLError(CE_Failure, CPLE_AppDefined,
74 : "DES header too small");
75 0 : return NULL;
76 : }
77 :
78 2 : pachHeader = (char*) VSIMalloc(psSegInfo->nSegmentHeaderSize);
79 2 : if (pachHeader == NULL)
80 : {
81 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
82 : "Cannot allocate memory for segment header");
83 0 : return NULL;
84 : }
85 :
86 : retry:
87 4 : if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
88 : SEEK_SET ) != 0
89 4 : || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize,
90 4 : psFile->fp ) != psSegInfo->nSegmentHeaderSize )
91 : {
92 0 : CPLError( CE_Failure, CPLE_FileIO,
93 : "Failed to read %u byte DES subheader from " CPL_FRMT_GUIB ".",
94 : psSegInfo->nSegmentHeaderSize,
95 : psSegInfo->nSegmentHeaderStart );
96 0 : CPLFree(pachHeader);
97 0 : return NULL;
98 : }
99 :
100 2 : if (!EQUALN(pachHeader, "DE", 2))
101 : {
102 0 : if (EQUALN(pachHeader + 4, "DERegistered", 12))
103 : {
104 : /* BAO_46_Ed1/rpf/conc/concz10/000fz010.ona and cie are buggy */
105 0 : CPLDebug("NITF", "Patching nSegmentHeaderStart and nSegmentStart for DE segment %d", iSegment);
106 0 : psSegInfo->nSegmentHeaderStart += 4;
107 0 : psSegInfo->nSegmentStart += 4;
108 0 : goto retry;
109 : }
110 :
111 0 : CPLError(CE_Failure, CPLE_AppDefined,
112 : "Invalid segment prefix for DE segment %d", iSegment);
113 :
114 0 : CPLFree(pachHeader);
115 0 : return NULL;
116 : }
117 :
118 : /* -------------------------------------------------------------------- */
119 : /* Initialize DES object. */
120 : /* -------------------------------------------------------------------- */
121 2 : psDES = (NITFDES *) CPLCalloc(sizeof(NITFDES),1);
122 :
123 2 : psDES->psFile = psFile;
124 2 : psDES->iSegment = iSegment;
125 2 : psDES->pachHeader = pachHeader;
126 :
127 2 : psSegInfo->hAccess = psDES;
128 :
129 : /* -------------------------------------------------------------------- */
130 : /* Collect a variety of information as metadata. */
131 : /* -------------------------------------------------------------------- */
132 : #define GetMD( length, name ) \
133 : do { NITFExtractMetadata( &(psDES->papszMetadata), pachHeader, \
134 : nOffset, length, \
135 : "NITF_" #name ); \
136 : nOffset += length; } while(0)
137 :
138 2 : nOffset = 2;
139 2 : GetMD( 25, DESID );
140 2 : GetMD( 2, DESVER );
141 2 : GetMD( 1, DECLAS );
142 2 : GetMD( 2, DESCLSY );
143 2 : GetMD( 11, DESCODE );
144 2 : GetMD( 2, DESCTLH );
145 2 : GetMD( 20, DESREL );
146 2 : GetMD( 2, DESDCTP );
147 2 : GetMD( 8, DESDCDT );
148 2 : GetMD( 4, DESDCXM );
149 2 : GetMD( 1, DESDG );
150 2 : GetMD( 8, DESDGDT );
151 2 : GetMD( 43, DESCLTX );
152 2 : GetMD( 1, DESCATP );
153 2 : GetMD( 40, DESCAUT );
154 2 : GetMD( 1, DESCRSN );
155 2 : GetMD( 8, DESSRDT );
156 2 : GetMD( 15, DESCTLN );
157 :
158 : /* Load DESID */
159 2 : NITFGetField( szDESID, pachHeader, 2, 25);
160 :
161 : /* For NITF < 02.10, we cannot rely on DESID=TRE_OVERFLOW to detect */
162 : /* if DESOFLW and DESITEM are present. So if the next 4 bytes are non */
163 : /* numeric, we'll assume that DESOFLW is there */
164 10 : bHasDESOFLW = EQUALN(szDESID, "TRE_OVERFLOW", strlen("TRE_OVERFLOW")) ||
165 2 : (!((pachHeader[nOffset+0] >= '0' && pachHeader[nOffset+0] <= '9') &&
166 2 : (pachHeader[nOffset+1] >= '0' && pachHeader[nOffset+1] <= '9') &&
167 2 : (pachHeader[nOffset+2] >= '0' && pachHeader[nOffset+2] <= '9') &&
168 2 : (pachHeader[nOffset+3] >= '0' && pachHeader[nOffset+3] <= '9')));
169 :
170 2 : if (bHasDESOFLW)
171 : {
172 1 : if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 6 + 3 )
173 : {
174 0 : CPLError(CE_Failure, CPLE_AppDefined,
175 : "DES header too small");
176 0 : NITFDESDeaccess(psDES);
177 0 : return NULL;
178 : }
179 1 : GetMD( 6, DESOFLW );
180 1 : GetMD( 3, DESITEM );
181 : }
182 :
183 2 : if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 4 )
184 : {
185 0 : CPLError(CE_Failure, CPLE_AppDefined,
186 : "DES header too small");
187 0 : NITFDESDeaccess(psDES);
188 0 : return NULL;
189 : }
190 :
191 2 : GetMD( 4, DESSHL );
192 2 : nDESSHL = atoi(CSLFetchNameValue( psDES->papszMetadata, "NITF_DESSHL" ) );
193 :
194 2 : if (nDESSHL < 0)
195 : {
196 0 : CPLError(CE_Failure, CPLE_AppDefined,
197 : "Invalid value for DESSHL");
198 0 : NITFDESDeaccess(psDES);
199 0 : return NULL;
200 : }
201 2 : if ( (int)psSegInfo->nSegmentHeaderSize < nOffset + nDESSHL)
202 : {
203 0 : CPLError(CE_Failure, CPLE_AppDefined,
204 : "DES header too small");
205 0 : NITFDESDeaccess(psDES);
206 0 : return NULL;
207 : }
208 :
209 2 : if (EQUALN(szDESID, "CSSHPA DES", strlen("CSSHPA DES")))
210 : {
211 0 : if ( nDESSHL != 62 && nDESSHL != 80)
212 : {
213 0 : CPLError(CE_Failure, CPLE_AppDefined,
214 : "Invalid DESSHL for CSSHPA DES");
215 0 : NITFDESDeaccess(psDES);
216 0 : return NULL;
217 : }
218 :
219 0 : GetMD( 25, SHAPE_USE );
220 0 : GetMD( 10, SHAPE_CLASS );
221 0 : if (nDESSHL == 80)
222 0 : GetMD( 18, CC_SOURCE );
223 0 : GetMD( 3, SHAPE1_NAME );
224 0 : GetMD( 6, SHAPE1_START );
225 0 : GetMD( 3, SHAPE2_NAME );
226 0 : GetMD( 6, SHAPE2_START );
227 0 : GetMD( 3, SHAPE3_NAME );
228 0 : GetMD( 6, SHAPE3_START );
229 : }
230 2 : else if (EQUALN(szDESID, "XML_DATA_CONTENT", strlen("XML_DATA_CONTENT")))
231 : {
232 : /* TODO : handle nDESSHL = 0005 and 0283 */
233 1 : if (nDESSHL >= 5)
234 : {
235 1 : GetMD( 5, DESCRC );
236 1 : if (nDESSHL >= 283)
237 : {
238 1 : GetMD( 8, DESSHFT );
239 1 : GetMD( 20, DESSHDT );
240 1 : GetMD( 40, DESSHRP );
241 1 : GetMD( 60, DESSHSI );
242 1 : GetMD( 10, DESSHSV );
243 1 : GetMD( 20, DESSHSD );
244 1 : GetMD( 120, DESSHTN );
245 1 : if (nDESSHL >= 773)
246 : {
247 1 : GetMD( 125, DESSHLPG );
248 1 : GetMD( 25, DESSHLPT );
249 1 : GetMD( 20, DESSHLI );
250 1 : GetMD( 120, DESSHLIN );
251 1 : GetMD( 200, DESSHABS );
252 : }
253 : }
254 : }
255 : }
256 1 : else if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")) && nDESSHL == 52)
257 : {
258 0 : GetMD( 12, ATT_TYPE );
259 0 : GetMD( 14, DT_ATT );
260 0 : GetMD( 8, DATE_ATT );
261 0 : GetMD( 13, T0_ATT );
262 0 : GetMD( 5, NUM_ATT );
263 : }
264 1 : else if (nDESSHL > 0)
265 0 : GetMD( nDESSHL, DESSHF );
266 :
267 2 : if ((int)psSegInfo->nSegmentHeaderSize > nOffset)
268 : {
269 : char* pszEscapedDESDATA =
270 0 : CPLEscapeString( pachHeader + nOffset,
271 : (int)psSegInfo->nSegmentHeaderSize - nOffset,
272 0 : CPLES_BackslashQuotable );
273 0 : psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
274 : "NITF_DESDATA",
275 : pszEscapedDESDATA );
276 0 : CPLFree(pszEscapedDESDATA);
277 : }
278 : else
279 : {
280 :
281 : #define TEN_MEGABYTES 10485760
282 :
283 2 : if (psSegInfo->nSegmentSize > TEN_MEGABYTES)
284 : {
285 0 : const char* pszOffset = CPLSPrintf(CPL_FRMT_GUIB, psFile->pasSegmentInfo[iSegment].nSegmentStart);
286 0 : const char* pszSize = CPLSPrintf(CPL_FRMT_GUIB, psFile->pasSegmentInfo[iSegment].nSegmentSize);
287 :
288 0 : psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
289 : "NITF_DESDATA_OFFSET",
290 : pszOffset );
291 0 : psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
292 : "NITF_DESDATA_LENGTH",
293 : pszSize);
294 :
295 : }
296 : else
297 : {
298 2 : char* pachData = (char*)VSIMalloc((size_t)psSegInfo->nSegmentSize);
299 2 : if (pachData == NULL )
300 : {
301 0 : CPLDebug("NITF", "Cannot allocate " CPL_FRMT_GUIB " bytes DES data",
302 : psSegInfo->nSegmentSize);
303 : }
304 4 : else if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart,
305 : SEEK_SET ) != 0
306 2 : || VSIFReadL( pachData, 1, (size_t)psSegInfo->nSegmentSize,
307 2 : psFile->fp ) != psSegInfo->nSegmentSize )
308 : {
309 0 : CPLDebug("NITF",
310 : "Failed to read " CPL_FRMT_GUIB" bytes DES data from " CPL_FRMT_GUIB ".",
311 : psSegInfo->nSegmentSize,
312 : psSegInfo->nSegmentStart );
313 : }
314 : else
315 : {
316 : char* pszEscapedDESDATA =
317 2 : CPLEscapeString( pachData,
318 : (int)psSegInfo->nSegmentSize,
319 2 : CPLES_BackslashQuotable );
320 2 : psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
321 : "NITF_DESDATA",
322 : pszEscapedDESDATA );
323 2 : CPLFree(pszEscapedDESDATA);
324 :
325 : }
326 2 : CPLFree(pachData);
327 : }
328 :
329 : #ifdef notdef
330 : /* Disabled because might generate a huge amount of elements */
331 : if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")))
332 : {
333 : int nNumAtt = atoi(CSLFetchNameValueDef(psDES->papszMetadata, "NITF_NUM_ATT", "0"));
334 : if (nNumAtt * 8 * 4 == psSegInfo->nSegmentSize)
335 : {
336 : int nMDSize = CSLCount(psDES->papszMetadata);
337 : char** papszMD = (char**)VSIRealloc(psDES->papszMetadata, (nMDSize + nNumAtt * 4 + 1) * sizeof(char*));
338 : if (papszMD)
339 : {
340 : int i, j;
341 : const GByte* pachDataIter = pachData;
342 :
343 : psDES->papszMetadata = papszMD;
344 : for(i=0;i<nNumAtt;i++)
345 : {
346 : char szAttrNameValue[64+1+256+1];
347 : double dfVal;
348 : for(j=0;j<4;j++)
349 : {
350 : memcpy(&dfVal, pachDataIter, 8);
351 : CPL_MSBPTR64(&dfVal);
352 : pachDataIter += 8;
353 : sprintf(szAttrNameValue, "NITF_ATT_Q%d_%d=%.16g", j+1, i, dfVal);
354 : papszMD[nMDSize + i * 4 + j] = CPLStrdup(szAttrNameValue);
355 : }
356 : }
357 : papszMD[nMDSize + nNumAtt * 4] = NULL;
358 : }
359 : }
360 : }
361 : #endif
362 :
363 :
364 : }
365 :
366 2 : return psDES;
367 : }
368 :
369 : /************************************************************************/
370 : /* NITFDESDeaccess() */
371 : /************************************************************************/
372 :
373 2 : void NITFDESDeaccess( NITFDES *psDES )
374 :
375 : {
376 2 : CPLAssert( psDES->psFile->pasSegmentInfo[psDES->iSegment].hAccess
377 : == psDES );
378 :
379 2 : psDES->psFile->pasSegmentInfo[psDES->iSegment].hAccess = NULL;
380 :
381 2 : CPLFree( psDES->pachHeader );
382 2 : CSLDestroy( psDES->papszMetadata );
383 :
384 2 : CPLFree( psDES );
385 2 : }
386 :
387 : /************************************************************************/
388 : /* NITFDESGetTRE() */
389 : /************************************************************************/
390 :
391 : /**
392 : * Return the TRE located at nOffset.
393 : *
394 : * @param psDES descriptor of the DE segment
395 : * @param nOffset offset of the TRE relative to the beginning of the segment data
396 : * @param szTREName will be filled with the TRE name
397 : * @param ppabyTREData will be allocated by the function and filled with the TRE content (in raw form)
398 : * @param pnFoundTRESize will be filled with the TRE size (excluding the first 11 bytes)
399 : * @return TRUE if a TRE was found
400 : */
401 :
402 6 : int NITFDESGetTRE( NITFDES* psDES,
403 : int nOffset,
404 : char szTREName[7],
405 : char** ppabyTREData,
406 : int* pnFoundTRESize)
407 : {
408 : char szTREHeader[12];
409 : char szTRETempName[7];
410 : NITFSegmentInfo* psSegInfo;
411 : VSILFILE* fp;
412 : int nTRESize;
413 :
414 6 : memset(szTREName, '\0', 7);
415 6 : if (ppabyTREData)
416 6 : *ppabyTREData = NULL;
417 6 : if (pnFoundTRESize)
418 6 : *pnFoundTRESize = 0;
419 :
420 6 : if (nOffset < 0)
421 0 : return FALSE;
422 :
423 6 : if (psDES == NULL)
424 0 : return FALSE;
425 :
426 6 : if (CSLFetchNameValue(psDES->papszMetadata, "NITF_DESOFLW") == NULL)
427 1 : return FALSE;
428 :
429 5 : psSegInfo = psDES->psFile->pasSegmentInfo + psDES->iSegment;
430 5 : fp = psDES->psFile->fp;
431 :
432 5 : if (nOffset >= psSegInfo->nSegmentSize)
433 1 : return FALSE;
434 :
435 4 : VSIFSeekL(fp, psSegInfo->nSegmentStart + nOffset, SEEK_SET);
436 :
437 4 : if (VSIFReadL(szTREHeader, 1, 11, fp) != 11)
438 : {
439 : /* Some files have a nSegmentSize larger than what is is in reality */
440 : /* So exit silently if we're at end of file */
441 0 : VSIFSeekL(fp, 0, SEEK_END);
442 0 : if (VSIFTellL(fp) == psSegInfo->nSegmentStart + nOffset)
443 0 : return FALSE;
444 :
445 0 : CPLError(CE_Failure, CPLE_FileIO,
446 : "Cannot get 11 bytes at offset " CPL_FRMT_GUIB ".",
447 : psSegInfo->nSegmentStart + nOffset );
448 0 : return FALSE;
449 : }
450 4 : szTREHeader[11] = '\0';
451 :
452 4 : memcpy(szTRETempName, szTREHeader, 6);
453 4 : szTRETempName[6] = '\0';
454 :
455 4 : nTRESize = atoi(szTREHeader + 6);
456 4 : if (nTRESize < 0)
457 : {
458 0 : CPLError(CE_Failure, CPLE_AppDefined,
459 : "Invalid size (%d) for TRE %s",
460 : nTRESize, szTRETempName);
461 0 : return FALSE;
462 : }
463 4 : if (nOffset + 11 + nTRESize > psSegInfo->nSegmentSize)
464 : {
465 0 : CPLError(CE_Failure, CPLE_AppDefined,
466 : "Cannot read %s TRE. Not enough bytes : remaining %d, expected %d",
467 : szTRETempName,
468 : (int)(psSegInfo->nSegmentSize - (nOffset + 11)), nTRESize);
469 0 : return FALSE;
470 : }
471 :
472 4 : if (ppabyTREData)
473 : {
474 : /* Allocate one extra byte for the NULL terminating character */
475 4 : *ppabyTREData = (char*) VSIMalloc(nTRESize + 1);
476 4 : if (*ppabyTREData == NULL)
477 : {
478 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
479 : "Cannot allocate %d bytes for TRE %s",
480 : nTRESize, szTRETempName);
481 0 : return FALSE;
482 : }
483 4 : (*ppabyTREData)[nTRESize] = '\0';
484 :
485 4 : if ((int)VSIFReadL(*ppabyTREData, 1, nTRESize, fp) != nTRESize)
486 : {
487 0 : CPLError(CE_Failure, CPLE_FileIO,
488 : "Cannot get %d bytes at offset " CPL_FRMT_GUIB ".",
489 : nTRESize, VSIFTellL(fp) );
490 0 : VSIFree(*ppabyTREData);
491 0 : *ppabyTREData = NULL;
492 0 : return FALSE;
493 : }
494 : }
495 :
496 4 : strcpy(szTREName, szTRETempName);
497 4 : if (pnFoundTRESize)
498 4 : *pnFoundTRESize = nTRESize;
499 :
500 4 : return TRUE;
501 : }
502 :
503 : /************************************************************************/
504 : /* NITFDESFreeTREData() */
505 : /************************************************************************/
506 :
507 4 : void NITFDESFreeTREData( char* pabyTREData )
508 : {
509 4 : VSIFree(pabyTREData);
510 4 : }
511 :
512 :
513 : /************************************************************************/
514 : /* NITFDESExtractShapefile() */
515 : /************************************************************************/
516 :
517 0 : int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
518 : {
519 : NITFSegmentInfo* psSegInfo;
520 : const char* apszExt[3];
521 : int anOffset[4];
522 : int iShpFile;
523 : char* pszFilename;
524 :
525 0 : if ( CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE_USE") == NULL )
526 0 : return FALSE;
527 :
528 0 : psSegInfo = psDES->psFile->pasSegmentInfo + psDES->iSegment;
529 :
530 0 : apszExt[0] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE1_NAME");
531 0 : anOffset[0] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE1_START"));
532 0 : apszExt[1] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE2_NAME");
533 0 : anOffset[1] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE2_START"));
534 0 : apszExt[2] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE3_NAME");
535 0 : anOffset[2] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE3_START"));
536 0 : anOffset[3] = (int) psSegInfo->nSegmentSize;
537 :
538 0 : for(iShpFile = 0; iShpFile < 3; iShpFile ++)
539 : {
540 0 : if (!EQUAL(apszExt[iShpFile], "SHP") &&
541 0 : !EQUAL(apszExt[iShpFile], "SHX") &&
542 0 : !EQUAL(apszExt[iShpFile], "DBF"))
543 0 : return FALSE;
544 :
545 0 : if (anOffset[iShpFile] < 0 ||
546 0 : anOffset[iShpFile] >= anOffset[iShpFile+1])
547 0 : return FALSE;
548 : }
549 :
550 0 : pszFilename = (char*) VSIMalloc(strlen(pszRadixFileName) + 4 + 1);
551 0 : if (pszFilename == NULL)
552 0 : return FALSE;
553 :
554 0 : for(iShpFile = 0; iShpFile < 3; iShpFile ++)
555 : {
556 : VSILFILE* fp;
557 : GByte* pabyBuffer;
558 0 : int nSize = anOffset[iShpFile+1] - anOffset[iShpFile];
559 :
560 0 : pabyBuffer = (GByte*) VSIMalloc(nSize);
561 0 : if (pabyBuffer == NULL)
562 : {
563 0 : VSIFree(pszFilename);
564 0 : return FALSE;
565 : }
566 :
567 0 : VSIFSeekL(psDES->psFile->fp, psSegInfo->nSegmentStart + anOffset[iShpFile], SEEK_SET);
568 0 : if (VSIFReadL(pabyBuffer, 1, nSize, psDES->psFile->fp) != nSize)
569 : {
570 0 : VSIFree(pabyBuffer);
571 0 : VSIFree(pszFilename);
572 0 : return FALSE;
573 : }
574 :
575 0 : sprintf(pszFilename, "%s.%s", pszRadixFileName, apszExt[iShpFile]);
576 0 : fp = VSIFOpenL(pszFilename, "wb");
577 0 : if (fp == NULL)
578 : {
579 0 : VSIFree(pabyBuffer);
580 0 : VSIFree(pszFilename);
581 0 : return FALSE;
582 : }
583 :
584 0 : VSIFWriteL(pabyBuffer, 1, nSize, fp);
585 0 : VSIFCloseL(fp);
586 0 : VSIFree(pabyBuffer);
587 : }
588 :
589 0 : VSIFree(pszFilename);
590 :
591 0 : return TRUE;
592 : }
|