Example #1
0
OGRErr OGRGeoconceptDriver::DeleteDataSource( const char *pszDataSource )

{
    VSIStatBufL sStatBuf;
    static const char * const apszExtensions[] =
        { "gxt", "txt", "gct", "gcm", "gcr", nullptr };

    if( VSIStatL( pszDataSource, &sStatBuf ) != 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "%s does not appear to be a file or directory.",
                  pszDataSource );

        return OGRERR_FAILURE;
    }

    if( VSI_ISREG(sStatBuf.st_mode)
        && (
            EQUAL(CPLGetExtension(pszDataSource),"gxt") ||
            EQUAL(CPLGetExtension(pszDataSource),"txt")
           ) )
    {
        for( int iExt=0; apszExtensions[iExt] != nullptr; iExt++ )
        {
            const char *pszFile = CPLResetExtension(pszDataSource,
                                                    apszExtensions[iExt] );
            if( VSIStatL( pszFile, &sStatBuf ) == 0 )
                VSIUnlink( pszFile );
        }
    }
    else if( VSI_ISDIR(sStatBuf.st_mode) )
    {
        char **papszDirEntries = VSIReadDir( pszDataSource );

        for( int iFile = 0;
             papszDirEntries != nullptr && papszDirEntries[iFile] != nullptr;
             iFile++ )
        {
            if( CSLFindString( const_cast<char **>( apszExtensions ),
                               CPLGetExtension(papszDirEntries[iFile])) != -1)
            {
                VSIUnlink( CPLFormFilename( pszDataSource,
                                            papszDirEntries[iFile],
                                            nullptr ) );
            }
        }

        CSLDestroy( papszDirEntries );

        VSIRmdir( pszDataSource );
    }

    return OGRERR_NONE;
}
Example #2
0
static void ProcessIdentifyTarget( const char *pszTarget,
                                   char **papszSiblingList,
                                   bool bRecursive,
                                   bool bReportFailures,
                                   bool bForceRecurse )

{
    GDALDriverH hDriver;
    VSIStatBufL sStatBuf;
    int i;

    hDriver = GDALIdentifyDriver( pszTarget, papszSiblingList );

    if( hDriver != nullptr )
        printf( "%s: %s\n", pszTarget, GDALGetDriverShortName( hDriver ) );
    else if( bReportFailures )
        printf( "%s: unrecognized\n", pszTarget );

    if( !bForceRecurse && (!bRecursive || hDriver != nullptr) )
        return;

    if( VSIStatL( pszTarget, &sStatBuf ) != 0
        || !VSI_ISDIR( sStatBuf.st_mode ) )
        return;

    papszSiblingList = VSIReadDir( pszTarget );
    for( i = 0; papszSiblingList && papszSiblingList[i]; i++ )
    {
        if( EQUAL(papszSiblingList[i],"..")
            || EQUAL(papszSiblingList[i],".") )
            continue;

        CPLString osSubTarget =
            CPLFormFilename( pszTarget, papszSiblingList[i], nullptr );

        ProcessIdentifyTarget( osSubTarget, papszSiblingList,
                               bRecursive, bReportFailures, bForceRecurse );
    }
    CSLDestroy(papszSiblingList);
}
Example #3
0
void OGRTigerDataSource::DeleteModuleFiles( const char *pszModule )

{
    char **papszDirFiles = VSIReadDir( GetDirPath() );
    const int nCount = CSLCount(papszDirFiles);

    for( int i = 0; i < nCount; i++ )
    {
        if( EQUALN(pszModule,papszDirFiles[i],strlen(pszModule)) )
        {
            const char *pszFilename = CPLFormFilename( GetDirPath(),
                                           papszDirFiles[i],
                                           nullptr );
            if( VSIUnlink( pszFilename ) != 0 )
            {
                CPLDebug( "OGR_TIGER", "Failed to unlink %s", pszFilename );
            }
        }
    }

    CSLDestroy( papszDirFiles );
}
Example #4
0
int OGRTABDataSource::Open( GDALOpenInfo *poOpenInfo, int bTestOpen )

{
    CPLAssert(m_pszName == nullptr);

    m_pszName = CPLStrdup(poOpenInfo->pszFilename);
    m_bUpdate = poOpenInfo->eAccess == GA_Update;

    // If it is a file, try to open as a Mapinfo file.
    if( !poOpenInfo->bIsDirectory )
    {
        IMapInfoFile *poFile =
            IMapInfoFile::SmartOpen(m_pszName, m_bUpdate, bTestOpen);
        if( poFile == nullptr )
            return FALSE;

        poFile->SetDescription(poFile->GetName());

        m_nLayerCount = 1;
        m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *)));
        m_papoLayers[0] = poFile;

        m_pszDirectory = CPLStrdup(CPLGetPath(m_pszName));

        m_bSingleFile = TRUE;
        m_bSingleLayerAlreadyCreated = TRUE;
    }

    // Otherwise, we need to scan the whole directory for files
    // ending in .tab or .mif.
    else
    {
        char **papszFileList = VSIReadDir(m_pszName);

        m_pszDirectory = CPLStrdup(m_pszName);

        for( int iFile = 0;
             papszFileList != nullptr && papszFileList[iFile] != nullptr;
             iFile++ )
        {
            const char *pszExtension = CPLGetExtension(papszFileList[iFile]);

            if( !EQUAL(pszExtension, "tab") && !EQUAL(pszExtension, "mif") )
                continue;

            char *pszSubFilename = CPLStrdup(
                CPLFormFilename(m_pszDirectory, papszFileList[iFile], nullptr));

            IMapInfoFile *poFile =
                IMapInfoFile::SmartOpen(pszSubFilename, m_bUpdate, bTestOpen);
            CPLFree(pszSubFilename);

            if( poFile == nullptr )
            {
                CSLDestroy(papszFileList);
                return FALSE;
            }
            poFile->SetDescription( poFile->GetName() );

            m_nLayerCount++;
            m_papoLayers = static_cast<IMapInfoFile **>(
                CPLRealloc(m_papoLayers,sizeof(void *) * m_nLayerCount));
            m_papoLayers[m_nLayerCount-1] = poFile;
        }

        CSLDestroy(papszFileList);

        if( m_nLayerCount == 0 )
        {
            if( !bTestOpen )
                CPLError(CE_Failure, CPLE_OpenFailed,
                         "No mapinfo files found in directory %s.",
                         m_pszDirectory);

            return FALSE;
        }
    }

    return TRUE;
}
int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
                            int bForceOpen, char** papszOpenOptions )

