Search code examples
c++macosg++mkdir

mkdir() returns -1 when launched through Finder


I have a simple program that makes a directory when it is executed:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(){
    if(int a = mkdir("abc",0700)){
        std::cout << "Failed to create: " << a << std::endl;
    }
    else{
        std::cout << "Created." << std::endl;
    }
}

It behaves differently for two different use cases:

  • Running the compiled binary through Terminal
    • Output: Created.
  • Launching this program via Finder with double click.
    • Output: Failed to create: -1

How do I make this so that launching this program via Finder creates the folder abc without using Cocoa framework (compiles with g++ only)?


Solution

  • Thanks to Wooble for pointing it out in the comment section that the problem is due to the working directory. When I launched it through Finder, the current working directory was my home directory.

    Below is how I address the problem:

    #include <iostream>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <libproc.h>
    
    int main(int argc, char** argv){
        // Gets and prints out the current directory
        char cwd[1024];
        getcwd(cwd, sizeof(cwd));
        std::cout << "Current Working Directory: " << cwd << std::endl;
        // Above is not necessary
    
        // Changes working directory to directory that contains executable
        char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
        if(proc_pidpath (getpid(), pathbuf, sizeof(pathbuf)) > 0){ // Gets the executable path
            std::string s(pathbuf);
            s = s.substr(0,s.find_last_of('/')); // Removes executable name from path
            std::cout << "Executable Path: " << s << std::endl;
            chdir(s.c_str()); // Changes working directory
        }
    
        if(int a = mkdir("abc",0700)){
            std::cout << "Failed to create: " << a << std::endl;
        }
        else{
            std::cout << "Created." << std::endl;
        }
    }