[haiku-development] RFC: find_directory() API extension

  • From: Ingo Weinhold <ingo_weinhold@xxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Fri, 01 Nov 2013 03:00:45 +0100

Howdy,

I've thought a bit about what additional find_directory() like functionality we need and came up with a first draft for new API:

/* find_path[s]() flags */
enum {
        B_FIND_PATH_CREATE_DIRECTORY                    = 0x0001,
        B_FIND_PATH_CREATE_PARENT_DIRECTORY             = 0x0002,
        B_FIND_PATH_EXISTING_ONLY                       = 0x0004,
};

typedef enum path_base_directory {
        B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY,
        B_FIND_PATH_ADD_ONS_DIRECTORY,
        B_FIND_PATH_APPS_DIRECTORY,
        B_FIND_PATH_BIN_DIRECTORY,
        B_FIND_PATH_BOOT_DIRECTORY,
        B_FIND_PATH_CACHE_DIRECTORY,
        B_FIND_PATH_DATA_DIRECTORY,
        B_FIND_PATH_DEVELOP_DIRECTORY,
        B_FIND_PATH_DEVELOP_LIB_DIRECTORY,
        B_FIND_PATH_DOCUMENTATION_DIRECTORY,
        B_FIND_PATH_ETC_DIRECTORY,
        B_FIND_PATH_FONTS_DIRECTORY,
        B_FIND_PATH_HEADERS_DIRECTORY,
        B_FIND_PATH_LIB_DIRECTORY,
        B_FIND_PATH_PACKAGES_DIRECTORY,
        B_FIND_PATH_PREFERENCES_DIRECTORY,
        B_FIND_PATH_SETTINGS_DIRECTORY,
        B_FIND_PATH_SOUNDS_DIRECTORY,
        B_FIND_PATH_SPOOL_DIRECTORY,
        B_FIND_PATH_TRANSLATORS_DIRECTORY,
        B_FIND_PATH_VAR_DIRECTORY,

        /* find_path() only */
        B_FIND_PATH_IMAGE_PATH                  = 1000,
        B_FIND_PATH_IMAGE_PACKAGE_PATH,
} path_base_directory;

status_t find_path(const void* codePointer, const char* dependency,
        path_base_directory baseDirectory, const char* subPath,
        uint32 flags, char* pathBuffer, size_t bufferSize);

status_t find_paths(path_base_directory baseDirectory,
        const char* subPath, uint32 flags, char*** paths,
        size_t* pathCount);

find_paths() is similar to the existing find_directory(), but instead of one path it returns an array of paths for the specified kind of directory. E.g. one can pass B_FIND_PATH_APPS_DIRECTORY to get back all apps directories, i.e. {"/boot/home/config/non-packaged/apps", "/boot/home/config/apps", "/boot/system/non-packaged/apps", "/boot/system/apps"}. So this function solves the issues that arises from introducing new or removing existing installation locations (like /boot/common).

The value of the (optional) subPath argument is appended to the base directory path identified by baseDirectory, thus saving the caller a common step. The B_FIND_PATH_CREATE_* flags are probably not that interesting for this function -- they create a directory at the resulting paths respectively the parent paths. B_FIND_PATH_EXISTING_ONLY filters the result list to include only the existing paths. The returned path array must be free()d by the caller.

The purpose of find_path() is mainly for packaged code to find other packaged files, respectively the right writable directories to use. It also works for software properly installed in one of the non-packaged directories.

codePointer refers to an address in the caller's code, thus identifying the executable, library, or add-on for which the call is performed. If NULL is passed, the executable is implied. Based off its installation location baseDirectory is applied and subPath appended. So e.g. for a program foo to get its data file the call could look like:

        char path[B_PATH_NAME_LENGTH];
        find_path(NULL, NULL, B_FIND_PATH_DATA_DIRECTORY,
                "foo/main-data", 0, path, sizeof(path));

When the program is installed in "/boot/system", "/boot/system/data/foo/main-data" is returned.

B_FIND_PATH_EXISTING_ONLY would cause the function to fail, if the path doesn't exist. The B_FIND_PATH_CREATE_* flags work as mentioned above.

The special path constants B_FIND_PATH_IMAGE_PATH and B_FIND_PATH_IMAGE_PACKAGE_PATH can be used to get the path of the executable/library/add-on respectively that of the package it lives in.

The dependency parameter can be used to resolve paths to dependencies declared by the package. E.g. a program wanting to call the perl interpreter (assuming its package declares the requirement "cmd:perl") could get its path via:

        char path[B_PATH_NAME_LENGTH];
        find_path(NULL, "cmd:perl", B_FIND_PATH_BIN_DIRECTORY,
                "perl", 0, path, sizeof(path));

Probably not that interesting for programs that are in the path anyway, but maybe for accessing files of a data package.

Trivial C++ versions of the two functions could be added, differing only in the return parameter -- a BPath*, respectively a BStringList*.

A respective findpath command, similar to finddir, could be added as well, providing the functionality to the shell.

Please comment.

CU, Ingo

Other related posts: