This specification defines an API to navigate file system hierarchies, and defines a means by which a user agent may expose sandboxed sections of a user's local filesystem to web applications. It builds on [[!FILE-WRITER]], which in turn built on [[!FILE-API]], each adding a different kind of functionality.

This specification defines conformance criteria that apply to a single product: a user agent that implements the interfaces that it contains.

Introduction

This API is intended to satisfy client-side-storage use cases not well served by databases. These are generally applications that involve large binary blobs and/or share data with applications outside of the browser.

It is intended to be minimal in extent, but sufficiently powerful that easy-to-use libraries may be built on top of it.

Use Cases

  1. Persistent uploader
    • When a file or directory is selected for upload, it copies it into a local sandbox and uploads a chunk at a time.
    • It can restart uploads after browser crashes, network interruptions, etc.
  2. Video game or other app with lots of media assets
    • It downloads one or several large tarballs, and expands them locally into a directory structure.
    • The same download should work on any operating system.
    • It can manage prefetching just the next-to-be-needed assets in the background, so going to the next game level or activating a new feature doesn't require waiting for a download.
    • It uses those assets directly from its local cache, by direct file reads or by handing local URLs to image or video tags, WebGL asset loaders, etc.
    • The files may be of arbitrary binary format.
    • On the server side, a compressed tarball will often be much smaller than a collection of separately-compressed files. Also, 1 tarball instead of 1000 little files will involve fewer seeks, all else being equal.
  3. Audio/Photo editor with offline access or local cache for speed
    • The data blobs are potentially quite large, and are read-write.
    • It may want to do partial writes to files (ovewriting just the ID3/EXIF tags, for example).
    • The ability to organize project files by creating directories would be useful.
    • Edited files should be accessable by client-side applications [iTunes, Picasa].
  4. Offline video viewer
    • It downloads large files (>1GB) for later viewing.
    • It needs efficient seek + streaming.
    • It must be able to hand a URL to the video tag.
    • It should enable access to partly-downloaded files e.g. to let you watch the first episode of the DVD even if your download didn't complete before you got on the plane.
    • It should be able to pull a single episode out of the middle of a download and give just that to the video tag.
  5. Offline Web Mail Client
    • Downloads attachments and stores them locally.
    • Caches user-selected attachments for later upload.
    • Needs to be able to refer to cached attachments and image thumbnails for display and upload.
    • Should be able to trigger the UA's download manager just as if talking to a server.
    • Should be able to upload an email with attachments as a multipart post, rather than sending a file at a time in an XHR.

Examples

          // In the DOM or worker context:

          function useAsyncFS(fs) {
            // see getAsText example in [[!FILE-API]].
            fs.root.getFile("already_there.txt", null, function (f) {
              getAsText(f.file());
            });

            // But now we can also write to the file; see [[!FILE-WRITER]].
            fs.root.getFile("logFile", {create: true}, function (f) {
              f.createWriter(writeDataToLogFile);
            });
          }
          requestFileSystem(TEMPORARY, 1024 * 1024, function(fs) {
            useAsyncFS(fs);
          });

          // In a worker:

          var tempFS = requestFileSystem(TEMPORARY, 1024 * 1024);
          var logFile = tempFS.root.getFile("logFile", {create: true});
          var writer = logFile.createWriter();
          writer.seek(writer.length);
          writeDataToLogFile(writer);
        

Data Persistence and accessing the API

Temporary vs. Persistent Storage

An application can request temporary or persistent storage space. Temporary storage may be easier to get, at the UA's discretion [looser quota restrictions, available without prompting the user], but the data stored there may be deleted at the UA's convenience, e.g. to deal with a shortage of disk space.

Conversely, once persistent storage has been granted, data stored there by the application should not be deleted by the UA without user intervention. The application may of course delete it at will. The UA should require permission from the user before granting persistent storage space to the application.

