Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hertzg/node-mount
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: NodeOS/nodeos-mount
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Jan 1, 2015

  1. Copy the full SHA
    57fc749 View commit details
  2. Removed deprecated functions

    piranna committed Jan 1, 2015
    Copy the full SHA
    55263ec View commit details
  3. Copy the full SHA
    f224402 View commit details

Commits on Jan 2, 2015

  1. Copy the full SHA
    10be4ba View commit details
  2. Copy the full SHA
    24f750e View commit details
  3. Copy the full SHA
    863c6a5 View commit details

Commits on Jan 3, 2015

  1. Copy the full SHA
    7b1560a View commit details
  2. Fixed error handling.

    netlovers committed Jan 3, 2015
    Copy the full SHA
    3a119a4 View commit details

Commits on Jan 4, 2015

  1. Copy the full SHA
    2afd21b View commit details
  2. Copy the full SHA
    c87d122 View commit details

Commits on Jan 5, 2015

  1. Bug-fixing

    piranna committed Jan 5, 2015
    Copy the full SHA
    cb5edfd View commit details

Commits on Jan 6, 2015

  1. Copy the full SHA
    c0fba1f View commit details
  2. Copy the full SHA
    7b4b4de View commit details
  3. Copy the full SHA
    946551c View commit details

Commits on Mar 7, 2015

  1. Copy the full SHA
    3ed5cd0 View commit details
  2. Copy the full SHA
    23e73cf View commit details
  3. Make BitHound happier

    piranna committed Mar 7, 2015
    Copy the full SHA
    3b09548 View commit details
  4. 0.1.13

    piranna committed Mar 7, 2015
    Copy the full SHA
    344abee View commit details

Commits on Sep 21, 2015

  1. Copy the full SHA
    0c46e11 View commit details

Commits on Sep 23, 2015

  1. convert to nan2

    heavyk committed Sep 23, 2015
    Copy the full SHA
    bb4d319 View commit details

Commits on Sep 24, 2015

  1. Copy the full SHA
    16494c8 View commit details

Commits on Mar 1, 2016

  1. Merge pull request #4 from heavyk/master

    convert to nan2
    piranna committed Mar 1, 2016
    Copy the full SHA
    d924939 View commit details
  2. Copy the full SHA
    505bba4 View commit details

Commits on Jun 28, 2016

  1. Initial support

    joshgarde committed Jun 28, 2016
    Copy the full SHA
    a20fe0e View commit details
  2. Copy the full SHA
    52c4027 View commit details

Commits on Jun 29, 2016

  1. Merge pull request #7 from joshgarde/osx-support

    OS X Support
    piranna authored Jun 29, 2016
    Copy the full SHA
    0632aa6 View commit details

Commits on Sep 4, 2016

  1. Updated dependencies

    piranna committed Sep 4, 2016
    Copy the full SHA
    b0fb25b View commit details
  2. Copy the full SHA
    67d649f View commit details
  3. Minor style clean-ups

    piranna committed Sep 4, 2016
    Copy the full SHA
    59674a9 View commit details
  4. Minor clean-up on test

    piranna committed Sep 4, 2016
    Copy the full SHA
    0e80202 View commit details
  5. Copy the full SHA
    8de623e View commit details
  6. Copy the full SHA
    e878938 View commit details
  7. v0.3.0

    piranna committed Sep 4, 2016
    Copy the full SHA
    a2d52df View commit details

Commits on Sep 8, 2016

  1. Copy the full SHA
    88689c3 View commit details
  2. 0.3.1

    piranna committed Sep 8, 2016
    Copy the full SHA
    d6a3496 View commit details

Commits on Sep 16, 2016

  1. Copy the full SHA
    e388815 View commit details
  2. Merge pull request #9 from NodeOS/greenkeeper-grunt-mocha-test-0.13.0

    Update grunt-mocha-test to version 0.13.0 🚀
    piranna authored Sep 16, 2016
    Copy the full SHA
    afc4be5 View commit details

Commits on Oct 31, 2016

  1. chore: drop support for Node.js 0.10

    BREAKING CHANGE: This module no longer supports Node.js 0.10
    greenkeeperio-bot committed Oct 31, 2016
    Copy the full SHA
    8aa7749 View commit details

