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:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -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
@@ -401,6 +401,6 @@ mountDirZips (uio_MountHandle *contentHandle, uio_DirHandle *dirHandle)
|
||||
}
|
||||
}
|
||||
}
|
||||
uio_freeDirList (dirList);
|
||||
uio_DirList_free (dirList);
|
||||
}
|
||||
|
||||
|
||||
+20
-12
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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] == ':'))
|
||||
{
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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,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;
|
||||
// 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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 = '/';
|
||||
|
||||
@@ -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 +=
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user