This API specifies the standard origin isolation in a filesystem context, along with persistence of data across invocations. Applications will likely use temporary storage for caching, and if it's still around from a previous session, it is often useful. Persistent data, on the other hand, is useless if you can't access it again the next time you're invoked. However, even persistent data may be deleted manually by the user [either through the UA or via direct filesystem operations].

Restrictions

FileSystem and FileSystemSync objects returned by requestFileSystem MUST have the following properties:

Do we need to mandate that the temporary and persistent filesystems be disjoint?

Security Considerations

Because this API may allow untrusted code to read and write parts of a user's hard drive, there are a number of security and privacy issues that must be dealt with. Risks to the user include:

As with any other client-side storage, filesystem access allows for cookie-resurrection attacks. UAs will likely wish to present the option of clearing it when the user clears any other origin-specific storage, blocking access to it when cookies are blocked, etc. This is especially important if temporary storage space is permitted by default without explicit user permission.

Obtaining access to file system entry points

There are several ways in which a file system entry point can be obtained. Not all user agents may in fact implement all of them. However, in order to avoid blocking UI actions while waiting on filesystem IO, we define only an asynchronous interface for Window, and restrict the synchronous API to the Worker context defined in [[!WEBWORKERS]].

Using LocalFileSystem

const unsigned short TEMPORARY = 0
Used for storage with no guarantee of persistence.
const unsigned short PERSISTENT = 1
Used for storage that should not be removed by the user agent without application or user permission.
void requestFileSystem ()

Requests a filesystem in which to store application data.

If successful, this function MUST give access to an origin-private filesystem, as defined above.

unsigned short type
Whether the filesystem requested should be persistent, as defined above. Use one of TEMPORARY or PERSISTENT.
unsigned long long size
This is an indicator of how much storage space, in bytes, the application expects to need.
FileSystemCallback successCallback
The callback that is called when the user agent provides a filesystem.
optional ErrorCallback errorCallback
A callback that is called when errors happen, or when the request to obtain the filesystem is denied.
void resolveLocalFileSystemURL ()

Allows the user to look up the Entry for a file or directory referred to by a local URL.

DOMString url
A URL referring to a local file in a filesystem accessable via this API.
EntryCallback successCallback
A callback that is called to report the Entry to which the supplied URL refers.
optional ErrorCallback errorCallback
A callback that is called when errors happen, or when the request to obtain the Entry is denied.

Using LocalFileSystemSync

const unsigned short TEMPORARY = 0
Used for storage with no guarantee of persistence.
const unsigned short PERSISTENT = 1
Used for storage that should not be removed by the user agent without application or user permission.
FileSystemSync requestFileSystemSync ()

Requests a filesystem in which to store application data.

If successful, this function MUST give access to an origin-private filesystem, as defined above.

unsigned short type
Whether the filesystem requested should be persistent, as defined above. Use one of TEMPORARY or PERSISTENT.
unsigned long long size
This is an indicator of how much storage space, in bytes, the application expects to need.
SECURITY_ERR
The application does not have permission to access the filesystem interface.
EntrySync resolveLocalFileSystemSyncURL ()

Allows the user to look up the Entry for a file or directory referred to by a local URL.

DOMString url
A URL referring to a local file in a filesystem accessable via this API.
ENCODING_ERR
The URL was invalid.
NOT_FOUND_ERR
The URL was structurally correct, but refers to a resource that does not exist.
SECURITY_ERR
The application does not have permission to access the filesystem interface or the element referred to by the URL.

Shared data types

The Metadata interface

This interface supplies information about the state of a file or directory.

readonly attribute Date modificationTime
This is the time at which the file or directory was last modified.

The Flags interface

This interface is used to supply arguments to methods that look up or create files or directories.

attribute boolean create
Used to indicate that the user wants to create a file or directory if it was not previously there.
attribute boolean exclusive
By itself, exclusive MUST have no effect. Used with create, it causes getFile and getDirectory to fail if the target path already exists.

