├── .gitignore ├── LICENSE ├── README.md ├── mmap.cc ├── package.json ├── test.js └── wscript /.gitignore: -------------------------------------------------------------------------------- 1 | .lock-wscript 2 | build/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Ben Noordhuis 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-mmap 2 | 3 | mmap(2) bindings for node.js - stop slurping, start mapping. 4 | 5 | ** This module is no longer maintained. ** 6 | 7 | ## Installing 8 | 9 | Through [npm](http://npmjs.org/): 10 | 11 | npm install mmap 12 | 13 | Or compile it from source with this one-liner: 14 | 15 | node-waf configure build install 16 | 17 | ## Usage 18 | 19 | buffer = mmap.map(n_bytes, protection, flags, fd, offset); 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
n_bytesThe number of bytes to map into memory.
protectionMemory protection: either PROT_NONE or a bitwise OR of PROT_READ, PROT_WRITE and PROT_EXEC.
flagsFlags: either MAP_SHARED or MAP_PRIVATE.
fdFile descriptor.
offsetFile offset. Must be either zero or a multiple of mmap.PAGESIZE.
43 | 44 | See [the man page](http://www.opengroup.org/onlinepubs/000095399/functions/mmap.html) for more details. 45 | 46 | ## Examples 47 | 48 | Map a file into memory: 49 | 50 | fs = require('fs'), mmap = require('mmap'); 51 | fd = fs.openSync('/path/to/file', 'r'); 52 | size = fs.fstatSync(fd).size; 53 | buffer = mmap.map(size, mmap.PROT_READ, mmap.MAP_SHARED, fd, 0); 54 | // calculate faux checksum 55 | var checksum = 0; 56 | for (var i = 0; i < buffer.length; i++) { 57 | checksum ^= buffer[i]; 58 | } 59 | 60 | The file is automatically unmapped when the buffer object is garbage collected. 61 | 62 | ## Bugs and limitations 63 | 64 | * Specifying the memory address is not implemented. I couldn't think of a reason 65 | why you would want to do that from JavaScript. Convince me otherwise. :-) 66 | 67 | * Reading from and writing to memory-mapped files is a potentially blocking 68 | operation. *Do not* use this module in performance critical code. Better yet, 69 | don't use this module at all. 70 | -------------------------------------------------------------------------------- /mmap.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace { 11 | 12 | using namespace v8; 13 | using namespace node; 14 | 15 | void Unmap(char* data, void* hint) { 16 | munmap(data, (size_t) hint); 17 | } 18 | 19 | Handle Map(const Arguments& args) { 20 | HandleScope scope; 21 | 22 | if (args.Length() <= 3) { 23 | return ThrowException(Exception::Error( 24 | String::New("Constructor takes 4 arguments: size, protection, flags, fd and offset."))); 25 | } 26 | 27 | const size_t size = args[0]->ToInteger()->Value(); 28 | const int protection = args[1]->ToInteger()->Value(); 29 | const int flags = args[2]->ToInteger()->Value(); 30 | const int fd = args[3]->ToInteger()->Value(); 31 | const off_t offset = args[4]->ToInteger()->Value(); 32 | 33 | char* data = (char *) mmap( 34 | 0, size, protection, flags, fd, offset); 35 | 36 | if (data == MAP_FAILED) { 37 | return ThrowException( 38 | ErrnoException(errno, "mmap", "")); 39 | } 40 | else { 41 | Buffer* buffer = Buffer::New( 42 | data, size, Unmap, (void *) size); 43 | 44 | return buffer->handle_; 45 | } 46 | } 47 | 48 | extern "C" void init(Handle target) { 49 | HandleScope scope; 50 | 51 | const PropertyAttribute attribs = (PropertyAttribute) (ReadOnly | DontDelete); 52 | 53 | target->Set(String::New("PROT_READ"), Integer::New(PROT_READ), attribs); 54 | target->Set(String::New("PROT_WRITE"), Integer::New(PROT_WRITE), attribs); 55 | target->Set(String::New("PROT_EXEC"), Integer::New(PROT_EXEC), attribs); 56 | target->Set(String::New("PROT_NONE"), Integer::New(PROT_NONE), attribs); 57 | target->Set(String::New("MAP_SHARED"), Integer::New(MAP_SHARED), attribs); 58 | target->Set(String::New("MAP_PRIVATE"), Integer::New(MAP_PRIVATE), attribs); 59 | target->Set(String::New("PAGESIZE"), Integer::New(sysconf(_SC_PAGESIZE)), 60 | attribs); 61 | 62 | target->Set(String::NewSymbol("map"), FunctionTemplate::New(Map)->GetFunction()); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mmap", 3 | "version": "0.0.4", 4 | "author": "Ben Noordhuis", 5 | "description": "mmap(2) bindings for node.js", 6 | "homepage": "https://github.com/bnoordhuis/node-mmap", 7 | "engines": { "node": ">=0.4.0" }, 8 | "main": "./build/Release/mmap", 9 | "scripts": { 10 | "preinstall": "node-waf configure build", 11 | "preuninstall": "node-waf clean" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/bnoordhuis/node-mmap.git" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | fs = require('fs'); 2 | mmap = require('mmap'); 3 | assert = require('assert'); 4 | constants = require('constants'); 5 | 6 | PAGESIZE = mmap.PAGESIZE; 7 | PROT_READ = mmap.PROT_READ; 8 | MAP_SHARED = mmap.MAP_SHARED; 9 | 10 | // open self (this script) 11 | fd = fs.openSync(process.argv[1], 'r'); 12 | size = fs.fstatSync(fd).size; 13 | 14 | // full 5-arg constructor 15 | buffer = mmap.map(size, PROT_READ, MAP_SHARED, fd, 0); 16 | assert.equal(buffer.length, size); 17 | 18 | // short-hand 4-arg constructor 19 | buffer = mmap.map(size, PROT_READ, MAP_SHARED, fd); 20 | assert.equal(buffer.length, size); 21 | 22 | // page size is almost certainly >= 4K and this script isn't that large... 23 | fd = fs.openSync(process.argv[1], 'r'); 24 | buffer = mmap.map(size, PROT_READ, MAP_SHARED, fd, PAGESIZE); 25 | assert.equal(buffer.length, size); // ...but this is according to spec 26 | 27 | // zero size should throw exception 28 | fd = fs.openSync(process.argv[1], 'r'); 29 | try { 30 | buffer = mmap.map(0, PROT_READ, MAP_SHARED, fd, 0); 31 | } catch (e) { 32 | assert.equal(e.errno, constants.EINVAL); 33 | } 34 | 35 | // non-page size offset should throw exception 36 | if (PAGESIZE != 1) { 37 | fd = fs.openSync(process.argv[1], 'r'); 38 | try { 39 | buffer = mmap.map(size, PROT_READ, MAP_SHARED, fd, 1); 40 | } catch (e) { 41 | assert.equal(e.errno, constants.EINVAL); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | srcdir = '.' 2 | blddir = 'build' 3 | VERSION = '1.0.0' 4 | 5 | def set_options(ctx): 6 | ctx.tool_options('compiler_cxx') 7 | 8 | def configure(ctx): 9 | ctx.check_tool('compiler_cxx') 10 | ctx.check_tool('node_addon') 11 | 12 | def build(ctx): 13 | t = ctx.new_task_gen('cxx', 'shlib', 'node_addon') 14 | t.target = 'mmap' 15 | t.source = 'mmap.cc' 16 | --------------------------------------------------------------------------------