├── .gitignore ├── main.js ├── types └── main.d.ts ├── .travis.yml ├── README.md ├── binding.gyp ├── package.json ├── LICENSE ├── test └── mkfifo.js └── src └── mkfifo.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject 2 | build 3 | node_modules 4 | .idea 5 | test.js 6 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | var binding = require(__dirname + '/build/Release/mkfifo'); 2 | 3 | exports.mkfifoSync = binding.mkfifoSync; 4 | exports.mkfifo = binding.mkfifo; 5 | -------------------------------------------------------------------------------- /types/main.d.ts: -------------------------------------------------------------------------------- 1 | export function mkfifoSync(path: string, mode: number): void; 2 | export function mkfifo(path: string, mode: number, callback: (err: ({ errno: number, errstr: string } | undefined)) => void): void; 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "10" 5 | - "12" 6 | - "node" 7 | 8 | script: 9 | - "npm test" 10 | 11 | notifications: 12 | email: false 13 | 14 | sudo: false 15 | 16 | env: 17 | - CXX=g++-4.8 18 | 19 | addons: 20 | apt: 21 | sources: 22 | - ubuntu-toolchain-r-test 23 | packages: 24 | - gcc-4.8 25 | - g++-4.8 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # POSIX `mkfifo(3)` for NodeJS [![Build Status](https://travis-ci.org/avz/node-mkfifo.svg?branch=master)](https://travis-ci.org/avz/node-mkfifo) 2 | 3 | 4 | ## Installation 5 | ``` 6 | npm install mkfifo 7 | ``` 8 | 9 | ## Example 10 | 11 | ### Sync 12 | 13 | ```javascript 14 | var mkfifoSync = require('mkfifo').mkfifoSync; 15 | 16 | mkfifoSync('/path/to/fifo', 0600); 17 | ``` 18 | 19 | ### Async 20 | 21 | ```javascript 22 | var mkfifo = require('mkfifo').mkfifo; 23 | 24 | mkfifo('/path/to/fifo', 0600, function(err) { 25 | /* ... */ 26 | }); 27 | ``` 28 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'targets': [ 3 | { 4 | 'target_name': 'mkfifo', 5 | 'sources': ['src/mkfifo.cpp'], 6 | 'include_dirs': ["", 15 | "main": "./main.js", 16 | "types": "./types/main.d.ts", 17 | "engines": { 18 | "node": ">=8.12" 19 | }, 20 | "scripts": { 21 | "test": "nodeunit test" 22 | }, 23 | "os": [ 24 | "linux", 25 | "freebsd", 26 | "darwin" 27 | ], 28 | "dependencies": { 29 | "node-addon-api": "^1.6.3" 30 | }, 31 | "devDependencies": { 32 | "nodeunit": "^0.11.3" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Artem Zaytsev 2 | Permission is hereby granted, free of charge, to any person obtaining a copy 3 | of this software and associated documentation files (the "Software"), to deal 4 | in the Software without restriction, including without limitation the rights 5 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | The above copyright notice and this permission notice shall be included 9 | in all copies or substantial portions of the Software. 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 13 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 14 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 15 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 16 | OTHER DEALINGS IN THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /test/mkfifo.js: -------------------------------------------------------------------------------- 1 | var mkfifo = require('../'); 2 | var os = require('os'); 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var crypto = require('crypto'); 6 | 7 | function checkFIFOSync(path, mode, test) { 8 | var stat = fs.statSync(path); 9 | 10 | test.ok(stat.isFIFO()); 11 | test.strictEqual(stat.mode & 0777, mode); 12 | }; 13 | 14 | module.exports = { 15 | setUp: function(cb) { 16 | this.tmppath = path.join( 17 | os.tmpdir(), 18 | '.node-mkfifo.tmp.' + Date.now() + '.' + crypto.randomBytes(8).toString('hex') 19 | ); 20 | 21 | cb(); 22 | }, 23 | tearDown: function(cb) { 24 | try { 25 | fs.unlinkSync(this.tmppath); 26 | } catch (e) { 27 | 28 | } 29 | 30 | cb(); 31 | }, 32 | mkfifoSync_mode1: function(test) { 33 | var mode = 0644; 34 | mkfifo.mkfifoSync(this.tmppath, mode); 35 | checkFIFOSync(this.tmppath, mode, test); 36 | 37 | test.done(); 38 | }, 39 | mkfifoSync_mode2: function(test) { 40 | var mode = 0600; 41 | 42 | mkfifo.mkfifoSync(this.tmppath, mode); 43 | checkFIFOSync(this.tmppath, mode, test); 44 | 45 | test.done(); 46 | }, 47 | mkfifoSync_error: function(test) { 48 | test.throws( 49 | function() { 50 | mkfifo.mkfifoSync(this.tmppath + '/nonexistent', 0644); 51 | }, 52 | Error, 53 | 'ENOENT' 54 | ); 55 | 56 | test.done(); 57 | }, 58 | mkfifoAsync_mode1: function(test) { 59 | var self = this; 60 | var mode = 0644; 61 | 62 | mkfifo.mkfifo(this.tmppath, mode, function(error) { 63 | test.strictEqual(error, undefined); 64 | checkFIFOSync(self.tmppath, mode, test); 65 | 66 | test.done(); 67 | }); 68 | }, 69 | mkfifoAsync_mode2: function(test) { 70 | var self = this; 71 | var mode = 0600; 72 | 73 | mkfifo.mkfifo(this.tmppath, mode, function(error) { 74 | test.strictEqual(error, undefined); 75 | checkFIFOSync(self.tmppath, mode, test); 76 | 77 | test.done(); 78 | }); 79 | }, 80 | mkfifoAsync_error: function(test) { 81 | mkfifo.mkfifo(this.tmppath + '/nonexistent', 0644, function(error) { 82 | test.ok(error.errno > 0); 83 | test.strictEqual(typeof(error.errstr), 'string'); 84 | test.done(); 85 | }); 86 | } 87 | }; 88 | -------------------------------------------------------------------------------- /src/mkfifo.cpp: -------------------------------------------------------------------------------- 1 | #define _DEFAULT_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "napi.h" 11 | 12 | Napi::Value MkfifoSync(const Napi::CallbackInfo& args) 13 | { 14 | Napi::Env env = args.Env(); 15 | 16 | if (args.Length() < 2) { 17 | Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); 18 | 19 | return env.Undefined(); 20 | } 21 | 22 | if (!args[0].IsString() || !args[1].IsNumber()) { 23 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); 24 | 25 | return env.Undefined(); 26 | } 27 | 28 | const mode_t mode = (mode_t)args[1].ToNumber().Uint32Value(); 29 | const std::string path(args[0].ToString().Utf8Value()); 30 | 31 | if (mkfifo(path.c_str(), mode) != 0) { 32 | Napi::TypeError::New(env, "mkfifo(" + path + "):" + strerror(errno)).ThrowAsJavaScriptException(); 33 | 34 | return env.Undefined(); 35 | } 36 | 37 | return env.Undefined(); 38 | } 39 | 40 | class MkfifoAsyncWorker : public Napi::AsyncWorker 41 | { 42 | const std::string path; 43 | mode_t mode; 44 | int error; 45 | 46 | public: 47 | 48 | MkfifoAsyncWorker(Napi::Function &callback, const std::string &path, mode_t mode) 49 | : Napi::AsyncWorker(callback), path(path), mode(mode) 50 | { 51 | } 52 | 53 | ~MkfifoAsyncWorker() 54 | { 55 | } 56 | 57 | void Execute() 58 | { 59 | if (mkfifo(path.c_str(), mode) == 0) { 60 | error = 0; 61 | } else { 62 | error = errno; 63 | } 64 | } 65 | 66 | void OnOK() 67 | { 68 | Napi::Env env = Env(); 69 | Napi::HandleScope scope(env); 70 | 71 | if (error == 0) { 72 | Callback().Call({env.Undefined()}); 73 | 74 | return; 75 | } 76 | 77 | Napi::Object err = Napi::Object::New(env); 78 | 79 | err.Set("errno", (int)error); 80 | err.Set("errstr", strerror(error)); 81 | 82 | this->Callback().Call({err}); 83 | } 84 | }; 85 | 86 | Napi::Value MkfifoAsync(const Napi::CallbackInfo& args) 87 | { 88 | Napi::Env env = args.Env(); 89 | 90 | if (args.Length() < 2) { 91 | Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); 92 | 93 | return env.Undefined(); 94 | } 95 | 96 | if (!args[0].IsString() || !args[1].IsNumber()) { 97 | Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); 98 | 99 | return env.Undefined(); 100 | } 101 | 102 | const std::string path(args[0].ToString().Utf8Value()); 103 | const mode_t mode = (mode_t)args[1].ToNumber().Uint32Value(); 104 | 105 | if (!args[2].IsFunction()) { 106 | Napi::TypeError::New(env, "callback must be a function").ThrowAsJavaScriptException(); 107 | 108 | return env.Undefined(); 109 | } 110 | 111 | Napi::Function callback = args[2].As(); 112 | MkfifoAsyncWorker* worker = new MkfifoAsyncWorker(callback, path, mode); 113 | 114 | worker->Queue(); 115 | 116 | return env.Undefined(); 117 | } 118 | 119 | Napi::Object Init(Napi::Env env, Napi::Object exports) 120 | { 121 | exports.Set(Napi::String::New(env, "mkfifoSync"), Napi::Function::New(env, MkfifoSync)); 122 | exports.Set(Napi::String::New(env, "mkfifo"), Napi::Function::New(env, MkfifoAsync)); 123 | 124 | return exports; 125 | } 126 | 127 | NODE_API_MODULE(mkfifo, Init); 128 | --------------------------------------------------------------------------------