From 9baf9438ce9398ae541988ffa7bd93d8a0a8ec9d Mon Sep 17 00:00:00 2001 From: Alan K Date: Wed, 17 Dec 2014 17:22:38 -0500 Subject: [PATCH] Create gh-pages branch via GitHub --- images/bg_hr.png | Bin 0 -> 78 bytes images/blacktocat.png | Bin 0 -> 463 bytes images/icon_download.png | Bin 0 -> 216 bytes images/sprite_download.png | Bin 0 -> 14832 bytes index.html | 1567 ++++++++++++++++++++++++++++++++++ javascripts/main.js | 1 + params.json | 1 + stylesheets/pygment_trac.css | 70 ++ stylesheets/stylesheet.css | 425 +++++++++ 9 files changed, 2064 insertions(+) create mode 100644 images/bg_hr.png create mode 100644 images/blacktocat.png create mode 100644 images/icon_download.png create mode 100644 images/sprite_download.png create mode 100644 index.html create mode 100644 javascripts/main.js create mode 100644 params.json create mode 100644 stylesheets/pygment_trac.css create mode 100644 stylesheets/stylesheet.css diff --git a/images/bg_hr.png b/images/bg_hr.png new file mode 100644 index 0000000000000000000000000000000000000000..514aee5056a320b059a4b92fc31385b01f3fd707 GIT binary patch literal 78 zcmeAS@N?(olHy`uVBq!ia0vp^EI=&E!3HD~tNk5798VX=5Q)pl2@*yR?(8i7?>Hmz b1S7-U!)%xJ1CQbP0l+XkKg_jic literal 0 HcmV?d00001 diff --git a/images/blacktocat.png b/images/blacktocat.png new file mode 100644 index 0000000000000000000000000000000000000000..e160053a5bfc1f1891c5df1a04244b46132ed91c GIT binary patch literal 463 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX3?zBp#Z3TGW&u7Su0Z-f>EL7Xu|Ghaf+azI z!3+%h6VAUEXmGf1FkfMPe?Wo5`wP+x42q#I?$ zCZCHu*mLc{mj@jVb0qJie|tLrXx$RV*xy|DA2&%h)(GsqVy%>MraS!Shm183{#@F! zV^vm_@$^Y{GUuI-cUN0({K+A*SMX|j#GmyK98SEwQl?dz*($XqK|j>0;H2RlD{}=; zx7!XPy5}bEXEt-@-@Ngc#+nIgOgm!u=S(u>E&hLN(cd}Wb8P2o&P?9><1zE8l8pz9 zg==?S&3yIdUhdL~<_mg1Y!?@vTUiymeaGcy&vRcbOG}I6uI`9fxn}VP_6h8=I%b0Z Rq=4be;OXk;vd$@?2>`O9@hboT literal 0 HcmV?d00001 diff --git a/images/icon_download.png b/images/icon_download.png new file mode 100644 index 0000000000000000000000000000000000000000..5a793f17688b22d0c98f8b32855f69daff65afaf GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3^F3W0Lp+WrCrGd^PB3WLTm5|# z<3>ZVHGbLMPaA&Ni`7(Ic@)^~t}9m~#>{KX@F?FxM~Q7di>SquC^@HPOZ^)nnu6w= zPs-5Ln9{RS^v!FJ4Hk1|eLTx~WO~PjEv;gjQBoc84>y)53m9M4vW{f>=&v)a$*Fn% zwMt9Ivq1qGD=w^dyuiIx3lB69mQJ=Ex6cJ85q6@e`QPvJEsD4 ODubu1pUXO@geCwMBTRk( literal 0 HcmV?d00001 diff --git a/images/sprite_download.png b/images/sprite_download.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f8de24c1c49ce421a44ce2a24ac22d045a39fe GIT binary patch literal 14832 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 WAV6(21mh6^0000 + + + + + + + + + + Filer + + + + + +
+
+ View on GitHub + +

Filer

+

Node-like file system for browsers

+ +
+ Download this project as a .zip file + Download this project as a tar.gz file +
+
+
+ + +
+
+

NPM

+ +

Build Status

+ +

+Filer

+ +

Filer is a POSIX-like file system interface for node.js and browser-based JavaScript.

+ +

+Compatibility

+ +

Filer is known to work in the following browsers/versions, with the specified Storage Providers:

+ +
    +
  • node.js: v0.10.*+
  • +
  • IE: 10+ (IndexedDB)
  • +
  • Firefox: 26+ (IndexedDB)
  • +
  • Chrome: 31+ (IndexedDB, WebSQL)
  • +
  • Safari: 7.0+ (WebSQL)
  • +
  • Opera: 19+ (IndexedDB, WebSQL)
  • +
  • iOS: 3.2+ (WebSQL)
  • +
  • Android Browser: 2.1-4.4 (WebSQL), 4.4+ (IndexedDB)
  • +
+ +

NOTE: if you're interested in maximum compatibility, use the Fallback provider instead of Default. +See the section on Storage Providers.

+ +

+Contributing

+ +

Want to join the fun? We'd love to have you! See CONTRIBUTING.

+ +

+How to Get It

+ +

Filer can be obtained in a number of ways:

+ +
    +
  1. npm - npm install filer +
  2. +
  3. bower - bower install filer +
  4. +
  5. download pre-built versions: filer.js, filer.min.js +
  6. +
+ +

+Loading and Usage

+ +

Filer is built as a UMD module and can therefore be loaded as a CommonJS or AMD module, or used via the global.

+ +
// Option 1: Filer loaded via require() in node/browserify
+var Filer = require('filer');
+
+// Option 2: Filer loaded via RequireJS
+requirejs.config({
+  baseUrl: '/',
+  paths: {
+    'filer': 'filer/dist/filer'
+  }
+});
+requirejs(['filer'], function(Filer) {...}
+
+// Option 3: Filer on global
+var Filer = window.Filer;
+ +

+Getting Started

+ +

Filer is as close to the node.js fs module as possible, +with the following differences:

+ +
    +
  • No synchronous versions of methods (e.g., mkdir() but not mkdirSync()).
  • +
  • No permissions (e.g., no chown(), chmod(), etc.).
  • +
  • No support for stream-based operations (e.g., fs.ReadStream, fs.WriteStream).
  • +
+ +

Filer has other features lacking in node.js (e.g., swappable backend +storage providers, extended attributes, etc).

+ +

Like node.js, the API is asynchronous and most methods expect the caller to provide +a callback function (note: like node.js, Filer will supply one if it's missing). +Errors are passed to callbacks through the first parameter. As with node.js, +there is no guarantee that file system operations will be executed in the order +they are invoked. Ensure proper ordering by chaining operations in callbacks.

+ +

+Overview

+ +

To create a new file system or open an existing one, create a new FileSystem +instance. By default, a new IndexedDB +database is created for each file system. The file system can also use other +backend storage providers, for example WebSQL +or even RAM (i.e., for temporary storage). See the section on Storage Providers.

+ +
var fs = new Filer.FileSystem();
+fs.open('/myfile', 'w+', function(err, fd) {
+  if (err) throw err;
+  fs.close(fd, function(err) {
+    if (err) throw err;
+    fs.stat('/myfile', function(err, stats) {
+      if (err) throw err;
+      console.log('stats: ' + JSON.stringify(stats));
+    });
+  });
+});
+ +

For a complete list of FileSystem methods and examples, see the FileSystem Instance Methods +section below.

+ +

Filer also supports node's Path module. See the Filer.Path section below.

+ +

In addition, common shell operations (e.g., rm, touch, cat, etc.) are supported via the +FileSystemShell object, which can be obtained from, and used with a FileSystem. +See theFileSystemShell section below.

+ +

+API Reference

+ +

Like node.js, callbacks for methods that accept them are optional but suggested (i.e., if +you omit the callback, errors will be thrown as exceptions). The first callback parameter is +reserved for passing errors. It will be null if no errors occurred and should always be checked.

+ +

+Filer.FileSystem(options, callback) constructor

+ +

File system constructor, invoked to open an existing file system or create a new one. +Accepts two arguments: an options object, and an optional callback. The options +object can specify a number of optional arguments, including:

+ +
    +
  • +name: the name of the file system, defaults to '"local' +
  • +
  • +flags: an Array of one or more flags to use when creating/opening the file system: + +
      +
    • +'FORMAT' to force Filer to format (i.e., erase) the file system
    • +
    • +'NOCTIME' to force Filer to not update ctime on nodes when metadata changes (i.e., for better performance)
    • +
    • +'NOMTIME' to force Filer to not update mtime on nodes when data changes (i.e., for better performance)
    • +
    +
  • +
  • +provider: an explicit storage provider to use for the file system's database context provider. See the section on Storage Providers.
  • +
+ +

The callback function indicates when the file system is ready for use. Depending on the storage provider used, this might +be right away, or could take some time. The callback should expect two arguments: first, an error argument, which will be +null if everything worked; second, an instance, such that you can access the newly ready FileSystem instance. Also users +should check the file system's readyState and error properties to make sure it is usable.

+ +
var fs;
+
+function fsReady(err, fs) {
+  if(err) throw err;
+  // Safe to use fs now...
+}
+
+fs = new Filer.FileSystem({
+  name: "my-filesystem",
+  flags: [ 'FORMAT' ],
+  provider: new Filer.FileSystem.providers.Memory()
+}, fsReady);
+ +

NOTE: if the optional callback argument is not passed to the FileSystem constructor, +operations done on the resulting file system will be queued and run in sequence when +it becomes ready.

+ +

+Filer.FileSystem.providers - Storage Providers +

+ +

Filer can be configured to use a number of different storage providers. The provider object encapsulates all aspects +of data access, making it possible to swap in different backend storage options. There are currently 4 different +providers to choose from:

+ +
    +
  • +FileSystem.providers.IndexedDB() - uses IndexedDB
  • +
  • +FileSystem.providers.WebSQL() - uses WebSQL
  • +
  • +FileSystem.providers.Fallback() - attempts to use IndexedDB if possible, falling-back to WebSQL if necessary
  • +
  • +FileSystem.providers.Memory() - uses memory (not suitable for data that needs to survive the current session)
  • +
+ +

You can choose your provider when creating a FileSystem:

+ +
var FileSystem = Filer.FileSystem;
+var providers = FileSystem.providers;
+
+// Example 1: Use the default provider (currently IndexedDB)
+var fs1 = new FileSystem();
+
+// Example 2: Explicitly use IndexedDB
+var fs2 = new FileSystem({ provider: new providers.IndexedDB() });
+
+// Example 3: Use one of IndexedDB or WebSQL, whichever is supported
+var fs3 = new FileSystem({ provider: new providers.Fallback() });
+ +

Every provider has an isSupported() method, which returns true if the browser supports this provider:

+ +
if( Filer.FileSystem.providers.WebSQL.isSupported() ) {
+  // WebSQL provider will work in current environment...
+}
+ +

You can also write your own provider if you need a different backend. See the code in src/providers for details.

+ +

A number of other providers have been written, including:

+ + + +

+Filer.Buffer +

+ +

When reading and writing data, Filer follows node.js and uses Buffer. +When in a node.js environment, native Buffers can be used, or Filer.Buffer, which is a shortcut +to node's Buffer. In a browser, you can use also use Filer.Buffer.

+ +

NOTE: a Filer.Buffer in a browser is really an augmented Uint8Array (i.e., the node Buffer api +methods are added to the instance). See https://github.com/feross/buffer for more details. Additionally, unlike native Buffer, Filer.Buffer's constructor can accept ArrayBuffer objects, which will be interpreted as Uint8Arrays.

+ +

+Filer.Path +

+ +

The node.js path module is available via the Filer.Path object. It is +identical to the node.js version with the following differences:

+ +
    +
  • No notion of a current working directory in resolve (the root dir is used instead)
  • +
+ +
var path = Filer.Path;
+var dir = path.dirname('/foo/bar/baz/asdf/quux');
+// dir is now '/foo/bar/baz/asdf'
+
+var base = path.basename('/foo/bar/baz/asdf/quux.html');
+// base is now 'quux.html'
+
+var ext = path.extname('index.html');
+// ext is now '.html'
+
+var newpath = path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
+// new path is now '/foo/bar/baz/asdf'
+ +

For more info see the docs in the path module for a particular method:

+ +
    +
  • path.normalize(p)
  • +
  • path.join([path1], [path2], [...])
  • +
  • path.resolve([from ...], to)
  • +
  • path.relative(from, to)
  • +
  • path.dirname(p)
  • +
  • path.basename(p, [ext])
  • +
  • path.extname(p)
  • +
  • path.sep
  • +
  • path.delimiter
  • +
+ +

+Filer.Errors +

+ +

The error objects used internally by Filer are also exposed via the Filer.Errors object. As much as possible +these match their node.js counterparts, with a few Filer-specifc additions. +See src/errors.js for the complete +list. Errors can be used, or compared, like so:

+ +

Examples:

+ +
// Example 1: create an EExist error
+var err1 = new Filer.Errors.EEXIST();
+var err2 = new Filer.Errors[47];
+
+// Example 2: compare an error to see if it is EInvalid
+function callback(err) {
+  if(err instanceof Filer.Errors.EINVAL){
+    ...
+  }
+
+  // Or compare the error's code
+  if(err.code === 'EINVAL') {
+    ...
+  }
+}
+
+// Example 4: compare an error using errno
+function callback(err) {
+  if(err.errno === 47){
+    ...
+  }
+
+// Example 5: display the error message
+console.log(err.message);
+ +

+FileSystem Instance Methods +

+ +

Once a FileSystem is created, it has the following methods. NOTE: code examples below assume +a FileSystem instance named fs has been created like so:

+ +
var fs = new Filer.FileSystem();
+ + + +

+fs.rename(oldPath, newPath, callback) +

+ +

Renames the file at oldPath to newPath. Asynchronous rename(2). +Callback gets no additional arguments.

+ +

Example:

+ +
// Rename myfile.txt to myfile.bak
+fs.rename("/myfile.txt", "/myfile.bak", function(err) {
+  if(err) throw err;
+  // myfile.txt is now myfile.bak
+});
+ +

+fs.ftruncate(fd, len, callback) +

+ +

Change the size of the file represented by the open file descriptor fd to be length +len bytes. Asynchronous ftruncate(2). +If the file is larger than len, the extra bytes will be discarded; if smaller, its size will +be increased, and the extended area will appear as if it were zero-filled. See also fs.truncate().

+ +

Example:

+ +
// Create a file, shrink it, expand it.
+var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);
+
+fs.open('/myfile', 'w', function(err, fd) {
+  if(err) throw error;
+  fs.write(fd, buffer, 0, buffer.length, 0, function(err, result) {
+    if(err) throw error;
+      fs.ftruncate(fd, 3, function(err) {
+        if(err) throw error;
+        // /myfile is now 3 bytes in length, rest of data discarded
+
+        fs.ftruncate(fd, 50, function(err) {
+          if(err) throw error;
+          // /myfile is now 50 bytes in length, with zero padding at end
+
+          fs.close(fd);
+        });
+      });
+    });
+  });
+});
+ +

+fs.truncate(path, len, callback) +

+ +

Change the size of the file at path to be length len bytes. Asynchronous truncate(2). If the file is larger than len, the extra bytes will be discarded; if smaller, its size will +be increased, and the extended area will appear as if it were zero-filled. See also fs.ftruncate().

+ +

Example:

+ +
// Create a file, shrink it, expand it.
+var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);
+
+fs.open('/myfile', 'w', function(err, fd) {
+  if(err) throw error;
+  fs.write(fd, buffer, 0, buffer.length, 0, function(err, result) {
+    if(err) throw error;
+    fs.close(fd, function(err) {
+      if(err) throw error;
+
+      fs.truncate('/myfile', 3, function(err) {
+        if(err) throw error;
+        // /myfile is now 3 bytes in length, rest of data discarded
+
+        fs.truncate('/myfile', 50, function(err) {
+          if(err) throw error;
+          // /myfile is now 50 bytes in length, with zero padding at end
+
+        });
+      });
+    });
+  });
+});
+ +