Examples

            // Get the data directory, creating it if it doesn't exist.
            dataDir = fsSync.root.getDirectory("data", {create: true});

            // Create the lock file, if and only if it doesn't exist.
            try {
              lockFile = dataDir.getFile("lockfile.txt",
                                         {create: true, exclusive: true});
            } catch (ex) {
              // It already exists, or something else went wrong.
              ...
            }
          

The asynchronous filesystem interface

The FileSystem interface

This interface represents a file system.

readonly attribute DOMString name
This is the name of the file system. The specifics of naming filesystems is unspecified, but a name MUST be unique across the list of exposed file systems.
readonly attribute DirectoryEntry root
The root directory of the file system.

The Entry interface

An abstract interface representing entries in a file system, each of which may be a File or DirectoryEntry.

readonly attribute boolean isFile
Entry is a file.
readonly attribute boolean isDirectory
Entry is a directory.
void getMetadata ()

Look up metadata about this entry.

MetadataCallback successCallback
A callback that is called with the time of the last modification.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
readonly attribute DOMString name
The name of the entry, excluding the path leading to it.
readonly attribute DOMString fullPath
The full absolute path from the root to the entry.
readonly attribute FileSystem filesystem
The file system on which the entry resides.
void moveTo ()

Move an entry to a different location on the file system. It is an error to try to:

  • move a directory inside itself or to any child at any depth;
  • move an entry into its parent if a name different from its current one isn't provided;
  • move a file to a path occupied by a directory;
  • move a directory to a path occupied by a file;
  • move any element to a path occupied by a directory which is not empty.
A move of a file on top of an existing file MUST attempt to delete and replace that file.
A move of a directory on top of an existing empty directory MUST attempt to delete and replace that directory.

DirectoryEntry parent
The directory to which to move the entry.
optional DOMString newName
The new name of the entry. Defaults to the Entry's current name if unspecified.
EntryCallback successCallback
A callback that is called with the Entry for the new location.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
void copyTo (DirectoryEntry parent, DOMString newName)

Copy an entry to a different location on the file system. It is an error to try to:

  • copy a directory inside itself or to any child at any depth;
  • copy an entry into its parent if a name different from its current one isn't provided;
  • copy a file to a path occupied by a directory;
  • copy a directory to a path occupied by a file;
  • copy any element to a path occupied by a directory which is not empty.
A copy of a file on top of an existing file MUST attempt to delete and replace that file.
A copy of a directory on top of an existing empty directory MUST attempt to delete and replace that directory.
Directory copies are always recursive--that is, they copy all contents of the directory.

DirectoryEntry parent
The directory to which to move the entry.
optional DOMString newName
The new name of the entry. Defaults to the Entry's current name if unspecified.
EntryCallback successCallback
A callback that is called with the Entry for the new object.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
DOMString toURL ()

Returns a URL that can be used to identify this entry. Unlike the URN defined in [[!FILE-API]], it has no specific expiration; as it describes a location on disk, it should be valid at least as long as that location exists.

Do we want to spec out the URL format/scheme? It would be quite nice if these could be edited and manipulated easily, as with normal filesystem paths.

How and where can these URLs be used? Can they be interchangeable with online URLs for the same domain?

Proposal currently under discussion:

  • Use a format such as filesystem:http://example.domain/persistent-or-temporary/path/to/file.html .
  • URLs should be usable for anything that online URLs can be used for, whether they appear in online or filesystem-resident web pages.
  • However, they can only be used by the origin that owns the filesystem. No other origin can e.g. reference another origin's filesystem in an IMG tag.

void remove ()

Deletes a file or directory. It is an error to attempt to delete a directory that is not empty. It is an error to attempt to delete the root directory of a filesystem.

VoidCallback successCallback
A callback that is called on success.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
void getParent ()
Look up the parent DirectoryEntry containing this Entry. If this Entry is the root of its filesystem, its parent is itself.
EntryCallback successCallback
A callback that is called to return the parent Entry.
optional ErrorCallback errorCallback
A callback that is called when errors happen.

The DirectoryEntry interface

This interface represents a directory on a file system.

DirectoryReader createReader ()

Creates a new DirectoryReader to read Entries from this Directory.

void getFile ()

Creates or looks up a file.

DOMString path
Either an absolute path or a relative path from this DirectoryEntry to the file to be looked up or created. It is an error to attempt to create a file whose immediate parent does not yet exist.
optional Flags options
  • If create and exclusive are both true, and the path already exists, getFile MUST fail.
  • If create is true, the path doesn't exist, and no other error occurs, getFile MUST create it as a zero-length file and return a corresponding FileEntry.
  • If create is not true and the path doesn't exist, getFile MUST fail.
  • If create is not true and the path exists, but is a directory, getFile MUST fail.
  • Otherwise, if no other error occurs, getFile MUST return a FileEntry corresponding to path.
EntryCallback successCallback
A callback that is called to return the File selected or created.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
void getDirectory ()

Creates or looks up a directory.

DOMString path
Either an absolute path or a relative path from this DirectoryEntry to the directory to be looked up or created. It is an error to attempt to create a directory whose immediate parent does not yet exist.
optional Flags options
  • If create and exclusive are both true and the path already exists, getDirectory MUST fail.
  • If create is true, the path doesn't exist, and no other error occurs, getDirectory MUST create and return a corresponding DirectoryEntry.
  • If create is not true and the path doesn't exist, getDirectory MUST fail.
  • If create is not true and the path exists, but is a file, getDirectory MUST fail.
  • Otherwise, if no other error occurs, getDirectory MUST return a DirectoryEntry corresponding to path.
EntryCallback successCallback
A callback that is called to return the DirectoryEntry selected or created.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
void removeRecursively ()

Deletes a directory and all of its contents, if any. In the event of an error [e.g. trying to delete a directory that contains a file that cannot be removed], some of the contents of the directory MAY be deleted. It is an error to attempt to delete the root directory of a filesystem.

VoidCallback successCallback
A callback that is called on success.
optional ErrorCallback errorCallback
A callback that is called when errors happen.

The DirectoryReader interface

This interface lets a user list files and directories in a directory. If there are no additions to or deletions from a directory between the first and last call to readEntries, and no errors occur, then:

void readEntries ()

Read the next block of entries from this directory.

EntriesCallback successCallback
Called once per successful call to readEntries to deliver the next previously-unreported set of Entries in the associated Directory. If all Entries have already been returned from previous invocations of readEntries, successCallback MUST be called with a zero-length array as an argument.
optional ErrorCallback errorCallback
A callback indicating that there was an error reading from the Directory.

The FileEntry interface

This interface represents a file on a file system.

void createWriter ()

Creates a new FileWriter associated with the file that this FileEntry represents.

FileWriterCallback successCallback
A callback that is called with the new FileWriter.
optional ErrorCallback errorCallback
A callback that is called when errors happen.
void file ()

Returns a File that represents the current state of the file that this FileEntry represents.

FileCallback successCallback
A callback that is called with the File.
optional ErrorCallback errorCallback
A callback that is called when errors happen.

Callbacks

Several calls in this API are asynchronous, and use callbacks.

The FileSystemCallback interface

When requestFileSystem() succeeds, the following callback is made:

void handleEvent ()

The file system was successfully obtained.

FileSystem filesystem
The file systems to which the app is granted access.

The EntryCallback interface

This interface is the callback used to look up Entry objects.

void handleEvent(Entry entry)
Used to supply an Entry as a response to a user query.

The EntriesCallback interface

When readEntries() succeeds, the following callback is made.

void handleEvent(Entry[] entries)
Used to supply an array of Entries as a response to a user query.

