Getting Current Directory in Objective C - objective-c

I am trying to get current directory, but its giving me path of DEBUG folder, how i can get the path of current directory. I am using the following code.
NSFileManager *filemgr;
NSString *currentpath;
filemgr = [[NSFileManager alloc] init];
currentpath = [filemgr currentDirectoryPath];

currentDirectoryPath returns the current working directory of the program. If you launch it from Xcode in Debug mode, the current directory of the program is the Debug directory.

Developing further on that. The current working directory and launch directory may be different! Take this example, the app is launched from the home directory (~).
Library/Developer/Xcode/DerivedData/MyApp-ehwczslxjxsxiob/Build/Products/Debug/MyApp.app/Contents/MacOS/MyApp -param value
NSString *p1 = [[NSFileManager defaultManager] currentDirectoryPath];
// p1 = ~/Library/Containers/com.MyApp.beta/Data
NSString *p2 = [[NSProcessInfo processInfo] environment][#"PWD"];
// p2 = ~
Depending on the situation you might want one or the other. In my case I want to provide a CLI which takes path arguments that may be relative to the current working directory in the shell.

When getting paths for a service loaded via launchd, the paths can be very different.
NSLog(#"argv: %s", argv[0]);
NSLog(#"NSProcessInfo: %#", NSProcessInfo.processInfo.arguments[0]);
NSLog(#"currentDirectoryPath: %#", [[NSFileManager defaultManager] currentDirectoryPath]);
NSLog(#"PWD: %#", [[NSProcessInfo processInfo] environment][#"PWD"]);
Output:
argv: /Users/dev/.ioi/default-runtime-manager/default-runtime-manager
NSProcessInfo: /Users/dev/.ioi/default-runtime-manager/default-runtime-manager
currentDirectoryPath: /Users/dev/Library/Application Support/IOI/default-runtime-manager
PWD: (null)
NSProcessInfo gives the location where the executable was found.
currentDirectoryPath returns the WorkingDirectory specified in the launchd plist.
The answer to getting the executable path was found here: StackOverflow: NSProcessInfo. The other paths were from: #lupdidup

Related

My OSX app is sandboxed and I am not able to read data from file by specifying the absolute path

I am completely new to objective C and currently I am trying to advance the functionality of an already existing project.
There is a finder extension in the project which on getting clicked performs an action inside (IBAction) Share(id) sender.
Inside this action , I want to read a file from a particular location (the file contains the port number) and using that port I want to connect to the server.
But what I found was when I click on this extension , nothing happens because it tries to go and read data from the file and is not able to read anything.
I tried to debug this by printing out whatever it has read to some other file but all it printed was blank confirming that it is not able to read the data. Below is my code trying to read the port from a temporary location :
- (IBAction)privateShareAction:(id)sender {
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: #"/var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties" ] == YES)
{
//create file handle
NSFileHandle *file;
file = [NSFileHandle fileHandleForReadingAtPath:#"/var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties"];
//read data into file in NSData format
NSData *filedata;
filedata = [file readDataToEndOfFile];
NSLog(#"fileDATA = %#", filedata);
//convert NSData to NSString
NSString *string;
string = [[NSString alloc] initWithData:filedata encoding:NSASCIIStringEncoding];
NSMutableString *directoryPath1 = [NSMutableString stringWithString: #"share1>"];
[directoryPath1 appendString: string];
NSData *dataToWrite3 = [directoryPath1 dataUsingEncoding: NSUTF8StringEncoding];
NSFileHandle* outputFile = [NSFileHandle fileHandleForWritingAtPath:#"/Users/yp/Downloads/a.txt"];
[outputFile seekToEndOfFile];
[outputFile writeData:dataToWrite3];
//convert from string to array
NSArray *lines = [string componentsSeparatedByString:#"="];
NSLog(#"arrau = %#", lines);
//take one of the string and store it in sword
NSString *sword = [lines objectAtIndex:1];
NSLog(#"port : %#", sword);
int port1=[sword intValue];
Communicator *c = [[Communicator alloc ]init];
c.host=#"http:127.0.0.1";
c.port=port1;
[c setup];
}
else
{
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:#"Error"];
[alert setInformativeText:#"You are not logged in.Kindly login to start performing the operations"];
[alert setAlertStyle:NSWarningAlertStyle];
[alert runModal];
}
}
The above code, on the action performed first tries to check if the file is present at the /var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties location or not.
This works perfectly fine , If the file is present , it shows a popup alert (which happens).
But if the file is present , it goes inside the if condition and tries to read the file where it fails .It always prints a blank string showing that nothing is being read.
So then I went and checked the entitlements in App Sandbox.
I tried to add an entitlement named com.apple.security.temporary-exception.files.absolute-path.read-only with a string value set to /var/folders/y3/jv117_75505fnk8htdrs0qm40000gr/T/com.aprivacy.xmlCorePort.properties so that it gets the permission to read the file from this location but still it doesn't solve my problem.
Could anyone please suggest how to get this file reading permission accessible in my app because the same code works completely fine in a newly created test project.
Following steps : Original client app running -login with user name and password Once logged in -it writes the port in a file At the same time ,once you are logged in with your application , if now you right click on any file in your system you will see certain extra extensions like share ,grant access etc. (This is because a finder project used to add extensions is merged with the original client) Now when I click on say share (on right clicking a file) , I want an action to be performed.The logic for action is written in (IBAction)Share (id) sender method This app used to add extensions is sandboxed because of which the permissions are restricted. So while I clicked on share , my logic was to read that file ,get the port and then connect to server using that port. I want to do everything inside action but I am unable to do so . It is not able to find the file data from /var/folder/y3/jv117_755fdlvfldsvgr/T/com.aprivacy.xmlcorePort.properties
Sandboxed apps (all in iOS) are only allowed access to specific directories. Use NSSearchPathForDirectoriesInDomainsto obtain paths to available directories.
Ex:
Objective-C:
NSArray *documentDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSError *error;
BOOL status = [string writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (status == NSError) {
NSLog(#"error: %#", error)
}
Swift:
let filePath = "path/file.txt";
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as! String
let path = documentDirectoryPath + filePath
Note: Sandboxed paths is not consistent across clean builds.
Don't use absolute paths in sandboxed applications.
In OS X there is the NSTemporaryDirectory() function to have access to the temporary directory for this specific application in the container. Entitlements are not needed.
From the documentation
Some path-finding APIs (above the POSIX layer) refer to app-specific
locations outside of the user’s home directory. In a sandboxed app,
for example, the NSTemporaryDirectory function provides a path to a
directory that is outside of the user’s home directory but specific to
your app and within your sandbox; you have unrestricted read/write
access to it for the current user. The behavior of these path-finding
APIs is suitably adjusted for App Sandbox and no code change is
needed.
Source: App Sandbox in Depth

Program directory in Objective-C (OSX)

I'm developing an OSX-application and in it, I'd like to know what the current directory is (i.e. the directory which holds .app-file).
At the moment, I'm using the following code:
NSString *dir=[[NSFileManager defaultManager] currentDirectoryPath];
[[NSAlert alertWithMessageText:#"dir"
defaultButton:#"OK"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:dir] runModal];
When running from Xcode (Run-button), this gives me the debug directory (which is what I'm looking for), but when double-clicking the app in Finder (so, in the debug directory), it's giving me / which puzzles me.
Why does this happen and how can I get the current directory reliably?
That is the bundle folder:
NSString *appPath = [[NSBundle mainBundle] bundlePath];
(reference).
When programming in Apple Swift you will get the application path with:
let pathtoapplication: String = NSBundle.mainBundle().bundlePath

LSCopyApplicationURLsForURL always returns null

When I try to log all available editors on my system for my temporary file (which is "toString" in this code) it always returns null, although I have many applications installed on my system.
NSArray *appUrls = (NSArray*)LSCopyApplicationURLsForURL((CFURLRef)[NSURL URLWithString:toString], kLSRolesViewer | kLSRolesEditor);
toString is containing the following file path:
/var/folders/pl/tcc5k3fd6tj2__9dprg9dm1m0000gp/T/tempFile
What should be the problem here?
[NSURL URLWithString:toString]
expects a complete URL string including scheme, such as "file://var/folders/...".
Use
[NSURL fileURLWithPath:toString]
instead to get a file URL with the specified path.
Another problem could be that your file name does not have any file extension (e.g. ".txt"), because Launch Services uses the extension (or file type/creator) to find a suitable application.
I was struggling with the this and I wanted to get all Bundles that could open a determined path/file extension.
If you have a file extension, you can get all bundles that can edit it by the following:
//All Bundle Ids
NSString *pathExtension = #"docx";
CFArrayRef utisRef = UTTypeCreateAllIdentifiersForTag(kUTTagClassFilenameExtension,(__bridge CFStringRef) pathExtension,nil);
NSLog( #"UTI: utisRef %#", utisRef);
NSArray *utis = CFBridgingRelease(utisRef);
NSMutableSet *mutableSet = [[NSMutableSet alloc] init];
for (NSString *uti in utis) {
CFArrayRef bundleIDsRef = LSCopyAllRoleHandlersForContentType((__bridge CFStringRef) uti,kLSRolesEditor);
[mutableSet addObjectsFromArray:CFBridgingRelease(bundleIDsRef)];
}
NSLog( #"bundleIDs: %#", mutableSet);
If you have a path of file and you want to get all apps location that can edit it, you can use the following:
//Location of apps
NSString *str = #"/Users/ricardoanjos/Library/Developer/Xcode/DerivedData/EgnyteDrive-hforbniifiojczefbnwanzxakvlr/Build/Products/Debug/1.pdf";
NSURL* url = [[NSURL alloc] initFileURLWithPath:str];
CFURLRef urlRef = (__bridge CFURLRef)url;
CFArrayRef appUrlsRef = LSCopyApplicationURLsForURL(urlRef, kLSRolesEditor);
NSArray *appUrls = CFBridgingRelease(appUrlsRef);
NSLog(#"appUrls: %#", appUrls);
I hope it will help.

NSFileManager finds files inside a folder only when it's running under a debugger

When I run the following code under the Xcode debugger it successfully finds the package with .app extension, but when I run it standalone "file" object is nil. In fact when I did NSLogs folderEnum was also nil. Note that folderPath points to a folder that is in the same directory as the the program executable.
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator *folderEnum = [localFileManager enumeratorAtPath:folderPath];
NSString *file;
while (file = [folderEnum nextObject]) {
if ([[file pathExtension] isEqualToString: #"app"]) {
break;
}
}
Any ideas? Something to do with the Mac system file permissions?
Edit
I should have probably mentioned that folderPath was actually a relative path and not an absolute one. So I changed folderPath to be relative to [[NSBundle mainBundle] bundlePath] path and it works now. But if anyone can shed some light why relative path doesn't work that be great.
Does changing the first line to:
NSFileManager *localFileManager = [NSFileManager defaultManager];
make any difference? Are you just trying to get the path for your application? (There are easier ways)

NSFileManager works when built in Xcode as release, but not when ran as standalone OS X Cocoa app

I have the following function written to randomly pick a file from a directory. It works totally fine when I build the project in Xcode for release with the application that automatically opens. However, if I open the application from finder, pressing the button that triggers this function will cause my program to freeze then crash. The only thing I could think of was changing the argument to contentsOfDirectoryAtPath: to not have the ./, but either version has the same exact issue.
Looking at Console tells me that my program exited abnormally with a Floating Point Exception, but I have no idea what's causing it. Is there something jumping out to you guys that I'm not seeing? I only started learning/using objective-C and cocoa about a week ago, so this is all fairly new to me.
Thanks for taking a look at this...
- (NSMutableString*)setFilePathRandom{
NSArray* files;
NSFileManager* fileManager;
fileManager = [[NSFileManager alloc] init];
files = [fileManager contentsOfDirectoryAtPath:#"./Random Trippy Pics" error:NULL];
NSString* directoryPath = (NSMutableString*)[fileManager currentDirectoryPath];
NSString* fileName;
do{
fileName = [files objectAtIndex:(arc4random()%[files count])];
}while([fileName isEqualToString:#".DS_Store"]);
filePath = [NSString stringWithFormat:#"%#/Random Trippy Pics/%#",directoryPath,fileName];
[fileManager release];
return filePath;
}
When an OS X application is run from Xcode, its current directory is the path to the build folder. When run "normally", the current directory is /. So your program is looking for a directory at /Random Trippy Pics, which almost certainly doesn't exist. Where is that directory normally?
Edit:
You could get the directory in which the application is currently stored with this bit of code:
NSString *currentStoragePath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
However, if the Random Trippy Pics directory is required by the application, you should store it in a known location -- preferably the application's Resource directory. Then you can get the contents with:
NSArray *files = [[NSBundle mainBundle] pathsForResourceOfType:nil inDirectory:#"Random Trippy Pics"];