Chameleon Applications

Chameleon Applications Svn Source Tree

Root/trunk/ChameleonPrefPane/Sources/PartitionInfoElement.mm

1//
2// PartitionInfoElement.mm
3// ChameleonPrefPane
4//
5// Powerful Partition Info class utility
6//
7// Created by Rekursor on 11-11-12.
8//
9
10#import "PartitionInfoElement.h"
11#import "ShellProcess.h"
12
13static NSUInteger sHdRedirTable[MAX_HD];
14
15@implementation PartitionInfoElement
16
17@synthesize descDict, bsdName, vUUID, vKind, vName, mediaPath, mediaRemovable, devInternal, devProtocol;
18@synthesize vAliasName, hidden;
19
20/// Create a list of all bsd partitions
21+(NSArray*) createBSDPartitionList
22{
23NSMutableArray* arr = [[NSMutableArray alloc] init];
24
25char line[256];
26ShellProcess p;
27
28p.open("ls -1 /dev/disk*");
29while( p.get_line(line, sizeof(line)-1))
30{
31size_t l = strlen(line);
32if (l==0 || strstr(line, "ls:")!=NULL) continue;
33if (line[l-1]) line[l-1]='\0';
34const char * p = strstr(line, "disk");
35NSString* s = [[NSString stringWithUTF8String: p] retain];
36[arr addObject: s];
37
38}
39p.close();
40
41return arr;
42}
43
44/// redirection table for disk swapping
45+(NSUInteger*) hdRedirTable
46{
47return sHdRedirTable;
48}
49
50/// extract disk number from bsdname spec
51-(int) diskNumber
52{
53int newDiskNum = (diskNum>=0 && diskNum <MAX_HD) ? sHdRedirTable[diskNum] : diskNum;
54return newDiskNum;
55}
56
57/// extract partition number from bsdname spec
58-(int) partitionNumber
59{
60return partNum; // todo extract d num from bsdname
61}
62
63-(NSString*) hdString
64{
65return [NSString stringWithFormat:@"hd(%d,%d)", [self diskNumber], [self partitionNumber]];
66}
67
68-(void) setDiskNumber: (int) d
69{
70diskNum = d;
71}
72
73-(void) setPartitionNumber:(int) p
74{
75partNum = p;
76}
77/// return true if partition extraction successfully executed, false otherwise
78-(bool) isValid
79{
80
81return (
82err==0
83// && [self isBootable] don't hide non bootable disk for now to be in sync
84// with chameleon as much as possible
85&& ![[self devProtocol] isEqual:@"Virtual Interface"]
86);
87}
88
89/// Extract a particular information from the disk partition dictionary from a key, generate a string value output
90-(NSString*) createStringValueWithKey: (NSString*) key
91{
92if (err) return @"";
93CFTypeRef o = [descDict objectForKey: key];
94if (o==nil) return @"";
95CFStringRef sref = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), o);
96NSString* s = [[((NSString*) sref) copy] autorelease];
97CFRelease(sref);
98return s;
99}
100
101/// main extraction method create a dictionary containing all needed information from disk arbitration API
102- (int) extractInfoWithBSDName: (NSString*) name withinSession:(DASessionRef) session
103{
104err = 0;
105
106NSRange rDisk = [name rangeOfString:@"disk"];
107NSRange rS = [name rangeOfString:@"s" options:NSBackwardsSearch] ;
108
109if (name == nil
110|| [name length] < 7
111|| rDisk.location == NSNotFound
112|| rS.location <5)
113{
114err = EINVAL;
115return err;
116}
117
118// extract disk and partition number
119int pos = rDisk.location+rDisk.length;
120int pos2 = rS.location+rS.length;
121NSString* sDisk = [name substringWithRange:
122 NSMakeRange(pos, rS.location - pos) ];
123NSString* sPart = [name substringFromIndex: pos2 ];
124
125bool mustRelease = (session == nil) ? true : false;
126
127if (session == nil)
128{
129session = DASessionCreate(NULL);
130}
131
132 DADiskRef disk;
133
134if (session == NULL)err = EINVAL;
135
136if (err == 0) {
137disk = DADiskCreateFromBSDName(NULL, session, [name UTF8String] );
138if (disk == NULL) err = EINVAL;
139}
140
141[self cleanup];
142
143if (err == 0) {
144CFDictionaryRefdr = DADiskCopyDescription(disk);
145if (dr!=NULL)
146{
147self.descDict = [((NSDictionary*) dr) copy];
148CFRelease(dr);
149if (self.descDict == NULL) err = EINVAL;
150}
151}
152
153if (err == 0) {
154diskNum = [sDiskintValue];
155partNum = [sPartintValue];
156
157self.vUUID = [self createStringValueWithKey: @"DAVolumeUUID"];
158self.vName = [self createStringValueWithKey: @"DAVolumeName"];
159self.vAliasName = self.vName; // by default renamed = original part name
160self.vKind = [self createStringValueWithKey: @"DAVolumeKind"];
161self.mediaPath = [self createStringValueWithKey: @"DAMediaPath"];
162self.devProtocol = [self createStringValueWithKey: @"DADeviceProtocol"];
163self.bsdName = [[NSString stringWithString:name] retain];
164
165self.devInternal = (bool) [[descDict objectForKey: @"DADeviceInternal"] boolValue];
166self.mediaRemovable = (bool) [[descDict objectForKey: @"DAMediaRemovable"] boolValue];
167
168}
169
170// Clean up.
171
172if (disk != NULL)CFRelease(disk);
173if (session != NULL && mustRelease) CFRelease(session);
174
175return err;
176}
177
178+(NSMutableArray*)extractInfoWithBSDNames: (NSArray*) bsdNames
179{
180return [PartitionInfoElement extractInfoWithBSDNames:bsdNames withArray: nil];
181}
182
183/// main extraction method create a dictionary of PartitionInfoElement objects containing all needed information from disk arbitration API
184+ (NSMutableArray*) extractInfoWithBSDNames: (NSArray*) names withArray:(NSMutableArray*) arr
185{
186NSArray* partArr = [PartitionInfoElement createBSDPartitionList];
187if (arr == nil)
188arr = [[NSMutableArray alloc ] init];
189
190if (partArr!=nil && [partArr count]>0)
191{
192DASessionRef session = DASessionCreate(NULL);
193for (NSString* part in partArr)
194{
195PartitionInfoElement* elt =
196[[PartitionInfoElement alloc] initWithBSDName: part withinSession: session];
197if (elt!=nil && [[elt vName] length] >0 && [elt isValid] )
198[arr addObject:elt];
199}
200if (session!=nil) CFRelease(session);
201}
202[partArr release];
203return arr;
204}
205
206- (int) extractInfoWithBSDName: (NSString*) name
207{
208return [self extractInfoWithBSDName:name withinSession: nil];
209}
210
211-(bool) isBootable
212{
213bool bootable = false;
214NSFileManager* mgr = [NSFileManager defaultManager];
215NSString *fmt = @"/Volumes/%@%s";
216// that Windows is the name of WIN32 bootable disk dir ...
217if(
218[mgr fileExistsAtPath: [NSString stringWithFormat: fmt, vName, "/System/Library/Extensions" ]] ||
219 [mgr fileExistsAtPath: [NSString stringWithFormat: fmt, vName, "/ntldr" ]] ||
220[mgr fileExistsAtPath: [NSString stringWithFormat: fmt, vName, "/bootmgr" ]] ||
221[mgr fileExistsAtPath: [NSString stringWithFormat: fmt, vName, "/boot/bcd" ]] ||
222[mgr fileExistsAtPath: [NSString stringWithFormat: fmt, vName, "/pagefile.sys" ]] ||
223[mgr fileExistsAtPath: [NSString stringWithFormat: fmt, vName, "/hiberfil.sys" ]]
224 )
225bootable=true;
226else if ([vName rangeOfString:@"ext"].location != NSNotFound) // linux ?
227bootable = true;
228return bootable;
229}
230
231/// Return the partition image index according to its file system
232-(int) imageIndexFromFs
233{
234
235if ( [[self vKind] rangeOfString:@"hfs"].location != NSNotFound )
236return 0; // Mac
237if ( [[self vKind] rangeOfString:@"fat"].location != NSNotFound ||
238 [[self vKind] rangeOfString:@"ntfs"].location != NSNotFound ||
239 [[self vKind] rangeOfString:@"dos"].location != NSNotFound )
240return 1; // Windows
241if ( [[self vKind] rangeOfString:@"ext"].location != NSNotFound )
242return 2; // Linux
243
244return 10; // unknown
245}
246
247/// Volume label trimming utility function
248+(NSString*) removesSpacesFromLabel:(NSString*) label
249{
250if (label == nil || [label length]==0) return label;
251return [label stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
252}
253
254/// make the object description available for NSLog() debug purpose
255-(NSString*) description
256{
257NSString* format =
258@"(\n"
259 " bsdName %@\n deviceProtocol %@\n deviceInternal %i\n"
260 " volumeName %@\n volumeKind %@\n volumeUUID %@\n"
261 " mediaPath %@\n mediaRemovable %i\n"
262 ")";
263NSString* value = [NSString stringWithFormat: format,
264 self.bsdName, self.devProtocol, self.devInternal,
265 self.vName, self.vKind, self.vUUID,
266 self.mediaPath, self.mediaRemovable ];
267return value;
268}
269
270
271/// initialize a partition element with DA partition info
272-(id) initWithBSDName:(NSString*) name
273{
274[super init];
275diskNum = partNum = -1;
276err = [self extractInfoWithBSDName: name withinSession: nil];
277return self;
278}
279
280/// initialize a partition element with DA partition info and an optional opened session
281-(id) initWithBSDName:(NSString*) name withinSession:(DASessionRef) session
282{
283[super init];
284diskNum = partNum = -1;
285err = [self extractInfoWithBSDName: name withinSession: session];
286
287return self;
288}
289
290-(void) cleanup
291{
292
293if (descDict != nil) CFRelease(descDict);
294if (bsdName != nil) [bsdName release];
295if (vUUID != nil) [vUUID release];
296if (vKind != nil) [vKind release];
297if (vName != nil) [vName release];
298if (mediaPath != nil) [mediaPath release];
299if (devProtocol != nil) [devProtocol release];
300if (vAliasName != nil) [vAliasName release];
301bsdName = vUUID = vKind = vName = mediaPath = devProtocol = vAliasName = nil;
302descDict = nil;
303}
304
305/// release created objects
306-(void) dealloc
307{
308[self cleanup];
309[super dealloc];
310}
311
312@end
313

Archive Download this file

Revision: 370