1vfs(n)                   Tcl-only Virtual File Systems                  vfs(n)
2
3
4

NAME

6       ::vfs - Commands and Procedures to create virtual filesystems
7

SYNOPSIS

9       package require Tcl 8.4
10
11       package require vfs ?1.2.1?
12
13       vfs::filesystem info
14
15       vfs::filesystem mount
16
17       vfs::filesystem unmount
18
19       vfs::accessMode mode
20
21       vfs::matchDirectories types
22
23       vfs::matchFiles types
24
25       vfs::matchCorrectTypes types filelist ?inDir?
26
27

DESCRIPTION

29       The ::vfs package provides commands to query, mount and unmount virtual
30       filesystems, and provides as Tcl libraries some facilities for  helping
31       the writing of new virtual filesystems in Tcl.  Once a virtual filesys‐
32       tem is in place, the standard Tcl file, glob, cd, pwd,  open  commands,
33       including all their C APIs in the Tcl library (e.g. Tcl_FSOpenFileChan‐
34       nel, Tcl_FSMatchInDirectory,...), can be  used  within  the  filesystem
35       (and  indeed,  properly written extensions such as Tk which may open or
36       read files will also  transparently  access  the  virtual  filesystem).
37       Because  all of Tcl's FS activity passes through a single layer, it can
38       all be intercepted.  This package does just that.  Notice that this  is
39       quite  different  to overloading the file command in Tcl.  We are actu‐
40       ally providing vfs replacements for C commands like access,  stat.   By
41       implementing  just  a  handful of commands at this low level, we ensure
42       that all commands at higher levels function  irrespective  of  what  is
43       going on inside the FS layer.
44
45       Tcl's  filesystem  hooks  operate  on  a per-process basis.  This means
46       every Tcl interpreter in the same  process/application  sees  the  same
47       filesystem, including any virtual filesystems.
48
49       The  package require vfs command should be used to access this library.
50       It automatically registers the vfs hooks  into  Tcl's  filesystem,  and
51       these  will  not  be  removed until Tcl exits (if desired, control over
52       this could be exposed to Tcl in the future).  However, the vfs  package
53       will  at  that  stage  not have any new filesystems mounted, so it will
54       have little effect.  Note that package require  vfs  has  two  effects.
55       First  of  all, when it is issued in any Tcl interpreter it will ensure
56       the vfs hooks have been registered with Tcl's core just  once  (and  if
57       any  of  those interpreters are later deleted, the vfs hooks will still
58       remain registered - they remain until Tcl exits).  The second effect is
59       to  provide the command vfs::filesystem which allows the interpreter to
60       intercept filesystem commands and handle them with  Tcl  code  in  that
61       interpreter.
62
63       There  are  three  somewhat unsupported subcommands of vfs::filesystem,
64       fullynormalize path, posixerror int, internalerror ?script?, which  are
65       used  to  normalize a path (including any final symlink), to register a
66       posix error code with a Tcl error, and to trap/report  internal  errors
67       in tclvfs implementations respectively.
68
69       vfs::filesystem mount ?-volume? path command
70              To  use  a  virtual  filesystem, it must be 'mounted'.  Mounting
71              involves declaring to the vfs package that any subdirectories of
72              a  given  path  in the filesystem should be handled by the given
73              command which should be a Tcl command or procedure in the inter‐
74              preter  in which the vfs::filesystem is executed.  If the ?-vol‐
75              ume?  flag is given, the given mount point  is  also  registered
76              with  Tcl as a new volume (like a new drive which will appear in
77              file volumes).  This is  useful  (and  required  for  reasonable
78              operation) for mounts like ftp://.  For paths mounted inside the
79              native filesystem, it should of course not be  given.   The  new
80              filesystem  mounts  will  be  observed immediately in all inter‐
81              preters in the current process.  If  the  interpreter  is  later
82              deleted, all mounts which are intercepted by it will be automat‐
83              ically removed (and  will  therefore  affect  the  view  of  the
84              filesystem seen by all interpreters).
85
86       vfs::filesystem unmount path
87              This  unmounts  the virtual filesystem which was mounted at path
88              (hence removing it from Tcl's filesystem), or throws an error if
89              no filesystem was mounted there.
90
91       vfs::filesystem info ?path?
92              If  no  arguments are given, this returns a list of all filesys‐
93              tems mounted (in all  interpreters).   If  a  path  argument  is
94              given, then the command to be used for that path is returned, or
95              an error is thrown if no vfs is mounted for that path.  There is
96              currently  no  facility  for examining in which interpreter each
97              command will be evaluated.
98
99       vfs::filesystem fullynormalize path
100              Performs a full expansion of path, (as  per  'file  normalize'),
101              but including following any links in the last element of path.
102

IMPLEMENTING A TCL ONLY VFS

104       The  vfs  package will intercept every filesystem operation which falls
105       within a given mount point, and pass the  operation  on  to  the  mount
106       point's command in the interpreter which registered it. In general this
107       occurs by the C equivalent of an evaluation like  this:  eval  $command
108       [list $subcmd $root $relative $actualpath] $args.
109
110       Here  subcmd  may  be  any  of  the following: access, createdirectory,
111       deletefile, fileattributes,  matchindirectory,  open,  removedirectory,
112       stat,  utime.  If  command  takes  appropriate action for each of these
113       cases, a complete, perfect virtual filesystem will be achieved,  indis‐
114       tinguishable  to Tcl from the native filesystem.  (CAVEATS: right now I
115       don't expose to Tcl all the permission-related flags of 'glob').
116
117       The remaining arguments specify a file path on which  to  operate  (all
118       commands  operate  on one of these), and any additional arguments which
119       may be required to carry out the action.  The file path is specified by
120       three  arguments:  root is the part of the path which lies outside this
121       filesystem's mount point, relative is the part of the path  which  lies
122       inside  this  filesytem,  and actualpath is the original (unnormalized)
123       name of the path which was used in  the  current  command  wherever  it
124       originated (in Tcl or C).  For example, if C:/foo/bar/mount.zip/xxx/yyy
125       is a path in your filesystem, where mount.zip is a  zip  archive  which
126       has  been mounted (on top of itself) and contains xxx/yyy, and the cur‐
127       rent working directory is inside xxx, and we evaluate  a  command  like
128       file  exists  yyy, then rootwill be C:/foo/bar/mount.zip, relative will
129       be xxx/yyy, and actualpath will be yyy. The file separator between  the
130       root and relative is omitted.
131
132       Note  that  most  filesystem  operations will only require the relative
133       argument to work  correctly,  but  the  other  arguments  are  actually
134       required for correct operation of some subcommands.
135
136       Almost  all of these commands should either return correctly (i.e. with
137       a TCL_OK result at the C level)  or  they  should  use  vfs::filesystem
138       posixerror  to signal the appropriate posix error code.  If a Tcl error
139       is thrown, that should be considered a bug, but it will be  interpreted
140       as  an  unknown  posix error in the filesystem call.  The exceptions to
141       these rules are those filesystem commands which are able to  specify  a
142       Tcl  error  message  directly:  open  (when  an  interpreter is given),
143       matchindirectory and fileattributes (for a set or get operation  only).
144       These  three  commands are allowed to throw any Tcl error message which
145       will be passed along to the caller, or they may  throw  a  posix  error
146       which will be handled appropriately.
147
148       The actual commands are as follows (where r-r-a represents the standard
149       argument triplet of root, relative and actualpath):
150
151       command access r-r-a mode
152              Return TCL_OK or throw a posix error depending  on  whether  the
153              given  access  mode (which is an integer) is compatible with the
154              file.
155
156       command createdirectory r-r-a
157              Create a directory with the given name.  The command can  assume
158              that  all  sub-directories  in the path exist and are valid, and
159              that the actual desired path does not yet exist (Tcl takes  care
160              of all of that for us).
161
162       command deletefile r-r-a
163              Delete the given file.
164
165       command fileattributes r-r-a ?index? ?value?
166              If  neither  index nor value is given, then return a list of all
167              acceptable attribute names.  If index is given,  but  no  value,
168              then  retrieve  the value of the index'th attribute (counting in
169              order over the list returned when no argument is given) for  the
170              given  file.   If  a  value  is also given then set the index'th
171              attribute of the given file to that value.
172
173       command matchindirectory r-r-a pattern types
174              Return the list of files or directories in the given path (which
175              is  always  the  name of an existing directory), which match the
176              pattern and are compatible with the types  given.   It  is  very
177              important  that  the command correctly handle types requests for
178              directories only (and files only), because to handle any kind of
179              recursive  globbing,  Tcl  will  actually  generate requests for
180              directory-only matches from the filesystem.   See  vfs::matchDi‐
181              rectories below for help.
182
183       command open r-r-a mode permissions
184              For  this command, mode is any of "r", "w", "a", "w+", "a+".  If
185              the open involves creating a  file,  then  permissions  dictates
186              what  modes  to  create  it with.  If the open operation was not
187              successful, an error should be thrown.  If the open operation is
188              successful,  the  command  should return a list of either one or
189              two items.  The first item (which is obligatory) is the name  of
190              the  channel which has been created.  The second item, if given,
191              is a Tcl-callback to be used when the channel is closed, so that
192              the  vfs  can  clean  up  as appropriate.  This callback will be
193              evaluated by Tcl just before the channel is closed.  The channel
194              will  still exist, and all available data will have been flushed
195              into it.  The callback can, for example, seek to  the  beginning
196              of  the channel, read its contents and store that contents else‐
197              where (e.g. compressed or on  a  remote  ftp  site,  etc).   The
198              return  code  or any errors returned by the callback are ignored
199              (if the callback wishes to signal an error, it must do so  asyc‐
200              nhronously,  with bgerror, for example), unless the 'internaler‐
201              ror' script has been specified, when they  are  passed  to  that
202              script for further action.
203
204       command removedirectory r-r-a recursive
205              Delete  the  given directory.  recursive is either 0 or 1. If it
206              is 1 then even if the directory is non-empty, an attempt  should
207              be  made  to recursively delete it and its contents.  If it is 0
208              and the directory is non-empty, a posix error (EEXIST) should be
209              thrown.
210
211       command stat r-r-a
212              Return  a  list  of  even length containing field-name and value
213              pairs for the contents of a stat structure.  The  order  is  not
214              important.   The  option  names are dev (long), ino (long), mode
215              (int), nlink (long), uid (long), gid (long), size (long),  atime
216              (long), mtime (long), ctime (long), type (string which is either
217              "directory" or "file"), where the type of each argument is given
218              in  brackets.   The procedure should therefore return with some‐
219              thing like return [list dev 0 type file mtime 1234 ...].
220
221       command utime r-r-a actime mtime
222              Set the access and modification times of the given  file  (these
223              are read with 'stat').
224
225

VFS HELPERS

227       The  vfslib  provides  a  number  of Tcl procedures which can help with
228       writing command procedures to handle the  above  possibilities.   These
229       are:
230
231       vfs::accessMode mode
232              converts  an  integer  access mode to a somewhat more preferable
233              string, any of F X W XW R RX RW.
234
235       vfs::matchDirectories types
236              Does types want directories included?
237
238       vfs::matchFiles types
239              Does types want files included?
240
241       vfs::matchCorrectTypes types filelist ?inDir?
242              Returns that subset of the filelist (which are  either  absolute
243              paths  or names of files in inDir) which are compatible with the
244              types given.
245
246

VFS DEBUGGING

248       Use something like this  to  debug  problems  in  your  implementation:
249       vfs::filesystem  internalerror  report  ;  proc report {} { puts stderr
250       $::errorInfo }
251
252

LIMITATIONS

254       There are very few limitations to the vfs code.  One subtlety that  you
255       may  encounter is if you mount a case-sensitive virtual filesystem into
256       a case-insensitive system (e.g. the standard Windows or MacOS  fs)  and
257       your  code  relies on case-insensitivity, then it will not run properly
258       in the virtual filesystem.  Of course if  your  code  relies  on  case-
259       insensitivity,  it  wouldn't  run under Tcl on Unix either, so the best
260       solution is to fix your code!
261
262       We may add link and lstat commands  in  the  future  to  allow  virtual
263       filesystems to support reading and writing links - this is supported by
264       the C API, but has simply not been exposed to Tcl  in  this  extension,
265       yet.
266
267       The  Tcl  'Tcl_FSMatchInDirectory'  function  takes  a  variety of type
268       information in a Tcl_GlobTypeData structure.  We currently only  expose
269       the  'type'  field  from that structure (so the 'permissions' and MacOS
270       type/creator fields are ignored).
271

KEYWORDS

273       vfs, filesystem, file
274
275
276
277
278
279Vfs                                  1.2.1                              vfs(n)
Impressum