in hfs/catalog.c [682:805]
int move(const char* source, const char* dest, Volume* volume) {
HFSPlusCatalogRecord* srcRec;
HFSPlusCatalogFolder* srcFolderRec;
HFSPlusCatalogFolder* destRec;
char* destPath;
char* destName;
char* curChar;
char* lastSeparator;
int i;
int threadLength;
HFSPlusCatalogKey srcKey;
HFSPlusCatalogKey destKey;
HFSPlusCatalogThread* thread;
srcRec = getRecordFromPath3(source, volume, NULL, &srcKey, TRUE, FALSE, kHFSRootFolderID);
if(srcRec == NULL) {
free(srcRec);
return FALSE;
}
srcFolderRec = (HFSPlusCatalogFolder*) getRecordByCNID(srcKey.parentID, volume);
if(srcFolderRec == NULL || srcFolderRec->recordType != kHFSPlusFolderRecord) {
free(srcRec);
free(srcFolderRec);
return FALSE;
}
destPath = strdup(dest);
curChar = destPath;
lastSeparator = NULL;
while((*curChar) != '\0') {
if((*curChar) == '/')
lastSeparator = curChar;
curChar++;
}
if(lastSeparator == NULL) {
destRec = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL);
destName = destPath;
} else {
destName = lastSeparator + 1;
*lastSeparator = '\0';
destRec = (HFSPlusCatalogFolder*) getRecordFromPath(destPath, volume, NULL, NULL);
if(destRec == NULL || destRec->recordType != kHFSPlusFolderRecord) {
free(destPath);
free(srcRec);
free(destRec);
free(srcFolderRec);
return FALSE;
}
}
removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey));
srcKey.nodeName.length = 0;
if(srcRec->recordType == kHFSPlusFolderRecord) {
srcKey.parentID = ((HFSPlusCatalogFolder*)srcRec)->folderID;
} else if(srcRec->recordType == kHFSPlusFileRecord) {
srcKey.parentID = ((HFSPlusCatalogFile*)srcRec)->fileID;
} else {
/* unexpected */
return FALSE;
}
srcKey.keyLength = sizeof(srcKey.parentID) + sizeof(srcKey.nodeName.length);
removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey));
destKey.nodeName.length = strlen(destName);
threadLength = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length);
thread = (HFSPlusCatalogThread*) malloc(threadLength);
thread->reserved = 0;
destKey.parentID = destRec->folderID;
thread->parentID = destKey.parentID;
thread->nodeName.length = destKey.nodeName.length;
for(i = 0; i < destKey.nodeName.length; i++) {
destKey.nodeName.unicode[i] = destName[i];
thread->nodeName.unicode[i] = destName[i];
}
destKey.keyLength = sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length);
switch(srcRec->recordType) {
case kHFSPlusFolderRecord:
thread->recordType = kHFSPlusFolderThreadRecord;
flipCatalogFolder((HFSPlusCatalogFolder*)srcRec);
addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFolder), (unsigned char *)(srcRec));
break;
case kHFSPlusFileRecord:
thread->recordType = kHFSPlusFileThreadRecord;
flipCatalogFile((HFSPlusCatalogFile*)srcRec);
addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFile), (unsigned char *)(srcRec));
break;
}
destKey.nodeName.length = 0;
destKey.parentID = srcKey.parentID;
destKey.keyLength = sizeof(destKey.parentID) + sizeof(destKey.nodeName.length);
flipCatalogThread(thread, TRUE);
addToBTree(volume->catalogTree, (BTKey*)(&destKey), threadLength, (unsigned char *)(thread));
/* adjust valence */
srcFolderRec->valence--;
updateCatalog(volume, (HFSPlusCatalogRecord*) srcFolderRec);
destRec->valence++;
updateCatalog(volume, (HFSPlusCatalogRecord*) destRec);
free(thread);
free(destPath);
free(srcRec);
free(destRec);
free(srcFolderRec);
return TRUE;
}