{
    pszName = CPLStrdup( pszFilename );
    bUpdate = bUpdateIn;

    if (bUpdateIn && bForceOpen && EQUAL(pszFilename, "/vsistdout/"))
        return TRUE;

    /* For writable /vsizip/, do nothing more */
    if (bUpdateIn && bForceOpen && strncmp(pszFilename, "/vsizip/", 8) == 0)
        return TRUE;

    CPLString osFilename(pszFilename);
    CPLString osBaseFilename = CPLGetFilename(pszFilename);
    CPLString osExt = GetRealExtension(osFilename);
    pszFilename = NULL;

    int bIgnoreExtension = EQUALN(osFilename, "CSV:", 4);
    int bUSGeonamesFile = FALSE;
    /* int bGeonamesOrgFile = FALSE; */
    if (bIgnoreExtension)
    {
        osFilename = osFilename + 4;
    }

    /* Those are *not* real .XLS files, but text file with tab as column separator */
    if (EQUAL(osBaseFilename, "NfdcFacilities.xls") ||
        EQUAL(osBaseFilename, "NfdcRunways.xls") ||
        EQUAL(osBaseFilename, "NfdcRemarks.xls") ||
        EQUAL(osBaseFilename, "NfdcSchedules.xls"))
    {
        if (bUpdateIn)
            return FALSE;
        bIgnoreExtension = TRUE;
    }
    else if ((EQUALN(osBaseFilename, "NationalFile_", 13) ||
              EQUALN(osBaseFilename, "POP_PLACES_", 11) ||
              EQUALN(osBaseFilename, "HIST_FEATURES_", 14) ||
              EQUALN(osBaseFilename, "US_CONCISE_", 11) ||
              EQUALN(osBaseFilename, "AllNames_", 9) ||
              EQUALN(osBaseFilename, "Feature_Description_History_", 28) ||
              EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
              EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
              EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
              EQUALN(osBaseFilename, "AllStates_", 10) ||
              EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) ||
              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) &&
             (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
    {
        if (bUpdateIn)
            return FALSE;
        bIgnoreExtension = TRUE;
        bUSGeonamesFile = TRUE;

        if (EQUAL(osExt, "zip") &&
            strstr(osFilename, "/vsizip/") == NULL )
        {
            osFilename = "/vsizip/" + osFilename;
        }
    }
    else if (EQUAL(osBaseFilename, "allCountries.txt") ||
             EQUAL(osBaseFilename, "allCountries.zip"))
    {
        if (bUpdateIn)
            return FALSE;
        bIgnoreExtension = TRUE;
        /* bGeonamesOrgFile = TRUE; */

        if (EQUAL(osExt, "zip") &&
            strstr(osFilename, "/vsizip/") == NULL )
        {
            osFilename = "/vsizip/" + osFilename;
        }
    }

/* -------------------------------------------------------------------- */
/*      Determine what sort of object this is.                          */
/* -------------------------------------------------------------------- */
    VSIStatBufL sStatBuf;

    if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      Is this a single CSV file?                                      */
/* -------------------------------------------------------------------- */
    if( VSI_ISREG(sStatBuf.st_mode)
        && (bIgnoreExtension || EQUAL(osExt,"csv") || EQUAL(osExt,"tsv")) )
    {
        if (EQUAL(CPLGetFilename(osFilename), "NfdcFacilities.xls"))
        {
            return OpenTable( osFilename, papszOpenOptions, "ARP");
        }
        else if (EQUAL(CPLGetFilename(osFilename), "NfdcRunways.xls"))
        {
            OpenTable( osFilename, papszOpenOptions, "BaseEndPhysical");
            OpenTable( osFilename, papszOpenOptions, "BaseEndDisplaced");
            OpenTable( osFilename, papszOpenOptions, "ReciprocalEndPhysical");
            OpenTable( osFilename, papszOpenOptions, "ReciprocalEndDisplaced");
            return nLayers != 0;
        }
        else if (bUSGeonamesFile)
        {
            /* GNIS specific */
            if (EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
                EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
                EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
                (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10)))
            {
                OpenTable( osFilename, papszOpenOptions, NULL, "PRIMARY");
            }
            else if (EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
                     EQUALN(osBaseFilename, "Feature_Description_History_", 28))
            {
                OpenTable( osFilename, papszOpenOptions, NULL, "");
            }
            else
            {
                OpenTable( osFilename, papszOpenOptions, NULL, "PRIM");
                OpenTable( osFilename, papszOpenOptions, NULL, "SOURCE");
            }
            return nLayers != 0;
        }

        return OpenTable( osFilename, papszOpenOptions );
    }

/* -------------------------------------------------------------------- */
/*      Is this a single a ZIP file with only a CSV file inside ?       */
/* -------------------------------------------------------------------- */
    if( strncmp(osFilename, "/vsizip/", 8) == 0 &&
        EQUAL(osExt, "zip") &&
        VSI_ISREG(sStatBuf.st_mode) )
    {
        char** papszFiles = VSIReadDir(osFilename);
        if (CSLCount(papszFiles) != 1 ||
            !EQUAL(CPLGetExtension(papszFiles[0]), "CSV"))
        {
            CSLDestroy(papszFiles);
            return FALSE;
        }
        osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL);
        CSLDestroy(papszFiles);
        return OpenTable( osFilename, papszOpenOptions );
    }

/* -------------------------------------------------------------------- */
/*      Otherwise it has to be a directory.                             */
/* -------------------------------------------------------------------- */
    if( !VSI_ISDIR(sStatBuf.st_mode) )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      Scan through for entries ending in .csv.                        */
/* -------------------------------------------------------------------- */
    int nNotCSVCount = 0, i;
    char **papszNames = CPLReadDir( osFilename );

    for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
    {
        CPLString oSubFilename = 
            CPLFormFilename( osFilename, papszNames[i], NULL );

        if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") )
            continue;

        if (EQUAL(CPLGetExtension(oSubFilename),"csvt"))
            continue;

        if( VSIStatL( oSubFilename, &sStatBuf ) != 0 
            || !VSI_ISREG(sStatBuf.st_mode) )
        {
            nNotCSVCount++;
            continue;
        }

        if (EQUAL(CPLGetExtension(oSubFilename),"csv"))
        {
            if( !OpenTable( oSubFilename, papszOpenOptions ) )
            {
                CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
                nNotCSVCount++;
                continue;
            }
        }

        /* GNIS specific */
        else if ( strlen(papszNames[i]) > 2 &&
                  EQUALN(papszNames[i]+2, "_Features_", 10) &&
                  EQUAL(CPLGetExtension(papszNames[i]), "txt") )
        {
            int bRet = OpenTable( oSubFilename, papszOpenOptions, NULL, "PRIM");
            bRet |= OpenTable( oSubFilename, papszOpenOptions, NULL, "SOURCE");
            if ( !bRet )
            {
                CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
                nNotCSVCount++;
                continue;
            }
        }
        /* GNIS specific */
        else if ( strlen(papszNames[i]) > 2 &&
                  EQUALN(papszNames[i]+2, "_FedCodes_", 10) &&
                  EQUAL(CPLGetExtension(papszNames[i]), "txt") )
        {
            if ( !OpenTable( oSubFilename, papszOpenOptions, NULL, "PRIMARY") )
            {
                CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
                nNotCSVCount++;
                continue;
            }
        }
        else
        {
            nNotCSVCount++;
            continue;
        }
    }

    CSLDestroy( papszNames );

/* -------------------------------------------------------------------- */
/*      We presume that this is indeed intended to be a CSV             */
/*      datasource if over half the files were .csv files.              */
/* -------------------------------------------------------------------- */
    return bForceOpen || nNotCSVCount < nLayers;
}
int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCreate) {
    // Check if a range is set and extract it and the filename
    const char *pszc=pszFilename;
    if (*pszFilename==0) return FALSE;
    while (*pszc) ++pszc;
    if (*(pszc-1)==']') {
        --pszc;
        while (pszc!=pszFilename && *pszc!='[') pszc--;
        if (pszc==pszFilename) return FALSE;
        poRange.setRange(pszc);
    }
    pszName = CPLStrdup( pszFilename );
    pszName[pszc-pszFilename]=0;
    bUpdate = bUpdateIn;
    if (bCreate && EQUAL(pszName, "/vsistdout/")) return TRUE;
    /* For writable /vsizip/, do nothing more */
    if (bCreate && STARTS_WITH(pszName, "/vsizip/")) return TRUE;
    CPLString osFilename(pszName);
    CPLString osBaseFilename = CPLGetFilename(pszName);
    // Determine what sort of object this is.
    VSIStatBufL sStatBuf;
    if (VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0) return FALSE;

    // Is this a single Selafin file?
    if (VSI_ISREG(sStatBuf.st_mode)) return OpenTable( pszName );

    // Is this a single a ZIP file with only a Selafin file inside ?
    if( STARTS_WITH(osFilename, "/vsizip/") && VSI_ISREG(sStatBuf.st_mode) ) {
        char** papszFiles = VSIReadDir(osFilename);
        if (CSLCount(papszFiles) != 1) {
            CSLDestroy(papszFiles);
            return FALSE;
        }
        osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL);
        CSLDestroy(papszFiles);
        return OpenTable( osFilename );
    }

