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

Archive Download this file

Revision: 375