CatalogUtilities.c [plain text]
#include <sys/param.h>
#include <sys/utfconv.h>
#include <sys/stat.h>
#include "../headers/FileMgrInternal.h"
#include "../headers/BTreesInternal.h"
#include "../headers/CatalogPrivate.h"
#include "../headers/HFSUnicodeWrappers.h"
#include <string.h>
OSErr
LocateCatalogNode(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
{
OSErr result;
CatalogName *nodeName = NULL;
HFSCatalogNodeID threadParentID;
result = LocateCatalogRecord(volume, folderID, name, hint, keyPtr, dataPtr, newHint);
ReturnIfError(result);
switch ( dataPtr->recordType )
{
case kHFSFileThreadRecord:
case kHFSFolderThreadRecord:
threadParentID = dataPtr->hfsThread.parentID;
nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
break;
case kHFSPlusFileThreadRecord:
case kHFSPlusFolderThreadRecord:
threadParentID = dataPtr->hfsPlusThread.parentID;
nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;
break;
default:
threadParentID = 0;
break;
}
if ( threadParentID ) result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
return result;
}
OSErr
LocateCatalogNodeByKey(const ExtendedVCB *volume, UInt32 hint, CatalogKey *keyPtr,
CatalogRecord *dataPtr, UInt32 *newHint)
{
OSErr result;
CatalogName *nodeName = NULL;
HFSCatalogNodeID threadParentID;
UInt16 tempSize;
FSBufferDescriptor btRecord;
BTreeIterator searchIterator = {0};
FCB *fcb;
fcb = GetFileControlBlock(volume->catalogRefNum);
btRecord.bufferAddress = dataPtr;
btRecord.itemCount = 1;
btRecord.itemSize = sizeof(CatalogRecord);
searchIterator.hint.nodeNum = hint;
bcopy(keyPtr, &searchIterator.key, sizeof(CatalogKey));
result = BTSearchRecord( fcb, &searchIterator, &btRecord, &tempSize, &searchIterator );
if (result == noErr)
{
*newHint = searchIterator.hint.nodeNum;
BlockMoveData(&searchIterator.key, keyPtr, sizeof(CatalogKey));
}
if (result == btNotFound)
result = cmNotFound;
ReturnIfError(result);
switch ( dataPtr->recordType )
{
case kHFSFileThreadRecord:
case kHFSFolderThreadRecord:
threadParentID = dataPtr->hfsThread.parentID;
nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
break;
case kHFSPlusFileThreadRecord:
case kHFSPlusFolderThreadRecord:
threadParentID = dataPtr->hfsPlusThread.parentID;
nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;
break;
default:
threadParentID = 0;
break;
}
if ( threadParentID ) result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
return result;
}
OSErr
LocateCatalogRecord(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
{
OSErr result;
CatalogKey tempKey; UInt16 tempSize;
BuildCatalogKey(folderID, name, (volume->vcbSigWord == kHFSPlusSigWord), &tempKey);
if ( name == NULL )
hint = kNoHint;
result = SearchBTreeRecord(volume->catalogRefNum, &tempKey, hint, keyPtr, dataPtr, &tempSize, newHint);
return (result == btNotFound ? cmNotFound : result);
}
void
BuildCatalogKey(HFSCatalogNodeID parentID, const CatalogName *cName, Boolean isHFSPlus, CatalogKey *key)
{
if ( isHFSPlus )
{
key->hfsPlus.keyLength = kHFSPlusCatalogKeyMinimumLength; key->hfsPlus.parentID = parentID; key->hfsPlus.nodeName.length = 0; if ( cName != NULL )
{
CopyCatalogName(cName, (CatalogName *) &key->hfsPlus.nodeName, isHFSPlus);
key->hfsPlus.keyLength += sizeof(UniChar) * cName->ustr.length; }
}
else
{
key->hfs.keyLength = kHFSCatalogKeyMinimumLength; key->hfs.reserved = 0; key->hfs.parentID = parentID; key->hfs.nodeName[0] = 0; if ( cName != NULL )
{
UpdateCatalogName(cName->pstr, key->hfs.nodeName);
key->hfs.keyLength += key->hfs.nodeName[0]; }
}
}
OSErr
BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char *name, UInt32 nameLength,
CatalogKey *key, UInt32 *textEncoding)
{
OSErr err = 0;
if ( name == NULL)
nameLength = 0;
else if (nameLength == kUndefinedStrLen)
nameLength = strlen(name);
if ( volume->vcbSigWord == kHFSPlusSigWord ) {
size_t unicodeBytes = 0;
key->hfsPlus.keyLength = kHFSPlusCatalogKeyMinimumLength; key->hfsPlus.parentID = parentID; key->hfsPlus.nodeName.length = 0; if ( nameLength > 0 ) {
err = utf8_decodestr(name, nameLength, key->hfsPlus.nodeName.unicode,
&unicodeBytes, sizeof(key->hfsPlus.nodeName.unicode), ':', UTF_DECOMPOSED);
key->hfsPlus.nodeName.length = unicodeBytes / sizeof(UniChar);
key->hfsPlus.keyLength += unicodeBytes;
}
if (textEncoding && (*textEncoding != kTextEncodingMacUnicode))
*textEncoding = hfs_pickencoding(key->hfsPlus.nodeName.unicode,
key->hfsPlus.nodeName.length);
}
else {
key->hfs.keyLength = kHFSCatalogKeyMinimumLength; key->hfs.reserved = 0; key->hfs.parentID = parentID; key->hfs.nodeName[0] = 0; if ( nameLength > 0 ) {
err = utf8_to_hfs(volume, nameLength, name, &key->hfs.nodeName[0]);
if (err && (textEncoding == NULL))
err = utf8_to_mac_roman(nameLength, name, &key->hfs.nodeName[0]);
key->hfs.keyLength += key->hfs.nodeName[0]; }
if (textEncoding)
*textEncoding = 0;
}
if (err) {
if (err == ENAMETOOLONG)
err = bdNamErr;
else
err = paramErr;
}
return err;
}
OSErr
FlushCatalog(ExtendedVCB *volume)
{
FCB * fcb;
OSErr result;
fcb = GetFileControlBlock(volume->catalogRefNum);
result = BTFlushPath(fcb);
if (result == noErr)
{
if ( 0 )
{
HFS_MOUNT_LOCK(volume, TRUE);
volume->vcbFlags |= 0xFF00; volume->vcbLsMod = GetTimeUTC(); HFS_MOUNT_UNLOCK(volume, TRUE);
}
}
return result;
}
void
UpdateCatalogName(ConstStr31Param srcName, Str31 destName)
{
Size length = srcName[0];
if (length > CMMaxCName)
length = CMMaxCName;
destName[0] = length;
BlockMoveData(&srcName[1], &destName[1], length);
}
void
CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSPLus)
{
UInt32 length;
if ( srcName == NULL )
{
if ( dstName != NULL )
dstName->ustr.length = 0; return;
}
if (isHFSPLus)
length = sizeof(UniChar) * (srcName->ustr.length + 1);
else
length = sizeof(UInt8) + srcName->pstr[0];
if ( length > 1 )
BlockMoveData(srcName, dstName, length);
else
dstName->ustr.length = 0; }