+fs.stat(path, callback) +

+ +

Obtain file status about the file at path. Asynchronous stat(2). +Callback gets (error, stats), where stats is an object with the following properties:

+ +
{
+  node: <string>   // internal node id (unique)
+  dev: <string>    // file system name
+  size: <number>   // file size in bytes
+  nlinks: <number> // number of links
+  atime: <number>  // last access time
+  mtime: <number>  // last modified time
+  ctime: <number>  // creation time
+  type: <string>   // file type (FILE, DIRECTORY, SYMLINK)
+}
+
+ +

The following convenience methods are also present on the callback's stats:

+ +
isFile():             Returns true if the node is a file.
+isDirectory():        Returns true if the node is a directory.
+isBlockDevice():      Not implemented, returns false.
+isCharacterDevice():  Not implemented, returns false.
+isSymbolicLink():     Returns true if the node is a symbolic link.
+isFIFO():             Not implemented, returns false.
+isSocket():           Not implemented, returns false.
+
+ +

If the file at path is a symbolic link, the file to which it links will be used instead. +To get the status of a symbolic link file, use fs.lstat() instead.

+ +

Examples:

+ +
// Check if a directory exists
+function dirExists(path, callback) {
+  fs.stat(path, function(err, stats) {
+    if(err) return callback(err);
+    var exists = stats.type === "DIRECTORY";
+    callback(null, exists);
+  });
+};
+
+// Get the size of a file in KB
+function fileSize(path, callback) {
+  fs.stat(path, function(err, stats) {
+    if(err) return callback(err);
+    var kb = stats.size / 1000;
+    callback(null, kb);
+  });
+}
+ +

+fs.fstat(fd, callback) +

+ +

Obtain information about the open file known by the file descriptor fd. +Asynchronous fstat(2). +Callback gets (error, stats). fstat() is identical to stat(), except that the file to be stat-ed is +specified by the open file descriptor fd instead of a path. See also fs.stat

+ +

Example:

+ +
fs.open("/file.txt", "r", function(err, fd) {
+  if(err) throw err;
+  fs.fstat(fd, function(err, stats) {
+    if(err) throw err;
+    // do something with stats object
+    // ...
+    fs.close(fd);
+  });
+});
+ +

+fs.lstat(path, callback) +

+ +

Obtain information about the file at path (i.e., the symbolic link file itself) vs. +the destination file to which it links. Asynchronous lstat(2). +Callback gets (error, stats). See also fs.stat.

+ +

Example:

+ +
// Create a symbolic link, /data/logs/current to /data/logs/august
+// and get info about the symbolic link file, and linked file.
+fs.link("/data/logs/august", "/data/logs/current", function(err) {
+  if(err) throw err;
+
+  // Get status of linked file, /data/logs/august
+  fs.stat("/data/logs/current", function(err, stats) {
+    if(err) throw err;
+    // Size of /data/logs/august
+    var size = stats.size;
+  });
+
+  // Get status of symbolic link file itself
+  fs.lstat("/data/logs/current", function(err, stats) {
+    if(err) throw err;
+    // Size of /data/logs/current
+    var size = stats.size;
+  });
+});
+ +

+fs.exists(path, callback) +

+ +

Test whether or not the given path exists by checking with the file system. +Then call the callback argument with either true or false.

+ +

Example:

+ +
//Test if the file exists
+fs.exists('/myfile', function (exists) {
+  console.log(exists ? "file exists" : "file not found");
+});
+ +

fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.

+ +

In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.

+ +

+fs.link(srcPath, dstPath, callback) +

+ +

Create a (hard) link to the file at srcPath named dstPath. Asynchronous link(2). Callback gets no additional arguments. Links are directory entries that point to the same file node.

+ +

Example:

+ +
fs.link('/logs/august.log', '/logs/current', function(err) {
+  if(err) throw err;
+  fs.readFile('/logs/current', 'utf8', function(err, data) {
+    // data is the contents of /logs/august.log
+    var currentLog = data;
+  });
+});
+ +

+fs.symlink(srcPath, dstPath, [type], callback) +

+ +

Create a symbolic link to the file at dstPath containing the path srcPath. Asynchronous symlink(2). Callback gets no additional arguments. +Symbolic links are files that point to other paths.

+ +

NOTE: Filer allows for, but ignores the optional type parameter used in node.js.

+ +

Example:

+ +
fs.symlink('/logs/august.log', '/logs/current', function(err) {
+  if(err) throw err;
+  fs.readFile('/logs/current', 'utf8', function(err, data) {
+    // data is the contents of /logs/august.log
+    var currentLog = data;
+  });
+});
+ +

+fs.readlink(path, callback) +

+ +

Reads the contents of a symbolic link. Asynchronous readlink(2). Callback gets (error, linkContents), where linkContents is a string containing the symbolic link's link path.

+ +

Example:

+ +
fs.symlink('/logs/august.log', '/logs/current', function(error) {
+  if(error) throw error;
+
+  fs.readlink('/logs/current', function(error, linkContents) {
+    // linkContents is now '/logs/august.log'
+  });
+});
+ +

+fs.realpath(path, [cache], callback) +

+ +

NOTE: Not implemented, see https://github.com/filerjs/filer/issues/85

+ +

+fs.unlink(path, callback) +

+ +

Removes the directory entry located at path. Asynchronous unlink(2). +Callback gets no additional arguments. If path names a symbolic link, the symbolic link will be removed +(i.e., not the linked file). Otherwise, the filed named by path will be removed (i.e., deleted).

+ +

Example:

+ +
// Delete regular file /backup.old
+fs.unlink('/backup.old', function(err) {
+  if(err) throw err;
+  // /backup.old is now removed
+});
+ +

+fs.mknod(path, mode, callback) +

+ +

Creates a node at path based on the mode passed which is either FILE or DIRECTORY. Asynchronous mknod(2). Callback gets no additional arguments.

+ +

Example:

+ +
// Create a /dir directory
+fs.mknod('/dir', 'DIRECTORY', function(err) {
+  if(err) throw err;
+  // /dir is now created
+
+  // Create a file inside /dir
+  fs.mknod('/dir/myfile', 'FILE', function(err) {
+    if(err) throw err;
+    // /dir/myfile now exists
+  });
+});
+ +

+fs.rmdir(path, callback) +

+ +

Removes the directory at path. Asynchronous rmdir(2). +Callback gets no additional arguments. The operation will fail if the directory at path is not empty.

+ +

Example:

+ +
/**
+ * Given the following dir structure, remove docs/
+ *  /docs
+ *    a.txt
+ */
+
+// Start by deleting the files in docs/, then remove docs/
+fs.unlink('/docs/a.txt', function(err) {
+  if(err) throw err;
+  fs.rmdir('/docs', function(err) {
+    if(err) throw err;
+  });
+});
+ +

+fs.mkdir(path, [mode], callback) +

+ +

Makes a directory with name supplied in path argument. Asynchronous mkdir(2). Callback gets no additional arguments.

+ +

NOTE: Filer allows for, but ignores the optional mode argument used in node.js.

+ +

Example:

+ +
// Create /home and then /home/carl directories
+fs.mkdir('/home', function(err) {
+  if(err) throw err;
+
+  fs.mkdir('/home/carl', function(err) {
+    if(err) throw err;
+    // directory /home/carl now exists
+  });
+});
+ +

+fs.readdir(path, callback) +

+ +

Reads the contents of a directory. Asynchronous readdir(3). +Callback gets (error, files), where files is an array containing the names of each directory entry (i.e., file, directory, link) in the directory, excluding . and ...

+ +

Example:

+ +
/**
+ * Given the following dir structure:
+ *  /docs
+ *    a.txt
+ *    b.txt
+ *    c/
+ */
+fs.readdir('/docs', function(err, files) {
+  if(err) throw err;
+  // files now contains ['a.txt', 'b.txt', 'c']
+});
+ +

+fs.close(fd, callback) +

+ +

Closes a file descriptor. Asynchronous close(2). +Callback gets no additional arguments.

+ +

Example:

+ +
fs.open('/myfile', 'w', function(err, fd) {
+  if(err) throw error;
+
+  // Do something with open file descriptor `fd`
+
+  // Close file descriptor when done
+  fs.close(fd);
+});
+ +

+fs.open(path, flags, [mode], callback) +

+ +

Opens a file. Asynchronous open(2). +Callback gets (error, fd), where fd is the file descriptor. The flags argument can be:

+ +
    +
  • +'r': Open file for reading. An exception occurs if the file does not exist.
  • +
  • +'r+': Open file for reading and writing. An exception occurs if the file does not exist.
  • +
  • +'w': Open file for writing. The file is created (if it does not exist) or truncated (if it exists).
  • +
  • +'w+': Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
  • +
  • +'a': Open file for appending. The file is created if it does not exist.
  • +
  • +'a+': Open file for reading and appending. The file is created if it does not exist.
  • +
+ +

NOTE: Filer allows for, but ignores the optional mode argument used in node.js.

+ +

Example:

+ +
fs.open('/myfile', 'w', function(err, fd) {
+  if(err) throw error;
+
+  // Do something with open file descriptor `fd`
+
+  // Close file descriptor when done
+  fs.close(fd);
+});
+ +

+fs.utimes(path, atime, mtime, callback) +

+ +

Changes the file timestamps for the file given at path path. Asynchronous utimes(2). Callback gets no additional arguments. Both atime (access time) and mtime (modified time) arguments should be a JavaScript Date.

+ +

Example:

+ +
var now = Date.now();
+fs.utimes('/myfile.txt', now, now, function(err) {
+  if(err) throw err;
+  // Access Time and Modified Time for /myfile.txt are now updated
+});
+ +

+fs.futimes(fd, atime, mtime, callback) +

+ +

Changes the file timestamps for the open file represented by the file descriptor fd. Asynchronous utimes(2). Callback gets no additional arguments. Both atime (access time) and mtime (modified time) arguments should be a JavaScript Date.

+ +

Example:

+ +
fs.open('/myfile.txt', function(err, fd) {
+  if(err) throw err;
+
+  var now = Date.now();
+  fs.futimes(fd, now, now, function(err) {
+    if(err) throw err;
+
+    // Access Time and Modified Time for /myfile.txt are now updated
+
+    fs.close(fd);
+  });
+});
+ +

+fs.fsync(fd, callback) +

+ +

NOTE: Not yet implemented, see https://github.com/filerjs/filer/issues/87

+ +

+fs.write(fd, buffer, offset, length, position, callback) +

+ +

Writes bytes from buffer to the file specified by fd. Asynchronous write(2), pwrite(2). The offset and length arguments describe the part of the buffer to be written. The position refers to the offset from the beginning of the file where this data should be written. If position is null, the data will be written at the current position. The callback gets (error, nbytes), where nbytes is the number of bytes written.

+ +

NOTE: Filer currently writes the entire buffer in a single operation. However, future versions may do it in chunks.

+ +

Example:

+ +
// Create a file with the following bytes.
+var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);
+
+fs.open('/myfile', 'w', function(err, fd) {
+  if(err) throw error;
+
+  var expected = buffer.length, written = 0;
+  function writeBytes(offset, position, length) {
+    length = length || buffer.length - written;
+
+    fs.write(fd, buffer, offset, length, position, function(err, nbytes) {
+      if(err) throw error;
+
+      // nbytes is now the number of bytes written, between 0 and buffer.length.
+      // See if we still have more bytes to write.
+      written += nbytes;
+
+      if(written < expected)
+        writeBytes(written, null);
+      else
+        fs.close(fd);
+    });
+  }
+
+  writeBytes(0, 0);
+});
+ +

+fs.read(fd, buffer, offset, length, position, callback) +

+ +

Read bytes from the file specified by fd into buffer. Asynchronous read(2), pread(2). The offset and length arguments describe the part of the buffer to be used. The position refers to the offset from the beginning of the file where this data should be read. If position is null, the data will be written at the current position. The callback gets (error, nbytes), where nbytes is the number of bytes read.

