Пример #1
0
status_t
__find_paths_etc(const char* architecture, path_base_directory baseDirectory,
	const char* subPath, uint32 flags, char*** _paths, size_t* _pathCount)
{
	if (_paths == NULL || _pathCount == NULL)
		return B_BAD_VALUE;

	// Analyze architecture. If NULL, use the caller's architecture. If the
	// effective architecture is the primary one, set architecture to NULL to
	// indicate that we don't need to insert an architecture subdirectory
	// component.
	if (architecture == NULL)
		architecture = __get_architecture();
	if (strcmp(architecture, __get_primary_architecture()) == 0)
		architecture = NULL;
	size_t architectureSize = architecture != NULL
		? strlen(architecture) + 1 : 0;

	size_t subPathLength = subPath != NULL ? strlen(subPath) + 1 : 0;

	// get the installation locations
	InstallationLocations* installationLocations = InstallationLocations::Get();
	MethodDeleter<InstallationLocations> installationLocationsDeleter(
		installationLocations, &InstallationLocations::Put);

	// Get the relative paths and compute the total size to allocate.
	const char* relativePaths[InstallationLocations::kCount];
	size_t totalSize = 0;

	for (size_t i = 0; i < InstallationLocations::kCount; i++) {
		if (((flags & B_FIND_PATHS_USER_ONLY) != 0
				&& !installationLocations->IsUserIndex(i))
			|| ((flags & B_FIND_PATHS_SYSTEM_ONLY) != 0
				&& !installationLocations->IsSystemIndex(i)))
			continue;

		relativePaths[i] = get_relative_directory_path(i, baseDirectory);
		if (relativePaths[i] == NULL)
			return B_BAD_VALUE;

		totalSize += strlen(installationLocations->At(i))
			+ strlen(relativePaths[i]) + subPathLength + 1;
		if (strchr(relativePaths[i], '%') != NULL)
			totalSize += architectureSize - 1;
	}

	// allocate storage
	char** paths = (char**)malloc(sizeof(char*) * InstallationLocations::kCount
		+ totalSize);
	if (paths == NULL)
		return B_NO_MEMORY;
	MemoryDeleter pathsDeleter(paths);

	// construct and process the paths
	size_t count = 0;
	char* pathBuffer = (char*)(paths + InstallationLocations::kCount);
	const char* pathBufferEnd = pathBuffer + totalSize;
	for (size_t i = 0; i < InstallationLocations::kCount; i++) {
		if (((flags & B_FIND_PATHS_USER_ONLY) != 0
				&& !installationLocations->IsUserIndex(i))
			|| ((flags & B_FIND_PATHS_SYSTEM_ONLY) != 0
				&& !installationLocations->IsSystemIndex(i)))
			continue;

		ssize_t pathSize = process_path(installationLocations->At(i),
			architecture, relativePaths[i], subPath, flags, pathBuffer,
			pathBufferEnd - pathBuffer);
		if (pathSize < 0)
			return pathSize;
		if (pathSize > 0) {
			paths[count++] = pathBuffer;
			pathBuffer += pathSize;
		}
	}

	if (count == 0)
		return B_ENTRY_NOT_FOUND;

	*_paths = paths;
	*_pathCount = count;
	pathsDeleter.Detach();

	return B_OK;
}
Пример #2
0
status_t
__find_directory(directory_which which, dev_t device, bool createIt,
	char *returnedPath, int32 _pathLength)
{
	if (_pathLength <= 0)
		return E2BIG;
	size_t pathLength = _pathLength;

	status_t err = B_OK;
	dev_t bootDevice = -1;
	struct fs_info fsInfo;
	struct stat st;
	const char *templatePath = NULL;

	/* as with the R5 version, no on-stack buffer */
	char *buffer = (char*)malloc(pathLength);
	if (buffer == NULL)
		return B_NO_MEMORY;
	MemoryDeleter bufferDeleter(buffer);

	memset(buffer, 0, pathLength);

	/* fiddle with non-boot volume for items that need it */
	switch (which) {
		case B_DESKTOP_DIRECTORY:
		case B_TRASH_DIRECTORY:
			bootDevice = dev_for_path("/boot");
			if (device <= 0)
				device = bootDevice;
			if (fs_stat_dev(device, &fsInfo) != B_OK)
				return ENODEV;
			if (device != bootDevice) {
#ifdef _KERNEL_MODE
				err = _user_entry_ref_to_path(device, fsInfo.root, /*"."*/
					NULL, buffer, pathLength);
#else
				err = _kern_entry_ref_to_path(device, fsInfo.root, /*"."*/
					NULL, buffer, pathLength);
#endif
				if (err != B_OK)
					return err;
			} else {
				/* use the user id to find the home folder */
				/* done later */
				strlcat(buffer, "/boot", pathLength);
			}
			break;
		case B_PACKAGE_LINKS_DIRECTORY:
			// this is a directory living in rootfs
			break;
		default:
			strlcat(buffer, "/boot", pathLength);
			break;
	}

	switch ((int)which) {
		/* Per volume directories */
		case B_DESKTOP_DIRECTORY:
			if (device == bootDevice || !strcmp(fsInfo.fsh_name, "bfs"))
				templatePath = "$h/Desktop";
			break;
		case B_TRASH_DIRECTORY:
			// TODO: eventually put that into the file system API?
			if (device == bootDevice || !strcmp(fsInfo.fsh_name, "bfs"))
				templatePath = "trash"; // TODO: add suffix for current user
			else if (!strcmp(fsInfo.fsh_name, "fat"))
				templatePath = "RECYCLED/_BEOS_";
			break;

		/* Haiku system directories */
		case B_SYSTEM_DIRECTORY:
		case B_BEOS_SYSTEM_DIRECTORY:
		case B_SYSTEM_ADDONS_DIRECTORY:
		case B_SYSTEM_BOOT_DIRECTORY:
		case B_SYSTEM_FONTS_DIRECTORY:
		case B_SYSTEM_LIB_DIRECTORY:
		case B_SYSTEM_SERVERS_DIRECTORY:
		case B_SYSTEM_APPS_DIRECTORY:
		case B_SYSTEM_BIN_DIRECTORY:
		case B_BEOS_ETC_DIRECTORY:
		case B_SYSTEM_DOCUMENTATION_DIRECTORY:
		case B_SYSTEM_PREFERENCES_DIRECTORY:
		case B_SYSTEM_TRANSLATORS_DIRECTORY:
		case B_SYSTEM_MEDIA_NODES_DIRECTORY:
		case B_SYSTEM_SOUNDS_DIRECTORY:
		case B_SYSTEM_DATA_DIRECTORY:
		case B_SYSTEM_DEVELOP_DIRECTORY:
		case B_SYSTEM_PACKAGES_DIRECTORY:
		case B_SYSTEM_HEADERS_DIRECTORY:
			templatePath = kSystemDirectories[which - B_SYSTEM_DIRECTORY];
			break;

		/* Obsolete common directories and writable system directories */
		case B_COMMON_DIRECTORY:
		case B_COMMON_SYSTEM_DIRECTORY:
		case B_COMMON_ADDONS_DIRECTORY:
		case B_COMMON_BOOT_DIRECTORY:
		case B_COMMON_FONTS_DIRECTORY:
		case B_COMMON_LIB_DIRECTORY:
		case B_COMMON_SERVERS_DIRECTORY:
		case B_COMMON_BIN_DIRECTORY:
		case B_SYSTEM_ETC_DIRECTORY:
		case B_COMMON_DOCUMENTATION_DIRECTORY:
		case B_SYSTEM_SETTINGS_DIRECTORY:
		case B_COMMON_DEVELOP_DIRECTORY:
		case B_SYSTEM_LOG_DIRECTORY:
		case B_SYSTEM_SPOOL_DIRECTORY:
		case B_SYSTEM_TEMP_DIRECTORY:
		case B_SYSTEM_VAR_DIRECTORY:
		case B_COMMON_TRANSLATORS_DIRECTORY:
		case B_COMMON_MEDIA_NODES_DIRECTORY:
		case B_COMMON_SOUNDS_DIRECTORY:
		case B_COMMON_DATA_DIRECTORY:
		case B_SYSTEM_CACHE_DIRECTORY:
		case B_COMMON_PACKAGES_DIRECTORY:
		case B_COMMON_HEADERS_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_BIN_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_DATA_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_LIB_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_HEADERS_DIRECTORY:
		case B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY:
			templatePath = kCommonDirectories[which - B_COMMON_DIRECTORY];
			break;

		/* User directories */
		case B_USER_DIRECTORY:
		case B_USER_CONFIG_DIRECTORY:
		case B_USER_ADDONS_DIRECTORY:
		case B_USER_BOOT_DIRECTORY:
		case B_USER_FONTS_DIRECTORY:
		case B_USER_LIB_DIRECTORY:
		case B_USER_SETTINGS_DIRECTORY:
		case B_USER_DESKBAR_DIRECTORY:
		case B_USER_PRINTERS_DIRECTORY:
		case B_USER_TRANSLATORS_DIRECTORY:
		case B_USER_MEDIA_NODES_DIRECTORY:
		case B_USER_SOUNDS_DIRECTORY:
		case B_USER_DATA_DIRECTORY:
		case B_USER_CACHE_DIRECTORY:
		case B_USER_PACKAGES_DIRECTORY:
		case B_USER_HEADERS_DIRECTORY:
		case B_USER_DEVELOP_DIRECTORY:
		case B_USER_DOCUMENTATION_DIRECTORY:
		case B_USER_NONPACKAGED_DIRECTORY:
		case B_USER_NONPACKAGED_ADDONS_DIRECTORY:
		case B_USER_NONPACKAGED_TRANSLATORS_DIRECTORY:
		case B_USER_NONPACKAGED_MEDIA_NODES_DIRECTORY:
		case B_USER_NONPACKAGED_BIN_DIRECTORY:
		case B_USER_NONPACKAGED_DATA_DIRECTORY:
		case B_USER_NONPACKAGED_FONTS_DIRECTORY:
		case B_USER_NONPACKAGED_SOUNDS_DIRECTORY:
		case B_USER_NONPACKAGED_DOCUMENTATION_DIRECTORY:
		case B_USER_NONPACKAGED_LIB_DIRECTORY:
		case B_USER_NONPACKAGED_HEADERS_DIRECTORY:
		case B_USER_NONPACKAGED_DEVELOP_DIRECTORY:
		case B_USER_SERVERS_DIRECTORY:
		case B_USER_APPS_DIRECTORY:
		case B_USER_BIN_DIRECTORY:
		case B_USER_PREFERENCES_DIRECTORY:
		case B_USER_ETC_DIRECTORY:
		case B_USER_LOG_DIRECTORY:
		case B_USER_SPOOL_DIRECTORY:
		case B_USER_VAR_DIRECTORY:
			templatePath = kUserDirectories[which - B_USER_DIRECTORY];
			break;

		/* Global directories */
		case B_APPS_DIRECTORY:
		case B_UTILITIES_DIRECTORY:
			templatePath = SYSTEM "/apps";
			break;
		case B_PREFERENCES_DIRECTORY:
			templatePath = SYSTEM "/preferences";
			break;
		case B_PACKAGE_LINKS_DIRECTORY:
			templatePath = "packages";
			break;

		default:
			return EINVAL;
	}

	if (templatePath == NULL)
		return ENOENT;

	PathBuffer pathBuffer(buffer, pathLength, strlen(buffer));

	// resolve "$h" placeholder to the user's home directory
	if (!strncmp(templatePath, "$h", 2)) {
		if (bootDevice > -1 && device != bootDevice) {
			pathBuffer.Append("/home");
		} else {
			size_t length = get_user_home_path(buffer, pathLength);
			if (length >= pathLength)
				return E2BIG;
			pathBuffer.SetTo(buffer, pathLength, length);
		}
		templatePath += 2;
	} else if (templatePath[0] != '\0')
		pathBuffer.Append('/');

	// resolve "$a" placeholder to the architecture subdirectory, if not
	// primary
	if (char* dollar = strchr(templatePath, '$')) {
		if (dollar[1] == 'a') {
			pathBuffer.Append(templatePath, dollar - templatePath);
#ifndef _KERNEL_MODE
			const char* architecture = __get_architecture();
			if (strcmp(architecture, __get_primary_architecture()) != 0) {
				pathBuffer.Append('/');
				pathBuffer.Append(architecture);
			}
#endif
			templatePath = dollar + 2;
		}
	}

	// append (remainder of) template path
	pathBuffer.Append(templatePath);

	if (pathBuffer.Length() >= pathLength)
		return E2BIG;

	if (createIt && stat(buffer, &st) < 0) {
		err = create_path(buffer, 0755);
		if (err != B_OK)
			return err;
	}

	strlcpy(returnedPath, buffer, pathLength);
	return B_OK;
}
Пример #3
0
status_t
internal_path_for_path(char* referencePath, size_t referencePathSize,
	const char* dependency, const char* architecture,
	path_base_directory baseDirectory, const char* subPath, uint32 flags,
	char* pathBuffer, size_t bufferSize)
{
	if (strcmp(architecture, __get_primary_architecture()) == 0)
		architecture = NULL;

	// 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) {
		// get the versioned package name
		status_t error = get_file_attribute(referencePath, "SYS:PACKAGE",
			packageName, sizeof(packageName));
		if (error != B_OK)
			return error;

		// normalize the dependency name
		char normalizedDependency[B_FILE_NAME_LENGTH];
		error = normalize_dependency(dependency, normalizedDependency,
			sizeof(normalizedDependency));
		if (error != B_OK)
			return error;

		// Compute the path of the dependency symlink. This will yield the
		// installation location path when normalized.
		if (snprintf(referencePath, referencePathSize,
					kSystemPackageLinksDirectory "/%s/%s", packageName,
					normalizedDependency)
				>= (ssize_t)referencePathSize) {
			return B_BUFFER_OVERFLOW;
		}
	}

	// 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)
			return error;

		dependency = NULL;
		subPath = packageName;
		baseDirectory = B_FIND_PATH_PACKAGES_DIRECTORY;
		flags = B_FIND_PATH_EXISTING_ONLY;
	}

	// 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
	const char* relativePath = get_relative_directory_path(
		installationLocationIndex, baseDirectory);
	if (relativePath == NULL)
		return B_BAD_VALUE;

	ssize_t pathSize = process_path(installationLocation, architecture,
		relativePath, subPath, flags, pathBuffer, bufferSize);
	if (pathSize <= 0)
		return pathSize == 0 ? B_ENTRY_NOT_FOUND : pathSize;
	return B_OK;
}