The MetadataCallback interface

This interface is the callback used to look up file and directory metadata.

void handleEvent (Metadata metadata)

Used to supply file or directory metadata as a response to a user query.

The FileWriterCallback interface

This interface is the callback used to create a FileWriter.

void handleEvent (FileWriter fileWriter)

Used to supply a FileWriter as a response to a user query.

The FileCallback interface

This interface is the callback used to obtain a File.

void handleEvent (File file)

Used to supply a File as a response to a user query.

The VoidCallback interface

This interface is the generic callback used to indicate success of an asynchronous method.

void handleEvent ()

The ErrorCallback interface

When an error occurs, the following callback is made:

void handleEvent ()

There was an error with the request. Details are provided by the FileError parameter.

FileError err
The error that was generated.

The synchronous filesystem interface

The FileSystemSync interface

This interface represents a file system.

readonly attribute DOMString name
This is the name of the file system. The specifics of naming filesystems is unspecified, but a name MUST be unique across the list of exposed file systems.
readonly attribute DirectoryEntrySync root
The root directory of the file system.

The EntrySync interface

An abstract interface representing entries in a file system, each of which may be a FileEntrySync or DirectoryEntrySync.

Some have requested support for archive files. I've not required that, but I've left space for it by not ruling out having both isFile and isDirectory be true. I welcome comments on this approach.

readonly attribute boolean isFile
EntrySync is a file.
readonly attribute boolean isDirectory
EntrySync is a directory.
Metadata getMetadata ()

Look up metadata about this entry.

NOT_FOUND_ERR
The entry no longer exists.
INVALID_STATE_ERR
This FileSystemSync is no longer valid for some reason other than it having been deleted.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.
readonly attribute DOMString name
The name of the entry, excluding the path leading to it.
readonly attribute DOMString fullPath
The full absolute path from the root to the entry.
readonly attribute FileSystemSync filesystem
The file system on which the entry resides.
EntrySync moveTo ()

Move an entry to a different location on the file system. It is an error to try to:

  • move a directory inside itself or to any child at any depth;
  • move an entry into its parent if a name different from its current one isn't provided;
  • move a file to a path occupied by a directory;
  • move a directory to a path occupied by a file;
  • move any element to a path occupied by a directory which is not empty.
A move of a file on top of an existing file MUST attempt to delete and replace that file. A move of a directory on top of an existing empty directory MUST attempt to delete and replace that directory.

DirectoryEntrySync parent
The directory to which to move the entry.
optional DOMString newName
The new name of the entry. Defaults to the EntrySync's current name if unspecified.
ENCODING_ERR
The name supplied was invalid.
NOT_FOUND_ERR
The target directory does not exist.
INVALID_MODIFICATION_ERR
The user attempted to move an entry into its parent without changing its name, or attempted to move a directory into a directory that it contains directly or indirectly.
NO_MODIFICATION_ALLOWED_ERR
The either the source entry, its parent directory, or the target directory is not writable.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.
EntrySync copyTo (DirectoryEntrySync parent, DOMString newName)

Copy an entry to a different location on the file system. It is an error to try to copy an entry inside itself at any depth if it is a directory, or to copy it into its parent if a name different from its current one isn't provided.

DirectoryEntrySync parent
The directory to which to move the entry.
optional DOMString newName
The new name of the entry. Defaults to the EntrySync's current name if unspecified.
ENCODING_ERR
The name supplied was invalid.
NOT_FOUND_ERR
The target directory does not exist.
INVALID_MODIFICATION_ERR
The user attempted to copy an entry into its parent without changing its name, or attempted to copy a directory into a directory that it contains directly or indirectly.
NO_MODIFICATION_ALLOWED_ERR
The target directory is not writable.
QUOTA_EXCEEDED_ERR
The operation would cause the application to exceed its storage quota.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.
DOMString toURL ()

