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