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
This commit is contained in:
Axel Dörfler
2006-04-02 16:02:28 +00:00
parent 60bf6a1fbe
commit ac1f397e60
+88 -38
View File
@@ -12,18 +12,13 @@
app_info structure provides info for a running app. app_info structure provides info for a running app.
*/ */
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <AppFileInfo.h> #include <AppFileInfo.h>
#include <Application.h> #include <Application.h>
#include <AppMisc.h> #include <AppMisc.h>
#include <Directory.h> #include <Directory.h>
#include <File.h> #include <File.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <fs_index.h>
#include <fs_info.h> #include <fs_info.h>
#include <image.h> #include <image.h>
#include <List.h> #include <List.h>
@@ -40,6 +35,14 @@
#include <RosterPrivate.h> #include <RosterPrivate.h>
#include <ServerProtocol.h> #include <ServerProtocol.h>
#include <Volume.h> #include <Volume.h>
#include <VolumeRoster.h>
#include <ctype.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
using namespace std; using namespace std;
using namespace BPrivate; using namespace BPrivate;
@@ -2509,7 +2512,7 @@ find_message_app_info(BMessage *message, app_info *info)
} }
// query_for_app // 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 signature The app's signature.
\param appRef A pointer to a pre-allocated entry_ref to be filled with \param appRef A pointer to a pre-allocated entry_ref to be filled with
a reference to the found application's executable. a reference to the found application's executable.
@@ -2524,43 +2527,90 @@ static
status_t status_t
query_for_app(const char *signature, entry_ref *appRef) query_for_app(const char *signature, entry_ref *appRef)
{ {
status_t error = (signature && appRef ? B_OK : B_BAD_VALUE); if (signature == NULL || appRef == NULL)
BVolume volume; return B_BAD_VALUE;
BQuery query;
if (error == B_OK) { status_t error = B_LAUNCH_FAILED_APP_NOT_FOUND;
// init the query bool caseInsensitive = false;
if (volume.SetTo(dev_for_path("/boot")) != B_OK
|| query.SetVolume(&volume) != B_OK while (true) {
|| query.PushAttr("BEOS:APP_SIG") != B_OK // search on all volumes
|| query.PushString(signature) != B_OK BVolumeRoster volumeRoster;
|| query.PushOp(B_EQ) != B_OK BVolume volume;
|| query.Fetch() != B_OK) { while (volumeRoster.GetNextVolume(&volume) == B_OK) {
error = B_LAUNCH_FAILED_APP_NOT_FOUND; if (!volume.KnowsQuery())
} continue;
}
// walk through the query index_info info;
bool appFound = false; if (fs_stat_index(volume.Device(), "BEOS:APP_SIG", &info) != 0) {
status_t foundAppError = B_OK; // This volume doesn't seem to have the index we're looking for;
if (error == B_OK) { // querying it might need a long time, and we don't care *that*
entry_ref ref; // much...
while (query.GetNextRef(&ref) == B_OK) { continue;
if ((!appFound || compare_app_versions(appRef, &ref) < 0)
&& (foundAppError = can_app_be_used(&ref)) == B_OK) {
*appRef = ref;
appFound = true;
} }
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 if (!caseInsensitive)
// B_LAUNCH_FAILED_APP_NOT_FOUND, otherwise we return the caseInsensitive = true;
// result of the last can_app_be_used(). else
error = (foundAppError != B_OK ? foundAppError break;
: B_LAUNCH_FAILED_APP_NOT_FOUND);
}
} }
return error; return error;
} }
// can_app_be_used // can_app_be_used
/*! \brief Checks whether or not an application can be used. /*! \brief Checks whether or not an application can be used.