Returns a URL that can be used to identify this entry. Unlike the URN defined in [[!FILE-API]], it has no specific expiration; as it describes a location on disk, it should be valid at least as long as that location exists.

void remove ()

Deletes a file or directory. It is an error to attempt to delete a directory that is not empty. It is an error to attempt to delete the root directory of a filesystem.

NOT_FOUND_ERR
The target directory does not exist.
INVALID_MODIFICATION_ERR
The user attempted to remove a directory that was not empty.
NO_MODIFICATION_ALLOWED_ERR
The target or its containing directory is not writable.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.
DirectoryEntrySync getParent ()
Look up the parent DirectoryEntrySync containing this Entry. If this EntrySync is the root of its filesystem, its parent is itself.

The DirectoryEntrySync interface

This interface represents a directory on a file system.

DirectoryReaderSync createReader ()

Creates a new DirectoryReaderSync to read EntrySyncs from this DirectorySync.

NOT_FOUND_ERR
The directory no longer exists.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.
FileEntrySync getFile ()

Creates or looks up a file.

DOMString path
Either an absolute path or a relative path from this DirectoryEntrySync to the file to be looked up or created. It is an error to attempt to create a file whose immediate parent does not yet exist.
optional Flags options
  • If create and exclusive are both true and the path already exists, getFile MUST fail.
  • If create is true, the path doesn't exist, and no other error occurs, getFile MUST create it as a zero-length file and return a corresponding FileEntry.
  • If create is not true and the path doesn't exist, getFile MUST fail.
  • If create is not true and the path exists, but is a directory, getFile MUST fail.
  • Otherwise, if no other error occurs, getFile MUST return a FileEntrySync corresponding to path.
ENCODING_ERR
The path was invalid.
NOT_FOUND_ERR
The path was structurally correct, but refers to a resource that does not exist.
NO_MODIFICATION_ALLOWED_ERR
The target directory or file is not writable.
PATH_EXISTS_ERR
The user attempted to create a file where an element already exists.
QUOTA_EXCEEDED_ERR
The operation would cause the application to exceed its storage quota.
SECURITY_ERR
The application does not have permission to access the element referred to by path.
TYPE_MISMATCH_ERR
The path supplied exists, but is not a directory.
DirectoryEntrySync getDirectory ()

Creates or looks up a directory.

DOMString path
Either an absolute path or a relative path from this DirectoryEntrySync to the directory to be looked up or created. It is an error to attempt to create a directory whose immediate parent does not yet exist.
optional Flags options
  • If create and exclusive are both true and the path already exists, getDirectory MUST fail.
  • If create is true, the path doesn't exist, and no other error occurs, getDirectory MUST create and return a corresponding DirectoryEntry.
  • If create is not true and the path doesn't exist, getDirectory MUST fail.
  • If create is not true and the path exists, but is a file, getDirectory MUST fail.
  • Otherwise, if no other error occurs, getDirectory MUST return a DirectoryEntrySync corresponding to path.
ENCODING_ERR
The path was invalid.
NOT_FOUND_ERR
The path was structurally correct, but refers to a resource that does not exist.
NO_MODIFICATION_ALLOWED_ERR
The target directory is not writable.
PATH_EXISTS_ERR
The user attempted to create a directory where an element already exists.
QUOTA_EXCEEDED_ERR
The operation would cause the application to exceed its storage quota.
SECURITY_ERR
The application does not have permission to access the element referred to by path.
TYPE_MISMATCH_ERR
The path supplied exists, but is not a directory.
void removeRecursively ()

Deletes a directory and all of its contents, if any. In the event of an error [e.g. trying to delete a directory that contains a file that cannot be removed], some of the contents of the directory MAY be deleted. It is an error to attempt to delete the root directory of a filesystem.

