mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
953 lines
25 KiB
C++
953 lines
25 KiB
C++
/*
|
|
* $Logfile: /DescentIII/Main/ddio_mac/macfile.cpp $
|
|
* $Revision: 1.1.1.1 $
|
|
* $Date: 2003/08/26 03:56:55 $
|
|
* $Author: kevinb $
|
|
*
|
|
* File operations not covered properly in ANSI C
|
|
*
|
|
* $Log: macfile.cpp,v $
|
|
* Revision 1.1.1.1 2003/08/26 03:56:55 kevinb
|
|
* initial 1.5 import
|
|
*
|
|
*
|
|
* 4 10/21/99 3:33p Jeff
|
|
* Macintosh merges
|
|
*
|
|
* 3 8/01/99 10:37p Duane
|
|
* Works with paht+wildcard or just wildcard
|
|
*
|
|
* 2 7/28/99 3:31p Kevin
|
|
* Mac Stuff!
|
|
*
|
|
* 6 5/15/97 1:44 AM Jeremy
|
|
* changed mprintf's to be standard (with newline at end), fixed two bugs:
|
|
* ddio_filediff was returning opposite of correct value, ddio function to
|
|
* set file time stamp had arguments in reverse order
|
|
*
|
|
* 5 5/9/97 8:04 PM Jeremy
|
|
* changed include of <Strings.h> to <TextUtils.h>
|
|
*
|
|
* 4 5/6/97 6:37 PM Jeremy
|
|
* implemented splitpath
|
|
*
|
|
* 3 5/6/97 4:22 PM Jeremy
|
|
* fixed a bug in ddio_MakePath
|
|
*
|
|
* 2 5/6/97 3:11 PM Jeremy
|
|
* added implementation of ddio_MakePath
|
|
*
|
|
* 1 3/13/97 6:53 PM Jeremy
|
|
* macintosh implementation of device dependent io functions
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
// ANSI Headers
|
|
#include <unistd.h>
|
|
#include <stat.h>
|
|
#include <stdio.h>
|
|
#include <unix.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
// #include <assert.h>
|
|
|
|
// Mac Headers
|
|
#include <Files.h>
|
|
#include <Strings.h>
|
|
#include <TextUtils.h>
|
|
// Descent 3 Headers
|
|
#include "mono.h"
|
|
#include "pserror.h"
|
|
#include "ddio.h"
|
|
#include "ddio_mac.h"
|
|
#include "psglob.h"
|
|
#include "mem.h"
|
|
#include "cfile.h"
|
|
// ---------------------------------------------------------------------------
|
|
// File Level Globals
|
|
// ---------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------
|
|
// Local File Prototypes
|
|
// ---------------------------------------------------------------------------
|
|
/*******************************************
|
|
Utility functions specific to the Mac OS
|
|
*******************************************
|
|
int
|
|
stricmp(const char* s1, const char* s2)
|
|
{
|
|
char c1, c2;
|
|
while (1)
|
|
{
|
|
c1 = tolower(*s1++);
|
|
c2 = tolower(*s2++);
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
if (c1 == 0) return 0;
|
|
}
|
|
}
|
|
int
|
|
strnicmp(const char *s1, const char *s2, int n)
|
|
{
|
|
int i;
|
|
char c1, c2;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
c1 = tolower(*s1++);
|
|
c2 = tolower(*s2++);
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
if (!c1) return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
/************************/
|
|
// ---------------------------------------------------------------------------
|
|
// File Operations
|
|
// ---------------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------------
|
|
// File operations
|
|
bool ddio_CreateDir(const char *path) {
|
|
bool failed = true;
|
|
failed = mkdir(path, 0);
|
|
|
|
return !failed;
|
|
}
|
|
bool ddio_RemoveDir(const char *path) {
|
|
bool failed = true;
|
|
|
|
failed = rmdir(path);
|
|
|
|
return (!failed);
|
|
}
|
|
// retrieve the current working folder where file operation will occur.
|
|
// Note ---> The path in Get/Set working directory is in the *LOCAL* file system's syntax
|
|
// This pathname is relative *OR* fully qualified
|
|
static char SavedWorkingDir[_MAX_PATH];
|
|
|
|
void ddio_GetWorkingDir(char *path, int len) {
|
|
getcwd(path, len);
|
|
len = strlen(path);
|
|
if (path[len - 1] == ':') {
|
|
path[len - 1] = '\0';
|
|
}
|
|
}
|
|
// set the current working folder where file operation will occur.
|
|
// Note ---> The path in Get/Set working directory is in the *LOCAL* file system's syntax
|
|
// This pathname is relative *OR* fully qualified
|
|
bool ddio_SetWorkingDir(const char *path) {
|
|
bool failed = true;
|
|
|
|
failed = chdir(path);
|
|
|
|
if (!failed) {
|
|
// if(path[strlen(path)-1] != ':')
|
|
// strcat(path, ":");
|
|
strcpy(SavedWorkingDir, path);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
// check if two files are different
|
|
bool ddio_FileDiff(const char *fileNameA, const char *fileNameB) {
|
|
struct stat infoA;
|
|
struct stat infoB;
|
|
|
|
bool filesAreEqual = false;
|
|
if (fileNameA && fileNameB) {
|
|
if (!(strcmp(fileNameA, fileNameB))) {
|
|
filesAreEqual = true;
|
|
} else // test file info
|
|
{
|
|
stat(fileNameA, &infoA);
|
|
stat(fileNameB, &infoB);
|
|
|
|
if ((infoA.st_mode == infoB.st_mode) && (infoA.st_size == infoB.st_size) && (infoA.st_mtime == infoB.st_mtime)) {
|
|
filesAreEqual = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return !filesAreEqual;
|
|
}
|
|
// get a file length of a FILE
|
|
int ddio_GetFileLength(FILE *filePtr) {
|
|
int size = -1;
|
|
if (filePtr) {
|
|
int filedes = fileno(filePtr);
|
|
struct stat info;
|
|
|
|
fstat(filedes, &info);
|
|
|
|
size = info.st_size;
|
|
} else {
|
|
mprintf((0, "Tried getting length of NULL fileptr!\n"));
|
|
Debugger();
|
|
}
|
|
|
|
return size;
|
|
}
|
|
// Split a pathname into its component parts
|
|
void ddio_SplitPath(const char *srcPath, char *path, char *filename, char *ext) {
|
|
int pathStart = -1;
|
|
int pathEnd = -1;
|
|
int fileStart = -1;
|
|
int fileEnd = -1;
|
|
int extStart = -1;
|
|
int extEnd = -1;
|
|
int totalLen = strlen(srcPath);
|
|
// Check for an extension
|
|
///////////////////////////////////////
|
|
int t = totalLen - 1;
|
|
while ((srcPath[t] != '.') && (srcPath[t] != ':') && (t >= 0))
|
|
t--;
|
|
// see if we are at an extension
|
|
if ((t >= 0) && (srcPath[t] == '.')) {
|
|
// we have an extension
|
|
extStart = t;
|
|
extEnd = totalLen - 1;
|
|
if (ext) {
|
|
strncpy(ext, &(srcPath[extStart]), extEnd - extStart + 1);
|
|
ext[extEnd - extStart + 1] = '\0';
|
|
}
|
|
} else {
|
|
// no extension
|
|
if (ext)
|
|
ext[0] = '\0';
|
|
}
|
|
// Check for file name
|
|
////////////////////////////////////
|
|
int temp = (extStart != -1) ? (extStart) : (totalLen - 1);
|
|
while ((srcPath[temp] != ':') && (temp >= 0))
|
|
temp--;
|
|
if (temp < 0)
|
|
temp = 0;
|
|
if (srcPath[temp] == ':') {
|
|
// we have a file
|
|
fileStart = temp + 1;
|
|
if (extStart != -1)
|
|
fileEnd = extStart - 1;
|
|
else
|
|
fileEnd = totalLen - 1;
|
|
if (filename) {
|
|
strncpy(filename, &(srcPath[fileStart]), fileEnd - fileStart + 1);
|
|
filename[fileEnd - fileStart + 1] = '\0';
|
|
}
|
|
pathStart = 0;
|
|
pathEnd = fileStart - 2;
|
|
// Copy the rest into the path name
|
|
if (path) {
|
|
strncpy(path, &(srcPath[pathStart]), pathEnd - pathStart + 1);
|
|
path[pathEnd - pathStart + 1] = 0;
|
|
}
|
|
} else {
|
|
// only file, no path
|
|
fileStart = 0;
|
|
if (extStart != -1)
|
|
fileEnd = extStart - 1;
|
|
else
|
|
fileEnd = totalLen - 1;
|
|
if (filename) {
|
|
strncpy(filename, &(srcPath[fileStart]), fileEnd - fileStart + 1);
|
|
filename[fileEnd - fileStart + 1] = 0;
|
|
}
|
|
|
|
// Only file no path
|
|
if (path) {
|
|
path[0] = 0;
|
|
}
|
|
}
|
|
#if 0
|
|
// Check for an extension
|
|
if (srcPath[totalLen - 4] == '.')
|
|
{
|
|
extStart = totalLen - 4;
|
|
extEnd = totalLen - 1;
|
|
strncpy(ext, &(srcPath[extStart]), extEnd - extStart + 1);
|
|
ext[extEnd - extStart + 1] = 0;
|
|
}
|
|
else
|
|
{
|
|
ext[0] = 0;
|
|
}
|
|
|
|
// Check for file name
|
|
char* namePtr = strrchr(srcPath, ':');
|
|
if (namePtr)
|
|
{
|
|
fileStart = namePtr - srcPath + 1;
|
|
if (extStart != -1)
|
|
{
|
|
fileEnd = extStart - 2;
|
|
}
|
|
else
|
|
{
|
|
fileEnd = totalLen - 1;
|
|
}
|
|
|
|
strncpy(filename, &(srcPath[fileStart]), fileEnd - fileStart + 1);
|
|
filename[fileEnd - fileStart + 1] = 0;
|
|
|
|
pathStart = 0;
|
|
pathEnd = fileStart - 2;
|
|
|
|
// Copy the rest into the path name
|
|
strncpy(path, &(srcPath[pathStart]), pathEnd - pathStart + 1);
|
|
path[pathEnd - pathStart + 1] = 0;
|
|
}
|
|
else
|
|
{
|
|
fileStart = 0;
|
|
if (extStart != -1)
|
|
{
|
|
fileEnd = extStart - 2;
|
|
}
|
|
else
|
|
{
|
|
fileEnd = totalLen - 1;
|
|
}
|
|
|
|
strncpy(filename, &(srcPath[fileStart]), fileEnd - fileStart + 1);
|
|
filename[fileEnd - fileStart + 1] = 0;
|
|
// Only file no path
|
|
path[0] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
void ddio_CopyFileTime(char *dstFile, const char *srcFile) {
|
|
CInfoPBRec srcPB;
|
|
CInfoPBRec dstPB;
|
|
OSErr err = noErr;
|
|
Str255 srcMacFile = "\p";
|
|
Str255 dstMacFile = "\p";
|
|
Str255 volName = "\p";
|
|
short volRefNum = 0;
|
|
long dirID = 0;
|
|
|
|
// Get the info for the current default volume (where the working directory lives)
|
|
err = HGetVol(volName, &volRefNum, &dirID);
|
|
if (err) {
|
|
mprintf((0, "Error getting default volume info in ddio_CopyFileTime: %d\n", err));
|
|
Debugger();
|
|
} else {
|
|
// Convert the c-string version of the path to a p-string
|
|
strcpy((char *)srcMacFile, srcFile);
|
|
c2pstr((char *)srcMacFile);
|
|
// Set up the source file's parameter block
|
|
memset(&srcPB, 0, sizeof(srcPB));
|
|
srcPB.hFileInfo.ioNamePtr = srcMacFile;
|
|
srcPB.hFileInfo.ioFDirIndex = 0;
|
|
srcPB.hFileInfo.ioVRefNum = volRefNum;
|
|
srcPB.hFileInfo.ioDirID = dirID;
|
|
|
|
// Get the source file's info
|
|
err = PBGetCatInfoSync(&srcPB);
|
|
if (err == noErr) {
|
|
// Convert the c-string version of the path to a p-string
|
|
strcpy((char *)dstMacFile, dstFile);
|
|
c2pstr((char *)dstMacFile);
|
|
// Set up the target file's parameter block
|
|
memset(&dstPB, 0, sizeof(dstPB));
|
|
dstPB.hFileInfo.ioNamePtr = dstMacFile;
|
|
dstPB.hFileInfo.ioVRefNum = volRefNum;
|
|
|
|
dstPB.hFileInfo.ioFDirIndex = 0;
|
|
dstPB.hFileInfo.ioDirID = dirID;
|
|
|
|
// Get the target file's info
|
|
err = PBGetCatInfoSync(&dstPB);
|
|
if (err == noErr) {
|
|
// Transfer the src file's time stamp to the target
|
|
dstPB.hFileInfo.ioFlCrDat = srcPB.hFileInfo.ioFlCrDat;
|
|
dstPB.hFileInfo.ioFlMdDat = srcPB.hFileInfo.ioFlMdDat;
|
|
dstPB.hFileInfo.ioFlBkDat = srcPB.hFileInfo.ioFlBkDat;
|
|
|
|
// Restore the directory id (which got bashed to the fileID by PBGetCatInfo
|
|
dstPB.hFileInfo.ioDirID = dirID;
|
|
|
|
err = PBSetCatInfoSync(&dstPB);
|
|
if (err == noErr) {
|
|
; // success
|
|
} else {
|
|
mprintf((0, "Error setting target file's timestamp in ddio_CopyFileTime: %d\n", err));
|
|
Debugger();
|
|
}
|
|
} else {
|
|
mprintf((0, "Error getting target file's info in ddio_CopyFileTime: %d\n", err));
|
|
Debugger();
|
|
}
|
|
} else {
|
|
mprintf((0, "Error getting source file's time stamp in ddio_CopyFileTime: %d\n", err));
|
|
Int3();
|
|
}
|
|
}
|
|
}
|
|
// deletes a file. Returns 1 if successful, 0 on failure
|
|
int ddio_DeleteFile(char *name) {
|
|
bool failed = true;
|
|
|
|
failed = remove(name);
|
|
|
|
return (!failed);
|
|
}
|
|
// Save/Restore the current working directory
|
|
void ddio_SaveWorkingDir(void) { ddio_GetWorkingDir(SavedWorkingDir, _MAX_PATH); }
|
|
void ddio_RestoreWorkingDir(void) { ddio_SetWorkingDir(SavedWorkingDir); }
|
|
// Checks if a directory exists (returns 1 if it does, 0 if not)
|
|
// This pathname is *RELATIVE* not fully qualified
|
|
bool ddio_DirExists(const char *path) {
|
|
bool res;
|
|
|
|
ddio_SaveWorkingDir();
|
|
res = chdir(path);
|
|
if (res) {
|
|
char tempbuffer[_MAX_PATH];
|
|
strcpy(tempbuffer, ":");
|
|
strcat(tempbuffer, path);
|
|
res = chdir(tempbuffer);
|
|
}
|
|
ddio_RestoreWorkingDir();
|
|
return (!res) ? true : false;
|
|
}
|
|
// Constructs a path in the local file system's syntax
|
|
// newPath: stores the constructed path
|
|
// absolutePathHeader: absolute path on which the sub directories will be appended
|
|
// (specified in local file system syntax)
|
|
// takes a variable number of subdirectories which will be concatenated on to the path
|
|
// the last argument in the list of sub dirs *MUST* be NULL to terminate the list
|
|
void ddio_MakePath(char *newPath, const char *absolutePathHeader, const char *subDir, ...) {
|
|
const char delimiter = ':';
|
|
va_list args;
|
|
char *currentDir = NULL;
|
|
int pathLength = 0;
|
|
|
|
assert(newPath);
|
|
if (absolutePathHeader == 0)
|
|
mprintf((2, "WOOPS\n"));
|
|
assert(absolutePathHeader);
|
|
assert(subDir);
|
|
|
|
if (newPath != absolutePathHeader) {
|
|
strcpy(newPath, absolutePathHeader);
|
|
}
|
|
// Add the first sub directory
|
|
pathLength = strlen(newPath);
|
|
if (newPath[pathLength - 1] != delimiter) {
|
|
newPath[pathLength] = delimiter; // add the delimiter
|
|
newPath[pathLength + 1] = 0; // terminate the string
|
|
}
|
|
strcat(newPath, subDir);
|
|
|
|
// Add the additional subdirectories
|
|
va_start(args, subDir);
|
|
while ((currentDir = va_arg(args, char *)) != NULL) {
|
|
pathLength = strlen(newPath);
|
|
if (newPath[pathLength - 1] != delimiter) {
|
|
newPath[pathLength] = delimiter; // add the delimiter
|
|
newPath[pathLength + 1] = 0; // terminate the string
|
|
}
|
|
strcat(newPath, currentDir);
|
|
}
|
|
va_end(args);
|
|
}
|
|
bool ddio_GetTempFileName(char *basedir, char *prefix, char *filename) {
|
|
char old_workdir[_MAX_PATH];
|
|
bool success = false;
|
|
if (strlen(prefix) > 64)
|
|
return false;
|
|
ddio_GetWorkingDir(old_workdir, _MAX_PATH);
|
|
if (!ddio_DirExists(basedir)) {
|
|
return false; // invalid base directory
|
|
}
|
|
char randname[10];
|
|
int index;
|
|
int tries = 0;
|
|
char rc;
|
|
bool created = false;
|
|
index = 0;
|
|
|
|
while (!success && tries < 20) {
|
|
// generate a bunch of random characters
|
|
rc = (rand() % 128);
|
|
if ((rc >= 'a' && rc <= 'z') || (rc >= 'A' && rc <= 'Z') || (rc >= '0' && rc <= '9')) {
|
|
// valid character
|
|
randname[index] = rc;
|
|
index++;
|
|
if (index == 10) {
|
|
// we hit the size of our max, see if we generated a unique filename
|
|
char t[_MAX_PATH];
|
|
randname[9] = '\0';
|
|
sprintf(t, "%s%s.tmp", prefix, randname);
|
|
// see if we can find this file
|
|
FILE *fd = mac_fopen(t, "rb");
|
|
if (!fd) {
|
|
// we found a good file!
|
|
ddio_MakePath(filename, basedir, t, NULL);
|
|
success = true;
|
|
created = true;
|
|
} else {
|
|
// already taken
|
|
fclose(fd);
|
|
tries++;
|
|
index = 0;
|
|
}
|
|
}
|
|
} else {
|
|
continue; // try again
|
|
}
|
|
}
|
|
ddio_SetWorkingDir(old_workdir);
|
|
return created;
|
|
}
|
|
// These functions allow one to find a file
|
|
// You use FindFileStart by giving it a wildcard (like *.*, *.txt, u??.*, whatever). It returns
|
|
// a filename in namebuf.
|
|
// Use FindNextFile to get the next file found with the wildcard given in FindFileStart.
|
|
// Use FindFileClose to end your search.
|
|
// These functions allow one to find a file
|
|
// You use FindFileStart by giving it a wildcard (like *.*, *.txt, u??.*, whatever). It returns
|
|
// a filename in namebuf.
|
|
// Use FindNextFile to get the next file found with the wildcard given in FindFileStart.
|
|
// Use FindFileClose to end your search.
|
|
int fileIndex = 1;
|
|
char wildsave[10];
|
|
bool ddio_FindFileStart(const char *wildcard, char *namebuf) {
|
|
ASSERT(wildcard);
|
|
ASSERT(namebuf);
|
|
|
|
fileIndex = 1;
|
|
char tempbuffer[_MAX_PATH];
|
|
|
|
if (strrchr(wildcard, ':')) {
|
|
strcpy(tempbuffer, wildcard);
|
|
|
|
char *c = strrchr(tempbuffer, '*');
|
|
strcpy(wildsave, c);
|
|
*c = '\0';
|
|
|
|
if (!ddio_DirExists(tempbuffer))
|
|
return (false);
|
|
|
|
} else {
|
|
strcpy(wildsave, wildcard);
|
|
}
|
|
|
|
ddio_SaveWorkingDir();
|
|
ddio_SetWorkingDir(tempbuffer);
|
|
if (ddio_FindNextFile(namebuf))
|
|
return (true);
|
|
else
|
|
return (false);
|
|
}
|
|
bool ddio_FindNextFile(char *namebuf) {
|
|
short err;
|
|
FileParam fpb;
|
|
CInfoPBRec cpb;
|
|
Str255 volName = "\p";
|
|
short volRefNum = 0;
|
|
long dirID = 0;
|
|
ASSERT(namebuf);
|
|
getAnother:
|
|
namebuf[0] = 0;
|
|
err = HGetVol(volName, &volRefNum, &dirID);
|
|
if (err)
|
|
return false;
|
|
/*
|
|
fpb.ioNamePtr=(unsigned char *)namebuf;
|
|
fpb.ioFDirIndex=fileIndex;
|
|
fpb.ioVRefNum=0;
|
|
// retrun just file info
|
|
err = PBGetFInfoSync( (ParmBlkPtr)&fpb );
|
|
*/
|
|
// returns both file & dir info
|
|
cpb.hFileInfo.ioVRefNum = volRefNum;
|
|
cpb.hFileInfo.ioDirID = dirID;
|
|
cpb.hFileInfo.ioNamePtr = (unsigned char *)namebuf;
|
|
cpb.hFileInfo.ioFDirIndex = fileIndex;
|
|
|
|
err = PBGetCatInfoSync(&cpb);
|
|
|
|
// if((cpb.hFileInfo.io.FlAttrib & (1<<4)))
|
|
if (err == fnfErr) {
|
|
return (false);
|
|
} else {
|
|
p2cstr((unsigned char *)namebuf);
|
|
fileIndex++;
|
|
if (PSGlobMatch(wildsave, namebuf, 0, 0)) {
|
|
return (true);
|
|
} else {
|
|
goto getAnother;
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
void ddio_FindFileClose() {
|
|
ddio_RestoreWorkingDir();
|
|
fileIndex = 1;
|
|
wildsave[0] = NULL;
|
|
}
|
|
// pass in a pathname (could be from ddio_SplitPath), root_path will have the drive name.
|
|
void ddio_GetRootFromPath(const char *srcPath, char *root_path) {
|
|
assert(root_path);
|
|
assert(srcPath);
|
|
// the first char should be drive letter, second char should be a :
|
|
// if(!(srcPath[0]==':')){
|
|
// everything is ok
|
|
// strncpy(root_path,srcPath,2);
|
|
// root_path[2] = '\0';
|
|
// }else{
|
|
// invalid path (no root)
|
|
root_path[0] = '\0';
|
|
// }
|
|
}
|
|
// retrieve root names, free up roots array (allocated with malloc) after use
|
|
int ddio_GetFileSysRoots(char **roots, int max_roots) {
|
|
#ifdef FIXED
|
|
char buffer[100];
|
|
int ret = GetLogicalDriveStrings(100, buffer);
|
|
if (ret == 0) {
|
|
// there was an error
|
|
return 0;
|
|
}
|
|
if (ret > 100) {
|
|
// we didn't have enough space
|
|
return 0;
|
|
}
|
|
int count = 0;
|
|
bool done = false;
|
|
char *strptr = buffer;
|
|
char *string;
|
|
int strsize;
|
|
while ((count < max_roots) && (!done)) {
|
|
if (*strptr != 0) {
|
|
strsize = strlen(strptr);
|
|
string = roots[count] = (char *)mem_malloc(strsize);
|
|
if (!string)
|
|
break;
|
|
// remove the trailing \ from windows
|
|
strncpy(string, strptr, strsize - 1);
|
|
string[strsize - 1] = '\0';
|
|
|
|
strptr += (strsize + 1);
|
|
count++;
|
|
} else
|
|
done = true;
|
|
}
|
|
return count;
|
|
#endif // FIXED
|
|
|
|
return 0;
|
|
}
|
|
// given a path, it cleans it up (if the path is c:\windows\..\dos it would make it c:\dos)
|
|
// srcPath is the original path
|
|
// dest is the finished cleaned path.
|
|
// dest should be at least _MAX_PATH in size
|
|
void ddio_CleanPath(char *dest, const char *srcPath) {
|
|
strcpy(dest, srcPath);
|
|
// break the path into directories
|
|
char **directories;
|
|
int dirs;
|
|
int path_length;
|
|
// make sure the path ends with a \ for sanity
|
|
path_length = strlen(dest);
|
|
if (dest[path_length - 1] != ':') {
|
|
dest[path_length] = ':';
|
|
dest[path_length + 1] = '\0';
|
|
path_length++;
|
|
}
|
|
// now divide the full path into seperate NULL terminated strings,counting the number
|
|
// of directories in the process
|
|
dirs = 0;
|
|
char *strptr = dest;
|
|
while (*strptr != '\0') {
|
|
if (*strptr == ':') {
|
|
*strptr = '\0';
|
|
dirs++;
|
|
}
|
|
strptr++;
|
|
}
|
|
// check to make sure we have a directory, if we don't then return the original path given
|
|
if (dirs == 0) {
|
|
strcpy(dest, srcPath);
|
|
return;
|
|
}
|
|
// allocate the memory needed for the seperate strings of each directory
|
|
directories = (char **)mem_malloc(sizeof(char *) * dirs);
|
|
if (!directories) {
|
|
strcpy(dest, srcPath);
|
|
return;
|
|
}
|
|
// now get all the directories, and place into the individual strings
|
|
strptr = dest;
|
|
int count = 0;
|
|
while (count < dirs) {
|
|
directories[count] = mem_strdup(strptr);
|
|
strptr += strlen(strptr) + 1;
|
|
count++;
|
|
}
|
|
// now the fun part, figure out the correct order of the directories
|
|
int *dir_order;
|
|
dir_order = (int *)mem_malloc(sizeof(int) * dirs);
|
|
if (!dir_order) {
|
|
strcpy(dest, srcPath);
|
|
return;
|
|
}
|
|
for (count = 0; count < dirs; count++)
|
|
dir_order[count] = -1; // a -1 means the end of the sequence
|
|
// now build the order based on the indicies
|
|
int curr_index = 0;
|
|
for (count = 0; count < dirs; count++) {
|
|
|
|
if (!stricmp(directories[count], "..")) {
|
|
// we have to back up a directory
|
|
curr_index--; // back up
|
|
if (curr_index < 0)
|
|
curr_index = 0; // can't go further than root
|
|
dir_order[curr_index] = -1; // invalidate current slot
|
|
} else if (stricmp(directories[count], ".")) {
|
|
// we have a normal directory, add it's index
|
|
dir_order[curr_index] = count;
|
|
curr_index++;
|
|
}
|
|
}
|
|
// now rebuild the correct path for use, when we hit -1, we're done
|
|
dest[0] = '\0';
|
|
for (count = 0; count < dirs; count++) {
|
|
if (dir_order[count] == -1)
|
|
break;
|
|
else {
|
|
strcat(dest, directories[dir_order[count]]);
|
|
strcat(dest, ":");
|
|
}
|
|
}
|
|
// now remove trailing \ char
|
|
path_length = strlen(dest);
|
|
if ((path_length > 0) && (dest[path_length - 1] == ':'))
|
|
dest[path_length - 1] = '\0';
|
|
// free up all the allocated memory and we're done
|
|
for (count = 0; count < dirs; count++) {
|
|
if (directories[count])
|
|
mem_free(directories[count]);
|
|
}
|
|
if (directories)
|
|
mem_free(directories);
|
|
if (dir_order)
|
|
mem_free(dir_order);
|
|
}
|
|
// given a path (with no filename), it will return the parent path
|
|
// srcPath is the source given path
|
|
// dest is where the parent path will be placed
|
|
// returns true on success
|
|
// dest should be at least _MAX_PATH in length
|
|
bool ddio_GetParentPath(char *dest, const char *srcPath) {
|
|
assert(srcPath);
|
|
assert(dest);
|
|
|
|
strcpy(dest, srcPath);
|
|
char *c = strrchr(dest, ':');
|
|
*c = '\0';
|
|
|
|
return true;
|
|
}
|
|
// Finds a full path from a relative path
|
|
// Parameters: full_path - filled in with the fully-specified path. Buffer must be at least _MAX_PATH bytes long
|
|
// rel_path - a path specification, either relative or absolute
|
|
// Returns TRUE if successful, FALSE if an error
|
|
bool ddio_GetFullPath(char *full_path, const char *rel_path) {
|
|
char old_path[_MAX_PATH];
|
|
ddio_GetWorkingDir(old_path, sizeof(old_path)); // save old directory
|
|
if (!ddio_SetWorkingDir(rel_path)) // try switching to new directory
|
|
return 0; // couldn't switch, so return error
|
|
ddio_GetWorkingDir(full_path, _MAX_PATH); // get path from the OS
|
|
ddio_SetWorkingDir(old_path); // now restore old path
|
|
return 1;
|
|
}
|
|
// Renames file
|
|
// Returns true on success or false on an error
|
|
bool ddio_RenameFile(char *oldfile, char *newfile) {
|
|
int rcode = rename(oldfile, newfile);
|
|
if (!rcode)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
// Give a volume label to look for, and if it's found returns a path
|
|
// If it isn't found, return ""
|
|
char *ddio_GetCDDrive(char *vol) {
|
|
|
|
bool res = true;
|
|
|
|
ddio_SaveWorkingDir();
|
|
res = ddio_DirExists(vol);
|
|
ddio_RestoreWorkingDir();
|
|
|
|
if (res)
|
|
return mem_strdup(vol);
|
|
else
|
|
return '\0';
|
|
}
|
|
int ddio_CheckLockFile(const char *dir) { return 0; }
|
|
int ddio_CreateLockFile(const char *dir) { return 0; }
|
|
int ddio_DeleteLockFile(const char *dir) { return 0; }
|
|
// routine to take a DOS path and turn it into a macintosh
|
|
// pathname.
|
|
void macify_dospath(const char *dos_path, char *mac_path) {
|
|
assert(dos_path != NULL);
|
|
assert(mac_path != NULL);
|
|
|
|
mac_path[0] = 0;
|
|
|
|
// Remove leading relative directory references
|
|
int i = 0;
|
|
if (dos_path[i] == '.') {
|
|
if (!strnicmp(dos_path, "..\\", 3)) {
|
|
strcat(mac_path, "::");
|
|
i += 3;
|
|
} else if (!strnicmp(dos_path, ".\\", 2)) {
|
|
strcat(mac_path, ":");
|
|
i += 2;
|
|
}
|
|
|
|
while (dos_path[i] == '.') {
|
|
if (!strnicmp(&(dos_path[i]), "..\\", 3)) {
|
|
strcat(mac_path, ":");
|
|
i += 3;
|
|
} else if (!strnicmp(&(dos_path[i]), ".\\", 2)) {
|
|
i += 2;
|
|
}
|
|
}
|
|
|
|
strcat(mac_path, &(dos_path[i]));
|
|
} else // no leading relative references
|
|
{
|
|
// Check if this is a full pathname
|
|
if (dos_path[0] == '\\') {
|
|
// Get current volume name
|
|
Str255 volName = "\p";
|
|
short volRefNum = 0;
|
|
long dirID = 0;
|
|
OSErr err = noErr;
|
|
|
|
err = HGetVol(volName, &volRefNum, &dirID);
|
|
assert(err == noErr);
|
|
p2cstr(volName);
|
|
strcat(mac_path, (char *)volName);
|
|
strcat(mac_path, ":");
|
|
strcat(mac_path, &(dos_path[1]));
|
|
} else {
|
|
strcat(mac_path, ":");
|
|
strcat(mac_path, dos_path);
|
|
}
|
|
}
|
|
|
|
// Leading references have been resolved
|
|
// Now replace remaining '/' with ':'
|
|
char *p = NULL;
|
|
while ((p = strchr(mac_path, '\\')) != NULL) {
|
|
*p = ':';
|
|
}
|
|
}
|
|
|
|
#include <Errors.h>
|
|
// #include <Files.h>
|
|
#include <Script.h>
|
|
#include "file_io.h"
|
|
|
|
#define text_type 'TEXT'
|
|
#define binary_type 'BINA'
|
|
#define creator 'GSCe'
|
|
|
|
FILE *mac_fopen(char *filename, const char *open_mode) {
|
|
__file_modes mode;
|
|
short permission;
|
|
OSErr ioResult;
|
|
short refNum;
|
|
OSType file_type;
|
|
FILE *file;
|
|
|
|
FSSpec spec;
|
|
Str255 macName;
|
|
|
|
strcpy((char *)macName, filename);
|
|
c2pstr((char *)macName);
|
|
|
|
ioResult = FSMakeFSSpec(0, 0L, macName, &spec);
|
|
|
|
if (!__get_file_modes(open_mode, &mode))
|
|
return (NULL);
|
|
|
|
permission = (mode.io_mode == __read) ? fsRdPerm : fsRdWrPerm;
|
|
|
|
ioResult = FSpOpenDF(&spec, permission, &refNum);
|
|
|
|
if (ioResult) {
|
|
if (ioResult != fnfErr || mode.open_mode == __must_exist)
|
|
return (NULL);
|
|
|
|
file_type = 'GSCf';
|
|
// file_type = (mode.binary_io) ? binary_type : text_type;
|
|
|
|
if (!(ioResult = FSpCreate(&spec, creator, file_type, smSystemScript)))
|
|
ioResult = FSpOpenDF(&spec, permission, &refNum);
|
|
|
|
if (ioResult)
|
|
return (NULL);
|
|
} else if (mode.open_mode == __create_or_truncate) {
|
|
ioResult = SetEOF(refNum, 0);
|
|
|
|
if (ioResult) {
|
|
FSClose(refNum);
|
|
return (NULL);
|
|
}
|
|
}
|
|
|
|
file = __handle_open(refNum, open_mode);
|
|
|
|
if (!file)
|
|
FSClose(refNum);
|
|
|
|
return (file);
|
|
}
|
|
FILE *FSp_fopen(ConstFSSpecPtr spec, const char *open_mode, OSType type) {
|
|
__file_modes mode;
|
|
short permission;
|
|
OSErr ioResult;
|
|
short refNum;
|
|
OSType file_type;
|
|
FILE *file;
|
|
|
|
if (!__get_file_modes(open_mode, &mode))
|
|
return (NULL);
|
|
|
|
permission = (mode.io_mode == __read) ? fsRdPerm : fsRdWrPerm;
|
|
|
|
ioResult = FSpOpenDF(spec, permission, &refNum);
|
|
|
|
if (ioResult) {
|
|
if (ioResult != fnfErr || mode.open_mode == __must_exist)
|
|
return (NULL);
|
|
|
|
if (!(ioResult = FSpCreate(spec, creator, type, smSystemScript)))
|
|
ioResult = FSpOpenDF(spec, permission, &refNum);
|
|
|
|
if (ioResult)
|
|
return (NULL);
|
|
} else if (mode.open_mode == __create_or_truncate) {
|
|
ioResult = SetEOF(refNum, 0);
|
|
|
|
if (ioResult) {
|
|
FSClose(refNum);
|
|
return (NULL);
|
|
}
|
|
}
|
|
|
|
file = __handle_open(refNum, open_mode);
|
|
|
|
if (!file)
|
|
FSClose(refNum);
|
|
|
|
return (file);
|
|
}
|