From ac1f397e60f051907568322e1e1fb984de390d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 2 Apr 2006 16:02:28 +0000 Subject: [PATCH] Rewrote the private query_for_app() function to search on all mounted volumes instead of just the boot volume. It now also has a second pass in case nothing could be found. The second pass does a case insensitive query for the application's signature, and fixes the problem that some apps couldn't be started by signature until they were launched once (because the MIME database is always case insensitive). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16967 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/app/Roster.cpp | 126 ++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 38 deletions(-) diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index e158e810dc..124b057767 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -12,18 +12,13 @@ app_info structure provides info for a running app. */ -#include -#include -#include -#include -#include - #include #include #include #include #include #include +#include #include #include #include @@ -40,6 +35,14 @@ #include #include #include +#include + +#include +#include +#include +#include +#include +#include using namespace std; using namespace BPrivate; @@ -2509,7 +2512,7 @@ find_message_app_info(BMessage *message, app_info *info) } // query_for_app -/*! \brief Finds an app by signature on the boot volume. +/*! \brief Finds an app by signature on any mounted volume. \param signature The app's signature. \param appRef A pointer to a pre-allocated entry_ref to be filled with a reference to the found application's executable. @@ -2524,43 +2527,90 @@ static status_t query_for_app(const char *signature, entry_ref *appRef) { - status_t error = (signature && appRef ? B_OK : B_BAD_VALUE); - BVolume volume; - BQuery query; - if (error == B_OK) { - // init the query - if (volume.SetTo(dev_for_path("/boot")) != B_OK - || query.SetVolume(&volume) != B_OK - || query.PushAttr("BEOS:APP_SIG") != B_OK - || query.PushString(signature) != B_OK - || query.PushOp(B_EQ) != B_OK - || query.Fetch() != B_OK) { - error = B_LAUNCH_FAILED_APP_NOT_FOUND; - } - } - // walk through the query - bool appFound = false; - status_t foundAppError = B_OK; - if (error == B_OK) { - entry_ref ref; - while (query.GetNextRef(&ref) == B_OK) { - if ((!appFound || compare_app_versions(appRef, &ref) < 0) - && (foundAppError = can_app_be_used(&ref)) == B_OK) { - *appRef = ref; - appFound = true; + if (signature == NULL || appRef == NULL) + return B_BAD_VALUE; + + status_t error = B_LAUNCH_FAILED_APP_NOT_FOUND; + bool caseInsensitive = false; + + while (true) { + // search on all volumes + BVolumeRoster volumeRoster; + BVolume volume; + while (volumeRoster.GetNextVolume(&volume) == B_OK) { + if (!volume.KnowsQuery()) + continue; + + index_info info; + if (fs_stat_index(volume.Device(), "BEOS:APP_SIG", &info) != 0) { + // This volume doesn't seem to have the index we're looking for; + // querying it might need a long time, and we don't care *that* + // much... + continue; } + + BQuery query; + query.SetVolume(&volume); + query.PushAttr("BEOS:APP_SIG"); + if (!caseInsensitive) + query.PushString(signature); + else { + // second pass, create a case insensitive query string + char string[B_MIME_TYPE_LENGTH * 4]; + strcpy(string, "application/"); + + int32 length = strlen(string); + const char *from = signature + length; + char *to = string + length; + + for (; from[0]; from++) { + if (isalpha(from[0])) { + *to++ = '['; + *to++ = tolower(from[0]); + *to++ = toupper(from[0]); + *to++ = ']'; + } else + *to++ = from[0]; + } + + to[0] = '\0'; + query.PushString(string); + } + query.PushOp(B_EQ); + + query.Fetch(); + + // walk through the query + bool appFound = false; + status_t foundAppError = B_OK; + entry_ref ref; + while (query.GetNextRef(&ref) == B_OK) { + if ((!appFound || compare_app_versions(appRef, &ref) < 0) + && (foundAppError = can_app_be_used(&ref)) == B_OK) { + *appRef = ref; + appFound = true; + } + } + if (!appFound) { + // If the query didn't return any hits, the error is + // B_LAUNCH_FAILED_APP_NOT_FOUND, otherwise we return the + // result of the last can_app_be_used(). + error = foundAppError != B_OK + ? foundAppError : B_LAUNCH_FAILED_APP_NOT_FOUND; + } else + return B_OK; } - if (!appFound) { - // If the query didn't return any hits, the error is - // B_LAUNCH_FAILED_APP_NOT_FOUND, otherwise we return the - // result of the last can_app_be_used(). - error = (foundAppError != B_OK ? foundAppError - : B_LAUNCH_FAILED_APP_NOT_FOUND); - } + + if (!caseInsensitive) + caseInsensitive = true; + else + break; } + return error; } + // can_app_be_used /*! \brief Checks whether or not an application can be used.