documentation and internalerror handling update
authorVince Darley <vincentdarley@sourceforge.net>
Fri, 21 Feb 2003 11:56:26 +0000 (11:56 +0000)
committerVince Darley <vincentdarley@sourceforge.net>
Fri, 21 Feb 2003 11:56:26 +0000 (11:56 +0000)
ChangeLog
doc/vfs.n
generic/vfs.c

index 29ebe793d12d1b04b80329b33b2a7cf0d5040dca..87155d45fce83286ea3c717087581746e6d9f1e3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2003-02-20  Vince Darley <vincentdarley@sourceforge.net>
+
+       * generic/vfs.c: completed use of internalerror and posix handling
+       for all functions.
+       * doc/vfs.n:
+       * doc/vfslib.n: more documentation regarding handling of errors
+       and use of the 'internalerror' feature.
+       
+        Around the time Tcl 8.4.2 is released we should increment tclvfs's
+       version to 1.3 and make a proper release.  In the meantime,
+       improvements to all .tcl implementations (esp. proper error
+       handling) would be greatly appreciated.
+       
 2003-02-20  Andreas Kupries  <andreask@activestate.com>
 
        * library/mk4vfs.tcl: Switching to canceling the stored after id
index 94bbcf4ab3623aa4faa7920c5538c628448ca5fb..81f0322f3c504b1638a44a88f1cf57c778821a5d 100644 (file)
--- a/doc/vfs.n
+++ b/doc/vfs.n
@@ -68,10 +68,12 @@ effect is to provide the command \fBvfs::filesystem\fR which allows
 the interpreter to intercept filesystem commands and handle them with
 Tcl code in that interpreter.
 .PP
-There are two unsupported subcommands of \fBvfs::filesystem\fR,
-\fBfullynormalize path\fR and \fBposixerror int\fR, which are used to
-normalize a path (including any final symlink) and to register a posix 
-error code with a Tcl error, respectively.
+There are three somewhat unsupported subcommands of
+\fBvfs::filesystem\fR, \fBfullynormalize path\fR, \fBposixerror int\fR,
+\fBinternalerror ?script?\fR, 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.
 .TP
 \fBvfs::filesystem\fR \fImount\fR \fI?-volume?\fR \fIpath\fR \fIcommand\fR
 To use a virtual filesystem, it must be 'mounted'.  Mounting involves
@@ -145,13 +147,25 @@ Note that most filesystem operations will only require the
 \fIrelative\fR argument to work correctly, but the other arguments are
 actually required for correct operation of some subcommands.
 .PP
+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.
+.PP
 The actual commands are as follows (where \fIr-r-a\fR represents the
 standard argument triplet of \fIroot\fR, \fIrelative\fR and
 \fIactualpath\fR):
 .TP
 \fIcommand\fR \fIaccess\fR \fIr-r-a\fR \fImode\fR
-Return 1 or throw an error depending on whether the given access mode (which 
-is an integer) is compatible with the file.
+Return TCL_OK or throw a posix error depending on whether the given
+access mode (which is an integer) is compatible with the file.
 .TP
 \fIcommand\fR \fIcreatedirectory\fR \fIr-r-a\fR
 Create a directory with the given name.
@@ -193,7 +207,9 @@ 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).
+asycnhronously, with bgerror, for example), unless the 'internalerror' 
+script has been specified, when they are passed to that script for
+further action.
 .TP
 \fIcommand\fR \fIremovedirectory\fR \fIr-r-a\fR
 Delete the given directory.
@@ -233,6 +249,12 @@ Returns that subset of the \fIfilelist\fR (which are either absolute
 paths or names of files in \fIinDir\fR) which are compatible with the
 \fItypes\fR given.
 
+.SH VFS DEBUGGING
+.PP
+Use something like this to debug problems in your implementation:
+vfs::filesystem internalerror report ; proc report {} { puts
+stderr $::errorInfo }
+
 .SH LIMITATIONS
 .PP
 There are very few limitations to the vfs code.  One subtlety that you
index 4f1d2a851314481224e0be01a7f966364a9d7a90..96a3ef16b4771af442aff8d20f664ea2aa329313 100644 (file)
@@ -854,12 +854,14 @@ VfsFilesystemObjCmd(dummy, interp, objc, objv)
 /* Handle an error thrown by a tcl vfs implementation */
 static void
 VfsInternalError(Tcl_Interp* interp) {
-    Tcl_MutexLock(&internalErrorMutex);
-    if (internalErrorScript != NULL) {
-        Tcl_EvalObjEx(interp, internalErrorScript, 
-                     TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+    if (interp != NULL) {
+       Tcl_MutexLock(&internalErrorMutex);
+       if (internalErrorScript != NULL) {
+           Tcl_EvalObjEx(interp, internalErrorScript, 
+                         TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+       }
+       Tcl_MutexUnlock(&internalErrorMutex);
     }
-    Tcl_MutexUnlock(&internalErrorMutex);
 }
 \f
 /* Return fully normalized path owned by the caller */
@@ -1344,7 +1346,7 @@ VfsOpenFileChannel(cmdInterp, pathPtr, mode, permissions)
                Tcl_ResetResult(cmdInterp);
                Tcl_AppendResult(cmdInterp, "couldn't open \"", 
                                 Tcl_GetString(pathPtr), "\": ",
-                                Tcl_PosixError(interp), (char *) NULL);
+                                Tcl_PosixError(cmdInterp), (char *) NULL);
            } else {
                Tcl_Obj* error = Tcl_GetObjResult(interp);
                /* 
@@ -1353,6 +1355,11 @@ VfsOpenFileChannel(cmdInterp, pathPtr, mode, permissions)
                 */
                Tcl_SetObjResult(cmdInterp, Tcl_DuplicateObj(error));
            }
+       } else {
+           /* Report any error, since otherwise it is lost */
+           if (returnVal != -1) {
+               VfsInternalError(interp);
+           }
        }
        if (interp == cmdInterp) {
            /* 
@@ -1663,6 +1670,11 @@ VfsFileAttrsGet(cmdInterp, index, pathPtr, objPtrRef)
            Tcl_SetObjResult(cmdInterp, *objPtrRef);
            *objPtrRef = NULL;
        }
+    } else {
+       Tcl_ResetResult(cmdInterp);
+       Tcl_AppendResult(cmdInterp, "couldn't read attributes for \"", 
+                        Tcl_GetString(pathPtr), "\": ",
+                        Tcl_PosixError(cmdInterp), (char *) NULL);
     }
     
     return returnVal;
@@ -1699,7 +1711,12 @@ VfsFileAttrsSet(cmdInterp, index, pathPtr, objPtr)
     Tcl_RestoreResult(interp, &savedResult);
     Tcl_DecrRefCount(mountCmd);
     
-    if (errorPtr != NULL) {
+    if (returnVal == -1) {
+       Tcl_ResetResult(cmdInterp);
+       Tcl_AppendResult(cmdInterp, "couldn't set attributes for \"", 
+                        Tcl_GetString(pathPtr), "\": ",
+                        Tcl_PosixError(cmdInterp), (char *) NULL);
+    } else if (errorPtr != NULL) {
        /* 
         * Leave error message in correct interp, errorPtr was
         * duplicated above, in case of threading issues.