Getting a list of all bootable drives mac - objective-c

I'm currently looking for a way to get a list of all the bootable partitions on a Mac?
I know you can get a list of all the volumes? But I don't know how to check if each particular volume is bootable?
Is there a way to do this using swift or objective c?

With objective-c or swift probably not, but you can run an apple script (terminal commands) from your objective-c app (on OS X, I don't know whether it can be done on iOS)
This is how you execute an apple script:
//Begin of the script
NSAppleScript *script = [[NSAppleScript alloc]
initWithSource:#"Tell application \"Terminal\" \n\
do shell script \" some script here \"\n\
end tell"];
NSDictionary *errors = nil;
NSAppleEventDescriptor *result = [script executeAndReturnError:&errors];
NSLog(#"result: %#", result);
NSLog(#"errors: %#", errors);
if(errors==NULL){
NSLog(#"Succeeded");
}
else{
NSLog(#"Failed");
}
//End of the script

The quick and dirty way to do this is to shell out to either bless --info or systemsetup liststartupdisks commands. You can specify that you want the output in plist format to make it easier to parse as well.
As far as executing those commands the typical NSTask should work. You could also use system() I suppose, but it isn't really standard practice on OS X as NSTask has many advantages over it.
A purely code way to do this would be to get the list of disks and then look at each them for the known files that make OS X bootable. Things like the boot.efi file in /System/Library/CoreServices, the mach kernel file, and the contents of /System/Library/CoreServices/SystemVersion.plist.

Related

system() call in cocoa app

In my cocoa app I have to call system() function to launch an external app. The command I use is:
system("./main &");
If I run the app from Xcode, it works fine, because I know the folder where to put main.
If I create an archive, and distribute my .app application, system() can't find "main". Where I have to put it?? Or otherwise, how can I run an app using "./" when I'm not in the folder the application is?
EDIT: Maybe I solved using NSTask, but how can I run "main" in background? Now it opens in a new terminal window.
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/Applications/Multibo/main"];
[task setArguments:[NSArray arrayWithObjects:[NSString stringWithFormat:#"./main &"], nil]];
[task launch];
Thanks
Try appending the full path before the executable's name and use it as an argument to system. Note that system is implementation defined -- its behavior is not guranteed to be the same across systems and its usage is thus not recommended. You should probably look for a suitable alternative such as NSWorkspace.
While dirkgently's answer is directly correct, the real answer is more complex.
First, NSTask is not a generic command line invoker. That is why adding & doesn't do what you expect. In fact, all tasks invoked via NSTask are effectively background.
But you really don't want to use NSTask. You should really be using an XPC service. Now, if your goal is something that runs even after your program exits, you should be looking into LaunchServices.

How to run Objective-C binary on a web server?

Alright, I have a rather odd question here. I feel much more comfortable writing code in Objective-C over any other language. I recently had to do some server-side programming, which required me to learn PHP. It works, yeah, but for fun I want to achieve the same thing through Objective-C. So, I created a binary using Xcode's Foundation preset. Here's most of the binary:
#import <Foundation/Foundation.h>
#import "JSONKit.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *theURL = [NSString stringWithFormat:#"http://blahblahblah.com/blah"];
NSError *err = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] init] autorelease];
NSURL*URL = [NSURL URLWithString:theURL];
[request setURL:URL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:30];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSDictionary *someData = [data objectFromJSONData];
NSString *someString = [[someData objectForKey:#"foo"]objectForKey:#"bar"];
//do something
[pool drain];
return 0;
}
Quite basic code. It simply downloads some stuff from my server and I parse the JSON result and get a string that I want to use. So, my question is - how can I run this on my Linux-based server? I know it's possible, maybe using GNUStep (or cocotron?), which I don't know how to use. Anyone have ideas?
Well,
I suggest the same thing as the #lacqui.. Use CGI to run your program.. and here's the steps ..
(Side note: using CGI is deprecated as it starts a process each time a request is coming to the server (modern servers/web containers initiate a new thread (vs process).)
So, let's Start:
The input at hand is a program written in Objectiv-c
The output is a CGI script(program or whatever they name it) that
will run inside some http server.
First, let me ask you, What's the target platform to deploy your application?
If target deployment platform is a Mac then you will have to get the binary out of xcode ( I think it would be in a .dmg format) and find some where how to run a .dmg as a CGI program inside a web server ( I am not sure if apache runs under Mac or not)
But If it is Windows or Linux:
You will need to compile your application using GNUstep (I know nothing about portability from Xcode to GNUstep) You will need a GNUstep. Steps to install GNUstep either for Windows or Linux is trivial.
Once Installing GNUstep, you will have to compile your application again using it, refer to the same two links above to know how to compile your application.
The issue here is, AFAIK, GNUstep don't fully support Objc-2, so possibilities that the compilation will fail cause of usage of JSONKit.h is high. If your program compiles successfully, then you are almost done.
Suppose your program compiles, And you now have the binary program.. You will need to deploy it in some HTTP server that have CGI enabled. You can follow my blogpost here to know how to deploy a binary program written in C into some small http server called mini-httpd on Linux (it should apply to any binary program regardless of its source language).
What you want to look at is called the Common Gateway Interface. It is a protocol that states the way a web server will interact with subordinate processes.
What will happen is that, when a user browses to the URL that is mapped to your program, the server will start your program, and put the text of the request into STDIN. Your program will do whatever processing is required, then put the results (as well as some header information) into STDOUT.
What goes wrong when you try? You should be able to compile it with the GCC's Objective-C compiler. You should be able to run it.

How to find file types in objective c

I have done a lot of research on this and haven't found anything useful. I want am making a simple program in objective c for personal use that opens files and gives information about them. The only problem i have encountered is that i cannot find the file of a file i am opening. Without simply looking at the extension, is there a way to find the full file format of a file in objective c?
If possible, i would also like to be able to save that file in a different format. Information on this subject is also important for this application. Help will be greatly appreciated.
Mac OS X has type information attached to each file which specifies what the type of the file is supposed to be. This information is given by the application which last saved the file, so it is not necessarily correct. Also, new versions of OS X ignore this information and go entirely off of the file extension. However, the information is still stored and can be retrieved using NSFileManager's attributesOfItemAtPath:error: method.
As mentioned by quixoto above, OS X now maps extensions to UTIs. The UTI of a file can be retrieved using NSWorkspace, which can also tell you what the UTI means. This code will get the localized description of the file at /full/path/to/file:
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSString *description = [ws localizedDescriptionForType:[ws typeOfFile:#"/full/path/to/file" error:nil]];
The typeOfFile:error: method requires an absolute path.
Consider: what do you mean by "full file format"? What kinds of files and level of detail do you care about?
You can't really get "format" information from the file system like you want. Believe it or not, the file system has no idea what format files are in.
File systems traditionally store files as a stream of bytes with a name, a size, and some other attributes ("hidden", permissions, etc). That's all that it's responsible for, and it's the application's problem to read those bytes and interpret them to mean something useful.
The extension is the traditional hint to an application about what a file contains, but as you might guess, it's certainly not a verified guarantee.
Modern Mac OS X has Quick Look, which uses a system-wide framework that adds some smarts on top of this, with mappings between extensions and UTIs, which are a richer notion of file type. Docs are here. I don't think there's a way to query this system for the mappings between extensions and UTIs, but I'm not sure.
Loading a file of one format and saving in another is 100% dependent on the file types you're talking about, and you're going to have ask very specific questions about specific formats if you really care to accomplish this. (And that topic extends well beyond a couple built-in method calls in Cocoa.)
This information is now (since OS X 10.5) handled through UTIs.
You can get it like this:
NSURL *desktopURL = [[[NSFileManager defaultManager] URLsForDirectory: NSDesktopDirectory
inDomains: NSUserDomainMask] lastObject];
NSURL *workingdirURL = [desktopURL URLByAppendingPathComponent:#"WorkingDir" isDirectory:YES];
NSArray *docURLs = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:workingdirURL
includingPropertiesForKeys:#[NSURLTypeIdentifierKey] options:NSDirectoryEnumerationSkipsHiddenFiles
error: nil];
NSMutableArray *pdfURLs = [NSMutableArray array];
for (NSURL *docURL in docURLs) {
id resourceValue;
BOOL found = [docURL getResourceValue: &resourceValue
forKey: NSURLTypeIdentifierKey
error: nil];
if ( found && [resourceValue isEqual:#"com.adobe.pdf"]) {
[pdfURLs addObject: docURL];
}
}
You can see the docs for more information about the file properties that can be retrieved this way. There is quite a lot of information available through this method.

Discover the environment and relative path of the running application

While playing with RubyCocoa, I keep progressing with my idea for my application. Because my application will be going to use configuration files, I would like to know how I discover the relative path to store these inside my application structure (or if a better idea emerges, please elaborate also the "why").
Also good for me to know is to discover environment variables, such as operating system version, the amount of memory that is available and such. Hyperlinks would be awesome too.
Please notice I use RubyCocoa and thank you for your feedback, comments and answers!
To access inside the application bundle, you use NSBundle. See NSBundle reference. In Obj-C, you use +[NSBundle mainBundle] to get the main bundle of the app. Then you use -[NSBundle pathForResource:ofType:] to get the file. I don't know RubyCocoa syntax, but I assume you know how to translate to it :)
If by the configuration file you mean a user-configurable things, remember you can't write inside the app bundle at runtime. Instead one uses NSUserDefaults. See User Defaults Guide.
Here's some Cocoa code I use to write all the environment variables to the console. Again, I don't use RubyCocoa, so you'll have to translate:
NSProcessInfo *myProcessInfo = [NSProcessInfo processInfo];
NSDictionary *env = [myProcessInfo environment];
for (id key in env)
{
NSLog (#"key: %#, value: %#", key, [env objectForKey: key]);
}

Cocoa/ Objective-C Shell Command Line Execution

This is probably a stupid question, but how can I execute a shell command from my Cocoa app?
I have the command as a string "command", but can easily manipulate data as needed.
There is no need to get a returned output value.
NSTask is pretty easy to do this with. For a synchronous call, you can use something like this fragment:
NSString *path = #"/path/to/executable";
NSArray *args = [NSArray arrayWithObjects:..., nil];
[[NSTask launchedTaskWithLaunchPath:path arguments:args] waitUntilExit];
The -waitUntilExit call makes sure it finishes before proceeding. If the task can be asynchronous, you can remove that call and just let the NSTask do it's thing.
If you just want to run something and don't care about the output or return code (for example, you want to touch a file), you can just do
system("touch myfile.txt");
Easy as that.
NSTask
Using the NSTask class, your program can run another program as a subprocess and can monitor that program’s execution.