Git Product home page Git Product logo

fuse-bindings's Introduction

fuse-bindings

NOTICE

We published the successor module to this at https://github.com/fuse-friends/fuse-native

Fully maintained fuse bindings for Node that aims to cover the entire FUSE api

npm install fuse-bindings

Compared to fuse4js these bindings cover almost the entire FUSE api (except for locking) and doesn't do any buffer copys in read/write. It also supports unmount and mouting of multiple fuse drives.

Requirements

You need to have FUSE installed (or Dokany on Windows)

  • On Linux/Ubuntu sudo apt-get install libfuse-dev
  • On OSX
    • if you use Brew, install OSXFuse and brew install pkg-config
    • if you use MacPorts, sudo port install osxfuse +devel
  • On Windows install Dokany

Windows

WARNING: Dokany is still not quite stable. It can cause BSODs. Be careful.

Using this on Windows is slightly more complicated. You need to install Dokany (for dokanfuse.lib, dokanctl.exe, driver and service) and clone its repo (for the headers).

Once the Dokany repo is cloned, you also need to set environment variable DOKAN_INSTALL_DIR to the path to DokenLibrary of your Dokany installaton, and DOKAN_FUSE_INCLUDE to the path to *dokany repo*\dokan_fuse\include.

EDIT: Dokany now includes needed headers and sets proper environment variables when installing! Just install Dokany and this module should install and work just fine! (Drop an issue otherwise)

Usage

Try creating an empty folder called mnt and run the below example

var fuse = require('fuse-bindings')

var mountPath = process.platform !== 'win32' ? './mnt' : 'M:\\'

fuse.mount(mountPath, {
  readdir: function (path, cb) {
    console.log('readdir(%s)', path)
    if (path === '/') return cb(0, ['test'])
    cb(0)
  },
  getattr: function (path, cb) {
    console.log('getattr(%s)', path)
    if (path === '/') {
      cb(0, {
        mtime: new Date(),
        atime: new Date(),
        ctime: new Date(),
        nlink: 1,
        size: 100,
        mode: 16877,
        uid: process.getuid ? process.getuid() : 0,
        gid: process.getgid ? process.getgid() : 0
      })
      return
    }

    if (path === '/test') {
      cb(0, {
        mtime: new Date(),
        atime: new Date(),
        ctime: new Date(),
        nlink: 1,
        size: 12,
        mode: 33188,
        uid: process.getuid ? process.getuid() : 0,
        gid: process.getgid ? process.getgid() : 0
      })
      return
    }

    cb(fuse.ENOENT)
  },
  open: function (path, flags, cb) {
    console.log('open(%s, %d)', path, flags)
    cb(0, 42) // 42 is an fd
  },
  read: function (path, fd, buf, len, pos, cb) {
    console.log('read(%s, %d, %d, %d)', path, fd, len, pos)
    var str = 'hello world\n'.slice(pos, pos + len)
    if (!str) return cb(0)
    buf.write(str)
    return cb(str.length)
  }
}, function (err) {
  if (err) throw err
  console.log('filesystem mounted on ' + mountPath)
})

process.on('SIGINT', function () {
  fuse.unmount(mountPath, function (err) {
    if (err) {
      console.log('filesystem at ' + mountPath + ' not unmounted', err)
    } else {
      console.log('filesystem at ' + mountPath + ' unmounted')
    }
  })
})

See also

fs-fuse is a wrapper module build on top of fuse-bindings that allow you to export and mount any fs-like object as a FUSE filesystem.

API

fuse.mount(mnt, ops, [cb])

Mount a new filesystem on mnt. Pass the FUSE operations you want to support as the ops argument.

fuse.unmount(mnt, [cb])

Unmount a filesystem

fuse.context()

Returns the current fuse context (pid, uid, gid). Must be called inside a fuse callback.

Mount options

ops.options

Set mount options

ops.options = ['direct_io'] // set the direct_io option

ops.displayFolder

Set to true to make OSX display a folder icon and the folder name as the mount point in finder

ops.force

Set to true to force mount the filesystem (will do an unmount first)

FUSE operations

Most of the FUSE api is supported. In general the callback for each op should be called with cb(returnCode, [value]) where the return code is a number (0 for OK and < 0 for errors). See below for a list of POSIX error codes.

ops.init(cb)

Called on filesystem init.

ops.access(path, mode, cb)

Called before the filesystem accessed a file

ops.statfs(path, cb)

Called when the filesystem is being stat'ed. Accepts a fs stat object after the return code in the callback.

ops.statfs = function (path, cb) {
  cb(0, {
    bsize: 1000000,
    frsize: 1000000,
    blocks: 1000000,
    bfree: 1000000,
    bavail: 1000000,
    files: 1000000,
    ffree: 1000000,
    favail: 1000000,
    fsid: 1000000,
    flag: 1000000,
    namemax: 1000000
  })
}

ops.getattr(path, cb)

Called when a path is being stat'ed. Accepts a stat object (similar to the one returned in fs.stat(path, cb)) after the return code in the callback.

ops.getattr = function (path, cb) {
  cb(0, {
    mtime: new Date(),
    atime: new Date(),
    ctime: new Date(),
    size: 100,
    mode: 16877,
    uid: process.getuid(),
    gid: process.getgid()
  })
}

ops.fgetattr(path, fd, cb)

Same as above but is called when someone stats a file descriptor

ops.flush(path, fd, cb)

Called when a file descriptor is being flushed

ops.fsync(path, fd, datasync, cb)

Called when a file descriptor is being fsync'ed.

ops.fsyncdir(path, fd, datasync, cb)

Same as above but on a directory

ops.readdir(path, cb)

Called when a directory is being listed. Accepts an array of file/directory names after the return code in the callback

ops.readdir = function (path, cb) {
  cb(0, ['file-1.txt', 'dir'])
}

ops.truncate(path, size, cb)

Called when a path is being truncated to a specific size

ops.ftruncate(path, fd, size, cb)

Same as above but on a file descriptor

ops.readlink(path, cb)

Called when a symlink is being resolved. Accepts a pathname (that the link should resolve to) after the return code in the callback

ops.readlink = function (path, cb) {
  cb(null, 'file.txt') // make link point to file.txt
}

ops.chown(path, uid, gid, cb)

Called when ownership of a path is being changed

ops.chmod(path, mode, cb)

Called when the mode of a path is being changed

ops.mknod(path, mode, dev, cb)

Called when the a new device file is being made.

ops.setxattr(path, name, buffer, length, offset, flags, cb)

Called when extended attributes is being set (see the extended docs for your platform). Currently you can read the attribute value being set in buffer at offset.

ops.getxattr(path, name, buffer, length, offset, cb)

Called when extended attributes is being read. Currently you have to write the result to the provided buffer at offset.

ops.listxattr(path, buffer, length, cb)

Called when extended attributes of a path are being listed. buffer should be filled with the extended attribute names as null-terminated strings, one after the other, up to a total of length in length. (ERANGE should be passed to the callback if length is insufficient.) The size of buffer required to hold all the names should be passed to the callback either on success, or if the supplied length was zero.

ops.removexattr(path, name, cb)

Called when an extended attribute is being removed.

ops.open(path, flags, cb)

Called when a path is being opened. flags in a number containing the permissions being requested. Accepts a file descriptor after the return code in the callback.