Commits on Nov 1, 2016

  1. Merge pull request #13 from NodeOS/greenkeeper/remove-node-0.10

    👻😱 Node.js 0.10 is unmaintained 😱👻
    piranna authored Nov 1, 2016
    Copy the full SHA
    dcf7be3 View commit details

Commits on Nov 25, 2016

  1. Copy the full SHA
    83d9dfd View commit details
  2. Merge pull request #14 from NodeOS/greenkeeper-mocha-3.2.0

    Update mocha to version 3.2.0 🚀
    piranna authored Nov 25, 2016
    Copy the full SHA
    720122f View commit details

Commits on May 11, 2017

  1. Copy the full SHA
    596cac8 View commit details
  2. Copy the full SHA
    b064df2 View commit details
  3. Merge pull request #17 from NodeOS/greenkeeper/initial

    Update dependencies to enable Greenkeeper 🌴
    piranna authored May 11, 2017
    Copy the full SHA
    2d7de50 View commit details

Commits on Aug 19, 2017

  1. Copy the full SHA
    7ee9ec6 View commit details
  2. Updated dependencies

    piranna committed Aug 19, 2017
    Copy the full SHA
    b29f887 View commit details
  3. 0.3.2

    piranna committed Aug 19, 2017
    Copy the full SHA
    2693fc9 View commit details
Showing with 2,596 additions and 400 deletions.
  1. +1 −0 .gitignore
  2. +17 −0 .travis.yml
  3. +83 −54 README.md
  4. +2 −1 binding.gyp
  5. +186 −159 mount.cc
  6. +228 −137 mount.js
  7. +2,004 −0 package-lock.json
  8. +36 −19 package.json
  9. +39 −30 test/mount.spec.js
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -3,3 +3,4 @@ build
.DS_Store
.*.sw[op]

