1
[comment {-*- tcl -*- doctools manpage}]
2
[manpage_begin vfs-fsapi n 1.0]
3
[copyright {2001-2003 Vince Darley <vincentdarley@users.sourceforge.net>}]
4
[copyright {2003 Andreas Kupries <andreas_kupries@users.sourceforge.net>}]
5
[moddesc {Tcl-level Virtual Filesystems}]
6
[titledesc {API for the implementation of a filesystem in Tcl}]
8
[require vfs [opt 1.2.1]]
11
This document explains the API used by the package [package vfs]
12
to communicate with filesystem implementations written in tcl.
14
[section {HANDLER OVERVIEW}]
16
The package [package vfs] intercepts every filesystem operation which
17
falls within a given mount point, and passes the operation on to the
18
mount point's [cmd vfshandler] command in the interpreter which
23
If the handler takes appropriate action for each of the cases it is
24
called for, a complete, perfect virtual filesystem will be achieved,
25
indistinguishable to Tcl from the native filesystem.
27
(CAVEATS: Right now [package vfs] does not expose to Tcl all the
28
permission-related flags of [cmd glob]).
31
[list_begin definitions]
33
[call [cmd vfshandler] [arg subcmd] [arg root] [arg relative] [arg actualpath] [arg args]...]
35
The first argument specifies the operation to perform on behalf of the
36
filesystem code in the tcl core, the remainder specify the file path
37
on which to operate, in different forms, and parts, and any additional
38
arguments which may be required to carry out the action.
42
To demonstrate the treatment of a path by the generic layer we use
43
[file C:/foo/bar/mount.zip/xxx/yyy] as an example and additionally
44
assume that the following conditions are true:
48
[file mount.zip] is a zip archive which has been mounted on top of
51
said zip archive contains a file with path [file xxx/yyy],
53
the current working directory of the application is inside of
56
and the command executed is [cmd {file exists yyy}].
59
The file separator between [arg root] and [arg relative] is omitted.
60
Most filesystem operations need only the [arg relative] argument for
61
their correct operation, but some actually require the other parts of
65
[list_begin definitions]
67
[lst_item [arg subcmd]]
69
This argument of the handler can be one of the following
70
[method access], [method createdirectory], [method deletefile],
71
[method fileattributes], [method matchindirectory], [method open],
72
[method removedirectory], [method stat], or [method utime].
76
The generic layer expects that the subcommands of a handler signal
77
error conditions by calling [cmd {vfs::filesystem posixerror}] with
78
the appropriate posix error code instead of throwing a tcl error. If
79
the latter is done nevertheless it will be treated as an unknown posix
84
There are three exceptions to the rule above: If any of [method open]
85
(when an interpreter is given), [method matchindirectory], and
87
[method fileattributes] (for a set or get operation only) throw a tcl
88
error, this error will be passed up to the caller of the filesystem
89
command which invoked the handler. Note that this does not preclude
90
the ability of these subcommands to use the command
92
[cmd {vfs::filesystem posixerror}] to report more regular filesystem
98
Part of the specification of the path to operate upon. It contains the
99
part of the path which lies outside this filesystem's mount point. For
100
example outlined above its value will be [file C:/foo/bar/mount.zip].
102
[lst_item [arg relative]]
104
Part of the specification of the path to operate upon. It contains the
105
part of the path which lies inside this filesystem. For example
106
outlined above its value will be [file xxx/yyy].
108
[lst_item [arg actualpath]]
110
Part of the specification of the path to operate upon. It contains the
111
original (unnormalized) name of the path which was used in the current
112
command wherever it originated (in Tcl or C). For example outlined
113
above its value will be [file yyy].
118
[section {HANDLER METHODS}]
119
[list_begin definitions]
122
[call [cmd vfshandler] [method access] [arg root] [arg relative] [arg actualpath] [arg mode]]
124
Signal a posix error if the specified access [arg mode] (an integer
125
number) is not compatible with the file or directory described by the
126
path. The generic layer will ignore any non-empty return value.
130
The command [cmd vfs::accessMode] (see section
132
[sectref {HANDLER ENVIRONMENT}]) can be used to convert the integer
133
[arg mode] into an easier to check string value.
136
[call [cmd vfshandler] [method createdirectory] [arg root] [arg relative] [arg actualpath]]
138
Create a directory with the given name. The command can assume that
139
all sub-directories in the path exist and are valid, and that the
140
actual desired path does not yet exist (Tcl takes care of all of that
144
[call [cmd vfshandler] [method deletefile] [arg root] [arg relative] [arg actualpath]]
146
Delete the given file.
149
[call [cmd vfshandler] [method fileattributes] [arg root] [arg relative] [arg actualpath] [opt [arg index]] [opt [arg value]]]
151
The command has to return a list containing the names of all
152
acceptable attributes, if neither [arg index] nor [arg value] were
157
The command has to return the value of the [arg index]'th attribute if
158
the [arg index] is specified, but not the [arg value]. The attributes
159
are counted in the same order as their names appear in the list
160
returned by a call where neither [arg index] nor [arg value] were
161
specified. The first attribute is has the index [const 0].
165
The command has to set the value of the [arg index]'th attribute to
166
[arg value] if both [arg index] and [arg value] were specified for the
170
[call [cmd vfshandler] [method matchindirectory] [arg root] [arg relative] [arg actualpath] [arg pattern] [arg types]]
172
Return the list of files or directories in the given path which match
173
the glob [arg pattern] and are compatible with the specified list of
174
[arg types]. The specified path is always the name of an existing
179
[emph Note:] As Tcl generates requests for directory-only matches from
180
the filesystems involved when performing any type of recursive
181
globbing this subcommand absolutely has to handle such (and file-only)
182
requests correctly or bad things (TM) will happen.
186
The commands [cmd vfs::matchDirectories] and [cmd vfs::matchFiles]
187
(see section [sectref {HANDLER ENVIRONMENT}]) can aid the
188
implementation greatly in this task.
191
[call [cmd vfshandler] [method open] [arg root] [arg relative] [arg actualpath] [arg mode] [arg permissions]]
193
Either returns a list describing the successfully opened file, or
194
throws an error describing how the operation failed.
198
The list returned upon success contains at least one and at most two
199
elements. The first, obligatory, element is always the handle of the
200
channel which was created to allow access to the contents of the
201
file. If specified the second element will be interpreted as a
202
callback, i.e. a command prefix. This prefix will always be executed
203
as is, i.e. without additional arguments. Any required arguments have
204
to be returned as part of the result of the call to [method open].
208
If present the specified callback will be evaluated by the generic
209
filesystem layer just before the channel whose handle was returned as
210
the first element of the list is closed. Additionally all available
211
data will have been flushed into it. This means, for example, that the
212
callback can seek to the beginning of the said channel, read its
213
contents and then store the gathered data elsewhere. In other words,
214
this callback is not only crucial to the cleanup of any resources
215
associated with an opened file, but also for the ability to implement
216
a filesystem which can be written to.
220
Under normal circumstances return code and any errors thrown by the
221
callback itself are ignored. In that case errors have to be signaled
222
asychronously, for example by calling [cmd bgerror].
224
However if, through a call of the subcommand [method internalerror],
225
an error handling script has been specified for the file system, all
226
errors thrown here will be passed to that script for further action.
229
[list_begin definitions]
231
[lst_item [arg mode]]
232
can be any of [const r], [const w], [const a], [const w+], or [const a+].
234
[lst_item [arg permissions]]
235
determines the native mode the openend file is created with. Relevant
236
only of the open [arg mode] actually requests the creation of a
237
non-existing file, i.e. is not [const r].
242
[call [cmd vfshandler] [method removedirectory] [arg root] [arg relative] [arg actualpath] [arg recursive]]
244
Delete the given directory. Argument [arg recursive] is a boolean. If
245
the specified value is [const true] then even if the directory is
246
non-empty, an attempt has to be made to recursively delete it and its
247
contents. If the spcified value is [const false] and the directory is
248
non-empty, a posix error ([const ENOTEMPTY]) has to be thrown.
251
[call [cmd vfshandler] [method stat] [arg root] [arg relative] [arg actualpath]]
253
The result has to be a list of keys and values, in a format acceptable
254
to the builtin command [cmd {array set}]. It describes the contents of
255
a stat structure. The order of the keys in the list is not important.
259
Given this the subcommand should use something like
261
[example {return [list dev 0 type file mtime 1234 ...].}]
263
as the last command of its implementation.
267
The following keys and their values have to be supplied by the
270
[list_begin definitions]
271
[lst_item [const dev]]
273
A long integer number, the device number of the path stat was called for.
275
[lst_item [const ino]]
277
A long integer number, the inode number of the path stat was called for.
279
Each path handled by the filesystem should be uniquely identified by
280
the combination of device and inode number. Violating this principle
281
will cause higher-level algorithms which(have to) keep track of device
282
and inode information to fail in all manners possible.
286
An example of such an algorithm would be a directory walker using
287
device/inode information to keep itself out of infinite loops
288
generated through symbolic links. Returning non-unique device/inode
289
information will most likely cause such a walker to skip over paths
290
under the wrong assumption of having them seen already.
292
[lst_item [const mode]]
294
An integer number, the access mode of the path. It is this mode which
295
is checked by the subcommand [method access].
297
[lst_item [const nlink]]
299
A long integer number, the number of hard links to the specified path.
301
[lst_item [const uid]]
303
A long integer number, the id of the user owning the virtual path.
305
[lst_item [const gid]]
307
A long integer number, the id of the user group the virtual path
310
[lst_item [const size]]
312
A long integer number, the true size of the virtual path, in bytes.
314
[lst_item [const atime]]
316
A long integer number, the time of the latest access to the path, in
317
seconds since the epoch. Convertible into a readable date/time by the
318
command [cmd {clock format}].
320
[lst_item [const mtime]]
322
A long integer number, the time of the latest modification of the
323
path, in seconds since the epoch. Convertible into a readable
324
date/time by the command [cmd {clock format}].
326
[lst_item [const ctime]]
328
A long integer number, the time of the path was created, in seconds
329
since the epoch. Convertible into a readable date/time by the command
330
[cmd {clock format}].
332
[lst_item [const type]]
334
A string, either [const directory], or [const file], describing the
335
type of the given path.
340
[call [cmd vfshandler] [method utime] [arg root] [arg relative] [arg actualpath] [arg actime] [arg mtime]]
342
Set the access and modification times of the given file (these are
343
read with [method stat]).
348
[section {HANDLER ENVIRONMENT}]
350
The implementation of a filesystem handler can rely on the
351
existence of the following utility commands:
353
[list_begin definitions]
354
[call [cmd vfs::accessMode] [arg mode]]
356
This commands converts an access [arg mode] given as integer into a
357
string, one of [const F], [const X], [const W], [const XW], [const R],
358
[const RX], and [const RW].
361
[call [cmd vfs::matchDirectories] [arg types]]
363
Checks if the glob types specification ask for the inclusion of
364
directories. Returns a boolean result. [const true] is returned if
365
types does ask for directories, else [const false].
368
[call [cmd vfs::matchFiles] [arg types]]
370
Checks if the glob types specification ask for the inclusion of
371
files. Returns a boolean result. [const true] is returned if types
372
does ask for directories, else [const false].
375
[call [cmd vfs::matchCorrectTypes] [arg types] [arg filelist] [opt [arg inDir]]]
377
Returns that subset of the [arg filelist] which are compatible with
378
the [arg types] given. The elements of [arg filelist] are either
379
absolute paths, or names of files in the directory [arg indir]. The
380
latter interpretation is taken if and only if the argument [arg indir]
386
[section {FILESYSTEM DEBUGGING}]
388
To debug a problem in the implementation of a filesystem use code as
389
shown below. This registers the command [cmd report] as the error
390
handler for the filesystem, which in turn prints out the error stack
394
[example {vfs::filesystem internalerror report
397
puts stderr $::errorInfo
400
[see_also vfs vfs-filesystems]
401
[keywords vfs filesystem file]