Fixed GfParms::safeFOpen silently failing to create parent dir under Windows (mkdir('D:') doesn't work)

Added new tgf::GfFileGetDirName

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@3402 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 30d29e36415a484e4f92352ea5ed95e4be8ab567
Former-commit-id: ae28668b7d4dd31548e7c35f73218736e8384f28
This commit is contained in:
pouillot 2011-02-27 10:39:54 +00:00
parent 534eb01eb1
commit c6e970d545
3 changed files with 60 additions and 17 deletions

View file

@ -36,12 +36,64 @@
#include "tgf.h"
/** Get the path-name of the directory containing a file
@ingroup file
@param pszFileName path-name of the file
@return Path-name of the directory, allocated on the heap (the caller must free it).
*/
char* GfFileGetDirName(const char* pszFileName)
{
// Allocate and initialize the target string
char* pszDirName = strdup(pszFileName);
// Replace '\\' by '/' under Windows
#ifdef WIN32
for (int i = 0; pszDirName[i]; i++)
if (pszDirName[i] == '\\')
pszDirName[i] = '/';
#endif
// Search for the last '/'.
char *lastSlash = strrchr(pszDirName, '/');
// If found, we've got the end of the directory name.
if (lastSlash)
{
// But keep the '/' if it is the first one of an absolute path-name.
if (lastSlash != pszDirName)
#ifdef WIN32
if (*(lastSlash-1) != ':')
#endif
*lastSlash = '\0';
}
// If no '/' found, empty directory name.
else
*pszDirName = '\0';
//GfLogDebug("GfFileGetDirName(%s) = %s\n", pszFileName, pszDirName);
// That's all.
return pszDirName;
}
/** Check if a file exists
@ingroup file
@param pszName Path-name of the file
@return true if the file exists, false otherwise.
*/
bool GfFileExists(const char* pszName)
{
struct stat st;
return stat(pszName, &st) ? false : true;
}
/** Copy a file to a target path-name
@ingroup file
@param pszSrcName Source file path-name
@param pszSrcName Target file path-name for the copy
@return true upon success, false otherwise.
*/
bool GfFileCopy(const char* pszSrcName, const char* pszTgtName)
{
static const size_t maxBufSize = 1024;
@ -54,6 +106,7 @@ bool GfFileCopy(const char* pszSrcName, const char* pszTgtName)
// Create the target local directory (and parents) if not already done
// (first, we have to deduce its path from the target file path-name).
// TODO: Use GfFileGetDirName
strncpy(buf, pszTgtName, strlen(pszTgtName)+1);
#ifdef WIN32
for (int i = 0; i < maxBufSize && buf[i] != '\0'; i++)

View file

@ -3743,25 +3743,14 @@ safeFOpen(const char *fileName, const char *mode)
return file;
}
// TODO: Make things simpler by using GfDirCreate (takes care of parent dirs).
// Otherwise, try and create parent dirs in case it is the cause of the error :
// - search the fileName for directory level separators (\\ or /) and create each directory.
// - directories' permissions are set to 700=u+rwx on UNIX-like systems.
// - the only error we silently ignore from mkdir is when the dir already exists.
char *mname = strdup(fileName);
for(int i = 0; mname[i] != '\0'; i++) {
if(i > 0 && (mname[i] == '\\' || mname[i] == '/')) {
const char slash = mname[i];
mname[i] = '\0';
if(mkdir(mname) == -1 && errno != EEXIST) {
return NULL;
}
mname[i] = slash;
}//if i
}//for i
char *pszDirName = GfFileGetDirName(fileName);
if (GfDirCreate(pszDirName) != GF_DIR_CREATED)
GfLogWarning("Failed to create parent dir(s) of %s\n", fileName);
free(pszDirName);
free(mname);
// And finally try again to open the file.
return fopen(fileName, mode);
}//safeFOpen

View file

@ -262,6 +262,7 @@ TGF_API void GfDirFreeList(tFList *list, tfDirfreeUserData freeUserData, bool fr
* File management *
************************/
TGF_API char* GfFileGetDirName(const char* pszFileName);
TGF_API bool GfFileExists(const char* pszName);
TGF_API bool GfFileCopy(const char* pszSrcName, const char* pszTgtName);