npm-debug.log
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
os:
- linux
- osx
osx_image: xcode7.3
sudo: required
language: node_js
node_js:
- "4.4.6"
- "6.2.2"
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update ; fi
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install g++-4.8 ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
script:
- npm install
137 changes: 83 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
[![Build Status](https://travis-ci.org/NodeOS/nodeos-mount.svg?branch=master)](https://travis-ci.org/NodeOS/nodeos-mount)
[![bitHound Score](https://www.bithound.io/NodeOS/nodeos-mount/badges/score.svg)](https://www.bithound.io/NodeOS/nodeos-mount)

# node-mount

[![Greenkeeper badge](https://badges.greenkeeper.io/NodeOS/nodeos-mount.svg)](https://greenkeeper.io/)

Mount/umount devices from node.js

Really works on linux, may work on OS X, and will never work on windows.
@@ -8,106 +13,127 @@ Really works on linux, may work on OS X, and will never work on windows.
**Mount Tmpfs:**
```javascript
var mount = require("mount");
mount.mount('tmpfs', 'tmpDir', 'tmpfs', function(err) {
mount.mount('tmpDir', 'tmpfs', function(err) {
if(err){
return;
}
//Tmpfs mounted successfully
return;
}

// Tmpfs mounted successfully
});
```

**Mount DVD:**
```javascript
var mount = require("mount");
mount.mount('/dev/sr0', 'myDir', 'iso9660', function(err) {
if(err){
return;
}
mount.mount('myDir', 'iso9660', {devFile: '/dev/sr0'}, function(err) {
if(err){
return;
}

//
//
});
```

**Mount ReadOnly+Remount (easy)**
```javascript
var mount = require("mount");
mount.mount('tmpfs', 'tmpdir', 'tmpfs', ['remount', 'readonly'], function(err) {
if(err){
return;
}
mount.mount('tmpdir', 'tmpfs', ['remount', 'readonly'], function(err) {
if(err){
return;
}

//
//
});
```

**Mount ReadOnly+Remount (flags)**
```javascript
var mount = require("mount");
mount.mount('tmpfs', 'tmpdir', 'tmpfs', mount.MS_REMOUNT | mount.MS_RDONLY, function(err) {
if(err){
return;
}
//
mount.mount('tmpdir', 'tmpfs', mount.MS_REMOUNT | mount.MS_RDONLY,
function(err) {
if(err){
return;
}

//
});
```

**Umount after successful mount:**
```javascript
var mount = requrie("mount");
mount.umount('myDir', function(err) {
if(err){
console.log("Umount went wrong: " + err);
return;
}
if(err){
console.log("Umount went wrong: " + err);
return;
}

//
});
```

##Installation
This package is not featured in NPM (yet), so you have to add this dependency line to your package.json
file:
This package is not featured in NPM (yet), so you have to add this dependency
line to your package.json file:

**Part of package.json:**
```
```json
{
"name" : "myproject",
"version" : "1.0",
...
...
"dependencies" : {
"mount" : "git+ssh://git@github.com:hertzg/node-mount.git"
}
"name" : "myproject",
"version" : "1.0",
...
...
"dependencies" : {
"mount" : "git+ssh://git@github.com:hertzg/node-mount.git"
}
}
```
## API
This module provides functionality to mount and unmount devices to and from specific targets. Module exports asynchronous and synchronous variants.
This module provides functionality to mount and unmount devices to and from
specific targets. Module exports asynchronous and synchronous variants.

Most of the explanations here are from `mount(2)` and `umount(2)`

* http://linux.die.net/man/2/umount
* http://linux.die.net/man/2/mount

**WARNING: Using synchronous methods may block the process for along time. (ex: Mounting scratched CD/DVD/BD, Network shares.. etc..)**
**WARNING: Using synchronous methods may block the process for along time. (ex:
Mounting scratched CD/DVD/BD, Network shares.. etc..)**

### mount.mount(source, target, fsType, [options], [dataStr], callback)

Attaches the file system specified by `source` (which is often a device name, but can also be a directory name or a dummy) to the directory specified by `target`.

Attaches the file system specified by `source` (which is often a device name,
but can also be a directory name or a dummy) to the directory specified by
`target`.

**Appropriate privilege is required to mount file systems.**

* `source` - `{String}` - Device-File being mounted (located in /dev) a.k.a. `devFile`.
* `target` - `{String}` - Directory to mount the device to.
* `fsType` - `{String}` - Filesystem identificator (one of /proc/filesystems).
* `options` - `{Array}|{Number}` - Number describing mount flags or an Array containing String options described below:
- `bind` - Perform a bind mount, making a file or a directory subtree visible at another point within a file system. Bind mounts may cross file system boundaries and span chroot(2) jails. The `fstype` and `dataStr` arguments are ignored.
- `readonly` - Mount file system read-only.
- `remount` - Remount an existing mount. This allows you to change the `options` and `dataStr` of an existing mount without having to unmount and remount the file system. `target` should be the same value specified in the initial `mount()` call; `source` and `fsType` are ignored.
- `noexec` - Do not allow programs to be executed from this file system.
* `dataStr` - The `data` argument is interpreted by the different file systems. Typically it is a string of comma-separated options understood by this file system.
* `callback` - Function called after the mount operation finishes. Receives only one argument `err`.
* `err` - Is `null` if mount succeeded or `Error` object similar to ones generated by `fs` module in case of failure.

Values for the `fstype` argument supported by the kernel are listed in `/proc/filesystems` (e.g., "minix", "ext2", "ext3", "jfs", "xfs", "reiserfs", "msdos", "proc", "nfs", "iso9660").
* `options` - `{Array}|{Number}` - Number describing mount flags or an Array
containing String options described below:
- `bind` - Perform a bind mount, making a file or a directory subtree visible
at another point within a file system. Bind mounts may cross file system
boundaries and span chroot(2) jails. The `fstype` and `dataStr` arguments
are ignored.
- `readonly` - Mount file system read-only.
- `remount` - Remount an existing mount. This allows you to change the
`options` and `dataStr` of an existing mount without having to unmount and
remount the file system. `target` should be the same value specified in the
initial `mount()` call; `source` and `fsType` are ignored.
- `noexec` - Do not allow programs to be executed from this file system.
* `dataStr` - The `data` argument is interpreted by the different file systems.
Typically it is a string of comma-separated options or an options bag
understood by this file system. `devFile` option can be used to define the
Device-File being mounted (located in /dev).
* `callback` - Function called after the mount operation finishes. Receives only
one argument `err`.
* `err` - Is `null` if mount succeeded or `Error` object similar to ones
generated by `fs` module in case of failure.

Values for the `fstype` argument supported by the kernel are listed in
`/proc/filesystems` (e.g., "minix", "ext2", "ext3", "jfs", "xfs", "reiserfs",
"msdos", "proc", "nfs", "iso9660"). It can be `auto`, too.


### mount.umount(target, callback)
@@ -116,23 +142,27 @@ Removes the attachment of the (topmost) file system mounted on `target`.
**Appropriate privilege is required to unmount file systems.**

* `target` - `{String}` - Directory to unmount.
* `callback` - Function called after the mount operation finishes. Receives only one argument `err`.
* `err` - `null` if umount succeeded or `Error` object similar to ones generated by `fs` module in case of failure.
* `callback` - Function called after the mount operation finishes. Receives only
one argument `err`.
* `err` - `null` if umount succeeded or `Error` object similar to ones
generated by `fs` module in case of failure.

Returns `undefined`

### mount.mountSync(source, target, fsType, [options], [dataStr])
Synchronous variant of `mount.mount()`

Returns: `true` if mount succeeded or **throws** `Error` object similar to ones generated by `fs` module in case of failure.
Returns: `true` if mount succeeded or **throws** `Error` object similar to ones
generated by `fs` module in case of failure.

### mount.umountSync(target)
Synchronous variant of `mount.umount()`

Returns: `true` if umount succeeded or **throws** `Error` object similar to ones generated by `fs` module in case of failure.
Returns: `true` if umount succeeded or **throws** `Error` object similar to ones
generated by `fs` module in case of failure.

### mount.unmount(target, callback)
This function is **deprecated**; please use `mount.umount()` instead.
This function is **deprecated**; please use `mount.umount()` instead.

Alias of `mount.umount()`

@@ -146,7 +176,6 @@ Constants for easy `mount` `flags` bitmask manipulation.

## TODO:
- umount2 - force force unmounting
- unittests

## Credits
- Directly forked from magicpat`s [repository](https://github.com/magicpat/node-mount)
3 changes: 2 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@
"targets": [
{
"target_name": "mount",
"sources": [ "mount.cc" ]
"sources": [ "mount.cc" ],
"include_dirs": [ "<!(node -e \"require('nan')\")" ]
}
]
}
345 changes: 186 additions & 159 deletions mount.cc
Original file line number Diff line number Diff line change
@@ -4,209 +4,236 @@
#include <errno.h>
#include <string.h>
#include <iostream>

//Uses an example of kkaefer's node addon tutorials for an async worker
//
//Link for the used template:
//https://github.com/kkaefer/node-cpp-modules/blob/master/05_threadpool/modulename.cpp#L88
#include <nan.h>

using namespace v8;

Handle<Value> Mount(const Arguments &args);
void AsyncMount(uv_work_t* req);
void AsyncUmount(uv_work_t *req);
void AsyncAfter(uv_work_t* req);


struct Mounty {
Persistent<Function> callback;

//All values excpect target are only used by mount
std::string devFile;
std::string fsType;
std::string target; //used by umount
std::string data;
long flags;
int error;
// All values except target are only used by mount
std::string devFile;
std::string fsType;
std::string target; // used by umount
std::string data;
long flags;
int error;
};

void AsyncMount(uv_work_t* req){
Mounty* mounty = static_cast<Mounty*>(req->data);

int ret = mount(mounty->devFile.c_str(),
mounty->target.c_str(),
mounty->fsType.c_str(),
mounty->flags,
mounty->data.c_str());

//Save error-code
if(ret == -1){
mounty->error = errno;
class MountWorker : public Nan::AsyncWorker {
public:
MountWorker(Nan::Callback *callback, Mounty *mounty)
: Nan::AsyncWorker(callback), mounty(mounty) {}
~MountWorker() {}

// This function is executed in another thread at some point after it has been
// scheduled. IT MUST NOT USE ANY V8 FUNCTIONALITY.
void Execute() {
#ifdef __linux__
int ret = mount(mounty->devFile.c_str(),
mounty->target.c_str(),
mounty->fsType.c_str(),
mounty->flags,
mounty->data.c_str());
#elif __APPLE__
int ret = mount(
mounty->fsType.c_str(),
mounty->target.c_str(),
mounty->flags,
&mounty->data);
#endif

if (ret == -1) {
mounty->error = errno;
}
}
}

void AsyncUmount(uv_work_t *req){
Mounty* mounty = static_cast<Mounty*>(req->data);
void HandleOKCallback() {
Nan::HandleScope scope;

int ret = umount(mounty->target.c_str());
Local<Value> argv[] = {
Nan::Null()
};

//Save error-code
if(ret == -1){
mounty->error = errno;
if (mounty->error > 0) {
argv[0] = Nan::ErrnoException(mounty->error, "mount", "",
mounty->devFile.c_str());
}
}

//Used for both, mount and umount since they have the same callback interface
void AsyncAfter(uv_work_t* req){
HandleScope scope;
Mounty* mounty = static_cast<Mounty*>(req->data);

const unsigned argc = 1;
Local<Value> argv[argc];

//Call error-callback, if error... otherwise send result
if(mounty->error > 0){
std::string syscall;
std::string path;
if(mounty->devFile.empty()) {
syscall = "umount";
path = mounty->target;
} else {
syscall = "mount";
path = mounty->devFile;
}
argv[0] = node::ErrnoException(mounty->error, syscall.c_str(), "", path.c_str());
} else {
argv[0] = Local<Value>::New(Null());
callback->Call(1, argv);
}

private:
Mounty *mounty;
};

class UmountWorker : public Nan::AsyncWorker {
public:
UmountWorker(Nan::Callback *callback, Mounty *mounty)
: Nan::AsyncWorker(callback), mounty(mounty) {}
~UmountWorker() {}

void Execute() {
#ifdef __linux__
int ret = umount(mounty->target.c_str());
#elif __APPLE__
int ret = unmount(
mounty->target.c_str(),
mounty->flags);
#endif

if (ret == -1) {
mounty->error = errno;
}
}

TryCatch tc;
mounty->callback->Call(Context::GetCurrent()->Global(), argc, argv);
void HandleOKCallback() {
Nan::HandleScope scope;
Local<Value> argv[] = {
Nan::Null()
};

if(tc.HasCaught()){
node::FatalException(tc);
if (mounty->error > 0) {
argv[0] = Nan::ErrnoException(mounty->error, "umount", "",
mounty->target.c_str());
}

mounty->callback.Dispose();
callback->Call(1, argv);

delete mounty;
delete req;
}
}

private:
Mounty *mounty;
};

// 0 1 2 3 4 5
//mount(devFile, target, fsType, options, data, cb)
Handle<Value> Mount(const Arguments &args) {
HandleScope scope;

if(args.Length() != 6) {
return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 6)")));
}
// 0 1 2 3 4 5
// mount(devFile, target, fsType, options, data, cb)
NAN_METHOD(Mount) {
Nan::HandleScope scope;

String::Utf8Value devFile(args[0]->ToString());
String::Utf8Value target(args[1]->ToString());
String::Utf8Value fsType(args[2]->ToString());
Local<Integer> options = args[3]->ToInteger();
String::Utf8Value dataStr(args[4]->ToString());
Local<Function> cb = Local<Function>::Cast(args[5]);

//Prepare data for the async work
Mounty* mounty = new Mounty();
mounty->devFile = std::string(*devFile);
mounty->target = std::string(*target);
mounty->fsType = std::string(*fsType);
mounty->flags = options->Value();
mounty->data = std::string(*dataStr);
mounty->callback = Persistent<Function>::New(cb);

//Create the Async work and set the prepared data
uv_work_t *req = new uv_work_t();
req->data = mounty;

int status = uv_queue_work(uv_default_loop(), req, AsyncMount, (uv_after_work_cb)AsyncAfter);
assert(status == 0);
return scope.Close(Undefined());
}
if (info.Length() != 6) {
return Nan::ThrowError("Invalid number of arguments (must be 6)");
}

Handle<Value> Umount(const Arguments &args) {
HandleScope scope;
String::Utf8Value devFile(info[0]->ToString());
String::Utf8Value target(info[1]->ToString());
String::Utf8Value fsType(info[2]->ToString());
Local<Integer> options = info[3]->ToInteger();
String::Utf8Value dataStr(info[4]->ToString());

if(args.Length() != 2) {
return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 2)")));
}
// Prepare data for the async work
Mounty* mounty = new Mounty();
mounty->devFile = std::string(*devFile);
mounty->target = std::string(*target);
mounty->fsType = std::string(*fsType);
mounty->flags = options->Value();
mounty->data = std::string(*dataStr);

String::Utf8Value target(args[0]->ToString());
Local<Function> cb = Local<Function>::Cast(args[1]);
Nan::Callback *callback = new Nan::Callback(info[5].As<Function>());

//Prepare data for the async work
Mounty* mounty = new Mounty();
mounty->target = std::string(*target);
mounty->callback = Persistent<Function>::New(cb);
Nan::AsyncQueueWorker(new MountWorker(callback, mounty));
return;
}

//Create the Async work and set the prepared data
uv_work_t *req = new uv_work_t();
req->data = mounty;
NAN_METHOD(Umount) {
Nan::HandleScope scope;

int status = uv_queue_work(uv_default_loop(), req, AsyncUmount, (uv_after_work_cb)AsyncAfter);
assert(status == 0);
return scope.Close(Undefined());
}
if (info.Length() != 2) {
return Nan::ThrowError("Invalid number of arguments (must be 2)");
}

Handle<Value> MountSync(const Arguments &args) {
HandleScope scope;
String::Utf8Value target(info[0]->ToString());

if(args.Length() != 5) {
return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 5)")));
}
// Prepare data for the async work
Mounty* mounty = new Mounty();
mounty->target = std::string(*target);

String::Utf8Value devFile(args[0]->ToString());
String::Utf8Value target(args[1]->ToString());
String::Utf8Value fsType(args[2]->ToString());
Handle<Integer> options = args[3]->ToInteger();
String::Utf8Value dataStr(args[4]->ToString());

std::string s_devFile(*devFile);
std::string s_target(*target);
std::string s_fsType(*fsType);
std::string s_dataStr(*dataStr);

int ret = mount(s_devFile.c_str(),
s_target.c_str(),
s_fsType.c_str(),
options->Value(),
s_dataStr.c_str());

if(ret != 0){
return ThrowException(node::ErrnoException(errno, "mount", "", s_devFile.c_str()));
}
Nan::Callback *callback = new Nan::Callback(info[1].As<Function>());

return scope.Close(True());
Nan::AsyncQueueWorker(new UmountWorker(callback, mounty));
return;
}

Handle<Value> UmountSync(const Arguments &args) {
HandleScope scope;

if(args.Length() != 1) {
return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 1)")));
}
NAN_METHOD(MountSync) {
Nan::HandleScope scope;

if (info.Length() != 5) {
return Nan::ThrowError("Invalid number of arguments (must be 5)");
}

String::Utf8Value devFile(info[0]->ToString());
String::Utf8Value target(info[1]->ToString());
String::Utf8Value fsType(info[2]->ToString());
Handle<Integer> options = info[3]->ToInteger();
String::Utf8Value dataStr(info[4]->ToString());

std::string s_devFile(*devFile);
std::string s_target(*target);
std::string s_fsType(*fsType);
std::string s_dataStr(*dataStr);

#ifdef __linux__
int ret = mount(s_devFile.c_str(),
s_target.c_str(),
s_fsType.c_str(),
options->Value(),
s_dataStr.c_str());
#elif __APPLE__
int ret = mount(
s_fsType.c_str(),
s_target.c_str(),
options->Value(),
&s_dataStr);
#endif

if (ret) {
return Nan::ThrowError(Nan::ErrnoException(errno, "mount", "",
s_devFile.c_str()));
}

info.GetReturnValue().Set(Nan::True());
}

String::Utf8Value target(args[0]->ToString());
NAN_METHOD(UmountSync) {
Nan::HandleScope scope;

std::string s_target(*target);
if (info.Length() != 1) {
return Nan::ThrowError("Invalid number of arguments (must be 1)");
}

int ret = umount(s_target.c_str());
if(ret != 0){
return ThrowException(node::ErrnoException(errno, "umount", "", s_target.c_str()));
}
String::Utf8Value target(info[0]->ToString());

return scope.Close(True());
std::string s_target(*target);

#ifdef __linux__
int ret = umount(s_target.c_str());
#elif __APPLE__
int ret = unmount(
s_target.c_str(),
0);
#endif

if (ret) {
return Nan::ThrowError(Nan::ErrnoException(errno, "umount", "",
s_target.c_str()));
}

info.GetReturnValue().Set(Nan::True());
}

void init (Handle<Object> exports, Handle<Object> module) {
exports->Set(String::NewSymbol("mount"), FunctionTemplate::New(Mount)->GetFunction());
exports->Set(String::NewSymbol("umount"), FunctionTemplate::New(Umount)->GetFunction());
exports->Set(String::NewSymbol("mountSync"), FunctionTemplate::New(MountSync)->GetFunction());
exports->Set(String::NewSymbol("umountSync"), FunctionTemplate::New(UmountSync)->GetFunction());

void init (Handle<Object> exports) {
exports->Set(Nan::New<String>("mount").ToLocalChecked(),
Nan::New<FunctionTemplate>(Mount)->GetFunction());
exports->Set(Nan::New<String>("umount").ToLocalChecked(),
Nan::New<FunctionTemplate>(Umount)->GetFunction());
exports->Set(Nan::New<String>("mountSync").ToLocalChecked(),
Nan::New<FunctionTemplate>(MountSync)->GetFunction());
exports->Set(Nan::New<String>("umountSync").ToLocalChecked(),
Nan::New<FunctionTemplate>(UmountSync)->GetFunction());
}

NODE_MODULE(mount, init)
365 changes: 228 additions & 137 deletions mount.js

Large diffs are not rendered by default.

2,004 changes: 2,004 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

55 changes: 36 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
{
"name": "mount",
"name": "nodeos-mount",
"description": "Async mount / umount system devices",
"main": "./mount",
"os" : [ "linux", "darwin", "!win32" ],
"os": [
"linux",
"darwin",
"!win32"
],
"keywords": [
"mount",
"linux",
"device",
"async"
],
"version": "0.1.1",
"homepage": "https://github.com/hertzg/node-mount",
"bugs": "https://github.com/hertzg/node-mount/issues",
"version": "0.3.2",
"homepage": "https://github.com/NodeOS/nodeos-mount",
"bugs": "https://github.com/NodeOS/nodeos-mount/issues",
"repository": {
"type": "git",
"url": "git://github.com/hertzg/node-mount.git"
"url": "git://github.com/NodeOS/nodeos-mount.git"
},
"engines": {
"node": ">=0.8.0"
"node": ">= 4"
},
"private": true,
"author": "George Kotchlamazashvili <georgedot@gmail.com>",
"contributors": [{
"contributors": [
{
"name": "Justas Brazauskas",
"email": "brazauskasjustas@gmail.com"
}, {
},
{
"name": "Patrick Stapfer",
"email": "p.stapfer@deadlock.at",
"url": "http://www.deadlock.at"
}],
},
{
"name": "Jesús Leganés Combarro 'piranna'",
"email": "piranna@gmail.com",
"url": "http://pirannafs.blogspot.com"
}
],
"scripts": {
"test": "grunt test"
},
"license": "MIT",
"gypfile": true,
"readmeFilename": "README.md",
"dependencies": {},
"dependencies": {
"async": "^2.5.0",
"nan": "^2.6.2"
},
"devDependencies": {
"mocha": "~1.18.2",
"chai": "~1.9.1",
"grunt": "~0.4.4",
"grunt-mocha-test": "~0.10.2",
"grunt-contrib-watch": "~0.6.1",
"grunt-node-gyp": "~0.3.0",
"q": "~1.0.1"
"mocha": "~3.5.0",
"chai": "~4.1.1",
"grunt": "~1.0.1",
"grunt-mocha-test": "~0.13.2",
"grunt-contrib-watch": "~1.0.0",
"grunt-node-gyp": "~4.0.0",
"q": "~1.5.0"
}
}
69 changes: 39 additions & 30 deletions test/mount.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* jshint -W024 */
/* jshint -W024 */
/* jshint expr:true */
"use strict";

@@ -11,38 +11,44 @@ var fs = require("fs");
var util = require("util");
var Q = require("q");

var TMP_DIR = path.join(__dirname, "tmp");
var TMP_DIR = path.join(__dirname, "tmp");


function expectErrToBeNotOk(done, err)
{
expect(err).to.be.not.ok;
done();
}


describe("mount", function(){
//Create the target directory for mounting
before(function(){
if(!fs.existsSync(TMP_DIR)){
fs.mkdirSync(TMP_DIR);
fs.mkdirSync(TMP_DIR);
}
});

//Delete it afterwards
after(function(done){
mount.umount(TMP_DIR, function(err){
fs.rmdirSync(TMP_DIR);
done();
fs.rmdir(TMP_DIR, done);
});
});

describe("#mount", function(){

afterEach(function(done){
mount.umount(TMP_DIR, function(){
done();
});
});

it("should mount tmpfs filesystem", function(done){
mount.mount("tmpfs", TMP_DIR, "tmpfs", function(err){
if(process.getuid()) return this.skip()

mount.mount(TMP_DIR, "tmpfs", function(err){
expect(err).to.be.not.ok;
mount.umount(TMP_DIR, function(err){
done();
});
mount.umount(TMP_DIR, done);
});
});

@@ -53,58 +59,61 @@ describe("mount", function(){
var p4 = function(err){};

//Should all fail
expect(mount.mount.bind(mount, p1, p4)).to.throw(Error);
// expect(mount.mount.bind(mount, p1, p4)).to.throw(Error);
expect(mount.mount.bind(mount, p1, p4, p2)).to.throw(Error);
});

it("should not mount on nonexisting target", function(done){
mount.mount("tmpfs", "notexist", "tmpfs", function(err){
mount.mount("notexist", "tmpfs", function(err){
expect(err).to.be.ok;
expect(err.message).to.be.equal("2");
expect(err.message).to.be.equal("ENOENT, No such file or "+
"directory 'tmpfs'");
done();
});
});

it("should mount tmpfs", function(done){
mount.mount("tmpfs", TMP_DIR, "tmpfs", function(err){
expect(err).to.be.not.ok;
done();
});
if(process.getuid()) return this.skip()

mount.mount(TMP_DIR, "tmpfs",
expectErrToBeNotOk.bind(undefined, done));
});

it("should mount / remount tmpfs with flags", function(done){
mount.mount("tmpfs", TMP_DIR, "tmpfs", ["readonly", "noexec"], function(err){
if(process.getuid()) return this.skip()

mount.mount(TMP_DIR, "tmpfs", ["readonly", "noexec"], function(err){
expect(err).to.be.not.ok;

mount.mount("tmpfs", TMP_DIR, "tmpfs", ["remount"], function(err){
expect(err).to.be.not.ok;
done();
});
mount.mount(TMP_DIR, "tmpfs", ["remount"],
expectErrToBeNotOk.bind(undefined, done));
});
});

it("should throw error on wrong flag", function(){
expect(mount.mount.bind(mount, "tmpfs", TMP_DIR, ["readonly", "fail"])).to.throw(Error);
});

});

describe("#umount", function(){
it("should umount mounting point", function(done){
mount.mount("tmpfs", TMP_DIR, "tmpfs", function(err){
if(process.getuid()) return this.skip()

mount.mount(TMP_DIR, "tmpfs", function(err){
expect(err).to.be.not.ok;

mount.umount(TMP_DIR, function(err){
expect(err).to.be.not.ok;
done();
});
mount.umount(TMP_DIR, expectErrToBeNotOk.bind(undefined, done));
});
});

it("should raise error on umounting a nonexisting mountpoint", function(done){
it("should raise error on umounting a nonexisting mountpoint",
function(done){
if(process.getuid()) return this.skip()

mount.umount("nonexistent", function(err){
expect(err).to.be.ok;
expect(err.message).to.be.equal("2");
expect(err.message).to.be.equal("ENOENT, No such file or "+
"directory 'nonexistent'");
done();
});
});