Provided by: tcl-vfs_1.3-20080503-4_amd64 bug

NAME

       ::vfs - Commands and Procedures to create virtual filesystems

SYNOPSIS

       package require Tcl 8.4

       package require vfs ?1.2.1?

       vfs::filesystem info

       vfs::filesystem mount

       vfs::filesystem unmount

       vfs::accessMode mode

       vfs::matchDirectories types

       vfs::matchFiles types

       vfs::matchCorrectTypes types filelist ?inDir?

DESCRIPTION

       The  ::vfs  package provides commands to query, mount and unmount virtual filesystems, and
       provides as Tcl  libraries  some  facilities  for  helping  the  writing  of  new  virtual
       filesystems  in  Tcl.  Once a virtual filesystem is in place, the standard Tcl file, glob,
       cd,  pwd,  open  commands,  including  all  their  C  APIs  in  the  Tcl   library   (e.g.
       Tcl_FSOpenFileChannel, Tcl_FSMatchInDirectory,...), can be used within the filesystem (and
       indeed, properly written extensions such as Tk which may open  or  read  files  will  also
       transparently  access  the  virtual  filesystem).  Because all of Tcl's FS activity passes
       through a single layer, it can all be intercepted.  This package does just  that.   Notice
       that  this  is  quite  different  to overloading the file command in Tcl.  We are actually
       providing vfs replacements for C commands like  access,  stat.   By  implementing  just  a
       handful  of  commands  at  this  low  level,  we ensure that all commands at higher levels
       function irrespective of what is going on inside the FS layer.

       Tcl's filesystem hooks operate on a per-process basis.  This means every  Tcl  interpreter
       in   the  same  process/application  sees  the  same  filesystem,  including  any  virtual
       filesystems.

       The package require vfs command should be used to access this library.   It  automatically
       registers  the  vfs  hooks  into Tcl's filesystem, and these will not be removed until Tcl
       exits (if desired, control over this could be exposed to Tcl in the future).  However, the
       vfs  package  will  at  that  stage  not have any new filesystems mounted, so it will have
       little effect.  Note that package require vfs has two effects.  First of all, when  it  is
       issued in any Tcl interpreter it will ensure the vfs hooks have been registered with Tcl's
       core just once (and if any of those interpreters are later deleted,  the  vfs  hooks  will
       still  remain  registered - they remain until Tcl exits).  The second effect is to provide
       the command vfs::filesystem which allows the interpreter to intercept filesystem  commands
       and handle them with Tcl code in that interpreter.

       There  are three somewhat unsupported subcommands of vfs::filesystem, fullynormalize path,
       posixerror int, internalerror ?script?, which are used to normalize a path (including  any
       final  symlink),  to  register  a  posix  error  code with a Tcl error, and to trap/report
       internal errors in tclvfs implementations respectively.

       vfs::filesystem mount ?-volume? path command
              To use a virtual filesystem, it must be 'mounted'.  Mounting involves declaring  to
              the vfs package that any subdirectories of a given path in the filesystem should be
              handled by the given command which should be a Tcl  command  or  procedure  in  the
              interpreter  in  which  the vfs::filesystem is executed.  If the ?-volume?  flag is
              given, the given mount point is also registered with Tcl as a new  volume  (like  a
              new  drive  which  will  appear in file volumes).  This is useful (and required for
              reasonable operation) for mounts like ftp://.  For paths mounted inside the  native
              filesystem,  it  should  of course not be given.  The new filesystem mounts will be
              observed  immediately  in  all  interpreters  in  the  current  process.   If   the
              interpreter  is  later  deleted,  all  mounts  which  are intercepted by it will be
              automatically removed (and will therefore affect the view of the filesystem seen by
              all interpreters).

       vfs::filesystem unmount path
              This  unmounts  the virtual filesystem which was mounted at path (hence removing it
              from Tcl's filesystem), or throws an error if no filesystem was mounted there.

       vfs::filesystem info ?path?
              If no arguments are given, this returns a list of all filesystems mounted  (in  all
              interpreters).   If  a path argument is given, then the command to be used for that
              path is returned, or an error is thrown if no vfs is mounted for that path.   There
              is  currently  no  facility for examining in which interpreter each command will be
              evaluated.

       vfs::filesystem fullynormalize path
              Performs a full expansion  of  path,  (as  per  'file  normalize'),  but  including
              following any links in the last element of path.

IMPLEMENTING A TCL ONLY VFS

       The vfs package will intercept every filesystem operation which falls within a given mount
       point, and pass the operation on to the mount point's command  in  the  interpreter  which
       registered it. In general this occurs by the C equivalent of an evaluation like this: eval
       $command [list $subcmd $root $relative $actualpath] $args.

       Here  subcmd  may  be  any  of  the  following:   access,   createdirectory,   deletefile,
       fileattributes,  matchindirectory,  open,  removedirectory,  stat, utime. If command takes
       appropriate action for each of these cases, a complete, perfect virtual filesystem will be
       achieved,  indistinguishable  to  Tcl  from  the native filesystem.  (CAVEATS: right now I
       don't expose to Tcl all the permission-related flags of 'glob').

       The remaining arguments specify a file path on which to operate (all commands  operate  on
       one of these), and any additional arguments which may be required to carry out the action.
       The file path is specified by three arguments: root is the part of  the  path  which  lies
       outside  this filesystem's mount point, relative is the part of the path which lies inside
       this filesytem, and actualpath is the original (unnormalized) name of the path  which  was
       used  in  the  current  command  wherever  it  originated  (in Tcl or C).  For example, if
       C:/foo/bar/mount.zip/xxx/yyy is a path in  your  filesystem,  where  mount.zip  is  a  zip
       archive  which  has  been mounted (on top of itself) and contains xxx/yyy, and the current
       working directory is inside xxx, and we evaluate a command like file exists yyy, then root
       will  be  C:/foo/bar/mount.zip,  relative will be xxx/yyy, and actualpath will be yyy. The
       file separator between the root and relative is omitted.

       Note that most filesystem operations will only  require  the  relative  argument  to  work
       correctly,  but  the  other  arguments are actually required for correct operation of some
       subcommands.

       Almost all of these commands should either return correctly (i.e. with a TCL_OK result  at
       the C level) or they should use vfs::filesystem posixerror to signal the appropriate posix
       error code.  If a Tcl error is thrown, that should be considered a bug,  but  it  will  be
       interpreted  as  an  unknown  posix error in the filesystem call.  The exceptions to these
       rules are those filesystem commands  which  are  able  to  specify  a  Tcl  error  message
       directly:  open (when an interpreter is given), matchindirectory and fileattributes (for a
       set or get operation only).  These three commands are  allowed  to  throw  any  Tcl  error
       message  which  will  be passed along to the caller, or they may throw a posix error which
       will be handled appropriately.

       The actual commands are as follows (where r-r-a represents the standard  argument  triplet
       of root, relative and actualpath):

       command access r-r-a mode
              Return  TCL_OK  or  throw  a posix error depending on whether the given access mode
              (which is an integer) is compatible with the file.

       command createdirectory r-r-a
              Create a directory with the given name.  The  command  can  assume  that  all  sub-
              directories  in the path exist and are valid, and that the actual desired path does
              not yet exist (Tcl takes care of all of that for us).

       command deletefile r-r-a
              Delete the given file.

       command fileattributes r-r-a ?index? ?value?
              If neither index nor value is given, then return a list of all acceptable attribute
              names.   If  index  is given, but no value, then retrieve the value of the index'th
              attribute (counting in order over the list returned when no argument is given)  for
              the  given  file.   If a value is also given then set the index'th attribute of the
              given file to that value.

       command matchindirectory r-r-a pattern types
              Return the list of files or directories in the given path (which is always the name
              of  an  existing  directory),  which  match the pattern and are compatible with the
              types given.  It is very important that the command correctly handle types requests
              for  directories  only  (and  files  only), because to handle any kind of recursive
              globbing, Tcl will actually generate requests for directory-only matches  from  the
              filesystem.  See vfs::matchDirectories below for help.

       command open r-r-a mode permissions
              For  this  command, mode is any of "r", "w", "a", "w+", "a+".  If the open involves
              creating a file, then permissions dictates what modes to create it  with.   If  the
              open  operation  was  not  successful,  an  error  should  be  thrown.  If the open
              operation is successful, the command should return a list  of  either  one  or  two
              items.   The  first item (which is obligatory) is the name of the channel which has
              been created.  The second item, if given, is a Tcl-callback to  be  used  when  the
              channel is closed, so that the vfs can clean up as appropriate.  This callback will
              be evaluated by Tcl just before the channel is  closed.   The  channel  will  still
              exist,  and  all  available data will have been flushed into it.  The callback can,
              for example, seek to the beginning of the channel, read its contents and store that
              contents elsewhere (e.g. compressed or on a remote ftp site, etc).  The return code
              or any errors returned by the callback are  ignored  (if  the  callback  wishes  to
              signal  an  error, it must do so asycnhronously, with bgerror, for example), unless
              the 'internalerror' script has been specified, when they are passed to that  script
              for further action.

       command removedirectory r-r-a recursive
              Delete  the  given  directory.  recursive is either 0 or 1. If it is 1 then even if
              the directory is non-empty, an attempt should be made to recursively delete it  and
              its contents.  If it is 0 and the directory is non-empty, a posix error (ENOTEMPTY)
              should be thrown.

       command stat r-r-a
              Return a list of even length containing field-name and value pairs for the contents
              of a stat structure.  The order is not important.  The option names are dev (long),
              ino (long), mode (int), nlink (long), uid (long), gid (long),  size  (long),  atime
              (long),  mtime  (long),  ctime  (long), type (string which is either "directory" or
              "file"), where the type of each argument  is  given  in  brackets.   The  procedure
              should therefore return with something like return [list dev 0 type file mtime 1234
              ...].

       command utime r-r-a actime mtime
              Set the access and modification times of  the  given  file  (these  are  read  with
              'stat').

VFS HELPERS

       The  vfslib  provides  a  number  of  Tcl  procedures  which can help with writing command
       procedures to handle the above possibilities.  These are:

       vfs::accessMode mode
              converts an integer access mode to a somewhat more preferable string, any of F X  W
              XW R RX RW.

       vfs::matchDirectories types
              Does types want directories included?

       vfs::matchFiles types
              Does types want files included?

       vfs::matchCorrectTypes types filelist ?inDir?
              Returns  that  subset  of the filelist (which are either absolute paths or names of
              files in inDir) which are compatible with the types given.

VFS DEBUGGING

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

LIMITATIONS

       There are very few limitations to the vfs code.  One subtlety that you may encounter is if
       you mount a case-sensitive virtual filesystem into a  case-insensitive  system  (e.g.  the
       standard Windows or MacOS fs) and your code relies on case-insensitivity, then it will not
       run properly in  the  virtual  filesystem.   Of  course  if  your  code  relies  on  case-
       insensitivity,  it  wouldn't  run under Tcl on Unix either, so the best solution is to fix
       your code!

       We may add link and lstat commands in the future to allow virtual filesystems  to  support
       reading  and  writing  links  -  this  is  supported by the C API, but has simply not been
       exposed to Tcl in this extension, yet.

       The Tcl 'Tcl_FSMatchInDirectory' function  takes  a  variety  of  type  information  in  a
       Tcl_GlobTypeData structure.  We currently only expose the 'type' field from that structure
       (so the 'permissions' and MacOS type/creator fields are ignored).

KEYWORDS

       vfs, filesystem, file