Common Files/FileUtilities.c

//////////
//
//  File:       FileUtilities.c
//
//  Contains:   Some utilities for working with pathnames, files, and file specifications.
//              All utilities start with the prefix "FileUtils_".
//
//  Written by: Tim Monroe
//
//  Copyright:  © 1999 by Apple Computer, Inc., all rights reserved.
//
//  Change History (most recent first):
//
//     <1>      05/27/99    rtm     first file
//
//////////
 
 
//////////
//
// header files
//
//////////
 
#ifndef __FileUtilities__
#include "FileUtilities.h"
 
 
//////////
//
// FileUtils_MakeFSSpecForPathName
// Fill in the specified FSSpec, using the specified volume, directory, and pathname information.
//
// On Windows, the volume and directory info are ignored; if the pathname is not a full pathname,
// create a full pathname using the current directory as a base path.
//
//////////
 
OSErr FileUtils_MakeFSSpecForPathName (short theVRefNum, long theDirID, char *thePathName, FSSpec *theFSSpec)
{
#if TARGET_OS_WIN32
#pragma unused(theVRefNum, theDirID)
    char        myFullPath[MAX_PATH];
#endif
    StringPtr   myStringPtr = NULL;
    OSErr       myErr = noErr;
    
    if ((thePathName == NULL) || (theFSSpec == NULL))
        return(paramErr);
            
#if TARGET_OS_MAC
    // on the MacOS, it doesn't matter whether thePathName is a full pathname or not,
    // since FSMakeFSSpec will do the right thing in either case
    myStringPtr = URLUtils_ConvertCToPascalString(thePathName);
        
    myErr = FSMakeFSSpec(theVRefNum, theDirID, myStringPtr, theFSSpec);
#endif
#if TARGET_OS_WIN32
    if (FileUtils_IsFullPathName(thePathName)) {
        myStringPtr = URLUtils_ConvertCToPascalString(thePathName);
        
        myErr = FSMakeFSSpec(0, 0L, myStringPtr, theFSSpec);
    } else {
        // thePathName is not a full pathname, so construct a full pathname relative
        // to the current directory; if doing so would make a pathname that's too large,
        // then just return an error
        GetCurrentDirectory(MAX_PATH, myFullPath);
        
        if (strlen(myFullPath) + strlen(kFilePathSepString) + strlen(thePathName) + 1 > MAX_PATH)
            return(paramErr);
            
        strcat(myFullPath, kFilePathSepString);
        strcat(myFullPath, thePathName);
        
        myStringPtr = URLUtils_ConvertCToPascalString(thePathName);
 
        myErr = FSMakeFSSpec(0, 0L, c2pstr(myFullPath), theFSSpec);
    }
#endif
 
    free(myStringPtr);
 
    return(myErr);
}
 
 
//////////
//
// FileUtils_MakeFSSpecForAnyFileInDir
// Return, through theFileFSSpec, a file specification for a file (possibly nonexistent) in the specified directory.
//
//////////
 
OSErr FileUtils_MakeFSSpecForAnyFileInDir (Str255 thePathName, FSSpecPtr theFileFSSpec)
{
    Str255      myString;
    short       myLength = thePathName[0];
    OSErr       myErr = noErr;
    
    // make sure we have enough space to add the path separator and a 1-character
    // file name onto thePathName
    if (myLength + 2 > 255)
        return(paramErr);
 
    BlockMove(&thePathName[1], &myString[1], myLength);
    myString[myLength + 1] = kFilePathSeparator;
    myString[myLength + 2] = 'a';   // a short and simple bogus file name
    myString[0] = myLength + 2;
    myErr = FSMakeFSSpec(0, 0L, myString, theFileFSSpec);
    
    return(myErr);
}
 
 
//////////
//
// FileUtils_IsFullPathName
// Is the specified pathname a full pathname?
//
// NOTE: THIS IS QUICK AND DIRTY, AND NEEDS TO BE REWORKED
//
//////////
 
static Boolean FileUtils_IsFullPathName (char *thePathName)
{
#if TARGET_OS_MAC
    // we need to do some work here, eh?
    return(true);
#endif
 
#if TARGET_OS_WIN32
    // on Windows, a full pathname always begins with a disk designator or a server name;
    // for the time being, we will support *local* files only
    if ((strlen(thePathName) >= 2) && (URLUtils_IsAlphabetic(thePathName[0])) && (thePathName[1] == kWinVolumeNameChar))
        return(true);
    else
        return(false);
#endif
}
 
 
//////////
//
// FileUtils_GetBaseName
// Return the basename of the specified pathname.
//
// Based heavily on URLUtils_GetURLBasename.
//
//////////
 
char *FileUtils_GetBaseName (char *thePathName)
{
    char    *myBasename = NULL;
    short   myLength = 0;
    short   myIndex;
 
    // make sure we got a pathname passed in
    if (thePathName == NULL)
        goto bail;
        
    // get the length of the pathname
    myLength = strlen(thePathName);
    
    // find the position of the rightmost file path separator in thePathName
    if (strchr(thePathName, kFilePathSeparator) != NULL) {
 
        myIndex = myLength - 1;
        while (thePathName[myIndex] != kFilePathSeparator)
            myIndex--;
            
        // calculate the length of the basename
        myLength = myLength - myIndex - 1;
 
    } else {
        // there is no rightmost file path separator in thePathName;
        // set myIndex so that myIndex + 1 == 0, for the call to BlockMove below
        myIndex = -1;
    }
    
    // allocate space to hold the string that we return to the caller
    myBasename = malloc(myLength + 1);
    if (myBasename == NULL)
        goto bail;
        
    // copy into myBasename the substring of thePathName from myIndex + 1 to the end
    BlockMove(&thePathName[myIndex + 1], myBasename, myLength);
    myBasename[myLength] = '\0';
    
bail:   
    return(myBasename);
}
 
 
//////////
//
// FileUtils_ChangeFileNameSuffix
// Change the suffix of the specified filename to the specified suffix;
// return the new filename as the function result.
//
//////////
 
char *FileUtils_ChangeFileNameSuffix (char *thePathName, char *theNewSuffix)
{
    char        *myNewName = NULL;
    short       myLength = 0;
    short       myIndex;
    Boolean     myNeedSep;
 
    // make sure we got a pathname passed in
    if (thePathName == NULL)
        goto bail;
        
    // get the length of the pathname
    myLength = strlen(thePathName);
    
    // find the position of the rightmost file suffix separator in thePathName
    if (strchr(thePathName, kFileSuffixSeparator) != NULL) {
        myNeedSep = false;
        
        myIndex = myLength - 1;
        while (thePathName[myIndex] != kFileSuffixSeparator)
            myIndex--;
            
        // calculate the length of the filename less the suffix, but including the separator
        myLength = myIndex + 1;
 
    } else {
        // there is no rightmost file suffix separator in thePathName
        myNeedSep = true;
    }
    
    // allocate space to hold the string that we return to the caller
    myNewName = malloc(myLength + (myNeedSep ? 1 : 0) + strlen(theNewSuffix));
    if (myNewName == NULL)
        goto bail;
        
    // copy into myBasename the substring of thePathName from the start to position myIndex
    BlockMove(thePathName, myNewName, myLength);
    if (myNeedSep)
        strcat(myNewName, kFileSuffixSepString);
    strcat(myNewName, theNewSuffix);
    
    myNewName[myLength + (myNeedSep ? 1 : 0) + strlen(theNewSuffix)] = '\0';
    
bail:   
    return(myNewName);
}
 
 
 
#endif  // ifndef __FileUtilities__