Skip to content

Commit

Permalink
Shape driver: in creation, uses w+b file opening mode instead of wb f…
Browse files Browse the repository at this point in the history
…ollowed by r+b, to support network file systems having sequential write only and when using CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE=YES (fixes OSGeo#7801)
  • Loading branch information
rouault committed May 22, 2023
1 parent 5b243ea commit e9f9842
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 23 deletions.
13 changes: 1 addition & 12 deletions ogr/ogrsf_frmts/shape/dbfopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,18 +680,7 @@ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
/* -------------------------------------------------------------------- */
/* Create the file. */
/* -------------------------------------------------------------------- */
SAFile fp = psHooks->FOpen(pszFullname, "wb");
if (fp == SHPLIB_NULLPTR)
{
free(pszFullname);
return SHPLIB_NULLPTR;
}

char chZero = '\0';
psHooks->FWrite(&chZero, 1, 1, fp);
psHooks->FClose(fp);

fp = psHooks->FOpen(pszFullname, "rb+");
SAFile fp = psHooks->FOpen(pszFullname, "wb+");
if (fp == SHPLIB_NULLPTR)
{
free(pszFullname);
Expand Down
2 changes: 1 addition & 1 deletion ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ OGRLayer *OGRShapeDataSource::ICreateLayer(const char *pszLayerName,
if (hDBF == nullptr)
{
CPLError(CE_Failure, CPLE_OpenFailed,
"Failed to open Shape DBF file `%s'.", pszFilename);
"Failed to create Shape DBF file `%s'.", pszFilename);
CPLFree(pszFilename);
CPLFree(pszFilenameWithoutExt);
SHPClose(hSHP);
Expand Down
43 changes: 33 additions & 10 deletions ogr/ogrsf_frmts/shape/shpopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,9 @@ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
pszFullname[nLenWithoutExtension] = 0;
snprintf(pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
pszFullname, pszFullname);
snprintf(pszMessage, nMessageLen,
"Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
pszFullname, pszAccess);
psHooks->Error(pszMessage);
free(pszMessage);

Expand Down Expand Up @@ -1027,7 +1028,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
SAFile fpSHP = psHooks->FOpen(pszFullname, "wb");
SAFile fpSHP = psHooks->FOpen(pszFullname, "w+b");
if (fpSHP == SHPLIB_NULLPTR)
{
char szErrorMsg[200];
Expand All @@ -1040,7 +1041,7 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
}

memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
SAFile fpSHX = psHooks->FOpen(pszFullname, "wb");
SAFile fpSHX = psHooks->FOpen(pszFullname, "w+b");
if (fpSHX == SHPLIB_NULLPTR)
{
char szErrorMsg[200];
Expand Down Expand Up @@ -1127,13 +1128,35 @@ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
return NULL;
}

/* -------------------------------------------------------------------- */
/* Close the files, and then open them as regular existing files. */
/* -------------------------------------------------------------------- */
psHooks->FClose(fpSHP);
psHooks->FClose(fpSHX);
SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));

psSHP->bUpdated = FALSE;
memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));

psSHP->fpSHP = fpSHP;
psSHP->fpSHX = fpSHX;
psSHP->nShapeType = nShapeType;
psSHP->nFileSize = 100;
psSHP->panRecOffset =
STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int)));
psSHP->panRecSize =
STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int)));

if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
psSHP->panRecSize == SHPLIB_NULLPTR)
{
psSHP->sHooks.Error("Not enough memory to allocate requested memory");
psSHP->sHooks.FClose(psSHP->fpSHP);
psSHP->sHooks.FClose(psSHP->fpSHX);
if (psSHP->panRecOffset)
free(psSHP->panRecOffset);
if (psSHP->panRecSize)
free(psSHP->panRecSize);
free(psSHP);
return SHPLIB_NULLPTR;
}

return (SHPOpenLL(pszLayer, "r+b", psHooks));
return psSHP;
}

/************************************************************************/
Expand Down

0 comments on commit e9f9842

Please sign in to comment.