int writeExtents(RawFile *rawFile) { Extent *extent; int currentExtent; HFSPlusExtentKey extentKey; HFSPlusExtentDescriptor descriptor[8]; HFSPlusForkData *forkData; removeExtents(rawFile); forkData = rawFile->forkData; currentExtent = 0; extent = rawFile->extents; memset(forkData->extents, 0, sizeof(HFSPlusExtentRecord)); while (extent != NULL && currentExtent < 8) { ((HFSPlusExtentDescriptor *)forkData->extents)[currentExtent].startBlock = extent->startBlock; ((HFSPlusExtentDescriptor *)forkData->extents)[currentExtent].blockCount = extent->blockCount; extent = extent->next; currentExtent++; } if (extent != NULL) { extentKey.keyLength = sizeof(HFSPlusExtentKey) - sizeof(extentKey.keyLength); extentKey.forkType = 0; extentKey.fileID = rawFile->id; currentExtent = 0; while (extent != NULL) { if (currentExtent == 0) { memset(descriptor, 0, sizeof(HFSPlusExtentRecord)); } if (currentExtent == 8) { extentKey.startBlock = descriptor[0].startBlock; addToBTree(rawFile->volume->extentsTree, (BTKey *)(&extentKey), sizeof(HFSPlusExtentRecord), (unsigned char *)(&(descriptor[0]))); currentExtent = 0; } descriptor[currentExtent].startBlock = extent->startBlock; descriptor[currentExtent].blockCount = extent->blockCount; currentExtent++; extent = extent->next; } extentKey.startBlock = descriptor[0].startBlock; addToBTree(rawFile->volume->extentsTree, (BTKey *)(&extentKey), sizeof(HFSPlusExtentRecord), (unsigned char *)(&(descriptor[0]))); } return TRUE; }
int updateCatalog(Volume* volume, HFSPlusCatalogRecord* catalogRecord) { HFSPlusCatalogKey key; HFSPlusCatalogRecord* record; HFSPlusCatalogFile file; HFSPlusCatalogFolder folder; int exact; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); if(catalogRecord->recordType == kHFSPlusFolderRecord) { key.parentID = ((HFSPlusCatalogFolder*)catalogRecord)->folderID; } else if(catalogRecord->recordType == kHFSPlusFileRecord) { key.parentID = ((HFSPlusCatalogFile*)catalogRecord)->fileID; } else { /* unexpected */ return FALSE; } key.nodeName.length = 0; record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); key.parentID = ((HFSPlusCatalogThread*)record)->parentID; key.nodeName = ((HFSPlusCatalogThread*)record)->nodeName; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length) + (sizeof(uint16_t) * key.nodeName.length); free(record); record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); removeFromBTree(volume->catalogTree, (BTKey*)(&key)); switch(record->recordType) { case kHFSPlusFolderRecord: memcpy(&folder, catalogRecord, sizeof(HFSPlusCatalogFolder)); flipCatalogFolder(&folder); free(record); return addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFolder), (unsigned char *)(&folder)); break; case kHFSPlusFileRecord: memcpy(&file, catalogRecord, sizeof(HFSPlusCatalogFile)); flipCatalogFile(&file); free(record); return addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFile), (unsigned char *)(&file)); break; } return TRUE; }
static int updateAttributes(Volume* volume, HFSPlusAttrKey* skey, HFSPlusAttrRecord* srecord) { HFSPlusAttrKey key; HFSPlusAttrRecord* record; int ret, len; memcpy(&key, skey, skey->keyLength); switch(srecord->recordType) { case kHFSPlusAttrInlineData: len = srecord->attrData.size + sizeof(HFSPlusAttrData); record = (HFSPlusAttrRecord*) malloc(len); memcpy(record, srecord, len); flipAttrData((HFSPlusAttrData*) record); removeFromBTree(volume->attrTree, (BTKey*)(&key)); ret = addToBTree(volume->attrTree, (BTKey*)(&key), len, (unsigned char *)record); free(record); break; case kHFSPlusAttrForkData: record = (HFSPlusAttrRecord*) malloc(sizeof(HFSPlusAttrForkData)); memcpy(record, srecord, sizeof(HFSPlusAttrForkData)); flipAttrForkData((HFSPlusAttrForkData*) record); removeFromBTree(volume->attrTree, (BTKey*)(&key)); ret = addToBTree(volume->attrTree, (BTKey*)(&key), sizeof(HFSPlusAttrForkData), (unsigned char *)record); free(record); break; case kHFSPlusAttrExtents: record = (HFSPlusAttrRecord*) malloc(sizeof(HFSPlusAttrExtents)); memcpy(record, srecord, sizeof(HFSPlusAttrExtents)); flipAttrExtents((HFSPlusAttrExtents*) record); removeFromBTree(volume->attrTree, (BTKey*)(&key)); ret = addToBTree(volume->attrTree, (BTKey*)(&key), sizeof(HFSPlusAttrExtents), (unsigned char *)record); free(record); break; } return ret; }
HFSCatalogNodeID newFolder(const char* pathName, Volume* volume) { HFSPlusCatalogFolder* parentFolder; HFSPlusCatalogFolder folder; HFSPlusCatalogKey key; HFSPlusCatalogThread thread; uint32_t newFolderID; int threadLength; char* path; char* name; char* curChar; char* lastSeparator; path = strdup(pathName); curChar = path; lastSeparator = NULL; while((*curChar) != '\0') { if((*curChar) == '/') lastSeparator = curChar; curChar++; } if(lastSeparator == NULL) { parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); name = path; } else { name = lastSeparator + 1; *lastSeparator = '\0'; parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath(path, volume, NULL, NULL); } if(parentFolder == NULL || parentFolder->recordType != kHFSPlusFolderRecord) { free(path); free(parentFolder); return FALSE; } newFolderID = volume->volumeHeader->nextCatalogID++; volume->volumeHeader->folderCount++; folder.recordType = kHFSPlusFolderRecord; folder.flags = kHFSHasFolderCountMask; folder.valence = 0; folder.folderID = newFolderID; folder.createDate = UNIX_TO_APPLE_TIME(time(NULL)); folder.contentModDate = folder.createDate; folder.attributeModDate = folder.createDate; folder.accessDate = folder.createDate; folder.backupDate = folder.createDate; folder.permissions.ownerID = parentFolder->permissions.ownerID; folder.permissions.groupID = parentFolder->permissions.groupID; folder.permissions.adminFlags = 0; folder.permissions.ownerFlags = 0; folder.permissions.fileMode = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; folder.permissions.special.iNodeNum = 0; memset(&folder.userInfo, 0, sizeof(folder.userInfo)); memset(&folder.finderInfo, 0, sizeof(folder.finderInfo)); folder.textEncoding = 0; folder.folderCount = 0; key.parentID = parentFolder->folderID; ASCIIToUnicode(name, &key.nodeName); key.keyLength = sizeof(key.parentID) + STR_SIZE(key.nodeName); thread.recordType = kHFSPlusFolderThreadRecord; thread.reserved = 0; thread.parentID = parentFolder->folderID; ASCIIToUnicode(name, &thread.nodeName); threadLength = sizeof(thread.recordType) + sizeof(thread.reserved) + sizeof(thread.parentID) + STR_SIZE(thread.nodeName); flipCatalogThread(&thread, TRUE); flipCatalogFolder(&folder); ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFolder), (unsigned char *)(&folder)), "addToBTree"); key.nodeName.length = 0; key.parentID = newFolderID; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), threadLength, (unsigned char *)(&thread)), "addToBTree"); parentFolder->folderCount++; parentFolder->valence++; updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); updateVolume(volume); free(parentFolder); free(path); return newFolderID; }
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; }