uio cleanups, documentation

path fixes, improvements
Fixes bugs 738, 907


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2641 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
Meep-Eep
2007-01-03 16:58:59 +00:00
parent a7b19f9f0d
commit cba93f7fce
26 changed files with 908 additions and 356 deletions
+6
View File
@@ -1,4 +1,10 @@
Changes towards version 0.7:
- uio cleanups, documentation - SvdB
- uio path parsing fixes/improvements - SvdB
- Windows UNC path support (#907)
- Windows drive-relative paths ("D:path" without a path seperator)
- treat multiple consecutive path seperators as one (like POSIX)
- config dir no longer needs trailing path seperator (bug #738)- SvdB
- Simplification of uio Stream functions. No more internal seeks. - SvdB
Changes towards version 0.6:
+3
View File
@@ -89,6 +89,9 @@ Bugs:
button won't be updated.
- If one side is computer-controlled, sync loss will occur, because the AI
uses the RNG. It needs its own RNG context.
- Pressing F10 to exit the supermelee setup when a connection is active
will cause an attempt to draw a NULL frame. (possibly the disconnect
feedback)
Final actions:
+2 -2
View File
@@ -20,10 +20,10 @@
#define CONFIGDIR USERDIR
/* Directory where supermelee teams will be stored */
#define MELEEDIR "${UQM_CONFIG_DIR}teams/"
#define MELEEDIR "${UQM_CONFIG_DIR}/teams/"
/* Directory where save games will be stored */
#define SAVEDIR "${UQM_CONFIG_DIR}save/"
#define SAVEDIR "${UQM_CONFIG_DIR}/save/"
/* Defined if words are stored with the most significant byte first */
@WORDS_BIGENDIAN@
+2 -2
View File
@@ -21,10 +21,10 @@
#define CONFIGDIR USERDIR
/* Directory where supermelee teams will be stored */
#define MELEEDIR "%UQM_CONFIG_DIR%teams/"
#define MELEEDIR "%UQM_CONFIG_DIR/%teams/"
/* Directory where save games will be stored */
#define SAVEDIR "%UQM_CONFIG_DIR%save/"
#define SAVEDIR "%UQM_CONFIG_DIR/%save/"
/* Defined if words are stored with the most significant byte first */
@WORDS_BIGENDIAN@
+1 -1
View File
@@ -401,6 +401,6 @@ mountDirZips (uio_MountHandle *contentHandle, uio_DirHandle *dirHandle)
}
}
}
uio_freeDirList (dirList);
uio_DirList_free (dirList);
}
+20 -12
View File
@@ -19,6 +19,26 @@
# endif
#endif
// Compilation related
#ifdef _MSC_VER
# define inline __inline
#else
# define inline __inline__
# ifdef __MINGW32__
// For when including Microsoft Windows header files.
# define _inline inline
# endif
#endif
// Compilation warnings:
// UQM uses a lot of functions that can be used unsafely, but it uses them
// in a safe way. The warnings about these functions however may drown out
// serious warnings, so we turn them off.
#ifdef _MSC_VER
# define _CRT_SECURE_NO_DEPRECATE
#endif
#ifdef _MSC_VER
# include <io.h>
#else
@@ -40,18 +60,6 @@ char *strupr (char *str);
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
#endif
// Compilation related
#ifdef _MSC_VER
# define inline __inline
#else
# define inline __inline__
# ifdef __MINGW32__
// For when including Microsoft Windows header files.
# define _inline inline
# endif
#endif
// Directories
#ifdef WIN32
# include <stdlib.h>
+12 -4
View File
@@ -49,15 +49,20 @@ int expandPath (char *dest, size_t len, const char *src, int what);
// Process ".." and "."
#define EP_SLASHES 16
// Consider backslashes as path component separators.
// They will be replaced by slashes.
#define EP_ALL (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | EP_SLASHES)
// They will be replaced by slashes. Windows UNC paths will always
// start with "\\server\share", with backslashes.
#define EP_SINGLESEP 32
// Replace multiple consecutive path separators by a single one.
#define EP_ALL (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | EP_SLASHES \
EP_SINGLESEP)
// 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)
EP_SLASHES | EP_SINGLESEP)
#else
# define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS)
# define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | \
EP_SINGLESEP)
#endif
// from files.h
@@ -65,6 +70,9 @@ int copyFile (uio_DirHandle *srcDir, const char *srcName,
uio_DirHandle *dstDir, const char *newName);
bool fileExists (const char *name);
bool fileExists2(uio_DirHandle *dir, const char *fileName);
#ifdef WIN32
size_t skipUNCServerShare(const char *inPath);
#endif
#ifdef WIN32
static inline int isDriveLetter(int c)
+198 -23
View File
@@ -42,8 +42,8 @@
#define APPDATA_FALLBACK
static char *expandPathAbsolute (char *dest, size_t destLen,
const char *src, int what);
static char *expandPathAbsolute (char *dest, size_t destLen, const char *src,
size_t *skipSrc, int what);
static char *strrchr2(const char *start, int c, const char *end);
@@ -73,19 +73,56 @@ mkdirhier (const char *path)
pathstart = path;
#ifdef WIN32
// driveletter + semicolon on Windows.
if (isDriveLetter(pathstart[0]) && pathstart[1] == ':')
{
// Driveletter + semicolon on Windows.
// Copy as is; don't try to create directories for it.
*(ptr++) = *(pathstart++);
*(ptr++) = *(pathstart++);
ptr[0] = '/';
ptr[1] = '\0';
if (stat (buf, &statbuf) == -1)
{
log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno));
return -1;
}
} else if (pathstart[0] == '\\' && pathstart[1] == '\\') {
// Windows UNC path. (\\server\share\...)
// Copy the server part as is; don't try to create directories for
// it, or stat it. Don't create a dir for the share either.
*(ptr++) = *(pathstart++);
*(ptr++) = *(pathstart++);
// Copy the server part
while (*pathstart != '\0' && *pathstart != '\\' && *pathstart != '/')
*(ptr++) = *(pathstart++);
if (*pathstart == '\0')
{
log_add (log_Error, "Incomplete UNC path \"%s\"", pathstart);
return -1;
}
// Copy the path seperator.
*(ptr++) = *(pathstart++);
// Copy the share part
while (*pathstart != '\0' && *pathstart != '\\' && *pathstart != '/')
*(ptr++) = *(pathstart++);
ptr[0] = '/';
ptr[1] = '\0';
if (stat (buf, &statbuf) == -1)
{
log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno));
return -1;
}
}
#endif
if (*pathstart == '/') {
*ptr = '/';
ptr++;
pathstart++;
}
if (*pathstart == '/')
*(ptr++) = *(pathstart++);
if (*pathstart == '\0') {
// path exists completely, nothing more to do
@@ -106,7 +143,7 @@ mkdirhier (const char *path)
{
if (errno != ENOENT)
{
log_add (log_Error, "Can't stat %s: %s", buf,
log_add (log_Error, "Can't stat \"%s\": %s", buf,
strerror (errno));
return -1;
}
@@ -194,6 +231,8 @@ getHomeDir (void)
// EP_DOTS - Process ".." and "."
// EP_SLASHES - Consider backslashes as path component separators.
// They will be replaced by slashes.
// EP_SINGLESEP - Replace multiple consecutive path seperators (which POSIX
// considers equivalent to a single one) by a single one.
// Additionally, there's EP_ALL, which indicates all of the above,
// and EP_SYSTEM_ALL, which does the same as EP_ALL, with the exception
// of EP_SLASHES, which will only be included if the operating system
@@ -396,13 +435,15 @@ expandPath (char *dest, size_t len, const char *src, int what)
homelen = strlen (home);
if (what & EP_ABSOLUTE) {
size_t skip;
destptr = expandPathAbsolute (dest, destend - dest,
home, what);
home, &skip, what);
if (destptr == NULL)
{
// errno is set
return -1;
}
home += skip;
what &= ~EP_ABSOLUTE;
// The part after the '~' should not be seen
// as absolute.
@@ -417,13 +458,15 @@ expandPath (char *dest, size_t len, const char *src, int what)
if (what & EP_ABSOLUTE)
{
size_t skip;
destptr = expandPathAbsolute (destptr, destend - destptr, src,
what);
&skip, what);
if (destptr == NULL)
{
// errno is set
return -1;
}
src += skip;
}
CHECKLEN (dest, srcend - src);
@@ -435,6 +478,20 @@ expandPath (char *dest, size_t len, const char *src, int what)
{
/* Replacing backslashes in path by slashes. */
destptr = dest;
#ifdef WIN32
{
// A Windows UNC path should always start with two backslashes
// and have a backslash in between the server and share part.
size_t skip = skipUNCServerShare (destptr);
if (skip != 0)
{
char *slash = (char *) memchr (destptr + 2, '/', skip - 2);
if (slash)
*slash = '\\';
destptr += skip;
}
}
#endif
while (*destptr != '\0')
{
if (*destptr == '\\')
@@ -456,8 +513,15 @@ expandPath (char *dest, size_t len, const char *src, int what)
pathStart = dest;
#ifdef WIN32
if (isDriveLetter(src[0]) && (src[1] == ':'))
if (isDriveLetter(pathStart[0]) && (pathStart[1] == ':'))
{
pathStart += 2;
}
else
{
// Test for a UNC path.
pathStart += skipUNCServerShare(pathStart);
}
#endif
if (pathStart[0] == '/')
pathStart++;
@@ -517,34 +581,113 @@ expandPath (char *dest, size_t len, const char *src, int what)
*destptr = '\0';
}
if (what & EP_SINGLESEP)
{
char *srcptr;
srcptr = dest;
destptr = dest;
while (*srcptr != '\0')
{
char ch = *srcptr;
*(destptr++) = *(srcptr++);
if (ch == '/')
{
while (*srcptr == '/')
srcptr++;
}
}
*destptr = '\0';
}
return 0;
}
#ifdef WIN32
// letter is 0 based: 0 = A, 1 = B, ...
bool
driveLetterExists(int letter)
{
unsigned long drives;
drives = _getdrives ();
return ((drives >> letter) & 1) != 0;
}
#endif
// 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, const char *src, int what)
expandPathAbsolute (char *dest, size_t destLen, const char *src,
size_t *skipSrc, int what)
{
if (src[0] == '/' || ((what & EP_SLASHES) && src[0] == '\\')
#ifdef WIN32
|| (isDriveLetter(src[0]) && (src[1] == ':'))
#endif
) {
const char *orgSrc;
if (src[0] == '/' || ((what & EP_SLASHES) && src[0] == '\\'))
{
// Path is already absolute; nothing to do
*skipSrc = 0;
return dest;
}
// Path is not already absolute; we've got work to do.
if (getcwd (dest, destLen) == NULL)
orgSrc = src;
#ifdef WIN32
if (isDriveLetter(src[0]) && (src[1] == ':'))
{
// errno is set
return NULL;
int letter;
if (src[2] == '/' || src[2] == '\\')
{
// Path is already absolute (of the form "d:/"); nothing to do
*skipSrc = 0;
return dest;
}
// Path is of the form "d:path", without a (back)slash after the
// semicolon.
letter = tolower(src[0]) - 'a';
// _getdcwd() should only be called on drives that exist.
// This is weird though, because it means a race condition
// in between the existance check and the call to _getdcwd()
// cannot be avoided, unless a drive still exists for Windows
// when the physical drive is removed.
if (!driveLetterExists(letter))
{
errno = ENOENT;
return NULL;
}
// Get the working directory for a specific drive.
if (_getdcwd (letter + 1, dest, destLen) == NULL)
{
// errno is set
return NULL;
}
src += 2;
}
else
#endif
{
// Relative dir
if (getcwd (dest, destLen) == NULL)
{
// errno is set
return NULL;
}
}
{
size_t tempLen;
tempLen = strlen (dest);
assert (tempLen > 0);
if (tempLen == 0)
{
// getcwd() or _getdcwd() returned a 0-length string.
errno = ENOENT;
return NULL;
}
dest += tempLen;
destLen -= tempLen;
}
@@ -561,6 +704,8 @@ expandPathAbsolute (char *dest, size_t destLen, const char *src, int what)
dest++;
destLen--;
}
*skipSrc = (size_t) (src - orgSrc);
return dest;
}
@@ -576,4 +721,34 @@ strrchr2(const char *start, int c, const char *end) {
}
}
#ifdef WIN32
// returns 0 if the path is not a valid UNC path.
// Does not skip trailing slashes.
size_t
skipUNCServerShare(const char *inPath) {
const char *path = inPath;
// Skip the initial two backslashes.
if (path[0] != '\\' || path[1] != '\\')
return (size_t) 0;
path += 2;
// Skip the server part.
while (*path != '\\' && *path != '/') {
if (*path == '\0')
return (size_t) 0;
path++;
}
// Skip the seperator.
path++;
// Skip the share part.
while (*path != '\0' && *path != '\\' && *path != '/')
path++;
return (size_t) (path - inPath);
}
#endif
+3 -3
View File
@@ -68,7 +68,7 @@ LoadDirEntryTable (uio_DirHandle *dirHandle, const char *path,
uio_closeDir (dir);
if (num_entries == 0) {
uio_freeDirList(dirList);
uio_DirList_free(dirList);
*pnum_entries = 0;
return ((DIRENTRY_REF) 0);
}
@@ -80,7 +80,7 @@ LoadDirEntryTable (uio_DirHandle *dirHandle, const char *path,
if (lpST == 0)
{
FreeStringTable (StringTable);
uio_freeDirList(dirList);
uio_DirList_free(dirList);
*pnum_entries = 0;
return ((DIRENTRY_REF) 0);
}
@@ -101,7 +101,7 @@ LoadDirEntryTable (uio_DirHandle *dirHandle, const char *path,
lpStr += size;
}
uio_freeDirList(dirList);
uio_DirList_free(dirList);
*pnum_entries = num_entries;
UnlockStringTable (StringTable);
return ((DIRENTRY_REF) StringTable);
+1 -1
View File
@@ -712,7 +712,7 @@ listOneDir(DebugContext *debugContext, const char *arg) {
}
for (i = 0; i < dirList->numNames; i++)
fprintf(debugContext->out, "%s\n", dirList->names[i]);
uio_freeDirList(dirList);
uio_DirList_free(dirList);
return 0;
}
+2 -2
View File
@@ -12,7 +12,7 @@ Documentation:
- It would be (theoretically) possible to add HTTP and FTP support for
remote file systems.
- on adding extra file system types:
- open, mkdir, rmdir, and unlink should themselves make sure that
open, mkdir, rmdir, and unlink should themselves make sure that
the physical structure is kept up to date when an entry is
removed or added.
- stream stuff is not thread safe
@@ -36,7 +36,7 @@ Bugs:
in the dirHandle, which will cause problems.
- 'openDirRelative(repository, "/")' causes segfaults later on
- uio_rename() doesn't work on directories
uio_getPhysicalAccess() needs to be changed so that it works the same on
- uio_getPhysicalAccess() needs to be changed so that it works the same on
dirs as on files. stat() can be cleaned up too then.
- uio_getPhysicalAccess() will not return ENOENT when (only) the last
component does not exist, even when O_RDONLY is used.
+4 -4
View File
@@ -27,7 +27,7 @@
static uio_FileBlock *uio_FileBlock_new(uio_Handle *handle, int flags,
off_t offset, size_t blockSize, char *buffer, size_t bufSize);
static inline uio_FileBlock *uio_FileBlock_alloc(void);
static void uio_freeFileBlock(uio_FileBlock *block);
static void uio_FileBlock_free(uio_FileBlock *block);
uio_FileBlock *
@@ -150,11 +150,11 @@ uio_closeFileBlock(uio_FileBlock *block) {
uio_free(block->buffer);
}
uio_Handle_unref(block->handle);
uio_freeFileBlock(block);
uio_FileBlock_free(block);
return 0;
}
// caller should uio_refHandle(handle) (unless it doesn't need it's own
// caller should uio_Handle_ref(handle) (unless it doesn't need it's own
// reference anymore).
static uio_FileBlock *
uio_FileBlock_new(uio_Handle *handle, int flags, off_t offset,
@@ -177,7 +177,7 @@ uio_FileBlock_alloc(void) {
}
static void
uio_freeFileBlock(uio_FileBlock *block) {
uio_FileBlock_free(uio_FileBlock *block) {
uio_free(block);
}
+5 -4
View File
@@ -38,7 +38,8 @@ static uio_FileSystemInfo **uio_getFileSystemInfoPtr(uio_FileSystemID id);
static inline uio_FileSystemInfo *uio_FileSystemInfo_alloc(void);
static inline void uio_freeFileSystemInfo(uio_FileSystemInfo *fileSystemInfo);
static inline void uio_FileSystemInfo_free(
uio_FileSystemInfo *fileSystemInfo);
uio_FileSystemInfo *uio_fileSystems = NULL;
@@ -173,9 +174,9 @@ uio_unRegisterFileSystem(uio_FileSystemID id) {
temp = *ptr;
*ptr = (*ptr)->next;
// uio_unrefFileSystemHandler(temp->handler);
// uio_FileSystemHandler_unref(temp->handler);
uio_free(temp->name);
uio_freeFileSystemInfo(temp);
uio_FileSystemInfo_free(temp);
return 0;
}
@@ -261,7 +262,7 @@ uio_FileSystemInfo_alloc(void) {
// *** Deallocators ***
static inline void
uio_freeFileSystemInfo(uio_FileSystemInfo *fileSystemInfo) {
uio_FileSystemInfo_free(uio_FileSystemInfo *fileSystemInfo) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_FileSystemInfo, (void *) fileSystemInfo);
#endif
+11 -11
View File
@@ -311,7 +311,7 @@ uio_unmountDir(uio_MountHandle *mountHandle) {
uio_repositoryRemoveMount(mountHandle->repository,
mountHandle->mountInfo);
uio_deleteMountInfo(mountHandle->mountInfo);
uio_MountInfo_delete(mountHandle->mountInfo);
uio_MountHandle_delete(mountHandle);
uio_PRoot_unrefMount(pRoot);
@@ -643,7 +643,7 @@ uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) {
uio_DirHandle *
uio_openDir(uio_Repository *repository, const char *path, int flags) {
uio_DirHandle *dirHandle;
const char * const rootStr = "/";
const char * const rootStr = "";
dirHandle = uio_DirHandle_new(repository,
unconst(rootStr), unconst(rootStr));
@@ -1009,8 +1009,8 @@ typedef struct uio_DirBufferLink {
} uio_DirBufferLink;
static int strPtrCmp(const char * const *ptr1, const char * const *ptr2);
static void uio_freeDirBufferLink(uio_DirBufferLink *sdbl);
static void uio_freeDirBufferChain(uio_DirBufferLink *dirBufferLink);
static void uio_DirBufferLink_free(uio_DirBufferLink *sdbl);
static void uio_DirBufferChain_free(uio_DirBufferLink *dirBufferLink);
static uio_DirList *uio_getDirListMulti(uio_PDirHandle **pDirHandles,
int numPDirHandles, const char *pattern, match_MatchType matchType);
static uio_DirList *uio_makeDirList(const char **newNames,
@@ -1037,7 +1037,7 @@ static inline void uio_EntriesContext_free(uio_EntriesContext
// The caller may modify the elements of dirHandle->names, but
// dirHandle->names itself, and the rest of the elements of dirHandle
// should be left alone, so that they will be freed by uio_freeDirList().
// should be left alone, so that they will be freed by uio_DirList_free().
uio_DirList *
uio_getDirList(uio_DirHandle *dirHandle, const char *path, const char *pattern,
match_MatchType matchType) {
@@ -1182,7 +1182,7 @@ uio_getDirListMulti(uio_PDirHandle **pDirHandles,
// free the old junk
for (pDirI = 0; pDirI < numPDirHandles; pDirI++)
uio_freeDirBufferChain(links[pDirI]);
uio_DirBufferChain_free(links[pDirI]);
uio_free(links);
uio_free(numNames);
@@ -1252,7 +1252,7 @@ uio_collectDirEntries(uio_PDirHandle *pDirHandle, uio_DirBufferLink **linkPtr,
if (numRead == 0) {
fprintf(stderr, "Warning: uio_DIR_BUFFER_SIZE is too small to "
"hold a certain large entry on its own!\n");
uio_freeDirBufferLink(*linkEndPtr);
uio_DirBufferLink_free(*linkEndPtr);
break;
}
totalEntries += numRead;
@@ -1356,18 +1356,18 @@ uio_EntriesContext_free(uio_EntriesContext *entriesContext) {
}
static void
uio_freeDirBufferLink(uio_DirBufferLink *dirBufferLink) {
uio_DirBufferLink_free(uio_DirBufferLink *dirBufferLink) {
uio_free(dirBufferLink->buffer);
uio_free(dirBufferLink);
}
static void
uio_freeDirBufferChain(uio_DirBufferLink *dirBufferLink) {
uio_DirBufferChain_free(uio_DirBufferLink *dirBufferLink) {
uio_DirBufferLink *next;
while (dirBufferLink != NULL) {
next = dirBufferLink->next;
uio_freeDirBufferLink(dirBufferLink);
uio_DirBufferLink_free(dirBufferLink);
dirBufferLink = next;
}
}
@@ -1389,7 +1389,7 @@ uio_DirList_alloc(void) {
}
void
uio_freeDirList(uio_DirList *dirList) {
uio_DirList_free(uio_DirList *dirList) {
if (dirList->buffer)
uio_free(dirList->buffer);
if (dirList->names)
+1 -1
View File
@@ -135,7 +135,7 @@ int uio_closeDir(uio_DirHandle *dirHandle);
uio_DirList *uio_getDirList(uio_DirHandle *dirHandle, const char *path,
const char *pattern, match_MatchType matchType);
void uio_freeDirList(uio_DirList *dirList);
void uio_DirList_free(uio_DirList *dirList);
// For debugging purposes
void uio_DirHandle_print(const uio_DirHandle *dirHandle, FILE *out);
+72 -27
View File
@@ -33,17 +33,30 @@ static int copyError(int error,
uio_FileSystemHandler *toHandler, uio_Handle *toHandle,
uio_PDirHandle *toDir, const char *toName, char *buf);
/*
* Follow a path starting from a specified physical dir as long as possible.
* When you can get no further, 'endPDirHandle' will be filled in with a
* reference to the dir where you ended up, and 'pathRest' will point into
* the original path to the beginning of the part that was not matched.
* It is allowed to have endPDirHandle point to pDirHandle and/or restPath
* point to path when calling this function. Just take care to keep a
* reference to the original so you can decrement the ref counter.
* returns: 0 if the complete path was matched
* ENOENT if some component (the next one) didn't exists
* ENODIR if a component (the next one) exists but isn't a dir
/**
* Follow a path starting from a specified physical dir for as long as
* possible.
*
* @param[in] startPDirHandle The physical dir to start from.
* @param[in] path The path to follow, relative to
* 'startPDirHandle'.
* @param[in] pathLen The string length of 'path'.
* @param[out] endPDirHandle The physical dir where you end up after
* following 'path' for as long as possible. Unmodified if an error
* occurs.
* @param[out] pathRest '*pathRest' will point into 'path' to the
* start the part that was not matched. Unmodified if an error occurs.
*
* @retval 0 if the complete path was matched
* @retval ENOENT if some component (the next one in '*pathRest') didn't
* exist.
* @retval ENODIR if a component (the next one in '*pathRest') did exist,
* but wasn't a dir.
*
* @note It is allowed to have 'endPDirHandle' point to pDirHandle, but
* care should be taken to keep a reference to the original so its
* reference counter can be decremented.
* @note It is allowed to have 'pathRest' point to 'path'.
*/
int
uio_walkPhysicalPath(uio_PDirHandle *startPDirHandle, const char *path,
@@ -61,7 +74,7 @@ uio_walkPhysicalPath(uio_PDirHandle *startPDirHandle, const char *path,
tempBuf = uio_alloca(strlen(path) + 1);
pathEnd = path + pathLen;
getFirstPathComponent(path, pathEnd, &partStart, &partEnd);
while (1) {
for (;;) {
if (partStart == pathEnd) {
retVal = 0;
break;
@@ -89,7 +102,19 @@ uio_walkPhysicalPath(uio_PDirHandle *startPDirHandle, const char *path,
return retVal;
}
// Make a all directory components of a path, inside a physical directory.
/**
* Create a directory inside a physical directory. All non-existant
* parent directories will be created as well.
*
* @param[in] pDirHandle The physical directory to which 'path' is relative
* @param[in] path The path to the directory to create, relative to
* 'pDirHandle'
* @param[in] pathLen The string length of 'path'.
* @param[in] mode The access mode for the newly created directories.
*
* @returns the new (physical) directory, or NULL if an error occurs, in
* which case #errno will be set.
*/
uio_PDirHandle *
uio_makePath(uio_PDirHandle *pDirHandle, const char *path, size_t pathLen,
mode_t mode) {
@@ -136,12 +161,23 @@ uio_makePath(uio_PDirHandle *pDirHandle, const char *path, size_t pathLen,
return pDirHandle;
}
/*
* permissions should already have been checked
/**
* Copy a file from one physical directory to another.
* The copy will have the same file permissions as the original.
*
* The new file will have the same permissions as the old.
* If an error occurs during copying, an attempt will be made to
* remove the copy.
* @param[in] fromDir The physical directory where the file to copy is
* located.
* @param[in] fromName The name of the file to copy.
* @param[in] toDir The physical directory where to put the copy.
* @param[in] toName The name to use for the copy.
*
* @note It is up to the caller to make any relevant permissions checks.
*
* @note This function will fail if a file with the name in 'toName' already
* exists, leaving the original file intact. If an error occurs during
* copying, an attempt is made to remove the file that was to be the
* copy.
*/
int
uio_copyFilePhysical(uio_PDirHandle *fromDir, const char *fromName,
@@ -683,7 +719,7 @@ uio_verifyPath(uio_DirHandle *dirHandle, const char *path,
return 0;
}
// try all the MountInfo structures in effect for this MountTree
// Try all the MountInfo structures in effect for this MountTree.
for (item = tree->pLocs; item != NULL; item = item->next) {
const char *pRootPath;
uio_PDirHandle *pDirHandle;
@@ -695,7 +731,7 @@ uio_verifyPath(uio_DirHandle *dirHandle, const char *path,
uio_PDirHandle_unref(pDirHandle);
switch (retVal) {
case 0:
// complete match. We're done.
// Complete match. We're done.
return 0;
case ENOTDIR:
// A component is matched, but not as a dir. Failed.
@@ -703,7 +739,7 @@ uio_verifyPath(uio_DirHandle *dirHandle, const char *path,
errno = ENOTDIR;
return -1;
case ENOENT:
// no match; try next pLoc
// No match; try the next pLoc.
continue;
default:
// Unknown error. Let's bail out just to be safe.
@@ -723,12 +759,21 @@ uio_verifyPath(uio_DirHandle *dirHandle, const char *path,
return -1;
}
// Get the absolute path pointed to by 'path' relative to 'dirHandle'
// The new path will be put in '*destPath', which will be newly allocated.
// It will be \0-terminated, and will not have a '/' as first or last
// character.
// The length of '*destPath' will be returned.
// On error, -1 will be returned, and errno will be set.
/**
* Determine the absolute path given a path relative to a given directory.
*
* @param[in] dirHandle The directory to which 'path' is relative.
* @param[in] path The path, relative to 'dirHandle', to make
* absolute.
* @param[in] pathLen The string length of 'path'.
* @param[out] destPath Filled with a newly allocated string containing
* the sought absolute path. It will not contain a '/' as the first
* or last character. It should be freed with uio_free().
* Unmodified if an error occurs.
*
* @returns the length of '*destPath', or -1 if an error occurs, in which
* case #errno will be set.
*/
ssize_t
uio_resolvePath(uio_DirHandle *dirHandle, const char *path, size_t pathLen,
char **destPath) {
+9
View File
@@ -48,6 +48,15 @@ uio_strdup(const char *s) {
# define uio_strdup strdup
#endif
// Allocates new memory, copies 'len' characters from 'src', and adds a '\0'.
static inline char *
uio_memdup0(const char *src, size_t len) {
char *dst = uio_malloc(len + 1);
memcpy(dst, src, len);
dst[len] = '\0';
return dst;
}
#endif
+7 -7
View File
@@ -31,9 +31,9 @@
# include "memdebug.h"
#endif
static void uio_deleteRepository(uio_Repository *repository);
static void uio_Repository_delete(uio_Repository *repository);
static uio_Repository *uio_Repository_alloc(void);
static void uio_freeRepository(uio_Repository *repository);
static void uio_Repository_free(uio_Repository *repository);
void
@@ -137,7 +137,7 @@ uio_Repository_unref(uio_Repository *repository) {
assert(repository->ref > 0);
repository->ref--;
if (repository->ref == 0)
uio_deleteRepository(repository);
uio_Repository_delete(repository);
}
static uio_Repository *
@@ -150,15 +150,15 @@ uio_Repository_alloc(void) {
}
static void
uio_deleteRepository(uio_Repository *repository) {
uio_Repository_delete(uio_Repository *repository) {
assert(repository->numMounts == 0);
uio_free(repository->mounts);
uio_deleteMountTree(repository->mountTree);
uio_freeRepository(repository);
uio_MountTree_delete(repository->mountTree);
uio_Repository_free(repository);
}
static void
uio_freeRepository(uio_Repository *repository) {
uio_Repository_free(uio_Repository *repository) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_Repository, (void *) repository);
#endif
+19 -133
View File
@@ -63,10 +63,6 @@ static uio_MountTree * uio_splitMountTree(uio_MountTree **tree, uio_PathComp
*lastComp, int depth);
static void uio_mountTreeRemoveMountInfoRec(uio_MountTree *mountTree,
uio_MountInfo *mountInfo);
static int uio_countPathComps(const uio_PathComp *comp);
static uio_PathComp *uio_lastPathComp(uio_PathComp *comp);
static uio_PathComp *uio_makePathComps(const char *path,
uio_PathComp *upComp);
static void uio_printMount(FILE *outStream, const uio_MountInfo *mountInfo);
static inline uio_MountTree * uio_MountTree_new(uio_MountTree *subTrees,
@@ -74,21 +70,16 @@ static inline uio_MountTree * uio_MountTree_new(uio_MountTree *subTrees,
*comps, uio_PathComp *lastComp, uio_MountTree *next);
static inline uio_MountTreeItem *uio_MountTree_newItem(
uio_MountInfo *mountInfo, int depth, uio_MountTreeItem *next);
static inline uio_PathComp *uio_PathComp_new(char *name, size_t nameLen,
uio_PathComp *upComp);
static inline void uio_deleteMountTreeItem(uio_MountTreeItem *item);
static inline void uio_deletePathComp(uio_PathComp *pathComp);
static inline void uio_MountTreeItem_delete(uio_MountTreeItem *item);
static inline uio_MountTree *uio_MountTree_alloc(void);
static inline uio_MountTreeItem *uio_MountTreeItem_alloc(void);
static inline uio_MountInfo *uio_MountInfo_alloc(void);
static inline uio_PathComp *uio_PathComp_alloc(void);
static inline void uio_freeMountTree(uio_MountTree *mountTree);
static inline void uio_freeMountTreeItem(uio_MountTreeItem *mountTreeItem);
static inline void uio_freeMountInfo(uio_MountInfo *mountInfo);
static inline void uio_freePathComp(uio_PathComp *pathComp);
static inline void uio_MountTree_free(uio_MountTree *mountTree);
static inline void uio_MountTreeItem_free(uio_MountTreeItem *mountTreeItem);
static inline void uio_MountInfo_free(uio_MountInfo *mountInfo);
// make the root mount Tree
@@ -409,7 +400,7 @@ uio_mountTreeRemoveMountInfo(uio_Repository *repository,
upTree = mountTree->upTree;
// Remove the tree itself.
uio_deleteMountTree(mountTree);
uio_MountTree_delete(mountTree);
// The upTree itself could have become unnecessary now.
// This is the case when upTree now only has one subTree, and upTree
@@ -453,7 +444,7 @@ uio_mountTreeRemoveMountInfo(uio_Repository *repository,
// Now delete the tree itself
upTree->subTrees = NULL;
upTree->comps = NULL;
uio_deleteMountTree(upTree);
uio_MountTree_delete(upTree);
}
// pre: mountInfo exists in mountTree->pLocs (and hence in pLocs for
@@ -484,28 +475,7 @@ uio_mountTreeRemoveMountInfoRec(uio_MountTree *mountTree,
item = *itemPtr;
*itemPtr = item->next;
uio_deleteMountTreeItem(item);
}
// Count the number of path components that 'comp' leads to.
static int
uio_countPathComps(const uio_PathComp *comp) {
int count;
count = 0;
for (; comp != NULL; comp = comp->next)
count++;
return count;
}
static uio_PathComp *
uio_lastPathComp(uio_PathComp *comp) {
if (comp == NULL)
return NULL;
while (comp->next != NULL)
comp = comp->next;
return comp;
uio_MountTreeItem_delete(item);
}
// Count the number of pLocs in a tree that leads to.
@@ -520,30 +490,6 @@ uio_mountTreeCountPLocs(const uio_MountTree *tree) {
return count;
}
// make a list of uio_PathComps from a path string
static uio_PathComp *
uio_makePathComps(const char *path, uio_PathComp *upComp) {
const char *start, *end;
char *str;
uio_PathComp *result;
uio_PathComp **compPtr; // Where to put the next PathComp
compPtr = &result;
getFirstPath0Component(path, &start, &end);
while (*start != '\0') {
str = uio_malloc(end - start + 1);
memcpy(str, start, end - start);
str[end - start] = '\0';
*compPtr = uio_PathComp_new(str, end - start, upComp);
upComp = *compPtr;
compPtr = &(*compPtr)->next;
getNextPath0Component(&start, &end);
}
*compPtr = NULL;
return result;
}
// resTree may point to top
// pPath may point to path
void
@@ -691,20 +637,6 @@ uio_printPathToMountTree(FILE *outStream, const uio_MountTree *tree) {
uio_printPathToComp(outStream, tree->lastComp);
}
void
uio_printPathComp(FILE *outStream, const uio_PathComp *comp) {
fprintf(outStream, "%s", comp->name);
}
void
uio_printPathToComp(FILE *outStream, const uio_PathComp *comp) {
if (comp == NULL)
return;
uio_printPathToComp(outStream, comp->up);
fprintf(outStream, "/");
uio_printPathComp(outStream, comp);
}
void
uio_printMountInfo(FILE *outStream, const uio_MountInfo *mountInfo) {
uio_FileSystemInfo *fsInfo;
@@ -757,28 +689,28 @@ uio_MountTree_new(uio_MountTree *subTrees, uio_MountTreeItem *pLocs,
}
void
uio_deleteMountTree(uio_MountTree *tree) {
uio_MountTree_delete(uio_MountTree *tree) {
uio_MountTree *subTree, *nextTree;
uio_MountTreeItem *item, *nextItem;
subTree = tree->subTrees;
while (subTree != NULL) {
nextTree = subTree->next;
uio_deleteMountTree(subTree);
uio_MountTree_delete(subTree);
subTree = nextTree;
}
item = tree->pLocs;
while (item != NULL) {
nextItem = item->next;
uio_deleteMountTreeItem(item);
uio_MountTreeItem_delete(item);
item = nextItem;
}
if (tree->comps != NULL)
uio_deletePathComp(tree->comps);
uio_PathComp_delete(tree->comps);
uio_freeMountTree(tree);
uio_MountTree_free(tree);
}
static inline uio_MountTree *
@@ -791,7 +723,7 @@ uio_MountTree_alloc(void) {
}
static inline void
uio_freeMountTree(uio_MountTree *mountTree) {
uio_MountTree_free(uio_MountTree *mountTree) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_MountTree, (void *) mountTree);
#endif
@@ -814,8 +746,8 @@ uio_MountTree_newItem(uio_MountInfo *mountInfo, int depth,
}
static inline void
uio_deleteMountTreeItem(uio_MountTreeItem *item) {
uio_freeMountTreeItem(item);
uio_MountTreeItem_delete(uio_MountTreeItem *item) {
uio_MountTreeItem_free(item);
}
static inline uio_MountTreeItem *
@@ -828,7 +760,7 @@ uio_MountTreeItem_alloc(void) {
}
static inline void
uio_freeMountTreeItem(uio_MountTreeItem *mountTreeItem) {
uio_MountTreeItem_free(uio_MountTreeItem *mountTreeItem) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_MountTreeItem, (void *) mountTreeItem);
#endif
@@ -856,10 +788,10 @@ uio_MountInfo_new(uio_FileSystemID fsID, uio_MountTree *mountTree,
}
void
uio_deleteMountInfo(uio_MountInfo *mountInfo) {
uio_MountInfo_delete(uio_MountInfo *mountInfo) {
uio_free(mountInfo->dirName);
uio_PDirHandle_unref(mountInfo->pDirHandle);
uio_freeMountInfo(mountInfo);
uio_MountInfo_free(mountInfo);
}
static inline uio_MountInfo *
@@ -872,7 +804,7 @@ uio_MountInfo_alloc(void) {
}
static inline void
uio_freeMountInfo(uio_MountInfo *mountInfo) {
uio_MountInfo_free(uio_MountInfo *mountInfo) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_MountInfo, (void *) mountInfo);
#endif
@@ -880,49 +812,3 @@ uio_freeMountInfo(uio_MountInfo *mountInfo) {
}
// *** uio_PathComp *** //
// 'name' should be a null terminated string. It is stored in the PathComp,
// no copy is made.
// 'namelen' should be the length of 'name'
static inline uio_PathComp *
uio_PathComp_new(char *name, size_t nameLen, uio_PathComp *upComp) {
uio_PathComp *result;
result = uio_PathComp_alloc();
result->name = name;
result->nameLen = nameLen;
result->up = upComp;
return result;
}
static inline void
uio_deletePathComp(uio_PathComp *pathComp) {
uio_PathComp *next;
while (pathComp != NULL) {
next = pathComp->next;
uio_free(pathComp->name);
uio_freePathComp(pathComp);
pathComp = next;
}
}
static inline uio_PathComp *
uio_PathComp_alloc(void) {
uio_PathComp *result = uio_malloc(sizeof (uio_PathComp));
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugAlloc(uio_PathComp, (void *) result);
#endif
return result;
}
static inline void
uio_freePathComp(uio_PathComp *pathComp) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_PathComp, (void *) pathComp);
#endif
uio_free(pathComp);
}
+5 -19
View File
@@ -33,12 +33,12 @@ void uio_printMounts(FILE *outStream, const uio_Repository *repository);
typedef struct uio_MountTreeItem uio_MountTreeItem;
typedef struct uio_MountTree uio_MountTree;
typedef struct uio_PathComp uio_PathComp;
typedef struct uio_MountInfo uio_MountInfo;
#include "physical.h"
#include "types.h"
#include "uioport.h"
#include "paths.h"
/*
@@ -69,19 +69,6 @@ struct uio_MountTreeItem {
// The next MountTreeItem in a MountTree
};
struct uio_PathComp {
char *name;
// The name of this path component, 0-terminated
size_t nameLen;
// The length of the 'name' field, for fast lookups.
struct uio_PathComp *next;
// The next path component leading to a MountTree
// If this is NULL, then this was the last component
// until the MountTree that
struct uio_PathComp *up;
// Links to the directory
};
struct uio_MountTree {
struct uio_MountTree *subTrees;
// Trees for subdirs in this MountTree
@@ -183,7 +170,7 @@ struct uio_MountInfo {
*/
uio_MountTree *uio_makeRootMountTree(void);
void uio_deleteMountTree(uio_MountTree *tree);
void uio_MountTree_delete(uio_MountTree *tree);
uio_MountTree *uio_mountTreeAddMountInfo(uio_Repository *repository,
uio_MountTree *mountTree, uio_MountInfo *mountInfo, const char *path,
uio_MountLocation location, const uio_MountInfo *relative);
@@ -198,13 +185,12 @@ uio_MountInfo *uio_MountInfo_new(uio_FileSystemID fsID,
uio_MountTree *mountTree, uio_PDirHandle *pDirHandle,
char *dirName, uio_AutoMount **autoMount,
uio_MountHandle *mountHandle, int flags);
void uio_deleteMountInfo(uio_MountInfo *mountInfo);
void uio_printMountTree(FILE *outStream, const uio_MountTree *tree, int indent);
void uio_MountInfo_delete(uio_MountInfo *mountInfo);
void uio_printMountTree(FILE *outStream, const uio_MountTree *tree,
int indent);
void uio_printMountTreeItem(FILE *outStream, const uio_MountTreeItem *item);
void uio_printMountTreeItems(FILE *outStream, const uio_MountTreeItem *item);
void uio_printPathToMountTree(FILE *outStream, const uio_MountTree *tree);
void uio_printPathComp(FILE *outStream, const uio_PathComp *comp);
void uio_printPathToComp(FILE *outStream, const uio_PathComp *comp);
void uio_printMountInfo(FILE *outStream, const uio_MountInfo *mountInfo);
static inline uio_bool
+358 -1
View File
@@ -18,14 +18,18 @@
*
*/
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "paths.h"
#include "uioport.h"
#include "mem.h"
static inline uio_PathComp *uio_PathComp_alloc(void);
static inline void uio_PathComp_free(uio_PathComp *pathComp);
// gets the first dir component of a path
// sets '*start' to the start of the first component
// sets '*end' to the end of the first component
@@ -236,4 +240,357 @@ validPathName(const char *path, size_t len) {
return true;
}
// returns 0 if the path is not a valid UNC path.
// Does not skip trailing slashes.
size_t
uio_skipUNCServerShare(const char *inPath) {
const char *path = inPath;
// Skip the initial two backslashes.
if (path[0] != '\\' || path[1] != '\\')
return (size_t) 0;
path += 2;
// Skip the server part.
while (*path != '\\' && *path != '/') {
if (*path == '\0')
return (size_t) 0;
path++;
}
// Skip the seperator.
path++;
// Skip the share part.
while (*path != '\0' && *path != '\\' && *path != '/')
path++;
return (size_t) (path - inPath);
}
/**
* Find the server and share part of a Windows "Universal Naming Convention"
* path (a path of the form '\\server\share\path\file').
* The path must contain at least a server and share path to be valid.
* The initial two slashes must be backslashes, the other slashes may each
* be either a forward slash or a backslash.
*
* @param[in] inPath The path to parse.
* @param[out] outPath Will contain a newly allocated string (to be
* freed using uio_free(), containing the server and share part
* of inPath, separated by a backslash, or NULL if 'inPath' was
* not a valid UNC path.
* @param[out] outLen If not NULL on entry, it will contain the string
* length of '*outPath', or 0 if 'inPath' was not a valid UNC path.
*
* @returns The number of characters to add to 'inPath' to get to the first
* path component past the server and share part, or 0 if 'inPath'
* was not a valid UNC path.
*/
size_t
uio_getUNCServerShare(const char *inPath, char **outPath, size_t *outLen) {
const char *ptr;
const char *server;
const char *serverEnd;
const char *share;
const char *shareEnd;
char *name;
char *nameEnd;
size_t nameLen;
ptr = inPath;
if (ptr[0] != '\\' || ptr[1] != '\\')
goto noMatch;
// Parse the server part.
server = ptr + 2;
serverEnd = server;
for (;;) {
if (*serverEnd == '\0')
goto noMatch;
if (isPathDelimiter(*serverEnd))
break;
serverEnd++;
}
if (serverEnd == server)
goto noMatch;
// Parse the share part.
share = serverEnd + 1;
shareEnd = share;
while (*shareEnd != '\0') {
if (isPathDelimiter(*shareEnd))
break;
serverEnd++;
}
// Skip any trailing path delimiters.
ptr = shareEnd;
while (isPathDelimiter(*ptr))
ptr++;
// Allocate a new string and fill it.
nameLen = (serverEnd - server) + (shareEnd - share) + 3;
name = uio_malloc(nameLen + 1);
nameEnd = name;
*(nameEnd++) = '\\';
*(nameEnd++) = '\\';
memcpy(nameEnd, server, serverEnd - server);
*(nameEnd++) = '\\';
memcpy(nameEnd, share, shareEnd - share);
*nameEnd = '\0';
*outPath = name;
if (outLen != NULL)
*outLen = nameLen;
return (size_t) (ptr - inPath);
noMatch:
*outPath = NULL;
if (outLen != NULL)
*outLen = 0;
return (size_t) 0;
}
// Decomposes a path into its components.
// If isAbsolute is not NULL, *isAbsolute will be set to true
// iff the path is absolute.
// As POSIX considers multiple consecutive slashes to be equivalent to
// a single slash, so will uio (but not in the "\\MACHINE\share" part
// of a Windows UNC path).
int
decomposePath(const char *path, uio_PathComp **pathComp,
uio_bool *isAbsolute) {
uio_PathComp *result;
uio_PathComp *last;
uio_PathComp **endResult = &result;
uio_bool absolute = false;
char *name;
#ifdef WIN32
size_t nameLen;
#endif
if (path[0] == '\0') {
errno = ENOENT;
return -1;
}
last = NULL;
#ifdef WIN32
path += uio_getUNCServerShare(path, &name, &nameLen);
if (name != NULL) {
// UNC path
*endResult = uio_PathComp_new(name, nameLen, last);
last = *endResult;
endResult = &last->next;
absolute = true;
} else if (isDriveLetter(path[0]) && path[1] == ':') {
// DOS/Windows drive letter.
if (path[2] != '\0' && !isPathDelimiter(path[2])) {
errno = ENOENT;
return -1;
}
name = uio_memdup0(path, 2);
*endResult = uio_PathComp_new(name, 2, last);
last = *endResult;
endResult = &last->next;
absolute = true;
} else
#endif
{
if (isPathDelimiter(*path)) {
absolute = true;
do {
path++;
} while (isPathDelimiter(*path));
}
}
while (*path != '\0') {
const char *start = path;
while (*path != '\0' && !isPathDelimiter(*path))
path++;
name = uio_memdup0(path, path - start);
*endResult = uio_PathComp_new(name, path - start, last);
last = *endResult;
endResult = &last->next;
while (isPathDelimiter(*path))
path++;
}
*endResult = NULL;
*pathComp = result;
if (isAbsolute != NULL)
*isAbsolute = absolute;
return 0;
}
// Pre: pathComp forms a valid path for the platform.
void
composePath(const uio_PathComp *pathComp, uio_bool absolute,
char **path, size_t *pathLen) {
size_t len;
const uio_PathComp *ptr;
char *result;
char *pathPtr;
assert(pathComp != NULL);
// First determine how much space is required.
len = 0;
if (absolute)
len++;
ptr = pathComp;
while (ptr != NULL) {
len += ptr->nameLen;
ptr = ptr->next;
}
// Allocate the required space.
result = (char *) uio_malloc(len + 1);
// Fill the path.
pathPtr = result;
ptr = pathComp;
if (absolute) {
#ifdef WIN32
if (ptr->name[0] == '\\') {
// UNC path
assert(ptr->name[1] == '\\');
// Nothing to do.
} else if (ptr->nameLen == 2 && ptr->name[1] == ':'
&& isDriveLetter(ptr->name[0])) {
// Nothing to do.
}
else
#endif
{
*(pathPtr++) = '/';
}
}
for (;;) {
memcpy(pathPtr, ptr->name, ptr->nameLen);
pathPtr += ptr->nameLen;
ptr = ptr->next;
if (ptr == NULL)
break;
*(pathPtr++) = '/';
}
*path = result;
*pathLen = len;
}
// *** uio_PathComp *** //
static inline uio_PathComp *
uio_PathComp_alloc(void) {
uio_PathComp *result = uio_malloc(sizeof (uio_PathComp));
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugAlloc(uio_PathComp, (void *) result);
#endif
return result;
}
static inline void
uio_PathComp_free(uio_PathComp *pathComp) {
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugFree(uio_PathComp, (void *) pathComp);
#endif
uio_free(pathComp);
}
// 'name' should be a null terminated string. It is stored in the PathComp,
// no copy is made.
// 'namelen' should be the length of 'name'
uio_PathComp *
uio_PathComp_new(char *name, size_t nameLen, uio_PathComp *upComp) {
uio_PathComp *result;
result = uio_PathComp_alloc();
result->name = name;
result->nameLen = nameLen;
result->up = upComp;
return result;
}
void
uio_PathComp_delete(uio_PathComp *pathComp) {
uio_PathComp *next;
while (pathComp != NULL) {
next = pathComp->next;
uio_free(pathComp->name);
uio_PathComp_free(pathComp);
pathComp = next;
}
}
// Count the number of path components that 'comp' leads to.
int
uio_countPathComps(const uio_PathComp *comp) {
int count;
count = 0;
for (; comp != NULL; comp = comp->next)
count++;
return count;
}
uio_PathComp *
uio_lastPathComp(uio_PathComp *comp) {
if (comp == NULL)
return NULL;
while (comp->next != NULL)
comp = comp->next;
return comp;
}
// make a list of uio_PathComps from a path string
uio_PathComp *
uio_makePathComps(const char *path, uio_PathComp *upComp) {
const char *start, *end;
char *str;
uio_PathComp *result;
uio_PathComp **compPtr; // Where to put the next PathComp
compPtr = &result;
getFirstPath0Component(path, &start, &end);
while (*start != '\0') {
str = uio_malloc(end - start + 1);
memcpy(str, start, end - start);
str[end - start] = '\0';
*compPtr = uio_PathComp_new(str, end - start, upComp);
upComp = *compPtr;
compPtr = &(*compPtr)->next;
getNextPath0Component(&start, &end);
}
*compPtr = NULL;
return result;
}
void
uio_printPathComp(FILE *outStream, const uio_PathComp *comp) {
fprintf(outStream, "%s", comp->name);
}
void
uio_printPathToComp(FILE *outStream, const uio_PathComp *comp) {
if (comp == NULL)
return;
uio_printPathToComp(outStream, comp->up);
fprintf(outStream, "/");
uio_printPathComp(outStream, comp);
}
+51 -2
View File
@@ -19,11 +19,26 @@
*/
#ifndef _PATHS_H
#define PATHS_H
#define _PATHS_H
typedef struct uio_PathComp uio_PathComp;
#include "types.h"
#include "uioport.h"
#include <stdio.h>
struct uio_PathComp {
char *name;
// The name of this path component, 0-terminated
size_t nameLen;
// The length of the 'name' field, for fast lookups.
struct uio_PathComp *next;
// Next component in the path.
struct uio_PathComp *up;
// Previous component in the path.
};
void getFirstPathComponent(const char *dir, const char *dirEnd,
const char **startComp, const char **endComp);
void getFirstPath0Component(const char *dir, const char **startComp,
@@ -42,6 +57,40 @@ char *joinPaths(const char *first, const char *second);
char *joinPathsAbsolute(const char *first, const char *second);
uio_bool validPathName(const char *path, size_t len);
size_t uio_skipUNCServerShare(const char *inPath);
size_t uio_getUNCServerShare(const char *inPath, char **outPath,
size_t *outLen);
#endif /* PATHS_H */
#ifdef WIN32
static inline int
isDriveLetter(int c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
#endif
static inline int
isPathDelimiter(int c)
{
#ifdef WIN32
return c == '/' || c == '\\';
#else
return c == '/';
#endif
}
int decomposePath(const char *path, uio_PathComp **pathComp,
uio_bool *isAbsolute);
void composePath(const uio_PathComp *pathComp, uio_bool absolute,
char **path, size_t *pathLen);
uio_PathComp *uio_PathComp_new(char *name, size_t nameLen,
uio_PathComp *upComp);
void uio_PathComp_delete(uio_PathComp *pathComp);
int uio_countPathComps(const uio_PathComp *comp);
uio_PathComp *uio_lastPathComp(uio_PathComp *comp);
uio_PathComp *uio_makePathComps(const char *path, uio_PathComp *upComp);
void uio_printPathComp(FILE *outStream, const uio_PathComp *comp);
void uio_printPathToComp(FILE *outStream, const uio_PathComp *comp);
#endif /* _PATHS_H */
+22 -11
View File
@@ -22,7 +22,7 @@
#ifdef __svr4__
# define _POSIX_PTHREAD_SEMANTICS
// For the POSIX variant of r_readdir()
// For the POSIX variant of readdir_r()
#endif
#include "./stdio.h"
@@ -348,13 +348,23 @@ stdio_getPDirEntryHandle(const uio_PDirHandle *pDirHandle, const char *name) {
#ifdef WIN32
if (pDirHandle->extra->extra->upDir == NULL) {
// Top dir. Contains only drive letters.
if (!isDriveLetter(name[0]) || name[1] != ':' || name[2] != '\0')
return NULL;
driveName[0] = tolower(name[0]);
driveName[1] = ':';
driveName[2] = '\0';
name = driveName;
// Top dir. Contains only drive letters and UNC \\server\share
// parts.
if (isDriveLetter(name[0]) && name[1] == ':' && name[2] == '\0') {
driveName[0] = tolower(name[0]);
driveName[1] = ':';
driveName[2] = '\0';
name = driveName;
} else {
size_t uncLen;
uncLen = uio_skipUNCServerShare(name);
if (name[uncLen] != '\0') {
// 'name' contains neither a drive letter, nor the
// first part of a UNC path.
return NULL;
}
}
}
#endif
@@ -363,8 +373,9 @@ stdio_getPDirEntryHandle(const uio_PDirHandle *pDirHandle, const char *name) {
return result;
#ifdef WIN32
if (name == driveName) {
// Need to create a 'directory' for the drive letter.
if (pDirHandle->extra->extra->upDir == NULL) {
// Need to create a 'directory' for the drive letter or UNC
// "\\server\share" part.
// It's no problem if we happen to create a dir for a non-existing
// drive. It should just produce an empty dir.
uio_GPDir *gPDir;
@@ -703,7 +714,7 @@ stdio_getPath(uio_GPDir *gPDir) {
if (gPDir->extra->upDir == NULL) {
#ifdef WIN32
// Drive letter still needs to follow follow.
// Drive letter still needs to follow.
gPDir->extra->cachedPath = uio_malloc(1);
gPDir->extra->cachedPath[0] = '\0';
#else
-8
View File
@@ -107,11 +107,3 @@ void stdio_EntriesIterator_delete(stdio_EntriesIterator *iterator);
uio_PDirEntryHandle *stdio_getPDirEntryHandle(
const uio_PDirHandle *pDirHandle, const char *name);
#ifdef WIN32
static inline int isDriveLetter(int c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
#endif
+31 -3
View File
@@ -23,10 +23,18 @@
#include "uioutils.h"
#include "mem.h"
#include "paths.h"
#include "uioport.h"
// concattenate two strings into a newly allocated buffer.
// It's up to the caller to free it.
/**
* Concatenate two strings into a newly allocated buffer.
*
* @param[in] first The first (left) string, '\0' terminated.
* @param[in] second The second (right) string, '\0' terminated.
*
* @returns A newly allocated string consisting of the concatenation of
* 'first' and 'second', to be freed using uio_free().
*/
char *
strcata(const char *first, const char *second) {
char *result, *resPtr;
@@ -144,7 +152,7 @@ dosToUnixTime(uio_uint16 date, uio_uint16 tm) {
static const int daysUntilMonth[] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
334, 334, 334, 334 };
// Last 4 entries are there so that there's no
// The last 4 entries are there so that there's no
// invalid memory access if the date is invalid.
year = date >> 9;
@@ -181,10 +189,30 @@ char *
dosToUnixPath(const char *path) {
const char *srcPtr;
char *result, *dstPtr;
size_t skip;
result = uio_malloc(strlen(path) + 1);
srcPtr = path;
dstPtr = result;
// A UNC path will look like this: "\\server\share/..."; the first two
// characters will be backslashes, and the separator between the server
// and the share too. The rest will be slashes.
// The goal is that at every forward slash, the path should be
// stat()'able.
skip = uio_skipUNCServerShare(srcPtr);
if (skip != 0) {
char *slash;
memcpy(dstPtr, srcPtr, skip);
slash = memchr(srcPtr + 2, '/', skip - 2);
if (slash != NULL)
*slash = '\\';
srcPtr += skip;
dstPtr += skip;
}
while (*srcPtr != '\0') {
if (*srcPtr == '\\') {
*dstPtr = '/';
+63 -75
View File
@@ -193,7 +193,8 @@ count_marines (STARSHIPPTR StarShipPtr, BOOLEAN FindSpot)
LockElement (hElement, &ElementPtr);
hNextElement = GetPredElement (ElementPtr);
if (ElementPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special
if (ElementPtr->current.image.farray ==
StarShipPtr->RaceDescPtr->ship_data.special
&& ElementPtr->life_span
&& !(ElementPtr->state_flags & (FINITE_LIFE | DISAPPEARING)))
{
@@ -222,7 +223,8 @@ count_marines (STARSHIPPTR StarShipPtr, BOOLEAN FindSpot)
}
static void
orz_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter)
orz_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern,
COUNT ConcernCounter)
{
ELEMENTPTR TurretPtr;
STARSHIPPTR StarShipPtr;
@@ -328,8 +330,7 @@ ion_preprocess (PELEMENT ElementPtr)
COLOR Color;
Color = COLOR_256 (GetPrimColor (&(GLOBAL (DisplayArray))[
ElementPtr->PrimIndex
]));
ElementPtr->PrimIndex]));
if (Color != 0x2D)
{
ElementPtr->life_span = ElementPtr->thrust_wait;
@@ -344,8 +345,7 @@ ion_preprocess (PELEMENT ElementPtr)
else /* color is between 0x7a and 0x7f */
color_index = (COUNT)(Color - 0x7a) + (NUM_TAB_COLORS >> 1);
SetPrimColor (&(GLOBAL (DisplayArray))[
ElementPtr->PrimIndex
], color_tab[color_index]);
ElementPtr->PrimIndex], color_tab[color_index]);
ElementPtr->state_flags &= ~DISAPPEARING;
ElementPtr->state_flags |= CHANGING;
@@ -454,15 +454,13 @@ LeftShip:
{
ElementPtr->state_flags &= ~NONSOLID;
ElementPtr->state_flags |= CHANGING | CREW_OBJECT;
SetPrimType (&(GLOBAL (DisplayArray))[
ElementPtr->PrimIndex
], STAMP_PRIM);
SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex],
STAMP_PRIM);
ElementPtr->current.image.frame =
ElementPtr->next.image.frame =
SetAbsFrameIndex (
StarShipPtr->RaceDescPtr->ship_data.special[0], 21
);
StarShipPtr->RaceDescPtr->ship_data.special[0], 21);
ElementPtr->thrust_wait = 0;
ElementPtr->turn_wait =
MAKE_BYTE (0, NORMALIZE_FACING ((BYTE)TFB_Random ()));
@@ -523,9 +521,8 @@ PELEMENT ElementPtr;
pfacing = ANGLE_TO_FACING (ARCTAN (delta_x, delta_y));
delta_facing = NORMALIZE_FACING (
pfacing - ANGLE_TO_FACING (
GetVelocityTravelAngle (&ElementPtr->velocity)
) + ANGLE_TO_FACING (OCTANT)
);
GetVelocityTravelAngle (&ElementPtr->velocity))
+ ANGLE_TO_FACING (OCTANT));
if (delta_facing <= ANGLE_TO_FACING (QUADRANT))
{
hTarget = hObject;
@@ -589,18 +586,17 @@ PELEMENT ElementPtr;
(ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))
&& (ElementPtr->state_flags & IGNORE_SIMILAR))
{
ElementPtr->next.image.frame =
SetAbsFrameIndex (
StarShipPtr->RaceDescPtr->ship_data.special[0], 21
);
ElementPtr->next.image.frame = SetAbsFrameIndex (
StarShipPtr->RaceDescPtr->ship_data.special[0],
21);
ElementPtr->state_flags &= ~IGNORE_SIMILAR;
ElementPtr->state_flags |= CHANGING;
}
if ((num_frames = WORLD_TO_TURN (
num_frames = WORLD_TO_TURN (
square_root ((long)delta_x * delta_x
+ (long)delta_y * delta_y)
)) == 0)
+ (long)delta_y * delta_y));
if (num_frames == 0)
num_frames = 1;
ShipVelocity = ObjectPtr->velocity;
@@ -613,8 +609,7 @@ PELEMENT ElementPtr;
- ElementPtr->current.location.y;
delta_facing = NORMALIZE_FACING (
ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing
);
ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing);
if (delta_facing > 0)
{
@@ -644,7 +639,8 @@ PELEMENT ElementPtr;
OldFacing = StarShipPtr->ShipFacing;
OldStatus = StarShipPtr->cur_status_flags;
OldIncrement = StarShipPtr->RaceDescPtr->characteristics.thrust_increment;
OldIncrement = StarShipPtr->RaceDescPtr->characteristics.
thrust_increment;
OldThrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust;
StarShipPtr->ShipFacing = facing;
@@ -655,7 +651,8 @@ PELEMENT ElementPtr;
thrust_status = inertial_thrust (ElementPtr);
StarShipPtr->RaceDescPtr->characteristics.max_thrust = OldThrust;
StarShipPtr->RaceDescPtr->characteristics.thrust_increment = OldIncrement;
StarShipPtr->RaceDescPtr->characteristics.thrust_increment =
OldIncrement;
StarShipPtr->cur_status_flags = OldStatus;
StarShipPtr->ShipFacing = OldFacing;
@@ -677,15 +674,16 @@ PELEMENT ElementPtr;
InsertElement (hIonElement, GetHeadElement ());
LockElement (hIonElement, &IonElementPtr);
IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID;
IonElementPtr->life_span = IonElementPtr->thrust_wait = ION_LIFE;
IonElementPtr->state_flags =
APPEARING | FINITE_LIFE | NONSOLID;
IonElementPtr->life_span =
IonElementPtr->thrust_wait = ION_LIFE;
SetPrimType (&(GLOBAL (DisplayArray))[
IonElementPtr->PrimIndex
], POINT_PRIM);
IonElementPtr->PrimIndex], POINT_PRIM);
SetPrimColor (&(GLOBAL (DisplayArray))[
IonElementPtr->PrimIndex
], START_ION_COLOR);
IonElementPtr->current.location = ElementPtr->current.location;
IonElementPtr->PrimIndex], START_ION_COLOR);
IonElementPtr->current.location =
ElementPtr->current.location;
IonElementPtr->current.location.x +=
(COORD)COSINE (angle, DISPLAY_TO_WORLD (2));
IonElementPtr->current.location.y +=
@@ -695,10 +693,10 @@ PELEMENT ElementPtr;
SetElementStarShip (IonElementPtr, StarShipPtr);
{
/* normally done during preprocess, but because
* object is being inserted at head rather than
* appended after tail it may never get preprocessed.
*/
/* normally done during preprocess, but because
* object is being inserted at head rather than
* appended after tail it may never get preprocessed.
*/
IonElementPtr->next = IonElementPtr->current;
--IonElementPtr->life_span;
IonElementPtr->state_flags |= PRE_PROCESS;
@@ -786,7 +784,8 @@ marine_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOIN
}
ProcessSound (SetAbsSoundIndex (
StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr1);
StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2),
ElementPtr1);
}
ElementPtr0->state_flags &= ~COLLISION;
@@ -819,8 +818,7 @@ turret_postprocess (PELEMENT ElementPtr)
STARSHIPPTR StarShipPtr;
SetPrimType (&(GLOBAL (DisplayArray))[
ElementPtr->PrimIndex
], NO_PRIM);
ElementPtr->PrimIndex], NO_PRIM);
GetElementStarShip (ElementPtr, &StarShipPtr);
if (StarShipPtr->hShip)
@@ -866,8 +864,7 @@ turret_postprocess (PELEMENT ElementPtr)
<< (NORMALIZE_FACING (facing + ANGLE_TO_FACING (OCTANT))
/ ANGLE_TO_FACING (QUADRANT));
TurretPtr->current.image.frame = SetAbsFrameIndex (
TurretPtr->current.image.frame, facing
);
TurretPtr->current.image.frame, facing);
facing = FACING_TO_ANGLE (facing);
if (StarShipPtr->cur_status_flags & WEAPON)
{
@@ -876,14 +873,14 @@ turret_postprocess (PELEMENT ElementPtr)
LockElement (GetTailElement (), &TurretEffectPtr);
if ((PELEMENT)TurretEffectPtr != ElementPtr
&& (TurretEffectPtr->state_flags & (GOOD_GUY | BAD_GUY)) ==
&& (TurretEffectPtr->state_flags &
(GOOD_GUY | BAD_GUY)) ==
(ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))
&& (TurretEffectPtr->state_flags & APPEARING)
&& GetPrimType (&(GLOBAL (DisplayArray))[
TurretEffectPtr->PrimIndex
]) == STAMP_PRIM
&& (hTurretEffect = AllocElement ())
)
&& (hTurretEffect = AllocElement ()))
{
TurretPtr->current.location.x -=
COSINE (facing, DISPLAY_TO_WORLD (2));
@@ -891,9 +888,10 @@ turret_postprocess (PELEMENT ElementPtr)
SINE (facing, DISPLAY_TO_WORLD (2));
LockElement (hTurretEffect, &TurretEffectPtr);
TurretEffectPtr->state_flags =
FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING
| (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY));
TurretEffectPtr->state_flags = FINITE_LIFE
| NONSOLID | IGNORE_SIMILAR | APPEARING
| (ElementPtr->state_flags &
(GOOD_GUY | BAD_GUY));
TurretEffectPtr->life_span = 4;
TurretEffectPtr->current.location.x =
@@ -906,18 +904,17 @@ turret_postprocess (PELEMENT ElementPtr)
DISPLAY_TO_WORLD (TURRET_OFFSET));
TurretEffectPtr->current.image.farray =
StarShipPtr->RaceDescPtr->ship_data.special;
TurretEffectPtr->current.image.frame = SetAbsFrameIndex (
TurretEffectPtr->current.image.frame =
SetAbsFrameIndex (
StarShipPtr->RaceDescPtr->ship_data.special[0],
ANGLE_TO_FACING (FULL_CIRCLE)
);
ANGLE_TO_FACING (FULL_CIRCLE));
TurretEffectPtr->preprocess_func = animate;
SetElementStarShip (TurretEffectPtr, StarShipPtr);
SetPrimType (&(GLOBAL (DisplayArray))[
TurretEffectPtr->PrimIndex
], STAMP_PRIM);
TurretEffectPtr->PrimIndex], STAMP_PRIM);
UnlockElement (hTurretEffect);
PutElement (hTurretEffect);
@@ -927,20 +924,15 @@ turret_postprocess (PELEMENT ElementPtr)
TurretPtr->next = TurretPtr->current;
SetPrimType (&(GLOBAL (DisplayArray))[
TurretPtr->PrimIndex
],
TurretPtr->PrimIndex],
GetPrimType (&(GLOBAL (DisplayArray))[
ShipPtr->PrimIndex
]));
ShipPtr->PrimIndex]));
SetPrimColor (&(GLOBAL (DisplayArray))[
TurretPtr->PrimIndex
],
TurretPtr->PrimIndex],
GetPrimColor (&(GLOBAL (DisplayArray))[
ShipPtr->PrimIndex
]));
ShipPtr->PrimIndex]));
TurretPtr->postprocess_func =
ElementPtr->postprocess_func;
TurretPtr->postprocess_func = ElementPtr->postprocess_func;
SetElementStarShip (TurretPtr, StarShipPtr);
@@ -969,37 +961,33 @@ turret_postprocess (PELEMENT ElementPtr)
facing = FACING_TO_ANGLE (StarShipPtr->ShipFacing);
SpaceMarinePtr->current.location.x =
ShipPtr->current.location.x
- COSINE (facing,
DISPLAY_TO_WORLD (TURRET_OFFSET));
- COSINE (facing, DISPLAY_TO_WORLD (TURRET_OFFSET));
SpaceMarinePtr->current.location.y =
ShipPtr->current.location.y
- SINE (facing,
DISPLAY_TO_WORLD (TURRET_OFFSET));
- SINE (facing, DISPLAY_TO_WORLD (TURRET_OFFSET));
SpaceMarinePtr->current.image.farray =
StarShipPtr->RaceDescPtr->ship_data.special;
SpaceMarinePtr->current.image.frame = SetAbsFrameIndex (
StarShipPtr->RaceDescPtr->ship_data.special[0], 20
);
StarShipPtr->RaceDescPtr->ship_data.special[0], 20);
SpaceMarinePtr->turn_wait = MAKE_BYTE (0,
NORMALIZE_FACING (
ANGLE_TO_FACING (facing + HALF_CIRCLE)
));
SpaceMarinePtr->turn_wait =
MAKE_BYTE (0, NORMALIZE_FACING (
ANGLE_TO_FACING (facing + HALF_CIRCLE)));
SpaceMarinePtr->preprocess_func = marine_preprocess;
SpaceMarinePtr->collision_func = marine_collision;
SetElementStarShip (SpaceMarinePtr, StarShipPtr);
SetPrimType (&(GLOBAL (DisplayArray))[
SpaceMarinePtr->PrimIndex
], STAMP_PRIM);
SpaceMarinePtr->PrimIndex], STAMP_PRIM);
UnlockElement (hSpaceMarine);
PutElement (hSpaceMarine);
DeltaCrew (ShipPtr, -1);
ProcessSound (SetAbsSoundIndex (
StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), SpaceMarinePtr);
StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1),
SpaceMarinePtr);
StarShipPtr->special_counter =
StarShipPtr->RaceDescPtr->characteristics.special_wait;