var toFlag = function(flags) {
  flags = flags & 3
  if (flags === 0) return 'r'
  if (flags === 1) return 'w'
  return 'r+'
}

ops.open = function (path, flags, cb) {
  var flag = toFlag(flags) // convert flags to a node style string
  ...
  cb(0, 42) // 42 is a file descriptor
}

ops.opendir(path, flags, cb)

Same as above but for directories

ops.read(path, fd, buffer, length, position, cb)

Called when contents of a file is being read. You should write the result of the read to the buffer and return the number of bytes written as the first argument in the callback. If no bytes were written (read is complete) return 0 in the callback.

var data = new Buffer('hello world')

ops.read = function (path, fd, buffer, length, position, cb) {
  if (position >= data.length) return cb(0) // done
  var part = data.slice(position, position + length)
  part.copy(buffer) // write the result of the read to the result buffer
  cb(part.length) // return the number of bytes read
}

ops.write(path, fd, buffer, length, position, cb)

Called when a file is being written to. You can get the data being written in buffer and you should return the number of bytes written in the callback as the first argument.

ops.write = function (path, fd, buffer, length, position, cb) {
  console.log('writing', buffer.slice(0, length))
  cb(length) // we handled all the data
}

ops.release(path, fd, cb)

Called when a file descriptor is being released. Happens when a read/write is done etc.

ops.releasedir(path, fd, cb)

Same as above but for directories

ops.create(path, mode, cb)

Called when a new file is being opened.

ops.utimens(path, atime, mtime, cb)

Called when the atime/mtime of a file is being changed.

ops.unlink(path, cb)

Called when a file is being unlinked.

ops.rename(src, dest, cb)

Called when a file is being renamed.

ops.link(src, dest, cb)

Called when a new link is created.

ops.symlink(src, dest, cb)

Called when a new symlink is created

ops.mkdir(path, mode, cb)

Called when a new directory is being created

ops.rmdir(path, cb)

Called when a directory is being removed

ops.destroy(cb)

Both read and write passes the underlying fuse buffer without copying them to be as fast as possible.

Error codes

The available error codes are exposes as well as properties. These include

  • fuse.EPERM === -1
  • fuse.ENOENT === -2
  • fuse.ESRCH === -3
  • fuse.EINTR === -4
  • fuse.EIO === -5
  • fuse.ENXIO === -6
  • fuse.E2BIG === -7
  • fuse.ENOEXEC === -8
  • fuse.EBADF === -9
  • fuse.ECHILD === -10
  • fuse.EAGAIN === -11
  • fuse.ENOMEM === -12
  • fuse.EACCES === -13
  • fuse.EFAULT === -14
  • fuse.ENOTBLK === -15
  • fuse.EBUSY === -16
  • fuse.EEXIST === -17
  • fuse.EXDEV === -18
  • fuse.ENODEV === -19
  • fuse.ENOTDIR === -20
  • fuse.EISDIR === -21
  • fuse.EINVAL === -22
  • fuse.ENFILE === -23
  • fuse.EMFILE === -24
  • fuse.ENOTTY === -25
  • fuse.ETXTBSY === -26
  • fuse.EFBIG === -27
  • fuse.ENOSPC === -28
  • fuse.ESPIPE === -29
  • fuse.EROFS === -30
  • fuse.EMLINK === -31
  • fuse.EPIPE === -32
  • fuse.EDOM === -33
  • fuse.ERANGE === -34
  • fuse.EDEADLK === -35
  • fuse.ENAMETOOLONG === -36
  • fuse.ENOLCK === -37
  • fuse.ENOSYS === -38
  • fuse.ENOTEMPTY === -39
  • fuse.ELOOP === -40
  • fuse.EWOULDBLOCK === -11
  • fuse.ENOMSG === -42
  • fuse.EIDRM === -43
  • fuse.ECHRNG === -44
  • fuse.EL2NSYNC === -45
  • fuse.EL3HLT === -46
  • fuse.EL3RST === -47
  • fuse.ELNRNG === -48
  • fuse.EUNATCH === -49
  • fuse.ENOCSI === -50
  • fuse.EL2HLT === -51
  • fuse.EBADE === -52
  • fuse.EBADR === -53
  • fuse.EXFULL === -54
  • fuse.ENOANO === -55
  • fuse.EBADRQC === -56
  • fuse.EBADSLT === -57
  • fuse.EDEADLOCK === -35
  • fuse.EBFONT === -59
  • fuse.ENOSTR === -60
  • fuse.ENODATA === -61
  • fuse.ETIME === -62
  • fuse.ENOSR === -63
  • fuse.ENONET === -64
  • fuse.ENOPKG === -65
  • fuse.EREMOTE === -66
  • fuse.ENOLINK === -67
  • fuse.EADV === -68
  • fuse.ESRMNT === -69
  • fuse.ECOMM === -70
  • fuse.EPROTO === -71
  • fuse.EMULTIHOP === -72
  • fuse.EDOTDOT === -73
  • fuse.EBADMSG === -74
  • fuse.EOVERFLOW === -75
  • fuse.ENOTUNIQ === -76
  • fuse.EBADFD === -77
  • fuse.EREMCHG === -78
  • fuse.ELIBACC === -79
  • fuse.ELIBBAD === -80
  • fuse.ELIBSCN === -81
  • fuse.ELIBMAX === -82
  • fuse.ELIBEXEC === -83
  • fuse.EILSEQ === -84
  • fuse.ERESTART === -85
  • fuse.ESTRPIPE === -86
  • fuse.EUSERS === -87
  • fuse.ENOTSOCK === -88
  • fuse.EDESTADDRREQ === -89
  • fuse.EMSGSIZE === -90
  • fuse.EPROTOTYPE === -91
  • fuse.ENOPROTOOPT === -92
  • fuse.EPROTONOSUPPORT === -93
  • fuse.ESOCKTNOSUPPORT === -94
  • fuse.EOPNOTSUPP === -95
  • fuse.EPFNOSUPPORT === -96
  • fuse.EAFNOSUPPORT === -97
  • fuse.EADDRINUSE === -98
  • fuse.EADDRNOTAVAIL === -99
  • fuse.ENETDOWN === -100
  • fuse.ENETUNREACH === -101
  • fuse.ENETRESET === -102
  • fuse.ECONNABORTED === -103
  • fuse.ECONNRESET === -104
  • fuse.ENOBUFS === -105
  • fuse.EISCONN === -106
  • fuse.ENOTCONN === -107
  • fuse.ESHUTDOWN === -108
  • fuse.ETOOMANYREFS === -109
  • fuse.ETIMEDOUT === -110
  • fuse.ECONNREFUSED === -111
  • fuse.EHOSTDOWN === -112
  • fuse.EHOSTUNREACH === -113
  • fuse.EALREADY === -114
  • fuse.EINPROGRESS === -115
  • fuse.ESTALE === -116
  • fuse.EUCLEAN === -117
  • fuse.ENOTNAM === -118
  • fuse.ENAVAIL === -119
  • fuse.EISNAM === -120
  • fuse.EREMOTEIO === -121
  • fuse.EDQUOT === -122
  • fuse.ENOMEDIUM === -123
  • fuse.EMEDIUMTYPE === -124

License

MIT

fuse-bindings's People

Contributors