#ifdef notdef
    // Otherwise it has to be a directory.
    if( !VSI_ISDIR(sStatBuf.st_mode) ) return FALSE;

    // Scan through for entries which look like Selafin files
    int nNotSelafinCount = 0, i;
    char **papszNames = VSIReadDir( osFilename );
    for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ ) {
        CPLString oSubFilename = CPLFormFilename( osFilename, papszNames[i], NULL );
        if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") ) continue;
        if( VSIStatL( oSubFilename, &sStatBuf ) != 0 || !VSI_ISREG(sStatBuf.st_mode) ) {
            nNotSelafinCount++;
            continue;
        }
        if( !OpenTable( oSubFilename ) ) {
            CPLDebug("Selafin", "Cannot open %s", oSubFilename.c_str());
            nNotSelafinCount++;
            continue;
        }
    }
    CSLDestroy( papszNames );

    // We presume that this is indeed intended to be a Selafin datasource if over half the files were Selafin files.
    return nNotSelafinCount < nLayers;
#else
    return FALSE;
#endif
}
Example #7
0
bool OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
                              bool bTestOpen, bool bForceSingleFileDataSource )

{
    CPLAssert( nLayers == 0 );

    const char * pszNewName = poOpenInfo->pszFilename;
    const bool bUpdate = poOpenInfo->eAccess == GA_Update;
    papszOpenOptions = CSLDuplicate( poOpenInfo->papszOpenOptions );

    pszName = CPLStrdup( pszNewName );

    bDSUpdate = bUpdate;

    bSingleFileDataSource = CPL_TO_BOOL(bForceSingleFileDataSource);

/* -------------------------------------------------------------------- */
/*      If bSingleFileDataSource is TRUE we don't try to do anything    */
/*      else.                                                           */
/*      This is only utilized when the OGRShapeDriver::Create()         */
/*      method wants to create a stub OGRShapeDataSource for a          */
/*      single shapefile.  The driver will take care of creating the    */
/*      file by calling ICreateLayer().                                 */
/* -------------------------------------------------------------------- */
    if( bSingleFileDataSource )
        return true;

/* -------------------------------------------------------------------- */
/*      Is the given path a directory or a regular file?                */
/* -------------------------------------------------------------------- */
    if( !poOpenInfo->bStatOK )
    {
        if( !bTestOpen )
            CPLError( CE_Failure, CPLE_AppDefined,
                      "%s is neither a file or directory, Shape access failed.",
                      pszNewName );

        return false;
    }

/* -------------------------------------------------------------------- */
/*      Build a list of filenames we figure are Shape files.            */
/* -------------------------------------------------------------------- */
    if( !poOpenInfo->bIsDirectory )
    {
        if( !OpenFile( pszNewName, bUpdate ) )
        {
            if( !bTestOpen )
                CPLError(
                    CE_Failure, CPLE_OpenFailed,
                    "Failed to open shapefile %s.  "
                    "It may be corrupt or read-only file accessed in "
                    "update mode.",
                    pszNewName );

            return false;
        }

        bSingleFileDataSource = true;

        return true;
    }
    else
    {
        char **papszCandidates = VSIReadDir( pszNewName );
        const int nCandidateCount = CSLCount( papszCandidates );
        bool bMightBeOldCoverage = false;
        std::set<CPLString> osLayerNameSet;

        for( int iCan = 0; iCan < nCandidateCount; iCan++ )
        {
            const char *pszCandidate = papszCandidates[iCan];
            const char *pszLayerName = CPLGetBasename(pszCandidate);
            CPLString osLayerName(pszLayerName);
#ifdef WIN32
            // On Windows, as filenames are case insensitive, a shapefile layer
            // can be made of foo.shp and FOO.DBF, so to detect unique layer
            // names, put them upper case in the unique set used for detection.
            osLayerName.toupper();
#endif

            if( EQUAL(pszCandidate,"ARC") )
                bMightBeOldCoverage = true;

            if( strlen(pszCandidate) < 4
                || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") )
                continue;

            char *pszFilename =
                CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));

            osLayerNameSet.insert(osLayerName);
#ifdef IMMEDIATE_OPENING
            if( !OpenFile( pszFilename, bUpdate )
                && !bTestOpen )
            {
                CPLError(
                    CE_Failure, CPLE_OpenFailed,
                    "Failed to open shapefile %s.  "
                    "It may be corrupt or read-only file accessed in "
                    "update mode.",
                    pszFilename );
                CPLFree( pszFilename );
                CSLDestroy( papszCandidates );
                return false;
            }
#else
            oVectorLayerName.push_back(pszFilename);
#endif
            CPLFree( pszFilename );
        }

        // Try and .dbf files without apparent associated shapefiles.
        for( int iCan = 0; iCan < nCandidateCount; iCan++ )
        {
            const char  *pszCandidate = papszCandidates[iCan];
            const char  *pszLayerName = CPLGetBasename(pszCandidate);
            CPLString osLayerName(pszLayerName);
#ifdef WIN32
            osLayerName.toupper();
#endif

            // We don't consume .dbf files in a directory that looks like
            // an old style Arc/Info (for PC?) that unless we found at least
            // some shapefiles.  See Bug 493.
            if( bMightBeOldCoverage && osLayerNameSet.size() == 0 )
                continue;

            if( strlen(pszCandidate) < 4
                || !EQUAL(pszCandidate+strlen(pszCandidate)-4, ".dbf") )
                continue;

            if( osLayerNameSet.find(osLayerName) != osLayerNameSet.end() )
                continue;

            // We don't want to access .dbf files with an associated .tab
            // file, or it will never get recognised as a mapinfo dataset.
            bool bFoundTAB = false;
            for( int iCan2 = 0; iCan2 < nCandidateCount; iCan2++ )
            {
                const char *pszCandidate2 = papszCandidates[iCan2];

                if( EQUALN(pszCandidate2, pszLayerName, strlen(pszLayerName))
                    && EQUAL(pszCandidate2 + strlen(pszLayerName), ".tab") )
                    bFoundTAB = true;
            }

            if( bFoundTAB )
                continue;

            char *pszFilename =
                CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));

            osLayerNameSet.insert(osLayerName);

#ifdef IMMEDIATE_OPENING
            if( !OpenFile( pszFilename, bUpdate )
                && !bTestOpen )
            {
                CPLError(
                    CE_Failure, CPLE_OpenFailed,
                    "Failed to open dbf file %s.  "
                    "It may be corrupt or read-only file accessed in "
                    "update mode.",
                    pszFilename );
                CPLFree( pszFilename );
                CSLDestroy( papszCandidates );
                return false;
            }
#else
            oVectorLayerName.push_back(pszFilename);
#endif
            CPLFree( pszFilename );
        }

        CSLDestroy( papszCandidates );

#ifdef IMMEDIATE_OPENING
        const int nDirLayers = nLayers;
#else
        const int nDirLayers = static_cast<int>(oVectorLayerName.size());
#endif

        CPLErrorReset();

        return nDirLayers > 0 || !bTestOpen;
    }
}
Example #8
0
/**********************************************************************
 *                     TABAdjustCaseSensitiveFilename()
 *
 * Scan a filename and its path, adjust uppercase/lowercases if
 * necessary.
 *
 * Returns TRUE if file found, or FALSE if it could not be located with
 * a case-insensitive search.
 *
 * This function works on the original buffer and returns a reference to it.
 * It does nothing on Windows systems where filenames are not case sensitive.
 **********************************************************************/
static GBool TABAdjustCaseSensitiveFilename(char *
#ifndef _WIN32
                                            pszFname
#endif
                                            )
{

#ifdef _WIN32
    /*-----------------------------------------------------------------
     * Nothing to do on Windows
     *----------------------------------------------------------------*/
    return TRUE;

#else
    /*-----------------------------------------------------------------
     * Unix case.
     *----------------------------------------------------------------*/
    VSIStatBufL  sStatBuf;
    char        *pszTmpPath = NULL;
    int         nTotalLen, iTmpPtr;
    GBool       bValidPath;

    /*-----------------------------------------------------------------
     * First check if the filename is OK as is.
     *----------------------------------------------------------------*/
    if (VSIStatL(pszFname, &sStatBuf) == 0)
    {
        return TRUE;
    }

    /*-----------------------------------------------------------------
     * OK, file either does not exist or has the wrong cases... we'll
     * go backwards until we find a portion of the path that is valid.
     *----------------------------------------------------------------*/
    pszTmpPath = CPLStrdup(pszFname);
    nTotalLen = static_cast<int>(strlen(pszTmpPath));
    iTmpPtr = nTotalLen;
    bValidPath = FALSE;

    while(iTmpPtr > 0 && !bValidPath)
    {
        /*-------------------------------------------------------------
         * Move back to the previous '/' separator
         *------------------------------------------------------------*/
        pszTmpPath[--iTmpPtr] = '\0';
        while( iTmpPtr > 0 && pszTmpPath[iTmpPtr-1] != '/' )
        {
            pszTmpPath[--iTmpPtr] = '\0';
        }

        if (iTmpPtr > 0 && VSIStatL(pszTmpPath, &sStatBuf) == 0)
            bValidPath = TRUE;
    }

    CPLAssert(iTmpPtr >= 0);

    /*-----------------------------------------------------------------
     * Assume that CWD is valid... so an empty path is a valid path
     *----------------------------------------------------------------*/
    if (iTmpPtr == 0)
        bValidPath = TRUE;

    /*-----------------------------------------------------------------
     * OK, now that we have a valid base, reconstruct the whole path
     * by scanning all the sub-directories.
     * If we get to a point where a path component does not exist then
     * we simply return the rest of the path as is.
     *----------------------------------------------------------------*/
    while(bValidPath && (int)strlen(pszTmpPath) < nTotalLen)
    {
        char    **papszDir=NULL;
        int     iEntry, iLastPartStart;

        iLastPartStart = iTmpPtr;
        papszDir = VSIReadDir(pszTmpPath);

        /*-------------------------------------------------------------
         * Add one component to the current path
         *------------------------------------------------------------*/
        pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
        iTmpPtr++;
        for( ; pszFname[iTmpPtr] != '\0' && pszFname[iTmpPtr]!='/'; iTmpPtr++)
        {
            pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
        }

        while(iLastPartStart < iTmpPtr && pszTmpPath[iLastPartStart] == '/')
            iLastPartStart++;

        /*-------------------------------------------------------------
         * And do a case insensitive search in the current dir...
         *------------------------------------------------------------*/
        for(iEntry=0; papszDir && papszDir[iEntry]; iEntry++)
        {
            if (EQUAL(pszTmpPath+iLastPartStart, papszDir[iEntry]))
            {
                /* Fount it! */
                strcpy(pszTmpPath+iLastPartStart, papszDir[iEntry]);
                break;
            }
        }

        if (iTmpPtr > 0 && VSIStatL(pszTmpPath, &sStatBuf) != 0)
            bValidPath = FALSE;

        CSLDestroy(papszDir);
    }

    /*-----------------------------------------------------------------
     * We reached the last valid path component... just copy the rest
     * of the path as is.
     *----------------------------------------------------------------*/
    if (iTmpPtr < nTotalLen-1)
    {
        strncpy(pszTmpPath+iTmpPtr, pszFname+iTmpPtr, nTotalLen-iTmpPtr);
    }

    /*-----------------------------------------------------------------
     * Update the source buffer and return.
     *----------------------------------------------------------------*/
    strcpy(pszFname, pszTmpPath);
    CPLFree(pszTmpPath);

    return bValidPath;

#endif
}
GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, GDALAccess eAccessIn,
                            char **papszSiblingsIn )

