natevw / fatfs

Standalone FAT16/FAT32 filesystem implementation in JavaScript
47 stars 13 forks source link

fatfs

A standalone FAT16/FAT32 implementation that takes in a block-access interface and exposes something quite similar to require('fs') (i.e. the node.js built-in Filesystem API).

Installation

npm install fatfs

Example

var fatfs = require('fatfs'),
    fs = fatfs.createFileSystem(exampleDriver);      // see below
fs.stat("autoexec.bat", function (e,stats) {
    if (e) console.error(e);
    else console.log(stats);
});
// TODO: open a file and write to it or something…

API

Filesystem options

The opts dictionary you pass to fatfs.createFileSystem can contain any of the following options:

(Note that these are similar to the options you could use with a POSIX mount operation.)

And that's it! The rest of the API (fs.readdir, fs.open, fs.createReadStream, fs.appendFile, etc.) is as documented by the node.js project.

Well, sort of…

Caveats

Temporary

As-planned

Some of the differences between fatfs and the node.js fs module are "by design" for architectural simplicity and/or due to underlying FAT limitations.

"Volume driver" API

To use 'fatfs', you must provide a driver object with the following properties/methods:

If you do not provide a writeSectors method, then fatfs will work in readonly mode. Pretty simple, eh? And the 'fatfs' module makes a good effort to check the parameters passed to your driver methods!

TBD: to facilitate proper cache handling, this module might add an optional driver.flush(cb) method at some point in the future.

Here's an example taken from code used to run this module's own tests:

// NOTE: this assumes image at `path` has no partition table.
//       If it did, you'd need to translate positions, natch…
var fs = require('fs');

exports.createDriverSync = function (path, opts) {
    opts || (opts = {});

    var secSize = 512,
        ro = opts.readOnly || false,
        fd = fs.openSync(path, (ro) ? 'r' : 'r+'),
        s = fs.fstatSync(fd);

    return {
        sectorSize: secSize,
        numSectors: s.size / secSize,
        readSectors: function (i, dest, cb) {
            if (dest.length % secSize) throw Error("Unexpected buffer length!");
            fs.read(fd, dest, 0, dest.length, i*secSize, function (e,n,d) {
                cb(e,d);
            });
        },
        writeSectors: (ro) ? null : function (i, data, cb) {
            if (data.length % secSize) throw Error("Unexpected buffer length!");
            fs.write(fd, data, 0, data.length, i*secSize, function (e) {
                cb(e);
            });
        }
    };
};

License

© 2014 Nathan Vander Wilt. Funding for this work was provided by Technical Machine, Inc.

Reuse under your choice of: