diff --git a/MFCommunicationServer.h b/MFCommunicationServer.h new file mode 100644 index 0000000..dc79389 --- /dev/null +++ b/MFCommunicationServer.h @@ -0,0 +1,25 @@ +// +// MFCommunicationServer.h +// MacFusion2 +// +// Created by Michael Gorbach on 12/7/07. +// Copyright 2007 Michael Gorbach. All rights reserved. +// + +#import +#import "MFServerProtocol.h" + +@class MFFilesystemController, MFPluginController; + +@interface MFCommunicationServer : NSObject +{ + +} + ++ (MFCommunicationServer*)sharedServer; + +- (MFFilesystemController*)filesystemController; +- (MFPluginController*)pluginController; +- (void)startServingRunloop; + +@end diff --git a/MFCommunicationServer.m b/MFCommunicationServer.m new file mode 100644 index 0000000..a710d31 --- /dev/null +++ b/MFCommunicationServer.m @@ -0,0 +1,103 @@ +// +// MFCommunicationServer.m +// MacFusion2 +// +// Created by Michael Gorbach on 12/7/07. +// Copyright 2007 Michael Gorbach. All rights reserved. +// + +#import "MFCommunicationServer.h" +#import "MFFilesystemController.h" +#import "MFPluginController.h" + +@implementation MFCommunicationServer +static MFCommunicationServer* sharedServer = nil; + + ++ (MFCommunicationServer*)sharedServer +{ + if (sharedServer == nil) + { + [[self alloc] init]; + } + + return sharedServer; +} + ++ (MFCommunicationServer*)allocWithZone:(NSZone*)zone +{ + if (sharedServer == nil) + { + sharedServer = [super allocWithZone: zone]; + return sharedServer; + } + + return nil; +} + +- (void)registerNotifications +{ + NSArray* filesystems = [[self filesystemController] filesystems]; + NSIndexSet* indexes = [NSIndexSet indexSetWithIndexesInRange: + NSMakeRange(0, [filesystems count])]; + [filesystems addObserver:self + toObjectsAtIndexes:indexes + forKeyPath:@"status" + options:NSKeyValueObservingOptionNew + context:nil]; +} + +- (id) init +{ + self = [super init]; + if (self != nil) { + [self registerNotifications]; + } + return self; +} + +- (void)vendDisributedObject +{ + NSConnection* connection = [NSConnection defaultConnection]; + // TODO: Vend a proxy to set up protocol instead of, um , everything + [connection setRootObject:self]; + if ([connection registerName:@"macfusion"] == YES) + { + MFLogS(self, @"Now Vending distributed object"); + } + else + { + MFLogS(self, @"Failed to register connection name"); + } +} + +- (void) observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ +// MFLogS(self, @"Observe triggered on keypath %@, object %@", keyPath, object); +} + +- (MFFilesystemController*)filesystemController +{ + return [MFFilesystemController sharedController]; +} + +- (MFPluginController*)pluginController +{ + return [MFPluginController sharedController]; +} + +- (void)startServingRunloop +{ + [self vendDisributedObject]; + [[NSRunLoop currentRunLoop] run]; +} + +- (void)sendStatus +{ + MFLogS(self, @"Status send triggered"); +} + +@end diff --git a/MFConstants.h b/MFConstants.h new file mode 100644 index 0000000..79033fa --- /dev/null +++ b/MFConstants.h @@ -0,0 +1,17 @@ +/* + * MFConstants.h + * MacFusion2 + * + * Created by Michael Gorbach on 12/1/07. + * Copyright 2007 Michael Gorbach. All rights reserved. + * + */ + +// Status values for filesystems +extern NSString* kMFStatusFSMounted; +extern NSString* kMFStatusFSUnmounted; +extern NSString* kMFStatusFSWaiting; +extern NSString* kMFStatusFSFailed; + +// Notification Names +extern NSString* kMFStatusChangedNotification; diff --git a/MFConstants.m b/MFConstants.m new file mode 100644 index 0000000..fff7c38 --- /dev/null +++ b/MFConstants.m @@ -0,0 +1,16 @@ +// +// MFConstants.m +// MacFusion2 +// +// Created by Michael Gorbach on 12/1/07. +// Copyright 2007 Michael Gorbach. All rights reserved. +// + +#import "MFConstants.h" + +NSString* kMFStatusFSMounted = @"Mounted"; +NSString* kMFStatusFSUnmounted = @"Unmounted"; +NSString* kMFStatusFSWaiting = @"Waiting to Mount"; +NSString* kMFStatusFSFailed = @"Failed to Mount"; + +NSString* kMFStatusChangedNotification = @"Status Changed Notification"; \ No newline at end of file diff --git a/MFFilesystem.h b/MFFilesystem.h index 25a05c5..b906a6a 100644 --- a/MFFilesystem.h +++ b/MFFilesystem.h @@ -12,18 +12,31 @@ @interface MFFilesystem : NSObject { NSMutableDictionary* parameters; MFPlugin* plugin; + NSTask* task; + NSString* status; + NSString* faliureReason; + NSString* recentOutput; } + (MFFilesystem*)filesystemFromParameters:(NSDictionary*)parameters plugin:(MFPlugin*)p; -- (MFPlugin*)plugin; - (MFFilesystem*)initWithParameters:(NSDictionary*)parameters plugin:(MFPlugin*)p; - (NSDictionary*)parameterDictionary; + +- (NSMutableDictionary*)fullParametersWithDictionary: (NSDictionary*)fsParams; +- (NSArray*)taskArguments; + +- (BOOL)validateValue:(id)value forParameterNamed:(NSString*)param; + - (NSString*)pluginID; -//- (void)mount; -//- (void)unmount; +- (void)mount; + +// - (void)unmount; + +@property(readonly) MFPlugin* plugin; +@property(retain) NSString* status; @end diff --git a/MFFilesystem.m b/MFFilesystem.m index 6d8305a..d0b059c 100644 --- a/MFFilesystem.m +++ b/MFFilesystem.m @@ -9,40 +9,70 @@ #import "MFFilesystem.h" //#import "MFPluginController.h" #import "MFPlugin.h" +#import "MFConstants.h" @interface MFFilesystem(PrivateAPI) -- (NSMutableDictionary*)fullParametersWithDictionary: (NSDictionary*)fsParams; -- (NSArray*)taskArgumentList; + @end @implementation MFFilesystem + (MFFilesystem*)filesystemFromParameters:(NSDictionary*)parameters plugin:(MFPlugin*)p { - MFFilesystem* fs = [[MFFilesystem alloc] initWithParameters: parameters plugin: p]; +// MFFilesystem* fs = [[MFFilesystem alloc] initWithParameters: parameters plugin: p]; + MFFilesystem* fs = nil; + NSBundle* b = p.bundle; + NSString* filesystemClassName = [b objectForInfoDictionaryKey:@"MFFilesystemClass"]; + if (filesystemClassName == nil || [filesystemClassName isEqualToString:@"MFFilesystem"]) + { + fs = [[MFFilesystem alloc] initWithParameters: parameters plugin: p]; + } + else + { + BOOL success = [b load]; + if (success) + { + Class filesystemClass = NSClassFromString(filesystemClassName); + fs = [[filesystemClass alloc] initWithParameters: parameters plugin:p]; + } + else + { + MFLogS(self, @"Failed to load bundle for filesystem, bundle path %@", [b bundlePath]); + } + } + return fs; } +- (void)registerGeneralNotifications +{ + NSDistributedNotificationCenter* dnc = [NSDistributedNotificationCenter defaultCenter]; + [self addObserver:self + forKeyPath:@"status" + options:NSKeyValueObservingOptionOld || NSKeyValueObservingOptionNew + context:nil]; + + [dnc addObserver:self + selector:@selector(handleMountNotification:) + name:@"mounted" + object:@"com.google.filesystems.fusefs.unotifications"]; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self + selector:@selector(handleUnmountNotification:) + name:NSWorkspaceDidUnmountNotification + object:nil]; +} + - (MFFilesystem*)initWithParameters:(NSDictionary*)params plugin:(MFPlugin*)p { self = [super init]; plugin = p; parameters = [self fullParametersWithDictionary: params]; + self.status = kMFStatusFSUnmounted; + [self registerGeneralNotifications]; return self; } - -- (NSString*)pluginID -{ - return [parameters objectForKey:@"Type"]; -} - -- (NSDictionary*)parameterDictionary -{ - // We want an immutable dictionary - return [parameters copy]; -} - +# pragma mark Parameter processing - (NSMutableDictionary*)fullParametersWithDictionary:(NSDictionary*)fsParams { NSDictionary* defaultParams = [plugin defaultParameterDictionary]; @@ -55,20 +85,20 @@ - (NSMutableDictionary*)fullParametersWithDictionary:(NSDictionary*)fsParams { // The fs specifies a value for this parameter, take it. // Validation per-value goes here - if (! [self validateValue: value forParameterNamed:parameterKey]) + if (! [self validateValue: value forParameterNamed:parameterKey] ) { - MFLog("Parameter validation failed for parameter %@, plugin %@", - parameterKey + MFLogS(self, "Parameter validation failed for parameter %@, plugin %@", + parameterKey); } [params setObject: [fsParams objectForKey:parameterKey] - forKey: parameterKey]; + forKey: parameterKey]; } else { // The fs doesn't specify a value for this parameter. // Use the default [params setObject: [defaultParams objectForKey:parameterKey] - forKey: parameterKey]; + forKey: parameterKey]; } } @@ -76,14 +106,24 @@ - (NSMutableDictionary*)fullParametersWithDictionary:(NSDictionary*)fsParams return params; } +- (BOOL)validateValue:(id)value forParameterNamed:(NSString*)param +{ + return YES; +} + +# pragma mark Initialization + + +# pragma mark Task Creation methods - (NSDictionary*)taskEnvironment { // No modifications here return [[NSProcessInfo processInfo] environment]; } -- (NSArray*)taskArgumentList +- (NSArray*)taskArguments { + // Default implementation will try to construct an argument list based // on the options dictionary and input format string NSMutableString* formatString = [[[self plugin] inputFormatString] mutableCopy]; @@ -125,25 +165,236 @@ - (NSArray*)taskArgumentList return argParameters; } -- (BOOL)validateValue:(id)value forParameterNamed:(NSString*)param +- (void)setupIOForTask:(NSTask*)t { - return YES; + NSPipe* outputPipe = [[NSPipe alloc] init]; + NSPipe* inputPipe = [[NSPipe alloc] init]; + [t setStandardError: outputPipe]; + [t setStandardOutput: outputPipe]; + [t setStandardInput: inputPipe]; +} + +- (void)registerNotificationsForTask:(NSTask*)t +{ + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(handleDataOnPipe:) + name:NSFileHandleDataAvailableNotification + object:[[t standardOutput] fileHandleForReading]]; + [nc addObserver:self + selector:@selector(handleTaskDidTerminate:) + name:NSTaskDidTerminateNotification + object:t]; } - (NSTask*)taskForLaunch { - return nil; + NSTask* t = [[NSTask alloc] init]; + + // Pull together all the tasks parameters + NSDictionary* env = [self taskEnvironment]; + [t setEnvironment: env]; + NSArray* args = [self taskArguments]; + [t setArguments: args]; + NSString* launchPath = [[self plugin] taskPath]; + [t setLaunchPath: launchPath]; + + [self setupIOForTask:t]; + [self registerNotificationsForTask:t]; + return t; +} + + +# pragma mark Mounting mechanics +- (BOOL)setupMountPoint +{ + NSFileManager* fm = [NSFileManager defaultManager]; + NSString* mountPath = [[self parameterDictionary] objectForKey:@"Mount Point"]; + BOOL pathExists, isDir; + + pathExists = [fm fileExistsAtPath:mountPath isDirectory:&isDir]; + if (pathExists && isDir == YES) // directory already exists + { + BOOL empty = ( [[fm directoryContentsAtPath:mountPath] count] == 0 ); + BOOL writeable = [fm isWritableFileAtPath:mountPath]; + if (!empty) + { + MFLogS(self, @"Mount point directory in use: %@", mountPath); + return NO; + } + else if (!writeable) + { + MFLogS(self, @"Mount point directory not writeable: %@", mountPath); + return NO; + } + else + { + // Mount point exists and is useable. We're all good. + return YES; + } + } + else if (pathExists && !isDir) + { + MFLogS(self, @"Mount point path is a file, not a directory: %@", mountPath); + return NO; + } + else if (!pathExists) + { + MFLogS(self, @"Creating directory %@", mountPath); + [fm createDirectoryAtPath:mountPath attributes:nil]; + return YES; + } + + return NO; } -- (MFPlugin*)plugin +- (void)removeMountPoint { - if (plugin) - return plugin; + NSFileManager* fm = [NSFileManager defaultManager]; + NSString* mountPath = [[self parameterDictionary] objectForKey:@"Mount Path"]; + BOOL pathExists, isDir; + + pathExists = [fm fileExistsAtPath:mountPath isDirectory:&isDir]; + if (pathExists && isDir && ([[fm directoryContentsAtPath:mountPath] count] == 0)) + { + [fm removeFileAtPath:mountPath handler:nil]; + } +} + +- (void)mount +{ + MFLogS(self, @"Mounting!"); + self.status = kMFStatusFSWaiting; + if ([self setupMountPoint] == YES) + { + task = [self taskForLaunch]; + [[[task standardOutput] fileHandleForReading] + waitForDataInBackgroundAndNotify]; + + [NSTimer scheduledTimerWithTimeInterval:5.0 + target:self + selector:@selector(handleMountTimeout:) + userInfo:nil + repeats:NO]; + + [task launch]; + MFLogS(self, @"Task launched OK"); + } + else + { + MFLogS(self, @"Mount point could not be created"); + self.status = kMFStatusFSFailed; + } +} + +# pragma mark Notification handlers +- (void)handleMountNotification:(NSNotification*)note +{ + NSDictionary* info = [note userInfo]; + if ([[info objectForKey:@"kFUSEMountPath"] + isEqualToString:[parameters objectForKey:@"Mount Path"]]) + { + // BINGO! + self.status = kMFStatusFSMounted; + } +} + +- (void)handleTaskDidTerminate:(NSNotification*)note +{ + MFLogS(self, @"Task terminated"); + if (self.status == kMFStatusFSMounted) + { + // We are terminating after a mount has been successful + // This may not quite be normal (may be for example a bad net connection) + // But we'll set status to unmounted anyway + self.status = kMFStatusFSUnmounted; + } + else if (self.status == kMFStatusFSWaiting) + { + // We terminated while trying to mount + self.status = kMFStatusFSFailed; + } +} + +- (void)handleDataOnPipe:(NSNotification*)note +{ + NSData* pipeData = [[note object] availableData]; + if ([pipeData length] == 0) + { + // pipe is now closed + return; + } else { - MFPrint(@"Plugin empty!"); - return nil; + recentOutput = [[NSString alloc] initWithData: pipeData encoding:NSUTF8StringEncoding]; + [[note object] waitForDataInBackgroundAndNotify]; + MFLogS(self, recentOutput); + } +} + +- (void)handleUnmountNotification:(NSNotification*)note +{ + NSString* path = [[note userInfo] objectForKey:@"NSDevicePath"]; + NSString* mountPath = [parameters objectForKey:@"Mount Path"]; + if ([path isEqualToString:mountPath]) + { + self.status = kMFStatusFSUnmounted; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + MFLogS(self, @"Value change on %@", keyPath); + if ([keyPath isEqualToString:@"status"] && + object == self && + [change objectForKey:NSKeyValueChangeNewKey] == kMFStatusFSUnmounted) + { + [self removeMountPoint]; + } + + /* + [super observeValueForKeyPath:keyPath + ofObject:object + change:change + context:context]; + */ +} + +- (void)handleMountTimeout:(NSTimer*)timer +{ +// MFLogS(self, @"Mount timeout"); + if (self.status != kMFStatusFSUnmounted) + self.status = kMFStatusFSFailed; +} + +# pragma mark Accessors + +- (NSString*)pluginID +{ + return [parameters objectForKey:@"Type"]; +} + +- (NSDictionary*)parameterDictionary +{ + // We want an immutable dictionary + return [parameters copy]; +} + +- (id)valueForUndefinedKey:(NSString*)key +{ + id value = [parameters valueForKey:key]; + if (value) + { + return value; } + + return [super valueForUndefinedKey:key]; } +// TODO: Finalizer + +@synthesize status, plugin; @end diff --git a/MFFilesystemController.h b/MFFilesystemController.h index e4ba611..0f1177a 100644 --- a/MFFilesystemController.h +++ b/MFFilesystemController.h @@ -15,7 +15,8 @@ + (MFFilesystemController*)sharedController; - (void)loadFilesystems; -- (NSArray*)filesystems; + +@property(readonly) NSArray* filesystems; @end diff --git a/MFFilesystemController.m b/MFFilesystemController.m index 9afcf65..199211a 100644 --- a/MFFilesystemController.m +++ b/MFFilesystemController.m @@ -40,6 +40,16 @@ + (MFFilesystemController*)allocWithZone:(NSZone*)zone return nil; } +- (id) init +{ + self = [super init]; + if (self != nil) { + filesystems = [[NSMutableArray alloc] init]; + } + return self; +} + + - (id)copyWithZone:(NSZone*)zone { return self; @@ -77,11 +87,6 @@ - (NSArray*)pathsToFilesystemDefs return [fsDefPaths copy]; } -- (NSArray*)filesystems -{ - return filesystems; -} - - (BOOL)validateFilesystemParameters:(NSDictionary*)params { return YES; @@ -89,11 +94,11 @@ - (BOOL)validateFilesystemParameters:(NSDictionary*)params - (void)loadFilesystems { - MFPrint(@"Filesystems loading. Searching ..."); + MFLog(@"Filesystems loading. Searching ..."); NSArray* filesystemPaths = [self pathsToFilesystemDefs]; for(NSString* fsPath in filesystemPaths) { - MFPrint(@"Loading fs at %@", fsPath); + MFLog(@"Loading fs at %@", fsPath); NSDictionary* fsParams = [NSDictionary dictionaryWithContentsOfFile:fsPath]; if (fsParams && [self validateFilesystemParameters: fsParams]) { @@ -101,17 +106,18 @@ - (void)loadFilesystems MFPlugin* plugin = [[MFPluginController sharedController] pluginWithID: type]; if (plugin) { - MFFilesystem* fs = [MFFilesystem filesystemFromParameters:fsParams plugin:plugin]; - MFPrint(@"%@", fs); - MFPrint(@"Args %@", [fs taskArgumentList]); + MFFilesystem* fs = [MFFilesystem filesystemFromParameters:fsParams + plugin:plugin]; + [filesystems addObject: fs]; } else { - MFPrint(@"Failed to find plugin for Filesystem"); + MFLog(@"Failed to find plugin for Filesystem"); } } } -// MFPrint(@"%@", filesystemPaths); } +@synthesize filesystems; + @end \ No newline at end of file diff --git a/MFLoggingController.h b/MFLoggingController.h index 204be8c..75aadad 100644 --- a/MFLoggingController.h +++ b/MFLoggingController.h @@ -18,7 +18,7 @@ void MFLog(NSString* format, ...); void MFPrint(NSString* format, ...); @interface MFLoggingController : NSObject { - + NSFileHandle* fileHandle; } + (MFLoggingController*)sharedController; diff --git a/MFLoggingController.m b/MFLoggingController.m index e8dea24..2e95a51 100644 --- a/MFLoggingController.m +++ b/MFLoggingController.m @@ -7,6 +7,7 @@ // #import "MFLoggingController.h" +#define LOG_FILE_PATH @"~/Library/Logs/MacFusion2.log" // Print to logging system void MFLog(NSString* format, ...) @@ -49,7 +50,26 @@ void MFLogP(int type, NSString* format, ...) [string release]; } - + +void MFLogS(id sender, NSString* format, ...) +{ + MFLoggingController* logger = [MFLoggingController sharedController]; + + // get a reference to the arguments on the stack that follow + // the format paramter + va_list argList; + va_start (argList, format); + + // NSString luckily provides us with this handy method which + // will do all the work for us, including %@ + NSString *string; + string = [[NSString alloc] initWithFormat: format + arguments: argList]; + va_end (argList); + [logger logMessage:string ofType:0 sender:sender]; + + [string release]; +} // Print directly to console void MFPrint(NSString* format, ...) @@ -99,9 +119,60 @@ - (void)init // Nothing here yet } +- (NSString*)descriptionForObject:(id)object +{ + if (object == nil) + { + return @"NILL"; + } + else + { + return [object description]; + } +} + +- (NSFileHandle*)handleForLogfile +{ + NSFileManager* fm = [NSFileManager defaultManager]; + NSString* filePath = [ LOG_FILE_PATH stringByExpandingTildeInPath ]; + + if (![fm fileExistsAtPath:filePath]) + { + [fm createFileAtPath:filePath contents:nil attributes:nil]; + } + + fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath]; + return fileHandle; +} + +- (void)logMessageToFile:(NSString*)message ofType:(int)type sender:(id)sender +{ + NSString* description = [self descriptionForObject: sender]; + NSString* writeString = [NSString stringWithFormat: @"%@: %@", + description, message]; + + NSFileHandle* handle = [self handleForLogfile]; + [handle truncateFileAtOffset: [fileHandle seekToEndOfFile]]; + [handle writeData: [writeString dataUsingEncoding:NSUTF8StringEncoding]]; + [handle synchronizeFile]; +} + - (void)logMessage:(NSString*)message ofType:(int)type sender:(id)sender { + [self logMessageToFile:message ofType:type sender:sender]; + if (!sender) + printf("%s\n", [message cStringUsingEncoding:NSUTF8StringEncoding]); + else + printf("%s: %s\n", [[sender description] cStringUsingEncoding:NSUTF8StringEncoding], + [message cStringUsingEncoding: NSUTF8StringEncoding]); return; } + +- (void)finalize +{ + [fileHandle closeFile]; + [super finalize]; +} + @end diff --git a/MFMainController.m b/MFMainController.m index 27b437d..9a140dd 100644 --- a/MFMainController.m +++ b/MFMainController.m @@ -10,6 +10,8 @@ #import "MFPlugin.h" #import "MFPluginController.h" #import "MFFilesystemController.h" +#import "MFFilesystem.h" +#import "MFCommunicationServer.h" @implementation MFMainController static MFMainController* sharedController = nil; @@ -50,23 +52,16 @@ - (void)fire - (void)startRunloop { NSRunLoop* runloop = [NSRunLoop currentRunLoop]; - NSLog(@"Runloop initialized! Let's roll!"); + MFLog(@"Runloop initialized! Let's roll!"); [runloop run]; } -- (void)setupCommunication +- (void)runTests:(id)timer { - NSConnection* connection = [NSConnection defaultConnection]; - // TODO: Vend a proxy to set up protocol instead of, um , everything - [connection setRootObject:self]; - if ([connection registerName:@"macfusion"] == YES) - { - NSLog(@"Now Vending distributed object"); - } - else - { - NSLog(@"Failed to register connection name"); - } + MFFilesystem* fs = [[[MFFilesystemController sharedController] filesystems] + objectAtIndex:0]; + MFLogS(self,@"TICK %@", [MFFilesystemController sharedController].filesystems); + [fs mount]; } - (void)initialize @@ -75,8 +70,13 @@ - (void)initialize MFFilesystemController* filesystemController = [MFFilesystemController sharedController]; [pluginController loadPlugins]; [filesystemController loadFilesystems]; - [self setupCommunication]; - [self startRunloop]; + [NSTimer scheduledTimerWithTimeInterval:2.0 + target:self + selector:@selector(runTests:) + userInfo:nil + repeats:NO]; + + [[MFCommunicationServer sharedServer] startServingRunloop]; } @end diff --git a/MFPlugin.h b/MFPlugin.h index 28e2b2c..acdade8 100644 --- a/MFPlugin.h +++ b/MFPlugin.h @@ -17,10 +17,13 @@ @property(readonly) NSMutableDictionary* dictionary; @property(readonly) NSString* ID; @property(readonly) NSString* inputFormatString; +@property(readonly) NSBundle* bundle; + (MFPlugin*)pluginFromBundleAtPath:(NSString*)path; - (NSString*)tokenForParameter:(NSString*)param; - (NSDictionary*)defaultParameterDictionary; +- (NSString*)taskPath; +- (id)defaultValueForParameter:(NSString*)parameterName; @end diff --git a/MFPlugin.m b/MFPlugin.m index 4cdc803..fdc2550 100644 --- a/MFPlugin.m +++ b/MFPlugin.m @@ -12,8 +12,29 @@ @implementation MFPlugin + (MFPlugin*)pluginFromBundleAtPath:(NSString*)path { - MFPlugin* plugin = [[MFPlugin alloc] initWithPath:path]; - return [plugin autorelease]; + + MFPlugin* plugin = nil; + NSBundle* b = [NSBundle bundleWithPath:path]; + NSString* pluginClassName = [b objectForInfoDictionaryKey:@"MFPluginClass"]; + if (pluginClassName == nil || [pluginClassName isEqualToString:@"MFPlugin"]) + { + plugin = [[MFPlugin alloc] initWithPath:path]; + } + else + { + BOOL success = [b load]; + if (success) + { + Class PluginClass = NSClassFromString(pluginClassName); + plugin = [[PluginClass alloc] initWithPath:path]; + } + else + { + MFLog(@"Failed to load bundle for plugin at path %@", path); + } + } + + return plugin; } - (MFPlugin*)initWithPath:(NSString*)path @@ -33,16 +54,55 @@ - (MFPlugin*)initWithPath:(NSString*)path return self; } +- (id)defaultValueForParameter:(NSString*)parameterName +{ + return nil; +} + +- (void)fillDefaultsDictionary:(NSMutableDictionary*)defaultsDictionary fromParameterDescription:(NSDictionary*)parametersDict +{ + for(NSString* parameterKey in [parametersDict keyEnumerator]) + { + NSDictionary* parameterDict = [parametersDict objectForKey:parameterKey]; + id defaultValueForParam = [self defaultValueForParameter: parameterKey]; + if (!defaultValueForParam) + { + defaultValueForParam = [parameterDict objectForKey:@"Default Value"]; + } + + if (defaultValueForParam) + { + [defaultsDictionary setObject:defaultValueForParam + forKey:parameterKey]; + } + else + { + MFLogS(self, @"Can not get a default value for parameter: %@", + parameterKey); + } + } +} + - (NSDictionary*)defaultParameterDictionary { NSMutableDictionary* defaultsDictionary = [NSMutableDictionary dictionary]; NSDictionary* parametersDict = [dictionary objectForKey:@"Parameters"]; - for(NSString* parameterKey in [parametersDict keyEnumerator]) + [self fillDefaultsDictionary:defaultsDictionary fromParameterDescription:parametersDict]; + + // Add in parameters common across all FUSE filesystems + NSBundle* searchBundle = [NSBundle bundleForClass: [MFPlugin class]]; + MFLog(@"Bundle to search %@", searchBundle); + NSString* fusePlistPath = [searchBundle pathForResource:@"fuse" ofType:@"plist"]; + NSDictionary* fusePlist = [NSDictionary dictionaryWithContentsOfFile:fusePlistPath]; + NSDictionary* fuseParams = [fusePlist objectForKey:@"Parameters"]; + if (fuseParams) { - NSDictionary* parameterDict = [parametersDict objectForKey:parameterKey]; - id defaultValueForParam = [parameterDict objectForKey:@"Default Value"]; - [defaultsDictionary setObject:defaultValueForParam - forKey:parameterKey]; + [self fillDefaultsDictionary:defaultsDictionary + fromParameterDescription:fuseParams]; + } + else + { + MFLogS(@"Can not read parameters from FUSE dictionary"); } return defaultsDictionary; @@ -94,5 +154,5 @@ - (NSString*)ID return [self.dictionary objectForKey: @"BundleIdentifier"]; } -@synthesize dictionary; +@synthesize dictionary, bundle; @end diff --git a/MFPluginController.m b/MFPluginController.m index fcfcfdb..add5939 100644 --- a/MFPluginController.m +++ b/MFPluginController.m @@ -91,7 +91,7 @@ - (BOOL)validatePluginAtPath:(NSString*)path - (void)loadPlugins { - NSLog(@"Plugins being loaded. Searching..."); + MFLog(@"Plugins being loaded. Searching..."); NSArray* pluginBundlePaths = [self pathsToPluginBundles]; for(NSString* path in pluginBundlePaths) { @@ -100,13 +100,13 @@ - (void)loadPlugins if ([self validatePluginAtPath: path] && (newPlugin = [MFPlugin pluginFromBundleAtPath: path])) { [plugins setObject: newPlugin forKey: newPlugin.ID]; - MFPrint(@"%@", plugins); - MFPrint(@"Loaded plugin at path %@ OK", path); - MFPrint(@"Name: %@", newPlugin.ID); + MFLog(@"%@", plugins); + MFLog(@"Loaded plugin at path %@ OK", path); + MFLog(@"Name: %@", newPlugin.ID); } else { - NSLog(@"Failed to load plugin at path %@", path); + MFLog(@"Failed to load plugin at path %@", path); } } } diff --git a/MacFusion2.xcodeproj/project.pbxproj b/MacFusion2.xcodeproj/project.pbxproj index d91d06e..50493ac 100644 --- a/MacFusion2.xcodeproj/project.pbxproj +++ b/MacFusion2.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ ); dependencies = ( D4FC0DAB0CF23D0D0029B133 /* PBXTargetDependency */, + D439D6490D0A06DD0025574A /* PBXTargetDependency */, D4FC0DA90CF23D060029B133 /* PBXTargetDependency */, D4FC0DA70CF23D040029B133 /* PBXTargetDependency */, ); @@ -39,15 +40,27 @@ 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; }; D40B79B40CF8B99500EB3137 /* SSHFilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = D40B79B30CF8B99500EB3137 /* SSHFilesystem.m */; }; D40B79B70CF8B9A200EB3137 /* SSHPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = D40B79B60CF8B9A200EB3137 /* SSHPlugin.m */; }; + D4386BB70D0B44070078C19F /* macfusionPrefs.xib in Resources */ = {isa = PBXBuildFile; fileRef = D4386BB60D0B44070078C19F /* macfusionPrefs.xib */; }; + D4386BBB0D0B44D10078C19F /* MFPreferencePane.m in Sources */ = {isa = PBXBuildFile; fileRef = D4386BBA0D0B44D10078C19F /* MFPreferencePane.m */; }; + D4386BC00D0B461A0078C19F /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4386BBF0D0B461A0078C19F /* PreferencePanes.framework */; }; + D4386C0E0D0B472D0078C19F /* macfusionIcon.icns in CopyFiles */ = {isa = PBXBuildFile; fileRef = D4386C0B0D0B47240078C19F /* macfusionIcon.icns */; }; + D4386C0F0D0B47340078C19F /* macfusionIcon.icns in CopyFiles */ = {isa = PBXBuildFile; fileRef = D4386C0B0D0B47240078C19F /* macfusionIcon.icns */; }; + D439D5950D09E4390025574A /* MFServerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D439D5940D09E4390025574A /* MFServerProtocol.h */; }; + D439D5980D09E4480025574A /* MFCommunicationServer.m in Sources */ = {isa = PBXBuildFile; fileRef = D439D5910D09E1510025574A /* MFCommunicationServer.m */; }; + D439D6D60D0A0FDE0025574A /* sshfsConfiguration.xib in Resources */ = {isa = PBXBuildFile; fileRef = D439D6D50D0A0FDE0025574A /* sshfsConfiguration.xib */; }; D44152720CE2E344001EEF36 /* MFMainController.m in Sources */ = {isa = PBXBuildFile; fileRef = D42E13E50CDFC69500C81814 /* MFMainController.m */; }; D44152730CE2E344001EEF36 /* MFPluginController.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B14C850CE0455A003195A3 /* MFPluginController.m */; }; + D46E4C0E0D02593B004926CE /* MFConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = D46E4C0D0D02593B004926CE /* MFConstants.m */; }; D4B14BC90CE03D25003195A3 /* sshnodelay.so in Resources */ = {isa = PBXBuildFile; fileRef = D4B14BAA0CE03C84003195A3 /* sshnodelay.so */; }; D4B14BCA0CE03D25003195A3 /* sshfs.plist in Resources */ = {isa = PBXBuildFile; fileRef = D4B14BAB0CE03C84003195A3 /* sshfs.plist */; }; D4B14BCB0CE03D25003195A3 /* sshfs-static in Resources */ = {isa = PBXBuildFile; fileRef = D4B14BAC0CE03C84003195A3 /* sshfs-static */; }; - D4B14D740CE195CB003195A3 /* macfusionctl.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B14D730CE195CB003195A3 /* macfusionctl.m */; }; + D4B14D740CE195CB003195A3 /* mfctl.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B14D730CE195CB003195A3 /* mfctl.m */; }; D4B14EE30CE2468B003195A3 /* MFLoggingController.h in Headers */ = {isa = PBXBuildFile; fileRef = D4B14EE10CE2468B003195A3 /* MFLoggingController.h */; }; D4B14EE40CE2468B003195A3 /* MFLoggingController.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B14EE20CE2468B003195A3 /* MFLoggingController.m */; }; D4B14FC20CE25A88003195A3 /* MFFilesystemController.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B14FC10CE25A88003195A3 /* MFFilesystemController.m */; }; + D4D6A0D80D025B4A00BC2E2D /* MFConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D6A0D70D025B4A00BC2E2D /* MFConstants.h */; }; + D4D6A1250D03548C00BC2E2D /* MFCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4FC0C980CF128480029B133 /* MFCore.framework */; }; + D4D6A2230D03686000BC2E2D /* fuse.plist in Resources */ = {isa = PBXBuildFile; fileRef = D4D6A2220D03686000BC2E2D /* fuse.plist */; }; D4E51FE60CE03AC3009B1A30 /* MFMainController.h in Headers */ = {isa = PBXBuildFile; fileRef = D42E13E40CDFC69500C81814 /* MFMainController.h */; }; D4E51FE70CE03AC3009B1A30 /* MFPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = D42E141B0CDFC99A00C81814 /* MFPlugin.h */; }; D4E51FE80CE03AC3009B1A30 /* MFFilesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = D42E14540CDFCF9000C81814 /* MFFilesystem.h */; }; @@ -55,10 +68,17 @@ D4E51FEB0CE03ACA009B1A30 /* MFFilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = D42E14550CDFCF9000C81814 /* MFFilesystem.m */; }; D4FC0C990CF128480029B133 /* MFCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4FC0C980CF128480029B133 /* MFCore.framework */; }; D4FC0C9A0CF128480029B133 /* MFCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4FC0C980CF128480029B133 /* MFCore.framework */; }; - D4FC0D1C0CF148720029B133 /* sshfs.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = D441521F0CE2933C001EEF36 /* sshfs.bundle */; }; + D4FC0D1C0CF148720029B133 /* sshfs.mfplugin in CopyFiles */ = {isa = PBXBuildFile; fileRef = D441521F0CE2933C001EEF36 /* sshfs.mfplugin */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + D439D6480D0A06DD0025574A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D4B14D6B0CE19545003195A3; + remoteInfo = mfctl; + }; D4B14C620CE044C5003195A3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; @@ -80,6 +100,13 @@ remoteGlobalIDString = D42E15540CE03A8200C81814; remoteInfo = MFCore; }; + D4D6A11E0D03548100BC2E2D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D42E15540CE03A8200C81814; + remoteInfo = MFCore; + }; D4E51FEC0CE03AD3009B1A30 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; @@ -117,16 +144,27 @@ dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( + D4386C0E0D0B472D0078C19F /* macfusionIcon.icns in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; + D4386C070D0B46CF0078C19F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 7; + files = ( + D4386C0F0D0B47340078C19F /* macfusionIcon.icns in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4B14C5E0CE044C0003195A3 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "~/Library/Application Support/Macfusion/Plugins"; dstSubfolderSpec = 0; files = ( - D4FC0D1C0CF148720029B133 /* sshfs.bundle in CopyFiles */, + D4FC0D1C0CF148720029B133 /* sshfs.mfplugin in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -147,20 +185,35 @@ D42E14540CDFCF9000C81814 /* MFFilesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFFilesystem.h; sourceTree = ""; }; D42E14550CDFCF9000C81814 /* MFFilesystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFFilesystem.m; sourceTree = ""; }; D42E15560CE03A8200C81814 /* MFCore-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MFCore-Info.plist"; sourceTree = ""; }; - D435480E0CE3DAF100EE39C6 /* macfusiond */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macfusiond; sourceTree = BUILT_PRODUCTS_DIR; }; - D441521F0CE2933C001EEF36 /* sshfs.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sshfs.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + D4386BB10D0B43B20078C19F /* macfusionPreferences.prefpane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = macfusionPreferences.prefpane; sourceTree = BUILT_PRODUCTS_DIR; }; + D4386BB20D0B43B20078C19F /* macfusionPreferences-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "macfusionPreferences-Info.plist"; path = "../macfusionPreferences-Info.plist"; sourceTree = ""; }; + D4386BB60D0B44070078C19F /* macfusionPrefs.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = macfusionPrefs.xib; sourceTree = ""; }; + D4386BB90D0B44D10078C19F /* MFPreferencePane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFPreferencePane.h; sourceTree = ""; }; + D4386BBA0D0B44D10078C19F /* MFPreferencePane.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFPreferencePane.m; sourceTree = ""; }; + D4386BBF0D0B461A0078C19F /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = /System/Library/Frameworks/PreferencePanes.framework; sourceTree = ""; }; + D4386C0A0D0B46EE0078C19F /* macfusion.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = macfusion.tiff; path = Images/macfusion.tiff; sourceTree = ""; }; + D4386C0B0D0B47240078C19F /* macfusionIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = macfusionIcon.icns; path = Images/macfusionIcon.icns; sourceTree = ""; }; + D439D4370D05D58D0025574A /* macfusionAgent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macfusionAgent; sourceTree = BUILT_PRODUCTS_DIR; }; + D439D5900D09E1510025574A /* MFCommunicationServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFCommunicationServer.h; sourceTree = ""; }; + D439D5910D09E1510025574A /* MFCommunicationServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFCommunicationServer.m; sourceTree = ""; }; + D439D5940D09E4390025574A /* MFServerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFServerProtocol.h; sourceTree = ""; }; + D439D6D50D0A0FDE0025574A /* sshfsConfiguration.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = sshfsConfiguration.xib; sourceTree = ""; }; + D441521F0CE2933C001EEF36 /* sshfs.mfplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sshfs.mfplugin; sourceTree = BUILT_PRODUCTS_DIR; }; + D46E4C0D0D02593B004926CE /* MFConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFConstants.m; sourceTree = ""; }; D4B14BAA0CE03C84003195A3 /* sshnodelay.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = sshnodelay.so; sourceTree = ""; }; D4B14BAB0CE03C84003195A3 /* sshfs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = sshfs.plist; sourceTree = ""; }; D4B14BAC0CE03C84003195A3 /* sshfs-static */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = "sshfs-static"; sourceTree = ""; }; D4B14C0F0CE03F4C003195A3 /* sshfs-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "sshfs-Info.plist"; sourceTree = ""; }; D4B14C840CE0455A003195A3 /* MFPluginController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFPluginController.h; sourceTree = ""; }; D4B14C850CE0455A003195A3 /* MFPluginController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFPluginController.m; sourceTree = ""; }; - D4B14D730CE195CB003195A3 /* macfusionctl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = macfusionctl.m; sourceTree = ""; }; - D4B14E730CE198AC003195A3 /* macfusionctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macfusionctl; sourceTree = BUILT_PRODUCTS_DIR; }; + D4B14D730CE195CB003195A3 /* mfctl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = mfctl.m; sourceTree = ""; }; + D4B14E730CE198AC003195A3 /* mfctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mfctl; sourceTree = BUILT_PRODUCTS_DIR; }; D4B14EE10CE2468B003195A3 /* MFLoggingController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoggingController.h; sourceTree = ""; }; D4B14EE20CE2468B003195A3 /* MFLoggingController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoggingController.m; sourceTree = ""; }; D4B14FC00CE25A88003195A3 /* MFFilesystemController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFFilesystemController.h; sourceTree = ""; }; D4B14FC10CE25A88003195A3 /* MFFilesystemController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFFilesystemController.m; sourceTree = ""; }; + D4D6A0D70D025B4A00BC2E2D /* MFConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFConstants.h; sourceTree = ""; }; + D4D6A2220D03686000BC2E2D /* fuse.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = fuse.plist; sourceTree = ""; }; D4FC0C980CF128480029B133 /* MFCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MFCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -181,10 +234,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4386BAF0D0B43B20078C19F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D4386BC00D0B461A0078C19F /* PreferencePanes.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4B14BB40CE03CC3003195A3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D4D6A1250D03548C00BC2E2D /* MFCore.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -202,6 +264,7 @@ 08FB7794FE84155DC02AAC07 /* macfusiond */ = { isa = PBXGroup; children = ( + D4386C060D0B46CF0078C19F /* Resources */, D4B14EE00CE24671003195A3 /* Shared */, D4B14D660CE19514003195A3 /* ConsoleClient */, D4E5200C0CE03B82009B1A30 /* Daemon */, @@ -229,15 +292,45 @@ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = { isa = PBXGroup; children = ( + D4386BBF0D0B461A0078C19F /* PreferencePanes.framework */, 08FB779EFE84155DC02AAC07 /* Foundation.framework */, ); name = "External Frameworks and Libraries"; sourceTree = ""; }; + D4386C060D0B46CF0078C19F /* Resources */ = { + isa = PBXGroup; + children = ( + D4386C080D0B46D90078C19F /* Images */, + D4D6A22A0D03686500BC2E2D /* Property Lists */, + ); + name = Resources; + sourceTree = ""; + }; + D4386C080D0B46D90078C19F /* Images */ = { + isa = PBXGroup; + children = ( + D4386C0B0D0B47240078C19F /* macfusionIcon.icns */, + D4386C0A0D0B46EE0078C19F /* macfusion.tiff */, + ); + name = Images; + sourceTree = ""; + }; + D439D5310D090E040025574A /* Prefpane */ = { + isa = PBXGroup; + children = ( + D4386BB60D0B44070078C19F /* macfusionPrefs.xib */, + D4386BB90D0B44D10078C19F /* MFPreferencePane.h */, + D4386BBA0D0B44D10078C19F /* MFPreferencePane.m */, + D4386BB20D0B43B20078C19F /* macfusionPreferences-Info.plist */, + ); + path = Prefpane; + sourceTree = ""; + }; D4B14D660CE19514003195A3 /* ConsoleClient */ = { isa = PBXGroup; children = ( - D4B14D730CE195CB003195A3 /* macfusionctl.m */, + D4B14D730CE195CB003195A3 /* mfctl.m */, ); name = ConsoleClient; sourceTree = ""; @@ -245,10 +338,11 @@ D4B14E620CE1987F003195A3 /* Products */ = { isa = PBXGroup; children = ( - D4B14E730CE198AC003195A3 /* macfusionctl */, - D441521F0CE2933C001EEF36 /* sshfs.bundle */, - D435480E0CE3DAF100EE39C6 /* macfusiond */, + D4B14E730CE198AC003195A3 /* mfctl */, + D441521F0CE2933C001EEF36 /* sshfs.mfplugin */, D4FC0C980CF128480029B133 /* MFCore.framework */, + D439D4370D05D58D0025574A /* macfusionAgent */, + D4386BB10D0B43B20078C19F /* macfusionPreferences.prefpane */, ); name = Products; sourceTree = ""; @@ -258,10 +352,21 @@ children = ( D4B14EE10CE2468B003195A3 /* MFLoggingController.h */, D4B14EE20CE2468B003195A3 /* MFLoggingController.m */, + D4D6A0D70D025B4A00BC2E2D /* MFConstants.h */, + D46E4C0D0D02593B004926CE /* MFConstants.m */, + D439D5940D09E4390025574A /* MFServerProtocol.h */, ); name = Shared; sourceTree = ""; }; + D4D6A22A0D03686500BC2E2D /* Property Lists */ = { + isa = PBXGroup; + children = ( + D4D6A2220D03686000BC2E2D /* fuse.plist */, + ); + name = "Property Lists"; + sourceTree = ""; + }; D4E5200C0CE03B82009B1A30 /* Daemon */ = { isa = PBXGroup; children = ( @@ -273,6 +378,8 @@ D4B14C850CE0455A003195A3 /* MFPluginController.m */, D4B14FC00CE25A88003195A3 /* MFFilesystemController.h */, D4B14FC10CE25A88003195A3 /* MFFilesystemController.m */, + D439D5900D09E1510025574A /* MFCommunicationServer.h */, + D439D5910D09E1510025574A /* MFCommunicationServer.m */, ); name = Daemon; sourceTree = ""; @@ -280,6 +387,7 @@ D4E5200E0CE03B9D009B1A30 /* UI */ = { isa = PBXGroup; children = ( + D439D5310D090E040025574A /* Prefpane */, ); name = UI; sourceTree = ""; @@ -303,6 +411,7 @@ D40B79B30CF8B99500EB3137 /* SSHFilesystem.m */, D40B79B50CF8B9A200EB3137 /* SSHPlugin.h */, D40B79B60CF8B9A200EB3137 /* SSHPlugin.m */, + D439D6D50D0A0FDE0025574A /* sshfsConfiguration.xib */, ); path = SSHFS; sourceTree = ""; @@ -318,6 +427,8 @@ D4E51FE70CE03AC3009B1A30 /* MFPlugin.h in Headers */, D4E51FE80CE03AC3009B1A30 /* MFFilesystem.h in Headers */, D4B14EE30CE2468B003195A3 /* MFLoggingController.h in Headers */, + D4D6A0D80D025B4A00BC2E2D /* MFConstants.h in Headers */, + D439D5950D09E4390025574A /* MFServerProtocol.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -341,7 +452,7 @@ name = macfusionAgent; productInstallPath = "$(HOME)/bin"; productName = macfusiond; - productReference = D435480E0CE3DAF100EE39C6 /* macfusiond */; + productReference = D439D4370D05D58D0025574A /* macfusionAgent */; productType = "com.apple.product-type.tool"; }; D42E15540CE03A8200C81814 /* MFCore */ = { @@ -362,6 +473,24 @@ productReference = D4FC0C980CF128480029B133 /* MFCore.framework */; productType = "com.apple.product-type.framework"; }; + D4386BB00D0B43B20078C19F /* macfusionPreferences */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4386BB50D0B43B20078C19F /* Build configuration list for PBXNativeTarget "macfusionPreferences" */; + buildPhases = ( + D4386BAD0D0B43B20078C19F /* Resources */, + D4386BAE0D0B43B20078C19F /* Sources */, + D4386BAF0D0B43B20078C19F /* Frameworks */, + D4386C070D0B46CF0078C19F /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = macfusionPreferences; + productName = macfusionPreferences; + productReference = D4386BB10D0B43B20078C19F /* macfusionPreferences.prefpane */; + productType = "com.apple.product-type.bundle"; + }; D4B14BB50CE03CC3003195A3 /* sshfs */ = { isa = PBXNativeTarget; buildConfigurationList = D4B14BBA0CE03CC4003195A3 /* Build configuration list for PBXNativeTarget "sshfs" */; @@ -373,15 +502,16 @@ buildRules = ( ); dependencies = ( + D4D6A11F0D03548100BC2E2D /* PBXTargetDependency */, ); name = sshfs; productName = SSHFS; - productReference = D441521F0CE2933C001EEF36 /* sshfs.bundle */; + productReference = D441521F0CE2933C001EEF36 /* sshfs.mfplugin */; productType = "com.apple.product-type.bundle"; }; - D4B14D6B0CE19545003195A3 /* macfusionctl */ = { + D4B14D6B0CE19545003195A3 /* mfctl */ = { isa = PBXNativeTarget; - buildConfigurationList = D4B14D720CE19555003195A3 /* Build configuration list for PBXNativeTarget "macfusionctl" */; + buildConfigurationList = D4B14D720CE19555003195A3 /* Build configuration list for PBXNativeTarget "mfctl" */; buildPhases = ( D4B14D690CE19545003195A3 /* Sources */, D4B14D6A0CE19545003195A3 /* Frameworks */, @@ -391,9 +521,9 @@ dependencies = ( D4B14F250CE24F1A003195A3 /* PBXTargetDependency */, ); - name = macfusionctl; + name = mfctl; productName = macfusionctl; - productReference = D4B14E730CE198AC003195A3 /* macfusionctl */; + productReference = D4B14E730CE198AC003195A3 /* mfctl */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ @@ -412,8 +542,9 @@ D42E15540CE03A8200C81814 /* MFCore */, D4B14BB50CE03CC3003195A3 /* sshfs */, D4B14C5F0CE044C0003195A3 /* Plugin Install */, - D4B14D6B0CE19545003195A3 /* macfusionctl */, + D4B14D6B0CE19545003195A3 /* mfctl */, D4FC0DA30CF23CFE0029B133 /* All */, + D4386BB00D0B43B20078C19F /* macfusionPreferences */, ); }; /* End PBXProject section */ @@ -423,6 +554,15 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4D6A2230D03686000BC2E2D /* fuse.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D4386BAD0D0B43B20078C19F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4386BB70D0B44070078C19F /* macfusionPrefs.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -433,6 +573,7 @@ D4B14BC90CE03D25003195A3 /* sshnodelay.so in Resources */, D4B14BCA0CE03D25003195A3 /* sshfs.plist in Resources */, D4B14BCB0CE03D25003195A3 /* sshfs-static in Resources */, + D439D6D60D0A0FDE0025574A /* sshfsConfiguration.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -447,6 +588,7 @@ D44152730CE2E344001EEF36 /* MFPluginController.m in Sources */, 8DD76F9A0486AA7600D96B5E /* macfusionAgent.m in Sources */, D4B14FC20CE25A88003195A3 /* MFFilesystemController.m in Sources */, + D439D5980D09E4480025574A /* MFCommunicationServer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -457,6 +599,15 @@ D4E51FEA0CE03ACA009B1A30 /* MFPlugin.m in Sources */, D4E51FEB0CE03ACA009B1A30 /* MFFilesystem.m in Sources */, D4B14EE40CE2468B003195A3 /* MFLoggingController.m in Sources */, + D46E4C0E0D02593B004926CE /* MFConstants.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D4386BAE0D0B43B20078C19F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4386BBB0D0B44D10078C19F /* MFPreferencePane.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -473,13 +624,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D4B14D740CE195CB003195A3 /* macfusionctl.m in Sources */, + D4B14D740CE195CB003195A3 /* mfctl.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + D439D6490D0A06DD0025574A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D4B14D6B0CE19545003195A3 /* mfctl */; + targetProxy = D439D6480D0A06DD0025574A /* PBXContainerItemProxy */; + }; D4B14C630CE044C5003195A3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D4B14BB50CE03CC3003195A3 /* sshfs */; @@ -495,6 +651,11 @@ target = D42E15540CE03A8200C81814 /* MFCore */; targetProxy = D4B14F240CE24F1A003195A3 /* PBXContainerItemProxy */; }; + D4D6A11F0D03548100BC2E2D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D42E15540CE03A8200C81814 /* MFCore */; + targetProxy = D4D6A11E0D03548100BC2E2D /* PBXContainerItemProxy */; + }; D4E51FED0CE03AD3009B1A30 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D42E15540CE03A8200C81814 /* MFCore */; @@ -534,7 +695,7 @@ "$(inherited)", "\"$(SRCROOT)/SSHFS\"", ); - PRODUCT_NAME = macfusiond; + PRODUCT_NAME = macfusionAgent; }; name = Release; }; @@ -578,6 +739,55 @@ }; name = Release; }; + D4386BB30D0B43B20078C19F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "macfusionPreferences-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Bundles"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = macfusionPreferences; + WRAPPER_EXTENSION = prefpane; + ZERO_LINK = NO; + }; + name = Release; + }; + D4386BB40D0B43B20078C19F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INFOPLIST_FILE = "macfusionPreferences-Info.plist"; + INSTALL_PATH = "$(HOME)/Library/Bundles"; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PREBINDING = NO; + PRODUCT_NAME = macfusionPreferences; + WRAPPER_EXTENSION = prefpane; + ZERO_LINK = YES; + }; + name = Debug; + }; D4B14BB90CE03CC4003195A3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -597,7 +807,7 @@ ); PREBINDING = NO; PRODUCT_NAME = sshfs; - WRAPPER_EXTENSION = bundle; + WRAPPER_EXTENSION = mfplugin; ZERO_LINK = NO; }; name = Release; @@ -634,7 +844,7 @@ AppKit, ); PREBINDING = NO; - PRODUCT_NAME = macfusionctl; + PRODUCT_NAME = mfctl; ZERO_LINK = NO; }; name = Release; @@ -676,7 +886,7 @@ "$(inherited)", "\"$(SRCROOT)/SSHFS\"", ); - PRODUCT_NAME = macfusiond; + PRODUCT_NAME = macfusionAgent; }; name = Debug; }; @@ -725,7 +935,7 @@ ); PREBINDING = NO; PRODUCT_NAME = sshfs; - WRAPPER_EXTENSION = bundle; + WRAPPER_EXTENSION = mfplugin; ZERO_LINK = NO; }; name = Debug; @@ -762,7 +972,7 @@ AppKit, ); PREBINDING = NO; - PRODUCT_NAME = macfusionctl; + PRODUCT_NAME = mfctl; ZERO_LINK = NO; }; name = Debug; @@ -808,6 +1018,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D4386BB50D0B43B20078C19F /* Build configuration list for PBXNativeTarget "macfusionPreferences" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D4386BB30D0B43B20078C19F /* Release */, + D4386BB40D0B43B20078C19F /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D4B14BBA0CE03CC4003195A3 /* Build configuration list for PBXNativeTarget "sshfs" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -826,7 +1045,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D4B14D720CE19555003195A3 /* Build configuration list for PBXNativeTarget "macfusionctl" */ = { + D4B14D720CE19555003195A3 /* Build configuration list for PBXNativeTarget "mfctl" */ = { isa = XCConfigurationList; buildConfigurations = ( D4B14D6F0CE19545003195A3 /* Release */, diff --git a/SSHFS/SSHFilesystem.h b/SSHFS/SSHFilesystem.h index af7b5c6..d817daf 100644 --- a/SSHFS/SSHFilesystem.h +++ b/SSHFS/SSHFilesystem.h @@ -7,7 +7,7 @@ // #import - +#import "MFFilesystem.h" @interface SSHFilesystem : MFFilesystem { diff --git a/SSHFS/SSHFilesystem.m b/SSHFS/SSHFilesystem.m index ea5be53..8475b90 100644 --- a/SSHFS/SSHFilesystem.m +++ b/SSHFS/SSHFilesystem.m @@ -10,23 +10,40 @@ @implementation SSHFilesystem -- (NSArray*)taskArgumentList +- (NSArray*)taskArguments { - NSMutableArray* arguments; + NSMutableArray* arguments = [NSMutableArray array]; [arguments addObject: [NSString stringWithFormat:@"%@@%@:%@", [parameters objectForKey:@"User"], [parameters objectForKey:@"Host"], [parameters objectForKey:@"Directory"]]]; - [arguments addObject: [parameters objectForKey: @"Mount Path"]]; - [arguments addObject: [parameters objectForKey: @"Port"]]; + [arguments addObject: [parameters objectForKey: @"Mount Point"]]; + [arguments addObject: [NSString stringWithFormat: @"-p%@", + [parameters objectForKey: @"Port"]]]; [arguments addObject: @"-oCheckHostIP=no"]; [arguments addObject: @"-oStrictHostKeyChecking=no"]; [arguments addObject: @"-oNumberOfPasswordPrompts=1"]; [arguments addObject: @"-ofollow_symlinks"]; + [arguments addObject: [NSString stringWithFormat: @"-ovolname=", + [parameters objectForKey:@"Volume Name"]]]; [arguments addObject: @"-f"]; + return arguments; } - +- (NSMutableDictionary*)fullParametersWithDictionary:(NSDictionary*)fsParams +{ + // Epic scale hack enabled! + NSMutableDictionary* hackedDictionary = [NSMutableDictionary dictionary]; + [hackedDictionary setObject:@"sccs" forKey:@"Host"]; + [hackedDictionary setObject:@"" forKey:@"Directory"]; + [hackedDictionary setObject:[NSNumber numberWithInt: 22] + forKey:@"Port"]; + [hackedDictionary setObject:@"mgorbach" forKey:@"User"]; + [hackedDictionary setObject:@"/Volumes/testMount" forKey:@"Mount Point"]; + [hackedDictionary setObject:@"Swarthmore" + forKey:@"Volume Name"]; + return hackedDictionary; +} @end diff --git a/SSHFS/SSHPlugin.h b/SSHFS/SSHPlugin.h index f1d135a..54e8584 100644 --- a/SSHFS/SSHPlugin.h +++ b/SSHFS/SSHPlugin.h @@ -7,7 +7,7 @@ // #import - +#import "MFPlugin.h" @interface SSHPlugin : MFPlugin { diff --git a/SSHFS/SSHPlugin.m b/SSHFS/SSHPlugin.m index 34a3f41..3643345 100644 --- a/SSHFS/SSHPlugin.m +++ b/SSHFS/SSHPlugin.m @@ -8,7 +8,6 @@ #import "SSHPlugin.h" - @implementation SSHPlugin @end diff --git a/SSHFS/sshfs-Info.plist b/SSHFS/sshfs-Info.plist index bd87b0e..5c05934 100644 --- a/SSHFS/sshfs-Info.plist +++ b/SSHFS/sshfs-Info.plist @@ -16,6 +16,10 @@ ???? CFBundleVersion 1.0 + MFFilesystemClass + SSHFilesystem + MFPluginClass + SSHPlugin MFPluginPlist sshfs.plist diff --git a/fuse.plist b/fuse.plist new file mode 100644 index 0000000..2b5801e --- /dev/null +++ b/fuse.plist @@ -0,0 +1,23 @@ + + + + + Parameters + + Mount Point + + Description + The location on this computer at which the filesystem will be located (mounted). + Token + mountpoint + Type + String + + Volume Name + + Description + Name of the volume + + + + diff --git a/macfusionPreferences-Info.plist b/macfusionPreferences-Info.plist new file mode 100644 index 0000000..d20a829 --- /dev/null +++ b/macfusionPreferences-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.mgorbach.macfusion.prefpane + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Macfusion Preferences + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + macfusionPrefs + NSPrefPaneIconFile + macfusionIcon + NSPrefPaneIconLabel + Macfusion 2 + NSPrincipalClass + MFPreferencePane + + diff --git a/macfusionctl.m b/macfusionctl.m deleted file mode 100644 index 0f603c1..0000000 --- a/macfusionctl.m +++ /dev/null @@ -1,34 +0,0 @@ -#import -#import "MFLoggingController.h" -#include "stdarg.h" - -int main (int argc, const char * argv[]) { - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - - NSArray* args = [[NSProcessInfo processInfo] arguments]; - if ([args count] < 2) - { - MFPrint(@"No arguments given. Exiting ..."); - return 0; - } - else if ([[args objectAtIndex: 1] isEqualToString:@"list"]) - { - if ([args count] < 3) - { - MFPrint(@"Not enough arguments. What to list?"); - return 0; - } - else if ([[args objectAtIndex: 2] isEqualToString:@"plugins"]) - { - MFPrint(@"Listing plugins"); - } - } - else - { - MFPrint(@"Invalid argument"); - return 0; - } - - [pool drain]; - return 0; -} \ No newline at end of file diff --git a/mfctl.m b/mfctl.m new file mode 100644 index 0000000..50f1930 --- /dev/null +++ b/mfctl.m @@ -0,0 +1,97 @@ +#import +#import "MFLoggingController.h" +#import "MFServerProtocol.h" +#import "MFFilesystemController.h" +#import "MFFilesystem.h" + +#include "stdarg.h" + +static id serverObject = nil; + +BOOL connectToServer(void) +{ + serverObject = [NSConnection rootProxyForConnectionWithRegisteredName:@"macfusion" host:nil]; + [serverObject setProtocolForProxy:@protocol(MFServerProtocol)]; + if (serverObject) + { + return YES; + } + else + { + return NO; + } +} + +void listPlugins(void) +{ + return; +} + +void listFilesystems(void) +{ + if (connectToServer()) + { + [serverObject sendStatus]; + NSArray* filesystems = [[serverObject filesystemController] filesystems]; + NSMutableArray* stringsToPrint = [NSMutableArray array]; + for(MFFilesystem* fs in filesystems) + { + [stringsToPrint addObject: + [NSString stringWithFormat:@"%@: %@", + [fs valueForKey:@"Volume Name"], + [fs valueForKey:@"status"]]]; + } + MFPrint(@"%@", serverObject); + MFPrint(@"%@", stringsToPrint); + } + else + { + MFPrint(@"Can not connect to macfusion agent. Exiting!"); + exit(-1); + } +} + +int main (int argc, const char * argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + NSArray* args = [[NSProcessInfo processInfo] arguments]; + + + if ([args count] < 2) + { + MFPrint(@"No arguments given. Exiting!"); + return 0; + } + else if ([[args objectAtIndex: 1] isEqualToString:@"list"]) + { + if ([args count] < 3) + { + MFPrint(@"Not enough arguments. What to list?"); + return -1; + } + if ([[args objectAtIndex: 2] isEqualToString:@"filesystems"]) + { + listFilesystems(); + } + else if ([[args objectAtIndex: 2] isEqualToString:@"plugins"]) + { + listPlugins(); + } + else + { + MFPrint(@"Syntax error: 'list' command must be followed by 'plugins' \ + or 'filesystems'. Exiting!"); + return -1; + } + } + else + { + MFPrint(@"Invalid first argument. Exiting!"); + } + + [pool drain]; + return 0; +} + + +