mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
643 lines
22 KiB
C
643 lines
22 KiB
C
|
/*
|
|||
|
File: alFind.c
|
|||
|
|
|||
|
Contains: Find files, folders etc. by various means.
|
|||
|
|
|||
|
Written by: Prashant Patel
|
|||
|
|
|||
|
Copyright: <EFBFBD> 1989-1991 by Apple Computer, Inc., all rights reserved.
|
|||
|
|
|||
|
This file is used in these builds: BigBang
|
|||
|
|
|||
|
Change History (most recent first):
|
|||
|
|
|||
|
<23> 2/5/91 stb gs: fix casing
|
|||
|
<22> 1/11/91 PP (ich) If parent directory exists but target does not exist,
|
|||
|
return the correct parent directory as a hint for relative path
|
|||
|
case.
|
|||
|
<21> 1/2/91 PP (ich) FindGivenPath returns a hint directory.
|
|||
|
<20> 12/20/90 PP (ich) Move AL_attribMatches to alExt.c.
|
|||
|
<19> 12/13/90 PP (ich) All find by path routines also return the leaf name if
|
|||
|
found.
|
|||
|
<18> 10/21/90 gbm Change hfileInfo to hFileInfo for the last time.
|
|||
|
<18> 10/10/90 JL Change hfileInfo to hFileInfo for the last time.
|
|||
|
<17> 10/10/90 PP For creation dates on AppleShare volumes, need to store raw data
|
|||
|
instead of time adjusted to current machine's date.
|
|||
|
<16> 8/28/90 dnf Change references to PBResolveFileID into PBResolveFileIDRef
|
|||
|
<15> 6/28/90 PP Convert CanonicalFileSpec to FSSpec.
|
|||
|
<14> 6/15/90 PP Special Traps to support dialog code are no longer traps.
|
|||
|
<13> 5/31/90 PP Relative path search should work with partial path > 255
|
|||
|
characters in length.
|
|||
|
<12> 5/16/90 PP AuxAliasInfo parameter added to AL_findVolume.
|
|||
|
<11> 5/3/90 PP Incorporate Diet Tips.
|
|||
|
<10> 4/10/90 PP Change once more hFileInfo to hfileInfo to stay consistent with
|
|||
|
Files.h
|
|||
|
<9> 4/10/90 PP Add support for kARMnoUI bit.
|
|||
|
<8> 4/5/90 PP Code size optimization.
|
|||
|
<7> 3/16/90 PP Conform to CatSearch parameter block change.
|
|||
|
<6> 3/8/90 PP Add minimal alias support. Change "hfileInfo" to "hFileInfo'"
|
|||
|
to match Files.h change.
|
|||
|
<5> 2/26/90 dnf Rename ioQuant to ioSearchTime, positionRec to CatPositionRec
|
|||
|
<4> 2/6/90 PP PBHResolveID call is now PBResolveFileID.
|
|||
|
<3> 1/21/90 PP AttribMatches routine has an additional argument. Some code
|
|||
|
optimization and fix bug in slow search that caused MatchAlias
|
|||
|
to hang.
|
|||
|
<2.6> 12/15/89 prp FindVolume uses different heuristics.
|
|||
|
<2.5> 11/27/89 prp Add SwitchDisk dialog for Ejectable floppies.
|
|||
|
<2.4> 11/16/89 prp During slow search without CatSearch matching criterion is file
|
|||
|
number on the original volume and not on all mounted volumes. In
|
|||
|
FindVolume, if auto mount happened, check the creation date and
|
|||
|
set the needsUpdate flag if it has changed. In
|
|||
|
FindAbsPathToRoot, return fnfErr if ndirsToRoot is zero.
|
|||
|
<2.3> 10/30/89 prp <EFBFBD> AppleShare volumes return wrgVolTypeErr when CatSearch and
|
|||
|
FileIDs not supported. <EFBFBD> Add AL_findVolume routine that combines
|
|||
|
various volume searching heuristics.
|
|||
|
<2.2> 10/13/89 prp Bug fix related to folder name.
|
|||
|
<2.1> 10/2/89 prp FileID and fileNum fields in Alias record are now same since the
|
|||
|
fileID interpretation has changed.
|
|||
|
<2.0> 9/18/89 prp FindBySlowSearch is client filtering aware.
|
|||
|
<1.9> 9/6/89 prp Changes from CodeReview.
|
|||
|
<1.8> 8/11/89 prp Handle eofErr as a valid legal error from CatSearch.
|
|||
|
<1.7> 8/7/89 prp Add SelectAlias with dialog support. Add automatic volume mount
|
|||
|
support.
|
|||
|
<1.6> 7/31/89 prp Since FileIDs.h has now merged with Files.h, remove its
|
|||
|
inclusion and fix names of fields that have changed in FIDParam.
|
|||
|
<1.5> 7/6/89 prp FileID calls across AppleShare volumes return noErr but garbage
|
|||
|
data. Do not use FileIDs if alias is on AppleShare volume.
|
|||
|
<1.4> 6/12/89 prp Incorporate FileIDs and CatSearch. Added slow search. Cleaned up
|
|||
|
IFNDEFs.
|
|||
|
<1.3> 6/6/89 prp EqualString test was inverted.
|
|||
|
<1.2> 6/1/89 prp In AL_findbyNum, ioNamePtr assignment is now out of loop.
|
|||
|
<1.1> 5/31/89 prp Moved AliasRecord to Private Definition File. Changed FileEntity
|
|||
|
to FileSpec.
|
|||
|
<1.0> 5/30/89 prp Initial Release
|
|||
|
|
|||
|
To Do:
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*
|
|||
|
* File: alFind.c
|
|||
|
* Project: Alias Manager
|
|||
|
* Contains: routines that support finding of an alias
|
|||
|
* Written by: Prashant Patel
|
|||
|
*
|
|||
|
* Copyright 1989 by Apple Computer, Inc.
|
|||
|
* All Rights Reserved.
|
|||
|
*
|
|||
|
**********************************************************************/
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
*************** Public Include files *******************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
#include "Aliases.h"
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
*************** Private Include files *******************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
#include "aliasPriv.h"
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
*************** External C Include files ***************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
#ifndef __MEMORY__
|
|||
|
#include <Memory.h>
|
|||
|
#endif
|
|||
|
#ifndef __FILES__
|
|||
|
#include <files.h>
|
|||
|
#endif
|
|||
|
#ifndef __ERRORS__
|
|||
|
#include <errors.h>
|
|||
|
#endif
|
|||
|
#ifndef __STRING__
|
|||
|
#include <String.h>
|
|||
|
#endif
|
|||
|
#ifndef __TOOLUTILS__
|
|||
|
#include <ToolUtils.h>
|
|||
|
#endif
|
|||
|
#ifndef __OSUTILS__
|
|||
|
#include <OSUtils.h>
|
|||
|
#endif
|
|||
|
#ifndef __STDLIB__
|
|||
|
#include <StdLib.h>
|
|||
|
#endif
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find volume by name ***************************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
pascal OSErr ALI_findVolByName (const StringPtr vname, //I volume name
|
|||
|
HVolumeParam *vpbPtr) //O volume parameter block
|
|||
|
|
|||
|
{
|
|||
|
OSErr err; // result code
|
|||
|
Str31 localName; // temporary local name
|
|||
|
|
|||
|
if (vname == NULL)
|
|||
|
return (paramErr);
|
|||
|
|
|||
|
AL_copyPString (vname, localName);
|
|||
|
|
|||
|
/* To force a lookup by a volume name, the name has to end in a volume separator
|
|||
|
character (colon). Otherwise, it will use the ioVRefNum field. */
|
|||
|
|
|||
|
if (localName[Length(localName)] != kChrSeparator) {
|
|||
|
|
|||
|
++(Length(localName));
|
|||
|
localName[Length(localName)] = kChrSeparator;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
vpbPtr->ioNamePtr = localName; // look for this name
|
|||
|
vpbPtr->ioVolIndex = -1; // find by name mode
|
|||
|
vpbPtr->ioVRefNum = 0;
|
|||
|
|
|||
|
err = PBHGetVInfo ((HParmBlkPtr)vpbPtr, FALSE);
|
|||
|
|
|||
|
vpbPtr->ioNamePtr = NULL; // make sure it is not used by client
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findVolByName routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find volume by vRefNum ***********************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
pascal OSErr AL_findVolByVRefNum (short vref, //I volume reference number
|
|||
|
HVolumeParam *vpbPtr) //O volume parameter block
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
vpbPtr->ioNamePtr = NULL; // not interested in name
|
|||
|
vpbPtr->ioVolIndex = 0; // find by vRefNum mode
|
|||
|
vpbPtr->ioVRefNum = vref; // put the vref in
|
|||
|
|
|||
|
return (PBHGetVInfo ((HParmBlkPtr)vpbPtr, FALSE));
|
|||
|
|
|||
|
} // end of AL_findVolByVRefNum routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find volume ***********************************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
OSErr AL_findVolume (const AliasPtrPriv aptr, //I alias record pointer
|
|||
|
unsigned long sMask, //I search mask
|
|||
|
short *vref, //O volume reference number
|
|||
|
Boolean *needsUpdate, //O did anything about volume change?
|
|||
|
AuxAliasInfo *auxInfo) //I auxiliary alias record info
|
|||
|
|
|||
|
{
|
|||
|
OSErr err; // result code
|
|||
|
|
|||
|
err = AL_checkIfMounted(aptr, vref, needsUpdate);
|
|||
|
|
|||
|
if (err == nsvErr) { // no such volume
|
|||
|
|
|||
|
// auto mount specified by client. but no auto mount for minimal fullpath aliases.
|
|||
|
|
|||
|
if ((sMask & kARMMountVol) && aptr->volumeType != kInvalidValue)
|
|||
|
|
|||
|
err = AL_mountVolume (aptr, vref, needsUpdate,
|
|||
|
sMask & kARMNoUI ? kNoUserInterface : kUserInterface, auxInfo);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findVolume routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find directory by ID ***********************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
pascal OSErr ALI_findDirByID ( short vref, //I volume reference number/WD ref
|
|||
|
long dirID, //I directory ID
|
|||
|
long *newParDirID, //O dir's parent dir's ID
|
|||
|
StringPtr dname) //O found dir's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err; // result code
|
|||
|
CInfoPBRec cpb; // catalog info parameter block
|
|||
|
|
|||
|
cpb.dirInfo.ioFDirIndex = -1; // interesetd in directory only
|
|||
|
|
|||
|
if ((err = AL_getCatInfo (vref, dirID, dname, &cpb)) == noErr)
|
|||
|
// found the directory by its ID
|
|||
|
*newParDirID = cpb.dirInfo.ioDrParID;
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findDirByID routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file or directory by name ***************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
pascal OSErr ALI_findByName (short vref, //I volume reference number/WD ref
|
|||
|
long dirID, //I parent directory ID
|
|||
|
const StringPtr fname, //I file/dir name
|
|||
|
long *fnum, //O file number or directory ID
|
|||
|
long *parDirID) //O parent's directory ID
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err; // result code
|
|||
|
CInfoPBRec cpb; // catalog info parameter block
|
|||
|
|
|||
|
cpb.hFileInfo.ioFDirIndex = 0; // find by name mode
|
|||
|
|
|||
|
if ((err = AL_getCatInfo (vref, dirID, fname, &cpb)) == noErr) {
|
|||
|
|
|||
|
// found the file/directory by name
|
|||
|
*fnum = cpb.hFileInfo.ioDirID; // return its file number or dir ID
|
|||
|
*parDirID = cpb.hFileInfo.ioFlParID; // its folder's dir ID
|
|||
|
|
|||
|
#ifndef HFSBUG_FIXED
|
|||
|
/* Bug in HFS, if you look for name ":" in dirID 2, it returns parent as 2 and not 1. */
|
|||
|
if (*fnum == kRootDirID && (cpb.hFileInfo.ioFlAttrib & kDirMask))
|
|||
|
*parDirID = kVolRootDirID;
|
|||
|
}
|
|||
|
#endif HFSBUG_FIXED
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findByName routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file by ID *******************************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
pascal OSErr ALI_findFileByID (short vref, //I volume reference number/WD ref
|
|||
|
long fileID, //I file ID
|
|||
|
long *newParDirID, //O file's parent's dir ID
|
|||
|
StringPtr fname) //O file's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err; // result code
|
|||
|
|
|||
|
FIDParam hpb; // H parameter block for fileID
|
|||
|
|
|||
|
if (fileID == kInvalidValue) // for minimal aliases, no valid fileID
|
|||
|
return(fnfErr);
|
|||
|
|
|||
|
hpb.ioVRefNum = vref; // on this volume/working directory
|
|||
|
hpb.ioFileID = fileID; // this fileID
|
|||
|
hpb.ioNamePtr = fname; // return the name
|
|||
|
|
|||
|
if ((err = PBResolveFileIDRef((HParmBlkPtr)&hpb, FALSE)) == noErr) // resolve file ID
|
|||
|
*newParDirID = hpb.ioSrcDirID; // found it in this folder
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findFileByID routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file or directory by ID ***************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
OSErr AL_findByID ( short vref, //I volume reference number/WD ref
|
|||
|
const AliasPtrPriv aptr,//I alias record pointer
|
|||
|
long *newParDirID, //O file's folder's directory ID
|
|||
|
StringPtr fname) //O file name
|
|||
|
|
|||
|
{
|
|||
|
if (aptr->thisAliasKind == kFileAlias) // for files, use findFileByID
|
|||
|
return (AL_findFileByID (vref, aptr->fileNum, newParDirID, fname));
|
|||
|
|
|||
|
else if (aptr->thisAliasKind == kDirAlias) // for folders, use findDirByID
|
|||
|
return (AL_findDirByID (vref, aptr->fileNum, newParDirID, fname));
|
|||
|
|
|||
|
} // end of AL_findByID routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file by number ***************************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
pascal OSErr ALI_findFileByNum (short vref, //I volume reference number/WD ref
|
|||
|
long dirID, //I ID of directory to be searched
|
|||
|
long fnum, //I this file number
|
|||
|
StringPtr fname) //O if found, file's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err; // result code
|
|||
|
CInfoPBRec cpb; // catalog info param block
|
|||
|
Str63 localName; // local temporary name
|
|||
|
|
|||
|
if (fnum == kInvalidValue) // for minimal aliases, no valid fileID
|
|||
|
return(fnfErr);
|
|||
|
|
|||
|
cpb.hFileInfo.ioFDirIndex = 0;
|
|||
|
|
|||
|
for (;;) { // index through this directory
|
|||
|
|
|||
|
++cpb.hFileInfo.ioFDirIndex; // next file in the directory
|
|||
|
|
|||
|
// no more files or a fatal error or found it
|
|||
|
if ((err = AL_getCatInfo(vref, dirID, localName, &cpb)) == afpAccessDenied)
|
|||
|
continue; // look for the next one
|
|||
|
|
|||
|
else if (err != noErr)
|
|||
|
return (err); // no more files or a fatal error
|
|||
|
|
|||
|
else if (cpb.hFileInfo.ioDirID == fnum) {
|
|||
|
|
|||
|
AL_copyPString (localName, fname);
|
|||
|
return (noErr); // found it
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} // end of infinite for loop
|
|||
|
|
|||
|
} // end of AL_findFileByNum routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file or directory as a given path ************
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
static OSErr FindGivenPath (short vref, //I volume reference number/WD ref
|
|||
|
long dirID, //I find it in this directory
|
|||
|
char *path, //I as a given path
|
|||
|
short len, //I length of given path
|
|||
|
long *newFileNum, //O if found, it's file number
|
|||
|
long *newParDirID,//O if found, it's parent folder's dir ID
|
|||
|
StringPtr newFileName) //O if found, file's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err; // result code
|
|||
|
register char *cur, *tail, *end;// temporary character pointers
|
|||
|
char saveCh; // save a character
|
|||
|
Str255 lastPartialPath; // last partial path that was found by name
|
|||
|
long lastDirLooked; // last directory we looked into
|
|||
|
FSSpec target; // canonical form of target
|
|||
|
|
|||
|
cur = path;
|
|||
|
|
|||
|
tail = end = cur + len; // end and tail points to the end of given Path
|
|||
|
|
|||
|
*newFileNum = dirID; // start looking from given directory
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
if ((end-cur) > kStrMaxlen) { // handle > 255 character fullpath correctly.
|
|||
|
|
|||
|
// locate tail that is pointing to end of a partial path that is less than kStrMaxlen
|
|||
|
tail = cur + kStrMaxlen - 1;
|
|||
|
|
|||
|
while (*tail != kChrSeparator && tail > cur)
|
|||
|
--tail; // point just before separator character
|
|||
|
|
|||
|
while ((*(tail-1)) == kChrSeparator)
|
|||
|
--tail; // point before any additional separator chars for "::" and ":::" type cases
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
saveCh = *(--cur); // save caracter before abs path name
|
|||
|
*cur = (tail - cur - 1); // pascal string expected as input
|
|||
|
|
|||
|
lastDirLooked = *newFileNum; // about to look in this directory
|
|||
|
AL_copyPString (cur, lastPartialPath); // looking for this partial path name
|
|||
|
err = AL_findByName (vref, *newFileNum, cur, newFileNum, newParDirID);
|
|||
|
|
|||
|
*cur = saveCh;
|
|||
|
cur = tail;
|
|||
|
tail = end;
|
|||
|
|
|||
|
} while (cur < end && err == noErr);
|
|||
|
|
|||
|
if (err == noErr && newFileName != NULL) { // compute the leaf name
|
|||
|
err = AL_canonifyFile (vref, lastDirLooked, (Str255 *)lastPartialPath, &target);
|
|||
|
if (err == noErr)
|
|||
|
AL_copyPString(target.name, newFileName);
|
|||
|
}
|
|||
|
else if (err != noErr) {
|
|||
|
AL_stripFilename ((unsigned char *)lastPartialPath+1, Length(lastPartialPath), lastPartialPath);
|
|||
|
err = AL_findByName (vref, lastDirLooked, lastPartialPath, newParDirID, newFileNum);
|
|||
|
err = (err == noErr) ? fnfErr : dirNFErr; // return hint parent dir as fnfErr
|
|||
|
}
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of FindGivenPath routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file or directory by absolute path name ******
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
OSErr AL_findByAbsPath (short vref, //I volume reference number/WD ref
|
|||
|
const AliasPtrPriv aptr, //I alias record pointer
|
|||
|
long *newParDirID, //O folder's dir ID
|
|||
|
StringPtr newFileName) //O if found, file's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
register char *cur, *end; // temporary character pointers
|
|||
|
short nchInAPath; // # of chars in absolute path
|
|||
|
long fnum; // file number
|
|||
|
|
|||
|
cur = AL_getVarPtr (aptr, kAbsPath, &nchInAPath); // point to absolute path within alias record
|
|||
|
|
|||
|
if (nchInAPath == 0)
|
|||
|
return (fnfErr);
|
|||
|
|
|||
|
// locate the first separator character after volume name and look for remaining partial path
|
|||
|
end = cur + nchInAPath; // end points to the end of AbsPath
|
|||
|
|
|||
|
while (*cur != kChrSeparator && cur < end)
|
|||
|
cur++; // point to separator char so its a partial pathname
|
|||
|
|
|||
|
return (FindGivenPath(vref, kRootDirID, cur, nchInAPath-Length(aptr->volumeName),
|
|||
|
&fnum, newParDirID, newFileName));
|
|||
|
|
|||
|
} // end of AL_findByAbsPath routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
**** Find by absolute path name on other same name volumes ***********
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
OSErr AL_findByAbsPathOnOtherVolume (short *vref, //I/O volume reference number
|
|||
|
const AliasPtrPriv aptr, //I alias record pointer
|
|||
|
long *newParDirID, //O folder's dir ID
|
|||
|
StringPtr newFileName) //O if found, file's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err = fnfErr; // result code
|
|||
|
Str27 localName; // temporary local volume name
|
|||
|
VolumeParam vpb; // volume parameter block
|
|||
|
|
|||
|
vpb.ioVolIndex = 1;
|
|||
|
vpb.ioNamePtr = localName; // return name
|
|||
|
|
|||
|
while (PBGetVInfo ((ParmBlkPtr)&vpb, FALSE) == noErr) {
|
|||
|
|
|||
|
++(vpb.ioVolIndex); // next mounted volume
|
|||
|
|
|||
|
if (*vref != vpb.ioVRefNum &&
|
|||
|
AL_FSEqualStringByLength (localName+1, aptr->volumeName+1, Length(localName))) {
|
|||
|
|
|||
|
err = AL_findByAbsPath(vpb.ioVRefNum, aptr, newParDirID, newFileName);
|
|||
|
if (err == noErr) {
|
|||
|
|
|||
|
*vref = vpb.ioVRefNum;
|
|||
|
return (noErr);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findByAbsPathOnOtherVolume routine
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file or directory by absolute path name ******
|
|||
|
*************** tracing directories upto root directory ******
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
OSErr AL_findByAbsPathToRoot (short vref, //I volume reference number/WD ref
|
|||
|
const AliasPtrPriv aptr,//I alias record pointer
|
|||
|
long *newParDirID, //O folder's directory ID
|
|||
|
StringPtr newFileName) //O if found, file's name
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err = fnfErr; // assume that it won't be found
|
|||
|
register char *s, *t; // temporary character pointers
|
|||
|
register short i; // for loop index
|
|||
|
unsigned short len = 0; // length of partial pathname
|
|||
|
long fnum; // file number
|
|||
|
long *l; // directory ID array pointer
|
|||
|
short nchInAPath; // # of chars in absolute path
|
|||
|
short ndirToRoot; // # of dirs to Root for the alias
|
|||
|
|
|||
|
s = t = AL_getVarPtr (aptr, kAbsPath, &nchInAPath); // pointer to absolute path name
|
|||
|
|
|||
|
if (nchInAPath == 0)
|
|||
|
return (fnfErr);
|
|||
|
|
|||
|
s += nchInAPath - 1; // point to the last character in abs path
|
|||
|
|
|||
|
l = (long *) AL_getVarPtr (aptr, kDirIDs, &ndirToRoot); // pointer to directory ID array
|
|||
|
|
|||
|
ndirToRoot = (ndirToRoot >> 2); // since dirIDs are long, this is equivalent to
|
|||
|
// division by sizeof(long);
|
|||
|
|
|||
|
for (i=ndirToRoot-1; i>=0; --i) {
|
|||
|
|
|||
|
// locate a separator character ':'
|
|||
|
while (*s-- != kChrSeparator && s > t)
|
|||
|
++len;
|
|||
|
++len; // add one for separator char
|
|||
|
|
|||
|
err = FindGivenPath(vref, *l++, s+1, len, &fnum, newParDirID, newFileName);
|
|||
|
if ((err == noErr) || (err != fnfErr && err != dirNFErr)) // found it or fatal error
|
|||
|
break;
|
|||
|
|
|||
|
} // end of for loop
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findByAbsPathToRoot routine
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*************** Find file or directory by relative path name ******
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
OSErr AL_findByRelPath (const FSSpec *fromFile, //I aliased from file
|
|||
|
const AliasPtrPriv aptr, //I alias record pointer
|
|||
|
long *newParDirID, //O if found, folder directory ID
|
|||
|
long *fnum) //O if found, file number or dirID
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
OSErr err; // result code
|
|||
|
register char *s, *t; // temporary character pointers
|
|||
|
register short i; // for loop indes
|
|||
|
register unsigned short len = 0;// length of partial pathname
|
|||
|
long cdir; // common ancestor dir number
|
|||
|
short nchInAPath; // # of chars in absolute path
|
|||
|
|
|||
|
/* This routine stuffs in *newParDirID evenif the file may not be found at
|
|||
|
the relative path. The value stuffed in the dirID of the place where it could
|
|||
|
have been found. This info is used later on to return hint about the place
|
|||
|
where the target may have been found.
|
|||
|
*/
|
|||
|
|
|||
|
if (aptr->nlvlFrom == kNoRelativePath) // across volumes or fromFile was null
|
|||
|
return (fnfErr);
|
|||
|
|
|||
|
// locate the common ancestor directory number
|
|||
|
|
|||
|
cdir = fromFile->parID;
|
|||
|
|
|||
|
if (aptr->nlvlFrom > 1)
|
|||
|
|
|||
|
for (i=aptr->nlvlFrom-2; i>=0; --i) {
|
|||
|
|
|||
|
if ((err = AL_findDirByID (fromFile->vRefNum, cdir, &cdir, NULL)) != noErr)
|
|||
|
goto EXIT;
|
|||
|
|
|||
|
if (cdir == kRootDirID)
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// locate correct toFile partial path in its full path
|
|||
|
|
|||
|
s = t = AL_getVarPtr (aptr, kAbsPath, &nchInAPath); // pointer into toFile absolute path
|
|||
|
|
|||
|
s += nchInAPath - 1; // point to last character of absolute path
|
|||
|
|
|||
|
// locate a separator character ':', until correct number of levels up
|
|||
|
// from end of absolute path is traced
|
|||
|
|
|||
|
for (i=aptr->nlvlTo-1; i>=0; --i) {
|
|||
|
|
|||
|
while (*s-- != kChrSeparator && s > t)
|
|||
|
++len;
|
|||
|
++len; // add one for separator char
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (s <= t) { // look in the root directory
|
|||
|
|
|||
|
i = Length(aptr->volumeName);
|
|||
|
s = t + i - 1; // skip volume name, but keep the separator
|
|||
|
// subtract one more to put length byte
|
|||
|
len = nchInAPath - i;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// look for the directory first and then the file. So, if only the directory
|
|||
|
// is found, correct parent dirID is returned eventhough target is not found.
|
|||
|
|
|||
|
len -= Length(aptr->fileName);
|
|||
|
|
|||
|
err = FindGivenPath(fromFile->vRefNum, cdir, s+1, len, fnum, newParDirID, NULL/* not interested in name*/);
|
|||
|
|
|||
|
if (err == noErr) {
|
|||
|
err = AL_findByName (fromFile->vRefNum, *fnum, aptr->fileName,
|
|||
|
fnum, newParDirID);
|
|||
|
if (err != noErr) // return the correct hint
|
|||
|
*newParDirID = *fnum;
|
|||
|
}
|
|||
|
|
|||
|
EXIT:
|
|||
|
|
|||
|
return (err);
|
|||
|
|
|||
|
} // end of AL_findByRelPath routine
|
|||
|
|
|||
|
/***************************** end of alFind.c file *****************************/
|