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; }
int removeFile(const char* fileName, Volume* volume) { HFSPlusCatalogRecord* record; HFSPlusCatalogKey key; io_func* io; HFSPlusCatalogFolder* parentFolder = NULL; record = getRecordFromPath3(fileName, volume, NULL, &key, TRUE, FALSE, kHFSRootFolderID); if(record != NULL) { parentFolder = (HFSPlusCatalogFolder*) getRecordByCNID(key.parentID, volume); if(parentFolder != NULL) { if(parentFolder->recordType != kHFSPlusFolderRecord) { ASSERT(FALSE, "parent not folder"); free(parentFolder); return FALSE; } } else { ASSERT(FALSE, "can't find parent"); return FALSE; } if(record->recordType == kHFSPlusFileRecord) { XAttrList* next, *attrs; io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &((HFSPlusCatalogFile*)record)->dataFork, record, volume); allocate((RawFile*)io->data, 0); CLOSE(io); removeFromBTree(volume->catalogTree, (BTKey*)(&key)); attrs = getAllExtendedAttributes(((HFSPlusCatalogFile*)record)->fileID, volume); if(attrs != NULL) { while(attrs != NULL) { next = attrs->next; unsetAttribute(volume, ((HFSPlusCatalogFile*)record)->fileID, attrs->name); free(attrs->name); free(attrs); attrs = next; } } key.nodeName.length = 0; key.parentID = ((HFSPlusCatalogFile*)record)->fileID; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); removeFromBTree(volume->catalogTree, (BTKey*)(&key)); volume->volumeHeader->fileCount--; } else { if(((HFSPlusCatalogFolder*)record)->valence > 0) { free(record); free(parentFolder); ASSERT(FALSE, "folder not empty"); return FALSE; } else { XAttrList *next, *attrs; removeFromBTree(volume->catalogTree, (BTKey*)(&key)); attrs = getAllExtendedAttributes(((HFSPlusCatalogFolder*)record)->folderID, volume); if(attrs != NULL) { while(attrs != NULL) { next = attrs->next; unsetAttribute(volume, ((HFSPlusCatalogFolder*)record)->folderID, attrs->name); free(attrs->name); free(attrs); attrs = next; } } key.nodeName.length = 0; key.parentID = ((HFSPlusCatalogFolder*)record)->folderID; key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); removeFromBTree(volume->catalogTree, (BTKey*)(&key)); } parentFolder->folderCount--; volume->volumeHeader->folderCount--; } parentFolder->valence--; updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); updateVolume(volume); free(record); free(parentFolder); return TRUE; } else { if(parentFolder) free(parentFolder); ASSERT(FALSE, "cannot find record"); return FALSE; } }
void addAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName) { CatalogRecordList* list; CatalogRecordList* theList; char cwd[1024]; char fullName[1024]; char testBuffer[1024]; char* pathComponent; int pathLen; char* name; DIR* dir; DIR* tmp; HFSCatalogNodeID cnid; struct dirent* ent; AbstractFile* file; HFSPlusCatalogFile* outFile; strcpy(fullName, parentName); pathComponent = fullName + strlen(fullName); ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); theList = list = getFolderContents(folderID, volume); ASSERT((dir = opendir(cwd)) != NULL, "opendir"); while((ent = readdir(dir)) != NULL) { if(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) { continue; } strcpy(pathComponent, ent->d_name); pathLen = strlen(fullName); cnid = 0; list = theList; while(list != NULL) { name = unicodeToAscii(&list->name); if(strcmp(name, ent->d_name) == 0) { cnid = (list->record->recordType == kHFSPlusFolderRecord) ? (((HFSPlusCatalogFolder*)list->record)->folderID) : (((HFSPlusCatalogFile*)list->record)->fileID); free(name); break; } free(name); list = list->next; } if((tmp = opendir(ent->d_name)) != NULL) { closedir(tmp); printf("folder: %s\n", fullName); fflush(stdout); if(cnid == 0) { cnid = newFolder(fullName, volume); } fullName[pathLen] = '/'; fullName[pathLen + 1] = '\0'; ASSERT(chdir(ent->d_name) == 0, "chdir"); addAllInFolder(cnid, volume, fullName); ASSERT(chdir(cwd) == 0, "chdir"); } else { printf("file: %s\n", fullName); fflush(stdout); if(cnid == 0) { cnid = newFile(fullName, volume); } file = createAbstractFileFromFile(fopen(ent->d_name, "rb")); ASSERT(file != NULL, "fopen"); outFile = (HFSPlusCatalogFile*)getRecordByCNID(cnid, volume); writeToHFSFile(outFile, file, volume); file->close(file); free(outFile); if(strncmp(fullName, "/Applications/", sizeof("/Applications/") - 1) == 0) { testBuffer[0] = '\0'; strcpy(testBuffer, "/Applications/"); strcat(testBuffer, ent->d_name); strcat(testBuffer, ".app/"); strcat(testBuffer, ent->d_name); if(strcmp(testBuffer, fullName) == 0) { if(strcmp(ent->d_name, "Installer") == 0 || strcmp(ent->d_name, "BootNeuter") == 0 ) { printf("Giving setuid permissions to %s...\n", fullName); fflush(stdout); chmodFile(fullName, 04755, volume); } else { printf("Giving permissions to %s\n", fullName); fflush(stdout); chmodFile(fullName, 0755, volume); } } } else if(strncmp(fullName, "/bin/", sizeof("/bin/") - 1) == 0 || strncmp(fullName, "/Applications/BootNeuter.app/bin/", sizeof("/Applications/BootNeuter.app/bin/") - 1) == 0 || strncmp(fullName, "/sbin/", sizeof("/sbin/") - 1) == 0 || strncmp(fullName, "/usr/sbin/", sizeof("/usr/sbin/") - 1) == 0 || strncmp(fullName, "/usr/bin/", sizeof("/usr/bin/") - 1) == 0 || strncmp(fullName, "/usr/libexec/", sizeof("/usr/libexec/") - 1) == 0 || strncmp(fullName, "/usr/local/bin/", sizeof("/usr/local/bin/") - 1) == 0 || strncmp(fullName, "/usr/local/sbin/", sizeof("/usr/local/sbin/") - 1) == 0 || strncmp(fullName, "/usr/local/libexec/", sizeof("/usr/local/libexec/") - 1) == 0 ) { chmodFile(fullName, 0755, volume); printf("Giving permissions to %s\n", fullName); fflush(stdout); } } } closedir(dir); releaseCatalogRecordList(theList); }