void* fxMapArchive(txString base, txCallbackAt callbackAt) { int error = 0; txArchive* archive = C_NULL; #if mxWindows #else struct stat statbuf; #endif txString p; Atom atom; int c, i; txString* symbol; txScript* script; archive = c_malloc(sizeof(txArchive)); bailElse(archive); c_memset(archive, 0, sizeof(txArchive)); c_strcpy(archive->base, base); #if mxWindows archive->file = CreateFile(base, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); bailElse(archive->file != INVALID_HANDLE_VALUE); archive->size = GetFileSize(archive->file, &archive->size); bailElse(archive->size != INVALID_FILE_SIZE); archive->mapping = CreateFileMapping(archive->file, NULL, PAGE_READONLY, 0, (SIZE_T)archive->size, NULL); bailElse(archive->mapping != INVALID_HANDLE_VALUE); archive->address = MapViewOfFile(archive->mapping, FILE_MAP_READ, 0, 0, (SIZE_T)archive->size); bailElse(archive->address != NULL); #else archive->fd = open(base, O_RDONLY); bailElse(archive->fd >= 0); fstat(archive->fd, &statbuf); archive->size = statbuf.st_size; archive->address = mmap(NULL, archive->size, PROT_READ, MAP_SHARED, archive->fd, 0); bailElse(archive->address != MAP_FAILED); #endif p = archive->address; p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_ARCHIVE); p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); if ((*p++) && !callbackAt) { char* dot; dot = c_strrchr(archive->base, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(archive->base, ".dll"); archive->library = LoadLibrary(archive->base); bailElse(archive->library); callbackAt = (txCallbackAt)GetProcAddress(archive->library, "xsHostModuleAt"); bailElse(callbackAt); #else c_strcat(archive->base, ".so"); archive->library = dlopen(archive->base, RTLD_NOW); if (!archive->library) fprintf(stderr, "%s\n", dlerror()); bailElse(archive->library); callbackAt = (txCallbackAt)dlsym(archive->library, "xsHostModuleAt"); bailElse(callbackAt); #endif archive->keys = callbackAt(0); } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); c = archive->symbolCount = ntohs(*((unsigned short*)p)); p += 2; if (c) { symbol = archive->symbols = c_malloc(c * sizeof(txString)); for (i = 0; i < c; i++) { *symbol = p; p += c_strlen(p) + 1; symbol++; } } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_PATHS); c = archive->scriptCount = ntohs(*((unsigned short*)p)); p += 2; script = archive->scripts = c_malloc(c * sizeof(txScript)); c_memset(script, 0, c * sizeof(txScript)); for (i = 1; i <= c; i++) { if (callbackAt) script->callback = callbackAt(i); script->path = p; p += c_strlen(p) + 1; script++; } script = archive->scripts; for (i = 0; i < c; i++) { p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = (txS1*)p; p += script->codeSize; script++; } p = c_strrchr(archive->base, mxSeparator); if (p) { p++; *p = 0; archive->baseLength = p - archive->base; } bail: if (error) { fxUnmapArchive(archive); archive = C_NULL; } return archive; }
void* fxMapArchive(txString base, txCallbackAt callbackAt) { FskErr err = kFskErrNone; txArchive* archive = NULL; txString p; Atom atom; int c, i; txString* symbol; txScript* script; bailIfError(FskMemPtrNewClear(sizeof(txArchive), &archive)); c_strcpy(archive->base, base); bailIfError(FskFileMap(base, (unsigned char**)&(archive->address), &(archive->size), 0, &(archive->map))); p = archive->address; p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_ARCHIVE); p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); if ((*p++) && !callbackAt) { char* dot; dot = c_strrchr(archive->base, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(archive->base, ".dll"); #else c_strcat(archive->base, ".so"); #endif bailIfError(FskLibraryLoad(&(archive->library), archive->base)); bailIfError(FskLibraryGetSymbolAddress(archive->library, "xsHostModuleAt", &callbackAt)); archive->keys = callbackAt(0); } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); mxDecode2(p, archive->symbolCount); c = archive->symbolCount; if (c) { bailIfError(FskMemPtrNew(c * sizeof(txString), &(archive->symbols))); symbol = archive->symbols; for (i = 0; i < c; i++) { *symbol = p; p += c_strlen(p) + 1; symbol++; } } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_PATHS); mxDecode2(p, archive->scriptCount); c = archive->scriptCount; bailIfError(FskMemPtrNewClear(c * sizeof(txScript), &(archive->scripts))); script = archive->scripts; for (i = 1; i <= c; i++) { if (callbackAt) script->callback = callbackAt(i); script->path = p; bailIfNULL(script->path); p += c_strlen(p) + 1; script++; } script = archive->scripts; for (i = 0; i < c; i++) { p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = (txS1*)p; p += script->codeSize; script++; } p = c_strrchr(archive->base, '/'); if (p) { p++; *p = 0; archive->baseLength = p - archive->base; } bail: if (err) { fxUnmapArchive(archive); archive = NULL; } return archive; }