{
/* -------------------------------------------------------------------- */
/*      Ensure that C: is treated as C:\ so we can stat it on           */
/*      Windows.  Similar to what is done in CPLStat().                 */
/* -------------------------------------------------------------------- */
#ifdef WIN32
    if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' )
    {
        char    szAltPath[10];
        
        strcpy( szAltPath, pszFilenameIn );
        strcat( szAltPath, "\\" );
        pszFilename = CPLStrdup( szAltPath );
    }
    else
#endif
        pszFilename = CPLStrdup( pszFilenameIn );

/* -------------------------------------------------------------------- */
/*      Initialize.                                                     */
/* -------------------------------------------------------------------- */

    nHeaderBytes = 0;
    pabyHeader = NULL;
    bIsDirectory = FALSE;
    bStatOK = FALSE;
    eAccess = eAccessIn;
    fp = NULL;
    
/* -------------------------------------------------------------------- */
/*      Collect information about the file.                             */
/* -------------------------------------------------------------------- */
    VSIStatBufL  sStat;

    if( VSIStatL( pszFilename, &sStat ) == 0 )
    {
        bStatOK = TRUE;

        if( VSI_ISREG( sStat.st_mode ) )
        {
            pabyHeader = (GByte *) CPLCalloc(1025,1);

            fp = VSIFOpen( pszFilename, "rb" );

            if( fp != NULL )
            {
                nHeaderBytes = (int) VSIFRead( pabyHeader, 1, 1024, fp );

                VSIRewind( fp );
            }
            /* XXX: ENOENT is used to catch the case of virtual filesystem
             * when we do not have a real file with such a name. Under some
             * circumstances EINVAL reported instead of ENOENT in Windows
             * (for filenames containing colon, e.g. "smth://name"). 
             * See also: #2437 */
            else if( errno == 27 /* "File to large" */ 
                     || errno == ENOENT || errno == EINVAL
#ifdef EOVERFLOW
                     || errno == EOVERFLOW
#else
                     || errno == 75 /* Linux EOVERFLOW */
                     || errno == 79 /* Solaris EOVERFLOW */ 
#endif
                     )
            {
                fp = VSIFOpenL( pszFilename, "rb" );
                if( fp != NULL )
                {
                    nHeaderBytes = (int) VSIFReadL( pabyHeader, 1, 1024, fp );
                    VSIFCloseL( fp );
                    fp = NULL;
                }
            }
        }
        else if( VSI_ISDIR( sStat.st_mode ) )
            bIsDirectory = TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Capture sibling list either from passed in values, or by        */
/*      scanning for them.                                              */
/* -------------------------------------------------------------------- */
    if( papszSiblingsIn != NULL )
    {
        papszSiblingFiles = CSLDuplicate( papszSiblingsIn );
    }
    else if( bStatOK && !bIsDirectory )
    {
        if( CSLTestBoolean( 
                CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" )) )
        {
            /* skip reading the directory */
            papszSiblingFiles = NULL;
        }
        else
        {
            CPLString osDir = CPLGetDirname( pszFilename );
            papszSiblingFiles = VSIReadDir( osDir );
        }
    }
    else
        papszSiblingFiles = NULL;
}
GDALOpenInfo::GDALOpenInfo(const char *pszFilenameIn, GDALAccess eAccessIn,
                           char **papszSiblingsIn)

{
/* -------------------------------------------------------------------- */
/*      Ensure that C: is treated as C:\ so we can stat it on           */
/*      Windows.  Similar to what is done in CPLStat().                 */
/* -------------------------------------------------------------------- */
#ifdef WIN32
    if (strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':')
    {
        char szAltPath[10];

        strcpy(szAltPath, pszFilenameIn);
        strcat(szAltPath, "\\");
        pszFilename = CPLStrdup(szAltPath);
    }
    else
#endif
    pszFilename = CPLStrdup(pszFilenameIn);

/* -------------------------------------------------------------------- */
/*      Initialize.                                                     */
/* -------------------------------------------------------------------- */

    nHeaderBytes = 0;
    pabyHeader   = NULL;
    bIsDirectory = FALSE;
    bStatOK      = FALSE;
    eAccess      = eAccessIn;
    fp           = NULL;

#ifdef HAVE_READLINK
    int bHasRetried = FALSE;
#endif

/* -------------------------------------------------------------------- */
/*      Collect information about the file.                             */
/* -------------------------------------------------------------------- */
    VSIStatBufL sStat;

#ifdef HAVE_READLINK
retry:
#endif
    if (VSIStatExL(pszFilename, &sStat,
                   VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0)
    {
        bStatOK = TRUE;

        if (VSI_ISREG(sStat.st_mode))
        {
            pabyHeader = (GByte*) CPLCalloc(1025, 1);

            fp = VSIFOpen(pszFilename, "rb");

            if (fp != NULL)
            {
                nHeaderBytes = (int) VSIFRead(pabyHeader, 1, 1024, fp);

                VSIRewind(fp);
            }
            /* XXX: ENOENT is used to catch the case of virtual filesystem
             * when we do not have a real file with such a name. Under some
             * circumstances EINVAL reported instead of ENOENT in Windows
             * (for filenames containing colon, e.g. "smth://name").
             * See also: #2437 */
            else if (errno == 27 /* "File to large" */
                     || errno == ENOENT || errno == EINVAL
#ifdef EOVERFLOW
                     || errno == EOVERFLOW
#else
                     || errno == 75 /* Linux EOVERFLOW */
                     || errno == 79 /* Solaris EOVERFLOW */
#endif
                     )
            {
                VSILFILE *fpL = VSIFOpenL(pszFilename, "rb");
                if (fpL != NULL)
                {
                    nHeaderBytes = (int) VSIFReadL(pabyHeader, 1, 1024, fpL);
                    VSIFCloseL(fpL);
                }
            }
        }
        else if (VSI_ISDIR(sStat.st_mode))
            bIsDirectory = TRUE;
    }

#ifdef HAVE_READLINK
    else if (!bHasRetried)
    {
        /* If someone creates a file with "ln -sf /vsicurl/http://download.osgeo.org/gdal/data/gtiff/utm.tif my_remote_utm.tif" */
        /* we will be able to open it by passing my_remote_utm.tif */
        /* This helps a lot for GDAL based readers that only provide file explorers to open datasets */
        char szPointerFilename[2048];
        int  nBytes = readlink(pszFilename, szPointerFilename, sizeof(szPointerFilename));
        if (nBytes != -1)
        {
            szPointerFilename[MIN(nBytes, (int)sizeof(szPointerFilename) - 1)] = 0;
            CPLFree(pszFilename);
            pszFilename     = CPLStrdup(szPointerFilename);
            papszSiblingsIn = NULL;
            bHasRetried     = TRUE;
            goto retry;
        }
    }
#endif

/* -------------------------------------------------------------------- */
/*      Capture sibling list either from passed in values, or by        */
/*      scanning for them.                                              */
/* -------------------------------------------------------------------- */
    if (papszSiblingsIn != NULL)
    {
        papszSiblingFiles = CSLDuplicate(papszSiblingsIn);
    }
    else if (bStatOK && !bIsDirectory)
    {
        const char *pszOptionVal =
            CPLGetConfigOption("GDAL_DISABLE_READDIR_ON_OPEN", "NO");
        if (EQUAL(pszOptionVal, "EMPTY_DIR"))
        {
            papszSiblingFiles = CSLAddString(NULL, CPLGetFilename(pszFilename));
        }
        else if (CSLTestBoolean(pszOptionVal))
        {
            /* skip reading the directory */
            papszSiblingFiles = NULL;
        }
        else
        {
            CPLString osDir = CPLGetDirname(pszFilename);
            papszSiblingFiles = VSIReadDir(osDir);
        }
    }
    else
        papszSiblingFiles = NULL;
}
Example #11
0
int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
                              char ** papszLimitedFileList )

{
    pszName = CPLStrdup( pszFilename );

/* -------------------------------------------------------------------- */
/*      Is the given path a directory or a regular file?                */
/* -------------------------------------------------------------------- */
    VSIStatBufL stat;

    if( VSIStatExL( pszFilename, &stat,
                    VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0
        || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
    {
        if( !bTestOpen )
            CPLError( CE_Failure, CPLE_AppDefined,
                   "%s is neither a file or directory, Tiger access failed.\n",
                      pszFilename );

        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Build a list of filenames we figure are Tiger files.            */
/* -------------------------------------------------------------------- */
    char **papszFileList = nullptr;
    if( VSI_ISREG(stat.st_mode) )
    {
        char       szModule[128];

        if( strlen(CPLGetFilename(pszFilename)) == 0 )
        {
            return FALSE;
        }

        pszPath = CPLStrdup( CPLGetPath(pszFilename) );

        strncpy( szModule, CPLGetFilename(pszFilename), sizeof(szModule)-1 );
        /* Make sure the buffer is 0 terminated */
        szModule[sizeof(szModule)-1] = '\0';

        /* And now remove last character of filename */
        szModule[strlen(szModule)-1] = '\0';

        papszFileList = CSLAddString( papszFileList, szModule );
    }
    else
    {
        char **candidateFileList = VSIReadDir( pszFilename );

        pszPath = CPLStrdup( pszFilename );

        for( int i = 0;
             candidateFileList != nullptr && candidateFileList[i] != nullptr;
             i++ )
        {
            size_t nCandidateLen = strlen(candidateFileList[i]);

            if( papszLimitedFileList != nullptr
                && CSLFindString(papszLimitedFileList,
                                 CPLGetBasename(candidateFileList[i])) == -1 )
            {
                continue;
            }

            if( nCandidateLen > 4
                && candidateFileList[i][nCandidateLen-4] == '.'
                && candidateFileList[i][nCandidateLen-1] == '1')
            {
                char       szModule[128];

                snprintf( szModule, sizeof(szModule), "%s",
                          candidateFileList[i] );
                const size_t nLen = strlen(szModule);
                if( nLen )
                    szModule[nLen-1] = '\0';

                papszFileList = CSLAddString(papszFileList, szModule);
            }
        }

        CSLDestroy( candidateFileList );

        if( CSLCount(papszFileList) == 0 )
        {
            if( !bTestOpen )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "No candidate Tiger files (TGR*.RT1) found in\n"
                          "directory: %s",
                          pszFilename );
            CSLDestroy(papszFileList);
            return FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      Loop over all these files trying to open them.  In testopen     */
/*      mode we first read the first 80 characters, to verify that      */
/*      it looks like an Tiger file.  Note that we don't keep the file  */
/*      open ... we don't want to occupy a lot of file handles when      */
/*      handling a whole directory.                                     */
/* -------------------------------------------------------------------- */
    papszModules = nullptr;

    for( int i = 0; papszFileList && papszFileList[i] != nullptr; i++ )
    {
        if( bTestOpen || i == 0 )
        {
            char *l_pszFilename = BuildFilename( papszFileList[i], "1" );

            VSILFILE *fp = VSIFOpenL( l_pszFilename, "rb" );
            CPLFree( l_pszFilename );

            if( fp == nullptr )
                continue;

            char szHeader[500] = {};
            if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
            {
                VSIFCloseL( fp );
                continue;
            }

            VSIFCloseL( fp );

            char *pszRecStart = szHeader;
            szHeader[sizeof(szHeader)-1] = '\0';

            bool bIsGDT = false;

            if( STARTS_WITH_CI(pszRecStart, "Copyright (C)")
                && strstr(pszRecStart,"Geographic Data Tech") != nullptr )
            {
                bIsGDT = true;

                while( *pszRecStart != '\0'
                       && *pszRecStart != 10
                       && *pszRecStart != 13 )
                    pszRecStart++;

                while( *pszRecStart == 10 || *pszRecStart == 13 )
                    pszRecStart++;
            }

            if( pszRecStart[0] != '1' )
                continue;

            if( !isdigit(pszRecStart[1]) || !isdigit(pszRecStart[2])
                || !isdigit(pszRecStart[3]) || !isdigit(pszRecStart[4]) )
                continue;

            nVersionCode = atoi(TigerFileBase::GetField( pszRecStart, 2, 5 ));
            nVersion = TigerClassifyVersion( nVersionCode );
            nVersion = TigerCheckVersion( nVersion, papszFileList[i] );

            CPLDebug( "OGR", "Tiger Version Code=%d, Classified as %s ",
                      nVersionCode, TigerVersionString(nVersion) );

            if(    nVersionCode !=  0
                && nVersionCode !=  2
                && nVersionCode !=  3
                && nVersionCode !=  5
                && nVersionCode != 21
                && nVersionCode != 24
                && pszRecStart[3]  != '9'
                && pszRecStart[3]  != DIGIT_ZERO
                && !bIsGDT )
                continue;

            // we could (and should) add a bunch more validation here.
        }

        papszModules = CSLAddString( papszModules, papszFileList[i] );
    }

    CSLDestroy( papszFileList );

    nModules = CSLCount( papszModules );

    if( nModules == 0 || papszModules == nullptr )
    {
        if( !bTestOpen )
        {
            if( VSI_ISREG(stat.st_mode) )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "No TIGER/Line files (TGR*.RT1) found in\n"
                          "directory: %s",
                          pszFilename );
            else
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "File %s does not appear to be a TIGER/Line .RT1 file.",
                          pszFilename );
        }

        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Do we have a user provided version override?                    */
/* -------------------------------------------------------------------- */
    const char *pszRequestedVersion =
            CPLGetConfigOption( "TIGER_VERSION", nullptr );
    if( pszRequestedVersion != nullptr )
    {

        if( STARTS_WITH_CI(pszRequestedVersion, "TIGER_") )
        {
            int iCode = 1;  // Used after for.

            for( ; iCode < TIGER_Unknown; iCode++ )
            {
                if( EQUAL(TigerVersionString((TigerVersion)iCode),
                          pszRequestedVersion) )
                {
                    nVersion = (TigerVersion) iCode;
                    break;
                }
            }

            if( iCode == TIGER_Unknown )
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                          "Failed to recognise TIGER_VERSION setting: %s",
                          pszRequestedVersion );
                return FALSE;
            }

            CPLDebug( "OGR", "OVERRIDE Tiger Version %s ",
                      TigerVersionString(nVersion) );
        }
        else
        {
            nVersionCode = atoi(pszRequestedVersion);
            nVersion = TigerClassifyVersion( nVersionCode );

            CPLDebug( "OGR",
                      "OVERRIDE Tiger Version Code=%d, Classified as %s ",
                      nVersionCode, TigerVersionString(nVersion) );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create the layers which appear to exist.                        */
/* -------------------------------------------------------------------- */
    // RT1, RT2, RT3
    AddLayer( new OGRTigerLayer( this,
                                 new TigerCompleteChain( this,
                                                         papszModules[0]) ));

    /* should we have kept track of whether we encountered an RT4 file? */
    // RT4
    AddLayer( new OGRTigerLayer( this,
                                 new TigerAltName( this,
                                                   papszModules[0]) ));

    // RT5
    AddLayer( new OGRTigerLayer( this,
                                 new TigerFeatureIds( this,
                                                      papszModules[0]) ));

    // RT6
    AddLayer( new OGRTigerLayer( this,
                                 new TigerZipCodes( this,
                                                    papszModules[0]) ));
    // RT7
    AddLayer( new OGRTigerLayer( this,
                                 new TigerLandmarks( this,
                                                     papszModules[0]) ));

    // RT8
    AddLayer( new OGRTigerLayer( this,
                                 new TigerAreaLandmarks( this,
                                                     papszModules[0]) ));

    // RT9
    if (nVersion < TIGER_2002) {
      AddLayer( new OGRTigerLayer( this,
                                   new TigerKeyFeatures( this,
                                                         papszModules[0]) ));
    }

    // RTA, RTS
    AddLayer( new OGRTigerLayer( this,
                                 new TigerPolygon( this,
                                                   papszModules[0]) ));

    // RTB
    if (nVersion >= TIGER_2002) {
      AddLayer( new OGRTigerLayer( this,
                                   new TigerPolygonCorrections( this,
                                                                papszModules[0]) ));
    }

    // RTC
    AddLayer( new OGRTigerLayer( this,
                                 new TigerEntityNames( this,
                                                       papszModules[0]) ));

    // RTE
    if (nVersion >= TIGER_2002) {
      AddLayer( new OGRTigerLayer( this,
                                   new TigerPolygonEconomic( this,
                                                             papszModules[0]) ));
    }

    // RTH
    AddLayer( new OGRTigerLayer( this,
                                 new TigerIDHistory( this,
                                                     papszModules[0]) ));

    // RTI
    AddLayer( new OGRTigerLayer( this,
                                 new TigerPolyChainLink( this,
                                                       papszModules[0]) ));

    // RTM
    AddLayer( new OGRTigerLayer( this,
                                 new TigerSpatialMetadata( this,
                                                           papszModules[0] ) ) );

    // RTP
    AddLayer( new OGRTigerLayer( this,
                                 new TigerPIP( this,
                                               papszModules[0]) ));

    // RTR
    AddLayer( new OGRTigerLayer( this,
                                 new TigerTLIDRange( this,
                                                     papszModules[0]) ));

    // RTT
    if (nVersion >= TIGER_2002) {
      AddLayer( new OGRTigerLayer( this,
                                   new TigerZeroCellID( this,
                                                        papszModules[0]) ));
    }

    // RTU
    if (nVersion >= TIGER_2002) {
      AddLayer( new OGRTigerLayer( this,
                                   new TigerOverUnder( this,
                                                       papszModules[0]) ));
    }

    // RTZ
    AddLayer( new OGRTigerLayer( this,
                                 new TigerZipPlus4( this,
                                                     papszModules[0]) ));

    return TRUE;
}
int OGROpenFileGDBDataSource::Open( const char* pszFilename )

{
    FileGDBTable oTable;

    m_pszName = CPLStrdup(pszFilename);

    m_osDirName = pszFilename;
    int nInterestTable = -1;
    const char* pszFilenameWithoutPath = CPLGetFilename(pszFilename);
    if( strlen(pszFilenameWithoutPath) == strlen("a00000000.gdbtable") &&
        pszFilenameWithoutPath[0] == 'a' &&
        sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &nInterestTable) == 1 )
    {
        m_osDirName = CPLGetPath(m_osDirName);
    }
    else
    {
        nInterestTable = -1;
    }

    if( EQUAL(CPLGetExtension(m_osDirName), "zip") &&
        strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) != 0 )
    {
        m_osDirName = "/vsizip/" + m_osDirName;
    }
    else  if( EQUAL(CPLGetExtension(m_osDirName), "tar") &&
        strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) != 0 )
    {
        m_osDirName = "/vsitar/" + m_osDirName;
    }

    if( strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) == 0 ||
        strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) == 0)
    {
        /* Look for one subdirectory ending with .gdb extension */
        char** papszDir = CPLReadDir(m_osDirName);
        int iCandidate = -1;
        for( int i=0; papszDir && papszDir[i] != NULL; i++ )
        {
            VSIStatBufL sStat;
            if( EQUAL(CPLGetExtension(papszDir[i]), "gdb") &&
                VSIStatL( CPLSPrintf("%s/%s", m_osDirName.c_str(), papszDir[i]), &sStat ) == 0 &&
                VSI_ISDIR(sStat.st_mode) )
            {
                if( iCandidate < 0 )
                    iCandidate = i;
                else
                {
                    iCandidate = -1;
                    break;
                }
            }
        }
        if( iCandidate >= 0 )
        {
            m_osDirName += "/";
            m_osDirName += papszDir[iCandidate];
        }
        CSLDestroy(papszDir);
    }

    m_papszFiles = VSIReadDir(m_osDirName);

    /* Explore catalog table */
    const char* psza00000001 = CPLFormFilename(m_osDirName, "a00000001", "gdbtable");
    if( !FileExists(psza00000001) || !oTable.Open(psza00000001) )
    {
        if( nInterestTable >= 0 && FileExists(m_pszName) )
        {
            const char* pszLyrName = CPLSPrintf("a%08x", nInterestTable);
            OGROpenFileGDBLayer* poLayer = new OGROpenFileGDBLayer(
                                m_pszName, pszLyrName, "", "");
            const char* pszTablX = CPLResetExtension(m_pszName, "gdbtablx");
            if( (!FileExists(pszTablX) &&
                 poLayer->GetLayerDefn()->GetFieldCount() == 0 &&
                 poLayer->GetFeatureCount() == 0) ||
                !poLayer->IsValidLayerDefn() )
            {
                delete poLayer;
                return FALSE;
            }
            m_apoLayers.push_back(poLayer);
            return TRUE;
        }
        return FALSE;
    }

    if( !(oTable.GetFieldCount() >= 2 &&
          oTable.GetField(0)->GetName() == "Name" &&
          oTable.GetField(0)->GetType() == FGFT_STRING &&
          oTable.GetField(1)->GetName() == "FileFormat" &&
          (oTable.GetField(1)->GetType() == FGFT_INT16 ||
           oTable.GetField(1)->GetType() == FGFT_INT32) ) )
    {
        return FALSE;
    }

    int iGDBItems = -1; /* V10 */
    int iGDBFeatureClasses = -1; /* V9.X */
    int iGDBObjectClasses = -1; /* V9.X */
    int i;

    std::vector<std::string> aosTableNames;
    for(i=0;i<oTable.GetTotalRecordCount();i++)
    {
        if( !oTable.SelectRow(i) )
        {
            if( oTable.HasGotError() )
                break;
            aosTableNames.push_back("");
            continue;
        }

        const OGRField* psField = oTable.GetFieldValue(0);
        if( psField != NULL )
        {
            aosTableNames.push_back(psField->String);

            if( strcmp(psField->String, "GDB_Items") == 0 )
            {
                iGDBItems = i;
            }
            else if( strcmp(psField->String, "GDB_FeatureClasses") == 0 )
            {
                iGDBFeatureClasses = i;
            }
            else if( strcmp(psField->String, "GDB_ObjectClasses") == 0 )
            {
                iGDBObjectClasses = i;
            }
            m_osMapNameToIdx[psField->String] = 1 + i;
        }
        else
        {
            aosTableNames.push_back("");
        }
    }

    oTable.Close();

    if( iGDBItems >= 0 )
    {
        int bRet = OpenFileGDBv10(iGDBItems,
                                  nInterestTable);
        if( !bRet )
            return FALSE;
    }
    else if( iGDBFeatureClasses >= 0 && iGDBObjectClasses >= 0 )
    {
        int bRet = OpenFileGDBv9(iGDBFeatureClasses,
                                 iGDBObjectClasses,
                                 nInterestTable);
        if( !bRet )
            return FALSE;
    }
    else
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "No GDB_Items nor GDB_FeatureClasses table");
        return FALSE;
    }

    if( m_apoLayers.size() == 0 && nInterestTable >= 0 )
    {
        if( FileExists(m_pszName) )
        {
            const char* pszLyrName;
            if( nInterestTable <= (int)aosTableNames.size()  &&
                aosTableNames[nInterestTable-1].size() != 0 )
                pszLyrName = aosTableNames[nInterestTable-1].c_str();
            else
                pszLyrName = CPLSPrintf("a%08x", nInterestTable);
            m_apoLayers.push_back(new OGROpenFileGDBLayer(
                m_pszName, pszLyrName, "", ""));
        }
        else
        {
            return FALSE;
        }
    }

    return TRUE;
}
Example #13
0
// Unix case.
static bool TABAdjustCaseSensitiveFilename(char *pszFname)
{
    VSIStatBufL sStatBuf;

    // First check if the filename is OK as is.
    if (VSIStatL(pszFname, &sStatBuf) == 0)
    {
        return true;
    }

    // File either does not exist or has the wrong cases.
    // Go backwards until we find a portion of the path that is valid.
    char *pszTmpPath = CPLStrdup(pszFname);
    const int nTotalLen = static_cast<int>(strlen(pszTmpPath));
    int iTmpPtr = nTotalLen;
    GBool bValidPath = false;

    while(iTmpPtr > 0 && !bValidPath)
    {
        // Move back to the previous '/' separator.
        pszTmpPath[--iTmpPtr] = '\0';
        while( iTmpPtr > 0 && pszTmpPath[iTmpPtr-1] != '/' )
        {
            pszTmpPath[--iTmpPtr] = '\0';
        }

        if (iTmpPtr > 0 && VSIStatL(pszTmpPath, &sStatBuf) == 0)
            bValidPath = true;
    }

    CPLAssert(iTmpPtr >= 0);

    // Assume that CWD is valid.  Therefor an empty path is a valid.
    if (iTmpPtr == 0)
        bValidPath = true;

    // Now that we have a valid base, reconstruct the whole path
    // by scanning all the sub-directories.
    // If we get to a point where a path component does not exist then
    // we simply return the rest of the path as is.
    while(bValidPath && (int)strlen(pszTmpPath) < nTotalLen)
    {
        int iLastPartStart = iTmpPtr;
        char **papszDir = VSIReadDir(pszTmpPath);

        // Add one component to the current path.
        pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
        iTmpPtr++;
        for( ; pszFname[iTmpPtr] != '\0' && pszFname[iTmpPtr]!='/'; iTmpPtr++)
        {
            pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
        }

        while(iLastPartStart < iTmpPtr && pszTmpPath[iLastPartStart] == '/')
            iLastPartStart++;

        // And do a case insensitive search in the current dir.
        for(int iEntry = 0; papszDir && papszDir[iEntry]; iEntry++)
        {
            if (EQUAL(pszTmpPath + iLastPartStart, papszDir[iEntry]))
            {
                // Fount it.
                strcpy(pszTmpPath+iLastPartStart, papszDir[iEntry]);
                break;
            }
        }

        if (iTmpPtr > 0 && VSIStatL(pszTmpPath, &sStatBuf) != 0)
            bValidPath = false;

        CSLDestroy(papszDir);
    }

    // We reached the last valid path component... just copy the rest
    // of the path as is.
    if (iTmpPtr < nTotalLen-1)
    {
        strncpy(pszTmpPath+iTmpPtr, pszFname+iTmpPtr, nTotalLen-iTmpPtr);
    }

    // Update the source buffer and return.
    strcpy(pszFname, pszTmpPath);
    CPLFree(pszTmpPath);

    return bValidPath;
}
Example #14
0
OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
{
    CPLMutexHolderOptionalLockD(hMutex);

    bOutHasReopenedDS = FALSE;


    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
    if( !pConnection->IsLocked() )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "No transaction in progress");
        return OGRERR_FAILURE;
    }

    bOutHasReopenedDS = TRUE;

    CPLString osName(poMutexedDS->GetName());
    CPLString osNameOri(osName);
    if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
        osName.resize(osName.size()-1);