NOT_FOUND_ERR
This DirectoryEntrySync refers to a resource that does not exist.
INVALID_STATE_ERR
This DirectoryEntrySync is no longer valid for some reason other than it having been deleted.
NO_MODIFICATION_ALLOWED_ERR
At least one of the target directory, its parent, or some of its contents, is not writable.
SECURITY_ERR
The application does not have permission to access the target directory, its parent, or some of its contents.

The DirectoryReaderSync interface

This interface lets a user list files and directories in a directory. If there are no additions to or deletions from a directory between the first and last call to readEntries, and no errors occur, then:

EntrySync[] readEntries ()

Read the next block of entries from this directory.

NOT_FOUND_ERR
The directory no longer exists.
INVALID_STATE_ERR
The directory has been modified since the first call to readEntries began to be processed.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.

The FileEntrySync interface

This interface represents a file on a file system.

FileWriterSync createWriter ()

Creates a new FileWriterSync associated with the file that this FileEntrySync represents.

NOT_FOUND_ERR
The entry no longer exists.
INVALID_STATE_ERR
This FileEntrySync is no longer valid for some reason other than it having been deleted.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.
File file ()

Returns a File that represents the current state of the file that this FileEntrySync represents.

NOT_FOUND_ERR
The entry no longer exists.
INVALID_STATE_ERR
This FileEntrySync is no longer valid for some reason other than it having been deleted.
SECURITY_ERR
The user agent determined that it was not safe to carry out this action.

Dealing with errors and exceptions

The FileError interface

This interface extends the FileError interface described in [[!FILE-WRITER]] to add several new error codes. It is used to report errors asynchronously.

const unsigned short NOT_FOUND_ERR = 1
const unsigned short SECURITY_ERR = 2
const unsigned short ABORT_ERR = 3
const unsigned short NOT_READABLE_ERR = 4
const unsigned short ENCODING_ERR = 5
const unsigned short NO_MODIFICATION_ALLOWED_ERR = 6
const unsigned short INVALID_STATE_ERR = 7
const unsigned short SYNTAX_ERR = 8
const unsigned short INVALID_MODIFICATION_ERR = 9
const unsigned short QUOTA_EXCEEDED_ERR = 10
const unsigned short TYPE_MISMATCH_ERR = 11
const unsigned short PATH_EXISTS_ERR = 12
attribute unsigned short code
The code attribute, on getting, MUST return one of the constants of the FileError error, which MUST be the most appropriate code from the table below.

The FileException exception

This interface extends the FileException interface described in [[!FILE-WRITER]] to add several new error codes. Any errors that need to be reported synchronously, including all that occur during use of the synchronous filesystem methods, are reported using the FileException exception.
const unsigned short NOT_FOUND_ERR = 1
const unsigned short SECURITY_ERR = 2
const unsigned short ABORT_ERR = 3
const unsigned short NOT_READABLE_ERR = 4
const unsigned short ENCODING_ERR = 5
const unsigned short NO_MODIFICATION_ALLOWED_ERR = 6
const unsigned short INVALID_STATE_ERR = 7
const unsigned short SYNTAX_ERR = 8
const unsigned short INVALID_MODIFICATION_ERR = 9
const unsigned short QUOTA_EXCEEDED_ERR = 10
const unsigned short TYPE_MISMATCH_ERR = 11
const unsigned short PATH_EXISTS_ERR = 12
readonly unsigned short code
The code attribute, on getting, MUST return one of the constants of the FileException exception, which MUST be the most appropriate code from the table below.

Error Code Descriptions