andrewosh avatar clkao avatar davidknoll avatar dcousens avatar dresende avatar mafintosh avatar marinkobabic avatar piranna avatar ralphtheninja avatar raymond-h avatar sam0x17 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fuse-bindings's Issues

need rigorous filesystem test suite

we need a script that, given a folder, will do the following:

  • any stuff from https://nodejs.org/api/fs.html that isn't here and would be useful to test
  • write a file
  • read a file
  • truncate a file
  • append to a file
  • delete a file
  • soft link a file
  • hard link a file
  • read a soft link
  • read a hard link
  • rewrite a hard link
  • rename a file
  • stat
  • writing big (~512KB) buffers in a single write call
  • reading big buffers in a single read call
  • writing small buffers (~10 bytes)
  • reading small buffers (~10 bytes)
  • readdir
  • rmdir
  • mkdir

that way we can use this for testing all the various fuse implementations for edge cases

Strange `link` behavior

In this little example https://github.com/aa6/nodejs_fuse_tests/blob/master/util/fuse-bindings_hardlinking.coffee when I try to call fs.link on a mounted fs, it calls gettattr on linking target, then calls getattr on non-existant-yet hardlink file and never calls the link function to actually create a hard link. What is wrong here? Readfile at the end is used to ensure that fs is working.
Output:

$ coffee fuse-bindings_hardlinking.coffee 
mount { '0': undefined }
getattr { '0': '/.xdg-volume-info', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
getattr { '0': '/autorun.inf', '1': [Function: bound ] }
getattr { '0': '/.Trash', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/.Trash-1000', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/', '1': [Function: bound ] }
readdir { '0': '/', '1': [Function: bound ] }
getattr { '0': '/autorun.inf', '1': [Function: bound ] }
=== link 1 ===
getattr { '0': '/test', '1': [Function: bound ] }
getattr { '0': '/test-lnk', '1': [Function: bound ] }
{ '0': 
   { Error: ENOENT: no such file or directory, link '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test' -> '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test-lnk'
     at Error (native)

     errno: -2,
     code: 'ENOENT',
     syscall: 'link',
     path: '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test',
     dest: '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test-lnk' } }
=== /link 1 ===
=== link 2 ===
getattr { '0': '/test-lnk', '1': [Function: bound ] }
{ '0': 
   { Error: ENOENT: no such file or directory, link '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test-lnk' -> '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test'
     at Error (native)

     errno: -2,
     code: 'ENOENT',
     syscall: 'link',
     path: '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test-lnk',
     dest: '/home/me/tst/nodejs_fuse_tests/util/tmp/fuse-bindings_hardlinking_mountpoint/test' } }
=== /link 2 ===
=== readFile ===
open { '0': '/test', '1': 32768, '2': [Function: bound ] }
read { '0': '/test',
  '1': 1,
  '2': <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >,
  '3': 4096,
  '4': 0,
  '5': [Function: bound ] }
getattr { '0': '/test', '1': [Function: bound ] }
read { '0': '/test',
  '1': 1,
  '2': <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >,
  '3': 4096,
  '4': 0,
  '5': [Function: bound ] }
hello world
=== /readFile ===
umount { '0': null, '1': '', '2': '' }

Wherefore callbacks?

Hi,
the current design uses callbacks to communicate the results of operations back to the fuse daemon, e.g.: the cb in readdir: function (path, cb) ....

Can you explain the rationale for this, rather than, say having the operations return values e.g.

readdir: function (path) { return ['file1'];}

The python bindings for fuse seems to choose that approach.

For instance is it ever correct to call a callback more than once for a given operation? Also can a callback be used after the operation notification has completed? (e.g. readdir returns without calling cb, and at a later point cb is called with proper data)

A 'yes' to either question would clarify the current design, however, best would be examples demonstrating the possibilities.

Cheers! nehal

need prebuild for node 8.x (v57) x64

prebuild info looking for local prebuild @ prebuilds/fuse-bindings-v2.11.1-node-v57-linux-x64.tar.gz
prebuild info looking for cached prebuild @ /root/.npm/_prebuilds/https-github.com-mafintosh-fuse-bindings-releases-download-v2.11.1-fuse-bindings-v2.11.1-node-v57-linux-x64.tar.gz
prebuild http request GET https://github.com/mafintosh/fuse-bindings/releases/download/v2.11.1/fuse-bindings-v2.11.1-node-v57-linux-x64.tar.gz
prebuild http 404 https://github.com/mafintosh/fuse-bindings/releases/download/v2.11.1/fuse-bindings-v2.11.1-node-v57-linux-x64.tar.gz

Pass arguments to `prebuild`

The start script is defined as prebuild --install, ignoring any argument given to it. This makes on NodeOS that it can't be cross-compiled, because this way it always gets the CPU arch of the Node.js process instead of the one I'm giving it explicitly, making the node-gyp execution to fail. I think just by changing the start script to prebuild --install @ to pass it all the arguments that has been already passed to the npm start execution would be just enough. How do you see it?

Undefined file size on stat

Is it possible to leave the file size in a stat call undetermined?

In https://github.com/Munter/fusile I had to add this very ugly size hack in order to account for the transpiled size being bigger than the source file. But the size of the transpiled file will not be available to me before the operation is done, and I want to avoid doing the work before the read operation.

The only reason this hack works because direct_io allows me to return 0 in a read callback, which should indicate to the consumer that the file is no longer, even though a read buffer has been allocated to account for the fake bloated file size I reported in the stat call.

The problem I have is that web servers seem to report the Content-Length header based on the stat size, and not close the connection when I return 0 in the read callback. Or the browser doesn't close the connection. No matter which of the two is at fault, the connection hangs and development is impossible.

So, can I leave the file size undertermined somehow and maybe trigger a different behavior by the web server (and other similar behaving clients)?

This is the issue in question: Munter/fusile#178

fuse-bindings read callback signature

I'm trying to learn how to use fuse-bindings by implement a driver that reads another directory via calling the various node fs calls. I.e., I can mount my /Users/<home> dir to /mnt this way.

What I don't fully grasp is how fuse.read's callback signature works. Node's fs.read signature is (err, bytesRead, buffer), but looking at the example code fuse.read seems to be (bytesRead).

  1. is my understanding correct?

  2. if so, how do I pass back an error?

Thanks.

libfuse 3.0.0

libfuse is preparing a 3.0.0 release with several aditions and some breaking changes, maybe it would be a good idea to start thinking to move to it and add some of the breaking changes it was discussed in the past...

easy callback parameters question

In a bunch of scenarios I am unsure whether to do cb(fuse.ERRORCODE) or cb(-1, fuse.ERRORCODE). For example in rename, I am unsure which to do. Is there a general rule of thumb to follow here?

Example filesystem

I've made a passthrough filesystem as an example, and put it at jkozak/node-fuse-bindings-xmp-example. It basically works (I ran fsx against it for a bit) but has a couple of issues:

  • default flags on creat
  • how to implement flush without dup?

Would you prefer this as a pull request?

Segmentation fault on unmount

var fuse = require('fuse-bindings')

var dir = process.argv[2]

fuse.mount(dir, {}, error => {
  if (error) {
    return console.error(error)
  }
  console.log('mounted')

  // unmount after 1 second
  setTimeout(() => {
    fuse.unmount(dir, error => {
      if (error) {
        return console.error(error)
      }
      console.log('unmounted')
    })
  }, 1e3)
})
> node index.js foo/mounted
fish: 'node index.js foo/' terminated by signal SIGSEGV (Address boundary error)

FYI, my environment is Debian Stretch with:

> npm version
{ npm: '4.0.3',
  ares: '1.10.1-DEV',
  http_parser: '2.7.0',
  icu: '57.1',
  modules: '48',
  node: '6.9.1',
  openssl: '1.0.2j',
  uv: '1.9.1',
  v8: '5.1.281.84',
  zlib: '1.2.8' }

Segfault with example.js when used with latest Dokany

This project reproduces the error with a segfault trace:

https://github.com/samkelly/flashsync_node_test

C:\Users\sam\Desktop\flashsync_node_test (master) ([email protected])
λ node .
Dokan: debug mode on
Dokan: use stderr
AllocationUnitSize: 512 SectorSize: 512
device opened
filesystem mounted on Z:
mounted: Z:\ -> \Volume{d6cc17c5-1730-4085-bce7-964f1e9f5de9}
Mounted
###QueryVolumeInfo -001
GetVolumeInformation
###Create 0000
CreateFile: \
        DesiredAccess: SYNCHRONIZE
        ShareAccess: 0x0
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 33 (0x21)
getattr(/)
CreateFile status = 0
###GetFileInfo 0000
GetFileInfo: : \
getattr(/)
        result =  0
  unknown type:54
        DispatchQueryInformation result =  c000000d
###GetFileInfo 0000
GetFileInfo: : \
getattr(/)
        result =  0
        FileStandardInformation
        DispatchQueryInformation result =  0
###QueryVolumeInfo 0000
GetVolumeInformation
###QueryVolumeInfo 0000
GetVolumeInformation
###Cleanup 0000
Cleanup: \

###Close 0000
Close: \

###Create 0001
CreateFile: \
        DesiredAccess: FILE_READ_ATTRIBUTES
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 2097152 (0x200000)
getattr(/)
CreateFile status = 0
###GetFileInfo 0001
GetFileInfo: : \
getattr(/)
        result =  0
        FileStandardInformation
        DispatchQueryInformation result =  0
###GetFileInfo 0001
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###Cleanup 0001
Cleanup: \

###Close 0001
Close: \

###Create 0002
CreateFile: \
        DesiredAccess: FILE_READ_ATTRIBUTES
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 2097152 (0x200000)
getattr(/)
CreateFile status = 0
###GetFileInfo 0002
GetFileInfo: : \
getattr(/)
        result =  0
        FileStandardInformation
        DispatchQueryInformation result =  0
###GetFileInfo 0002
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###Cleanup 0002
Cleanup: \

###Close 0002
Close: \

###Create 0003
CreateFile: \
        DesiredAccess: SYNCHRONIZE|FILE_READ_ATTRIBUTES|FILE_READ_DATA
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 0 (0x0)
getattr(/)
CreateFile status = 0
###GetFileInfo 0003
GetFileInfo: : \
getattr(/)
        result =  0
        FileStandardInformation
        DispatchQueryInformation result =  0
###GetFileInfo 0003
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###GetFileInfo 0003
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###Create 0004
CreateFile: \
        DesiredAccess: SYNCHRONIZE|FILE_READ_ATTRIBUTES|FILE_READ_DATA
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 0 (0x0)
getattr(/)
CreateFile status = 0
###GetFileInfo 0004
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###GetFileInfo 0004
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###Create 0005
CreateFile: \
        DesiredAccess: FILE_READ_ATTRIBUTES
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 2097152 (0x200000)
getattr(/)
CreateFile status = 0
###Create 0006
CreateFile: \desktop.ini
        DesiredAccess: FILE_GENERIC_READ
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 100 (0x64)
getattr(/desktop.ini)
CreateFile status = c0000034
###GetFileInfo 0005
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###Create 0007
CreateFile: \
        DesiredAccess: SYNCHRONIZE|FILE_READ_ATTRIBUTES|FILE_READ_DATA
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 32 (0x20)
getattr(/)
CreateFile status = 0
###Cleanup 0005
Cleanup: \

###GetFileInfo 0007
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###Close 0005
Close: \

###Create 0008
CreateFile: \
        DesiredAccess: FILE_READ_ATTRIBUTES
        ShareAccess: FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ
        Disposition: FILE_OPEN (1)
        Attributes: 0 (0x0)
        Options: 2097152 (0x200000)
getattr(/)
CreateFile status = 0
###GetFileInfo 0007
GetFileInfo: : \
getattr(/)
        result =  0
  unknown type:55
        DispatchQueryInformation result =  c000000d
###GetFileInfo 0008
GetFileInfo: : \
getattr(/)
        result =  0
        FileBasicInformation
        DispatchQueryInformation result =  0
###FindFiles 0007
FindFiles: \
getattr(/)
readdir(/)
PID 3344 received SIGSEGV for address: 0x6ef1d1b
SymInit: Symbol-SearchPath: '.;C:\Users\sam\Desktop\flashsync_node_test;C:\Program Files\nodejs;C:\Windows;C:\Windows\system32;SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols;', symOptions: 530, UserName: 'sam'
OS-Version: 10.0.14393 () 0x100-0x1
c:\users\sam\desktop\flashsync_node_test\node_modules\segfault-handler\src\stackwalker.cpp (941): StackWalker::ShowCallstack
c:\users\sam\desktop\flashsync_node_test\node_modules\segfault-handler\src\segfault-handler.cpp (116): segfault_handler
00007FFF1234BD00 (ntdll): (filename not available): RtlInitializeCriticalSection
00007FFF1232960B (ntdll): (filename not available): RtlImageNtHeaderEx
00007FFF12389CBA (ntdll): (filename not available): KiUserExceptionDispatcher
c:\users\sam\desktop\flashsync_node_test\node_modules\fuse-bindings\fuse-bindings.cc (238): bindings_getattr
00007FFF0440228B (dokanfuse1): (filename not available): fuse_teardown
c:\users\sam\desktop\flashsync_node_test\node_modules\fuse-bindings\fuse-bindings.cc (751): bindings_set_dirs
c:\users\sam\desktop\flashsync_node_test\node_modules\fuse-bindings\fuse-bindings.cc (775): OpCallback
c:\users\sam\desktop\flashsync_node_test\node_modules\nan\nan_callbacks_12_inl.h (175): Nan::imp::FunctionCallbackWrapper
00007FF687915C0F (node): (filename not available): v8::internal::LookupIterator::Start<1>
00007FF687748EFE (node): (filename not available): v8::internal::StrDup
00007FF687747E43 (node): (filename not available): v8::internal::StrDup
00007FF687747D1B (node): (filename not available): v8::internal::StrDup
00000343961043AB ((module-name not available)): (filename not available): (function-name not available)
00000343961042E1 ((module-name not available)): (filename not available): (function-name not available)
0000001D1A8FE2A0 ((module-name not available)): (filename not available): (function-name not available)
0000000300000000 ((module-name not available)): (filename not available): (function-name not available)
00000343961042E1 ((module-name not available)): (filename not available): (function-name not available)
0000001D1A8FE2B0 ((module-name not available)): (filename not available): (function-name not available)
0000000300000000 ((module-name not available)): (filename not available): (function-name not available)
00000343961042E1 ((module-name not available)): (filename not available): (function-name not available)
0000001D1A8FE2D0 ((module-name not available)): (filename not available): (function-name not available)
0000000300000000 ((module-name not available)): (filename not available): (function-name not available)
0000001D1A8FE378 ((module-name not available)): (filename not available): (function-name not available)
0000034396286829 ((module-name not available)): (filename not available): (function-name not available)
0000002CEB982311 ((module-name not available)): (filename not available): (function-name not available)
000002705D9AEB69 ((module-name not available)): (filename not available): (function-name not available)
0000000700000000 ((module-name not available)): (filename not available): (function-name not available)
000000EE0B162601 ((module-name not available)): (filename not available): (function-name not available)
send global release for Z:

C:\Users\sam\Desktop\flashsync_node_test (master) ([email protected])
λ

Touch not implemented?

Trying to run touch inside the mounted directory:

$ touch hello.txt

Seeing:

touch: hello.txt: Function not implemented

Is touch not suppose to work?

Windows and Dokany: node-gyp error in fuse-bindings.cc

Console:

Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.                                                                                                                              
  fuse-bindings.cc                                                                                                                                                                                                                       
  abstractions.cc                                                                                                                                                                                                                        
c:\users\dave\code\dokany\dokan_fuse\include\fuse_win.h(118): warning C4005: 'S_IFLNK': macro redefinition (compiling source file ..\fuse-bindings.cc) [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]    
  c:\users\dave\.node-gyp\5.0.0\include\node\uv-win.h(66): note: see previous definition of 'S_IFLNK' (compiling source file ..\fuse-bindings.cc)                                                                                        
..\fuse-bindings.cc(613): error C2440: '=': cannot convert from 'int (__cdecl *)(const char *,_stat64 *)' to 'int (__cdecl *)(const char *,stat64_cygwin *)' [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxp  
roj]                                                                                                                                                                                                                                     
  ..\fuse-bindings.cc(613): note: This conversion requires a reinterpret_cast, a C-style cast or function-style cast                                                                                                                     
..\fuse-bindings.cc(614): error C2440: '=': cannot convert from 'int (__cdecl *)(const char *,_stat64 *,fuse_file_info *)' to 'int (__cdecl *)(const char *,stat64_cygwin *,fuse_file_info *)' [C:\Users\Dave\Desktop\node_modules\fuse  
-bindings\build\fuse_bindings.vcxproj]                                                                                                                                                                                                   
  ..\fuse-bindings.cc(614): note: This conversion requires a reinterpret_cast, a C-style cast or function-style cast                                                                                                                     
..\fuse-bindings.cc(613): warning C4390: ';': empty controlled statement found; is this the intent? [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                       
..\fuse-bindings.cc(614): warning C4390: ';': empty controlled statement found; is this the intent? [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                       
..\fuse-bindings.cc(695): error C2440: 'return': cannot convert from 'v8::MaybeLocal<T>' to 'v8::Local<T>' [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                
          with                                                                                                                                                                                                                           
          [                                                                                                                                                                                                                              
              T=v8::Date                                                                                                                                                                                                                 
          ]                                                                                                                                                                                                                              
  ..\fuse-bindings.cc(695): note: No constructor could take the source type, or constructor overload resolution was ambiguous                                                                                                            
..\fuse-bindings.cc(706): warning C4244: '=': conversion from 'double' to '_dev_t', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                 
..\fuse-bindings.cc(707): warning C4244: '=': conversion from 'double' to '_ino_t', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                 
..\fuse-bindings.cc(709): warning C4244: '=': conversion from 'double' to 'short', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                  
..\fuse-bindings.cc(710): warning C4244: '=': conversion from 'double' to 'short', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                  
..\fuse-bindings.cc(711): warning C4244: '=': conversion from 'double' to 'short', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                  
..\fuse-bindings.cc(712): warning C4244: '=': conversion from 'double' to '_dev_t', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                 
..\fuse-bindings.cc(713): warning C4244: '=': conversion from 'double' to '__int64', possible loss of data [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]                                                
..\fuse-bindings.cc(751): error C2664: 'int (void *,const char *,const stat64_cygwin *,__int64)': cannot convert argument 3 from '_stat64 *' to 'const stat64_cygwin *' [C:\Users\Dave\Desktop\node_modules\fuse-bindings\build\fuse_bi  
ndings.vcxproj]                                                                                                                                                                                                                          
  ..\fuse-bindings.cc(751): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast                                                                                              
gyp ERR! build error                                                                                                                                                                                                                     
gyp ERR! stack Error: `C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe` failed with exit code: 1                                                                                                                                     
gyp ERR! stack     at ChildProcess.onExit (C:\Users\Dave\AppData\Roaming\nvm\v5.0.0\node_modules\npm\node_modules\node-gyp\lib\build.js:270:23)                                                                                          
gyp ERR! stack     at emitTwo (events.js:87:13)                                                                                                                                                                                          
gyp ERR! stack     at ChildProcess.emit (events.js:172:7)                                                                                                                                                                                
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)                                                                                                                                             
gyp ERR! System Windows_NT 10.0.10240                                                                                                                                                                                                    
gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Dave\\AppData\\Roaming\\nvm\\v5.0.0\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"                                                           
gyp ERR! cwd C:\Users\Dave\Desktop\node_modules\fuse-bindings                                                                                                                                                                            
gyp ERR! node -v v5.0.0                                                                                                                                                                                                                  
gyp ERR! node-gyp -v v3.0.3                                                                                                                                                                                                              
gyp ERR! not ok                                                                                                                                                                                                                          
npm WARN ENOENT ENOENT: no such file or directory, open 'C:\Users\Dave\Desktop\package.json'                                                                                                                                             
npm WARN EPACKAGEJSON C:\Users\Dave\Desktop No description                                                                                                                                                                               
npm WARN EPACKAGEJSON C:\Users\Dave\Desktop No repository field.                                                                                                                                                                         
npm WARN EPACKAGEJSON C:\Users\Dave\Desktop No README data                                                                                                                                                                               
npm WARN EPACKAGEJSON C:\Users\Dave\Desktop No license field.                                                                                                                                                                            
npm ERR! Windows_NT 10.0.10240                                                                                                                                                                                                           
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "fuse-bindings"                                                                                            
npm ERR! node v5.0.0                                                                                                                                                                                                                     
npm ERR! npm  v3.3.6                                                                                                                                                                                                                     
npm ERR! code ELIFECYCLE                                                                                                                                                                                                                 

npm ERR! [email protected] install: `node-gyp rebuild`                                                                                                                                                                                 
npm ERR! Exit status 1                                                                                                                                                                                                                   
npm ERR!                                                                                                                                                                                                                                 
npm ERR! Failed at the [email protected] install script 'node-gyp rebuild'.                                                                                                                                                            
npm ERR! This is most likely a problem with the fuse-bindings package,                                                                                                                                                                   
npm ERR! not with npm itself.                                                                                                                                                                                                            
npm ERR! Tell the author that this fails on your system:                                                                                                                                                                                 
npm ERR!     node-gyp rebuild                                                                                                                                                                                                            
npm ERR! You can get their info via:                                                                                                                                                                                                     
npm ERR!     npm owner ls fuse-bindings                                                                                                                                                                                                  
npm ERR! There is likely additional logging output above.                                                                                                                                                                                

npm ERR! Please include the following file with any support request:                                                                                                                                                                     
npm ERR!     C:\Users\Dave\Desktop\npm-debug.log                                                                                                                                                                                         

npm-debug.log: http://pastebin.com/6dCCQDJC

I have Microsoft Visual Studio 2014 and dokany installed. Windows 10 64bit machine.

Environment Variables set:

DOKAN_FUSE_INCLUDE -> Include directory of headers dokan's repo. I also noticed the dokan installer now includes the headers and tried those but it didn't work.
DOKAN_INSTALL_DIR- -> C:\Program Files (x86)\Dokan\DokanLibrary
I also tried "C:\Program Files\Dokan\DokanLibrary" (not sure which one it was supposed to be)

I'm using node 5, but I also tried with node 0.12.7 using nvm. I've been trying to debug this for a while with no luck.

Open vs Read

I'm attempting to implement FUSE into my Amazon Cloud Drive app (https://github.com/alex-phillips/node-clouddrive) and I'm running into some issues. Some of my directories are quite large (images, videos, etc.) and I'm having trouble figuring out the best course of action to take when reading/opening files.

If you mount the drive and open the window in OS X, when you go to a directory, it appears that it attempts to read (in this case, download) each file. What I'd really like happen is that when you go to a directory, it gets the listing along with all of the file information (size, mtime, etc.), but doesn't actually read (download) the contents of a file until the user opens the file in an application (i.e., Preview, VLC, etc.).

What is the best way to solve this? I can provide the little bit of FUSE code I have so far if that would help.

Macports install

This is not an issue, it's just an information regarding installation. If you use macports instead of brew, the only thing you need to do before installing the module is:

sudo port install osxfuse +devel

Crash on readdir on Windows

Hey,

npm v4.0.2
node v6.4.0
Windows 10
[email protected]

The given example won't work on windows

process.getgid is not a function
process.getuid is not a function

If I try to remove the UID and GID then on readdir callback function if I
callback empty directory cb(0) it works, but on this case cb(0, ["test"]); the app just crash

[nodemon] app crashed - waiting for file changes before starting...

process.on("uncaughtException") won't fire any event

Any idea what can I do?

Thanks!

Errors support for init callback?

It would've been convenient to have an ability to pass an error to the init callback in case if initialization could not be performed.

Unable to install fuse-bindings

Hi, when I try to install fuse-bindings via npm on my debian unstable, I get the following error:

17364 info postuninstall [email protected]
17365 error [email protected] install: `prebuild --install`
17365 error Exit status 127
17366 error Failed at the [email protected] install script.
17366 error This is most likely a problem with the fuse-bindings package,
17366 error not with npm itself.
17366 error Tell the author that this fails on your system:
17366 error     prebuild --install
17366 error You can get their info via:
17366 error     npm owner ls fuse-bindings
17366 error There is likely additional logging output above.
17367 error System Linux 4.5.0-1-amd64
17368 error command "/usr/bin/nodejs" "/usr/bin/npm" "install" "--save" "fuse-bindings"
17369 error cwd /home/witiko
17370 error node -v v4.4.3
17371 error npm -v 1.4.21
17372 error code ELIFECYCLE
17373 verbose exit [ 1, true ]

Do you have any idea what the issue could be? The 127 exit code suggests a missing executable.

32768 in open() flags

Sorry for the question but probably you might know the answer. I'm trying to figure out open() flags for different nodejs open modes on linux and have got this:

  'r'   # Open file for reading. An exception occurs if the file does not exist.
        #32768
        # 0b1000000000000000
  'r+'  # Open file for reading and writing. An exception occurs if the file does not exist.
        #32770
        # 0b1000000000000010
  'rs'  # Open file for reading in synchronous mode. Instructs the operating system to bypass the local file system cache.
        # This is primarily useful for opening files on NFS mounts as it allows you to skip the potentially stale local cache. It has a very real impact on I/O performance so don't use this flag unless you need it.
        # Note that this doesn't turn fs.open() into a synchronous blocking call. If that's what you want then you should be using fs.openSync()
        #36864
        # 0b1001000000000000
  'rs+' # Open file for reading and writing, telling the OS to open it synchronously. See notes for 'rs' about using this with caution.
        #36866
        # 0b1001000000000010
  'w'   # Open file for writing. The file is created (if it does not exist) or truncated (if it exists).
        #32769
        # 0b1000000000000001
  'wx'  # Like 'w' but fails if path exists.
  'w+'  # Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
        #32770
        # 0b1000000000000010
  'wx+' # Like 'w+' but fails if path exists.
  'a'   # Open file for appending. The file is created if it does not exist.
        #33793
        # 0b1000010000000001
  'ax'  # Like 'a' but fails if path exists.
  'a+'  # Open file for reading and appending. The file is created if it does not exist.
        #33794
        # 0b1000010000000010
  'ax+' # Like 'a+' but fails if path exists.

Every flags value I've got contains 0b1000000000000000 bitmask which is 32768 in decimal or 0100000 octal. But there is no such value in require('constants') which I believe should be used instead of hardcoded values. S_IFREG is equal to 32768 but I doubt it is suitable for open flags. Could you tell me please what is this flag for and what it means? Thank you.

Build fails with io.js 3.0.0

Running npm install with io.js 3.0.0 on Ubuntu 14.04.3:

> [email protected] install /mnt/devdrive/NodeProjects/fuse-bindings
> node-gyp rebuild

make: Entering directory `/mnt/devdrive/NodeProjects/fuse-bindings/build'
  CXX(target) Release/obj.target/fuse_bindings/fuse-bindings.o
In file included from ../fuse-bindings.cc:1:0:
../node_modules/nan/nan.h:324:27: error: redefinition of ‘template<class T> v8::Local<T> Nan::imp::NanEnsureHandleOrPersistent(const v8::Local<T>&)’
   NAN_INLINE v8::Local<T> NanEnsureHandleOrPersistent(const v8::Local<T> &val) {
                           ^
../node_modules/nan/nan.h:319:17: error: ‘template<class T> v8::Handle<T> Nan::imp::NanEnsureHandleOrPersistent(v8::Handle<T>&)’ previously declared here
   v8::Handle<T> NanEnsureHandleOrPersistent(const v8::Handle<T> &val) {
                 ^
../node_modules/nan/nan.h:344:27: error: redefinition of ‘template<class T> v8::Local<T> Nan::imp::NanEnsureLocal(v8::Handle<T>&)’
   NAN_INLINE v8::Local<T> NanEnsureLocal(const v8::Handle<T> &val) {
                           ^
../node_modules/nan/nan.h:334:27: error: ‘template<class T> v8::Local<T> Nan::imp::NanEnsureLocal(const v8::Local<T>&)’ previously declared here
   NAN_INLINE v8::Local<T> NanEnsureLocal(const v8::Local<T> &val) {
                           ^
../node_modules/nan/nan.h:757:13: error: ‘node::smalloc’ has not been declared
     , node::smalloc::FreeCallback callback
             ^
../node_modules/nan/nan.h:757:35: error: expected ‘,’ or ‘...’ before ‘callback’
     , node::smalloc::FreeCallback callback
                                   ^
../node_modules/nan/nan.h: In function ‘v8::Local<v8::Object> NanNewBufferHandle(char*, size_t, int)’:
../node_modules/nan/nan.h:761:50: error: ‘callback’ was not declared in this scope
         v8::Isolate::GetCurrent(), data, length, callback, hint);
                                                  ^
../node_modules/nan/nan.h:761:60: error: ‘hint’ was not declared in this scope
         v8::Isolate::GetCurrent(), data, length, callback, hint);
                                                            ^
../node_modules/nan/nan.h: In function ‘v8::Local<v8::Object> NanNewBufferHandle(const char*, uint32_t)’:
../node_modules/nan/nan.h:768:67: error: call of overloaded ‘New(v8::Isolate*, const char*&, uint32_t&)’ is ambiguous
     return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
                                                                   ^
../node_modules/nan/nan.h:768:67: note: candidates are:
In file included from ../node_modules/nan/nan.h:25:0,
                 from ../fuse-bindings.cc:1:
/home/at/.node-gyp/3.0.0/include/node/node_buffer.h:35:40: note: v8::MaybeLocal<v8::Object> node::Buffer::New(v8::Isolate*, v8::Handle<v8::String>, node::encoding) <near match>
 NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                        ^
/home/at/.node-gyp/3.0.0/include/node/node_buffer.h:35:40: note:   no known conversion for argument 3 from ‘uint32_t {aka unsigned int}’ to ‘node::encoding’
/home/at/.node-gyp/3.0.0/include/node/node_buffer.h:47:40: note: v8::MaybeLocal<v8::Object> node::Buffer::New(v8::Isolate*, char*, size_t) <near match>
 NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
                                        ^
/home/at/.node-gyp/3.0.0/include/node/node_buffer.h:47:40: note:   no known conversion for argument 2 from ‘const char*’ to ‘char*’
In file included from ../fuse-bindings.cc:1:0:
../node_modules/nan/nan.h: In function ‘v8::Local<v8::Object> NanNewBufferHandle(uint32_t)’:
../node_modules/nan/nan.h:772:61: error: could not convert ‘node::Buffer::New(v8::Isolate::GetCurrent(), ((size_t)size))’ from ‘v8::MaybeLocal<v8::Object>’ to ‘v8::Local<v8::Object>’
     return node::Buffer::New(v8::Isolate::GetCurrent(), size);
                                                             ^
../node_modules/nan/nan.h: In function ‘v8::Local<v8::Object> NanBufferUse(char*, uint32_t)’:
../node_modules/nan/nan.h:779:12: error: ‘Use’ is not a member of ‘node::Buffer’
     return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
            ^
../fuse-bindings.cc: In function ‘v8::Local<v8::Object> bindings_buffer(char*, size_t)’:
../fuse-bindings.cc:203:8: error: ‘class v8::Object’ has no member named ‘SetIndexedPropertiesToExternalArrayData’
   buf->SetIndexedPropertiesToExternalArrayData((char *) data, kExternalUnsignedByteArray, length);
        ^
../fuse-bindings.cc:203:63: error: ‘kExternalUnsignedByteArray’ was not declared in this scope
   buf->SetIndexedPropertiesToExternalArrayData((char *) data, kExternalUnsignedByteArray, length);
                                                               ^
../fuse-bindings.cc: In function ‘void* bindings_thread(void*)’:
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::getattr’ [-Wmissing-field-initializers]
   struct fuse_operations ops = { };
                                  ^
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::readlink’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::getdir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::mknod’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::mkdir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::unlink’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::rmdir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::symlink’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::rename’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::link’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::chmod’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::chown’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::truncate’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::utime’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::open’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::read’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::write’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::statfs’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::flush’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::release’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::fsync’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::setxattr’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::getxattr’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::listxattr’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::removexattr’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::opendir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::readdir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::releasedir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::fsyncdir’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::init’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::destroy’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::access’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::create’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::ftruncate’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::fgetattr’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::lock’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::utimens’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::bmap’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::flag_nullpath_ok’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::flag_nopath’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::flag_utime_omit_ok’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::flag_reserved’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::ioctl’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::poll’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::write_buf’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::read_buf’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::flock’ [-Wmissing-field-initializers]
../fuse-bindings.cc:648:34: warning: missing initializer for member ‘fuse_operations::fallocate’ [-Wmissing-field-initializers]
make: *** [Release/obj.target/fuse_bindings/fuse-bindings.o] Error 1
make: Leaving directory `/mnt/devdrive/NodeProjects/fuse-bindings/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:269:23)
gyp ERR! stack     at emitTwo (events.js:87:13)
gyp ERR! stack     at ChildProcess.emit (events.js:172:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Linux 3.13.0-61-generic
gyp ERR! command "/usr/bin/iojs" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /mnt/devdrive/NodeProjects/fuse-bindings
gyp ERR! node -v v3.0.0
gyp ERR! node-gyp -v v2.0.2
gyp ERR! not ok 

npm ERR! Linux 3.13.0-61-generic
npm ERR! argv "/usr/bin/iojs" "/usr/bin/npm" "install"
npm ERR! node v3.0.0
npm ERR! npm  v2.13.3
npm ERR! code ELIFECYCLE
npm ERR! [email protected] install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] install script 'node-gyp rebuild'.
npm ERR! This is most likely a problem with the fuse-bindings package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node-gyp rebuild
npm ERR! You can get their info via:
npm ERR!     npm owner ls fuse-bindings
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /mnt/devdrive/NodeProjects/fuse-bindings/npm-debug.log

utimens atime/mtime parameters jumping about non-monotonically

If I repeatedly touch the same file, then rather than increasing by a few seconds each time to match the current time, the atime and mtime my utimens function receives are jumping about (in either direction) by as much as 15 minutes, and may be several minutes ahead of (I haven't seen behind) the current time as returned by Date.now(), which is used for ctime. My system's clock is correct.

At the beginning of my utimens function, I have an optional debug output that shows the parameters, before I do anything else with them. The problem shows here, as well as in the output of the stat command once those times have been saved.

Below I have attempted to demonstrate this in an orderly way.

[proposal] make API more Node.js style

Current signature of read & write functions is

ops.read(path, fd, buffer, length, position, cb)
ops.write(path, fd, buffer, length, position, cb)

I think it's easier to understand that on read you set the buffer data on the callback and get the readed lenght from there. In the same way, in write the length is somewhat superfluous, since you already has the length of data you want to write in the buffer. This changes can simplify the API without loosing performance at the same time.

Something similar could be done in the other operations with the error argument, accepting null for success and any thruthy value to notify an error has occurred. Error code could be inspected (specially util for overlay filesystems, where the real filesystem error from the 'fs' module could be directly reused) or use a generic one if none valid could be found.

setattr: "Function not implemented"

"Function not implemented" error happens when there is a setattr operation triggered:

unique: 20, opcode: SETATTR (4), nodeid: 3, insize: 168
   unique: 20, error: -78 (Function not implemented), outsize: 16

Does fuse-binding implement setattr?

P.S. both setattr and setxattr are implemented in the codes.

Thanks.

Cannot include fuse.h

Hey, I'm using windows and trying to install fuse-bindings

I followed all the instructions, and did install Dokany myself

image

I also tried to set environment variables:
DOKAN_INSTALL_DIR = C:\Program Files\Dokan\DokanLibrary

DOKAN_FUSE_INCLUDE = C:\Program Files\Dokan\DokanLibrary\include

and still getting the error (npm install):

..\fuse-bindings.cc(12): fatal error C1083: Cannot open include file: 'fuse.h': No such file or directory [C:\project\node_modules\fuse-bindings\build\fuse_bindings.vcxproj]

I tried to research as much as I can but I couldn't solve this
Any idea?
Thanks!

dokan status

I see the following warning in the docs.

WARNING: Dokany is still not quite stable. It can cause BSODs. Be careful.

Is Dokany still having BSOD issues or has it stabilized?

Thanks,
John

Export the FUSE based file system to windows

Hi,

Is there any example for samba exporting an FUSE based file system to windows using fuse-bindings?

After setting up the samba, windows can explorer the directory before mount my file system, so the samba setting should be correct. And after node program begin, it calls some fuse operations while I try to open the directory by double click it in windows, like

access(/)
getattr(/)
getattr(/desktop.ini)
getattr(/desktop.ini)
opendir(/)
readdir(/)
releasedir(/)
getattr(/desktop.ini)
getattr(/)

but end with error of no authority.

In my program, I just output the name of operations and cb(0) without any code, so my guess is there are something that need for windows missing.

Any suggestion? Thanks a lot!

options can't be at prototype

I've created my filesystem as a class, so the ops parameter of mount is an option of this class. I've tried to set a mount option on the prototype like this:

ExclFS.prototype.options = ['nonempty']

but doesn't work. On the other hand, setting it on the constructor at the instance level:

this.options = ['nonempty']

it works. I don't know if it's a fuse-bindings bug or a nan one (I think it's of the last one, in fact in the Get method), I'm telling it here just for the record.

OS X El Capitan

Not having any joy getting this working with El Capitan.

Tried lots of versions of node so guessing this is an OSX issue :(

What happens when running the example in readme is nothing, no error it just exits....

Any tips on debugging this?

How to implement writable file system?

I'm trying to implement FuSeQL, a simple readable and writable filesystem with SQLite as backend and fuse-bindings as bridge to FUSE.

So far, reading and listing seems to work but my mock write method is not called when i do a write-to redirect on the shell (with >), only when i do an append-to redirect (with >>). In both cases, i do get an error message:

/Volumes/Storage/io/fuseql ► echo "helo" > mnt/file-5.txt
bash: mnt/file-5.txt: Function not implemented
/Volumes/Storage/io/fuseql ► echo "helo" >> mnt/file-5.txt
bash: echo: write error: Input/output error

I can open files in the text editor, but when trying to save them, i likewise get the not implemented message. What is going wrong here?

(If anyone wants to run the code, install by cloning or with npm install fuseql; to re-build and mount, run npm run build && npm start).

[Question]What is the meaning of file descriptor in FUSE?

I tried to get fd by using below code.

ops.open = function (path, flags, cb) {
  var flag = toFlag(flags) // convert flags to a node style string
  ...
  const fd = fs.openSync(path);
}

But I think this code generates recursive call, so doesn't work against my expectation....
Can you tell me the meaning of fd in FUSE?

Thanks in advance...

Shouldn't utimens be utimes?

$ man utimens
No manual entry for utimens

$ man utimes
UTIMES(2)                   BSD System Calls Manual                  UTIMES(2)

NAME
     futimes, utimes -- set file access and modification times

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <sys/time.h>

     int
     futimes(int fildes, const struct timeval times[2]);

     int
     utimes(const char *path, const struct timeval times[2]);

I know it'd be an API break to change it, but I've never heard of utimens. Typo?

Stale links in readme (I am making typescript definitions for this library)

Link for mount options and FUSE api are stale and don't resolve.

Can you point me to a fresher ones? And can you tell in a few words what is a general translation from FUSE api into javascript expected types. I am making a .d.ts definitions file for this library, and I will PR it.

And, thank you for this nice library.

fuse silently reconnecting?

Apologies upfront for this being somewhat vague, but it seemed like filing an issue would be the best route to get some feedback.

I'm running fuse/fuse-bindings inside of a docker container, and consuming that filesystem inside of other docker containers, which mostly works great. But I'm running into an issue where occasionally something is causing the "consumer" docker containers to lose access to the fuse filesystem ("Transport endpoint is not connected" error).

I can reproduce a similar state by just restarting the process that's running the fuse-fs -- any pre-existing mounts that point to something inside the fuse-fs fail. Re-mounting them again works. This hints to me that maybe somehow fuse is being remounted internally in response to some event or error, which isn't surfaced to me at the node level? Looking through the code I didn't see anything obvious though.

Here's a repo I made with instructions on how to reproduce the restart failure mode:
https://github.com/boucher/docker-fuse-restart-test

Any ideas?

Add support for CUSE operations

CUSE is an extension of FUSE that adds support to write character devices drivers in userspace. It's already available in the mainline kernel since severa years ago, although probably it would need a kernel recompilation to enable it. It's easy to detect because it offer a new /dev/cuse entry, so it would be trivial to throw an error is it's not available.

fuse-bindings doesn't work on virtualbox

OS : xubuntu 18.04
node-version : 8.11.2

this simple example works fine on my host machine

var fuse = require('fuse-bindings')

var mountPath = process.platform !== 'win32' ? './mnt' : 'M:\\'

fuse.mount(mountPath, {
  readdir: function (path, cb) {
    console.log('readdir(%s)', path)
    if (path === '/') return cb(0, ['test'])
    cb(0)
  },
  getattr: function (path, cb) {
    console.log('getattr(%s)', path)
    if (path === '/') {
      cb(0, {
        mtime: new Date(),
        atime: new Date(),
        ctime: new Date(),
        nlink: 1,
        size: 100,
        mode: 16877,
        uid: process.getuid ? process.getuid() : 0,
        gid: process.getgid ? process.getgid() : 0
      })
      return
    }

    if (path === '/test') {
      cb(0, {
        mtime: new Date(),
        atime: new Date(),
        ctime: new Date(),
        nlink: 1,
        size: 12,
        mode: 33188,
        uid: process.getuid ? process.getuid() : 0,
        gid: process.getgid ? process.getgid() : 0
      })
      return
    }

    cb(fuse.ENOENT)
  },
  open: function (path, flags, cb) {
    console.log('open(%s, %d)', path, flags)
    cb(0, 42) // 42 is an fd
  },
  read: function (path, fd, buf, len, pos, cb) {
    console.log('read(%s, %d, %d, %d)', path, fd, len, pos)
    var str = 'hello world\n'.slice(pos, pos + len)
    if (!str) return cb(0)
    buf.write(str)
    return cb(str.length)
  }
}, function (err) {
  if (err) throw err
  console.log('filesystem mounted on ' + mountPath)
})

process.on('SIGINT', function () {
  fuse.unmount(mountPath, function (err) {
    if (err) {
      console.log('filesystem at ' + mountPath + ' not unmounted', err)
    } else {
      console.log('filesystem at ' + mountPath + ' unmounted')
    }
  })
})

but on guest machine (xubuntu 18.04) (when i run the same example) mounted directory is not accessible
https://i.imgur.com/ncvQxT9.png

[Question] How to support file renames?

I've got a writeable filesystem implemented successfully, however, I can't seem to figure out how to get file renames to work. I've implemented the rename operation, but if I try to rename a file, I get an EPERM: operation not permitted, rename error message. Just to double-check, I also set every file and directory's stat mode to include read/write/execute permissions for everyone, and I still can't seem to get rename working.

Is there a trick to getting this to work? My rename handler doesn't even appear to be getting called, so I seem to be missing something (that's probably obvious!). Any suggestions would be greatly appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.