+ +

NOTE: Filer currently reads into the buffer in a single operation. However, future versions may do it in chunks.

+ +

Example:

+ +
fs.open('/myfile', 'r', function(err, fd) {
+  if(err) throw error;
+
+  // Determine size of file
+  fs.fstat(fd, function(err, stats) {
+    if(err) throw error;
+
+    // Create a buffer large enough to hold the file's contents
+    var nbytes = expected = stats.size;
+    var buffer = new Filer.Buffer(nbytes);
+    var read = 0;
+
+    function readBytes(offset, position, length) {
+      length = length || buffer.length - read;
+
+      fs.read(fd, buffer, offset, length, position, function(err, nbytes) {
+        if(err) throw error;
+
+        // nbytes is now the number of bytes read, between 0 and buffer.length.
+        // See if we still have more bytes to read.
+        read += nbytes;
+
+        if(read < expected)
+          readBytes(read, null);
+        else
+          fs.close(fd);
+      });
+    }
+
+    readBytes(0, 0);
+  });
+});
+ +

+fs.readFile(filename, [options], callback) +

+ +

Reads the entire contents of a file. The options argument is optional, and can take the form "utf8" (i.e., an encoding) or be an object literal: { encoding: "utf8", flag: "r" }. If no encoding is specified, the raw binary buffer is returned via the callback. The callback gets (error, data), where data is the contents of the file.

+ +

Examples:

+ +
// Read UTF8 text file
+fs.readFile('/myfile.txt', 'utf8', function (err, data) {
+  if (err) throw err;
+  // data is now the contents of /myfile.txt (i.e., a String)
+});
+
+// Read binary file
+fs.readFile('/myfile.txt', function (err, data) {
+  if (err) throw err;
+  // data is now the contents of /myfile.txt (i.e., a Buffer with the bytes)
+});
+ +

+fs.writeFile(filename, data, [options], callback) +

+ +

Writes data to a file. data can be a string or Buffer, in which case any encoding option is ignored. The options argument is optional, and can take the form "utf8" (i.e., an encoding) or be an object literal: { encoding: "utf8", flag: "w" }. If no encoding is specified, and data is a string, the encoding defaults to 'utf8'. The callback gets (error).

+ +

Examples:

+ +
// Write UTF8 text file
+fs.writeFile('/myfile.txt', "...data...", function (err) {
+  if (err) throw err;
+});
+
+// Write binary file
+var buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);
+fs.writeFile('/myfile', buffer, function (err) {
+  if (err) throw err;
+});
+ +

+fs.appendFile(filename, data, [options], callback) +

+ +

Writes data to the end of a file. data can be a string or a Buffer, in which case any encoding option is ignored. The options argument is optional, and can take the form "utf8" (i.e., an encoding) or be an object literal: { encoding: "utf8", flag: "w" }. If no encoding is specified, and data is a string, the encoding defaults to 'utf8'. The callback gets (error).

+ +

Examples:

+ +
// Append UTF8 text file
+fs.writeFile('/myfile.txt', "More...", function (err) {
+    if (err) throw err;
+});
+fs.appendFile('/myfile.txt', "Data...", function (err) {
+  if (err) throw err;
+});
+// '/myfile.txt' would now read out 'More...Data...'
+
+// Append binary file
+var data = new Filer.Buffer([1, 2, 3, 4]);
+var more = new Filer.Buffer([5, 6, 7, 8]);
+
+fs.writeFile('/myfile', data, function (err) {
+  if (err) throw err;
+
+  fs.appendFile('/myfile', more, function (err) {
+    if (err) throw err;
+
+    // '/myfile' would now contain [1, 2, 3, 4, 5, 6, 7, 8]
+  });
+});
+ +

+fs.setxattr(path, name, value, [flag], callback) +

+ +

Sets an extended attribute of a file or directory named path. Asynchronous setxattr(2). +The optional flag parameter can be set to the following:

+ +
    +
  • +XATTR_CREATE: ensures that the extended attribute with the given name will be new and not previously set. If an attribute with the given name already exists, it will return an EExists error to the callback.
  • +
  • +XATTR_REPLACE: ensures that an extended attribute with the given name already exists. If an attribute with the given name does not exist, it will return an ENoAttr error to the callback.
  • +
+ +

Callback gets no additional arguments.

+ +

Example:

+ +
fs.writeFile('/myfile', 'data', function(err) {
+  if(err) throw err;
+
+  // Set a simple extended attribute on /myfile
+  fs.setxattr('/myfile', 'extra', 'some-information', function(err) {
+    if(err) throw err;
+
+    // /myfile now has an added attribute of extra='some-information'
+  });
+
+  // Set a complex object attribute on /myfile
+  fs.setxattr('/myfile', 'extra-complex', { key1: 'value1', key2: 103 }, function(err) {
+    if(err) throw err;
+
+    // /myfile now has an added attribute of extra={ key1: 'value1', key2: 103 }
+  });
+});
+ +

+fs.fsetxattr(fd, name, value, [flag], callback) +

+ +

Sets an extended attribute of the file represented by the open file descriptor fd. Asynchronous setxattr(2). See fs.setxattr for more details. Callback gets no additional arguments.

+ +

Example:

+ +
fs.open('/myfile', 'w', function(err, fd) {
+  if(err) throw err;
+
+  // Set a simple extended attribute on fd for /myfile
+  fs.fsetxattr(fd, 'extra', 'some-information', function(err) {
+    if(err) throw err;
+
+    // /myfile now has an added attribute of extra='some-information'
+  });
+
+  // Set a complex object attribute on fd for /myfile
+  fs.fsetxattr(fd, 'extra-complex', { key1: 'value1', key2: 103 }, function(err) {
+    if(err) throw err;
+
+    // /myfile now has an added attribute of extra={ key1: 'value1', key2: 103 }
+  });
+
+  fs.close(fd);
+});
+ +

+fs.getxattr(path, name, callback) +

+ +

Gets an extended attribute value for a file or directory. Asynchronous getxattr(2). +Callback gets (error, value), where value is the value for the extended attribute named name.

+ +

Example:

+ +
// Get the value of the extended attribute on /myfile named `extra`
+fs.getxattr('/myfile', 'extra', function(err, value) {
+  if(err) throw err;
+
+  // `value` is now the value of the extended attribute named `extra` for /myfile
+});
+ +

+fs.fgetxattr(fd, name, callback) +

+ +

Gets an extended attribute value for the file represented by the open file descriptor fd. +Asynchronous getxattr(2). +See fs.getxattr for more details. Callback gets (error, value), where value is the value for the extended attribute named name.

+ +

Example:

+ +
// Get the value of the extended attribute on /myfile named `extra`
+fs.open('/myfile', 'r', function(err, fd) {
+  if(err) throw err;
+
+  fs.fgetxattr(fd, 'extra', function(err, value) {
+    if(err) throw err;
+
+    // `value` is now the value of the extended attribute named `extra` for /myfile
+  });
+
+  fs.close(fd);
+});
+ +

+fs.removexattr(path, name, callback) +

+ +

Removes the extended attribute identified by name for the file given at path. Asynchronous removexattr(2). Callback gets no additional arguments.

+ +

Example:

+ +
// Remove an extended attribute on /myfile
+fs.removexattr('/myfile', 'extra', function(err) {
+  if(err) throw err;
+
+  // The `extra` extended attribute on /myfile is now gone
+});
+ +

+fs.fremovexattr(fd, name, callback) +

+ +

Removes the extended attribute identified by name for the file represented by the open file descriptor fd. +Asynchronous removexattr(2). See fs.removexattr for more details. +Callback gets no additional arguments.

+ +

Example:

+ +
// Remove an extended attribute on /myfile
+fs.open('/myfile', 'r', function(err, fd) {
+  if(err) throw err;
+
+  fs.fremovexattr(fd, 'extra', function(err) {
+    if(err) throw err;
+
+    // The `extra` extended attribute on /myfile is now gone
+  });
+
+  fs.close(fd);
+});
+ +

+fs.watch(filename, [options], [listener]) +

+ +

Watch for changes to a file or directory at filename. The object returned is an FSWatcher, +which is an EventEmitter with the following additional method:

+ +
    +
  • +close() - stops listening for changes, and removes all listeners from this instance. Use this +to stop watching a file or directory after calling fs.watch().
  • +
+ +

The only supported option is recursive, which if true will cause a watch to be placed +on a directory, and all sub-directories and files beneath it.

+ +

The listener callback gets two arguments (event, filename). event is either 'rename' or 'change', +(currenty only 'rename' is supported) and filename is the name of the file/dir which triggered the event.

+ +

Unlike node.js, all watch events return a path. Also, all returned paths are absolute from the root +vs. just a relative filename.

+ +

Examples:

+ +
// Example 1: create a watcher to see when a file is created
+var watcher = fs.watch('/myfile', function(event, filename) {
+  // event could be 'change' or 'rename' and filename will be '/myfile'
+  // Stop watching for changes
+  watcher.close();
+});
+fs.writeFile('/myfile', 'data');
+
+// Example 2: add the listener via watcher.on()
+var watcher = fs.watch('/myfile2');
+watcher.on('change', function(event, filename) {
+  // event will be 'change' and filename will be '/myfile2'
+  // Stop watching for changes
+  watcher.close();
+});
+fs.writeFile('/myfile2', 'data2');
+
+// Example 3: recursive watch on /data dir
+var watcher = fs.watch('/data', { recursive: true }, function(event, filename) {
+  // event could be 'change' or 'rename' and filename will be '/data/subdir/file'
+  // Stop watching for changes
+  watcher.close();
+});
+fs.writeFile('/data/subdir/file', 'data');
+ +

+FileSystemShell +

+ +

Many common file system shell operations are available by using a FileSystemShell object. +The FileSystemShell is used in conjuction with a FileSystem, +and provides augmented features. Many separate FileSystemShell objects can exist per +FileSystem, but each FileSystemShell is bound to a single instance of a FileSystem +for its lifetime.

+ +

A FileSystemShell is created by instantiating Filer.FileSystem().Shell:

+ +
var fs = new Filer.FileSystem();
+var sh = new fs.Shell(options);
+var sh2 = new fs.Shell(options);
+// sh and sh2 are two separate shells, each bound to fs
+ +

In addition, the constructor function can be accessed through Filer:

+ +
var fs = new Filer.FileSystem();
+var sh = new fs.Shell();
+
+Filer.Shell.prototype.newFunction = ...;
+
+sh.newFunction();
+ +

The FileSystemShell can take an optional options object. The options object +can include env, which is a set of environment variables. Currently supported variables +include TMP (the path to the temporary directory), and PATH (the list of known paths) and +others may be added in the future. You can also add your own, or update existing variables.

+ +
var fs = new Filer.FileSystem();
+var sh = new fs.Shell({
+  env: {
+    TMP: '/tempdir',
+    PATH: '/one:/two'
+  }
+});
+var tempPath = sh.env.get('TMP');
+sh.env.set('TMP', '/newtempdir');
+ +

NOTE: unless otherwise stated, all FileSystemShell methods can take relative or absolute +paths. Relative paths are resolved relative to the shell's current working directory (sh.cwd). +This is different from the FileSystem, which requires absolute paths, and has no notion +of a current working directory.

+ +

+FileSystemShell Properties

+ +

A FileSystemShell has a number of properties, including:

+ +
    +
  • +fs - (readonly) a reference to the bound FileSystem +
  • +
  • +env - (readonly) the shell's environment. The shell's environemnt env object has get(name) +and set(name, value) methods.
  • +
+ +

Example:

+ +
var fs = new Filer.FileSystem();
+var sh = new fs.Shell();
+var p = sh.env.get('PATH');
+
+// Store the current location
+var before = sh.pwd();
+var after;
+sh.cd('/newdir', function(err) {
+  if(err) throw err;
+  // Get the new location
+  after = sh.pwd();
+});
+ +

+FileSystemShell Instance Methods

+ +

Once a FileSystemShell object is created, it has the following methods. NOTE: code +examples below assume a FileSystemShell instance named sh has been created like so:

+ +
var fs = new Filer.FileSystem();
+var sh = new fs.Shell();
+ + + +

+sh.cd(path, callback) +

+ +

Changes the current working directory to the directory at path. The callback returns +an error if path does not exist, or is not a directory. Once the callback occurs +the shell's cwd is updated to the new path (you can access it via sh.pwd()).

+ +

Example:

+ +
sh.cd('/dir1', function(err) {
+  if(err) throw err;
+  // sh.pwd() is now '/dir1'
+});
+ +

+sh.pwd() +

+ +

Returns the shell's current working directory. See sh.cd().

+ +

+sh.find(dir, [options], callback) +

+ +

Recursively walk a directory tree, reporting back all paths that were +found along the way. Asynchronous find(1) +If given no options, find walks the given dir path +and the callback gives function(err, found), where found is an array of +all paths discovered during a depth-first walk.

+ +

Valid options include a regex for pattern matching paths, allowing paths +to be ignored (e.g., regex: /\.bak$/ to find all .bak files). You can +also use name and path to provide a match pattern for the basename and +dirname respectively (e.g., {name: '*.js'} to find all JavaScript files or +{path: '*-modules'} to only look in folders named base-modules, foo-modules, etc.). +Finally, you can also provide an exec function of the form function(path, next) where +path is the current path that was found and matches any provided regex +(NOTE: dir paths have an '/' appended), and next is a callback to call +when you are done processing the path.

+ +

Example:

+ +
function processPath(path, next) {
+  // Process the path somehow, in this case we print it.
+  // Dir paths end with /
+  if(path.endsWith('/')) {
+    console.log('Found dir: ' + path);
+  } else {
+    console.log('Found file: ' + path);
+  }
+
+  // All done, let the process continue by invoking second arg:
+  next();
+}
+
+// Get every path (NOTE: no name or regex provided) below the root, depth first
+sh.find('/', {exec: processPath}, function(err, found) {
+  /* find command is finished, `found` contains the flattened list as an Array */
+});
+
+// Find all files that look like map201.jpg, map202.jpg in the /data dir
+sh.find('/data', {regex: /map20\d\.jpg$/, exec: processPath}, function(err) {
+  /* find command is finished */
+});
+
+// Find and delete all *.bak files under /app/user
+sh.find('/app/user', {
+  name: '*.bak',
+  exec: function(path, next) {
+    sh.rm(path, next);
+  }
+}, function callback(err, found) {
+  if(err) throw err;
+
+  if(found.length) {
+    console.log('Deleted the following ' + found.length + ' files: ', found);
+  }
+});
+ +

+sh.ls(dir, [options], callback) +

+ +

Get the listing of a directory, returning an array of directory entries +in the following form:

+ +
{
+  path: <String> the basename of the directory entry
+  links: <Number> the number of links to the entry
+  size: <Number> the size in bytes of the entry
+  modified: <Number> the last modified date/time
+  type: <String> the type of the entry
+  contents: <Array> an optional array of child entries, if this entry is itself a directory
+}
+
+ +

By default sh.ls() gives a shallow listing. If you want to follow +directories as they are encountered, use the recursive=true option. NOTE: +you should not count on the order of the returned entries always being the same.

+ +

Example:

+ +
/**
+ * Given a dir structure of:
+ *
+ * /dir
+ *  file1
+ *  file2
+ *  dir2/
+ *   file3
+ */
+
+// Shallow listing
+sh.ls('/dir', function(err, entries) {
+  if(err) throw err;
+  // entries is now an array of 3 file/dir entries under /dir
+});
+
+// Deep listing
+sh.ls('/dir', { recursive: true }, function(err, entries) {
+  if(err) throw err;
+  // entries is now an array of 3 file/dir entries under /dir.
+  // The entry object for '/dir2' also includes a `contents` property,
+  // which is an array of 1 entry element for `file3`.
+});
+ +

+sh.exec(path, [args], callback) +

+ +

Attempts to execute the .js command located at path. The sh.exec method +enables apps to install larger programs into the file system and run them +later without having to re-download. Such commands should be written so as +to assume the existence of 3 global variables, which will be defined at runtime:

+ +
    +
  • +fs - [FileSystem] the FileSystem object bound to this shell.
  • +
  • +args - [Array] a list of any arguments for the command, or the empty list
  • +
  • +callback - [Function] a callback function of the form function callback(error, result) +to call when done.
  • +
+ +

The .js command's contents should be the body of a function that +looks like this:

+ +
function(fs, args, callback) {
+//-------------------------commmand code here---------
+// ...
+//----------------------------------------------------
+ }
+ +

Example:

+ +
// Simple command to delete a file.
+var cmd = "fs.unlink(args[0], callback);"
+
+// Write the file to the filesystem
+fs.writeFile('/cmd.js', cmd, callback(err) {
+  if(err) throw err;
+
+  // Execute the command
+  sh.exec('/cmd.js', [ '/file' ], function(err, result) {
+    if(err) throw err;
+  });
+});
+ +

+sh.touch(path, [options], callback) +

+ +

Create a file if it does not exist, or update the access and modified +times if it does. Valid options include:

+ +
    +
  • +updateOnly - true if the file's access/modified dates are to be updated +only (but missing file not to be)
  • +
  • +date - a date to use instead of the current date and time when updating +access and modified dates.
  • +
+ +

Example:

