/**
* {1 Low-level API for file access.}
*/
const FileUtilities =
{
/**
* {2 Access a file or a directory}
*/
/**
* Open a file
*
* @param {string} fileName A platform-dependent name. To create a file in a directory, use [DirectoryDescriptor.openFile].
* @param {number} accessMode A or-ing of flags, as specified by [FileUtilities.Open.Access].
* @param {number} contentMode A or-ing of flags, as specified by [FileUtilities.Open.Content]
* @param {number} pragmaMode A or-ing of flags, as specified by [FileUtilities.Open.Pragma]
* @return {FileDescriptor} a FileDescriptor
*
* @throws FileDescriptorError
*/
openFile: function(fullName, accessMode, contentMode, pragmaMode) {
//Unix: maps to [open]
//Windows: maps to [CreateFile]
//Windows note: we probably want flags FLAG_SHARE_READ, FLAG_SHARE_WRITE, FLAG_SHARE_DELETE to allow moving files that are currently open
},
/**
* Create a temporary file. This file is deleted when the process closes, when the file is closed or when the FileDescriptor is garbage-collected.
*
* @return {FileDescriptor} a FileDescriptor
*/
createTempFile: function() {
//Unix: [FileUtilities.tmpdir] followed by [mkstemp] and [FileUtilities.openFile]
//Windows: [FileUtilities.tmpdir] followed by [GetTempFileName] and [FileUtilities.openFile]
//Alternative version:
//Unix minus Android: maps to [tmpfile]
//Android: need to implement custom [tmpfile]
//Windows: maps to [GetTempPath] + [GetTempFileName] + [CreateFile] http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875%28v=vs.85%29.aspx
},
/**
* @param {string} fullName The platform-specific name of the directory.
* @param {number=} accessMode A or-ing of flags, as specified by [FileDescriptor.OpenDir.Access]
*
* @returns {DirectoryDescriptor} a descriptor which may be used to access this directory
*/
openDirectory: function(fullName, accessMode) {
//Unix: lazy
//Windows: lazy
},
/**
* Create a temporary directory.
*
* Note: For the time being, there is no guarantee that the temporary directory will be cleaned
*
* @returns {DirectoryDescriptor} a descriptor which may be used to access this directory
*/
createTempDirectory: function() {
//Unix: [FileUtilities.tmpdir] followed by [mkstemp] and [FileUtilities.openDirectory]
//Windows: [FileUtilities.tmpdir] followed by [GetTempFileName] and [FileUtilities.openDirectory]
},
/**
* Open a copy of a file.
*
* If neither [directory] nor [name] is provided, the destination file is first created as with [createTemp]
*
* @param {DirectoryDescriptor=} destination Optionally, the directory in which to place the file.
* @param {string=} name Optionally, the name of the file in the directory.
* @return {FileDescriptor} The copy.
*/
openFileCopy: function(directory, name) {
//Unix: need to implement -- note that some file systems support an [ioctl] for copy-on-write.
//Windows: maps to [CopyFile] http://msdn.microsoft.com/en-us/library/aa363851(v=VS.85).aspx
},
/**
* {2 General utilities}
*/
/**
* @param {string} source The name of the file/directory to copy.
* @param {string} target The name of the file/directory to be created.
* @throws FileDescriptorError
*/
copy: function(source, target)
{
//Unix: need to implement with [open], [read], [write], [close]
//Windows: maps to [CopyFile] http://msdn.microsoft.com/en-us/library/aa363851(v=VS.85).aspx
//Check if it works with directories
},
/**
* @param {string} source The name of the file/directory to move.
* @param {string} target The name of the file/directory to be created.
* @throws FileDescriptorError
*/
move: function(source, target)
{
//Unix: maps to [rename]
//Windows: maps to [MoveFile] http://msdn.microsoft.com/en-us/library/aa365239(v=VS.85).aspx
},
//TODO: doc
link: function(name)
{
//Unix: maps to [link]
//Windows: maps to [CreateHardLink] http://msdn.microsoft.com/en-us/library/aa363860(v=VS.85).aspx
},
/**
* Remove a file/directory.
*/
remove: function(name)
{
//Unix: maps to [unlink]
//Windows: maps to [DeleteFile]
},
//TODO: doc
symlink: function(name)
{
//Unix: maps to [symlink]
//Windows: maps to [CreateSymbolicLink] http://msdn.microsoft.com/en-us/library/aa363866(v=VS.85).aspx
},
/**
* {3 Constants}
*/
get stdin: function() {
//...
},
get stdout: function() {
//...
},
get stderr: function() {
//...
},
/**
* Return the location of the directory/folder used to store temporary files.
*
* Computed lazily.
*
* @return {DirectoryDescriptor}
*/
get tmpdir: function () {
//All platforms: use [nsIDirectoryService] [NS_OS_TEMP_DIR] to get the directory the first time
//Alternative solution:
//Unix minus Android: maps to [getenv] for "TMPDIR"
//Android: TODO - probably somewhere in the Moz preferences directory - check with nsIDirectoryService
//Windows: maps to [GetTempPath] http://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx
//Note: Perhaps we should check with nsIDirectoryServi
},
/**
* {3 Flags}
*/
Open: {
/**
* @enum {number}
*/
Access: {
READ: ...,
WRITE: ...,
},
/**
* @enum {number}
*/
Content: {
MAY_CREATE:...,
APPEND: ...,
OVERWRITE: ...,
},
/**
* @enum {number}
*/
Pragma: {
POSIX_SEMANTICS: ...,
SEQUENTIAL_ACCESS: ....
RANDOM_ACCESS: ...,
WRITE_THROUGH: ...
}
},
Seek: {
/**
* Possible methods for seeking.
*
* @enum {number}
*/
Method: {
/**
* Seek from file start
*/
SET: ...,
/**
* Seek from current position
*/
CUR: ...,
/**
* Seek from file end
*/
END: ...
},
},
/**
* The kind of information that can be found by calling [FileDescroptor.info] or [DirectoryDescriptor.forEachFile].
*
* Note that some or all fields may be computed lazily.
*
* @interface
*/
FileInfo: {
/**
* @return {FileDescriptor} the file descriptor for this file
*/
get descriptor(): {
...
},
/**
* @TODO Not available on all platforms. Should we still allow it?
*
* @return {number} milliseconds
*/
get creationTime(): {
...
},
/**
* @return {number} milliseconds
*/
get lastAccessTime() : {
...
},
/**
* @return {number} milliseconds
*/
get lastModificationTime() : {
...
},
/**
* @return {number} bytes
*/
get fileSize() : {
...
},
/**
* @return {boolean}
*/
get isExecutable(): {
//Windows: [GetBinaryType] http://msdn.microsoft.com/en-us/library/windows/desktop/aa364819(v=VS.85).aspx
//Unix: contents of [stat]
},
},
/**
* An exception launched by this module.
*
* @constructor
* @extends {Error}
*/
Error: function(){}
}
FileUtilities.Error.prototype = new Error();
FileUtilities.Error.prototype.constructor = FileDescriptor.Error;
FileDescriptor.prototype =
{
/**
* {3 Reading}
*/
/**
* Read some content from a file from the current position, advance.
*
* @param {ArrayBuffer} buf The buffer which will receive the data.
* @param {number} offset The position in the array at which to start putting data, in bytes.
* @param {number} size The maximal number of bytes to read. This method can read less bytes if the file is shorter.
* @return {number} The number of bytes read.
* @throws {FileDescriptorException} In case of error.
*/
read: function(buf, offset, size) {
//Unix: [read]
//Windows: [ReadFile] http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=VS.85%29.aspx
},
/**
* As [read], but returns a string instead of filling a buffer.
*
* @return {string} The content read from the file. Note that its length may be shorter than [size]
* @throws {FileDescriptorException} In case of error.
*/
readString: function(size) {
//as [read]
},
/**
* As [read], but do not advance
*/
pread: function(...) {
//Unix: [pread]
//Windows: [ReadFile] + [SetFilePointer] http://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=VS.85).aspx
},
/**
* As [pread], but returns a string instead of filling a buffer.
*
* @return {string} The content read from the file. Note that its length may be shorter than [size]
* @throws {FileDescriptorException} In case of error.
*/
preadString: function(size) {
//as [pread]
},
/**
* {3 Writing}
*/
/**
* Write some content to a file, advance.
*
* @param {ArrayBuffer} buf The buffer containing the data.
* @param {number} offset The position in the array at which the data starts, in bytes.
* @param {number} size The maximal number of bytes to read. This method can write less bytes, depending on buffering.
*
* @return {number} The number of bytes written.
* @throws {FileDescriptorException} In case of error.
*/
write: function(buf, offset, size) {
//Unix: [write]
//Windows: [WriteFile] http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=VS.85%29.aspx
},
/**
* As [write], but with a [string]
*/
writeString: function(buf, offset, size) {
//as [write]
},
/**
* As [write] but do not advance
*/
pwrite: function(buf, offset, size) {
//Unix: [pwrite]
//Windows: [WriteFile] + [SetFilePointer]
},
pwriteString: function(buf, offset, size) {
//as [pwrite]
},
/**
* {3 File attributes}
*/
/**
* Gather information about the file
*
* @return {FileDescriptor.FileInfo} information about the file.
*/
stat: function() {
//Unix: [lstat]
//Windows: [GetFileInformationByHandle] http://msdn.microsoft.com/en-us/library/windows/desktop/aa364952(v=VS.85).aspx
},
/**
* Set the size of the file
*
* @param {number} newSize The size to give to the file.
*/
setSize: function(newSize) {
//Unix: [truncate]
//Windows: [SetFileValidData] http://msdn.microsoft.com/en-us/library/windows/desktop/aa365544%28v=VS.85%29.aspx
},
/**
* {3 Misc}
*/
/**
* Change the position in the current file
*
* @param {number} delta Number of bytes. Can be positive or negative.
* @param {FileDescriptor.Seek.Methodmethod} Determine whether [delta] is to be taken from the start of the file, from the end or from the current position.
*/
seek: function(delta, method) {
//Unix: [lseek]
//Windows: [SetFilePointer]
},
/**
* Close a file descriptor.
*
* Any further operation on that file descriptor will launch an exception
*/
close: function() {
//Unix: [close]
//Windows: [CloseHandle]
},
/**
* Flush the buffer
*/
flush: function() {
//Unix: [fsync]
//Windows: [FlushFileBuffers] http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439(v=VS.85).aspx
},
/**
* {3 Locking}
*/
//TODO: Understand differences between Unix and Windows locking better.
//TODO: Don't forget to unlock when leaving the process and/or closing the file.
lock: function() {
//Unix: [flock]
//Windows: [LockFile] http://msdn.microsoft.com/en-us/library/windows/desktop/aa365202%28v=VS.85%29.aspx
},
unlock: function() {
//Unix: [funlock]
//Windows: [UnlockFile] http://msdn.microsoft.com/en-us/library/aa365715%28v=VS.85%29.aspx
}
/**
* {3 Not implemented}
*/
//Not implemented: chmod, chown -- very different between platforms - might implement platform-specific functions
//Not implemented: select -- very different between platforms, higher level
//Not implemented: mmap -- probably feasible, just might require additional API
}
DirectoryDescriptor.prototype =
{
/**
* Open a file from a directory
*
* @param {string} leafName The name of the file.
* @param {number} accessMode A or-ing of flags, as specified by [FileDescriptor.Open.Access].
* @param {number} contentMode A or-ing of flags, as specified by [FileDescriptor.Content.Access]
* @param {number} pragmaMode A or-ing of flags, as specified by [FileDescriptor.Pragma.Access]
* @return {FileDescriptor} a FileDescriptor
*
* @throws FileDescriptorError
*/
openFile: function(leafName, accessMode, contentMode, pragmaMode) {
//Unix: maps to [openat] (warning, this requires gnulib on non-Linux platforms)
//Windows: cf. [FileDescriptor.open]
},
/**
* Create a temporary file in this directory. This file is deleted when the process closes, when the file is closed.
*/
createTempFile: function() {
//Unix: uses [mkstemp] and [this.openFile]
//Windows: maps to [GetTempFileName] + [CreateFile] http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875%28v=vs.85%29.aspx
},
/**
* Open a subdirectory of this directory.
*
* @param {string} leafName The platform-specific name of the directory.
* @param {number=} accessMode A or-ing of flags, as specified by [FileDescriptor.OpenDir.Access]
*
* @returns {DirectoryDescriptor} a descriptor which may be used to access this directory
*/
openDirectory: function(leafName, accessMode) {
//Unix: lazy
//Windows: lazy
},
/**
* Create a temporary directory.
*
* Note: For the time being, there is no guarantee that the temporary directory will be cleaned
*
* @returns {DirectoryDescriptor} a descriptor which may be used to access this directory
*/
createTempDirectory: function()
{
},
/**
* Apply a treatment to all files in the directory.
*
* Note: objects of type DirectoryDescriptor are iterable. Therefore, you can also loop through them using a standard [for..in].
*
* @param {(string|regexp|(function(string): boolean)) =} filter. If a [string], uses platform-specific filtering.
* @param {function(string, FileDescriptor.FileInfo, number)} onFile A function called for each file in the directory, with the name of the file, a (lazy) file info for that file and a file number. If the function returns anything [null], the loop stops immediately and returns the value returned by that function.
*
* @returns The first value returned by [onFile], or [undefined] otherwise.
*/
forEachFile: function(filter, onFile) {
//Unix: maps to [opendir], [dfd], [readdir]/[readdir64], lazy calls to [stat]
//Windows: maps to [FindFirstFile], [FindNextFile], [Close]
}
}