Index: trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.h =================================================================== --- trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.h (revision 19) +++ trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.h (revision 20) @@ -35,7 +35,7 @@ NSImage* mUnknownImage; NSImage* mCDROMImage; NSMutableDictionary* mOptionsDict; - NSMutableDictionary* mPartitionsList; + NSMutableDictionary* mPartitionsDict; NSString* mOptionsPlistPath; int mPreferenceFileVersion; } Index: trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm (revision 19) +++ trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm (revision 20) @@ -37,6 +37,8 @@ static const NSString* const keySwapHD02 = @"swapHD02"; static const NSString* const keyUseFrozenParts = @"useFrozenParts"; static const NSString* const keyPartitionsList = @"partitionsList"; +static const char cPartDescSep = ';'; // partition descriptor separator +static const char* sPartDescSep = ";"; // cstring version //-------------------------------------------------------------------------- // Static file variables //-------------------------------------------------------------------------- @@ -107,20 +109,66 @@ PropertyList::chmodFile(sPath.c_str(), "0644", auth); return true; } - //-------------------------------------------------------------------------- +- (void) loadFrozenParts +{ + std::vector& partList = partExtractor->editPartList(); //rw + // iterate for all entries to add + char keyPartN[32] = ""; + char buffer[256]=""; + int k=0; + partList.clear(); + for (int i=0; i<[mPartitionsDict count]; i++) + { + // get the key + snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i); + NSString* obj = [mPartitionsDict objectForKey: [[NSString alloc] initWithUTF8String: keyPartN] ]; + // assign this key if valid + if (obj!=nil && [obj length]>0) + { + PartitionInfo p; + // parse string + strncpy(buffer, [obj UTF8String], sizeof(buffer)-1); + k=0; + for(const char* word = strtok(buffer,";"); word; word=strtok(NULL,sPartDescSep),k++) + { + switch (k) { + case 0: // parse disk number + if (isdigit(*word)) p.disk(*word-'0'); + break; + case 1: // parse partition number + if (isdigit(*word)) p.partition(*word-'0'); + break; + case 2: // parse volume label + p.label(word); + case 3: + p.fsType(word); + break; + default: + break; + } + } + partList.push_back(p); + } + } +} +//-------------------------------------------------------------------------- - (void) loadPreferences { id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile: kPreferencesFilePath ] retain]; + + mPartitionsDict = [[NSMutableDictionary alloc] init]; + [mPartitionsDict retain]; + if (oldGlobalPreferences!=nil) { mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ]; [mSwapHD01 setIntValue: [[oldGlobalPreferences objectForKey: keySwapHD01] intValue]]; [mSwapHD02 setIntValue: [[oldGlobalPreferences objectForKey: keySwapHD02] intValue]]; [mFreezeParts setIntValue: [[oldGlobalPreferences objectForKey: keyUseFrozenParts] intValue] ]; - mPartitionsList = [oldGlobalPreferences objectForKey: keyUseFrozenParts]; + [mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ]; } else { // Create a preference plist file with Defaults values @@ -134,7 +182,7 @@ [oldGlobalPreferences setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD01]; [oldGlobalPreferences setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD02]; [oldGlobalPreferences setObject:[[NSNumber alloc] initWithBool: false] forKey: keyUseFrozenParts]; - [oldGlobalPreferences setObject: [[NSMutableDictionary alloc] initWithCapacity:64] forKey: keyPartitionsList]; + [oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList]; // Save the preferences file [ self savePreferences:oldGlobalPreferences ]; @@ -142,10 +190,8 @@ mOptionsDict = [[NSMutableDictionary alloc] init]; [mOptionsDict addEntriesFromDictionary:oldGlobalPreferences]; - [mOptionsDict retain]; - if (mPartitionsList!=nil) [mPartitionsList retain]; + if (mPartitionsDict!=nil) [mPartitionsDict retain]; [oldGlobalPreferences release]; - } //-------------------------------------------------------------------------- @@ -292,7 +338,12 @@ { partExtractor->swapHD(iSrc, iDst); } - partExtractor->extractPartitions(); + + if ([mFreezeParts intValue]==0) + partExtractor->extractPartitions(); + else + [self loadFrozenParts ]; + [ self selectDefaultPartition]; } @@ -301,7 +352,7 @@ - (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst { - if( val>0) //on + if( val>0 && ![mFreezeParts intValue]) //on { [self swapDisks: true src:isrc dst:idst ]; } @@ -336,18 +387,56 @@ { bool val = !![sender intValue]; [mOptionsDict setObject: [NSNumber numberWithBool: val] forKey: keyUseFrozenParts]; - [self savePreferences :mOptionsDict]; + [self savePreferences: mOptionsDict]; + [self onSwapHD: nil]; } //-------------------------------------------------------------------------- - (IBAction)onInjectPartsToFreeze: (id)sender { - // TODO generate the parts list in preferences proplist + int size = partExtractor ? partExtractor->partList().size() : 0; + if (!size) + { // nothing to inject + NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", + @"No current partitions to inject, did you check boot config file ?",@"OK", nil,nil); + return; + } + // generate the parts list in preferences proplist NSInteger n = NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", @"Are you sure you want to overwrite your Freeze settings with current partition list ?", @"OK", @"Cancel",nil); if (n==1) { + // populate the dictionary with the current partitions + + // empty dictionary and update key in parent: + [mOptionsDict removeObjectForKey: keyPartitionsList]; + [mPartitionsDict removeAllObjects ]; + + // iterate for all entries to add + char partDesc[256]=""; + char keyPartN[32] = ""; + for (int i=0; i< size; i++) + { + + const PartitionInfo& p =partExtractor->partList()[i]; + + // format the partition key and descriptor string + snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i); + + snprintf(partDesc, sizeof(partDesc)-1, "%d%c%d%c%s%c%s", + p.disk(), cPartDescSep, + p.partition(), cPartDescSep, + p.label().c_str(), cPartDescSep, + p.fsType().c_str()); + + // write it to the dictionary + NSString * key = [[NSString alloc] initWithUTF8String: keyPartN]; + NSString * desc = [[NSString alloc] initWithUTF8String: partDesc]; + [mPartitionsDict setObject: desc forKey: key]; + } + [mOptionsDict setObject: mPartitionsDict forKey: keyPartitionsList]; + [self savePreferences: mOptionsDict]; } } //-------------------------------------------------------------------------- @@ -364,6 +453,7 @@ } } +//-------------------------------------------------------------------------- - (IBAction)onShutdown: (id)sender { NSInteger n = NSRunAlertPanel(@"Shutting Down OS X", Index: trunk/ChameleonPrefPane/Sources/process.h =================================================================== --- trunk/ChameleonPrefPane/Sources/process.h (revision 19) +++ trunk/ChameleonPrefPane/Sources/process.h (revision 20) @@ -92,10 +92,9 @@ const char* szRenamed=NULL); int getListCount() const {return (int) _partList.size();} - const std::vector& partList() const - { - return _partList; - } + const std::vector& partList() const {return _partList;} + std::vector& editPartList() {return _partList;} + // get the index in the internal partlist of the hd(n,m) partition specified by the input string // return -1 if no match, >=0 if a match happens int getIndexFromHdStringSpec(const char*); Index: trunk/ChameleonPrefPane/ChameleonPrefPane.xcodeproj/project.pbxproj =================================================================== --- trunk/ChameleonPrefPane/ChameleonPrefPane.xcodeproj/project.pbxproj (revision 19) +++ trunk/ChameleonPrefPane/ChameleonPrefPane.xcodeproj/project.pbxproj (revision 20) @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0143D924110806E000D290B4 /* version in Resources */ = {isa = PBXBuildFile; fileRef = 0143D923110806E000D290B4 /* version */; }; 01466A931104062500088464 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01466A921104062500088464 /* Security.framework */; }; 01466C2A110408CC00088464 /* SecurityInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01466C29110408CC00088464 /* SecurityInterface.framework */; }; 01466C381104091400088464 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01466C371104091400088464 /* SecurityFoundation.framework */; }; @@ -34,6 +35,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0143D923110806E000D290B4 /* version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = version; path = ../../../../../devl/OSX/chameleonApplications/trunk/ChameleonPrefPane/bin/version; sourceTree = SOURCE_ROOT; }; 01466A921104062500088464 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 01466C29110408CC00088464 /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = System/Library/Frameworks/SecurityInterface.framework; sourceTree = SDKROOT; }; 01466C371104091400088464 /* SecurityFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityFoundation.framework; path = System/Library/Frameworks/SecurityFoundation.framework; sourceTree = SDKROOT; }; @@ -163,6 +165,7 @@ 32DBCFA10370C40200C91783 /* Other Sources */ = { isa = PBXGroup; children = ( + 0143D923110806E000D290B4 /* version */, 01CB09D91107727D00A56FC3 /* CREDITS */, 32DBCFA20370C41700C91783 /* StartupPrefPane_Prefix.pch */, 01A40F74110550F4002A74CD /* CHANGES */, @@ -243,6 +246,7 @@ 01CB09641107654A00A56FC3 /* MacOSX.png in Resources */, 01CB09651107654A00A56FC3 /* Windows.png in Resources */, 01CB09DA1107727D00A56FC3 /* CREDITS in Resources */, + 0143D924110806E000D290B4 /* version in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; Index: trunk/ChameleonPrefPane/bin/OSX105/Chameleon.prefPane.zip =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/ChameleonPrefPane/bin/OSX106/Chameleon.prefPane.zip =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/ChameleonPrefPane/bin/version =================================================================== --- trunk/ChameleonPrefPane/bin/version (revision 19) +++ trunk/ChameleonPrefPane/bin/version (revision 20) @@ -1 +1 @@ -1.0b8-2 +1.0b9 Index: trunk/ChameleonPrefPane/README =================================================================== --- trunk/ChameleonPrefPane/README (revision 19) +++ trunk/ChameleonPrefPane/README (revision 20) @@ -10,15 +10,26 @@ The persistent configuration file is a all users level preferences property list located in In /Library/Preferences/com.chameleon.prefPane.plist. - The swap diskk fix option might be use if your disk order from chameleon is different from what diskutil list returns - Idealy we should not need this fix, but as for now, I don't know another way to do it + The swap disk fix option might be use if your disk order from chameleon is different + from what diskutil list returns. + Ideally we should not need this fix, but as for now, I don't know another way to do it In /Library/Preferences/com.chameleon.prefPane.plist: you can insert a 'forceBootConfigPath' key with your com.apple.Boot,plist file path: So if automatic detection does not work, then force your com.apple.Boot.plist path here. + Freeze Partitions (lock the partition list and prevent autodetection to happen) + You can also decide to freeze the partitions to prevent automatic detection, + if disk order is not matching after the boot or if you don't want the list to change + each time that a usb key is inserted, then use this feature. + For it to work, you will need first to click on: + Settings/Boot Selector Fixes/Inject Parts In Freeze File + Then all your automatically detected current partitions are injected in the pref. file, + all you need to do is to manually edit them to change their disk id/partition id + (2 first parameters in the pref. file under the partitionList key) + Troubleshooting If the panel sees your com.apple.boot.plist in the status box, but the boot selection seem to have no effect, it might be that you have more than one bootConfig file and that the chameleon booter does not load the one that the panel selected, - see upper to force the bootConfig to match the one loaded by the chameleon booter. \ No newline at end of file + see upper to force the bootConfig to match the one loaded by the chameleon booter. Index: trunk/ChameleonPrefPane/English.lproj/Chameleon.xib =================================================================== --- trunk/ChameleonPrefPane/English.lproj/Chameleon.xib (revision 19) +++ trunk/ChameleonPrefPane/English.lproj/Chameleon.xib (revision 20) @@ -12,7 +12,7 @@ YES - + YES @@ -85,7 +85,7 @@ 72482368 138544128 - V1.0 b8, by Rekursor + V1.0 b9, by Rekursor LucidaGrande 11