Extended the functionality of expandPath().

It now performs certain expanding actions depending on an extra argument.
It also can expand relative paths to absolute paths now, hopefully
fixing bug #456.


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1185 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2003-09-03 02:01:12 +00:00
parent e0d56f37ed
commit a524e09504
3 changed files with 225 additions and 119 deletions
+3 -3
View File
@@ -83,7 +83,7 @@ prepareConfigDir (void) {
static uio_AutoMount *autoMount[] = { NULL }; static uio_AutoMount *autoMount[] = { NULL };
uio_MountHandle *contentHandle; uio_MountHandle *contentHandle;
if (expandPath (buf, PATH_MAX - 13, CONFIGDIR) == -1) if (expandPath (buf, PATH_MAX - 13, CONFIGDIR, EP_ALL_SYSTEM) == -1)
{ {
// Doesn't have to be fatal, but might mess up things when saving // Doesn't have to be fatal, but might mess up things when saving
// config files. // config files.
@@ -115,7 +115,7 @@ prepareConfigDir (void) {
void void
prepareSaveDir (void) { prepareSaveDir (void) {
char buf[PATH_MAX]; char buf[PATH_MAX];
if (expandPath (buf, PATH_MAX - 13, SAVEDIR) == -1) if (expandPath (buf, PATH_MAX - 13, SAVEDIR, EP_ALL_SYSTEM) == -1)
{ {
// Doesn't have to be fatal, but might mess up things when saving // Doesn't have to be fatal, but might mess up things when saving
// config files. // config files.
@@ -142,7 +142,7 @@ void
prepareMeleeDir (void) { prepareMeleeDir (void) {
char buf[PATH_MAX]; char buf[PATH_MAX];
if (expandPath (buf, PATH_MAX - 13, MELEEDIR) == -1) if (expandPath (buf, PATH_MAX - 13, MELEEDIR, EP_ALL_SYSTEM) == -1)
{ {
// Doesn't have to be fatal, but might mess up things when saving // Doesn't have to be fatal, but might mess up things when saving
// config files. // config files.
+23 -1
View File
@@ -30,11 +30,33 @@ void unInitTempDir (void);
char *tempFilePath (const char *filename); char *tempFilePath (const char *filename);
extern uio_DirHandle *tempDir; extern uio_DirHandle *tempDir;
// from dirs.h // from dirs.h
int mkdirhier (const char *path); int mkdirhier (const char *path);
const char *getHomeDir (void); const char *getHomeDir (void);
int createDirectory (const char *dir, int mode); int createDirectory (const char *dir, int mode);
int expandPath (char *dest, size_t len, const char *src);
int expandPath (char *dest, size_t len, const char *src, int what);
// values for 'what':
#define EP_HOME 1
// Expand '~' for home dirs.
#define EP_ABSOLUTE 2
// Make paths absolute
#define EP_ENVVARS 4
// Expand environment variables.
#define EP_DOTS 8
// Process '..' and '.' (not implemented)
#define EP_SLASHES 16
// Change (Windows style) backslashes to (Unix style) slashes.
#define EP_ALL (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | EP_SLASHES)
// Everything
// Everything except Windows style backslashes on Unix Systems:
#ifdef WIN32
# define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | \
EP_SLASHES)
#else
# define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS)
#endif
// from files.h // from files.h
int copyFile (uio_DirHandle *srcDir, const char *srcName, int copyFile (uio_DirHandle *srcDir, const char *srcName,
+199 -115
View File
@@ -21,6 +21,7 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include "port.h" #include "port.h"
#include "config.h" #include "config.h"
#include "filintrn.h" #include "filintrn.h"
@@ -38,6 +39,10 @@
#define APPDATA_FALLBACK #define APPDATA_FALLBACK
static char *expandPathAbsolute (char *dest, size_t destLen, char first,
int what);
int int
createDirectory(const char *dir, int mode) createDirectory(const char *dir, int mode)
{ {
@@ -162,8 +167,10 @@ getHomeDir (void)
// Expand ~/ in a path, and replaces \ by / on Windows. // Expand ~/ in a path, and replaces \ by / on Windows.
// Environment variable parsing could be added here if we need it. // Environment variable parsing could be added here if we need it.
// Returns 0 on success.
// Returns -1 on failure, setting errno.
int int
expandPath (char *dest, size_t len, const char *src) expandPath (char *dest, size_t len, const char *src, int what)
{ {
char *destend; char *destend;
char *destptr; char *destptr;
@@ -179,140 +186,217 @@ expandPath (char *dest, size_t len, const char *src)
destptr = dest; destptr = dest;
destend = dest + len; destend = dest + len;
if (src[0] == '~')
{
const char *home;
size_t homelen;
if (src[1] != '/')
{
errno = EINVAL;
return -1;
}
home = getHomeDir (); if (what & EP_HOME)
if (home == NULL)
{
errno = ENOENT;
return -1;
}
homelen = strlen (home);
CHECKLEN (homelen);
memcpy (destptr, home, homelen);
destptr += homelen;
src++; /* skip the ~ */
}
while (*src != '\0')
{ {
switch (*src) if (src[0] == '~')
{ {
#ifdef WIN32 const char *home;
case '%': size_t homelen;
if (src[1] != '/')
{ {
/* Environment variable substitution in Windows */ errno = EINVAL;
const char *end; // end of env var name in src return -1;
const char *envVar; }
char *envName;
size_t envNameLen, envVarLen; home = getHomeDir ();
if (home == NULL)
src++; {
end = strchr (src, '%'); errno = ENOENT;
if (end == NULL) return -1;
}
homelen = strlen (home);
if (what & EP_ABSOLUTE) {
dest = expandPathAbsolute (dest, destend - dest,
home[0], what);
if (dest == NULL)
{ {
errno = EINVAL; // errno is set
return -1; return -1;
} }
what &= ~EP_ABSOLUTE;
envNameLen = end - src; // The part after the '~' should not be seen
envName = HMalloc (envNameLen + 1); // as absolute.
memcpy (envName, src, envNameLen + 1); }
envName[envNameLen] = '\0';
envVar = getenv (envName);
HFree (envName);
if (envVar == NULL) CHECKLEN (homelen);
memcpy (destptr, home, homelen);
destptr += homelen;
src++; /* skip the ~ */
}
}
if (what & EP_ABSOLUTE)
{
destptr = expandPathAbsolute (destptr, destend - destptr, src[0],
what);
if (destptr == NULL)
{
// errno is set
return -1;
}
}
if (what & EP_ENVVARS)
{
while (*src != '\0')
{
switch (*src)
{
#ifdef WIN32
case '%':
{ {
#ifdef APPDATA_FALLBACK /* Environment variable substitution in Windows */
if (strncmp (src, "APPDATA", envNameLen) != 0) const char *end; // end of env var name in src
const char *envVar;
char *envName;
size_t envNameLen, envVarLen;
src++;
end = strchr (src, '%');
if (end == NULL)
{ {
errno = EINVAL;
return -1;
}
envNameLen = end - src;
envName = HMalloc (envNameLen + 1);
memcpy (envName, src, envNameLen + 1);
envName[envNameLen] = '\0';
envVar = getenv (envName);
HFree (envName);
if (envVar == NULL)
{
#ifdef APPDATA_FALLBACK
if (strncmp (src, "APPDATA", envNameLen) != 0)
{
// Substitute an empty string
src = end + 1;
break;
}
// fallback for when the APPDATA env var is not set
// Using SHGetFolderPath or SHGetSpecialFolderPath
// is problematic (not everywhere available).
fprintf(stderr, "Warning: %%APPDATA%% is not set. "
"Falling back to \"%%USERPROFILE%%\\Application "
"Data\"\n");
envVar = getenv ("USERPROFILE");
if (envVar != NULL)
{
#define APPDATA_STRING "\\Application Data"
envVarLen = strlen (envVar);
CHECKLEN (envVarLen + sizeof (APPDATA_STRING) - 1);
strcpy (destptr, envVar);
destptr += envVarLen;
strcpy (destptr, APPDATA_STRING);
destptr += sizeof (APPDATA_STRING) - 1;
src = end + 1;
break;
}
// fallback to "../userdata"
fprintf(stderr, "Warning: %%USERPROFILE%% is not set. "
"Falling back to \"..\\userdata\" for %%APPDATA%%"
"\n");
#define APPDATA_FALLBACK_STRING "..\\userdata"
CHECKLEN (sizeof (APPDATA_FALLBACK_STRING) - 1);
strcpy (destptr, APPDATA_FALLBACK_STRING);
destptr += sizeof (APPDATA_FALLBACK_STRING) - 1;
src = end + 1;
break;
#else /* !defined (APPDATA_FALLBACK) */
// Substitute an empty string // Substitute an empty string
src = end + 1; src = end + 1;
break; break;
}
// fallback for when the APPDATA env var is not set
// Using SHGetFolderPath or SHGetSpecialFolderPath
// is problematic (not everywhere available).
fprintf(stderr, "Warning: %%APPDATA%% is not set. "
"Falling back to \"%%USERPROFILE%%\\Application "
"Data\"\n");
envVar = getenv ("USERPROFILE");
if (envVar != NULL)
{
#define APPDATA_STRING "\\Application Data"
envVarLen = strlen (envVar);
CHECKLEN (envVarLen + sizeof (APPDATA_STRING) - 1);
strcpy (destptr, envVar);
destptr += envVarLen;
strcpy (destptr, APPDATA_STRING);
destptr += sizeof (APPDATA_STRING) - 1;
src = end + 1;
break;
}
// fallback to "../userdata"
fprintf(stderr, "Warning: %%USERPROFILE%% is not set. "
"Falling back to \"..\\userdata\" for %%APPDATA%%"
"\n");
#define APPDATA_FALLBACK_STRING "..\\userdata"
CHECKLEN (sizeof (APPDATA_FALLBACK_STRING) - 1);
strcpy (destptr, APPDATA_FALLBACK_STRING);
destptr += sizeof (APPDATA_FALLBACK_STRING) - 1;
src = end + 1;
break;
#else /* !defined (APPDATA_FALLBACK) */
// Substitute an empty string
src = end + 1;
break;
#endif /* APPDATA_FALLBACK */ #endif /* APPDATA_FALLBACK */
} }
envVarLen = strlen (envVar); envVarLen = strlen (envVar);
CHECKLEN (envVarLen); CHECKLEN (envVarLen);
strcpy (destptr, envVar); strcpy (destptr, envVar);
destptr += envVarLen; destptr += envVarLen;
src = end + 1; src = end + 1;
break; break;
} }
#endif #endif
#if 0 #if 0
case '$': case '$':
/* Environment variable substitution for Unix */ /* Environment variable substitution for Unix */
// not implemented // not implemented
// Should accept both $BLA_123 and ${BLA} // Should accept both $BLA_123 and ${BLA}
break; break;
#endif #endif
default: default:
CHECKLEN(1); CHECKLEN(1);
*(destptr++) = *(src++); *(destptr++) = *(src++);
break; break;
} // switch
} // while
*destptr = '\0';
} // if (what & EP_ENVVARS)
else
{
strcpy (destptr, src);
}
if (EP_SLASHES)
{
/* Replacing backslashes in path by slashes. */
destptr = dest;
while (*destptr != '\0')
{
if (*destptr == '\\')
*destptr = '/';
destptr++;
} }
} }
*destptr = '\0';
#ifdef WIN32
/* Replacing backslashes in path by slashes in Windows. */
destptr = dest;
while (*destptr != '\0')
{
if (*destptr == '\\')
*destptr = '/';
destptr++;
}
#endif
return 0; return 0;
} }
// helper for expandPath, expanding an absolute path
// returns a pointer to the end of the filled in part of dest.
static char *
expandPathAbsolute (char *dest, size_t destLen, char first, int what)
{
if (first == '/' || ((what & EP_SLASHES) && first == '\\')) {
// Path is already absolute; nothing to do
return dest;
}
// Path is not already absolute; we've got work to do.
if (getcwd (dest, destLen) == NULL)
{
// errno is set
return NULL;
}
{
size_t tempLen;
tempLen = strlen (dest);
assert (tempLen > 0);
dest += tempLen;
destLen -= tempLen;
}
if (dest[-1] != '/'
#ifdef WIN32
&& dest[-1] != '\\'
#endif
)
{
// Need to add a slash.
// There's always space, as we overwrite the '\0' that getcwd()
// always returns.
dest[0] = '/';
dest++;
destLen--;
}
return dest;
}