| 43 | | static void Demangle(const char *name, BString &out); |
|---|
| 44 | | static void Mangle(const char *name, BString &out); |
|---|
| 45 | | static instantiation_func FindFuncInImage(BString& funcName, image_id id, |
|---|
| 46 | | status_t& err); |
|---|
| 47 | | static bool CheckSig(const char* sig, image_info& info); |
|---|
| 48 | | |
|---|
| 49 | | |
|---|
| 50 | | BArchivable::BArchivable() |
|---|
| 51 | | { |
|---|
| 52 | | } |
|---|
| 53 | | |
|---|
| 54 | | |
|---|
| 55 | | BArchivable::BArchivable(BMessage* from) |
|---|
| 56 | | { |
|---|
| 57 | | } |
|---|
| 58 | | |
|---|
| 59 | | |
|---|
| 60 | | BArchivable::~BArchivable() |
|---|
| 61 | | { |
|---|
| 62 | | } |
|---|
| 63 | | |
|---|
| 64 | | |
|---|
| 65 | | status_t |
|---|
| 66 | | BArchivable::Archive(BMessage* into, bool deep) const |
|---|
| 67 | | { |
|---|
| 68 | | if (!into) { |
|---|
| 69 | | // TODO: logging/other error reporting? |
|---|
| 70 | | return B_BAD_VALUE; |
|---|
| 71 | | } |
|---|
| 72 | | |
|---|
| 73 | | BString name; |
|---|
| 74 | | Demangle(typeid(*this).name(), name); |
|---|
| 75 | | |
|---|
| 76 | | return into->AddString(B_CLASS_FIELD, name); |
|---|
| 77 | | } |
|---|
| 78 | | |
|---|
| 79 | | |
|---|
| 80 | | BArchivable* |
|---|
| 81 | | BArchivable::Instantiate(BMessage* from) |
|---|
| 82 | | { |
|---|
| 83 | | debugger("Can't create a plain BArchivable object"); |
|---|
| 84 | | return NULL; |
|---|
| 85 | | } |
|---|
| 86 | | |
|---|
| 87 | | |
|---|
| 88 | | status_t |
|---|
| 89 | | BArchivable::Perform(perform_code d, void* arg) |
|---|
| 90 | | { |
|---|
| 91 | | // TODO: Check against original |
|---|
| 92 | | return B_ERROR; |
|---|
| 93 | | } |
|---|
| 94 | | |
|---|
| 95 | | |
|---|
| 96 | | void BArchivable::_ReservedArchivable1() {} |
|---|
| 97 | | void BArchivable::_ReservedArchivable2() {} |
|---|
| 98 | | void BArchivable::_ReservedArchivable3() {} |
|---|
| 99 | | |
|---|
| 100 | | |
|---|
| 101 | | // #pragma mark - |
|---|
| 102 | | |
|---|
| 103 | | |
|---|
| 104 | | void |
|---|
| 105 | | BuildFuncName(const char* className, BString& funcName) |
|---|
| 106 | | { |
|---|
| 107 | | funcName = ""; |
|---|
| 108 | | |
|---|
| 109 | | // This is what we're after: |
|---|
| 110 | | // Instantiate__Q28OpenBeOS11BArchivableP8BMessage |
|---|
| 111 | | Mangle(className, funcName); |
|---|
| 112 | | #if __GNUC__ >= 4 |
|---|
| 113 | | funcName.Prepend("_ZN"); |
|---|
| 114 | | funcName.Append("11InstantiateE"); |
|---|
| 115 | | #else |
|---|
| 116 | | funcName.Prepend("Instantiate__"); |
|---|
| 117 | | #endif |
|---|
| 118 | | funcName.Append("P8BMessage"); |
|---|
| 119 | | } |
|---|
| 120 | | |
|---|
| 121 | | |
|---|
| 122 | | BArchivable* |
|---|
| 123 | | instantiate_object(BMessage* archive, image_id* id) |
|---|
| 124 | | { |
|---|
| 125 | | // Check our params |
|---|
| 126 | | if (id) |
|---|
| 127 | | *id = B_BAD_VALUE; |
|---|
| 128 | | |
|---|
| 129 | | if (!archive) { |
|---|
| 130 | | // TODO: extended error handling |
|---|
| 131 | | errno = B_BAD_VALUE; |
|---|
| 132 | | syslog(LOG_ERR, "instantiate_object failed: NULL BMessage argument"); |
|---|
| 133 | | return NULL; |
|---|
| 134 | | } |
|---|
| 135 | | |
|---|
| 136 | | // Get class name from archive |
|---|
| 137 | | const char* name = NULL; |
|---|
| 138 | | status_t err = archive->FindString(B_CLASS_FIELD, &name); |
|---|
| 139 | | if (err) { |
|---|
| 140 | | // TODO: extended error handling |
|---|
| 141 | | syslog(LOG_ERR, "instantiate_object failed: Failed to find an entry " |
|---|
| 142 | | "defining the class name (%s).", strerror(err)); |
|---|
| 143 | | return NULL; |
|---|
| 144 | | } |
|---|
| 145 | | |
|---|
| 146 | | // Get sig from archive |
|---|
| 147 | | const char* sig = NULL; |
|---|
| 148 | | bool hasSig = (archive->FindString(B_ADD_ON_FIELD, &sig) == B_OK); |
|---|
| 149 | | |
|---|
| 150 | | instantiation_func iFunc = find_instantiation_func(name, sig); |
|---|
| 151 | | |
|---|
| 152 | | // if find_instantiation_func() can't locate Class::Instantiate() |
|---|
| 153 | | // and a signature was specified |
|---|
| 154 | | if (!iFunc && hasSig) { |
|---|
| 155 | | // use BRoster::FindApp() to locate an app or add-on with the symbol |
|---|
| 156 | | BRoster Roster; |
|---|
| 157 | | entry_ref ref; |
|---|
| 158 | | err = Roster.FindApp(sig, &ref); |
|---|
| 159 | | |
|---|
| 160 | | // if an entry_ref is obtained |
|---|
| 161 | | BEntry entry; |
|---|
| 162 | | if (!err) |
|---|
| 163 | | err = entry.SetTo(&ref); |
|---|
| 164 | | |
|---|
| 165 | | if (err) { |
|---|
| 166 | | syslog(LOG_ERR, "instantiate_object failed: Error finding app " |
|---|
| 167 | | "with signature \"%s\" (%s)", sig, strerror(err)); |
|---|
| 168 | | } |
|---|
| 169 | | |
|---|
| 170 | | if (!err) { |
|---|
| 171 | | BPath path; |
|---|
| 172 | | err = entry.GetPath(&path); |
|---|
| 173 | | if (!err) { |
|---|
| 174 | | // load the app/add-on |
|---|
| 175 | | image_id addOn = load_add_on(path.Path()); |
|---|
| 176 | | if (addOn < 0) { |
|---|
| 177 | | // TODO: extended error handling |
|---|
| 178 | | syslog(LOG_ERR, "instantiate_object failed: Could not load " |
|---|
| 179 | | "add-on %s: %s.", path.Path(), strerror(addOn)); |
|---|
| 180 | | return NULL; |
|---|
| 181 | | } |
|---|
| 182 | | |
|---|
| 183 | | // Save the image_id |
|---|
| 184 | | if (id) |
|---|
| 185 | | *id = addOn; |
|---|
| 186 | | |
|---|
| 187 | | BString funcName; |
|---|
| 188 | | BuildFuncName(name, funcName); |
|---|
| 189 | | |
|---|
| 190 | | iFunc = FindFuncInImage(funcName, addOn, err); |
|---|
| 191 | | if (!iFunc) { |
|---|
| 192 | | syslog(LOG_ERR, "instantiate_object failed: Failed to find exported " |
|---|
| 193 | | "Instantiate static function for class %s.", name); |
|---|
| 194 | | } |
|---|
| 195 | | } |
|---|
| 196 | | } |
|---|
| 197 | | } else if (!iFunc) { |
|---|
| 198 | | syslog(LOG_ERR, "instantiate_object failed: No signature specified " |
|---|
| 199 | | "in archive, looking for class \"%s\".", name); |
|---|
| 200 | | errno = B_BAD_VALUE; |
|---|
| 201 | | } |
|---|
| 202 | | |
|---|
| 203 | | if (err) { |
|---|
| 204 | | // TODO: extended error handling |
|---|
| 205 | | syslog(LOG_ERR, "instantiate_object failed: %s (%x)", |
|---|
| 206 | | strerror(err), err); |
|---|
| 207 | | errno = err; |
|---|
| 208 | | return NULL; |
|---|
| 209 | | } |
|---|
| 210 | | |
|---|
| 211 | | // if Class::Instantiate(BMessage*) was found |
|---|
| 212 | | if (iFunc) { |
|---|
| 213 | | // use to create and return an object instance |
|---|
| 214 | | return iFunc(archive); |
|---|
| 215 | | } |
|---|
| 216 | | |
|---|
| 217 | | return NULL; |
|---|
| 218 | | } |
|---|
| 219 | | |
|---|
| 220 | | |
|---|
| 221 | | BArchivable* |
|---|
| 222 | | instantiate_object(BMessage* from) |
|---|
| 223 | | { |
|---|
| 224 | | return instantiate_object(from, NULL); |
|---|
| 225 | | } |
|---|
| 226 | | |
|---|
| 227 | | |
|---|
| 228 | | bool |
|---|
| 229 | | validate_instantiation(BMessage* from, const char* class_name) |
|---|
| 230 | | { |
|---|
| 231 | | errno = B_OK; |
|---|
| 232 | | |
|---|
| 233 | | // Make sure our params are kosher -- original skimped here =P |
|---|
| 234 | | if (!from) { |
|---|
| 235 | | // Not standard; Be implementation has a segment |
|---|
| 236 | | // violation on this error mode |
|---|
| 237 | | errno = B_BAD_VALUE; |
|---|
| 238 | | |
|---|
| 239 | | return false; |
|---|
| 240 | | } |
|---|
| 241 | | |
|---|
| 242 | | status_t err = B_OK; |
|---|
| 243 | | const char* data; |
|---|
| 244 | | for (int32 index = 0; err == B_OK; ++index) { |
|---|
| 245 | | err = from->FindString(B_CLASS_FIELD, index, &data); |
|---|
| 246 | | if (!err && strcmp(data, class_name) == 0) { |
|---|
| 247 | | return true; |
|---|
| 248 | | } |
|---|
| 249 | | } |
|---|
| 250 | | |
|---|
| 251 | | errno = B_MISMATCHED_VALUES; |
|---|
| 252 | | syslog(LOG_ERR, "validate_instantiation failed on class %s.", class_name); |
|---|
| 253 | | |
|---|
| 254 | | return false; |
|---|
| 255 | | } |
|---|
| 256 | | |
|---|
| 257 | | |
|---|
| 258 | | instantiation_func |
|---|
| 259 | | find_instantiation_func(const char* class_name, const char* sig) |
|---|
| 260 | | { |
|---|
| 261 | | errno = B_OK; |
|---|
| 262 | | if (!class_name) { |
|---|
| 263 | | errno = B_BAD_VALUE; |
|---|
| 264 | | return NULL; |
|---|
| 265 | | } |
|---|
| 266 | | |
|---|
| 267 | | instantiation_func theFunc = NULL; |
|---|
| 268 | | BString funcName; |
|---|
| 269 | | |
|---|
| 270 | | BuildFuncName(class_name, funcName); |
|---|
| 271 | | |
|---|
| 272 | | //printf("find_instantiation_func() - looking for '%s'\n", funcName.String()); |
|---|
| 273 | | |
|---|
| 274 | | thread_id tid = find_thread(NULL); |
|---|
| 275 | | thread_info ti; |
|---|
| 276 | | status_t err = get_thread_info(tid, &ti); |
|---|
| 277 | | if (!err) { |
|---|
| 278 | | // for each image_id in team_id |
|---|
| 279 | | image_info info; |
|---|
| 280 | | int32 cookie = 0; |
|---|
| 281 | | while (!theFunc && (get_next_image_info(ti.team, &cookie, &info) == B_OK)) { |
|---|
| 282 | | theFunc = FindFuncInImage(funcName, info.id, err); |
|---|
| 283 | | } |
|---|
| 284 | | |
|---|
| 285 | | if (theFunc && !CheckSig(sig, info)) { |
|---|
| 286 | | // TODO: extended error handling |
|---|
| 287 | | theFunc = NULL; |
|---|
| 288 | | } |
|---|
| 289 | | } |
|---|
| 290 | | |
|---|
| 291 | | //printf("find_instantiation_func(): %p\n", theFunc); |
|---|
| 292 | | |
|---|
| 293 | | return theFunc; |
|---|
| 294 | | } |
|---|
| 295 | | |
|---|
| 296 | | |
|---|
| 297 | | instantiation_func |
|---|
| 298 | | find_instantiation_func(const char* class_name) |
|---|
| 299 | | { |
|---|
| 300 | | return find_instantiation_func(class_name, NULL); |
|---|
| 301 | | } |
|---|
| 302 | | |
|---|
| 303 | | |
|---|
| 304 | | instantiation_func |
|---|
| 305 | | find_instantiation_func(BMessage* archive_data) |
|---|
| 306 | | { |
|---|
| 307 | | errno = B_OK; |
|---|
| 308 | | |
|---|
| 309 | | if (!archive_data) { |
|---|
| 310 | | // TODO: extended error handling |
|---|
| 311 | | errno = B_BAD_VALUE; |
|---|
| 312 | | return NULL; |
|---|
| 313 | | } |
|---|
| 314 | | |
|---|
| 315 | | const char* name = NULL; |
|---|
| 316 | | const char* sig = NULL; |
|---|
| 317 | | status_t err; |
|---|
| 318 | | |
|---|
| 319 | | err = archive_data->FindString(B_CLASS_FIELD, &name); |
|---|
| 320 | | if (err) { |
|---|
| 321 | | // TODO: extended error handling |
|---|
| 322 | | return NULL; |
|---|
| 323 | | } |
|---|
| 324 | | |
|---|
| 325 | | err = archive_data->FindString(B_ADD_ON_FIELD, &sig); |
|---|
| 326 | | |
|---|
| 327 | | return find_instantiation_func(name, sig); |
|---|
| 328 | | } |
|---|
| 329 | | |
|---|
| 330 | | |
|---|
| 331 | | // #pragma mark - |
|---|
| 332 | | |
|---|
| 333 | | |
|---|
| 334 | | int |
|---|
| | 43 | |
|---|
| | 44 | |
|---|
| | 45 | static int |
|---|
| | 144 | static void |
|---|
| | 145 | build_function_name(const BString& className, BString& funcName) |
|---|
| | 146 | { |
|---|
| | 147 | funcName = ""; |
|---|
| | 148 | |
|---|
| | 149 | // This is what we're after: |
|---|
| | 150 | // Instantiate__Q28OpenBeOS11BArchivableP8BMessage |
|---|
| | 151 | mangle_class_name(className.String(), funcName); |
|---|
| | 152 | #if __GNUC__ >= 4 |
|---|
| | 153 | funcName.Prepend("_ZN"); |
|---|
| | 154 | funcName.Append("11InstantiateE"); |
|---|
| | 155 | #else |
|---|
| | 156 | funcName.Prepend("Instantiate__"); |
|---|
| | 157 | #endif |
|---|
| | 158 | funcName.Append("P8BMessage"); |
|---|
| | 159 | } |
|---|
| | 160 | |
|---|
| | 161 | |
|---|
| | 162 | static bool |
|---|
| | 163 | add_private_namespace(BString& name) |
|---|
| | 164 | { |
|---|
| | 165 | if (name.Compare("_", 1) != 0) |
|---|
| | 166 | return false; |
|---|
| | 167 | |
|---|
| | 168 | name.Prepend("BPrivate::"); |
|---|
| | 169 | return true; |
|---|
| | 170 | } |
|---|
| | 171 | |
|---|
| | 172 | |
|---|
| | 173 | static instantiation_func |
|---|
| | 174 | find_function_in_image(BString& funcName, image_id id, status_t& err) |
|---|
| | 175 | { |
|---|
| | 176 | instantiation_func instantiationFunc = NULL; |
|---|
| | 177 | err = get_image_symbol(id, funcName.String(), B_SYMBOL_TYPE_TEXT, |
|---|
| | 178 | (void**)&instantiationFunc); |
|---|
| | 179 | if (err != B_OK) |
|---|
| | 180 | return NULL; |
|---|
| | 181 | |
|---|
| | 182 | return instantiationFunc; |
|---|
| | 183 | } |
|---|
| | 184 | |
|---|
| | 185 | |
|---|
| | 186 | static status_t |
|---|
| | 187 | check_signature(const char* signature, image_info& info) |
|---|
| | 188 | { |
|---|
| | 189 | if (signature == NULL) { |
|---|
| | 190 | // If it wasn't specified, anything "matches" |
|---|
| | 191 | return B_OK; |
|---|
| | 192 | } |
|---|
| | 193 | |
|---|
| | 194 | // Get image signature |
|---|
| | 195 | BFile file(info.name, B_READ_ONLY); |
|---|
| | 196 | status_t err = file.InitCheck(); |
|---|
| | 197 | if (err != B_OK) |
|---|
| | 198 | return err; |
|---|
| | 199 | |
|---|
| | 200 | char imageSignature[B_MIME_TYPE_LENGTH]; |
|---|
| | 201 | BAppFileInfo appFileInfo(&file); |
|---|
| | 202 | err = appFileInfo.GetSignature(imageSignature); |
|---|
| | 203 | if (err != B_OK) { |
|---|
| | 204 | syslog(LOG_ERR, "instantiate_object - couldn't get mime sig for %s", |
|---|
| | 205 | info.name); |
|---|
| | 206 | return err; |
|---|
| | 207 | } |
|---|
| | 208 | |
|---|
| | 209 | if (strcmp(signature, imageSignature)) |
|---|
| | 210 | return B_MISMATCHED_VALUES; |
|---|
| | 211 | |
|---|
| | 212 | return B_OK; |
|---|
| | 213 | } |
|---|
| | 214 | |
|---|
| | 215 | |
|---|
| | 216 | // #pragma mark - |
|---|
| | 217 | |
|---|
| | 218 | |
|---|
| | 219 | BArchivable::BArchivable() |
|---|
| | 220 | { |
|---|
| | 221 | } |
|---|
| | 222 | |
|---|
| | 223 | |
|---|
| | 224 | BArchivable::BArchivable(BMessage* from) |
|---|
| | 225 | { |
|---|
| | 226 | } |
|---|
| | 227 | |
|---|
| | 228 | |
|---|
| | 229 | BArchivable::~BArchivable() |
|---|
| | 230 | { |
|---|
| | 231 | } |
|---|
| | 232 | |
|---|
| | 233 | |
|---|
| | 234 | status_t |
|---|
| | 235 | BArchivable::Archive(BMessage* into, bool deep) const |
|---|
| | 236 | { |
|---|
| | 237 | if (!into) { |
|---|
| | 238 | // TODO: logging/other error reporting? |
|---|
| | 239 | return B_BAD_VALUE; |
|---|
| | 240 | } |
|---|
| | 241 | |
|---|
| | 242 | BString name; |
|---|
| | 243 | demangle_class_name(typeid(*this).name(), name); |
|---|
| | 244 | |
|---|
| | 245 | return into->AddString(B_CLASS_FIELD, name); |
|---|
| | 246 | } |
|---|
| | 247 | |
|---|
| | 248 | |
|---|
| | 249 | BArchivable* |
|---|
| | 250 | BArchivable::Instantiate(BMessage* from) |
|---|
| | 251 | { |
|---|
| | 252 | debugger("Can't create a plain BArchivable object"); |
|---|
| | 253 | return NULL; |
|---|
| | 254 | } |
|---|
| | 255 | |
|---|
| | 256 | |
|---|
| | 257 | status_t |
|---|
| | 258 | BArchivable::Perform(perform_code d, void* arg) |
|---|
| | 259 | { |
|---|
| | 260 | // TODO: Check against original |
|---|
| | 261 | return B_ERROR; |
|---|
| | 262 | } |
|---|
| | 263 | |
|---|
| | 264 | |
|---|
| | 265 | void BArchivable::_ReservedArchivable1() {} |
|---|
| | 266 | void BArchivable::_ReservedArchivable2() {} |
|---|
| | 267 | void BArchivable::_ReservedArchivable3() {} |
|---|
| | 268 | |
|---|
| | 269 | |
|---|
| | 270 | // #pragma mark - |
|---|
| | 271 | |
|---|
| | 272 | |
|---|
| | 273 | BArchivable* |
|---|
| | 274 | instantiate_object(BMessage* archive, image_id* _id) |
|---|
| | 275 | { |
|---|
| | 276 | status_t statusBuffer; |
|---|
| | 277 | status_t* status = &statusBuffer; |
|---|
| | 278 | if (_id != NULL) |
|---|
| | 279 | status = _id; |
|---|
| | 280 | |
|---|
| | 281 | // Check our params |
|---|
| | 282 | if (archive == NULL) { |
|---|
| | 283 | syslog(LOG_ERR, "instantiate_object failed: NULL BMessage argument"); |
|---|
| | 284 | *status = B_BAD_VALUE; |
|---|
| | 285 | return NULL; |
|---|
| | 286 | } |
|---|
| | 287 | |
|---|
| | 288 | // Get class name from archive |
|---|
| | 289 | const char* className = NULL; |
|---|
| | 290 | status_t err = archive->FindString(B_CLASS_FIELD, &className); |
|---|
| | 291 | if (err) { |
|---|
| | 292 | syslog(LOG_ERR, "instantiate_object failed: Failed to find an entry " |
|---|
| | 293 | "defining the class name (%s).", strerror(err)); |
|---|
| | 294 | *status = B_BAD_VALUE; |
|---|
| | 295 | return NULL; |
|---|
| | 296 | } |
|---|
| | 297 | |
|---|
| | 298 | // Get sig from archive |
|---|
| | 299 | const char* signature = NULL; |
|---|
| | 300 | bool hasSignature = archive->FindString(B_ADD_ON_FIELD, &signature) == B_OK; |
|---|
| | 301 | |
|---|
| | 302 | instantiation_func instantiationFunc = find_instantiation_func(className, |
|---|
| | 303 | signature); |
|---|
| | 304 | |
|---|
| | 305 | // if find_instantiation_func() can't locate Class::Instantiate() |
|---|
| | 306 | // and a signature was specified |
|---|
| | 307 | if (!instantiationFunc && hasSignature) { |
|---|
| | 308 | // use BRoster::FindApp() to locate an app or add-on with the symbol |
|---|
| | 309 | BRoster Roster; |
|---|
| | 310 | entry_ref ref; |
|---|
| | 311 | err = Roster.FindApp(signature, &ref); |
|---|
| | 312 | |
|---|
| | 313 | // if an entry_ref is obtained |
|---|
| | 314 | BEntry entry; |
|---|
| | 315 | if (err == B_OK) |
|---|
| | 316 | err = entry.SetTo(&ref); |
|---|
| | 317 | |
|---|
| | 318 | BPath path; |
|---|
| | 319 | if (err == B_OK) |
|---|
| | 320 | err = entry.GetPath(&path); |
|---|
| | 321 | |
|---|
| | 322 | if (err != B_OK) { |
|---|
| | 323 | syslog(LOG_ERR, "instantiate_object failed: Error finding app " |
|---|
| | 324 | "with signature \"%s\" (%s)", signature, strerror(err)); |
|---|
| | 325 | *status = err; |
|---|
| | 326 | return NULL; |
|---|
| | 327 | } |
|---|
| | 328 | |
|---|
| | 329 | // load the app/add-on |
|---|
| | 330 | image_id addOn = load_add_on(path.Path()); |
|---|
| | 331 | if (addOn < B_OK) { |
|---|
| | 332 | syslog(LOG_ERR, "instantiate_object failed: Could not load " |
|---|
| | 333 | "add-on %s: %s.", path.Path(), strerror(addOn)); |
|---|
| | 334 | *status = addOn; |
|---|
| | 335 | return NULL; |
|---|
| | 336 | } |
|---|
| | 337 | |
|---|
| | 338 | // Save the image_id |
|---|
| | 339 | if (_id != NULL) |
|---|
| | 340 | *_id = addOn; |
|---|
| | 341 | |
|---|
| | 342 | BString name = className; |
|---|
| | 343 | for (int32 pass = 0; pass < 2; pass++) { |
|---|
| | 344 | BString funcName; |
|---|
| | 345 | build_function_name(name, funcName); |
|---|
| | 346 | |
|---|
| | 347 | instantiationFunc = find_function_in_image(funcName, addOn, err); |
|---|
| | 348 | if (instantiationFunc != NULL) |
|---|
| | 349 | break; |
|---|
| | 350 | |
|---|
| | 351 | // Check if we have a private class, and add the BPrivate namespace |
|---|
| | 352 | // (for backwards compatibility) |
|---|
| | 353 | if (!add_private_namespace(name)) |
|---|
| | 354 | break; |
|---|
| | 355 | } |
|---|
| | 356 | |
|---|
| | 357 | if (instantiationFunc == NULL) { |
|---|
| | 358 | syslog(LOG_ERR, "instantiate_object failed: Failed to find exported " |
|---|
| | 359 | "Instantiate static function for class %s.", className); |
|---|
| | 360 | *status = B_NAME_NOT_FOUND; |
|---|
| | 361 | return NULL; |
|---|
| | 362 | } |
|---|
| | 363 | } else if (instantiationFunc == NULL) { |
|---|
| | 364 | syslog(LOG_ERR, "instantiate_object failed: No signature specified " |
|---|
| | 365 | "in archive, looking for class \"%s\".", className); |
|---|
| | 366 | *status = B_NAME_NOT_FOUND; |
|---|
| | 367 | return NULL; |
|---|
| | 368 | } |
|---|
| | 369 | |
|---|
| | 370 | // if Class::Instantiate(BMessage*) was found |
|---|
| | 371 | if (instantiationFunc != NULL) { |
|---|
| | 372 | // use to create and return an object instance |
|---|
| | 373 | return instantiationFunc(archive); |
|---|
| | 374 | } |
|---|
| | 375 | |
|---|
| | 376 | return NULL; |
|---|
| | 377 | } |
|---|
| | 378 | |
|---|
| | 379 | |
|---|
| | 380 | BArchivable* |
|---|
| | 381 | instantiate_object(BMessage* from) |
|---|
| | 382 | { |
|---|
| | 383 | return instantiate_object(from, NULL); |
|---|
| | 384 | } |
|---|
| | 385 | |
|---|
| | 386 | |
|---|
| | 387 | bool |
|---|
| | 388 | validate_instantiation(BMessage* from, const char* className) |
|---|
| | 389 | { |
|---|
| | 390 | // Make sure our params are kosher -- original skimped here =P |
|---|
| | 391 | if (!from) { |
|---|
| | 392 | errno = B_BAD_VALUE; |
|---|
| | 393 | return false; |
|---|
| | 394 | } |
|---|
| | 395 | |
|---|
| | 396 | const char* data; |
|---|
| | 397 | for (int32 index = 0; from->FindString(B_CLASS_FIELD, index, &data) == B_OK; |
|---|
| | 398 | ++index) { |
|---|
| | 399 | if (!strcmp(data, className)) |
|---|
| | 400 | return true; |
|---|
| | 401 | } |
|---|
| | 402 | |
|---|
| | 403 | errno = B_MISMATCHED_VALUES; |
|---|
| | 404 | syslog(LOG_ERR, "validate_instantiation failed on class %s.", className); |
|---|
| | 405 | |
|---|
| | 406 | return false; |
|---|
| | 407 | } |
|---|
| | 408 | |
|---|
| | 409 | |
|---|
| 434 | | FindFuncInImage(BString& funcName, image_id id, status_t& err) |
|---|
| 435 | | { |
|---|
| 436 | | err = B_OK; |
|---|
| 437 | | instantiation_func theFunc = NULL; |
|---|
| 438 | | |
|---|
| 439 | | // Don't need to do it this way ... |
|---|
| 440 | | #if 0 |
|---|
| 441 | | char foundFuncName[FUNC_NAME_LEN]; |
|---|
| 442 | | int32 symbolType; |
|---|
| 443 | | int32 funcNameLen; |
|---|
| 444 | | |
|---|
| 445 | | // for each B_SYMBOL_TYPE_TEXT in image_id |
|---|
| 446 | | for (int32 i = 0; !err; ++i) { |
|---|
| 447 | | funcNameLen = FUNC_NAME_LEN; |
|---|
| 448 | | err = get_nth_image_symbol(id, i, foundFuncName, &funcNameLen, |
|---|
| 449 | | &symbolType, (void**)&theFunc); |
|---|
| 450 | | |
|---|
| 451 | | if (!err && symbolType == B_SYMBOL_TYPE_TEXT) { |
|---|
| 452 | | // try to match Class::Instantiate(BMessage*) signature |
|---|
| 453 | | if (funcName.ICompare(foundFuncName, funcNameLen) == 0) |
|---|
| 454 | | break; |
|---|
| 455 | | else |
|---|
| 456 | | theFunc = NULL; |
|---|
| 457 | | } |
|---|
| 458 | | } |
|---|
| 459 | | #endif |
|---|
| 460 | | |
|---|
| 461 | | err = get_image_symbol(id, funcName.String(), B_SYMBOL_TYPE_TEXT, |
|---|
| 462 | | (void**)&theFunc); |
|---|
| 463 | | |
|---|
| 464 | | if (err) { |
|---|
| 465 | | // TODO: error handling |
|---|
| 466 | | theFunc = NULL; |
|---|
| 467 | | } |
|---|
| 468 | | |
|---|
| 469 | | return theFunc; |
|---|
| 470 | | } |
|---|
| 471 | | |
|---|
| 472 | | |
|---|
| 473 | | bool |
|---|
| 474 | | CheckSig(const char* sig, image_info& info) |
|---|
| 475 | | { |
|---|
| 476 | | if (!sig) { |
|---|
| 477 | | // If it wasn't specified, anything "matches" |
|---|
| 478 | | return true; |
|---|
| 479 | | } |
|---|
| 480 | | |
|---|
| 481 | | status_t err = B_OK; |
|---|
| 482 | | |
|---|
| 483 | | // Get image signature |
|---|
| 484 | | BFile ImageFile(info.name, B_READ_ONLY); |
|---|
| 485 | | err = ImageFile.InitCheck(); |
|---|
| 486 | | if (err) { |
|---|
| 487 | | // TODO: extended error handling |
|---|
| 488 | | return false; |
|---|
| 489 | | } |
|---|
| 490 | | |
|---|
| 491 | | char imageSig[B_MIME_TYPE_LENGTH]; |
|---|
| 492 | | BAppFileInfo AFI(&ImageFile); |
|---|
| 493 | | err = AFI.GetSignature(imageSig); |
|---|
| 494 | | if (err) { |
|---|
| 495 | | // TODO: extended error handling |
|---|
| 496 | | syslog(LOG_ERR, "instantiate_object - couldn't get mime sig for %s", |
|---|
| 497 | | info.name); |
|---|
| 498 | | return false; |
|---|
| 499 | | } |
|---|
| 500 | | |
|---|
| 501 | | return strcmp(sig, imageSig) == 0; |
|---|
| 502 | | } |
|---|
| 503 | | |
|---|
| | 411 | find_instantiation_func(const char* className, const char* signature) |
|---|
| | 412 | { |
|---|
| | 413 | if (className == NULL) { |
|---|
| | 414 | errno = B_BAD_VALUE; |
|---|
| | 415 | return NULL; |
|---|
| | 416 | } |
|---|
| | 417 | |
|---|
| | 418 | thread_info threadInfo; |
|---|
| | 419 | status_t err = get_thread_info(find_thread(NULL), &threadInfo); |
|---|
| | 420 | if (err != B_OK) { |
|---|
| | 421 | errno = err; |
|---|
| | 422 | return NULL; |
|---|
| | 423 | } |
|---|
| | 424 | |
|---|
| | 425 | instantiation_func instantiationFunc = NULL; |
|---|
| | 426 | image_info imageInfo; |
|---|
| | 427 | |
|---|
| | 428 | BString name = className; |
|---|
| | 429 | for (int32 pass = 0; pass < 2; pass++) { |
|---|
| | 430 | BString funcName; |
|---|
| | 431 | build_function_name(name, funcName); |
|---|
| | 432 | |
|---|
| | 433 | // for each image_id in team_id |
|---|
| | 434 | int32 cookie = 0; |
|---|
| | 435 | while (instantiationFunc == NULL |
|---|
| | 436 | && get_next_image_info(threadInfo.team, &cookie, &imageInfo) |
|---|
| | 437 | == B_OK) { |
|---|
| | 438 | instantiationFunc = find_function_in_image(funcName, imageInfo.id, |
|---|
| | 439 | err); |
|---|
| | 440 | } |
|---|
| | 441 | if (instantiationFunc != NULL) |
|---|
| | 442 | break; |
|---|
| | 443 | |
|---|
| | 444 | // Check if we have a private class, and add the BPrivate namespace |
|---|
| | 445 | // (for backwards compatibility) |
|---|
| | 446 | if (!add_private_namespace(name)) |
|---|
| | 447 | break; |
|---|
| | 448 | } |
|---|
| | 449 | |
|---|
| | 450 | if (instantiationFunc != NULL |
|---|
| | 451 | && check_signature(signature, imageInfo) != B_OK) |
|---|
| | 452 | return NULL; |
|---|
| | 453 | |
|---|
| | 454 | return instantiationFunc; |
|---|
| | 455 | } |
|---|
| | 456 | |
|---|
| | 457 | |
|---|
| | 458 | instantiation_func |
|---|
| | 459 | find_instantiation_func(const char* className) |
|---|
| | 460 | { |
|---|
| | 461 | return find_instantiation_func(className, NULL); |
|---|
| | 462 | } |
|---|
| | 463 | |
|---|
| | 464 | |
|---|
| | 465 | instantiation_func |
|---|
| | 466 | find_instantiation_func(BMessage* archive) |
|---|
| | 467 | { |
|---|
| | 468 | if (archive == NULL) { |
|---|
| | 469 | errno = B_BAD_VALUE; |
|---|
| | 470 | return NULL; |
|---|
| | 471 | } |
|---|
| | 472 | |
|---|
| | 473 | const char* name = NULL; |
|---|
| | 474 | const char* signature = NULL; |
|---|
| | 475 | if (archive->FindString(B_CLASS_FIELD, &name) != B_OK |
|---|
| | 476 | || archive->FindString(B_ADD_ON_FIELD, &signature)) { |
|---|
| | 477 | errno = B_BAD_VALUE; |
|---|
| | 478 | return NULL; |
|---|
| | 479 | } |
|---|
| | 480 | |
|---|
| | 481 | return find_instantiation_func(name, signature); |
|---|
| | 482 | } |
|---|
| | 483 | |
|---|