#ifndef WIN32
    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
#endif

    pConnection->m_nRefCount ++;
    delete poDSInOut;
    poDSInOut = NULL;
    poMutexedDS = NULL;
    poDS = NULL;

    pConnection->CloseGeodatabase();

    CPLString osEditedName(osName);
    osEditedName += ".ogredited";
    
#ifndef WIN32
    if( bPerLayerCopyingForTransaction )
    {
        int bError = FALSE;
        char** papszFiles;
        std::vector<CPLString> aosTmpFilesToClean;
        
        // Check for files present in original copy that are not in edited copy
        // That is to say deleted layers
        papszFiles = VSIReadDir(osName);
        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
        {
            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
                continue;
            VSIStatBufL sStat;
            if( (*papszIter)[0] == 'a' &&
                VSIStatL( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
            {
                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
                    VSIRename( CPLFormFilename(osName, *papszIter, NULL),
                               CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
                {
                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
                             CPLFormFilename(osName, *papszIter, NULL),
                             CPLFormFilename(osName, *papszIter, "tmp"));
                    bError = TRUE;
                }
                else
                    aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
            }
        }
        CSLDestroy(papszFiles);

        // Move modified files from edited directory to main directory
        papszFiles = VSIReadDir(osEditedName);
        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
        {
            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
                continue;
            struct stat sStat;
            if( lstat( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
            {
                CPLError(CE_Failure, CPLE_AppDefined, "Cannot stat %s",
                         CPLFormFilename(osEditedName, *papszIter, NULL));
                bError = TRUE;
            }
            else if( !S_ISLNK(sStat.st_mode) )
            {
                // If there was such a file in original directory, first rename it
                // as a temporary file
                if( lstat( CPLFormFilename(osName, *papszIter, NULL), &sStat ) == 0 )
                {
                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
                        VSIRename( CPLFormFilename(osName, *papszIter, NULL),
                                   CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
                    {
                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
                                 CPLFormFilename(osName, *papszIter, NULL),
                                 CPLFormFilename(osName, *papszIter, "tmp"));
                        bError = TRUE;
                    }
                    else
                        aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
                }
                if( !bError )
                {
                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
                        CPLMoveFile( CPLFormFilename(osName, *papszIter, NULL),
                                     CPLFormFilename(osEditedName, *papszIter, NULL) ) != 0 )
                    {
                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot move %s to %s",
                                 CPLFormFilename(osEditedName, *papszIter, NULL),
                                 CPLFormFilename(osName, *papszIter, NULL));
                        bError = TRUE;
                    }
                    else
                        CPLDebug("FileGDB", "Move %s to %s",
                                 CPLFormFilename(osEditedName, *papszIter, NULL),
                                 CPLFormFilename(osName, *papszIter, NULL));
                }
            }
        }
        CSLDestroy(papszFiles);

        if( !bError )
        {
            for(size_t i=0;i<aosTmpFilesToClean.size();i++)
            {
                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") || 
                    VSIUnlink(aosTmpFilesToClean[i]) != 0 )
                {
                    CPLError(CE_Warning, CPLE_AppDefined,
                             "Cannot remove %s. Manual cleanup required", aosTmpFilesToClean[i].c_str());
                }
            }
        }

        if( bError )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "An error occurred while moving files from %s back to %s. "
                     "Manual cleaning must be done and dataset should be closed",
                     osEditedName.c_str(),
                     osName.c_str());
            pConnection->SetLocked(FALSE);
            Release(osName);
            return OGRERR_FAILURE;
        }
        else if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE5") || 
                 CPLUnlinkTree(osEditedName) != 0 )
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                    "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
        }
    }
    else
