Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/TIP+%23431+Discussion?V=2
QUERY_STRINGV=2
CONTENT_TYPE
DOCUMENT_URI/revision/TIP+#431+Discussion
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.130.89
REMOTE_PORT19618
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.138.122.4
HTTP_CF_RAY87706c700ee02d9d-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP3.138.122.4
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: TR -> LINE

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: TR -> LINE} {}} CALL {my render_wikit {TIP #431 Discussion} http://code.activestate.com/lists/tcl-core/14142/%|%discussion\ on\ tcl-core%|%\n\nOver\ several\ hours\ in\ the\ chat,\ this\ TIP\ was\ discussed.\ \ \[aspect\]\ tries\ to\ summarise\ the\ eventual\ consensus\ below.\ \ Any\ errors\ or\ misrepresentations\ are\ my\ own,\ so\ speak\ up\ :-).\n\n\nWhile\ exposing\ `mkdtemp(3)`\ as\ `\[file\ tempdir\]`\ is\ desirable,\ the\ underlying\ issue\ can\ be\ addressed\ more\ usefully\ in\ a\ much\ simpler\ fashion.\n\n\[file\ mkdir\]\ as\ implemented\ eats\ the\ `EEXIST`\ (or\ equivalent)\ error\ from\ the\ underlying\ syscall.\ \ This\ is\ desirable\ with\ `mkdir\ -p`\ style\ usage,\ where\ an\ arbitrary\ number\ of\ parent\ directories\ may\ or\ may\ not\ need\ to\ be\ created\ first,\ but\ makes\ it\ impossible\ for\ a\ script\ to\ safely\ generate\ a\ directory\ for\ its\ own\ use.\n\nPresently,\ the\ best\ option\ a\ script\ writer\ has\ is\ to\ call\ `file\ mkdir\ \$dir`\ after\ ensuring\ `file\ exists\ \$dir`\ returns\ false.\ \ But\ here\ lies\ a\ race\ condition:\ \ \ in\ the\ short\ interval\ between\ \[file\ exists\]\ returning\ false\ and\ \[file\ mkdir\]\ being\ called,\ another\ process\ might\ have\ created\ the\ directory.\ \ \[file\ mkdir\]\ turns\ EEXIST\ into\ success,\ and\ the\ programmer\ is\ none\ the\ wiser.\n\nIn\ principle,\ it\ may\ be\ possible\ to\ recover\ security\ by\ checking\ the\ ownership\ and\ permissions\ of\ the\ directory\ after\ \[file\ mkdir\],\ but\ this\ is\ nearly\ impossible\ to\ get\ correct.\ \ And\ there\ is\ no\ safe\ way\ to\ recover\ --\ if\ we\ believe\ the\ directory\ has\ been\ tampered\ with,\ we\ cannot\ safely\ change\ it.\n\nBy\ contrast,\ the\ system\ call\ itself\ offers\ an\ \"atomic\ create\"\ which\ returns\ an\ error\ when\ the\ directory\ already\ exists.\ \ TclpObjCreateDirectory\ passes\ this\ error\ back\ to\ its\ caller,\ but\ TclFileMakeDirsCmd\ hides\ it.\n\n\nSo\ the\ solution\ seems\ to\ be\ a\ variant\ of\ \[file\ mkdir\]\ that\ respects\ EEXIST.\ \ Such\ a\ command\ could\ be\ used\ to\ implement\ \[file\ tempdir\]\ correctly\ at\ the\ script\ level.\n\n\nSince\ \[file\ mkdir\]\ is\ N-ary,\ we\ can't\ simply\ add\ an\ option\ so\ a\ new\ command\ is\ needed:\ \ the\ best\ suggested\ name\ so\ far\ seems\ to\ be:\ \ \[file\ createdir\].\n\n\n\nSuggested\ behaviour\ for\ this\ command:\n\n\ \ file\ createdir\ \$dir\n\ \ \ \ Attempt\ to\ create\ the\ directory\ specified.\ \ Raises\ an\ error\ if:\n\ \ \ \ \ \ 1\ -\ The\ immediate\ parent\ of\ \$dir\ (ie,\ \[file\ dirname\ \$dir\])\ does\ not\ exist\ (POSIX\ ENOENT)\n\ \ \ \ \ \ 2\ -\ A\ directory\ named\ \$dir\ already\ exists\ (POSIX\ EEXIST)\n\ \ \ \ Otherwise,\ behaviour\ is\ equivalent\ to\ \[file\ mkdir\]\ called\ with\ one\ argument.\n\nThis\ corresponds\ to\ a\ simple\ call\ to\ `Tcl_FSCreateDirectoryProc()`,\ exposing\ the\ POSIX\ errors\ mentioned\ above.\ \ On\ Windows,\ these\ are\ translated\ from\ the\ native\ errors\ (`ERROR_ALREADY_EXISTS`,\ `ERROR_PATH_NOT_FOUND`)\ in\ `tclWinError.c`\ and\ this\ translation\ is\ tested\ in\ `winFCmd-4.3`\ and\ `4.2`.\n\n\nA\ future\ enhancement\ might\ add\ platform-specific\ prefix\ options\ to\ \[file\ createdir\],\ exposing\ permissions\ (on\ Unix)\ or\ security\ attributes\ (on\ Windows),\ but\ that's\ beyond\ scope\ for\ now.\n\n---\n**\ Proof-of-concept\ implementation\ **\n\nThis\ is\ a\ naive\ patch\ against\ trunk\ `\[b5ecfdaff3\]`:\n\n----\nIndex:\ generic/tclCmdAH.c\n==================================================================\n---\ generic/tclCmdAH.c\n+++\ generic/tclCmdAH.c\n@@\ -951,10\ +951,11\ @@\n\ \ \ \ \ static\ const\ EnsembleImplMap\ initMap\[\]\ =\ \{\n\ \ \ \ \ \ \ \ \ \{\"atime\",\ \ \ \ \ \ \ \ FileAttrAccessTimeCmd,\ \ \ \ \ \ \ \ TclCompileBasic1Or2ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"attributes\",\ \ \ \ \ \ \ \ TclFileAttrsCmd,\ \ \ \ \ \ \ \ NULL,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"channels\",\ \ \ \ \ \ \ \ TclChannelNamesCmd,\ \ \ \ \ \ \ \ TclCompileBasic0Or1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"copy\",\ \ \ \ \ \ \ \ TclFileCopyCmd,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ NULL,\ NULL,\ NULL,\ 0\},\n+\ \ \ \ \ \ \ \ \{\"createdir\",\ \ \ \ \ \ \ \ TclFileCreateDirCmd,\ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"delete\",\ \ \ \ \ \ \ \ TclFileDeleteCmd,\ \ \ \ \ \ \ \ TclCompileBasicMin0ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"dirname\",\ \ \ \ \ \ \ \ PathDirNameCmd,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"executable\",\ \ \ \ \ \ \ \ FileAttrIsExecutableCmd,\ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"exists\",\ \ \ \ \ \ \ \ FileAttrIsExistingCmd,\ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"extension\",\ \ \ \ \ \ \ \ PathExtensionCmd,\ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\nIndex:\ generic/tclFCmd.c\n==================================================================\n---\ generic/tclFCmd.c\n+++\ generic/tclFCmd.c\n@@\ -209,10\ +209,32\ @@\n\ \ *\ Side\ effects:\n\ \ *\ \ \ \ \ \ \ \ See\ the\ user\ documentation.\n\ \ *\n\ \ *----------------------------------------------------------------------\n\ \ */\n+int\n+TclFileCreateDirCmd(\n+\ \ \ \ ClientData\ clientData,\ \ \ \ \ \ \ \ /*\ Unused\ */\n+\ \ \ \ Tcl_Interp\ *interp,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /*\ Used\ for\ error\ reporting.\ */\n+\ \ \ \ int\ objc,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /*\ Number\ of\ arguments\ */\n+\ \ \ \ Tcl_Obj\ *const\ objv\[\])\ \ \ \ \ \ \ \ /*\ Argument\ strings\ passed\ to\ Tcl_FileCmd.\ */\n+\{\n+\ \ \ \ if\ (objc\ !=\ 2)\ \{\n+\ \ \ \ \ \ \ \ Tcl_WrongNumArgs(interp,\ 1,\ objv,\ \"target\")\;\n+\ \ \ \ \ \ \ \ return\ TCL_ERROR\;\n+\ \ \ \ \}\n+\n+\ \ \ \ if\ (Tcl_FSCreateDirectory(objv\[1\])\ !=\ TCL_OK)\ \{\n+\ \ \ \ \ \ \ \ Tcl_SetObjResult(interp,\ Tcl_ObjPrintf(\n+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \"can't\ create\ directory\ \\\"%s\\\":\ %s\",\n+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ TclGetString(objv\[1\]),\ Tcl_PosixError(interp)))\;\n+\ \ \ \ \ \ \ \ return\ TCL_ERROR\;\n+\ \ \ \ \}\n+\n+\ \ \ \ return\ TCL_OK\;\n+\}\n+\n\ \n\ int\n\ TclFileMakeDirsCmd(\n\ \ \ \ \ ClientData\ clientData,\ \ \ \ \ \ \ \ /*\ Unused\ */\n\ \ \ \ \ Tcl_Interp\ *interp,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /*\ Used\ for\ error\ reporting.\ */\n\nIndex:\ generic/tclInt.h\n==================================================================\n---\ generic/tclInt.h\n+++\ generic/tclInt.h\n@@\ -2891,10\ +2891,11\ @@\n\ MODULE_SCOPE\ int\ \ \ \ \ \ \ \ TclEvalEx(Tcl_Interp\ *interp,\ const\ char\ *script,\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ int\ numBytes,\ int\ flags,\ int\ line,\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ int\ *clNextOuter,\ const\ char\ *outerScript)\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileAttrsCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileCopyCmd\;\n+MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileCreateDirCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileDeleteCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileLinkCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileMakeDirsCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileReadLinkCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileRenameCmd\;\n\nIndex:\ tests/fCmd.test\n==================================================================\n---\ tests/fCmd.test\n+++\ tests/fCmd.test\n@@\ -390,10\ +390,29\ @@\n\ \}\ -constraints\ \{notRoot\}\ -body\ \{\n\ \ \ \ \ file\ mkdir\ tf1\n\ \ \ \ \ file\ exists\ tf1\n\ \}\ -result\ \{1\}\n\ \n+\;#\ not\ sure\ how\ to\ number\ these\ ..\n+test\ fCmd-4.20\ \{TclFileCreateDirCmd:\ TclpCreateDirectory\ succeeds\}\ -setup\ \{\n+\ \ \ \ cleanup\n+\}\ -constraints\ \{notRoot\}\ -body\ \{\n+\ \ \ \ file\ createdir\ td1\n+\ \ \ \ file\ exists\ td1\n+\}\ -result\ \{1\}\n+test\ fCmd-4.21\ \{TclFileCreateDirCmd:\ errno:\ EEXIST\}\ -setup\ \{\n+\ \ \ \ cleanup\n+\}\ -constraints\ \{notRoot\}\ -body\ \{\n+\ \ \ \ file\ createdir\ td1\n+\ \ \ \ list\ \[catch\ \{file\ createdir\ td1\}\ msg\]\ \$msg\ \$errorCode\n+\}\ -result\ \{1\ \{can't\ create\ directory\ \"td1\":\ file\ already\ exists\}\ \{POSIX\ EEXIST\ \{file\ already\ exists\}\}\}\n+test\ fCmd-4.22\ \{TclFileCreateDirCmd:\ errno:\ ENOENT\}\ -setup\ \{\n+\ \ \ \ cleanup\n+\}\ -constraints\ \{notRoot\}\ -body\ \{\n+\ \ \ \ list\ \[catch\ \{file\ createdir\ td1/td2\}\ msg\]\ \$msg\ \$errorCode\n+\}\ -result\ \{1\ \{can't\ create\ directory\ \"td1/td2\":\ no\ such\ file\ or\ directory\}\ \{POSIX\ ENOENT\ \{no\ such\ file\ or\ directory\}\}\}\n+\n\ test\ fCmd-5.1\ \{TclFileDeleteCmd:\ FileForceOption\ fails\}\ -constraints\ \{notRoot\}\ -body\ \{\n\ \ \ \ \ file\ delete\ -xyz\n\ \}\ -returnCodes\ error\ -result\ \{bad\ option\ \"-xyz\":\ must\ be\ -force\ or\ --\}\n\ test\ fCmd-5.2\ \{TclFileDeleteCmd:\ accept\ 0\ files\ (TIP\ 323)\}\ -body\ \{\n\ \ \ \ \ file\ delete\ -force\ -force\n\n----\n\n<<categories>>Discussion\ |\ TIP regexp2} CALL {my render {TIP #431 Discussion} http://code.activestate.com/lists/tcl-core/14142/%|%discussion\ on\ tcl-core%|%\n\nOver\ several\ hours\ in\ the\ chat,\ this\ TIP\ was\ discussed.\ \ \[aspect\]\ tries\ to\ summarise\ the\ eventual\ consensus\ below.\ \ Any\ errors\ or\ misrepresentations\ are\ my\ own,\ so\ speak\ up\ :-).\n\n\nWhile\ exposing\ `mkdtemp(3)`\ as\ `\[file\ tempdir\]`\ is\ desirable,\ the\ underlying\ issue\ can\ be\ addressed\ more\ usefully\ in\ a\ much\ simpler\ fashion.\n\n\[file\ mkdir\]\ as\ implemented\ eats\ the\ `EEXIST`\ (or\ equivalent)\ error\ from\ the\ underlying\ syscall.\ \ This\ is\ desirable\ with\ `mkdir\ -p`\ style\ usage,\ where\ an\ arbitrary\ number\ of\ parent\ directories\ may\ or\ may\ not\ need\ to\ be\ created\ first,\ but\ makes\ it\ impossible\ for\ a\ script\ to\ safely\ generate\ a\ directory\ for\ its\ own\ use.\n\nPresently,\ the\ best\ option\ a\ script\ writer\ has\ is\ to\ call\ `file\ mkdir\ \$dir`\ after\ ensuring\ `file\ exists\ \$dir`\ returns\ false.\ \ But\ here\ lies\ a\ race\ condition:\ \ \ in\ the\ short\ interval\ between\ \[file\ exists\]\ returning\ false\ and\ \[file\ mkdir\]\ being\ called,\ another\ process\ might\ have\ created\ the\ directory.\ \ \[file\ mkdir\]\ turns\ EEXIST\ into\ success,\ and\ the\ programmer\ is\ none\ the\ wiser.\n\nIn\ principle,\ it\ may\ be\ possible\ to\ recover\ security\ by\ checking\ the\ ownership\ and\ permissions\ of\ the\ directory\ after\ \[file\ mkdir\],\ but\ this\ is\ nearly\ impossible\ to\ get\ correct.\ \ And\ there\ is\ no\ safe\ way\ to\ recover\ --\ if\ we\ believe\ the\ directory\ has\ been\ tampered\ with,\ we\ cannot\ safely\ change\ it.\n\nBy\ contrast,\ the\ system\ call\ itself\ offers\ an\ \"atomic\ create\"\ which\ returns\ an\ error\ when\ the\ directory\ already\ exists.\ \ TclpObjCreateDirectory\ passes\ this\ error\ back\ to\ its\ caller,\ but\ TclFileMakeDirsCmd\ hides\ it.\n\n\nSo\ the\ solution\ seems\ to\ be\ a\ variant\ of\ \[file\ mkdir\]\ that\ respects\ EEXIST.\ \ Such\ a\ command\ could\ be\ used\ to\ implement\ \[file\ tempdir\]\ correctly\ at\ the\ script\ level.\n\n\nSince\ \[file\ mkdir\]\ is\ N-ary,\ we\ can't\ simply\ add\ an\ option\ so\ a\ new\ command\ is\ needed:\ \ the\ best\ suggested\ name\ so\ far\ seems\ to\ be:\ \ \[file\ createdir\].\n\n\n\nSuggested\ behaviour\ for\ this\ command:\n\n\ \ file\ createdir\ \$dir\n\ \ \ \ Attempt\ to\ create\ the\ directory\ specified.\ \ Raises\ an\ error\ if:\n\ \ \ \ \ \ 1\ -\ The\ immediate\ parent\ of\ \$dir\ (ie,\ \[file\ dirname\ \$dir\])\ does\ not\ exist\ (POSIX\ ENOENT)\n\ \ \ \ \ \ 2\ -\ A\ directory\ named\ \$dir\ already\ exists\ (POSIX\ EEXIST)\n\ \ \ \ Otherwise,\ behaviour\ is\ equivalent\ to\ \[file\ mkdir\]\ called\ with\ one\ argument.\n\nThis\ corresponds\ to\ a\ simple\ call\ to\ `Tcl_FSCreateDirectoryProc()`,\ exposing\ the\ POSIX\ errors\ mentioned\ above.\ \ On\ Windows,\ these\ are\ translated\ from\ the\ native\ errors\ (`ERROR_ALREADY_EXISTS`,\ `ERROR_PATH_NOT_FOUND`)\ in\ `tclWinError.c`\ and\ this\ translation\ is\ tested\ in\ `winFCmd-4.3`\ and\ `4.2`.\n\n\nA\ future\ enhancement\ might\ add\ platform-specific\ prefix\ options\ to\ \[file\ createdir\],\ exposing\ permissions\ (on\ Unix)\ or\ security\ attributes\ (on\ Windows),\ but\ that's\ beyond\ scope\ for\ now.\n\n---\n**\ Proof-of-concept\ implementation\ **\n\nThis\ is\ a\ naive\ patch\ against\ trunk\ `\[b5ecfdaff3\]`:\n\n----\nIndex:\ generic/tclCmdAH.c\n==================================================================\n---\ generic/tclCmdAH.c\n+++\ generic/tclCmdAH.c\n@@\ -951,10\ +951,11\ @@\n\ \ \ \ \ static\ const\ EnsembleImplMap\ initMap\[\]\ =\ \{\n\ \ \ \ \ \ \ \ \ \{\"atime\",\ \ \ \ \ \ \ \ FileAttrAccessTimeCmd,\ \ \ \ \ \ \ \ TclCompileBasic1Or2ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"attributes\",\ \ \ \ \ \ \ \ TclFileAttrsCmd,\ \ \ \ \ \ \ \ NULL,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"channels\",\ \ \ \ \ \ \ \ TclChannelNamesCmd,\ \ \ \ \ \ \ \ TclCompileBasic0Or1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"copy\",\ \ \ \ \ \ \ \ TclFileCopyCmd,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ NULL,\ NULL,\ NULL,\ 0\},\n+\ \ \ \ \ \ \ \ \{\"createdir\",\ \ \ \ \ \ \ \ TclFileCreateDirCmd,\ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"delete\",\ \ \ \ \ \ \ \ TclFileDeleteCmd,\ \ \ \ \ \ \ \ TclCompileBasicMin0ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"dirname\",\ \ \ \ \ \ \ \ PathDirNameCmd,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"executable\",\ \ \ \ \ \ \ \ FileAttrIsExecutableCmd,\ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"exists\",\ \ \ \ \ \ \ \ FileAttrIsExistingCmd,\ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\ \ \ \ \ \ \ \ \ \{\"extension\",\ \ \ \ \ \ \ \ PathExtensionCmd,\ \ \ \ \ \ \ \ TclCompileBasic1ArgCmd,\ NULL,\ NULL,\ 0\},\n\nIndex:\ generic/tclFCmd.c\n==================================================================\n---\ generic/tclFCmd.c\n+++\ generic/tclFCmd.c\n@@\ -209,10\ +209,32\ @@\n\ \ *\ Side\ effects:\n\ \ *\ \ \ \ \ \ \ \ See\ the\ user\ documentation.\n\ \ *\n\ \ *----------------------------------------------------------------------\n\ \ */\n+int\n+TclFileCreateDirCmd(\n+\ \ \ \ ClientData\ clientData,\ \ \ \ \ \ \ \ /*\ Unused\ */\n+\ \ \ \ Tcl_Interp\ *interp,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /*\ Used\ for\ error\ reporting.\ */\n+\ \ \ \ int\ objc,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /*\ Number\ of\ arguments\ */\n+\ \ \ \ Tcl_Obj\ *const\ objv\[\])\ \ \ \ \ \ \ \ /*\ Argument\ strings\ passed\ to\ Tcl_FileCmd.\ */\n+\{\n+\ \ \ \ if\ (objc\ !=\ 2)\ \{\n+\ \ \ \ \ \ \ \ Tcl_WrongNumArgs(interp,\ 1,\ objv,\ \"target\")\;\n+\ \ \ \ \ \ \ \ return\ TCL_ERROR\;\n+\ \ \ \ \}\n+\n+\ \ \ \ if\ (Tcl_FSCreateDirectory(objv\[1\])\ !=\ TCL_OK)\ \{\n+\ \ \ \ \ \ \ \ Tcl_SetObjResult(interp,\ Tcl_ObjPrintf(\n+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \"can't\ create\ directory\ \\\"%s\\\":\ %s\",\n+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ TclGetString(objv\[1\]),\ Tcl_PosixError(interp)))\;\n+\ \ \ \ \ \ \ \ return\ TCL_ERROR\;\n+\ \ \ \ \}\n+\n+\ \ \ \ return\ TCL_OK\;\n+\}\n+\n\ \n\ int\n\ TclFileMakeDirsCmd(\n\ \ \ \ \ ClientData\ clientData,\ \ \ \ \ \ \ \ /*\ Unused\ */\n\ \ \ \ \ Tcl_Interp\ *interp,\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ /*\ Used\ for\ error\ reporting.\ */\n\nIndex:\ generic/tclInt.h\n==================================================================\n---\ generic/tclInt.h\n+++\ generic/tclInt.h\n@@\ -2891,10\ +2891,11\ @@\n\ MODULE_SCOPE\ int\ \ \ \ \ \ \ \ TclEvalEx(Tcl_Interp\ *interp,\ const\ char\ *script,\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ int\ numBytes,\ int\ flags,\ int\ line,\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ int\ *clNextOuter,\ const\ char\ *outerScript)\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileAttrsCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileCopyCmd\;\n+MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileCreateDirCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileDeleteCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileLinkCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileMakeDirsCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileReadLinkCmd\;\n\ MODULE_SCOPE\ Tcl_ObjCmdProc\ TclFileRenameCmd\;\n\nIndex:\ tests/fCmd.test\n==================================================================\n---\ tests/fCmd.test\n+++\ tests/fCmd.test\n@@\ -390,10\ +390,29\ @@\n\ \}\ -constraints\ \{notRoot\}\ -body\ \{\n\ \ \ \ \ file\ mkdir\ tf1\n\ \ \ \ \ file\ exists\ tf1\n\ \}\ -result\ \{1\}\n\ \n+\;#\ not\ sure\ how\ to\ number\ these\ ..\n+test\ fCmd-4.20\ \{TclFileCreateDirCmd:\ TclpCreateDirectory\ succeeds\}\ -setup\ \{\n+\ \ \ \ cleanup\n+\}\ -constraints\ \{notRoot\}\ -body\ \{\n+\ \ \ \ file\ createdir\ td1\n+\ \ \ \ file\ exists\ td1\n+\}\ -result\ \{1\}\n+test\ fCmd-4.21\ \{TclFileCreateDirCmd:\ errno:\ EEXIST\}\ -setup\ \{\n+\ \ \ \ cleanup\n+\}\ -constraints\ \{notRoot\}\ -body\ \{\n+\ \ \ \ file\ createdir\ td1\n+\ \ \ \ list\ \[catch\ \{file\ createdir\ td1\}\ msg\]\ \$msg\ \$errorCode\n+\}\ -result\ \{1\ \{can't\ create\ directory\ \"td1\":\ file\ already\ exists\}\ \{POSIX\ EEXIST\ \{file\ already\ exists\}\}\}\n+test\ fCmd-4.22\ \{TclFileCreateDirCmd:\ errno:\ ENOENT\}\ -setup\ \{\n+\ \ \ \ cleanup\n+\}\ -constraints\ \{notRoot\}\ -body\ \{\n+\ \ \ \ list\ \[catch\ \{file\ createdir\ td1/td2\}\ msg\]\ \$msg\ \$errorCode\n+\}\ -result\ \{1\ \{can't\ create\ directory\ \"td1/td2\":\ no\ such\ file\ or\ directory\}\ \{POSIX\ ENOENT\ \{no\ such\ file\ or\ directory\}\}\}\n+\n\ test\ fCmd-5.1\ \{TclFileDeleteCmd:\ FileForceOption\ fails\}\ -constraints\ \{notRoot\}\ -body\ \{\n\ \ \ \ \ file\ delete\ -xyz\n\ \}\ -returnCodes\ error\ -result\ \{bad\ option\ \"-xyz\":\ must\ be\ -force\ or\ --\}\n\ test\ fCmd-5.2\ \{TclFileDeleteCmd:\ accept\ 0\ files\ (TIP\ 323)\}\ -body\ \{\n\ \ \ \ \ file\ delete\ -force\ -force\n\n----\n\n<<categories>>Discussion\ |\ TIP} CALL {my revision {TIP #431 Discussion}} CALL {::oo::Obj4067586 process revision/TIP+%23431+Discussion} CALL {::oo::Obj4067584 process}

-errorcode

NONE

-errorinfo

Unknow state transition: TR -> LINE
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4