Didn't deal correctly with files containing more than one module. Fixed.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3508 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,8 +11,13 @@
|
|||||||
#include <module.h>
|
#include <module.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#ifdef TRACE
|
||||||
|
#undef TRACE
|
||||||
|
#endif
|
||||||
#define TRACE(x)
|
#define TRACE(x)
|
||||||
//#define TRACE(x) printf x
|
//#define TRACE(x) printf x
|
||||||
|
|
||||||
@@ -27,74 +32,82 @@ struct module_name_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Module
|
// ModuleAddOn
|
||||||
|
|
||||||
class Module {
|
class ModuleAddOn {
|
||||||
public:
|
public:
|
||||||
Module();
|
ModuleAddOn();
|
||||||
~Module();
|
~ModuleAddOn();
|
||||||
|
|
||||||
status_t Load(const char *name, bool isPath = false, bool init = true);
|
status_t Load(const char *path, const char *dirPath);
|
||||||
void Unload();
|
void Unload();
|
||||||
|
|
||||||
status_t Init();
|
const char *Name() { return fName.String(); }
|
||||||
status_t Uninit();
|
|
||||||
|
|
||||||
void Get();
|
void Get();
|
||||||
bool Put();
|
bool Put();
|
||||||
|
|
||||||
module_info *Info() const { return fInfo; }
|
module_info **ModuleInfos() const { return fInfos; }
|
||||||
|
module_info *FindModuleInfo(const char *name) const;
|
||||||
private:
|
|
||||||
bool _Load(const char *path, const char *name, bool isPath, bool init);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
image_id fAddOn;
|
image_id fAddOn;
|
||||||
module_info *fInfo;
|
module_info **fInfos;
|
||||||
int32 fReferenceCount;
|
int32 fReferenceCount;
|
||||||
bool fInitialized;
|
BString fName;
|
||||||
};
|
};
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
Module::Module()
|
ModuleAddOn::ModuleAddOn()
|
||||||
: fAddOn(-1),
|
: fAddOn(-1),
|
||||||
fInfo(NULL),
|
fInfos(NULL),
|
||||||
fReferenceCount(0),
|
fReferenceCount(0)
|
||||||
fInitialized(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor
|
// destructor
|
||||||
Module::~Module()
|
ModuleAddOn::~ModuleAddOn()
|
||||||
{
|
{
|
||||||
Unload();
|
Unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
status_t
|
status_t
|
||||||
Module::Load(const char *name, bool isPath, bool init)
|
ModuleAddOn::Load(const char *path, const char *dirPath)
|
||||||
{
|
{
|
||||||
TRACE(("Module::Load(): searching module `%s'...\n", name));
|
TRACE(("ModuleAddOn::Load(): searching module `%s'...\n", path));
|
||||||
Unload();
|
Unload();
|
||||||
status_t error = (name ? B_OK : B_BAD_VALUE);
|
status_t error = (path && dirPath ? B_OK : B_BAD_VALUE);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
|
// get the module dir relative path
|
||||||
|
BPath absPath;
|
||||||
|
BPath absDirPath;
|
||||||
|
if (absPath.SetTo(path, NULL, true) != B_OK
|
||||||
|
|| absDirPath.SetTo(dirPath, NULL, true) != B_OK
|
||||||
|
|| strlen(absPath.Path()) <= strlen(absDirPath.Path())) {
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
int32 dirPathLen = strlen(absDirPath.Path());
|
||||||
|
if (strncmp(absPath.Path(), absDirPath.Path(), dirPathLen)
|
||||||
|
|| absPath.Path()[dirPathLen] != '/') {
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
const char *name = absPath.Path() + dirPathLen + 1;
|
||||||
|
// load the file
|
||||||
error = B_ENTRY_NOT_FOUND;
|
error = B_ENTRY_NOT_FOUND;
|
||||||
if (isPath) {
|
BEntry entry;
|
||||||
// name is a path name: try to load it
|
if (entry.SetTo(path) == B_OK && entry.Exists()) {
|
||||||
if (_Load(name, name, isPath, init))
|
image_id image = load_add_on(path);
|
||||||
|
module_info **infos = NULL;
|
||||||
|
if (image >= 0
|
||||||
|
&& get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
|
||||||
|
(void**)&infos) == B_OK
|
||||||
|
&& infos != NULL) {
|
||||||
|
fAddOn = image;
|
||||||
|
fInfos = infos;
|
||||||
|
fName = name;
|
||||||
|
fReferenceCount = 0;
|
||||||
error = B_OK;
|
error = B_OK;
|
||||||
} else {
|
|
||||||
// name is a relative module name: search in the module dirs
|
|
||||||
for (int32 i = 0; gModuleDirs[i]; i++) {
|
|
||||||
TRACE(("Module::Load(): ...in `%s'\n", gModuleDirs[i]));
|
|
||||||
BPath path;
|
|
||||||
if (path.SetTo(gModuleDirs[i]) == B_OK
|
|
||||||
&& path.SetTo(path.Path(), name) == B_OK) {
|
|
||||||
if (_Load(path.Path(), name, isPath, init)) {
|
|
||||||
error = B_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,16 +116,83 @@ TRACE(("Module::Load(): ...in `%s'\n", gModuleDirs[i]));
|
|||||||
|
|
||||||
// Unload
|
// Unload
|
||||||
void
|
void
|
||||||
Module::Unload()
|
ModuleAddOn::Unload()
|
||||||
{
|
{
|
||||||
if (fAddOn >= 0) {
|
if (fAddOn >= 0)
|
||||||
Uninit();
|
|
||||||
unload_add_on(fAddOn);
|
unload_add_on(fAddOn);
|
||||||
}
|
|
||||||
fAddOn = -1;
|
fAddOn = -1;
|
||||||
fInfo = NULL;
|
fInfos = NULL;
|
||||||
fReferenceCount = 0;
|
fReferenceCount = 0;
|
||||||
fInitialized = false;
|
}
|
||||||
|
|
||||||
|
// Get
|
||||||
|
void
|
||||||
|
ModuleAddOn::Get()
|
||||||
|
{
|
||||||
|
if (fAddOn >= 0)
|
||||||
|
fReferenceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put
|
||||||
|
bool
|
||||||
|
ModuleAddOn::Put()
|
||||||
|
{
|
||||||
|
if (fAddOn >= 0)
|
||||||
|
fReferenceCount--;
|
||||||
|
return (fReferenceCount == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindModuleInfo
|
||||||
|
module_info *
|
||||||
|
ModuleAddOn::FindModuleInfo(const char *name) const
|
||||||
|
{
|
||||||
|
if (fInfos && name) {
|
||||||
|
for (int32 i = 0; module_info *info = fInfos[i]; i++) {
|
||||||
|
if (!strcmp(info->name, name))
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module
|
||||||
|
|
||||||
|
class Module {
|
||||||
|
public:
|
||||||
|
Module(ModuleAddOn *addon, module_info *info);
|
||||||
|
~Module();
|
||||||
|
|
||||||
|
status_t Init();
|
||||||
|
status_t Uninit();
|
||||||
|
|
||||||
|
void Get();
|
||||||
|
bool Put();
|
||||||
|
|
||||||
|
ModuleAddOn *AddOn() const { return fAddOn; }
|
||||||
|
module_info *Info() const { return fInfo; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModuleAddOn *fAddOn;
|
||||||
|
module_info *fInfo;
|
||||||
|
int32 fReferenceCount;
|
||||||
|
bool fInitialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Module::Module(ModuleAddOn *addon, module_info *info)
|
||||||
|
: fAddOn(addon),
|
||||||
|
fInfo(info),
|
||||||
|
fReferenceCount(0),
|
||||||
|
fInitialized(false)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
Module::~Module()
|
||||||
|
{
|
||||||
|
Uninit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
@@ -157,39 +237,6 @@ Module::Put()
|
|||||||
return (fReferenceCount == 0 && !(fInfo->flags & B_KEEP_LOADED));
|
return (fReferenceCount == 0 && !(fInfo->flags & B_KEEP_LOADED));
|
||||||
}
|
}
|
||||||
|
|
||||||
// _Load
|
|
||||||
bool
|
|
||||||
Module::_Load(const char *path, const char *name, bool isPath, bool init)
|
|
||||||
{
|
|
||||||
TRACE(("Module::_Load(): trying to load `%s'\n", path));
|
|
||||||
BEntry entry;
|
|
||||||
if (entry.SetTo(path) == B_OK && entry.Exists()) {
|
|
||||||
image_id image = load_add_on(path);
|
|
||||||
module_info **infos = NULL;
|
|
||||||
if (image >= 0
|
|
||||||
&& get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
|
|
||||||
(void**)&infos) == B_OK
|
|
||||||
&& infos != NULL) {
|
|
||||||
for (int32 i = 0; module_info *info = infos[i]; i++) {
|
|
||||||
if ((isPath || !strcmp(name, info->name))
|
|
||||||
&& (!init || info->std_ops(B_MODULE_INIT) == B_OK)) {
|
|
||||||
fAddOn = image;
|
|
||||||
fInfo = info;
|
|
||||||
fReferenceCount = 0;
|
|
||||||
fInitialized = init;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!isPath) {
|
|
||||||
// entry does not exist -- try loading the parent path
|
|
||||||
BPath parentPath;
|
|
||||||
if (BPath(path).GetParent(&parentPath) == B_OK)
|
|
||||||
return _Load(parentPath.Path(), name, isPath, init);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ModuleList
|
// ModuleList
|
||||||
|
|
||||||
@@ -285,11 +332,16 @@ public:
|
|||||||
status_t CloseModuleList(module_name_list *list);
|
status_t CloseModuleList(module_name_list *list);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _FindModules(BDirectory &dir, module_name_list *list);
|
void _FindModules(BDirectory &dir, const char *moduleDir,
|
||||||
|
module_name_list *list);
|
||||||
|
|
||||||
|
status_t _GetAddOn(const char *path, ModuleAddOn **addon);
|
||||||
|
void _PutAddOn(ModuleAddOn *addon);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ModuleManager fDefaultManager;
|
static ModuleManager fDefaultManager;
|
||||||
ModuleList fModules;
|
ModuleList fModules;
|
||||||
|
BObjectList<ModuleAddOn> fAddOns;
|
||||||
};
|
};
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
@@ -315,13 +367,18 @@ ModuleManager::GetModule(const char *path, module_info **infop)
|
|||||||
Module *module = fModules.FindModule(path);
|
Module *module = fModules.FindModule(path);
|
||||||
if (!module) {
|
if (!module) {
|
||||||
// module not yet loaded, try to get it
|
// module not yet loaded, try to get it
|
||||||
module = new Module;
|
// get the responsible add-on
|
||||||
error = module->Load(path);
|
ModuleAddOn *addon = NULL;
|
||||||
if (error == B_OK && !fModules.AddModule(module))
|
error = _GetAddOn(path, &addon);
|
||||||
error = B_NO_MEMORY;
|
if (error == B_OK) {
|
||||||
if (error != B_OK) {
|
// add-on found, get the module
|
||||||
delete module;
|
if (module_info *info = addon->FindModuleInfo(path)) {
|
||||||
module = NULL;
|
module = new Module(addon, info);
|
||||||
|
fModules.AddModule(module);
|
||||||
|
} else {
|
||||||
|
_PutAddOn(addon);
|
||||||
|
error = B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// "get" the module
|
// "get" the module
|
||||||
@@ -342,8 +399,10 @@ ModuleManager::PutModule(const char *path)
|
|||||||
BAutolock _lock(fModules);
|
BAutolock _lock(fModules);
|
||||||
if (Module *module = fModules.FindModule(path)) {
|
if (Module *module = fModules.FindModule(path)) {
|
||||||
if (module->Put()) {
|
if (module->Put()) {
|
||||||
|
ModuleAddOn *addon = module->AddOn();
|
||||||
fModules.RemoveModule(module);
|
fModules.RemoveModule(module);
|
||||||
delete module;
|
delete module;
|
||||||
|
_PutAddOn(addon);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
error = B_BAD_VALUE;
|
error = B_BAD_VALUE;
|
||||||
@@ -386,7 +445,7 @@ ModuleManager::OpenModuleList(const char *prefix)
|
|||||||
BDirectory dir;
|
BDirectory dir;
|
||||||
if (path.SetTo(gModuleDirs[i], prefix) == B_OK
|
if (path.SetTo(gModuleDirs[i], prefix) == B_OK
|
||||||
&& dir.SetTo(path.Path()) == B_OK) {
|
&& dir.SetTo(path.Path()) == B_OK) {
|
||||||
_FindModules(dir, list);
|
_FindModules(dir, gModuleDirs[i], list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list->it = list->names.begin();
|
list->it = list->names.begin();
|
||||||
@@ -428,21 +487,84 @@ ModuleManager::CloseModuleList(module_name_list *list)
|
|||||||
|
|
||||||
// _FindModules
|
// _FindModules
|
||||||
void
|
void
|
||||||
ModuleManager::_FindModules(BDirectory &dir, module_name_list *list)
|
ModuleManager::_FindModules(BDirectory &dir, const char *moduleDir,
|
||||||
|
module_name_list *list)
|
||||||
{
|
{
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
while (dir.GetNextEntry(&entry) == B_OK) {
|
while (dir.GetNextEntry(&entry) == B_OK) {
|
||||||
if (entry.IsFile()) {
|
if (entry.IsFile()) {
|
||||||
Module module;
|
ModuleAddOn addon;
|
||||||
BPath path;
|
BPath path;
|
||||||
if (entry.GetPath(&path) == B_OK
|
if (entry.GetPath(&path) == B_OK
|
||||||
&& module.Load(path.Path(), true, false) == B_OK) {
|
&& addon.Load(path.Path(), moduleDir) == B_OK) {
|
||||||
list->names.insert(module.Info()->name);
|
module_info **infos = addon.ModuleInfos();
|
||||||
|
for (int32 i = 0; infos[i]; i++) {
|
||||||
|
if (infos[i]->name)
|
||||||
|
list->names.insert(infos[i]->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (entry.IsDirectory()) {
|
} else if (entry.IsDirectory()) {
|
||||||
BDirectory subdir;
|
BDirectory subdir;
|
||||||
if (subdir.SetTo(&entry) == B_OK)
|
if (subdir.SetTo(&entry) == B_OK)
|
||||||
_FindModules(subdir, list);
|
_FindModules(subdir, moduleDir, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _GetAddOn
|
||||||
|
status_t
|
||||||
|
ModuleManager::_GetAddOn(const char *name, ModuleAddOn **_addon)
|
||||||
|
{
|
||||||
|
// search list first
|
||||||
|
for (int32 i = 0; ModuleAddOn *addon = fAddOns.ItemAt(i); i++) {
|
||||||
|
BString addonName(addon->Name());
|
||||||
|
addonName << "/";
|
||||||
|
if (!strcmp(name, addon->Name())
|
||||||
|
|| strncmp(addonName.String(), name, addonName.Length())) {
|
||||||
|
addon->Get();
|
||||||
|
*_addon = addon;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// not in list yet, load from disk
|
||||||
|
// iterate through module dirs
|
||||||
|
for (int32 i = 0; gModuleDirs[i]; i++) {
|
||||||
|
BPath path;
|
||||||
|
if (path.SetTo(gModuleDirs[i]) == B_OK
|
||||||
|
&& path.SetTo(path.Path(), name) == B_OK) {
|
||||||
|
BEntry entry;
|
||||||
|
for (;;) {
|
||||||
|
if (entry.SetTo(path.Path()) == B_OK && entry.Exists()) {
|
||||||
|
// found an entry: if it is a file, try to load it
|
||||||
|
if (entry.IsFile()) {
|
||||||
|
ModuleAddOn *addon = new ModuleAddOn;
|
||||||
|
if (addon->Load(path.Path(), gModuleDirs[i]) == B_OK) {
|
||||||
|
fAddOns.AddItem(addon);
|
||||||
|
addon->Get();
|
||||||
|
*_addon = addon;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
delete addon;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// chop off last path component
|
||||||
|
if (path.GetParent(&path) != B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _PutAddOn
|
||||||
|
void
|
||||||
|
ModuleManager::_PutAddOn(ModuleAddOn *addon)
|
||||||
|
{
|
||||||
|
if (addon) {
|
||||||
|
if (addon->Put()) {
|
||||||
|
fAddOns.RemoveItem(addon);
|
||||||
|
delete addon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user