#endif
    {
        CPLString osTmpName(osName);
        osTmpName += ".ogrtmp";
        
        /* Install the backup copy as the main database in 3 steps : */
        /* first rename the main directory  in .tmp */
        /* then rename the edited copy under regular name */
        /* and finally dispose the .tmp directory */
        /* That way there's no risk definitely losing data */
        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
            VSIRename(osName, osTmpName) != 0 )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                    "Cannot rename %s to %s. Edited database during transaction is in %s"
                    "Dataset should be closed",
                    osName.c_str(), osTmpName.c_str(), osEditedName.c_str());
            pConnection->SetLocked(FALSE);
            Release(osName);
            return OGRERR_FAILURE;
        }
        
        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
            VSIRename(osEditedName, osName) != 0 )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                    "Cannot rename %s to %s. The original geodatabase is in '%s'. "
                    "Dataset should be closed",
                    osEditedName.c_str(), osName.c_str(), osTmpName.c_str());
            pConnection->SetLocked(FALSE);
            Release(osName);
            return OGRERR_FAILURE;
        }

        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
            CPLUnlinkTree(osTmpName) != 0 )
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                    "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
        }
    }

    pConnection->m_pGeodatabase = new Geodatabase;
    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE_REOPEN") || FAILED(hr))
    {
        delete pConnection->m_pGeodatabase;
        pConnection->m_pGeodatabase = NULL;
        pConnection->SetLocked(FALSE);
        Release(osName);
        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
        return OGRERR_FAILURE;
    }

    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
    pDS->Open(osNameOri, TRUE, NULL);
    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);

    pConnection->SetLocked(FALSE);

    return OGRERR_NONE;
}
Example #15
0
OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
{
    CPLMutexHolderOptionalLockD(hMutex);

    bOutHasReopenedDS = FALSE;

    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
    if( !poDS->GetUpdate() )
        return OGRERR_FAILURE;
    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
    if( pConnection->GetRefCount() != 1 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Cannot start transaction as database is opened in another connection");
        return OGRERR_FAILURE;
    }
    if( pConnection->IsLocked() )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Transaction is already in progress");
        return OGRERR_FAILURE;
    }

    bOutHasReopenedDS = TRUE;

    CPLString osName(poMutexedDS->GetName());
    CPLString osNameOri(osName);
    if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
        osName.resize(osName.size()-1);

