Support multiple MIME DB directories
Each installation location (system, common, common/non-packaged, ~/config, ~/config/non-package) can now have a read-only data/mime_db directory. ~/config/settings/beos_mime is now named mime_db as well. The contents of all directories makes up the MIME DB. Entries in more specific locations shadow entries in more general locations. Only the directory in ~/config/settings is where the registrar writes changes to. The new layout allows packages to contribute entries to the MIME DB by simply providing the respective files in data/mime_db. Consequently the user settings directory is supposed to contain only the things the user has actually changed. Seems to work fine as far as tested. A few issues, though: * The registrar doesn't monitor the directories yet, so it doesn't notice entry changes due to package de-/activation. * ATM it is not possible to remove a MIME type that is not in the user settings directory, although the FileTypes GUI suggests that it is. We'd have to work with white-outs, since we cannot remove the files in the data/mime_db directories. Or, alternatively, the API has to be extended and the FileTypes GUI adjusted to disable the "Remove" button in such a case.
This commit is contained in:
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <StorageDefs.h>
|
#include <StorageDefs.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class BNode;
|
class BNode;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
class BString;
|
class BStringList;
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
@@ -20,8 +20,8 @@ namespace Storage {
|
|||||||
namespace Mime {
|
namespace Mime {
|
||||||
|
|
||||||
// Database directory
|
// Database directory
|
||||||
const std::string get_database_directory();
|
const BStringList& get_database_directories();
|
||||||
const std::string get_application_database_directory();
|
BString get_writable_database_directory();
|
||||||
|
|
||||||
// Attribute Prefixes
|
// Attribute Prefixes
|
||||||
extern const char *kMiniIconAttrPrefix;
|
extern const char *kMiniIconAttrPrefix;
|
||||||
@@ -75,7 +75,7 @@ extern const char *kMetaMimeType;
|
|||||||
// Error codes (to be used only by BPrivate::Storage::Mime members)
|
// Error codes (to be used only by BPrivate::Storage::Mime members)
|
||||||
extern const status_t kMimeGuessFailureError;
|
extern const status_t kMimeGuessFailureError;
|
||||||
|
|
||||||
std::string type_to_filename(const char *type);
|
BString type_to_writable_filename(const char *type);
|
||||||
|
|
||||||
status_t open_type(const char *type, BNode *result);
|
status_t open_type(const char *type, BNode *result);
|
||||||
status_t open_or_create_type(const char *type, BNode *result, bool *didCreate);
|
status_t open_or_create_type(const char *type, BNode *result, bool *didCreate);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Tyler Dauwalder
|
* Tyler Dauwalder
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -14,18 +15,23 @@
|
|||||||
#include <AppMisc.h>
|
#include <AppMisc.h>
|
||||||
#include <DataIO.h>
|
#include <DataIO.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <File.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
|
#include <Entry.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <storage_support.h>
|
#include <storage_support.h>
|
||||||
|
#include <StringList.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
#include <fs_attr.h> // For struct attr_info
|
#include <fs_attr.h> // For struct attr_info
|
||||||
#include <new> // For new(nothrow)
|
#include <new> // For new(nothrow)
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
#include "mime/database_support.h"
|
#include "mime/database_support.h"
|
||||||
|
|
||||||
@@ -94,49 +100,187 @@ const char *kMetaMimeType = "application/x-vnd.Be-meta-mime";
|
|||||||
// Error codes
|
// Error codes
|
||||||
const status_t kMimeGuessFailureError = B_ERRORS_END+1;
|
const status_t kMimeGuessFailureError = B_ERRORS_END+1;
|
||||||
|
|
||||||
|
static const directory_which kBaseDirectoryConstants[] = {
|
||||||
|
B_USER_SETTINGS_DIRECTORY,
|
||||||
|
B_USER_NONPACKAGED_DATA_DIRECTORY,
|
||||||
|
B_USER_DATA_DIRECTORY,
|
||||||
|
B_COMMON_NONPACKAGED_DATA_DIRECTORY,
|
||||||
|
B_COMMON_DATA_DIRECTORY,
|
||||||
|
B_SYSTEM_DATA_DIRECTORY
|
||||||
|
};
|
||||||
|
|
||||||
static pthread_once_t sDatabaseDirectoryInitOnce = PTHREAD_ONCE_INIT;
|
static pthread_once_t sDatabaseDirectoryInitOnce = PTHREAD_ONCE_INIT;
|
||||||
static std::string sDatabaseDirectory;
|
static BStringList sDatabaseDirectories;
|
||||||
static std::string sApplicationDatabaseDirectory;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_database_directories()
|
init_database_directories()
|
||||||
{
|
{
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < sizeof(kBaseDirectoryConstants)
|
||||||
|
/ sizeof(kBaseDirectoryConstants[0]); i++) {
|
||||||
|
BString directoryPath;
|
||||||
BPath path;
|
BPath path;
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK)
|
if (find_directory(kBaseDirectoryConstants[i], &path) == B_OK)
|
||||||
sDatabaseDirectory = path.Path();
|
directoryPath = path.Path();
|
||||||
|
else if (i == 0)
|
||||||
|
directoryPath = "/boot/home/config/settings";
|
||||||
else
|
else
|
||||||
sDatabaseDirectory = "/boot/home/config/settings";
|
continue;
|
||||||
|
|
||||||
sDatabaseDirectory += "/beos_mime";
|
directoryPath += "/mime_db";
|
||||||
sApplicationDatabaseDirectory = sDatabaseDirectory + "/application";
|
sDatabaseDirectories.Add(directoryPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string
|
const BStringList&
|
||||||
get_database_directory()
|
get_database_directories()
|
||||||
{
|
{
|
||||||
pthread_once(&sDatabaseDirectoryInitOnce, &init_database_directories);
|
pthread_once(&sDatabaseDirectoryInitOnce, &init_database_directories);
|
||||||
return sDatabaseDirectory;
|
return sDatabaseDirectories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string
|
BString
|
||||||
get_application_database_directory()
|
get_writable_database_directory()
|
||||||
{
|
{
|
||||||
pthread_once(&sDatabaseDirectoryInitOnce, &init_database_directories);
|
return get_database_directories().StringAt(0);
|
||||||
return sApplicationDatabaseDirectory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// type_to_filename
|
static BString
|
||||||
//! Converts the given MIME type to an absolute path in the MIME database.
|
type_to_filename(const char* type, int32 index)
|
||||||
std::string
|
|
||||||
type_to_filename(const char *type)
|
|
||||||
{
|
{
|
||||||
return get_database_directory() + "/" + BPrivate::Storage::to_lower(type);
|
BString path = get_database_directories().StringAt(index);
|
||||||
|
return path << '/' << BPrivate::Storage::to_lower(type).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Converts the given MIME type to an absolute path in the user writeable MIME
|
||||||
|
database directory.
|
||||||
|
*/
|
||||||
|
BString
|
||||||
|
type_to_writable_filename(const char* type)
|
||||||
|
{
|
||||||
|
return type_to_filename(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
open_type(const char* type, BNode* _node, int32& _index)
|
||||||
|
{
|
||||||
|
const BStringList& directories = get_database_directories();
|
||||||
|
int32 count = directories.CountStrings();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
status_t error = _node->SetTo(type_to_filename(type, i));
|
||||||
|
attr_info attrInfo;
|
||||||
|
if (error == B_OK && _node->GetAttrInfo(kTypeAttr, &attrInfo) == B_OK) {
|
||||||
|
_index = i;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
create_type_node(const char* type, BNode& _result)
|
||||||
|
{
|
||||||
|
const char* slash = strchr(type, '/');
|
||||||
|
BString superTypeName;
|
||||||
|
if (slash != NULL)
|
||||||
|
superTypeName.SetTo(type, slash - type);
|
||||||
|
else
|
||||||
|
superTypeName = type;
|
||||||
|
superTypeName.ToLower();
|
||||||
|
|
||||||
|
// open/create the directory for the supertype
|
||||||
|
BDirectory parent(get_writable_database_directory());
|
||||||
|
status_t error = parent.InitCheck();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
BDirectory superTypeDirectory;
|
||||||
|
if (BEntry(&parent, superTypeName).Exists())
|
||||||
|
error = superTypeDirectory.SetTo(&parent, superTypeName);
|
||||||
|
else
|
||||||
|
error = parent.CreateDirectory(superTypeName, &superTypeDirectory);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// create the subtype
|
||||||
|
BFile subTypeFile;
|
||||||
|
if (slash != NULL) {
|
||||||
|
error = superTypeDirectory.CreateFile(BString(slash + 1).ToLower(),
|
||||||
|
&subTypeFile);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign the result
|
||||||
|
if (slash != NULL)
|
||||||
|
_result = subTypeFile;
|
||||||
|
else
|
||||||
|
_result = superTypeDirectory;
|
||||||
|
return _result.InitCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
copy_type_node(BNode& source, const char* type, BNode& _target)
|
||||||
|
{
|
||||||
|
status_t error = create_type_node(type, _target);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// copy the attributes
|
||||||
|
MemoryDeleter bufferDeleter;
|
||||||
|
size_t bufferSize = 0;
|
||||||
|
|
||||||
|
source.RewindAttrs();
|
||||||
|
char attribute[B_ATTR_NAME_LENGTH];
|
||||||
|
while (source.GetNextAttrName(attribute) == B_OK) {
|
||||||
|
attr_info info;
|
||||||
|
error = source.GetAttrInfo(attribute, &info);
|
||||||
|
if (error != B_OK) {
|
||||||
|
syslog(LOG_ERR, "Failed to get info for attribute \"%s\" of MIME "
|
||||||
|
"type \"%s\": %s", attribute, type, strerror(error));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize our buffer, if necessary
|
||||||
|
if (info.size > bufferSize) {
|
||||||
|
bufferDeleter.SetTo(malloc(info.size));
|
||||||
|
if (bufferDeleter.Get() == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
bufferSize = info.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t bytesRead = source.ReadAttr(attribute, info.type, 0,
|
||||||
|
bufferDeleter.Get(), info.size);
|
||||||
|
if (bytesRead != info.size) {
|
||||||
|
syslog(LOG_ERR, "Failed to read attribute \"%s\" of MIME "
|
||||||
|
"type \"%s\": %s", attribute, type,
|
||||||
|
bytesRead < 0 ? strerror(bytesRead) : "short read");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t bytesWritten = _target.WriteAttr(attribute, info.type, 0,
|
||||||
|
bufferDeleter.Get(), info.size);
|
||||||
|
if (bytesWritten < 0) {
|
||||||
|
syslog(LOG_ERR, "Failed to write attribute \"%s\" of MIME "
|
||||||
|
"type \"%s\": %s", attribute, type,
|
||||||
|
bytesWritten < 0 ? strerror(bytesWritten) : "short write");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// open_type
|
// open_type
|
||||||
/*! \brief Opens a BNode on the given type, failing if the type has no
|
/*! \brief Opens a BNode on the given type, failing if the type has no
|
||||||
corresponding file in the database.
|
corresponding file in the database.
|
||||||
@@ -150,20 +294,8 @@ open_type(const char *type, BNode *result)
|
|||||||
if (type == NULL || result == NULL)
|
if (type == NULL || result == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
status_t status = result->SetTo(type_to_filename(type).c_str());
|
int32 index;
|
||||||
|
return open_type(type, result, index);
|
||||||
// TODO: this can be removed again later - we just didn't write this
|
|
||||||
// attribute is before at all...
|
|
||||||
#if 1
|
|
||||||
if (status == B_OK) {
|
|
||||||
// check if the MIME:TYPE attribute exist, and create it if not
|
|
||||||
attr_info info;
|
|
||||||
if (result->GetAttrInfo(kTypeAttr, &info) != B_OK)
|
|
||||||
result->WriteAttr(kTypeAttr, B_STRING_TYPE, 0, type, strlen(type) + 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// open_or_create_type
|
// open_or_create_type
|
||||||
@@ -180,44 +312,47 @@ open_or_create_type(const char *type, BNode *result, bool *didCreate)
|
|||||||
{
|
{
|
||||||
if (didCreate)
|
if (didCreate)
|
||||||
*didCreate = false;
|
*didCreate = false;
|
||||||
std::string filename;
|
|
||||||
std::string typeLower = BPrivate::Storage::to_lower(type);
|
// See, if the type already exists.
|
||||||
status_t err = (type && result ? B_OK : B_BAD_VALUE);
|
int32 index;
|
||||||
if (!err) {
|
status_t error = open_type(type, result, index);
|
||||||
filename = type_to_filename(type);
|
if (error == B_OK) {
|
||||||
err = result->SetTo(filename.c_str());
|
if (index == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// The caller wants a editable node, but the node found is not in the
|
||||||
|
// user's settings directory. Copy the node.
|
||||||
|
BNode nodeToClone(*result);
|
||||||
|
if (nodeToClone.InitCheck() != B_OK)
|
||||||
|
return nodeToClone.InitCheck();
|
||||||
|
|
||||||
|
error = copy_type_node(nodeToClone, type, *result);
|
||||||
|
if (error != B_OK) {
|
||||||
|
result->Unset();
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
if (err == B_ENTRY_NOT_FOUND) {
|
|
||||||
// Figure out what type of node we need to create
|
if (didCreate != NULL)
|
||||||
// + Supertype == directory
|
|
||||||
// + Non-supertype == file
|
|
||||||
size_t pos = typeLower.find_first_of('/');
|
|
||||||
if (pos == std::string::npos) {
|
|
||||||
// Supertype == directory
|
|
||||||
BDirectory parent(get_database_directory().c_str());
|
|
||||||
err = parent.InitCheck();
|
|
||||||
if (!err)
|
|
||||||
err = parent.CreateDirectory(typeLower.c_str(), NULL);
|
|
||||||
} else {
|
|
||||||
// Non-supertype == file
|
|
||||||
std::string super(typeLower, 0, pos);
|
|
||||||
std::string sub(typeLower, pos+1);
|
|
||||||
BDirectory parent((get_database_directory() + "/" + super).c_str());
|
|
||||||
err = parent.InitCheck();
|
|
||||||
if (!err)
|
|
||||||
err = parent.CreateFile(sub.c_str(), NULL);
|
|
||||||
}
|
|
||||||
// Now try opening again
|
|
||||||
if (err == B_OK)
|
|
||||||
err = result->SetTo(filename.c_str());
|
|
||||||
if (err == B_OK && didCreate)
|
|
||||||
*didCreate = true;
|
*didCreate = true;
|
||||||
if (err == B_OK) {
|
return error;
|
||||||
// write META:TYPE attribute
|
|
||||||
result->WriteAttr(kTypeAttr, B_STRING_TYPE, 0, type, strlen(type) + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type doesn't exist yet -- create the respective node
|
||||||
|
error = create_type_node(type, *result);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// write the type attribute
|
||||||
|
error = result->WriteAttr(kTypeAttr, B_STRING_TYPE, 0, type,
|
||||||
|
strlen(type) + 1);
|
||||||
|
if (error != B_OK) {
|
||||||
|
result->Unset();
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
|
if (didCreate != NULL)
|
||||||
|
*didCreate = true;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read_mime_attr
|
// read_mime_attr
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ Server registrar
|
|||||||
AssociatedTypes.cpp
|
AssociatedTypes.cpp
|
||||||
CreateAppMetaMimeThread.cpp
|
CreateAppMetaMimeThread.cpp
|
||||||
Database.cpp
|
Database.cpp
|
||||||
|
DatabaseDirectory.cpp
|
||||||
InstalledTypes.cpp
|
InstalledTypes.cpp
|
||||||
MimeSnifferAddon.cpp
|
MimeSnifferAddon.cpp
|
||||||
MimeSnifferAddonManager.cpp
|
MimeSnifferAddonManager.cpp
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AssociatedTypes.h"
|
#include "AssociatedTypes.h"
|
||||||
#include "MimeSnifferAddonManager.h"
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
@@ -19,8 +22,9 @@
|
|||||||
#include <mime/database_support.h>
|
#include <mime/database_support.h>
|
||||||
#include <storage_support.h>
|
#include <storage_support.h>
|
||||||
|
|
||||||
#include <new>
|
#include "DatabaseDirectory.h"
|
||||||
#include <stdio.h>
|
#include "MimeSnifferAddonManager.h"
|
||||||
|
|
||||||
|
|
||||||
#define DBG(x) x
|
#define DBG(x) x
|
||||||
//#define DBG(x)
|
//#define DBG(x)
|
||||||
@@ -330,8 +334,8 @@ AssociatedTypes::BuildAssociatedTypesTable()
|
|||||||
fFileExtensions.clear();
|
fFileExtensions.clear();
|
||||||
fAssociatedTypes.clear();
|
fAssociatedTypes.clear();
|
||||||
|
|
||||||
BDirectory root;
|
DatabaseDirectory root;
|
||||||
status_t err = root.SetTo(get_database_directory().c_str());
|
status_t err = root.Init();
|
||||||
if (!err) {
|
if (!err) {
|
||||||
root.Rewind();
|
root.Rewind();
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -354,8 +358,8 @@ AssociatedTypes::BuildAssociatedTypesTable()
|
|||||||
|
|
||||||
// First, iterate through this supertype directory and process
|
// First, iterate through this supertype directory and process
|
||||||
// all of its subtypes
|
// all of its subtypes
|
||||||
BDirectory dir;
|
DatabaseDirectory dir;
|
||||||
if (dir.SetTo(&entry) == B_OK) {
|
if (dir.Init(supertype) == B_OK) {
|
||||||
dir.Rewind();
|
dir.Rewind();
|
||||||
while (true) {
|
while (true) {
|
||||||
BEntry subEntry;
|
BEntry subEntry;
|
||||||
@@ -392,8 +396,7 @@ AssociatedTypes::BuildAssociatedTypesTable()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DBG(OUT("Mime::AssociatedTypes::BuildAssociatedTypesTable(): "
|
DBG(OUT("Mime::AssociatedTypes::BuildAssociatedTypesTable(): "
|
||||||
"Failed opening mime database directory '%s'\n",
|
"Failed opening mime database directory\n"));
|
||||||
get_database_directory().c_str()));
|
|
||||||
}
|
}
|
||||||
if (!err) {
|
if (!err) {
|
||||||
fHaveDoneFullBuild = true;
|
fHaveDoneFullBuild = true;
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ Database::Database()
|
|||||||
fDeferredInstallNotificationsLocker("deferred install notifications"),
|
fDeferredInstallNotificationsLocker("deferred install notifications"),
|
||||||
fDeferredInstallNotifications()
|
fDeferredInstallNotifications()
|
||||||
{
|
{
|
||||||
// Do some really minor error checking
|
// make sure the user's MIME DB directory exists
|
||||||
BEntry entry(get_database_directory().c_str());
|
fStatus = create_directory(get_writable_database_directory(),
|
||||||
fStatus = entry.Exists() ? B_OK : B_BAD_VALUE;
|
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -107,7 +107,7 @@ Database::Install(const char *type)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
status_t err = entry.SetTo(type_to_filename(type).c_str());
|
status_t err = entry.SetTo(type_to_writable_filename(type));
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (entry.Exists())
|
if (entry.Exists())
|
||||||
err = B_FILE_EXISTS;
|
err = B_FILE_EXISTS;
|
||||||
@@ -139,7 +139,7 @@ Database::Delete(const char *type)
|
|||||||
|
|
||||||
// Open the type
|
// Open the type
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
status_t status = entry.SetTo(type_to_filename(type).c_str());
|
status_t status = entry.SetTo(type_to_writable_filename(type));
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "DatabaseDirectory.h"
|
||||||
|
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <StringList.h>
|
||||||
|
|
||||||
|
#include <mime/database_support.h>
|
||||||
|
|
||||||
|
|
||||||
|
DatabaseDirectory::DatabaseDirectory()
|
||||||
|
:
|
||||||
|
BMergedDirectory(B_COMPARE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DatabaseDirectory::~DatabaseDirectory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DatabaseDirectory::Init(const char* superType)
|
||||||
|
{
|
||||||
|
status_t error = BMergedDirectory::Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
const BStringList& directories
|
||||||
|
= BPrivate::Storage::Mime::get_database_directories();
|
||||||
|
int32 count = directories.CountStrings();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
BString directory = directories.StringAt(i);
|
||||||
|
if (superType != NULL)
|
||||||
|
directory << '/' << superType;
|
||||||
|
|
||||||
|
AddDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DatabaseDirectory::ShallPreferFirstEntry(const entry_ref& entry1, int32 index1,
|
||||||
|
const entry_ref& entry2, int32 index2)
|
||||||
|
{
|
||||||
|
return _IsValidMimeTypeEntry(entry1) || !_IsValidMimeTypeEntry(entry2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DatabaseDirectory::_IsValidMimeTypeEntry(const entry_ref& entry)
|
||||||
|
{
|
||||||
|
// check whether the MIME:TYPE attribute exists
|
||||||
|
BNode node;
|
||||||
|
attr_info info;
|
||||||
|
return node.SetTo(&entry) == B_OK
|
||||||
|
&& node.GetAttrInfo(BPrivate::Storage::Mime::kTypeAttr, &info) == B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
#ifndef DATABASE_DIRECTORY_H
|
||||||
|
#define DATABASE_DIRECTORY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <MergedDirectory.h>
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseDirectory : public BMergedDirectory {
|
||||||
|
public:
|
||||||
|
DatabaseDirectory();
|
||||||
|
virtual ~DatabaseDirectory();
|
||||||
|
|
||||||
|
status_t Init(const char* superType = NULL);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool ShallPreferFirstEntry(const entry_ref& entry1,
|
||||||
|
int32 index1, const entry_ref& entry2,
|
||||||
|
int32 index2);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _IsValidMimeTypeEntry(const entry_ref& entry);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DATABASE_DIRECTORY_H
|
||||||
@@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
#include "InstalledTypes.h"
|
#include "InstalledTypes.h"
|
||||||
|
|
||||||
#include <mime/database_support.h>
|
#include <stdio.h>
|
||||||
#include <storage_support.h>
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
@@ -20,8 +21,11 @@
|
|||||||
#include <MimeType.h>
|
#include <MimeType.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include <new>
|
#include <mime/database_support.h>
|
||||||
#include <stdio.h>
|
#include <storage_support.h>
|
||||||
|
|
||||||
|
#include "DatabaseDirectory.h"
|
||||||
|
|
||||||
|
|
||||||
#define DBG(x) x
|
#define DBG(x) x
|
||||||
//#define DBG(x)
|
//#define DBG(x)
|
||||||
@@ -380,9 +384,9 @@ InstalledTypes::_BuildInstalledTypesList()
|
|||||||
err = B_NO_MEMORY;
|
err = B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
BDirectory root;
|
DatabaseDirectory root;
|
||||||
if (!err)
|
if (!err)
|
||||||
err = root.SetTo(get_database_directory().c_str());
|
err = root.Init();
|
||||||
if (!err) {
|
if (!err) {
|
||||||
root.Rewind();
|
root.Rewind();
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -413,8 +417,8 @@ InstalledTypes::_BuildInstalledTypesList()
|
|||||||
|
|
||||||
// Now iterate through this supertype directory and add
|
// Now iterate through this supertype directory and add
|
||||||
// all of its subtypes
|
// all of its subtypes
|
||||||
BDirectory dir;
|
DatabaseDirectory dir;
|
||||||
if (dir.SetTo(&entry) == B_OK) {
|
if (dir.Init(supertype) == B_OK) {
|
||||||
dir.Rewind();
|
dir.Rewind();
|
||||||
while (true) {
|
while (true) {
|
||||||
BEntry subEntry;
|
BEntry subEntry;
|
||||||
@@ -453,8 +457,7 @@ InstalledTypes::_BuildInstalledTypesList()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList(): "
|
DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList(): "
|
||||||
"Failed opening mime database directory '%s'\n",
|
"Failed opening mime database directory.\n"));
|
||||||
get_database_directory().c_str()));
|
|
||||||
}
|
}
|
||||||
fHaveDoneFullBuild = true;
|
fHaveDoneFullBuild = true;
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <storage_support.h>
|
#include <storage_support.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "DatabaseDirectory.h"
|
||||||
#include "MimeSnifferAddonManager.h"
|
#include "MimeSnifferAddonManager.h"
|
||||||
|
|
||||||
#define DBG(x) x
|
#define DBG(x) x
|
||||||
@@ -332,9 +333,9 @@ SnifferRules::BuildRuleList()
|
|||||||
|
|
||||||
ssize_t maxBytesNeeded = 0;
|
ssize_t maxBytesNeeded = 0;
|
||||||
ssize_t bytesNeeded = 0;
|
ssize_t bytesNeeded = 0;
|
||||||
BDirectory root;
|
DatabaseDirectory root;
|
||||||
|
|
||||||
status_t err = root.SetTo(get_database_directory().c_str());
|
status_t err = root.Init();
|
||||||
if (!err) {
|
if (!err) {
|
||||||
root.Rewind();
|
root.Rewind();
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -357,8 +358,8 @@ SnifferRules::BuildRuleList()
|
|||||||
|
|
||||||
// First, iterate through this supertype directory and process
|
// First, iterate through this supertype directory and process
|
||||||
// all of its subtypes
|
// all of its subtypes
|
||||||
BDirectory dir;
|
DatabaseDirectory dir;
|
||||||
if (dir.SetTo(&entry) == B_OK) {
|
if (dir.Init(supertype) == B_OK) {
|
||||||
dir.Rewind();
|
dir.Rewind();
|
||||||
while (true) {
|
while (true) {
|
||||||
BEntry subEntry;
|
BEntry subEntry;
|
||||||
@@ -399,8 +400,7 @@ SnifferRules::BuildRuleList()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DBG(OUT("Mime::SnifferRules::BuildRuleList(): "
|
DBG(OUT("Mime::SnifferRules::BuildRuleList(): "
|
||||||
"Failed opening mime database directory '%s'\n",
|
"Failed opening mime database directory.\n"));
|
||||||
get_database_directory().c_str()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
|||||||
@@ -10,9 +10,11 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "SupportingApps.h"
|
#include "SupportingApps.h"
|
||||||
#include <mime/database_support.h>
|
|
||||||
|
|
||||||
#include <storage_support.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
@@ -20,9 +22,11 @@
|
|||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include <new>
|
#include <mime/database_support.h>
|
||||||
#include <stdio.h>
|
#include <storage_support.h>
|
||||||
#include <iostream>
|
|
||||||
|
#include "DatabaseDirectory.h"
|
||||||
|
|
||||||
|
|
||||||
#define DBG(x) x
|
#define DBG(x) x
|
||||||
//#define DBG(x)
|
//#define DBG(x)
|
||||||
@@ -262,8 +266,8 @@ SupportingApps::BuildSupportingAppsTable()
|
|||||||
fSupportingApps.clear();
|
fSupportingApps.clear();
|
||||||
fStrandedTypes.clear();
|
fStrandedTypes.clear();
|
||||||
|
|
||||||
BDirectory dir;
|
DatabaseDirectory dir;
|
||||||
status_t status = dir.SetTo(get_application_database_directory().c_str());
|
status_t status = dir.Init("application");
|
||||||
|
|
||||||
// Build the supporting apps table based on the mime database
|
// Build the supporting apps table based on the mime database
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
|
|||||||
Reference in New Issue
Block a user