find_path*(): Improve B_FIND_PATH_IMAGE_PATH handling

* get_file_attribute(): Use O_NOTRAVERSE, so we correctly read the
  attribute from symlinks.
* internal_path_for_path(): Shuffle things around a bit: The dependency
  is resolved before handling B_FIND_PATH_PACKAGE_PATH, now. This adds
  support for getting the package file for a dependency. The dependency
  was ignored in this case before.
* Use kSystemPackageLinksDirectory instead of hard-coding "/packages".
This commit is contained in:
Ingo Weinhold
2013-11-21 13:29:20 +01:00
parent d0126238fd
commit 23c521cf5e
+43 -49
View File
@@ -385,7 +385,8 @@ static status_t
get_file_attribute(const char* path, const char* attribute, char* nameBuffer, get_file_attribute(const char* path, const char* attribute, char* nameBuffer,
size_t bufferSize) size_t bufferSize)
{ {
int fd = fs_open_attr(path, attribute, B_STRING_TYPE, O_RDONLY); int fd = fs_open_attr(path, attribute, B_STRING_TYPE,
O_RDONLY | O_NOTRAVERSE);
if (fd < 0) if (fd < 0)
return errno; return errno;
@@ -489,47 +490,13 @@ internal_path_for_path(char* referencePath, size_t referencePathSize,
if (strcmp(architecture, __get_primary_architecture()) == 0) if (strcmp(architecture, __get_primary_architecture()) == 0)
architecture = NULL; architecture = NULL;
// normalize
status_t error = normalize_path(referencePath, referencePath,
referencePathSize);
if (error != B_OK)
return error;
// handle B_FIND_PATH_IMAGE_PATH
if (baseDirectory == B_FIND_PATH_IMAGE_PATH)
return copy_path(referencePath, pathBuffer, bufferSize);
// get the installation location
InstallationLocations* installationLocations = InstallationLocations::Get();
MethodDeleter<InstallationLocations> installationLocationsDeleter(
installationLocations, &InstallationLocations::Put);
size_t installationLocationIndex;
const char* installationLocation = installationLocations->LocationFor(
referencePath, installationLocationIndex);
if (installationLocation == NULL)
return B_ENTRY_NOT_FOUND;
// Handle B_FIND_PATH_PACKAGE_PATH: get the package file name and
// simply adjust our arguments to look the package file up in the packages
// directory.
char packageName[B_FILE_NAME_LENGTH];
if (baseDirectory == B_FIND_PATH_PACKAGE_PATH) {
error = get_file_attribute(referencePath, "SYS:PACKAGE_FILE",
packageName, sizeof(packageName));
if (error != B_OK)
return error;
dependency = NULL;
subPath = packageName;
baseDirectory = B_FIND_PATH_PACKAGES_DIRECTORY;
flags = B_FIND_PATH_EXISTING_ONLY;
}
// resolve dependency // resolve dependency
char packageName[B_FILE_NAME_LENGTH];
// Temporarily used here, permanently used below where
// B_FIND_PATH_PACKAGE_PATH is handled.
if (dependency != NULL) { if (dependency != NULL) {
// get the versioned package name // get the versioned package name
error = get_file_attribute(referencePath, "SYS:PACKAGE", status_t error = get_file_attribute(referencePath, "SYS:PACKAGE",
packageName, sizeof(packageName)); packageName, sizeof(packageName));
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -541,25 +508,52 @@ internal_path_for_path(char* referencePath, size_t referencePathSize,
if (error != B_OK) if (error != B_OK)
return error; return error;
// Compute the path of the dependency symlink and normalize it. This // Compute the path of the dependency symlink. This will yield the
// should yield the installation location path. // installation location path when normalized.
if (snprintf(referencePath, referencePathSize, "/packages/%s/%s", if (snprintf(referencePath, referencePathSize,
packageName, normalizedDependency) kSystemPackageLinksDirectory "/%s/%s", packageName,
normalizedDependency)
>= (ssize_t)referencePathSize) { >= (ssize_t)referencePathSize) {
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
} }
}
error = normalize_path(referencePath, referencePath, referencePathSize); // handle B_FIND_PATH_IMAGE_PATH
if (baseDirectory == B_FIND_PATH_IMAGE_PATH)
return copy_path(referencePath, pathBuffer, bufferSize);
// Handle B_FIND_PATH_PACKAGE_PATH: get the package file name and
// simply adjust our arguments to look the package file up in the packages
// directory.
if (baseDirectory == B_FIND_PATH_PACKAGE_PATH) {
status_t error = get_file_attribute(referencePath, "SYS:PACKAGE_FILE",
packageName, sizeof(packageName));
if (error != B_OK) if (error != B_OK)
return error; return error;
// get the installation location dependency = NULL;
installationLocation = installationLocations->LocationFor(referencePath, subPath = packageName;
installationLocationIndex); baseDirectory = B_FIND_PATH_PACKAGES_DIRECTORY;
if (installationLocation == NULL) flags = B_FIND_PATH_EXISTING_ONLY;
return B_ENTRY_NOT_FOUND;
} }
// normalize
status_t error = normalize_path(referencePath, referencePath,
referencePathSize);
if (error != B_OK)
return error;
// get the installation location
InstallationLocations* installationLocations = InstallationLocations::Get();
MethodDeleter<InstallationLocations> installationLocationsDeleter(
installationLocations, &InstallationLocations::Put);
size_t installationLocationIndex;
const char* installationLocation = installationLocations->LocationFor(
referencePath, installationLocationIndex);
if (installationLocation == NULL)
return B_ENTRY_NOT_FOUND;
// get base dir and process the path // get base dir and process the path
const char* relativePath = get_relative_directory_path( const char* relativePath = get_relative_directory_path(
installationLocationIndex, baseDirectory); installationLocationIndex, baseDirectory);