mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
1041 lines
24 KiB
C++
1041 lines
24 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);
|
|
}
|