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

Archive Download this file

Revision: 459