NameValueDescription
ABORT_ERR3 This value MUST NOT be used in this API.
ENCODING_ERR5 user agent MUST use this code when a URL supplied to the API is malformed.
INVALID_MODIFICATION_ERR9 user agent MAY use this code if the modification requested is illegal. Examples of invalid modifications include moving a directory into its own child or moving a file into its parent directory without changing its name.
INVALID_STATE_ERR7 user agent MAY use this code if an operation depends on state cached in an interface object that has changed since it was read from disk.
Which values will actually go stale? Modification time, name, more rarely type. If an atomic save [replacing a file with a new one of the same name] happens underneath, should we even be required to notice?
NOT_FOUND_ERR1 user agent MUST use this code if a required file or directory could not be found at the time an operation was processed.
NOT_READABLE_ERR4 user agent MUST use this code if a file or directory cannot be read, typically due due to permission problems that occur after a reference to a file has been acquired (e.g. concurrent lock with another application).
NO_MODIFICATION_ALLOWED_ERR6 user agent MUST use this code when attempting to write to a file or directory which cannot be modified due to the state of the underlying filesystem.
PATH_EXISTS_ERR12 user agent MUST use this code when failing to create a file or directory due to the existence of a file or directory with the same path.
QUOTA_EXCEEDED_ERR10 user agent MUST use this code if the operation failed because it would cause the application to exceed its storage quota.
SECURITY_ERR2 user agent MAY use this code if:
  • it is determined that certain files are unsafe for access within a Web application
  • it is determined that too many calls are being made on file resources
This is a security error code to be used in situations not covered by any other error codes.
SYNTAX_ERR8 This error code is not used in this specification; it is included here only for completeness, as it is used in [[!FILE-WRITER]].
TYPE_MISMATCH_ERR11 user agent MUST use this code when the user has attempted to look up a file or directory, but the Entry found is of the wrong type [e.g. is a DirectoryEntry when the user requested a FileEntry].

Uniformity of interface

In order to make it easy for web app developers to write portable applications that work on all platforms, we enforce certain restrictions and make certain guarantees with respect to paths used in this API.

The implementation MUST refuse to create any file or directory whose name or existence would violate these rules. The implementation MUST NOT accept a noncompliant path where it designates the new name of a file or directory to be moved, copied, or created.

TODO(ericu): Spec the exception given for noncompliant paths.

Case-sensitivity

Paths in this filesystem MUST be case sensitive and case-preserving.

Encoding

Implementations MUST accept any valid UTF-8 sequence as a path segment, so long as it does not include any characters or sequences restricted below. When returning paths or path segments, implementations MUST return them in the same normalization in which they were presented.

Naming restrictions

File and directory names MUST NOT contain either of the following characters:

There's been discussion on whether backslash '\' (U+005c) should be disallowed or not. In favor of leaving it in is that it's a legal character on some filesystems, and it seems somewhat arbitrary to remove it. Opposed is that it may cause confusion, and in at least some cases complicates implementation.

Directories

The directory separator is '/' (U+002F).

The character '/', when it is the first character in a path, refers to the root directory.

All absolute paths begin with '/'; no relative paths begin with '/'.

A relative path describes how to get from a particular directory to a file or directory. All methods that accept paths are on DirectoryEntry or DirectoryEntrySync objects; the paths, if relative, are interpreted as being relative to the directories represented by these objects.

An absolute path is a relative path from the root directory, prepended with a '/'.

'.', when used where it is legal to use a directory name, refers to the currently-referenced directory. Thus 'foo/./bar' is equivalent to 'foo/bar', and './foo' is equivalent to 'foo'.

'..', when used where it is legal to use a directory name, refers to the parent of the currently-referenced directory. Thus, 'foo/..' refers to the directory containing 'foo', and '../foo' refers to an element named 'foo' in the parent of the directory on whose DirectoryEntry or DirectoryEntrySync the method receiving the path is being called.

What about path and path segment lengths? Should we limit them at all? It's hard to control the true length of a path, due to renames of parent directories, so we really just want to reject the obviously-too-long; they won't often really come up anyway. We should at least provide minimum lengths for paths and segments.

Should we limit the number of elements in a directory?

Acknowledgements

Thanks to Arun Ranganathan for his File API, Opera for theirs, and Robin Berjon both for his work on various file APIs and for ReSpec.