+ +
sh.touch('/newfile', function(err) {
+  if(err) throw err;
+
+  fs.exists('/newfile', function(exists) {
+    // exists is now true.
+  }
+});
+ +

+sh.cat(files, callback) +

+ +

Concatenates multiple files into a single string, with each file +separated by a newline character. The files argument should be +a String (i.e., path to a single file) or an Array of Strings (i.e., +multiple paths for multiple files).

+ +

Example:

+ +
sh.cat([ './file1', '../file2' ], function(err, data) {
+  if(err) throw err;
+  // data is now the contents of file1 and file2 joined
+});
+ +

+sh.rm(path, [options], callback) +

+ +

Removes (deletes) the file or directory at path. If path is a file, it will +be removed. If path is a directory, it will be removed if it is empty, otherwise +the callback will receive an error. In order to remove non-empty directories, +use the recursive=true option.

+ +

Example:

+ +
sh.rm('./file', function(err) {
+  if(err) throw err;
+  // ./file is now removed
+});
+
+sh.rm('/dir', { recursive: true }, function(err) {
+  if(err) throw err;
+  // /dir and all its children are now removed
+});
+ +

+sh.tempDir(callback) +

+ +

Gets the path to the shell's temporary directory, creating it if it +does not already exist. The temp directory to use is specified in the +env.TMP environment variable. The callback receives an error +and the tempDir path. NOTE: it is safe to call this many times (i.e., +the temp dir will only be created once). No effort is made to clean-up +the temp dir, and it is up to the caller to destroy it if desired.

+ +

Example:

+ +
// Default /tmp dir
+sh.tempDir(function(err, tmp) {
+  if(err) throw err;
+  // tmp is now '/tmp' by default, and /tmp exists
+});
+
+// Specify a tmp dir path
+sh.env.TMP = '/temporary'
+sh.tempDir(function(err, tmp) {
+  if(err) throw err;
+  // tmp is now '/temporary', and /temporary exists
+});
+ +

+sh.mkdirp(path, callback) +

+ +

Recursively creates the directory at the provided path. If the +directory already exists, no error is returned. All parents must +be valid directories (not files).

+ +

Example:

+ +
// Default empty filesystem
+sh.mkdirp('/test/mkdirp', function(err) {
+  if(err) throw err;
+  // the root '/' now contains a directory 'test' containing the directory 'mkdirp'
+});
+
+
+ + + + + + + + diff --git a/javascripts/main.js b/javascripts/main.js new file mode 100644 index 0000000..d8135d3 --- /dev/null +++ b/javascripts/main.js @@ -0,0 +1 @@ +console.log('This would be the main JS file.'); diff --git a/params.json b/params.json new file mode 100644 index 0000000..be4ce27 --- /dev/null +++ b/params.json @@ -0,0 +1 @@ +{"name":"Filer","tagline":"Node-like file system for browsers","body":"[![NPM](https://nodei.co/npm/filer.png?downloads=true&stars=true)](https://nodei.co/npm/filer/)\r\n\r\n[![Build Status](https://secure.travis-ci.org/filerjs/filer.png?branch=develop)](http://travis-ci.org/filerjs/filer)\r\n\r\n###Filer\r\n\r\nFiler is a POSIX-like file system interface for node.js and browser-based JavaScript.\r\n\r\n###Compatibility\r\n\r\nFiler is known to work in the following browsers/versions, with the specified [Storage Providers](#providers):\r\n\r\n* node.js: v0.10.*+\r\n* IE: 10+ (IndexedDB)\r\n* Firefox: 26+ (IndexedDB)\r\n* Chrome: 31+ (IndexedDB, WebSQL)\r\n* Safari: 7.0+ (WebSQL)\r\n* Opera: 19+ (IndexedDB, WebSQL)\r\n* iOS: 3.2+ (WebSQL)\r\n* Android Browser: 2.1-4.4 (WebSQL), 4.4+ (IndexedDB)\r\n\r\nNOTE: if you're interested in maximum compatibility, use the `Fallback` provider instead of `Default`.\r\nSee the section on [Storage Providers](#providers).\r\n\r\n### Contributing\r\n\r\nWant to join the fun? We'd love to have you! See [CONTRIBUTING](https://github.com/filerjs/filer/blob/develop/CONTRIBUTING.md).\r\n\r\n### How to Get It\r\n\r\nFiler can be obtained in a number of ways:\r\n\r\n1. npm - `npm install filer`\r\n2. bower - `bower install filer`\r\n3. download pre-built versions: [filer.js](https://raw.github.com/filerjs/filer/develop/dist/filer.js), [filer.min.js](https://raw.github.com/filerjs/filer/develop/dist/filer.min.js)\r\n\r\n### Loading and Usage\r\n\r\nFiler is built as a UMD module and can therefore be loaded as a CommonJS or AMD module, or used via the global.\r\n\r\n```javascript\r\n// Option 1: Filer loaded via require() in node/browserify\r\nvar Filer = require('filer');\r\n\r\n// Option 2: Filer loaded via RequireJS\r\nrequirejs.config({\r\n baseUrl: '/',\r\n paths: {\r\n 'filer': 'filer/dist/filer'\r\n }\r\n});\r\nrequirejs(['filer'], function(Filer) {...}\r\n\r\n// Option 3: Filer on global\r\nvar Filer = window.Filer;\r\n```\r\n\r\n### Getting Started\r\n\r\nFiler is as close to the node.js [fs module](http://nodejs.org/api/fs.html) as possible,\r\nwith the following differences:\r\n\r\n* No synchronous versions of methods (e.g., `mkdir()` but not `mkdirSync()`).\r\n* No permissions (e.g., no `chown()`, `chmod()`, etc.).\r\n* No support for stream-based operations (e.g., `fs.ReadStream`, `fs.WriteStream`).\r\n\r\nFiler has other features lacking in node.js (e.g., swappable backend\r\nstorage providers, extended attributes, etc).\r\n\r\nLike node.js, the API is asynchronous and most methods expect the caller to provide\r\na callback function (note: like node.js, Filer will supply one if it's missing).\r\nErrors are passed to callbacks through the first parameter. As with node.js,\r\nthere is no guarantee that file system operations will be executed in the order\r\nthey are invoked. Ensure proper ordering by chaining operations in callbacks.\r\n\r\n### Overview\r\n\r\nTo create a new file system or open an existing one, create a new `FileSystem`\r\ninstance. By default, a new [IndexedDB](https://developer.mozilla.org/en/docs/IndexedDB)\r\ndatabase is created for each file system. The file system can also use other\r\nbackend storage providers, for example [WebSQL](http://en.wikipedia.org/wiki/Web_SQL_Database)\r\nor even RAM (i.e., for temporary storage). See the section on [Storage Providers](#providers).\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\nfs.open('/myfile', 'w+', function(err, fd) {\r\n if (err) throw err;\r\n fs.close(fd, function(err) {\r\n if (err) throw err;\r\n fs.stat('/myfile', function(err, stats) {\r\n if (err) throw err;\r\n console.log('stats: ' + JSON.stringify(stats));\r\n });\r\n });\r\n});\r\n```\r\n\r\nFor a complete list of `FileSystem` methods and examples, see the [FileSystem Instance Methods](#FileSystemMethods)\r\nsection below.\r\n\r\nFiler also supports node's Path module. See the [Filer.Path](#FilerPath) section below.\r\n\r\nIn addition, common shell operations (e.g., rm, touch, cat, etc.) are supported via the\r\n`FileSystemShell` object, which can be obtained from, and used with a `FileSystem`.\r\nSee the[FileSystemShell](#FileSystemShell) section below.\r\n\r\n### API Reference\r\n\r\nLike node.js, callbacks for methods that accept them are optional but suggested (i.e., if\r\nyou omit the callback, errors will be thrown as exceptions). The first callback parameter is\r\nreserved for passing errors. It will be `null` if no errors occurred and should always be checked.\r\n\r\n#### Filer.FileSystem(options, callback) constructor\r\n\r\nFile system constructor, invoked to open an existing file system or create a new one.\r\nAccepts two arguments: an `options` object, and an optional `callback`. The `options`\r\nobject can specify a number of optional arguments, including:\r\n\r\n* `name`: the name of the file system, defaults to `'\"local'`\r\n* `flags`: an Array of one or more flags to use when creating/opening the file system:\r\n * `'FORMAT'` to force Filer to format (i.e., erase) the file system\r\n * `'NOCTIME'` to force Filer to not update `ctime` on nodes when metadata changes (i.e., for better performance)\r\n * `'NOMTIME'` to force Filer to not update `mtime` on nodes when data changes (i.e., for better performance)\r\n* `provider`: an explicit storage provider to use for the file system's database context provider. See the section on [Storage Providers](#providers).\r\n\r\nThe `callback` function indicates when the file system is ready for use. Depending on the storage provider used, this might\r\nbe right away, or could take some time. The callback should expect two arguments: first, an `error` argument, which will be\r\nnull if everything worked; second, an instance, such that you can access the newly ready FileSystem instance. Also users\r\nshould check the file system's `readyState` and `error` properties to make sure it is usable.\r\n\r\n```javascript\r\nvar fs;\r\n\r\nfunction fsReady(err, fs) {\r\n if(err) throw err;\r\n // Safe to use fs now...\r\n}\r\n\r\nfs = new Filer.FileSystem({\r\n name: \"my-filesystem\",\r\n flags: [ 'FORMAT' ],\r\n provider: new Filer.FileSystem.providers.Memory()\r\n}, fsReady);\r\n```\r\n\r\nNOTE: if the optional callback argument is not passed to the `FileSystem` constructor,\r\noperations done on the resulting file system will be queued and run in sequence when\r\nit becomes ready.\r\n\r\n####Filer.FileSystem.providers - Storage Providers\r\n\r\nFiler can be configured to use a number of different storage providers. The provider object encapsulates all aspects\r\nof data access, making it possible to swap in different backend storage options. There are currently 4 different\r\nproviders to choose from:\r\n\r\n* `FileSystem.providers.IndexedDB()` - uses IndexedDB\r\n* `FileSystem.providers.WebSQL()` - uses WebSQL\r\n* `FileSystem.providers.Fallback()` - attempts to use IndexedDB if possible, falling-back to WebSQL if necessary\r\n* `FileSystem.providers.Memory()` - uses memory (not suitable for data that needs to survive the current session)\r\n\r\nYou can choose your provider when creating a `FileSystem`:\r\n\r\n```javascript\r\nvar FileSystem = Filer.FileSystem;\r\nvar providers = FileSystem.providers;\r\n\r\n// Example 1: Use the default provider (currently IndexedDB)\r\nvar fs1 = new FileSystem();\r\n\r\n// Example 2: Explicitly use IndexedDB\r\nvar fs2 = new FileSystem({ provider: new providers.IndexedDB() });\r\n\r\n// Example 3: Use one of IndexedDB or WebSQL, whichever is supported\r\nvar fs3 = new FileSystem({ provider: new providers.Fallback() });\r\n```\r\n\r\nEvery provider has an `isSupported()` method, which returns `true` if the browser supports this provider:\r\n\r\n```javascript\r\nif( Filer.FileSystem.providers.WebSQL.isSupported() ) {\r\n // WebSQL provider will work in current environment...\r\n}\r\n```\r\n\r\nYou can also write your own provider if you need a different backend. See the code in `src/providers` for details.\r\n\r\nA number of other providers have been written, including:\r\n\r\n* node.js fs provider: https://github.com/humphd/filer-fs\r\n* node.js Amazon S3 provider: https://github.com/alicoding/filer-s3\r\n\r\n####Filer.Buffer\r\n\r\nWhen reading and writing data, Filer follows node.js and uses [`Buffer`](http://nodejs.org/api/buffer.html).\r\nWhen in a node.js environment, native `Buffer`s can be used, or Filer.Buffer, which is a shortcut\r\nto node's `Buffer`. In a browser, you can use also use `Filer.Buffer`.\r\n\r\nNOTE: a `Filer.Buffer` in a browser is really an augmented `Uint8Array` (i.e., the node `Buffer` api\r\nmethods are added to the instance). See https://github.com/feross/buffer for more details. Additionally, unlike native `Buffer`, `Filer.Buffer`'s constructor can accept `ArrayBuffer` objects, which will be interpreted as `Uint8Array`s.\r\n\r\n####Filer.Path\r\n\r\nThe node.js [path module](http://nodejs.org/api/path.html) is available via the `Filer.Path` object. It is\r\nidentical to the node.js version with the following differences:\r\n* No notion of a current working directory in `resolve` (the root dir is used instead)\r\n\r\n```javascript\r\nvar path = Filer.Path;\r\nvar dir = path.dirname('/foo/bar/baz/asdf/quux');\r\n// dir is now '/foo/bar/baz/asdf'\r\n\r\nvar base = path.basename('/foo/bar/baz/asdf/quux.html');\r\n// base is now 'quux.html'\r\n\r\nvar ext = path.extname('index.html');\r\n// ext is now '.html'\r\n\r\nvar newpath = path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');\r\n// new path is now '/foo/bar/baz/asdf'\r\n```\r\n\r\nFor more info see the docs in the [path module](http://nodejs.org/api/path.html) for a particular method:\r\n* `path.normalize(p)`\r\n* `path.join([path1], [path2], [...])`\r\n* `path.resolve([from ...], to)`\r\n* `path.relative(from, to)`\r\n* `path.dirname(p)`\r\n* `path.basename(p, [ext])`\r\n* `path.extname(p)`\r\n* `path.sep`\r\n* `path.delimiter`\r\n\r\n####Filer.Errors\r\n\r\nThe error objects used internally by Filer are also exposed via the `Filer.Errors` object. As much as possible\r\nthese match their node.js counterparts, with a few Filer-specifc additions.\r\nSee [src/errors.js](https://github.com/filerjs/filer/blob/develop/src/errors.js) for the complete\r\nlist. Errors can be used, or compared, like so:\r\n\r\nExamples:\r\n\r\n```javascript\r\n// Example 1: create an EExist error\r\nvar err1 = new Filer.Errors.EEXIST();\r\nvar err2 = new Filer.Errors[47];\r\n\r\n// Example 2: compare an error to see if it is EInvalid\r\nfunction callback(err) {\r\n if(err instanceof Filer.Errors.EINVAL){\r\n ...\r\n }\r\n\r\n // Or compare the error's code\r\n if(err.code === 'EINVAL') {\r\n ...\r\n }\r\n}\r\n\r\n// Example 4: compare an error using errno\r\nfunction callback(err) {\r\n if(err.errno === 47){\r\n ...\r\n }\r\n\r\n// Example 5: display the error message\r\nconsole.log(err.message);\r\n```\r\n\r\n###FileSystem Instance Methods\r\n\r\nOnce a `FileSystem` is created, it has the following methods. NOTE: code examples below assume\r\na `FileSystem` instance named `fs` has been created like so:\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\n```\r\n\r\n* [fs.rename(oldPath, newPath, callback)](#rename)\r\n* [fs.ftruncate(fd, len, callback)](#ftruncate)\r\n* [fs.truncate(path, len, callback)](#truncate)\r\n* [fs.stat(path, callback)](#stat)\r\n* [fs.fstat(fd, callback)](#fstat)\r\n* [fs.lstat(path, callback)](#lstat)\r\n* [fs.exists(path, callback)](#exists)\r\n* [fs.link(srcpath, dstpath, callback)](#link)\r\n* [fs.symlink(srcpath, dstpath, [type], callback)](#symlink)\r\n* [fs.readlink(path, callback)](#readlink)\r\n* [fs.realpath(path, [cache], callback)](#realpath)\r\n* [fs.unlink(path, callback)](#unlink)\r\n* [fs.mknod(path, mode, callback)](#mknod)\r\n* [fs.rmdir(path, callback)](#rmdir)\r\n* [fs.mkdir(path, [mode], callback)](#mkdir)\r\n* [fs.readdir(path, callback)](#readdir)\r\n* [fs.close(fd, callback)](#close)\r\n* [fs.open(path, flags, [mode], callback)](#open)\r\n* [fs.utimes(path, atime, mtime, callback)](#utimes)\r\n* [fs.futimes(fd, atime, mtime, callback)](#fsutimes)\r\n* [fs.fsync(fd, callback)](#fsync)\r\n* [fs.write(fd, buffer, offset, length, position, callback)](#write)\r\n* [fs.read(fd, buffer, offset, length, position, callback)](#read)\r\n* [fs.readFile(filename, [options], callback)](#readFile)\r\n* [fs.writeFile(filename, data, [options], callback)](#writeFile)\r\n* [fs.appendFile(filename, data, [options], callback)](#appendFile)\r\n* [fs.setxattr(path, name, value, [flag], callback)](#setxattr)\r\n* [fs.fsetxattr(fd, name, value, [flag], callback)](#fsetxattr)\r\n* [fs.getxattr(path, name, callback)](#getxattr)\r\n* [fs.fgetxattr(fd, name, callback)](#fgetxattr)\r\n* [fs.removexattr(path, name, callback)](#removexattr)\r\n* [fs.fremovexattr(fd, name, callback)](#fremovexattr)\r\n* [fs.watch(filename, [options], [listener])](#watch)\r\n\r\n#### fs.rename(oldPath, newPath, callback)\r\n\r\nRenames the file at `oldPath` to `newPath`. Asynchronous [rename(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/rename.html).\r\nCallback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Rename myfile.txt to myfile.bak\r\nfs.rename(\"/myfile.txt\", \"/myfile.bak\", function(err) {\r\n if(err) throw err;\r\n // myfile.txt is now myfile.bak\r\n});\r\n```\r\n\r\n#### fs.ftruncate(fd, len, callback)\r\n\r\nChange the size of the file represented by the open file descriptor `fd` to be length\r\n`len` bytes. Asynchronous [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/ftruncate.html).\r\nIf the file is larger than `len`, the extra bytes will be discarded; if smaller, its size will\r\nbe increased, and the extended area will appear as if it were zero-filled. See also [fs.truncate()](#truncate).\r\n\r\nExample:\r\n\r\n```javascript\r\n// Create a file, shrink it, expand it.\r\nvar buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);\r\n\r\nfs.open('/myfile', 'w', function(err, fd) {\r\n if(err) throw error;\r\n fs.write(fd, buffer, 0, buffer.length, 0, function(err, result) {\r\n if(err) throw error;\r\n fs.ftruncate(fd, 3, function(err) {\r\n if(err) throw error;\r\n // /myfile is now 3 bytes in length, rest of data discarded\r\n\r\n fs.ftruncate(fd, 50, function(err) {\r\n if(err) throw error;\r\n // /myfile is now 50 bytes in length, with zero padding at end\r\n\r\n fs.close(fd);\r\n });\r\n });\r\n });\r\n });\r\n});\r\n```\r\n\r\n#### fs.truncate(path, len, callback)\r\n\r\nChange the size of the file at `path` to be length `len` bytes. Asynchronous [truncate(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/truncate.html). If the file is larger than `len`, the extra bytes will be discarded; if smaller, its size will\r\nbe increased, and the extended area will appear as if it were zero-filled. See also [fs.ftruncate()](#ftruncate).\r\n\r\nExample:\r\n\r\n```javascript\r\n// Create a file, shrink it, expand it.\r\nvar buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);\r\n\r\nfs.open('/myfile', 'w', function(err, fd) {\r\n if(err) throw error;\r\n fs.write(fd, buffer, 0, buffer.length, 0, function(err, result) {\r\n if(err) throw error;\r\n fs.close(fd, function(err) {\r\n if(err) throw error;\r\n\r\n fs.truncate('/myfile', 3, function(err) {\r\n if(err) throw error;\r\n // /myfile is now 3 bytes in length, rest of data discarded\r\n\r\n fs.truncate('/myfile', 50, function(err) {\r\n if(err) throw error;\r\n // /myfile is now 50 bytes in length, with zero padding at end\r\n\r\n });\r\n });\r\n });\r\n });\r\n});\r\n```\r\n\r\n#### fs.stat(path, callback)\r\n\r\nObtain file status about the file at `path`. Asynchronous [stat(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html).\r\nCallback gets `(error, stats)`, where `stats` is an object with the following properties:\r\n\r\n```\r\n{\r\n node: // internal node id (unique)\r\n dev: // file system name\r\n size: // file size in bytes\r\n nlinks: // number of links\r\n atime: // last access time\r\n mtime: // last modified time\r\n ctime: // creation time\r\n type: // file type (FILE, DIRECTORY, SYMLINK)\r\n}\r\n```\r\n\r\nThe following convenience methods are also present on the callback's `stats`:\r\n\r\n```\r\nisFile(): Returns true if the node is a file.\r\nisDirectory(): Returns true if the node is a directory.\r\nisBlockDevice(): Not implemented, returns false.\r\nisCharacterDevice(): Not implemented, returns false.\r\nisSymbolicLink(): Returns true if the node is a symbolic link.\r\nisFIFO(): Not implemented, returns false.\r\nisSocket(): Not implemented, returns false.\r\n```\r\n\r\nIf the file at `path` is a symbolic link, the file to which it links will be used instead.\r\nTo get the status of a symbolic link file, use [fs.lstat()](#lstat) instead.\r\n\r\nExamples:\r\n\r\n```javascript\r\n// Check if a directory exists\r\nfunction dirExists(path, callback) {\r\n fs.stat(path, function(err, stats) {\r\n if(err) return callback(err);\r\n var exists = stats.type === \"DIRECTORY\";\r\n callback(null, exists);\r\n });\r\n};\r\n\r\n// Get the size of a file in KB\r\nfunction fileSize(path, callback) {\r\n fs.stat(path, function(err, stats) {\r\n if(err) return callback(err);\r\n var kb = stats.size / 1000;\r\n callback(null, kb);\r\n });\r\n}\r\n```\r\n\r\n#### fs.fstat(fd, callback)\r\n\r\nObtain information about the open file known by the file descriptor `fd`.\r\nAsynchronous [fstat(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/fstat.html).\r\nCallback gets `(error, stats)`. `fstat()` is identical to `stat()`, except that the file to be stat-ed is\r\nspecified by the open file descriptor `fd` instead of a path. See also [fs.stat](#stat)\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.open(\"/file.txt\", \"r\", function(err, fd) {\r\n if(err) throw err;\r\n fs.fstat(fd, function(err, stats) {\r\n if(err) throw err;\r\n // do something with stats object\r\n // ...\r\n fs.close(fd);\r\n });\r\n});\r\n```\r\n\r\n#### fs.lstat(path, callback)\r\n\r\nObtain information about the file at `path` (i.e., the symbolic link file itself) vs.\r\nthe destination file to which it links. Asynchronous [lstat(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/lstat.html).\r\nCallback gets `(error, stats)`. See also [fs.stat](#stat).\r\n\r\nExample:\r\n\r\n```javascript\r\n// Create a symbolic link, /data/logs/current to /data/logs/august\r\n// and get info about the symbolic link file, and linked file.\r\nfs.link(\"/data/logs/august\", \"/data/logs/current\", function(err) {\r\n if(err) throw err;\r\n\r\n // Get status of linked file, /data/logs/august\r\n fs.stat(\"/data/logs/current\", function(err, stats) {\r\n if(err) throw err;\r\n // Size of /data/logs/august\r\n var size = stats.size;\r\n });\r\n\r\n // Get status of symbolic link file itself\r\n fs.lstat(\"/data/logs/current\", function(err, stats) {\r\n if(err) throw err;\r\n // Size of /data/logs/current\r\n var size = stats.size;\r\n });\r\n});\r\n```\r\n\r\n#### fs.exists(path, callback)\r\n\r\nTest whether or not the given path exists by checking with the file system.\r\nThen call the callback argument with either true or false.\r\n\r\nExample:\r\n\r\n```javascript\r\n//Test if the file exists\r\nfs.exists('/myfile', function (exists) {\r\n console.log(exists ? \"file exists\" : \"file not found\");\r\n});\r\n```\r\n\r\nfs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.\r\n\r\nIn particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.\r\n\r\n#### fs.link(srcPath, dstPath, callback)\r\n\r\nCreate a (hard) link to the file at `srcPath` named `dstPath`. Asynchronous [link(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/link.html). Callback gets no additional arguments. Links are directory entries that point to the same file node.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.link('/logs/august.log', '/logs/current', function(err) {\r\n if(err) throw err;\r\n fs.readFile('/logs/current', 'utf8', function(err, data) {\r\n // data is the contents of /logs/august.log\r\n var currentLog = data;\r\n });\r\n});\r\n```\r\n\r\n#### fs.symlink(srcPath, dstPath, [type], callback)\r\n\r\nCreate a symbolic link to the file at `dstPath` containing the path `srcPath`. Asynchronous [symlink(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/symlink.html). Callback gets no additional arguments.\r\nSymbolic links are files that point to other paths.\r\n\r\nNOTE: Filer allows for, but ignores the optional `type` parameter used in node.js.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.symlink('/logs/august.log', '/logs/current', function(err) {\r\n if(err) throw err;\r\n fs.readFile('/logs/current', 'utf8', function(err, data) {\r\n // data is the contents of /logs/august.log\r\n var currentLog = data;\r\n });\r\n});\r\n```\r\n\r\n#### fs.readlink(path, callback)\r\n\r\nReads the contents of a symbolic link. Asynchronous [readlink(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/readlink.html). Callback gets `(error, linkContents)`, where `linkContents` is a string containing the symbolic link's link path.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.symlink('/logs/august.log', '/logs/current', function(error) {\r\n if(error) throw error;\r\n\r\n fs.readlink('/logs/current', function(error, linkContents) {\r\n // linkContents is now '/logs/august.log'\r\n });\r\n});\r\n```\r\n\r\n#### fs.realpath(path, [cache], callback)\r\n\r\nNOTE: Not implemented, see https://github.com/filerjs/filer/issues/85\r\n\r\n#### fs.unlink(path, callback)\r\n\r\nRemoves the directory entry located at `path`. Asynchronous [unlink(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/unlink.html).\r\nCallback gets no additional arguments. If `path` names a symbolic link, the symbolic link will be removed\r\n(i.e., not the linked file). Otherwise, the filed named by `path` will be removed (i.e., deleted).\r\n\r\nExample:\r\n\r\n```javascript\r\n// Delete regular file /backup.old\r\nfs.unlink('/backup.old', function(err) {\r\n if(err) throw err;\r\n // /backup.old is now removed\r\n});\r\n```\r\n\r\n#### fs.mknod(path, mode, callback)\r\n\r\nCreates a node at `path` based on the mode passed which is either `FILE` or `DIRECTORY`. Asynchronous [mknod(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/mknod.html). Callback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Create a /dir directory\r\nfs.mknod('/dir', 'DIRECTORY', function(err) {\r\n if(err) throw err;\r\n // /dir is now created\r\n\r\n // Create a file inside /dir\r\n fs.mknod('/dir/myfile', 'FILE', function(err) {\r\n if(err) throw err;\r\n // /dir/myfile now exists\r\n });\r\n});\r\n```\r\n\r\n#### fs.rmdir(path, callback)\r\n\r\nRemoves the directory at `path`. Asynchronous [rmdir(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html).\r\nCallback gets no additional arguments. The operation will fail if the directory at `path` is not empty.\r\n\r\nExample:\r\n\r\n```javascript\r\n/**\r\n * Given the following dir structure, remove docs/\r\n * /docs\r\n * a.txt\r\n */\r\n\r\n// Start by deleting the files in docs/, then remove docs/\r\nfs.unlink('/docs/a.txt', function(err) {\r\n if(err) throw err;\r\n fs.rmdir('/docs', function(err) {\r\n if(err) throw err;\r\n });\r\n});\r\n```\r\n\r\n#### fs.mkdir(path, [mode], callback)\r\n\r\nMakes a directory with name supplied in `path` argument. Asynchronous [mkdir(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/mkdir.html). Callback gets no additional arguments.\r\n\r\nNOTE: Filer allows for, but ignores the optional `mode` argument used in node.js.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Create /home and then /home/carl directories\r\nfs.mkdir('/home', function(err) {\r\n if(err) throw err;\r\n\r\n fs.mkdir('/home/carl', function(err) {\r\n if(err) throw err;\r\n // directory /home/carl now exists\r\n });\r\n});\r\n```\r\n\r\n#### fs.readdir(path, callback)\r\n\r\nReads the contents of a directory. Asynchronous [readdir(3)](http://pubs.opengroup.org/onlinepubs/009695399/functions/readdir.html).\r\nCallback gets `(error, files)`, where `files` is an array containing the names of each directory entry (i.e., file, directory, link) in the directory, excluding `.` and `..`.\r\n\r\nExample:\r\n\r\n```javascript\r\n/**\r\n * Given the following dir structure:\r\n * /docs\r\n * a.txt\r\n * b.txt\r\n * c/\r\n */\r\nfs.readdir('/docs', function(err, files) {\r\n if(err) throw err;\r\n // files now contains ['a.txt', 'b.txt', 'c']\r\n});\r\n```\r\n\r\n#### fs.close(fd, callback)\r\n\r\nCloses a file descriptor. Asynchronous [close(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/close.html).\r\nCallback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.open('/myfile', 'w', function(err, fd) {\r\n if(err) throw error;\r\n\r\n // Do something with open file descriptor `fd`\r\n\r\n // Close file descriptor when done\r\n fs.close(fd);\r\n});\r\n```\r\n\r\n#### fs.open(path, flags, [mode], callback)\r\n\r\nOpens a file. Asynchronous [open(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html).\r\nCallback gets `(error, fd)`, where `fd` is the file descriptor. The `flags` argument can be:\r\n\r\n* `'r'`: Open file for reading. An exception occurs if the file does not exist.\r\n* `'r+'`: Open file for reading and writing. An exception occurs if the file does not exist.\r\n* `'w'`: Open file for writing. The file is created (if it does not exist) or truncated (if it exists).\r\n* `'w+'`: Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).\r\n* `'a'`: Open file for appending. The file is created if it does not exist.\r\n* `'a+'`: Open file for reading and appending. The file is created if it does not exist.\r\n\r\nNOTE: Filer allows for, but ignores the optional `mode` argument used in node.js.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.open('/myfile', 'w', function(err, fd) {\r\n if(err) throw error;\r\n\r\n // Do something with open file descriptor `fd`\r\n\r\n // Close file descriptor when done\r\n fs.close(fd);\r\n});\r\n```\r\n\r\n#### fs.utimes(path, atime, mtime, callback)\r\n\r\nChanges the file timestamps for the file given at path `path`. Asynchronous [utimes(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/utimes.html). Callback gets no additional arguments. Both `atime` (access time) and `mtime` (modified time) arguments should be a JavaScript Date.\r\n\r\nExample:\r\n\r\n```javascript\r\nvar now = Date.now();\r\nfs.utimes('/myfile.txt', now, now, function(err) {\r\n if(err) throw err;\r\n // Access Time and Modified Time for /myfile.txt are now updated\r\n});\r\n```\r\n\r\n#### fs.futimes(fd, atime, mtime, callback)\r\n\r\nChanges the file timestamps for the open file represented by the file descriptor `fd`. Asynchronous [utimes(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/utimes.html). Callback gets no additional arguments. Both `atime` (access time) and `mtime` (modified time) arguments should be a JavaScript Date.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.open('/myfile.txt', function(err, fd) {\r\n if(err) throw err;\r\n\r\n var now = Date.now();\r\n fs.futimes(fd, now, now, function(err) {\r\n if(err) throw err;\r\n\r\n // Access Time and Modified Time for /myfile.txt are now updated\r\n\r\n fs.close(fd);\r\n });\r\n});\r\n```\r\n\r\n#### fs.fsync(fd, callback)\r\n\r\nNOTE: Not yet implemented, see https://github.com/filerjs/filer/issues/87\r\n\r\n#### fs.write(fd, buffer, offset, length, position, callback)\r\n\r\nWrites bytes from `buffer` to the file specified by `fd`. Asynchronous [write(2), pwrite(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html). The `offset` and `length` arguments describe the part of the buffer to be written. The `position` refers to the offset from the beginning of the file where this data should be written. If `position` is `null`, the data will be written at the current position. The callback gets `(error, nbytes)`, where `nbytes` is the number of bytes written.\r\n\r\nNOTE: Filer currently writes the entire buffer in a single operation. However, future versions may do it in chunks.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Create a file with the following bytes.\r\nvar buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);\r\n\r\nfs.open('/myfile', 'w', function(err, fd) {\r\n if(err) throw error;\r\n\r\n var expected = buffer.length, written = 0;\r\n function writeBytes(offset, position, length) {\r\n length = length || buffer.length - written;\r\n\r\n fs.write(fd, buffer, offset, length, position, function(err, nbytes) {\r\n if(err) throw error;\r\n\r\n // nbytes is now the number of bytes written, between 0 and buffer.length.\r\n // See if we still have more bytes to write.\r\n written += nbytes;\r\n\r\n if(written < expected)\r\n writeBytes(written, null);\r\n else\r\n fs.close(fd);\r\n });\r\n }\r\n\r\n writeBytes(0, 0);\r\n});\r\n```\r\n\r\n#### fs.read(fd, buffer, offset, length, position, callback)\r\n\r\nRead bytes from the file specified by `fd` into `buffer`. Asynchronous [read(2), pread(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html). The `offset` and `length` arguments describe the part of the buffer to be used. The `position` refers to the offset from the beginning of the file where this data should be read. If `position` is `null`, the data will be written at the current position. The callback gets `(error, nbytes)`, where `nbytes` is the number of bytes read.\r\n\r\nNOTE: Filer currently reads into the buffer in a single operation. However, future versions may do it in chunks.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.open('/myfile', 'r', function(err, fd) {\r\n if(err) throw error;\r\n\r\n // Determine size of file\r\n fs.fstat(fd, function(err, stats) {\r\n if(err) throw error;\r\n\r\n // Create a buffer large enough to hold the file's contents\r\n var nbytes = expected = stats.size;\r\n var buffer = new Filer.Buffer(nbytes);\r\n var read = 0;\r\n\r\n function readBytes(offset, position, length) {\r\n length = length || buffer.length - read;\r\n\r\n fs.read(fd, buffer, offset, length, position, function(err, nbytes) {\r\n if(err) throw error;\r\n\r\n // nbytes is now the number of bytes read, between 0 and buffer.length.\r\n // See if we still have more bytes to read.\r\n read += nbytes;\r\n\r\n if(read < expected)\r\n readBytes(read, null);\r\n else\r\n fs.close(fd);\r\n });\r\n }\r\n\r\n readBytes(0, 0);\r\n });\r\n});\r\n```\r\n\r\n#### fs.readFile(filename, [options], callback)\r\n\r\nReads the entire contents of a file. The `options` argument is optional, and can take the form `\"utf8\"` (i.e., an encoding) or be an object literal: `{ encoding: \"utf8\", flag: \"r\" }`. If no encoding is specified, the raw binary buffer is returned via the callback. The callback gets `(error, data)`, where data is the contents of the file.\r\n\r\nExamples:\r\n\r\n```javascript\r\n// Read UTF8 text file\r\nfs.readFile('/myfile.txt', 'utf8', function (err, data) {\r\n if (err) throw err;\r\n // data is now the contents of /myfile.txt (i.e., a String)\r\n});\r\n\r\n// Read binary file\r\nfs.readFile('/myfile.txt', function (err, data) {\r\n if (err) throw err;\r\n // data is now the contents of /myfile.txt (i.e., a Buffer with the bytes)\r\n});\r\n```\r\n\r\n#### fs.writeFile(filename, data, [options], callback)\r\n\r\nWrites data to a file. `data` can be a string or `Buffer`, in which case any encoding option is ignored. The `options` argument is optional, and can take the form `\"utf8\"` (i.e., an encoding) or be an object literal: `{ encoding: \"utf8\", flag: \"w\" }`. If no encoding is specified, and `data` is a string, the encoding defaults to `'utf8'`. The callback gets `(error)`.\r\n\r\nExamples:\r\n\r\n```javascript\r\n// Write UTF8 text file\r\nfs.writeFile('/myfile.txt', \"...data...\", function (err) {\r\n if (err) throw err;\r\n});\r\n\r\n// Write binary file\r\nvar buffer = new Filer.Buffer([1, 2, 3, 4, 5, 6, 7, 8]);\r\nfs.writeFile('/myfile', buffer, function (err) {\r\n if (err) throw err;\r\n});\r\n```\r\n\r\n#### fs.appendFile(filename, data, [options], callback)\r\n\r\nWrites data to the end of a file. `data` can be a string or a `Buffer`, in which case any encoding option is ignored. The `options` argument is optional, and can take the form `\"utf8\"` (i.e., an encoding) or be an object literal: `{ encoding: \"utf8\", flag: \"w\" }`. If no encoding is specified, and `data` is a string, the encoding defaults to `'utf8'`. The callback gets `(error)`.\r\n\r\nExamples:\r\n\r\n```javascript\r\n// Append UTF8 text file\r\nfs.writeFile('/myfile.txt', \"More...\", function (err) {\r\n\tif (err) throw err;\r\n});\r\nfs.appendFile('/myfile.txt', \"Data...\", function (err) {\r\n if (err) throw err;\r\n});\r\n// '/myfile.txt' would now read out 'More...Data...'\r\n\r\n// Append binary file\r\nvar data = new Filer.Buffer([1, 2, 3, 4]);\r\nvar more = new Filer.Buffer([5, 6, 7, 8]);\r\n\r\nfs.writeFile('/myfile', data, function (err) {\r\n if (err) throw err;\r\n\r\n fs.appendFile('/myfile', more, function (err) {\r\n if (err) throw err;\r\n\r\n // '/myfile' would now contain [1, 2, 3, 4, 5, 6, 7, 8]\r\n });\r\n});\r\n```\r\n\r\n#### fs.setxattr(path, name, value, [flag], callback)\r\n\r\nSets an extended attribute of a file or directory named `path`. Asynchronous [setxattr(2)](http://man7.org/linux/man-pages/man2/setxattr.2.html).\r\nThe optional `flag` parameter can be set to the following:\r\n* `XATTR_CREATE`: ensures that the extended attribute with the given name will be new and not previously set. If an attribute with the given name already exists, it will return an `EExists` error to the callback.\r\n* `XATTR_REPLACE`: ensures that an extended attribute with the given name already exists. If an attribute with the given name does not exist, it will return an `ENoAttr` error to the callback.\r\n\r\nCallback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.writeFile('/myfile', 'data', function(err) {\r\n if(err) throw err;\r\n\r\n // Set a simple extended attribute on /myfile\r\n fs.setxattr('/myfile', 'extra', 'some-information', function(err) {\r\n if(err) throw err;\r\n\r\n // /myfile now has an added attribute of extra='some-information'\r\n });\r\n\r\n // Set a complex object attribute on /myfile\r\n fs.setxattr('/myfile', 'extra-complex', { key1: 'value1', key2: 103 }, function(err) {\r\n if(err) throw err;\r\n\r\n // /myfile now has an added attribute of extra={ key1: 'value1', key2: 103 }\r\n });\r\n});\r\n```\r\n\r\n#### fs.fsetxattr(fd, name, value, [flag], callback)\r\n\r\nSets an extended attribute of the file represented by the open file descriptor `fd`. Asynchronous [setxattr(2)](http://man7.org/linux/man-pages/man2/setxattr.2.html). See `fs.setxattr` for more details. Callback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\nfs.open('/myfile', 'w', function(err, fd) {\r\n if(err) throw err;\r\n\r\n // Set a simple extended attribute on fd for /myfile\r\n fs.fsetxattr(fd, 'extra', 'some-information', function(err) {\r\n if(err) throw err;\r\n\r\n // /myfile now has an added attribute of extra='some-information'\r\n });\r\n\r\n // Set a complex object attribute on fd for /myfile\r\n fs.fsetxattr(fd, 'extra-complex', { key1: 'value1', key2: 103 }, function(err) {\r\n if(err) throw err;\r\n\r\n // /myfile now has an added attribute of extra={ key1: 'value1', key2: 103 }\r\n });\r\n\r\n fs.close(fd);\r\n});\r\n```\r\n\r\n#### fs.getxattr(path, name, callback)\r\n\r\nGets an extended attribute value for a file or directory. Asynchronous [getxattr(2)](http://man7.org/linux/man-pages/man2/getxattr.2.html).\r\nCallback gets `(error, value)`, where `value` is the value for the extended attribute named `name`.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Get the value of the extended attribute on /myfile named `extra`\r\nfs.getxattr('/myfile', 'extra', function(err, value) {\r\n if(err) throw err;\r\n\r\n // `value` is now the value of the extended attribute named `extra` for /myfile\r\n});\r\n```\r\n\r\n#### fs.fgetxattr(fd, name, callback)\r\n\r\nGets an extended attribute value for the file represented by the open file descriptor `fd`.\r\nAsynchronous [getxattr(2)](http://man7.org/linux/man-pages/man2/getxattr.2.html).\r\nSee `fs.getxattr` for more details. Callback gets `(error, value)`, where `value` is the value for the extended attribute named `name`.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Get the value of the extended attribute on /myfile named `extra`\r\nfs.open('/myfile', 'r', function(err, fd) {\r\n if(err) throw err;\r\n\r\n fs.fgetxattr(fd, 'extra', function(err, value) {\r\n if(err) throw err;\r\n\r\n // `value` is now the value of the extended attribute named `extra` for /myfile\r\n });\r\n\r\n fs.close(fd);\r\n});\r\n```\r\n\r\n#### fs.removexattr(path, name, callback)\r\n\r\nRemoves the extended attribute identified by `name` for the file given at `path`. Asynchronous [removexattr(2)](http://man7.org/linux/man-pages/man2/removexattr.2.html). Callback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Remove an extended attribute on /myfile\r\nfs.removexattr('/myfile', 'extra', function(err) {\r\n if(err) throw err;\r\n\r\n // The `extra` extended attribute on /myfile is now gone\r\n});\r\n```\r\n\r\n#### fs.fremovexattr(fd, name, callback)\r\n\r\nRemoves the extended attribute identified by `name` for the file represented by the open file descriptor `fd`.\r\nAsynchronous [removexattr(2)](http://man7.org/linux/man-pages/man2/removexattr.2.html). See `fs.removexattr` for more details.\r\nCallback gets no additional arguments.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Remove an extended attribute on /myfile\r\nfs.open('/myfile', 'r', function(err, fd) {\r\n if(err) throw err;\r\n\r\n fs.fremovexattr(fd, 'extra', function(err) {\r\n if(err) throw err;\r\n\r\n // The `extra` extended attribute on /myfile is now gone\r\n });\r\n\r\n fs.close(fd);\r\n});\r\n```\r\n\r\n#### fs.watch(filename, [options], [listener])\r\n\r\nWatch for changes to a file or directory at `filename`. The object returned is an `FSWatcher`,\r\nwhich is an [`EventEmitter`](http://nodejs.org/api/events.html) with the following additional method:\r\n\r\n* `close()` - stops listening for changes, and removes all listeners from this instance. Use this\r\nto stop watching a file or directory after calling `fs.watch()`.\r\n\r\nThe only supported option is `recursive`, which if `true` will cause a watch to be placed\r\non a directory, and all sub-directories and files beneath it.\r\n\r\nThe `listener` callback gets two arguments `(event, filename)`. `event` is either `'rename'` or `'change'`,\r\n(currenty only `'rename'` is supported) and `filename` is the name of the file/dir which triggered the event.\r\n\r\nUnlike node.js, all watch events return a path. Also, all returned paths are absolute from the root\r\nvs. just a relative filename.\r\n\r\nExamples:\r\n\r\n```javascript\r\n// Example 1: create a watcher to see when a file is created\r\nvar watcher = fs.watch('/myfile', function(event, filename) {\r\n // event could be 'change' or 'rename' and filename will be '/myfile'\r\n // Stop watching for changes\r\n watcher.close();\r\n});\r\nfs.writeFile('/myfile', 'data');\r\n\r\n// Example 2: add the listener via watcher.on()\r\nvar watcher = fs.watch('/myfile2');\r\nwatcher.on('change', function(event, filename) {\r\n // event will be 'change' and filename will be '/myfile2'\r\n // Stop watching for changes\r\n watcher.close();\r\n});\r\nfs.writeFile('/myfile2', 'data2');\r\n\r\n// Example 3: recursive watch on /data dir\r\nvar watcher = fs.watch('/data', { recursive: true }, function(event, filename) {\r\n // event could be 'change' or 'rename' and filename will be '/data/subdir/file'\r\n // Stop watching for changes\r\n watcher.close();\r\n});\r\nfs.writeFile('/data/subdir/file', 'data');\r\n```\r\n\r\n### FileSystemShell\r\n\r\nMany common file system shell operations are available by using a `FileSystemShell` object.\r\nThe `FileSystemShell` is used in conjuction with a `FileSystem`,\r\nand provides augmented features. Many separate `FileSystemShell` objects can exist per\r\n`FileSystem`, but each `FileSystemShell` is bound to a single instance of a `FileSystem`\r\nfor its lifetime.\r\n\r\nA `FileSystemShell` is created by instantiating `Filer.FileSystem().Shell`:\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\nvar sh = new fs.Shell(options);\r\nvar sh2 = new fs.Shell(options);\r\n// sh and sh2 are two separate shells, each bound to fs\r\n```\r\n\r\nIn addition, the constructor function can be accessed through `Filer`:\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\nvar sh = new fs.Shell();\r\n\r\nFiler.Shell.prototype.newFunction = ...;\r\n\r\nsh.newFunction();\r\n```\r\n\r\nThe `FileSystemShell` can take an optional `options` object. The `options` object\r\ncan include `env`, which is a set of environment variables. Currently supported variables\r\ninclude `TMP` (the path to the temporary directory), and `PATH` (the list of known paths) and\r\nothers may be added in the future. You can also add your own, or update existing variables.\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\nvar sh = new fs.Shell({\r\n env: {\r\n TMP: '/tempdir',\r\n PATH: '/one:/two'\r\n }\r\n});\r\nvar tempPath = sh.env.get('TMP');\r\nsh.env.set('TMP', '/newtempdir');\r\n```\r\n\r\nNOTE: unless otherwise stated, all `FileSystemShell` methods can take relative or absolute\r\npaths. Relative paths are resolved relative to the shell's current working directory (`sh.cwd`).\r\nThis is different from the `FileSystem`, which requires absolute paths, and has no notion\r\nof a current working directory.\r\n\r\n#### FileSystemShell Properties\r\n\r\nA `FileSystemShell` has a number of properties, including:\r\n* `fs` - (readonly) a reference to the bound `FileSystem`\r\n* `env` - (readonly) the shell's environment. The shell's environemnt `env` object has `get(name)`\r\nand `set(name, value)` methods.\r\n\r\nExample:\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\nvar sh = new fs.Shell();\r\nvar p = sh.env.get('PATH');\r\n\r\n// Store the current location\r\nvar before = sh.pwd();\r\nvar after;\r\nsh.cd('/newdir', function(err) {\r\n if(err) throw err;\r\n // Get the new location\r\n after = sh.pwd();\r\n});\r\n```\r\n\r\n#### FileSystemShell Instance Methods\r\n\r\nOnce a `FileSystemShell` object is created, it has the following methods. NOTE: code\r\nexamples below assume a `FileSystemShell` instance named `sh` has been created like so:\r\n\r\n```javascript\r\nvar fs = new Filer.FileSystem();\r\nvar sh = new fs.Shell();\r\n```\r\n\r\n* [sh.cd(path, callback)](#cd)\r\n* [sh.pwd()](#pwd)\r\n* [sh.find(dir, [options], callback)](#find)\r\n* [sh.ls(dir, [options], callback)](#ls)\r\n* [sh.exec(path, [args], callback)](#exec)\r\n* [sh.touch(path, [options], callback)](#touch)\r\n* [sh.cat(files, callback)](#cat)\r\n* [sh.rm(path, [options], callback)](#rm)\r\n* [sh.tempDir(callback)](#tempDir)\r\n* [sh.mkdirp(path, callback)](#mkdirp)\r\n\r\n\r\n#### sh.cd(path, callback)\r\n\r\nChanges the current working directory to the directory at `path`. The callback returns\r\nan error if `path` does not exist, or is not a directory. Once the callback occurs\r\nthe shell's cwd is updated to the new path (you can access it via `sh.pwd()`).\r\n\r\nExample:\r\n\r\n```javascript\r\nsh.cd('/dir1', function(err) {\r\n if(err) throw err;\r\n // sh.pwd() is now '/dir1'\r\n});\r\n```\r\n\r\n#### sh.pwd()\r\n\r\nReturns the shell's current working directory. See [sh.cd()](#cd).\r\n\r\n#### sh.find(dir, [options], callback)\r\n\r\nRecursively walk a directory tree, reporting back all paths that were\r\nfound along the way. Asynchronous [find(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html\r\n)\r\nIf given no options, `find` walks the given dir path\r\nand the callback gives `function(err, found)`, where `found` is an array of\r\nall paths discovered during a depth-first walk.\r\n\r\nValid options include a `regex` for pattern matching paths, allowing paths\r\nto be ignored (e.g., ```regex: /\\.bak$/``` to find all `.bak` files). You can\r\nalso use `name` and `path` to provide a [match pattern](https://github.com/isaacs/minimatch) for the basename and\r\ndirname respectively (e.g., `{name: '*.js'}` to find all JavaScript files or\r\n`{path: '*-modules'}` to only look in folders named `base-modules`, `foo-modules`, etc.).\r\nFinally, you can also provide an `exec` function of the form `function(path, next)` where\r\n`path` is the current path that was found and matches any provided `regex`\r\n(NOTE: dir paths have an '/' appended), and `next` is a callback to call\r\nwhen you are done processing the path.\r\n\r\nExample:\r\n\r\n```javascript\r\nfunction processPath(path, next) {\r\n // Process the path somehow, in this case we print it.\r\n // Dir paths end with /\r\n if(path.endsWith('/')) {\r\n console.log('Found dir: ' + path);\r\n } else {\r\n console.log('Found file: ' + path);\r\n }\r\n\r\n // All done, let the process continue by invoking second arg:\r\n next();\r\n}\r\n\r\n// Get every path (NOTE: no name or regex provided) below the root, depth first\r\nsh.find('/', {exec: processPath}, function(err, found) {\r\n /* find command is finished, `found` contains the flattened list as an Array */\r\n});\r\n\r\n// Find all files that look like map201.jpg, map202.jpg in the /data dir\r\nsh.find('/data', {regex: /map20\\d\\.jpg$/, exec: processPath}, function(err) {\r\n /* find command is finished */\r\n});\r\n\r\n// Find and delete all *.bak files under /app/user\r\nsh.find('/app/user', {\r\n name: '*.bak',\r\n exec: function(path, next) {\r\n sh.rm(path, next);\r\n }\r\n}, function callback(err, found) {\r\n if(err) throw err;\r\n\r\n if(found.length) {\r\n console.log('Deleted the following ' + found.length + ' files: ', found);\r\n }\r\n});\r\n```\r\n\r\n#### sh.ls(dir, [options], callback)\r\n\r\nGet the listing of a directory, returning an array of directory entries\r\nin the following form:\r\n```\r\n{\r\n path: the basename of the directory entry\r\n links: the number of links to the entry\r\n size: the size in bytes of the entry\r\n modified: the last modified date/time\r\n type: the type of the entry\r\n contents: an optional array of child entries, if this entry is itself a directory\r\n}\r\n```\r\n\r\nBy default `sh.ls()` gives a shallow listing. If you want to follow\r\ndirectories as they are encountered, use the `recursive=true` option. NOTE:\r\nyou should not count on the order of the returned entries always being the same.\r\n\r\nExample:\r\n\r\n```javascript\r\n/**\r\n * Given a dir structure of:\r\n *\r\n * /dir\r\n * file1\r\n * file2\r\n * dir2/\r\n * file3\r\n */\r\n\r\n// Shallow listing\r\nsh.ls('/dir', function(err, entries) {\r\n if(err) throw err;\r\n // entries is now an array of 3 file/dir entries under /dir\r\n});\r\n\r\n// Deep listing\r\nsh.ls('/dir', { recursive: true }, function(err, entries) {\r\n if(err) throw err;\r\n // entries is now an array of 3 file/dir entries under /dir.\r\n // The entry object for '/dir2' also includes a `contents` property,\r\n // which is an array of 1 entry element for `file3`.\r\n});\r\n```\r\n\r\n#### sh.exec(path, [args], callback)\r\n\r\nAttempts to execute the .js command located at `path`. The `sh.exec` method\r\nenables apps to install larger programs into the file system and run them\r\nlater without having to re-download. Such commands should be written so as\r\nto assume the existence of 3 global variables, which will be defined at runtime:\r\n* `fs` - [FileSystem] the `FileSystem` object bound to this shell.\r\n* `args` - [Array] a list of any arguments for the command, or the empty list\r\n* `callback` - [Function] a callback function of the form `function callback(error, result)`\r\nto call when done.\r\n\r\nThe .js command's contents should be the body of a function that\r\nlooks like this:\r\n\r\n```javascript\r\nfunction(fs, args, callback) {\r\n//-------------------------commmand code here---------\r\n// ...\r\n//----------------------------------------------------\r\n }\r\n```\r\n\r\nExample:\r\n\r\n```javascript\r\n// Simple command to delete a file.\r\nvar cmd = \"fs.unlink(args[0], callback);\"\r\n\r\n// Write the file to the filesystem\r\nfs.writeFile('/cmd.js', cmd, callback(err) {\r\n if(err) throw err;\r\n\r\n // Execute the command\r\n sh.exec('/cmd.js', [ '/file' ], function(err, result) {\r\n if(err) throw err;\r\n });\r\n});\r\n```\r\n\r\n#### sh.touch(path, [options], callback)\r\n\r\nCreate a file if it does not exist, or update the access and modified\r\ntimes if it does. Valid options include:\r\n* `updateOnly` - `true` if the file's access/modified dates are to be updated\r\nonly (but missing file not to be)\r\n* `date` - a date to use instead of the current date and time when updating\r\naccess and modified dates.\r\n\r\nExample:\r\n\r\n```javascript\r\nsh.touch('/newfile', function(err) {\r\n if(err) throw err;\r\n\r\n fs.exists('/newfile', function(exists) {\r\n // exists is now true.\r\n }\r\n});\r\n```\r\n\r\n#### sh.cat(files, callback)\r\n\r\nConcatenates multiple files into a single string, with each file\r\nseparated by a newline character. The `files` argument should be\r\na String (i.e., path to a single file) or an Array of Strings (i.e.,\r\nmultiple paths for multiple files).\r\n\r\nExample:\r\n\r\n```javascript\r\nsh.cat([ './file1', '../file2' ], function(err, data) {\r\n if(err) throw err;\r\n // data is now the contents of file1 and file2 joined\r\n});\r\n```\r\n\r\n#### sh.rm(path, [options], callback)\r\n\r\nRemoves (deletes) the file or directory at `path`. If `path` is a file, it will\r\nbe removed. If `path` is a directory, it will be removed if it is empty, otherwise\r\nthe callback will receive an error. In order to remove non-empty directories,\r\nuse the `recursive=true` option.\r\n\r\nExample:\r\n\r\n```javascript\r\nsh.rm('./file', function(err) {\r\n if(err) throw err;\r\n // ./file is now removed\r\n});\r\n\r\nsh.rm('/dir', { recursive: true }, function(err) {\r\n if(err) throw err;\r\n // /dir and all its children are now removed\r\n});\r\n```\r\n\r\n#### sh.tempDir(callback)\r\n\r\nGets the path to the shell's temporary directory, creating it if it\r\ndoes not already exist. The temp directory to use is specified in the\r\n`env.TMP` environment variable. The callback receives an error\r\nand the `tempDir` path. NOTE: it is safe to call this many times (i.e.,\r\nthe temp dir will only be created once). No effort is made to clean-up\r\nthe temp dir, and it is up to the caller to destroy it if desired.\r\n\r\nExample:\r\n\r\n```javascript\r\n// Default /tmp dir\r\nsh.tempDir(function(err, tmp) {\r\n if(err) throw err;\r\n // tmp is now '/tmp' by default, and /tmp exists\r\n});\r\n\r\n// Specify a tmp dir path\r\nsh.env.TMP = '/temporary'\r\nsh.tempDir(function(err, tmp) {\r\n if(err) throw err;\r\n // tmp is now '/temporary', and /temporary exists\r\n});\r\n```\r\n\r\n#### sh.mkdirp(path, callback)\r\n\r\nRecursively creates the directory at the provided path. If the\r\ndirectory already exists, no error is returned. All parents must\r\nbe valid directories (not files).\r\n\r\nExample:\r\n\r\n```javascript\r\n// Default empty filesystem\r\nsh.mkdirp('/test/mkdirp', function(err) {\r\n if(err) throw err;\r\n // the root '/' now contains a directory 'test' containing the directory 'mkdirp'\r\n});\r\n```\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css new file mode 100644 index 0000000..e65cedf --- /dev/null +++ b/stylesheets/pygment_trac.css @@ -0,0 +1,70 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f0f3f3; } +.highlight .c { color: #0099FF; font-style: italic } /* Comment */ +.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */ +.highlight .k { color: #006699; font-weight: bold } /* Keyword */ +.highlight .o { color: #555555 } /* Operator */ +.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #009999 } /* Comment.Preproc */ +.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */ +.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ +.highlight .go { color: #AAAAAA } /* Generic.Output */ +.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #99CC66 } /* Generic.Traceback */ +.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #006699 } /* Keyword.Pseudo */ +.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #FF6600 } /* Literal.Number */ +.highlight .s { color: #CC3300 } /* Literal.String */ +.highlight .na { color: #330099 } /* Name.Attribute */ +.highlight .nb { color: #336666 } /* Name.Builtin */ +.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */ +.highlight .no { color: #336600 } /* Name.Constant */ +.highlight .nd { color: #9999FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #CC00FF } /* Name.Function */ +.highlight .nl { color: #9999FF } /* Name.Label */ +.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #003333 } /* Name.Variable */ +.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #FF6600 } /* Literal.Number.Float */ +.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */ +.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */ +.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */ +.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */ +.highlight .sc { color: #CC3300 } /* Literal.String.Char */ +.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #CC3300 } /* Literal.String.Double */ +.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */ +.highlight .si { color: #AA0000 } /* Literal.String.Interpol */ +.highlight .sx { color: #CC3300 } /* Literal.String.Other */ +.highlight .sr { color: #33AAAA } /* Literal.String.Regex */ +.highlight .s1 { color: #CC3300 } /* Literal.String.Single */ +.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */ +.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #003333 } /* Name.Variable.Class */ +.highlight .vg { color: #003333 } /* Name.Variable.Global */ +.highlight .vi { color: #003333 } /* Name.Variable.Instance */ +.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */ + +.type-csharp .highlight .k { color: #0000FF } +.type-csharp .highlight .kt { color: #0000FF } +.type-csharp .highlight .nf { color: #000000; font-weight: normal } +.type-csharp .highlight .nc { color: #2B91AF } +.type-csharp .highlight .nn { color: #000000 } +.type-csharp .highlight .s { color: #A31515 } +.type-csharp .highlight .sc { color: #A31515 } diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css new file mode 100644 index 0000000..619d19d --- /dev/null +++ b/stylesheets/stylesheet.css @@ -0,0 +1,425 @@ +/******************************************************************************* +Slate Theme for GitHub Pages +by Jason Costello, @jsncostello +*******************************************************************************/ + +@import url(pygment_trac.css); + +/******************************************************************************* +MeyerWeb Reset +*******************************************************************************/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +ol, ul { + list-style: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/******************************************************************************* +Theme Styles +*******************************************************************************/ + +body { + box-sizing: border-box; + color:#373737; + background: #212121; + font-size: 16px; + font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +h1, h2, h3, h4, h5, h6 { + margin: 10px 0; + font-weight: 700; + color:#222222; + font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; + letter-spacing: -1px; +} + +h1 { + font-size: 36px; + font-weight: 700; +} + +h2 { + padding-bottom: 10px; + font-size: 32px; + background: url('../images/bg_hr.png') repeat-x bottom; +} + +h3 { + font-size: 24px; +} + +h4 { + font-size: 21px; +} + +h5 { + font-size: 18px; +} + +h6 { + font-size: 16px; +} + +p { + margin: 10px 0 15px 0; +} + +footer p { + color: #f2f2f2; +} + +a { + text-decoration: none; + color: #007edf; + text-shadow: none; + + transition: color 0.5s ease; + transition: text-shadow 0.5s ease; + -webkit-transition: color 0.5s ease; + -webkit-transition: text-shadow 0.5s ease; + -moz-transition: color 0.5s ease; + -moz-transition: text-shadow 0.5s ease; + -o-transition: color 0.5s ease; + -o-transition: text-shadow 0.5s ease; + -ms-transition: color 0.5s ease; + -ms-transition: text-shadow 0.5s ease; +} + +a:hover, a:focus {text-decoration: underline;} + +footer a { + color: #F2F2F2; + text-decoration: underline; +} + +em { + font-style: italic; +} + +strong { + font-weight: bold; +} + +img { + position: relative; + margin: 0 auto; + max-width: 739px; + padding: 5px; + margin: 10px 0 10px 0; + border: 1px solid #ebebeb; + + box-shadow: 0 0 5px #ebebeb; + -webkit-box-shadow: 0 0 5px #ebebeb; + -moz-box-shadow: 0 0 5px #ebebeb; + -o-box-shadow: 0 0 5px #ebebeb; + -ms-box-shadow: 0 0 5px #ebebeb; +} + +p img { + display: inline; + margin: 0; + padding: 0; + vertical-align: middle; + text-align: center; + border: none; +} + +pre, code { + width: 100%; + color: #222; + background-color: #fff; + + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + font-size: 14px; + + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +pre { + width: 100%; + padding: 10px; + box-shadow: 0 0 10px rgba(0,0,0,.1); + overflow: auto; +} + +code { + padding: 3px; + margin: 0 3px; + box-shadow: 0 0 10px rgba(0,0,0,.1); +} + +pre code { + display: block; + box-shadow: none; +} + +blockquote { + color: #666; + margin-bottom: 20px; + padding: 0 0 0 20px; + border-left: 3px solid #bbb; +} + + +ul, ol, dl { + margin-bottom: 15px +} + +ul { + list-style-position: inside; + list-style: disc; + padding-left: 20px; +} + +ol { + list-style-position: inside; + list-style: decimal; + padding-left: 20px; +} + +dl dt { + font-weight: bold; +} + +dl dd { + padding-left: 20px; + font-style: italic; +} + +dl p { + padding-left: 20px; + font-style: italic; +} + +hr { + height: 1px; + margin-bottom: 5px; + border: none; + background: url('../images/bg_hr.png') repeat-x center; +} + +table { + border: 1px solid #373737; + margin-bottom: 20px; + text-align: left; + } + +th { + font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif; + padding: 10px; + background: #373737; + color: #fff; + } + +td { + padding: 10px; + border: 1px solid #373737; + } + +form { + background: #f2f2f2; + padding: 20px; +} + +/******************************************************************************* +Full-Width Styles +*******************************************************************************/ + +.outer { + width: 100%; +} + +.inner { + position: relative; + max-width: 640px; + padding: 20px 10px; + margin: 0 auto; +} + +#forkme_banner { + display: block; + position: absolute; + top:0; + right: 10px; + z-index: 10; + padding: 10px 50px 10px 10px; + color: #fff; + background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%; + font-weight: 700; + box-shadow: 0 0 10px rgba(0,0,0,.5); + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + +#header_wrap { + background: #212121; + background: -moz-linear-gradient(top, #373737, #212121); + background: -webkit-linear-gradient(top, #373737, #212121); + background: -ms-linear-gradient(top, #373737, #212121); + background: -o-linear-gradient(top, #373737, #212121); + background: linear-gradient(top, #373737, #212121); +} + +#header_wrap .inner { + padding: 50px 10px 30px 10px; +} + +#project_title { + margin: 0; + color: #fff; + font-size: 42px; + font-weight: 700; + text-shadow: #111 0px 0px 10px; +} + +#project_tagline { + color: #fff; + font-size: 24px; + font-weight: 300; + background: none; + text-shadow: #111 0px 0px 10px; +} + +#downloads { + position: absolute; + width: 210px; + z-index: 10; + bottom: -40px; + right: 0; + height: 70px; + background: url('../images/icon_download.png') no-repeat 0% 90%; +} + +.zip_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom left; +} + +.tar_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom right; + margin-left: 10px; +} + +.zip_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top left; +} + +.tar_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top right; +} + +#main_content_wrap { + background: #f2f2f2; + border-top: 1px solid #111; + border-bottom: 1px solid #111; +} + +#main_content { + padding-top: 40px; +} + +#footer_wrap { + background: #212121; +} + + + +/******************************************************************************* +Small Device Styles +*******************************************************************************/ + +@media screen and (max-width: 480px) { + body { + font-size:14px; + } + + #downloads { + display: none; + } + + .inner { + min-width: 320px; + max-width: 480px; + } + + #project_title { + font-size: 32px; + } + + h1 { + font-size: 28px; + } + + h2 { + font-size: 24px; + } + + h3 { + font-size: 21px; + } + + h4 { + font-size: 18px; + } + + h5 { + font-size: 14px; + } + + h6 { + font-size: 12px; + } + + code, pre { + min-width: 320px; + max-width: 480px; + font-size: 11px; + } + +}