#ifndef WIN32
    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
#endif

    pConnection->m_nRefCount ++;
    delete poDSInOut;
    poDSInOut = NULL;
    poMutexedDS = NULL;
    poDS = NULL;

    pConnection->CloseGeodatabase();

    CPLString osEditedName(osName);
    osEditedName += ".ogredited";

    CPLPushErrorHandler(CPLQuietErrorHandler);
    CPL_IGNORE_RET_VAL(CPLUnlinkTree(osEditedName));
    CPLPopErrorHandler();

    OGRErr eErr = OGRERR_NONE;
    
    CPLString osDatabaseToReopen;
#ifndef WIN32
    if( bPerLayerCopyingForTransaction )
    {
        int bError = FALSE;
        
        if( VSIMkdir( osEditedName, 0755 ) != 0 )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Cannot create directory '%s'.",
                      osEditedName.c_str() );
            bError = TRUE;
        }

        // Only copy a0000000X.Y files with X >= 1 && X <= 8, gdb and timestamps
        // and symlink others
        char** papszFiles = VSIReadDir(osName);
        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
        {
            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
                continue;
            if( ((*papszIter)[0] == 'a' && atoi((*papszIter)+1) >= 1 &&
                 atoi((*papszIter)+1) <= 8) || EQUAL(*papszIter, "gdb") ||
                 EQUAL(*papszIter, "timestamps") )
            {
                if( CPLCopyFile(CPLFormFilename(osEditedName, *papszIter, NULL),
                                CPLFormFilename(osName, *papszIter, NULL)) != 0 )
                {
                    bError = TRUE;
                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Cannot copy %s", *papszIter);
                }
            }
            else
            {
                CPLString osSourceFile;
                if( CPLIsFilenameRelative(osName) )
                    osSourceFile = CPLFormFilename(CPLSPrintf("../%s", CPLGetFilename(osName.c_str())), *papszIter, NULL);
                else
                    osSourceFile = osName;
                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
                    CPLSymlink( osSourceFile,
                                CPLFormFilename(osEditedName.c_str(), *papszIter, NULL),
                                NULL ) != 0 )
                {
                    bError = TRUE;
                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Cannot symlink %s", *papszIter);
                }
            }
        }
        CSLDestroy(papszFiles);

        if( bError )
        {
            eErr = OGRERR_FAILURE;
            osDatabaseToReopen = osName;
        }
        else
            osDatabaseToReopen = osEditedName;
    }
    else
#endif
    {
        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
            CPLCopyTree( osEditedName, osName ) != 0 )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                    "Cannot backup geodatabase");
            eErr = OGRERR_FAILURE;
            osDatabaseToReopen = osName;
        }
        else
            osDatabaseToReopen = osEditedName;
    }

    pConnection->m_pGeodatabase = new Geodatabase;
    long hr = ::OpenGeodatabase(StringToWString(osDatabaseToReopen), *(pConnection->m_pGeodatabase));
    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || FAILED(hr))
    {
        delete pConnection->m_pGeodatabase;
        pConnection->m_pGeodatabase = NULL;
        Release(osName);
        GDBErr(hr, CPLSPrintf("Failed to open %s. Dataset should be closed",
                              osDatabaseToReopen.c_str()));

        return OGRERR_FAILURE;
    }

    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
    pDS->Open(osDatabaseToReopen, TRUE, osNameOri);

#ifndef WIN32
    if( eErr == OGRERR_NONE && bPerLayerCopyingForTransaction )
    {
        pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
        pDS->SetSymlinkFlagOnAllLayers();
    }
#endif

    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);

    if( eErr == OGRERR_NONE )
        pConnection->SetLocked(TRUE);
    return eErr;
}