Finally fixed update_mime_info(). As Be's version it understands two

different "force" levels now and updates the app file info attributes
for shared object files.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16123 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2006-01-28 19:41:07 +00:00
parent 1ee5d15ef8
commit 15424f3d37
10 changed files with 211 additions and 54 deletions
+6 -5
View File
@@ -579,7 +579,7 @@ message: B_REG_MIME_UPDATE_MIME_INFO
"entry": B_REF_TYPE "entry": B_REF_TYPE
"recursive": B_BOOLEAN_TYPE "recursive": B_BOOLEAN_TYPE
"synchronous": B_BOOLEAN_TYPE "synchronous": B_BOOLEAN_TYPE
"force": B_BOOLEAN_TYPE "force": B_INT32_TYPE
reply: standard general result reply: standard general result
message fields: message fields:
@@ -589,8 +589,9 @@ message fields:
- "synchronous": If true, the call will block until the operation is - "synchronous": If true, the call will block until the operation is
completed. If false, the call will return immediately and the operation completed. If false, the call will return immediately and the operation
will run asynchronously in another thread. will run asynchronously in another thread.
- "force": If true, also update entries for which a BEOS:TYPE attribute - "force": Specifies how to handle entries for which a BEOS:TYPE attribute
already exists. already exists. Valid values are
B_UPDATE_MIME_INFO_{NO_FORCE, FORCE_KEEP_TYPE, FORCE_UPDATE_ALL}.
reply fields: reply fields:
- "result": - "result":
@@ -607,7 +608,7 @@ message: B_REG_MIME_CREATE_APP_META_MIME
"entry": B_REF_TYPE "entry": B_REF_TYPE
"recursive": B_BOOLEAN_TYPE "recursive": B_BOOLEAN_TYPE
"synchronous": B_BOOLEAN_TYPE "synchronous": B_BOOLEAN_TYPE
"force": B_BOOLEAN_TYPE "force": B_INT32_TYPE
reply: standard general result reply: standard general result
message fields: message fields:
@@ -617,7 +618,7 @@ message fields:
- "synchronous": If true, the call will block until the operation is - "synchronous": If true, the call will block until the operation is
completed. If false, the call will return immediately and the operation completed. If false, the call will return immediately and the operation
will run asynchronously in another thread. will run asynchronously in another thread.
- "force": If true, also update entries for which meta app information - "force": If != 0, also update entries for which meta app information
already exists. already exists.
reply fields: reply fields:
+13 -7
View File
@@ -1,7 +1,8 @@
//---------------------------------------------------------------------- /*
// This software is part of the OpenBeOS distribution and is covered * Copyright 2004-2006, Haiku Inc. All Rights Reserved.
// by the OpenBeOS license. * Distributed under the terms of the MIT License.
//--------------------------------------------------------------------- */
/*! /*!
\file Mime.h \file Mime.h
Mime type C functions interface declarations. Mime type C functions interface declarations.
@@ -37,11 +38,18 @@ enum icon_size {
B_MINI_ICON = 16 B_MINI_ICON = 16
}; };
// values for the "force" parameter of update_mime_info() (Haiku only)
enum {
B_UPDATE_MIME_INFO_NO_FORCE = 0,
B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE = 1,
B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL = 2,
};
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// OpenBeOS only! // Haiku only!
#ifdef __cplusplus #ifdef __cplusplus
class BBitmap; class BBitmap;
@@ -56,5 +64,3 @@ status_t get_device_icon(const char *dev, BBitmap *icon, icon_size which);
#endif #endif
#endif // _MIME_H #endif // _MIME_H
@@ -18,8 +18,9 @@ namespace Mime {
class CreateAppMetaMimeThread : public MimeUpdateThread { class CreateAppMetaMimeThread : public MimeUpdateThread {
public: public:
CreateAppMetaMimeThread(const char *name, int32 priority, BMessenger managerMessenger, CreateAppMetaMimeThread(const char *name, int32 priority,
const entry_ref *root, bool recursive, bool force, BMessage *replyee); BMessenger managerMessenger, const entry_ref *root, bool recursive,
int32 force, BMessage *replyee);
status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir); status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir);
}; };
@@ -26,8 +26,9 @@ namespace Mime {
class MimeUpdateThread : public RegistrarThread { class MimeUpdateThread : public RegistrarThread {
public: public:
MimeUpdateThread(const char *name, int32 priority, BMessenger managerMessenger, MimeUpdateThread(const char *name, int32 priority,
const entry_ref *root, bool recursive, bool force, BMessage *replyee); BMessenger managerMessenger, const entry_ref *root, bool recursive,
int32 force, BMessage *replyee);
virtual ~MimeUpdateThread(); virtual ~MimeUpdateThread();
virtual status_t InitCheck(); virtual status_t InitCheck();
@@ -38,7 +39,7 @@ protected:
const entry_ref fRoot; const entry_ref fRoot;
const bool fRecursive; const bool fRecursive;
const bool fForce; const int32 fForce;
BMessage *fReplyee; BMessage *fReplyee;
bool DeviceSupportsAttributes(dev_t device); bool DeviceSupportsAttributes(dev_t device);
@@ -18,8 +18,9 @@ namespace Mime {
class UpdateMimeInfoThread : public MimeUpdateThread { class UpdateMimeInfoThread : public MimeUpdateThread {
public: public:
UpdateMimeInfoThread(const char *name, int32 priority, BMessenger managerMessenger, UpdateMimeInfoThread(const char *name, int32 priority,
const entry_ref *root, bool recursive, bool force, BMessage *replyee); BMessenger managerMessenger, const entry_ref *root, bool recursive,
int32 force, BMessage *replyee);
status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir); status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir);
}; };
+11 -3
View File
@@ -53,7 +53,7 @@ status_t do_mime_update(int32 what, const char *path, int recursive,
if (!err) if (!err)
err = msg.AddBool("synchronous", synchronous); err = msg.AddBool("synchronous", synchronous);
if (!err) if (!err)
err = msg.AddBool("force", force); err = msg.AddInt32("force", force);
if (!err) if (!err)
err = BRoster::Private().SendTo(&msg, &reply, true); err = BRoster::Private().SendTo(&msg, &reply, true);
if (!err) if (!err)
@@ -78,8 +78,16 @@ status_t do_mime_update(int32 what, const char *path, int recursive,
\param synchronous If non-null update_mime_info() waits until the \param synchronous If non-null update_mime_info() waits until the
operation is finished, otherwise it returns immediately and the operation is finished, otherwise it returns immediately and the
update is done asynchronously. update is done asynchronously.
\param force If non-null, also the information for files are updated that \param force Specifies how to handle files that already have MIME
have already been updated. information:
- \c B_UPDATE_MIME_INFO_NO_FORCE: Files that already have a
\c BEOS:TYPE attribute won't be updated.
- \c B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE: Files that already have a
\c BEOS:TYPE attribute will be updated too, but \c BEOS:TYPE
itself will remain untouched.
- \c B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL: Similar to
\c B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE, but the \c BEOS:TYPE
attribute will be updated too.
\return \return
- \c B_OK: Everything went fine. - \c B_OK: Everything went fine.
- An error code otherwise. - An error code otherwise.
@@ -23,9 +23,11 @@ namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
CreateAppMetaMimeThread::CreateAppMetaMimeThread(const char *name, int32 priority, CreateAppMetaMimeThread::CreateAppMetaMimeThread(const char *name,
BMessenger managerMessenger, const entry_ref *root, bool recursive, bool force, BMessage *replyee) int32 priority, BMessenger managerMessenger, const entry_ref *root,
: MimeUpdateThread(name, priority, managerMessenger, root, recursive, force, replyee) bool recursive, int32 force, BMessage *replyee)
: MimeUpdateThread(name, priority, managerMessenger, root, recursive, force,
replyee)
{ {
} }
+3 -2
View File
@@ -42,8 +42,9 @@ namespace Mime {
field detached from the registrar's mime manager looper (though this is not verified). field detached from the registrar's mime manager looper (though this is not verified).
The message will be replied to at the end of the thread's execution. The message will be replied to at the end of the thread's execution.
*/ */
MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, BMessenger managerMessenger, MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority,
const entry_ref *root, bool recursive, bool force, BMessage *replyee) BMessenger managerMessenger, const entry_ref *root, bool recursive,
int32 force, BMessage *replyee)
: RegistrarThread(name, priority, managerMessenger) : RegistrarThread(name, priority, managerMessenger)
, fRoot(root ? *root : entry_ref()) , fRoot(root ? *root : entry_ref())
, fRecursive(recursive) , fRecursive(recursive)
+160 -25
View File
@@ -9,7 +9,10 @@
#include "mime/UpdateMimeInfoThread.h" #include "mime/UpdateMimeInfoThread.h"
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <fs_attr.h> #include <fs_attr.h>
#include <Message.h>
#include <MimeType.h> #include <MimeType.h>
#include <mime/database_support.h> #include <mime/database_support.h>
#include <Node.h> #include <Node.h>
@@ -18,11 +21,36 @@ namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS";
// update_icon
static status_t
update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
const char *type, BBitmap &icon, icon_size iconSize)
{
status_t err = appFileInfoRead.GetIconForType(type, &icon, iconSize);
if (err == B_OK)
err = appFileInfoWrite.SetIconForType(type, &icon, iconSize);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetIconForType(type, NULL, iconSize);
return err;
}
// is_shared_object_mime_type
static bool
is_shared_object_mime_type(BMimeType &type)
{
return (type == "application/x-vnd.Be-elfexecutable");
}
// constructor // constructor
//! Creates a new UpdateMimeInfoThread object //! Creates a new UpdateMimeInfoThread object
UpdateMimeInfoThread::UpdateMimeInfoThread(const char *name, int32 priority, UpdateMimeInfoThread::UpdateMimeInfoThread(const char *name, int32 priority,
BMessenger managerMessenger, const entry_ref *root, bool recursive, bool force, BMessage *replyee) BMessenger managerMessenger, const entry_ref *root, bool recursive,
: MimeUpdateThread(name, priority, managerMessenger, root, recursive, force, replyee) int32 force, BMessage *replyee)
: MimeUpdateThread(name, priority, managerMessenger, root, recursive, force,
replyee)
{ {
} }
@@ -35,43 +63,150 @@ UpdateMimeInfoThread::UpdateMimeInfoThread(const char *name, int32 priority,
status_t status_t
UpdateMimeInfoThread::DoMimeUpdate(const entry_ref *entry, bool *entryIsDir) UpdateMimeInfoThread::DoMimeUpdate(const entry_ref *entry, bool *entryIsDir)
{ {
// TODO: This implementation is incomplete.
// For application executables we also need to copy several things from the
// resources into attributes (basically that is supported by BAppFileInfo,
// which we can use here, BTW).
// Furthermore fForce shouldn't be a boolean. The do_mime_update() API
// functions takes an "int force", which can have three valid values, 0, 1,
// and 2. 0 is no-force, 1 and 2 correspond to the mimeset flags -f and -F,
// respectively.
status_t err = entry ? B_OK : B_BAD_VALUE; status_t err = entry ? B_OK : B_BAD_VALUE;
bool doUpdate = true; bool updateType = false;
bool updateAppInfo = false;
BNode node; BNode node;
if (!err) if (!err)
err = node.SetTo(entry); err = node.SetTo(entry);
if (!err && entryIsDir) if (!err && entryIsDir)
*entryIsDir = node.IsDirectory(); *entryIsDir = node.IsDirectory();
if (!err && !fForce) { if (!err) {
// If not forced, only update if the entry has no file type attribute // If not forced, only update if the entry has no file type attribute
attr_info info; attr_info info;
if (!err) if (fForce == B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL
doUpdate = node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND; || node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND) {
updateType = true;
}
updateAppInfo = (updateType
|| fForce == B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE);
} }
if (!err && doUpdate) {
BMimeType type; // guess the MIME type
BMimeType type;
if (!err && (updateType || updateAppInfo)) {
err = BMimeType::GuessMimeType(entry, &type); err = BMimeType::GuessMimeType(entry, &type);
if (!err) if (!err)
err = type.InitCheck(); err = type.InitCheck();
if (!err) {
const char *typeStr = type.Type();
ssize_t len = strlen(typeStr)+1;
ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, typeStr, len);
if (bytes < B_OK)
err = bytes;
else
err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK);
}
} }
// update the MIME type
if (!err && updateType) {
const char *typeStr = type.Type();
ssize_t len = strlen(typeStr)+1;
ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, typeStr,
len);
if (bytes < B_OK)
err = bytes;
else
err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK);
}
// update the app file info attributes, if this is a shared object
BFile file;
BAppFileInfo appFileInfoRead;
BAppFileInfo appFileInfoWrite;
if (!err && updateAppInfo && node.IsFile()
&& is_shared_object_mime_type(type)
&& file.SetTo(entry, B_READ_WRITE) == B_OK
&& appFileInfoRead.SetTo(&file) == B_OK
&& appFileInfoWrite.SetTo(&file) == B_OK) {
// we read from resources and write to attributes
appFileInfoRead.SetInfoLocation(B_USE_RESOURCES);
appFileInfoWrite.SetInfoLocation(B_USE_ATTRIBUTES);
// signature
char signature[B_MIME_TYPE_LENGTH];
err = appFileInfoRead.GetSignature(signature);
if (err == B_OK)
err = appFileInfoWrite.SetSignature(signature);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetSignature(NULL);
if (err != B_OK)
return err;
// app flags
uint32 appFlags;
err = appFileInfoRead.GetAppFlags(&appFlags);
if (err == B_OK) {
err = appFileInfoWrite.SetAppFlags(appFlags);
} else if (err == B_ENTRY_NOT_FOUND) {
file.RemoveAttr(kAppFlagsAttribute);
err = B_OK;
}
if (err != B_OK)
return err;
// supported types
BMessage supportedTypes;
bool hasSupportedTypes = false;
err = appFileInfoRead.GetSupportedTypes(&supportedTypes);
if (err == B_OK) {
err = appFileInfoWrite.SetSupportedTypes(&supportedTypes);
hasSupportedTypes = true;
} else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetSignature(NULL);
if (err != B_OK)
return err;
// small icon
BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK,
B_CMAP8);
if (smallIcon.InitCheck() != B_OK)
return smallIcon.InitCheck();
err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon,
B_MINI_ICON);
if (err != B_OK)
return err;
// large icon
BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK,
B_CMAP8);
if (largeIcon.InitCheck() != B_OK)
return largeIcon.InitCheck();
err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon,
B_LARGE_ICON);
if (err != B_OK)
return err;
// version infos
const version_kind versionKinds[]
= {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND};
for (int i = 0; i < 2; i++) {
version_kind kind = versionKinds[i];
version_info versionInfo;
err = appFileInfoRead.GetVersionInfo(&versionInfo, kind);
if (err == B_OK)
err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetVersionInfo(NULL, kind);
if (err != B_OK)
return err;
}
// icons for supported types
if (hasSupportedTypes) {
const char *supportedType;
for (int32 i = 0;
supportedTypes.FindString("types", i, &supportedType) == B_OK;
i++) {
// small icon
err = update_icon(appFileInfoRead, appFileInfoWrite,
supportedType, smallIcon, B_MINI_ICON);
if (err != B_OK)
return err;
// large icon
err = update_icon(appFileInfoRead, appFileInfoWrite,
supportedType, largeIcon, B_LARGE_ICON);
if (err != B_OK)
return err;
}
}
}
return err; return err;
} }
+3 -2
View File
@@ -186,8 +186,9 @@ MIMEManager::MessageReceived(BMessage *message)
using BPrivate::Storage::Mime::UpdateMimeInfoThread; using BPrivate::Storage::Mime::UpdateMimeInfoThread;
entry_ref root; entry_ref root;
bool recursive, force; bool recursive;
bool synchronous = false; bool synchronous = false;
int32 force;
MimeUpdateThread *thread = NULL; MimeUpdateThread *thread = NULL;
@@ -202,7 +203,7 @@ MIMEManager::MessageReceived(BMessage *message)
if (!err) if (!err)
err = message->FindBool("synchronous", &synchronous); err = message->FindBool("synchronous", &synchronous);
if (!err) if (!err)
err = message->FindBool("force", &force); err = message->FindInt32("force", &force);
// Detach the message for synchronous calls // Detach the message for synchronous calls
if (!err && synchronous) { if (!err && synchronous) {