LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/avc - avc_e00write.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 278 0 0.0 %
Date: 2010-01-09 Functions: 8 0 0.0 %

       1                 : /**********************************************************************
       2                 :  * $Id: avc_e00write.c,v 1.21 2008/07/23 20:51:38 dmorissette Exp $
       3                 :  *
       4                 :  * Name:     avc_e00write.c
       5                 :  * Project:  Arc/Info vector coverage (AVC)  E00->BIN conversion library
       6                 :  * Language: ANSI C
       7                 :  * Purpose:  Functions to create a binary coverage from a stream of
       8                 :  *           ASCII E00 lines.
       9                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
      10                 :  *
      11                 :  **********************************************************************
      12                 :  * Copyright (c) 1999-2001, Daniel Morissette
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  * 
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  * 
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  **********************************************************************
      32                 :  *
      33                 :  * $Log: avc_e00write.c,v $
      34                 :  * Revision 1.21  2008/07/23 20:51:38  dmorissette
      35                 :  * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
      36                 :  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
      37                 :  *
      38                 :  * Revision 1.20  2006/06/27 18:38:43  dmorissette
      39                 :  * Cleaned up E00 reading (bug 1497, patch from James F.)
      40                 :  *
      41                 :  * Revision 1.19  2006/06/14 16:31:28  daniel
      42                 :  * Added support for AVCCoverPC2 type (bug 1491)
      43                 :  *
      44                 :  * Revision 1.18  2006/03/02 22:46:26  daniel
      45                 :  * Accept empty subclass names for TX6/TX7 sections (bug 1261)
      46                 :  *
      47                 :  * Revision 1.17  2005/06/03 03:49:59  daniel
      48                 :  * Update email address, website url, and copyright dates
      49                 :  *
      50                 :  * Revision 1.16  2002/08/27 15:46:15  daniel
      51                 :  * Applied fix made in GDAL/OGR by 'aubin' (moved include ctype.h after avc.h)
      52                 :  *
      53                 :  * Revision 1.15  2002/04/16 21:19:10  daniel
      54                 :  * Use VSIRmdir()
      55                 :  *
      56                 :  * Revision 1.14  2002/03/18 19:00:44  daniel
      57                 :  * Use VSIMkdir() and not VSIMkDir()
      58                 :  *
      59                 :  * Revision 1.13  2002/02/18 21:16:33  warmerda
      60                 :  * modified to use VSIMkDir
      61                 :  *
      62                 :  * Revision 1.12  2001/05/23 15:23:17  daniel
      63                 :  * Remove trailing '/' in info directory path when creating the info dir.
      64                 :  *
      65                 :  * Revision 1.11  2000/09/26 20:21:04  daniel
      66                 :  * Added AVCCoverPC write
      67                 :  *
      68                 :  * Revision 1.10  2000/09/22 19:45:21  daniel
      69                 :  * Switch to MIT-style license
      70                 :  *
      71                 :  * Revision 1.9  2000/05/29 22:47:39  daniel
      72                 :  * Made validation on new coverage name more flexible.
      73                 :  *
      74                 :  * Revision 1.8  2000/05/29 15:31:31  daniel
      75                 :  * Added Japanese DBCS support
      76                 :  *
      77                 :  * Revision 1.7  2000/02/14 17:19:53  daniel
      78                 :  * Accept '-' cahracter in new coverage name
      79                 :  *
      80                 :  * Revision 1.6  2000/01/10 02:57:44  daniel
      81                 :  * Little changes to accomodate read support for "weird" coverages
      82                 :  *
      83                 :  * Revision 1.5  1999/12/24 07:18:34  daniel
      84                 :  * Added PC Arc/Info coverages support
      85                 :  *
      86                 :  * Revision 1.4  1999/08/26 17:36:36  daniel
      87                 :  * Avoid overwriting arc.dir on Windows... happened only when several
      88                 :  * coverages are created by the same process on Windows.
      89                 :  *
      90                 :  * Revision 1.3  1999/08/23 18:23:35  daniel
      91                 :  * Added AVCE00DeleteCoverage()
      92                 :  *
      93                 :  * Revision 1.2  1999/05/17 16:23:36  daniel
      94                 :  * Added AVC_DEFAULT_PREC + more cover name validation in AVCE00WriteOpen().
      95                 :  *
      96                 :  * Revision 1.1  1999/05/11 02:34:46  daniel
      97                 :  * Initial revision
      98                 :  *
      99                 :  **********************************************************************/
     100                 : 
     101                 : #include "cpl_vsi.h"
     102                 : #include "avc.h"
     103                 : #include <ctype.h>      /* tolower() */
     104                 : 
     105                 : static GBool _IsStringAlnum(const char *pszFname);
     106                 : 
     107                 : /**********************************************************************
     108                 :  *                          AVCE00WriteOpen()
     109                 :  *
     110                 :  * Open (create) an Arc/Info coverage, ready to be receive a stream
     111                 :  * of ASCII E00 lines and convert that to the binary coverage format.
     112                 :  *
     113                 :  * For now, writing to or overwriting existing coverages is not supported
     114                 :  * (and may quite well never be!)... you can only create new coverages.
     115                 :  *
     116                 :  * Important Note: The E00 source lines are assumed to be valid... the
     117                 :  * library performs no validation on the consistency of what it is 
     118                 :  * given as input (i.e. topology, polygons consistency, etc.).
     119                 :  * So the coverage that will be created will be only as good as the 
     120                 :  * E00 input that is used to generate it.
     121                 :  *
     122                 :  * pszCoverPath MUST be the name of the coverage directory, including 
     123                 :  * the path to it.
     124                 :  * (contrary to AVCE00ReadOpen(), you cannot pass the name of one of
     125                 :  *  the files in the coverage directory).
     126                 :  * The name of the coverage MUST be included in pszCoverPath... this 
     127                 :  * means that passing "." is invalid.
     128                 :  *
     129                 :  * eNewCoverType is the type of coverage to create.  
     130                 :  *               Either AVCCoverV7 (Arc/Info V7 (Unix) coverage)
     131                 :  *               or     AVCCoverPC (PC Arc/Info coverage)
     132                 :  *
     133                 :  * nPrecision should always be AVC_DEFAULT_PREC to automagically detect the
     134                 :  *            source coverage's precision and use that same precision
     135                 :  *            for the new coverage.  
     136                 :  *
     137                 :  *            This parameter has been included to allow adding the 
     138                 :  *            possibility to eventually create coverages with a precision 
     139                 :  *            different from the source E00.
     140                 :  *            Given the way the lib is built, it could be possible to
     141                 :  *            also pass  AVC_SINGLE_PREC or AVC_DOUBLE_PREC to explicitly
     142                 :  *            request the creation of a coverage with that precision, 
     143                 :  *            but the library does not (not yet!) properly convert the 
     144                 :  *            TABLE attributes' precision, and the resulting coverage may
     145                 :  *            be invalid in some cases.  
     146                 :  *            This improvement is on the ToDo list!
     147                 :  *
     148                 :  * Returns a new AVCE00WritePtr handle or NULL if the coverage could 
     149                 :  * not be created or if a coverage with that name already exists.
     150                 :  *
     151                 :  * The handle will eventually have to be released with AVCE00ReadClose().
     152                 :  **********************************************************************/
     153               0 : AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath, 
     154                 :                                 AVCCoverType eNewCoverType, int nPrecision )
     155                 : {
     156                 :     AVCE00WritePtr  psInfo;
     157                 :     int             i, nLen;
     158                 :     VSIStatBuf      sStatBuf;
     159                 : 
     160               0 :     CPLErrorReset();
     161                 : 
     162                 :     /*-----------------------------------------------------------------
     163                 :      * Create pszCoverPath directory.  
     164                 :      *----------------------------------------------------------------*/
     165               0 :     if (pszCoverPath == NULL || strlen(pszCoverPath) == 0)
     166                 :     {
     167               0 :         CPLError(CE_Failure, CPLE_AssertionFailed, 
     168                 :                  "Invalid (empty) coverage directory name.");
     169               0 :         return NULL;
     170                 :     }
     171               0 :     else if ( VSIStat(pszCoverPath, &sStatBuf) == 0 &&
     172               0 :               VSI_ISDIR(sStatBuf.st_mode) )
     173                 :     {
     174                 :         /*-------------------------------------------------------------
     175                 :          * Directory already exists... make sure it is empty
     176                 :          * otherwise we can't use it as a coverage directory.
     177                 :          *------------------------------------------------------------*/
     178                 :         char **papszFiles;
     179               0 :         papszFiles = CPLReadDir(pszCoverPath);
     180               0 :         for(i=0; papszFiles && papszFiles[i]; i++)
     181                 :         {
     182               0 :             if (!EQUAL(".", papszFiles[i]) &&
     183               0 :                 !EQUAL("..", papszFiles[i]))
     184                 :             {
     185               0 :                 CPLError(CE_Failure, CPLE_OpenFailed, 
     186                 :                          "Cannot create coverage %s: directory already exists "
     187                 :                          "and is not empty.", pszCoverPath);
     188               0 :                 CSLDestroy(papszFiles);
     189               0 :                 papszFiles = NULL;
     190               0 :                 return NULL;
     191                 :             }
     192                 :         }
     193                 : 
     194               0 :         CSLDestroy(papszFiles);
     195               0 :         papszFiles = NULL;
     196                 :     }
     197                 :     else
     198                 :     {
     199                 :         /*-------------------------------------------------------------
     200                 :          * Create new pszCoverPath directory.  
     201                 :          * This will fail if a file with the same name already exists.
     202                 :          *------------------------------------------------------------*/
     203               0 :         if( VSIMkdir(pszCoverPath, 0777) != 0 )
     204                 :         {
     205               0 :             CPLError(CE_Failure, CPLE_OpenFailed, 
     206                 :                      "Unable to create coverage directory: %s.", pszCoverPath);
     207               0 :             return NULL;
     208                 :         }
     209                 :     }
     210                 : 
     211                 :     /*-----------------------------------------------------------------
     212                 :      * Alloc the AVCE00WritePtr handle
     213                 :      *----------------------------------------------------------------*/
     214               0 :     psInfo = (AVCE00WritePtr)CPLCalloc(1, sizeof(struct AVCE00WriteInfo_t));
     215                 : 
     216                 :     /*-----------------------------------------------------------------
     217                 :      * Validate and store coverage type
     218                 :      *----------------------------------------------------------------*/
     219               0 :     if (eNewCoverType == AVCCoverV7 || eNewCoverType == AVCCoverPC)
     220               0 :         psInfo->eCoverType = eNewCoverType;
     221                 :     else
     222                 :     {
     223               0 :         CPLError(CE_Failure, CPLE_NotSupported, 
     224                 :                  "Requested coverage type cannot be created.  Please use "
     225                 :                  "the AVCCoverV7 or AVCCoverPC coverage type.");
     226               0 :         CPLFree(psInfo);
     227               0 :         return NULL;
     228                 :     }
     229                 : 
     230                 :     /*-----------------------------------------------------------------
     231                 :      * Requested precision for the new coverage... for now only
     232                 :      * AVC_DEFAULT_PREC is supported.  When the first section is
     233                 :      * read, then this section's precision will be used for the whole
     234                 :      * coverage.  (This is done inside AVCE00WriteNextLine())
     235                 :      *----------------------------------------------------------------*/
     236               0 :     if (psInfo->eCoverType == AVCCoverPC)
     237               0 :         psInfo->nPrecision = AVC_SINGLE_PREC; /* PC Cover always single prec.*/
     238               0 :     else if (nPrecision == AVC_DEFAULT_PREC)
     239               0 :         psInfo->nPrecision = nPrecision;
     240                 :     else
     241                 :     {
     242               0 :         CPLError(CE_Failure, CPLE_IllegalArg, 
     243                 :                  "Coverages can only be created using AVC_DEFAULT_PREC. "
     244                 :                  "Please see the documentation for AVCE00WriteOpen().");
     245               0 :         CPLFree(psInfo);
     246               0 :         return NULL;
     247                 :     }
     248                 : 
     249                 :     /*-----------------------------------------------------------------
     250                 :      * Make sure coverage directory name is terminated with a '/' (or '\\')
     251                 :      *----------------------------------------------------------------*/
     252               0 :     nLen = strlen(pszCoverPath);
     253                 : 
     254               0 :     if (pszCoverPath[nLen-1] == '/' || pszCoverPath[nLen-1] == '\\')
     255               0 :         psInfo->pszCoverPath = CPLStrdup(pszCoverPath);
     256                 :     else
     257                 :     {
     258                 : #ifdef WIN32
     259                 :         psInfo->pszCoverPath = CPLStrdup(CPLSPrintf("%s\\",pszCoverPath));
     260                 : #else
     261               0 :         psInfo->pszCoverPath = CPLStrdup(CPLSPrintf("%s/",pszCoverPath));
     262                 : #endif
     263                 :     }
     264                 : 
     265                 :     /*-----------------------------------------------------------------
     266                 :      * Extract the coverage name from the coverage path.  Note that
     267                 :      * for this the coverage path must be in the form:
     268                 :      * "dir1/dir2/dir3/covername/" ... if it is not the case, then
     269                 :      * we would have to use getcwd() to find the current directory name...
     270                 :      * but for now we'll just produce an error if this happens.
     271                 :      *----------------------------------------------------------------*/
     272               0 :     nLen = 0;
     273               0 :     for( i = strlen(psInfo->pszCoverPath)-1; 
     274               0 :    i > 0 && psInfo->pszCoverPath[i-1] != '/' &&
     275               0 :             psInfo->pszCoverPath[i-1] != '\\'&&
     276               0 :             psInfo->pszCoverPath[i-1] != ':';
     277               0 :    i-- ) 
     278                 :     {
     279               0 :         nLen++;
     280                 :     }
     281                 : 
     282               0 :     if (nLen > 0)
     283                 :     {
     284               0 :         psInfo->pszCoverName = CPLStrdup(psInfo->pszCoverPath+i);
     285               0 :         psInfo->pszCoverName[nLen] = '\0';
     286                 :     }
     287                 :     else
     288                 :     {
     289               0 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     290                 :                  "Invalid coverage path (%s): "
     291                 :                  "coverage name must be included in path.", pszCoverPath);
     292                 : 
     293               0 :         CPLFree(psInfo->pszCoverPath);
     294               0 :         CPLFree(psInfo);
     295               0 :         return NULL;
     296                 :     }
     297                 : 
     298               0 :     if (strlen(psInfo->pszCoverName) > 13 ||
     299               0 :         !_IsStringAlnum(psInfo->pszCoverName) )
     300                 :     {
     301               0 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     302                 :                  "Invalid coverage name (%s): "
     303                 :                  "coverage name must be 13 chars or less and contain only "
     304                 :                  "alphanumerical characters, '-' or '_'.", 
     305                 :                  psInfo->pszCoverName);
     306                 : 
     307               0 :         CPLFree(psInfo->pszCoverPath);
     308               0 :         CPLFree(psInfo->pszCoverName);
     309               0 :         CPLFree(psInfo);
     310               0 :         return NULL;
     311                 :     }
     312                 : 
     313               0 :     if (psInfo->eCoverType == AVCCoverPC || psInfo->eCoverType == AVCCoverPC2)
     314                 :     {
     315                 :         /*-------------------------------------------------------------
     316                 :          * No 'info' directory is required for PC coverages
     317                 :          *------------------------------------------------------------*/
     318               0 :         psInfo->pszInfoPath = NULL;
     319                 :     }
     320                 :     else
     321                 :     {
     322                 :         /*-------------------------------------------------------------
     323                 :          * Lazy way to build the INFO path: simply add "../info/"...
     324                 :          * this could probably be improved!
     325                 :          *------------------------------------------------------------*/
     326               0 :         psInfo->pszInfoPath = (char*)CPLMalloc((strlen(psInfo->pszCoverPath)+9)
     327                 :                                                *sizeof(char));
     328                 : #ifdef WIN32
     329                 : #  define AVC_INFOPATH "..\\info\\"
     330                 : #else
     331                 : #  define AVC_INFOPATH "../info/"
     332                 : #endif
     333               0 :         sprintf(psInfo->pszInfoPath, "%s%s", psInfo->pszCoverPath, 
     334                 :                                              AVC_INFOPATH);
     335                 : 
     336                 :         /*-------------------------------------------------------------
     337                 :          * Check if the info directory exists and contains the "arc.dir"
     338                 :          * if the info dir does not exist, then make sure we can create
     339                 :          * the arc.dir file (i.e. try to create an empty one)
     340                 :          *
     341                 :          * Note: On Windows, this VSIStat() call seems to sometimes fail even 
     342                 :          *       when the directory exists (buffering issue?), and the 
     343                 :          *       following if() block is sometimes executed even if it 
     344                 :          *       should not, but this should not cause problems since the 
     345                 :          *       arc.dir is opened with "a+b" access.
     346                 :          *------------------------------------------------------------*/
     347               0 :         if ( VSIStat(psInfo->pszInfoPath, &sStatBuf) == -1)
     348                 :         {
     349                 :             FILE *fp;
     350                 :             char *pszArcDir;
     351                 :             char *pszInfoDir;
     352                 : 
     353               0 :             pszArcDir = CPLStrdup(CPLSPrintf("%s%s", 
     354                 :                                              psInfo->pszInfoPath, "arc.dir"));
     355                 : 
     356                 :             /* Remove the trailing "/" from pszInfoPath.  Most OSes are
     357                 :              * forgiving, and allow mkdir to include the trailing character,
     358                 :              * but some UNIXes are not. [GEH 2001/05/17]
     359                 :              */
     360               0 :             pszInfoDir = CPLStrdup(psInfo->pszInfoPath);
     361               0 :             pszInfoDir[strlen(pszInfoDir)-1] = '\0';
     362                 :             
     363               0 :             VSIMkdir(pszInfoDir, 0777);
     364               0 :             fp = VSIFOpen(pszArcDir, "a+b");
     365                 : 
     366               0 :             CPLFree(pszArcDir);
     367               0 :             CPLFree(pszInfoDir);
     368               0 :             if (fp)
     369                 :             {
     370               0 :                 VSIFClose(fp);
     371                 :             }
     372                 :             else
     373                 :             {
     374               0 :                 CPLError(CE_Failure, CPLE_OpenFailed, 
     375                 :                          "Unable to create (or write to) 'info' directory %s", 
     376                 :                          psInfo->pszInfoPath);
     377               0 :                 CPLFree(psInfo->pszCoverPath);
     378               0 :                 CPLFree(psInfo->pszInfoPath);
     379               0 :                 CPLFree(psInfo);
     380               0 :                 return NULL;
     381                 :             }
     382                 :         }
     383                 :     }
     384                 : 
     385                 :     /*-----------------------------------------------------------------
     386                 :      * Init the E00 parser.
     387                 :      *----------------------------------------------------------------*/
     388               0 :     psInfo->hParseInfo = AVCE00ParseInfoAlloc();
     389               0 :     psInfo->eCurFileType = AVCFileUnknown;
     390                 : 
     391                 :     /*-----------------------------------------------------------------
     392                 :      * Init multibyte encoding info
     393                 :      *----------------------------------------------------------------*/
     394               0 :     psInfo->psDBCSInfo = AVCAllocDBCSInfo();
     395                 : 
     396                 :     /*-----------------------------------------------------------------
     397                 :      * If an error happened during the open call, cleanup and return NULL.
     398                 :      *----------------------------------------------------------------*/
     399               0 :     if (CPLGetLastErrorNo() != 0)
     400                 :     {
     401               0 :         AVCE00WriteClose(psInfo);
     402               0 :         psInfo = NULL;
     403                 :     }
     404                 : 
     405               0 :     return psInfo;
     406                 : }
     407                 : 
     408                 : /**********************************************************************
     409                 :  *                          AVCE00WriteClose()
     410                 :  *
     411                 :  * Close a coverage and release all memory used by the AVCE00WritePtr
     412                 :  * handle.
     413                 :  **********************************************************************/
     414               0 : void AVCE00WriteClose(AVCE00WritePtr psInfo)
     415                 : {
     416               0 :     CPLErrorReset();
     417                 : 
     418               0 :     if (psInfo == NULL)
     419               0 :         return;
     420                 : 
     421               0 :     CPLFree(psInfo->pszCoverPath);
     422               0 :     CPLFree(psInfo->pszCoverName);
     423               0 :     CPLFree(psInfo->pszInfoPath);
     424                 : 
     425               0 :     if (psInfo->hFile)
     426               0 :         AVCBinWriteClose(psInfo->hFile);
     427                 : 
     428               0 :     if (psInfo->hParseInfo)
     429               0 :         AVCE00ParseInfoFree(psInfo->hParseInfo);
     430                 : 
     431               0 :     AVCFreeDBCSInfo(psInfo->psDBCSInfo);
     432                 : 
     433               0 :     CPLFree(psInfo);
     434                 : }
     435                 : 
     436                 : 
     437                 : /**********************************************************************
     438                 :  *                          _IsStringAlnum()
     439                 :  *
     440                 :  * Scan a string, and return TRUE if it contains only valid characters, 
     441                 :  * Return FALSE otherwise.
     442                 :  *
     443                 :  * We used to accept only isalnum() chars, but since extended chars with
     444                 :  * accents seem to be accepted, we will only check for chars that 
     445                 :  * could confuse the lib.
     446                 :  **********************************************************************/
     447               0 : static GBool _IsStringAlnum(const char *pszFname)
     448                 : {
     449               0 :     GBool bOK = TRUE;
     450                 : 
     451               0 :     while(bOK && *pszFname != '\0')
     452                 :     {
     453               0 :         if (strchr(" \t.,/\\", (unsigned char)*pszFname) != NULL)
     454               0 :             bOK = FALSE;
     455               0 :         pszFname ++;
     456                 :     }
     457                 : 
     458               0 :     return bOK;
     459                 : }
     460                 : 
     461                 : /**********************************************************************
     462                 :  *                          _AVCE00WriteRenameTable()
     463                 :  *
     464                 :  * Rename the table and the system fields in a tabledef that will
     465                 :  * be written to a new coverage.
     466                 :  **********************************************************************/
     467               0 : static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef, 
     468                 :                                     const char *pszNewCoverName)
     469                 : {
     470                 :     char szOldName[40], szOldExt[40], szNewName[40], *pszTmp;
     471                 :     char szSysId[40], szUserId[40];
     472                 :     int  i;
     473                 : 
     474               0 :     strcpy(szNewName, pszNewCoverName);
     475               0 :     for(i=0; szNewName[i] != '\0'; i++)
     476               0 :         szNewName[i] = toupper(szNewName[i]);
     477                 : 
     478                 :     /*-----------------------------------------------------------------
     479                 :      * Extract components from the current table name.
     480                 :      *----------------------------------------------------------------*/
     481               0 :     strcpy(szOldName, psTableDef->szTableName);
     482                 : 
     483               0 :     if ( !EQUAL(psTableDef->szExternal, "XX") ||
     484                 :          (pszTmp = strchr(szOldName, '.')) == NULL )
     485               0 :         return;  /* We don't deal with that table */
     486                 : 
     487               0 :     *pszTmp = '\0';
     488               0 :     pszTmp++;
     489                 : 
     490               0 :     strcpy(szOldExt, pszTmp);
     491               0 :     if ( (pszTmp = strchr(szOldExt, ' ')) != NULL )
     492               0 :         *pszTmp = '\0';
     493                 : 
     494               0 :     if (strlen(szOldExt) < 3)
     495               0 :         return;  /* We don't deal with that table */
     496                 : 
     497                 :     /*-----------------------------------------------------------------
     498                 :      * Look for system attributes with same name as table
     499                 :      * If the table name extension is followed by a subclass name 
     500                 :      * (e.g. "TEST.PATCOUNTY") then this subclass is used to build
     501                 :      * the system attributes (COUNTY# and COUNTY-ID) and thus we do 
     502                 :      * not need to rename them
     503                 :      * Otherwise (e.g. COUNTY.PAT) the coverage name is used and then 
     504                 :      * we need to rename these attribs for the new coverage name.
     505                 :      *----------------------------------------------------------------*/
     506               0 :     if (strlen(szOldExt) == 3)
     507                 :     {
     508               0 :         sprintf(szSysId, "%s#", szOldName);
     509               0 :         sprintf(szUserId, "%s-ID", szOldName);
     510                 : 
     511               0 :         for(i=0; i<psTableDef->numFields; i++)
     512                 :         {
     513                 :             /* Remove trailing spaces */
     514               0 :             if ((pszTmp=strchr(psTableDef->pasFieldDef[i].szName,' '))!=NULL)
     515               0 :                 *pszTmp = '\0';
     516                 : 
     517               0 :             if (EQUAL(psTableDef->pasFieldDef[i].szName, szSysId))
     518                 :             {
     519               0 :                 sprintf(psTableDef->pasFieldDef[i].szName, "%s#", szNewName);
     520                 :             }
     521               0 :             else if (EQUAL(psTableDef->pasFieldDef[i].szName, szUserId))
     522                 :             {
     523               0 :                 sprintf(psTableDef->pasFieldDef[i].szName, "%s-ID", szNewName);
     524                 :             }
     525                 :         }
     526                 :     }
     527                 : 
     528                 :     /*-----------------------------------------------------------------
     529                 :      * Build new table name
     530                 :      *----------------------------------------------------------------*/
     531               0 :     sprintf(psTableDef->szTableName, "%s.%s", szNewName, szOldExt);
     532                 : 
     533                 : }
     534                 : 
     535                 : /**********************************************************************
     536                 :  *                          _AVCE00WriteCreateCoverFile()
     537                 :  *
     538                 :  * Create a coverage file for the specified file type.
     539                 :  *
     540                 :  * The main part of the work is to find the right filename to use based on
     541                 :  * the file type, the coverage precision, etc... the rest of job is 
     542                 :  * done by AVCBinWriteCreate().
     543                 :  *
     544                 :  * Returns 0 on success, or -1 if an error happened.
     545                 :  *
     546                 :  * AVCWriteCloseCoverFile() will eventually have to be called to release the 
     547                 :  * resources used by the AVCBinFile structure.
     548                 :  **********************************************************************/
     549               0 : int  _AVCE00WriteCreateCoverFile(AVCE00WritePtr psInfo, AVCFileType eType,
     550                 :                                  const char *pszLine, AVCTableDef *psTableDef)
     551                 : {
     552               0 :     char        *pszPath, szFname[50]="";
     553               0 :     int         i, nStatus = 0;
     554                 : 
     555                 :     /* By now, new coverage precision should have been established */
     556                 :     CPLAssert(psInfo->nPrecision != AVC_DEFAULT_PREC);
     557                 : 
     558                 :     /*-----------------------------------------------------------------
     559                 :      * Establish filename based on file type, precision, and possibly the
     560                 :      * contents of the header line.
     561                 :      *----------------------------------------------------------------*/
     562               0 :     pszPath = psInfo->pszCoverPath;
     563               0 :     switch(eType)
     564                 :     {
     565                 :       case AVCFileARC:
     566               0 :         strcpy(szFname, "arc");
     567               0 :         break;
     568                 :       case AVCFilePAL:
     569               0 :         strcpy(szFname, "pal");
     570               0 :         break;
     571                 :       case AVCFileCNT:
     572               0 :         strcpy(szFname, "cnt");
     573               0 :         break;
     574                 :       case AVCFileLAB:
     575               0 :         strcpy(szFname, "lab");
     576               0 :         break;
     577                 :       case AVCFileTOL:
     578               0 :         if (psInfo->nPrecision == AVC_SINGLE_PREC)
     579               0 :             strcpy(szFname, "tol");
     580                 :         else
     581               0 :             strcpy(szFname, "par");
     582               0 :         break;
     583                 :       case AVCFilePRJ:
     584               0 :         strcpy(szFname, "prj");
     585               0 :         break;
     586                 :       case AVCFileTXT:
     587               0 :         strcpy(szFname, "txt");
     588               0 :         break;
     589                 :       case AVCFileTX6:
     590                 :       /* For TX6/TX7: the filename is subclass_name.txt 
     591                 :        */
     592                 : 
     593                 :         /* See bug 1261: It seems that empty subclass names are valid
     594                 :          * for TX7. In this case we'll default the filename to txt.txt
     595                 :          */
     596               0 :         if (pszLine[0] == '\0')
     597                 :         {
     598               0 :             strcpy(szFname, "txt.txt");
     599                 :         }
     600               0 :         else if (strlen(pszLine) > 30 || strchr(pszLine, ' ') != NULL)
     601               0 :             CPLError(CE_Failure, CPLE_IllegalArg, 
     602                 :                      "Invalid TX6/TX7 subclass name \"%s\"", pszLine);
     603                 :         else
     604               0 :             sprintf(szFname, "%s.txt", pszLine);
     605               0 :         break;
     606                 :       case AVCFileRPL:
     607                 :       /* For RPL and RXP: the filename is region_name.pal or region_name.rxp
     608                 :        */
     609               0 :         if (strlen(pszLine) > 30 || strchr(pszLine, ' ') != NULL)
     610               0 :             CPLError(CE_Failure, CPLE_IllegalArg, 
     611                 :                      "Invalid RPL region name \"%s\"", pszLine);
     612                 :         else
     613               0 :             sprintf(szFname, "%s.pal", pszLine);
     614               0 :         break;
     615                 :       case AVCFileRXP:
     616               0 :         if (strlen(pszLine) > 30 || strchr(pszLine, ' ') != NULL)
     617               0 :             CPLError(CE_Failure, CPLE_IllegalArg, 
     618                 :                      "Invalid RXP name \"%s\"", pszLine);
     619                 :         else
     620               0 :             sprintf(szFname, "%s.rxp", pszLine);
     621               0 :         break;
     622                 :       case AVCFileTABLE:
     623                 :         /*-------------------------------------------------------------
     624                 :          * For tables, Filename will be based on info in the psTableDef 
     625                 :          * but we need to rename the table and the system attributes 
     626                 :          * based on the new coverage name.
     627                 :          *------------------------------------------------------------*/
     628               0 :         if (psInfo->eCoverType != AVCCoverPC && 
     629               0 :             psInfo->eCoverType != AVCCoverPC2)
     630               0 :             pszPath = psInfo->pszInfoPath;
     631               0 :         _AVCE00WriteRenameTable(psTableDef, psInfo->pszCoverName);
     632               0 :         break;
     633                 :       default:
     634               0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     635                 :                  "_AVCE00WriteCreateCoverFile(): Unsupported file type!");
     636               0 :         nStatus = -1;
     637                 :         break;
     638                 :     }
     639                 : 
     640                 :     /*-----------------------------------------------------------------
     641                 :      * V7 coverage filenames default to have a .adf extension
     642                 :      * but PC coverage filenames (except .dbf tables) have no extensions.
     643                 :      *----------------------------------------------------------------*/
     644               0 :     if (psInfo->eCoverType == AVCCoverV7 && strchr(szFname, '.') == NULL)
     645               0 :         strcat(szFname, ".adf");
     646                 : 
     647                 :     /*-----------------------------------------------------------------
     648                 :      * Make sure filename is all lowercase and attempt to create the file
     649                 :      *----------------------------------------------------------------*/
     650               0 :     for(i=0; szFname[i] != '\0'; i++)
     651               0 :         szFname[i] = tolower(szFname[i]);
     652                 : 
     653               0 :     if (nStatus == 0)
     654                 :     {
     655               0 :         psInfo->eCurFileType = eType;
     656                 : 
     657               0 :         if (eType == AVCFileTABLE)
     658               0 :             psInfo->hFile = AVCBinWriteCreateTable(pszPath, 
     659               0 :                                                    psInfo->pszCoverName, 
     660                 :                                                    psTableDef,
     661                 :                                                    psInfo->eCoverType,
     662                 :                                                    psInfo->nPrecision,
     663                 :                                                    psInfo->psDBCSInfo);
     664                 :         else
     665                 : 
     666               0 :             psInfo->hFile = AVCBinWriteCreate(pszPath, szFname, 
     667                 :                                               psInfo->eCoverType,
     668                 :                                               eType, psInfo->nPrecision,
     669                 :                                               psInfo->psDBCSInfo);
     670                 : 
     671               0 :         if (psInfo->hFile == NULL)
     672                 :         {
     673               0 :             nStatus = -1;
     674               0 :             psInfo->eCurFileType = AVCFileUnknown;
     675                 :         }
     676                 :     }
     677                 : 
     678               0 :     return nStatus;
     679                 : }
     680                 : 
     681                 : /**********************************************************************
     682                 :  *                          _AVCE00WriteCloseCoverFile()
     683                 :  *
     684                 :  * Close current coverage file and reset the contents of psInfo.
     685                 :  *
     686                 :  * File should have been previously opened by _AVCE00WriteCreateCoverFile().
     687                 :  *
     688                 :  **********************************************************************/
     689               0 : void  _AVCE00WriteCloseCoverFile(AVCE00WritePtr psInfo)
     690                 : {
     691                 :     /*-----------------------------------------------------------------
     692                 :      * PRJ sections behave differently... since there is only one "object"
     693                 :      * per section, they accumulate lines while we read them, and we 
     694                 :      * write everything at once when we reach the end-of-section (EOP) line.
     695                 :      *----------------------------------------------------------------*/
     696               0 :     if (psInfo->eCurFileType == AVCFilePRJ)
     697                 :     {
     698               0 :         AVCBinWriteObject(psInfo->hFile, psInfo->hParseInfo->cur.papszPrj);
     699                 :     }
     700                 : 
     701               0 :     AVCBinWriteClose(psInfo->hFile);
     702               0 :     psInfo->hFile = NULL;
     703               0 :     psInfo->eCurFileType = AVCFileUnknown;
     704               0 : }
     705                 : 
     706                 : /**********************************************************************
     707                 :  *                          AVCE00WriteNextLine()
     708                 :  *
     709                 :  * Take the next line of E00 input for this coverage, parse it and 
     710                 :  * write the result to the coverage.
     711                 :  *
     712                 :  * Important Note: The E00 source lines are assumed to be valid... the
     713                 :  * library performs no validation on the consistency of what it is 
     714                 :  * given as input (i.e. topology, polygons consistency, etc.).
     715                 :  * So the coverage that will be created will be only as good as the 
     716                 :  * E00 input that is used to generate it.
     717                 :  *
     718                 :  * Returns 0 on success or -1 on error.
     719                 :  **********************************************************************/
     720               0 : int     AVCE00WriteNextLine(AVCE00WritePtr psInfo, const char *pszLine)
     721                 : {
     722                 :     /*-----------------------------------------------------------------
     723                 :      * TODO: Update this call to use _AVCE00ReadNextLineE00(), if
     724                 :      * possible.
     725                 :      *----------------------------------------------------------------*/
     726                 : 
     727               0 :     int nStatus = 0;
     728                 : 
     729               0 :     CPLErrorReset();
     730                 : 
     731                 :     /*-----------------------------------------------------------------
     732                 :      * If we're at the top level inside a supersection... check if this
     733                 :      * supersection ends here.
     734                 :      *----------------------------------------------------------------*/
     735               0 :     if (AVCE00ParseSuperSectionEnd(psInfo->hParseInfo, pszLine) == TRUE)
     736                 :     {
     737                 :         /* Nothing to do... it's all been done by the call to 
     738                 :          * AVCE00ParseSuperSectionEnd()
     739                 :          */
     740                 :     }
     741               0 :     else if (psInfo->eCurFileType == AVCFileUnknown)
     742                 :     {
     743                 :         /*-------------------------------------------------------------
     744                 :          * We're at the top level or inside a supersection... waiting 
     745                 :          * to encounter a valid section or supersection header 
     746                 :          * (i.e. "ARC  2", etc...)
     747                 :          *------------------------------------------------------------*/
     748                 : 
     749                 :         /*-------------------------------------------------------------
     750                 :          * First check for a supersection header (TX6, RXP, IFO, ...)
     751                 :          *------------------------------------------------------------*/
     752               0 :         if ( AVCE00ParseSuperSectionHeader(psInfo->hParseInfo,
     753                 :                                            pszLine) == AVCFileUnknown )
     754                 :         {
     755                 :             /*---------------------------------------------------------
     756                 :              * This was not a supersection header... check if it's a simple
     757                 :              * section header
     758                 :              *--------------------------------------------------------*/
     759               0 :             psInfo->eCurFileType=AVCE00ParseSectionHeader(psInfo->hParseInfo,
     760                 :                                                           pszLine);
     761                 :         }
     762                 : 
     763                 :         /*-------------------------------------------------------------
     764                 :          * If the coverage was created using AVC_DEFAULT_PREC and we are
     765                 :          * processing the first section header, then use this section's
     766                 :          * precision for the new coverage.
     767                 :          * (Note: this code segment will be executed only once per 
     768                 :          *        coverage and only if AVC_DEFAULT_PREC was selected)
     769                 :          *------------------------------------------------------------*/
     770               0 :         if (psInfo->nPrecision == AVC_DEFAULT_PREC &&
     771               0 :             psInfo->eCurFileType != AVCFileUnknown)
     772                 :         {
     773               0 :             psInfo->nPrecision = psInfo->hParseInfo->nPrecision;
     774                 :         }
     775                 : 
     776               0 :         if (psInfo->eCurFileType == AVCFileTABLE)
     777                 :         {
     778                 :             /*---------------------------------------------------------
     779                 :              * We can't create the file for a TABLE until the
     780                 :              * whole header has been read... send the first header
     781                 :              * line to the parser and wait until the whole header has 
     782                 :              * been read.
     783                 :              *--------------------------------------------------------*/
     784               0 :             AVCE00ParseNextLine(psInfo->hParseInfo, pszLine); 
     785                 :         }
     786               0 :         else if (psInfo->eCurFileType != AVCFileUnknown)
     787                 :         {
     788                 :             /*---------------------------------------------------------
     789                 :              * OK, we've found a valid section header... create the 
     790                 :              * corresponding file in the coverage.
     791                 :              * Note: supersection headers don't trigger the creation
     792                 :              *       of any output file... they just alter the psInfo state.
     793                 :              *--------------------------------------------------------*/
     794                 : 
     795               0 :             nStatus = _AVCE00WriteCreateCoverFile(psInfo, 
     796                 :                                                   psInfo->eCurFileType,
     797               0 :                                        psInfo->hParseInfo->pszSectionHdrLine,
     798                 :                                                   NULL);
     799                 :         }
     800                 :     }
     801               0 :     else if (psInfo->eCurFileType == AVCFileTABLE &&
     802               0 :              ! psInfo->hParseInfo->bTableHdrComplete )
     803                 :     {
     804                 :         /*-------------------------------------------------------------
     805                 :          * We're reading a TABLE header... continue reading lines
     806                 :          * from the header, and create the output file only once
     807                 :          * the header will have been completely read.
     808                 :          *
     809                 :          * Note: When parsing a TABLE, the first object returned will 
     810                 :          * be the AVCTableDef, then data records will follow.
     811                 :          *------------------------------------------------------------*/
     812                 :         AVCTableDef *psTableDef;
     813               0 :         psTableDef = (AVCTableDef*)AVCE00ParseNextLine(psInfo->hParseInfo, 
     814                 :                                                        pszLine); 
     815               0 :         if (psTableDef)
     816                 :         {
     817               0 :             nStatus = _AVCE00WriteCreateCoverFile(psInfo, 
     818                 :                                                   psInfo->eCurFileType,
     819               0 :                                        psInfo->hParseInfo->pszSectionHdrLine,
     820                 :                                                   psTableDef);
     821                 :         }
     822                 :     }
     823                 :     else
     824                 :     {
     825                 :         /*-------------------------------------------------------------
     826                 :          * We're are in the middle of a section... first check if we
     827                 :          * have reached the end.
     828                 :          *
     829                 :          * note: The first call to AVCE00ParseSectionEnd() with FALSE will 
     830                 :          *       not reset the parser until we close the file... and then
     831                 :          *       we call the function again to reset the parser.
     832                 :          *------------------------------------------------------------*/
     833               0 :         if (AVCE00ParseSectionEnd(psInfo->hParseInfo, pszLine, FALSE))
     834                 :         {
     835               0 :             _AVCE00WriteCloseCoverFile(psInfo);
     836               0 :             AVCE00ParseSectionEnd(psInfo->hParseInfo, pszLine, TRUE);
     837                 :         }
     838                 :         else
     839                 :         /*-------------------------------------------------------------
     840                 :          * ... not at the end yet, so continue reading objects.
     841                 :          *------------------------------------------------------------*/
     842                 :         {
     843                 :             void *psObj;
     844               0 :             psObj = AVCE00ParseNextLine(psInfo->hParseInfo, pszLine);
     845                 : 
     846               0 :             if (psObj)
     847               0 :                 AVCBinWriteObject(psInfo->hFile, psObj);
     848                 :         }
     849                 :     }
     850                 : 
     851                 : 
     852               0 :     if (psInfo->hParseInfo->bForceEndOfSection)
     853                 :     {
     854                 :         /*-------------------------------------------------------------
     855                 :          * The last call encountered an implicit end of section, so
     856                 :          * we close the section now without waiting for an end-of-section
     857                 :          * line (there won't be any!)... and get ready to proceed with
     858                 :          * the next section.
     859                 :          * This is used for TABLEs.
     860                 :          *------------------------------------------------------------*/
     861               0 :         _AVCE00WriteCloseCoverFile(psInfo);
     862               0 :         AVCE00ParseSectionEnd(psInfo->hParseInfo, pszLine, TRUE);
     863                 :         /* psInfo->hParseInfo->bForceEndOfSection = FALSE; */
     864                 :     }
     865                 : 
     866               0 :     if (CPLGetLastErrorNo() != 0)
     867               0 :         nStatus = -1;
     868                 : 
     869               0 :     return nStatus;
     870                 : }
     871                 : 
     872                 : 
     873                 : /**********************************************************************
     874                 :  *                          AVCE00DeleteCoverage()
     875                 :  *
     876                 :  * Delete a coverage directory, its contents, and the associated info
     877                 :  * tables.
     878                 :  *
     879                 :  * Note:
     880                 :  * When deleting tables, only the ../info/arc????.nit and arc????.dat
     881                 :  * need to be deleted; the arc.dir does not need to be updated.  This
     882                 :  * is exactly what Arc/Info's KILL command does.
     883                 :  *
     884                 :  * Returns 0 on success or -1 on error.
     885                 :  **********************************************************************/
     886               0 : int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
     887                 : {
     888               0 :     int i, j, nStatus = 0;
     889                 :     char *pszInfoPath, *pszCoverPath, *pszCoverName;
     890                 :     const char *pszFname;
     891               0 :     char **papszTables=NULL, **papszFiles=NULL;
     892                 :     AVCE00ReadPtr   psInfo;
     893                 :     VSIStatBuf      sStatBuf;
     894                 :     AVCCoverType    eCoverType;
     895                 : 
     896               0 :     CPLErrorReset();
     897                 : 
     898                 :     /*-----------------------------------------------------------------
     899                 :      * Since we don't want to duplicate all the logic to figure coverage
     900                 :      * and info dir name, etc... we'll simply open the coverage and
     901                 :      * grab the info we need from the coverage handle.
     902                 :      * By the same way, this will verify that the coverage exists and is
     903                 :      * valid.
     904                 :      *----------------------------------------------------------------*/
     905               0 :     psInfo = AVCE00ReadOpen(pszCoverToDelete);
     906                 : 
     907               0 :     if (psInfo == NULL)
     908                 :     {
     909               0 :         CPLError(CE_Failure, CPLE_FileIO,
     910                 :                  "Cannot delete coverage %s: it does not appear to be valid\n",
     911                 :                  pszCoverToDelete);
     912               0 :         return -1;
     913                 :     }
     914                 : 
     915               0 :     pszCoverPath = CPLStrdup(psInfo->pszCoverPath);
     916               0 :     pszInfoPath = CPLStrdup(psInfo->pszInfoPath);
     917               0 :     pszCoverName = CPLStrdup(psInfo->pszCoverName);
     918               0 :     eCoverType = psInfo->eCoverType;
     919                 : 
     920               0 :     AVCE00ReadClose(psInfo);
     921                 : 
     922                 :     /*-----------------------------------------------------------------
     923                 :      * Delete files in cover directory.
     924                 :      *----------------------------------------------------------------*/
     925               0 :     papszFiles = CPLReadDir(pszCoverPath);
     926               0 :     for(i=0; nStatus==0 && papszFiles && papszFiles[i]; i++)
     927                 :     {
     928               0 :         if (!EQUAL(".", papszFiles[i]) &&
     929               0 :             !EQUAL("..", papszFiles[i]))
     930                 :         {
     931               0 :             pszFname = CPLSPrintf("%s%s", pszCoverPath, papszFiles[i]);
     932               0 :             if (unlink(pszFname) != 0)
     933                 :             {
     934               0 :                 CPLError(CE_Failure, CPLE_FileIO, 
     935                 :                          "Failed deleting %s%s", 
     936               0 :                          pszCoverPath, papszFiles[i]);
     937               0 :                 nStatus = -1;
     938               0 :                 break;
     939                 :             }
     940                 :         }
     941                 :     }
     942                 : 
     943               0 :     CSLDestroy(papszFiles);
     944               0 :     papszFiles = NULL;
     945                 : 
     946                 :     /*-----------------------------------------------------------------
     947                 :      * Get the list of info files (ARC????) to delete and delete them
     948                 :      * (No 'info' directory for PC coverages)
     949                 :      *----------------------------------------------------------------*/
     950               0 :     if (nStatus == 0 && eCoverType != AVCCoverPC && eCoverType != AVCCoverPC2)
     951                 :     {
     952               0 :         papszTables = AVCBinReadListTables(pszInfoPath, pszCoverName, 
     953                 :                                            &papszFiles, eCoverType,
     954                 :                                            NULL /*DBCSInfo*/);
     955                 : 
     956               0 :         for(i=0; nStatus==0 && papszFiles && papszFiles[i]; i++)
     957                 :         {
     958                 :             /* Convert table filename to lowercases */
     959               0 :             for(j=0; papszFiles[i] && papszFiles[i][j]!='\0'; j++)
     960               0 :                 papszFiles[i][j] = tolower(papszFiles[i][j]);
     961                 : 
     962                 :             /* Delete the .DAT file */
     963               0 :             pszFname = CPLSPrintf("%s%s.dat", pszInfoPath, papszFiles[i]);
     964               0 :             if ( VSIStat(pszFname, &sStatBuf) != -1 &&
     965               0 :                  unlink(pszFname) != 0)
     966                 :             {
     967               0 :                 CPLError(CE_Failure, CPLE_FileIO, 
     968                 :                          "Failed deleting %s%s", 
     969               0 :                          pszInfoPath, papszFiles[i]);
     970               0 :                 nStatus = -1;
     971               0 :                 break;
     972                 :             }
     973                 : 
     974                 :             /* Delete the .DAT file */
     975               0 :             pszFname = CPLSPrintf("%s%s.nit", pszInfoPath, papszFiles[i]);
     976               0 :             if ( VSIStat(pszFname, &sStatBuf) != -1 &&
     977               0 :                  unlink(pszFname) != 0)
     978                 :             {
     979               0 :                 CPLError(CE_Failure, CPLE_FileIO, 
     980                 :                          "Failed deleting %s%s", 
     981               0 :                          pszInfoPath, papszFiles[i]);
     982               0 :                 nStatus = -1;
     983               0 :                 break;
     984                 :             }
     985                 :         }
     986                 : 
     987               0 :         CSLDestroy(papszTables);
     988               0 :         CSLDestroy(papszFiles);
     989                 :     }
     990                 : 
     991                 :     /*-----------------------------------------------------------------
     992                 :      * Delete the coverage directory itself
     993                 :      * In some cases, the directory could be locked by another application 
     994                 :      * on the same system or somewhere on the network.  
     995                 :      * Define AVC_IGNORE_RMDIR_ERROR at compile time if you want this 
     996                 :      * error to be ignored.
     997                 :      *----------------------------------------------------------------*/
     998               0 :     if (VSIRmdir(pszCoverPath) != 0)
     999                 :     {
    1000                 : #ifndef AVC_IGNORE_RMDIR_ERROR
    1001               0 :         CPLError(CE_Failure, CPLE_FileIO, 
    1002                 :                  "Failed deleting directory %s", pszCoverPath);
    1003               0 :         nStatus = -1;
    1004                 : #endif
    1005                 :     }
    1006                 : 
    1007               0 :     CPLFree(pszCoverPath);
    1008               0 :     CPLFree(pszInfoPath);
    1009               0 :     CPLFree(pszCoverName);
    1010                 : 
    1011               0 :     return nStatus;
    1012                 : }
    1013                 : 

Generated by: LCOV version 1.7