diff --git a/vm/factor.cpp b/vm/factor.cpp index bcb102b6e2..dd9be27774 100755 --- a/vm/factor.cpp +++ b/vm/factor.cpp @@ -10,6 +10,7 @@ void init_globals() void factor_vm::default_parameters(vm_parameters *p) { + p->embedded_image = false; p->image_path = NULL; p->datastack_size = 32 * sizeof(cell); @@ -118,7 +119,15 @@ void factor_vm::init_factor(vm_parameters *p) p->executable_path = executable_path; if(p->image_path == NULL) - p->image_path = default_image_path(); + { + if (embedded_image_p()) + { + p->embedded_image = true; + p->image_path = p->executable_path; + } + else + p->image_path = default_image_path(); + } srand((unsigned int)nano_count()); init_ffi(); diff --git a/vm/image.cpp b/vm/image.cpp index d1851d6b32..d8c9f9f470 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -219,11 +219,37 @@ void factor_vm::fixup_code(cell data_offset, cell code_offset) code->allocator->iterate(updater,fixup); } +FILE* factor_vm::open_image(vm_parameters *p) +{ + if (p->embedded_image) + { + FILE *file = OPEN_READ(p->executable_path); + if (file == NULL) + { + std::cout << "Cannot open embedded image" << std::endl; + std::cout << strerror(errno) << std::endl; + exit(1); + } + safe_fseek(file, -sizeof(embedded_image_footer), SEEK_END); + embedded_image_footer footer; + safe_fread(&footer, sizeof(embedded_image_footer), 1, file); + if (footer.magic != image_magic) + { + std::cout << "No embedded image" << std::endl; + exit(1); + } + safe_fseek(file, footer.image_offset, SEEK_SET); + return file; + } + else + return OPEN_READ(p->image_path); +} + /* Read an image file from disk, only done once during startup */ /* This function also initializes the data and code heaps */ void factor_vm::load_image(vm_parameters *p) { - FILE *file = OPEN_READ(p->image_path); + FILE *file = open_image(p); if(file == NULL) { std::cout << "Cannot open image file: " << p->image_path << std::endl; @@ -339,4 +365,19 @@ void factor_vm::primitive_save_image_and_exit() exit(1); } +bool factor_vm::embedded_image_p() +{ + const vm_char *vm_path = vm_executable_path(); + if (!vm_path) + return false; + FILE *file = OPEN_READ(vm_path); + if (!file) + return false; + safe_fseek(file, -sizeof(embedded_image_footer), SEEK_END); + embedded_image_footer footer; + safe_fread(&footer, sizeof(embedded_image_footer), 1, file); + fclose(file); + return footer.magic == image_magic; +} + } diff --git a/vm/image.hpp b/vm/image.hpp index 40ffa28d11..21cf8944d1 100755 --- a/vm/image.hpp +++ b/vm/image.hpp @@ -4,6 +4,11 @@ namespace factor static const cell image_magic = 0x0f0e0d0c; static const cell image_version = 4; +struct embedded_image_footer { + cell magic; + cell image_offset; +}; + struct image_header { cell magic; cell version; @@ -28,6 +33,7 @@ struct image_header { }; struct vm_parameters { + bool embedded_image; const vm_char *image_path; const vm_char *executable_path; cell datastack_size, retainstack_size, callstack_size; diff --git a/vm/vm.hpp b/vm/vm.hpp index 7193d50e2f..f3bf5a06ef 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -610,7 +610,9 @@ struct factor_vm void primitive_save_image_and_exit(); void fixup_data(cell data_offset, cell code_offset); void fixup_code(cell data_offset, cell code_offset); + FILE *open_image(vm_parameters *p); void load_image(vm_parameters *p); + bool embedded_image_p(); // callstack template void iterate_callstack_object(callstack *stack_, Iterator &iterator);