# This file tests the tclWinFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: winFCmd.test,v 1.20.2.9 2006/03/19 22:47:30 vincentdarley Exp $
#

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

proc createfile {file {string a}} {
    set f [open $file w]
    puts -nonewline $f $string
    close $f
    return $string
}

proc contents {file} {
    set f [open $file r]
    set r [read $f]
    close $f
    set r
}

proc cleanup {args} {
    foreach p ". $args" {
	set x ""
	catch {
	    set x [glob -directory $p tf* td*]
	}
	if {$x != ""} {
	    catch {eval file delete -force -- $x}
	}
    }
}

if {[string equal $tcl_platform(platform) "windows"]} {
    if {[string equal $tcl_platform(os) "Windows NT"] \
      && [string equal [string index $tcl_platform(osVersion) 0] "5"]} {
	tcltest::testConstraint win2000orXP 1
	tcltest::testConstraint winOlderThan2000 0
    } else {
	tcltest::testConstraint win2000orXP 0
	tcltest::testConstraint winOlderThan2000 1
    }
} else {
    tcltest::testConstraint win2000orXP 0
    tcltest::testConstraint winOlderThan2000 0
}

set ::tcltest::testConstraints(cdrom) 0
set ::tcltest::testConstraints(exdev) 0

# find a CD-ROM so we can test read-only filesystems.

set cdrom {}
if { [info commands ::testvolumetype] ne {} } {
    foreach p {d e f g h i j k l m n o p q r s t u v w x y z} {
        if { ! [catch { testvolumetype ${p}: } result] && $result eq {CDFS} } {
	    set cdrom ${p}:
	}
    }
}

proc findfile {dir} {
    foreach p [glob $dir/*] {
        if {[file type $p] == "file"} {
	    return $p
	}
    }
    foreach p [glob $dir/*] {
        if {[file type $p] == "directory"} {
	    set f [findfile $p]
	    if {$f != ""} {
	        return $f
	    }
	}
    }
    return ""
}

if {$cdrom != ""} {
    set ::tcltest::testConstraints(cdrom) 1
    set cdfile [findfile $cdrom]
}

if {[file exists c:/] && [file exists d:/]} {
    catch {file delete d:/tf1}
    if {[catch {close [open d:/tf1 w]}] == 0} {
	file delete d:/tf1
	set ::tcltest::testConstraints(exdev) 1
    }
}

file delete -force -- td1
set foo [catch {open td1 w} testfile]
if {$foo} {
    set ::tcltest::testConstraints(longFileNames) 0
} else {
    close $testfile
    set ::tcltest::testConstraints(longFileNames) 1
    file delete -force -- td1
}

# A really long file name
# length of longname is 1216 chars, which should be greater than any static
# buffer or allowable filename.

set longname "abcdefghihjllmnopqrstuvwxyz01234567890"
append longname $longname
append longname $longname
append longname $longname
append longname $longname
append longname $longname

# Uses the "testfile" command instead of the "file" command.  The "file"
# command provides several layers of sanity checks on the arguments and
# it can be difficult to actually forward "insane" arguments to the
# low-level posix emulation layer.

test winFCmd-1.1 {TclpRenameFile: errno: EACCES} {pcOnly cdrom} {
    list [catch {testfile mv $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
test winFCmd-1.2 {TclpRenameFile: errno: EEXIST} {pcOnly} {
    cleanup
    file mkdir td1/td2/td3
    file mkdir td2
    list [catch {testfile mv td2 td1/td2} msg] $msg
} {1 EEXIST} 
test winFCmd-1.3 {TclpRenameFile: errno: EINVAL} {pcOnly} {
    cleanup
    list [catch {testfile mv / td1} msg] $msg
} {1 EINVAL}
test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile mv td1 td1/td2} msg] $msg
} {1 EINVAL}
test winFCmd-1.5 {TclpRenameFile: errno: EISDIR} {pcOnly} {
    cleanup
    file mkdir td1
    createfile tf1
    list [catch {testfile mv tf1 td1} msg] $msg
} {1 EISDIR}
test winFCmd-1.6 {TclpRenameFile: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile mv tf1 tf2} msg] $msg
} {1 ENOENT}
test winFCmd-1.7 {TclpRenameFile: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile mv "" tf2} msg] $msg
} {1 ENOENT}
test winFCmd-1.8 {TclpRenameFile: errno: ENOENT} {pcOnly} {
    cleanup
    createfile tf1
    list [catch {testfile mv tf1 ""} msg] $msg
} {1 ENOENT}
test winFCmd-1.9 {TclpRenameFile: errno: ENOTDIR} {pcOnly} {
    cleanup
    file mkdir td1
    createfile tf1
    list [catch {testfile mv td1 tf1} msg] $msg
} {1 ENOTDIR}
test winFCmd-1.10 {TclpRenameFile: errno: EXDEV} {pcOnly exdev} {
    file delete -force d:/tf1
    file mkdir c:/tf1
    set msg [list [catch {testfile mv c:/tf1 d:/tf1} msg] $msg]
    file delete -force c:/tf1
    set msg
} {1 EXDEV}
test winFCmd-1.11 {TclpRenameFile: errno: EACCES} {pcOnly} {
    cleanup
    set fd [open tf1 w]
    set msg [list [catch {testfile mv tf1 tf2} msg] $msg]
    close $fd
    set msg
} {1 EACCES}
test winFCmd-1.12 {TclpRenameFile: errno: EACCES} {pcOnly} {
    cleanup
    createfile tf1
    set fd [open tf2 w]
    set msg [list [catch {testfile mv tf1 tf2} msg] $msg]
    close $fd
    set msg
} {1 EACCES}
test winFCmd-1.13 {TclpRenameFile: errno: EACCES} {pcOnly win2000orXP} {
    cleanup
    list [catch {testfile mv nul tf1} msg] $msg
} {1 EINVAL}
test winFCmd-1.13.1 {TclpRenameFile: errno: EACCES} {pcOnly winOlderThan2000} {
    cleanup
    list [catch {testfile mv nul tf1} msg] $msg
} {1 EACCES}
test winFCmd-1.14 {TclpRenameFile: errno: EACCES} {pcOnly 95} {
    cleanup
    createfile tf1
    list [catch {testfile mv tf1 nul} msg] $msg
} {1 EACCES}
test winFCmd-1.15 {TclpRenameFile: errno: EEXIST} {pcOnly nt} {
    cleanup
    createfile tf1
    list [catch {testfile mv tf1 nul} msg] $msg
} {1 EEXIST}
test winFCmd-1.16 {TclpRenameFile: MoveFile() != FALSE} {pcOnly} {
    cleanup
    createfile tf1 tf1
    testfile mv tf1 tf2
    list [file exists tf1] [contents tf2]
} {0 tf1}
test winFCmd-1.17 {TclpRenameFile: MoveFile() == FALSE} {pcOnly} {
    cleanup
    list [catch {testfile mv tf1 tf2} msg] $msg
} {1 ENOENT} 
test winFCmd-1.18 {TclpRenameFile: srcAttr == -1} {pcOnly} {
    cleanup
    list [catch {testfile mv tf1 tf2} msg] $msg
} {1 ENOENT} 
test winFCmd-1.19 {TclpRenameFile: errno == EACCES} {pcOnly win2000orXP} {
    cleanup
    list [catch {testfile mv nul tf1} msg] $msg
} {1 EINVAL}
test winFCmd-1.19.1 {TclpRenameFile: errno == EACCES} {pcOnly winOlderThan2000} {
    cleanup
    list [catch {testfile mv nul tf1} msg] $msg
} {1 EACCES}
test winFCmd-1.20 {TclpRenameFile: src is dir} {pcOnly nt} {
    # under 95, this would actually succeed and move the current dir out from 
    # under the current process!
    cleanup
    file delete /tf1
    list [catch {testfile mv [pwd] /tf1} msg] $msg
} {1 EACCES}
test winFCmd-1.21 {TclpRenameFile: long src} {pcOnly} {
    cleanup
    list [catch {testfile mv $longname tf1} msg] $msg
} {1 ENAMETOOLONG}
test winFCmd-1.22 {TclpRenameFile: long dst} {pcOnly} {
    cleanup
    createfile tf1
    list [catch {testfile mv tf1 $longname} msg] $msg
} {1 ENAMETOOLONG}
test winFCmd-1.23 {TclpRenameFile: move dir into self} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile mv [pwd]/td1 td1/td2} msg] $msg
} {1 EINVAL}
test winFCmd-1.24 {TclpRenameFile: move a root dir} {pcOnly} {
    cleanup
    list [catch {testfile mv / c:/} msg] $msg
} {1 EINVAL}
test winFCmd-1.25 {TclpRenameFile: cross file systems} {pcOnly cdrom} {
    cleanup
    file mkdir td1
    list [catch {testfile mv td1 $cdrom/td1} msg] $msg
} {1 EXDEV} 
test winFCmd-1.26 {TclpRenameFile: readonly fs} {pcOnly cdrom} {
    cleanup
    list [catch {testfile mv $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
test winFCmd-1.27 {TclpRenameFile: open file} {pcOnly} {
    cleanup
    set fd [open tf1 w]
    set msg [list [catch {testfile mv tf1 tf2} msg] $msg]
    close $fd
    set msg
} {1 EACCES}    
test winFCmd-1.28 {TclpRenameFile: errno == EEXIST} {pcOnly} {
    cleanup
    createfile tf1
    createfile tf2
    testfile mv tf1 tf2
    list [file exists tf1] [file exists tf2]
} {0 1}
test winFCmd-1.29 {TclpRenameFile: src is dir} {pcOnly} {
    cleanup
    file mkdir td1
    createfile tf1
    list [catch {testfile mv td1 tf1} msg] $msg
} {1 ENOTDIR} 
test winFCmd-1.30 {TclpRenameFile: dst is dir} {pcOnly} {
    cleanup
    file mkdir td1
    file mkdir td2/td2
    list [catch {testfile mv td1 td2} msg] $msg
} {1 EEXIST}
test winFCmd-1.31 {TclpRenameFile: TclpRemoveDirectory fails} {pcOnly} {
    cleanup
    file mkdir td1
    file mkdir td2/td2
    list [catch {testfile mv td1 td2} msg] $msg
} {1 EEXIST}
test winFCmd-1.32 {TclpRenameFile: TclpRemoveDirectory succeeds} {pcOnly} {
    cleanup
    file mkdir td1/td2
    file mkdir td2
    testfile mv td1 td2
    list [file exists td1] [file exists td2] [file exists td2/td2]
} {0 1 1}
test winFCmd-1.33 {TclpRenameFile: After removing dst dir, MoveFile fails} \
	{pcOnly exdev} {
    file mkdir d:/td1
    testchmod 000 d:/td1
    file mkdir c:/tf1
    set msg [list [catch {testfile mv c:/tf1 d:/td1} msg] $msg]
    set msg "$msg [file writable d:/td1]"
    file delete d:/td1
    file delete -force c:/tf1
    set msg
} {1 EXDEV 0}
test winFCmd-1.34 {TclpRenameFile: src is dir, dst is not} {pcOnly} {
    file mkdir td1
    createfile tf1
    list [catch {testfile mv td1 tf1} msg] $msg
} {1 ENOTDIR}
test winFCmd-1.35 {TclpRenameFile: src is not dir, dst is} {pcOnly} {
    file mkdir td1
    createfile tf1
    list [catch {testfile mv tf1 td1} msg] $msg
} {1 EISDIR}
test winFCmd-1.36 {TclpRenameFile: src and dst not dir} {pcOnly} {
    createfile tf1 tf1
    createfile tf2 tf2
    testfile mv tf1 tf2
    contents tf2
} {tf1}
test winFCmd-1.37 {TclpRenameFile: need to restore temp file} {pcOnly} {
    # Can't figure out how to cause this. 
    # Need a file that can't be copied.
} {}

test winFCmd-2.1 {TclpCopyFile: errno: EACCES} {pcOnly cdrom} {
    cleanup
    list [catch {testfile cp $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
test winFCmd-2.2 {TclpCopyFile: errno: EISDIR} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile cp td1 tf1} msg] $msg
} {1 EISDIR}
test winFCmd-2.3 {TclpCopyFile: errno: EISDIR} {pcOnly} {
    cleanup
    createfile tf1
    file mkdir td1
    list [catch {testfile cp tf1 td1} msg] $msg
} {1 EISDIR}
test winFCmd-2.4 {TclpCopyFile: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile cp tf1 tf2} msg] $msg
} {1 ENOENT}
test winFCmd-2.5 {TclpCopyFile: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile cp "" tf2} msg] $msg
} {1 ENOENT}
test winFCmd-2.6 {TclpCopyFile: errno: ENOENT} {pcOnly} {
    cleanup
    createfile tf1
    list [catch {testfile cp tf1 ""} msg] $msg
} {1 ENOENT}
test winFCmd-2.7 {TclpCopyFile: errno: EACCES} {pcOnly 95} {
    cleanup
    createfile tf1
    set fd [open tf2 w]
    set msg [list [catch {testfile cp tf1 tf2} msg] $msg]
    close $fd
    set msg
} {1 EACCES}
test winFCmd-2.8 {TclpCopyFile: errno: EACCES} {pcOnly win2000orXP} {
    cleanup
    list [catch {testfile cp nul tf1} msg] $msg
} {1 EINVAL}
test winFCmd-2.8.1 {TclpCopyFile: errno: EACCES} {pcOnly nt winOlderThan2000} {
    cleanup
    list [catch {testfile cp nul tf1} msg] $msg
} {1 EACCES}
test winFCmd-2.9 {TclpCopyFile: errno: ENOENT} {pcOnly 95} {
    cleanup
    list [catch {testfile cp nul tf1} msg] $msg
} {1 ENOENT}
test winFCmd-2.10 {TclpCopyFile: CopyFile succeeds} {pcOnly} {
    cleanup
    createfile tf1 tf1
    testfile cp tf1 tf2
    list [contents tf1] [contents tf2]
} {tf1 tf1}
test winFCmd-2.11 {TclpCopyFile: CopyFile succeeds} {pcOnly} {
    cleanup
    createfile tf1 tf1
    createfile tf2 tf2
    testfile cp tf1 tf2
    list [contents tf1] [contents tf2]
} {tf1 tf1}
test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} {pcOnly} {
    cleanup
    createfile tf1 tf1
    testchmod 000 tf1
    testfile cp tf1 tf2
    list [contents tf2] [file writable tf2]
} {tf1 0}
test winFCmd-2.13 {TclpCopyFile: CopyFile fails} {pcOnly} {
    cleanup
    createfile tf1
    file mkdir td1
    list [catch {testfile cp tf1 td1} msg] $msg
} {1 EISDIR} 
test winFCmd-2.14 {TclpCopyFile: errno == EACCES} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile cp td1 tf1} msg] $msg
} {1 EISDIR}
test winFCmd-2.15 {TclpCopyFile: src is directory} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile cp td1 tf1} msg] $msg
} {1 EISDIR}
test winFCmd-2.16 {TclpCopyFile: dst is directory} {pcOnly} {
    cleanup
    createfile tf1
    file mkdir td1
    list [catch {testfile cp tf1 td1} msg] $msg
} {1 EISDIR}
test winFCmd-2.17 {TclpCopyFile: dst is readonly} {pcOnly} {
    cleanup
    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 000 tf2
    testfile cp tf1 tf2
    list [file writable tf2] [contents tf2]
} {1 tf1}
test winFCmd-2.18 {TclpCopyFile: still can't copy onto dst} {pcOnly 95} {
    cleanup
    createfile tf1
    createfile tf2
    testchmod 000 tf2
    set fd [open tf2]
    set msg [list [catch {testfile cp tf1 tf2} msg] $msg]
    close $fd
    set msg "$msg [file writable tf2]"
} {1 EACCES 0}    

test winFCmd-3.1 {TclpDeleteFile: errno: EACCES} {pcOnly cdrom} {
    list [catch {testfile rm $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
test winFCmd-3.2 {TclpDeleteFile: errno: EISDIR} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile rm td1} msg] $msg
} {1 EISDIR} 
test winFCmd-3.3 {TclpDeleteFile: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile rm tf1} msg] $msg
} {1 ENOENT}
test winFCmd-3.4 {TclpDeleteFile: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile rm ""} msg] $msg
} {1 ENOENT}
test winFCmd-3.5 {TclpDeleteFile: errno: EACCES} {pcOnly} {
    cleanup
    set fd [open tf1 w]
    set msg [list [catch {testfile rm tf1} msg] $msg]
    close $fd
    set msg
} {1 EACCES}
test winFCmd-3.6 {TclpDeleteFile: errno: EACCES} {pcOnly} {
    cleanup
    list [catch {testfile rm nul} msg] $msg
} {1 EACCES}
test winFCmd-3.7 {TclpDeleteFile: DeleteFile succeeds} {pcOnly} {
    cleanup
    createfile tf1
    testfile rm tf1
    file exists tf1
} {0}
test winFCmd-3.8 {TclpDeleteFile: DeleteFile fails} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile rm td1} msg] $msg
} {1 EISDIR}
test winFCmd-3.9 {TclpDeleteFile: errno == EACCES} {pcOnly} {
    cleanup
    set fd [open tf1 w]
    set msg [list [catch {testfile rm tf1} msg] $msg]
    close $fd
    set msg
} {1 EACCES}
test winFCmd-3.10 {TclpDeleteFile: path is readonly} {pcOnly} {
    cleanup
    createfile tf1
    testchmod 000 tf1
    testfile rm tf1
    file exists tf1
} {0}
test winFCmd-3.11 {TclpDeleteFile: still can't remove path} {pcOnly} {
    cleanup
    set fd [open tf1 w]
    testchmod 000 tf1
    set msg [list [catch {testfile rm tf1} msg] $msg]
    close $fd
    set msg
} {1 EACCES}

test winFCmd-4.1 {TclpCreateDirectory: errno: EACCES} {pcOnly nt cdrom} {
    list [catch {testfile mkdir $cdrom/dummy~~.dir} msg] $msg
} {1 EACCES}
test winFCmd-4.2 {TclpCreateDirectory: errno: EACCES} {pcOnly 95 cdrom} {
    list [catch {testfile mkdir $cdrom/dummy~~.dir} msg] $msg
} {1 ENOSPC}
test winFCmd-4.3 {TclpCreateDirectory: errno: EEXIST} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile mkdir td1} msg] $msg
} {1 EEXIST}
test winFCmd-4.4 {TclpCreateDirectory: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile mkdir td1/td2} msg] $msg
} {1 ENOENT}
test winFCmd-4.5 {TclpCreateDirectory: CreateDirectory succeeds} {pcOnly} {
    cleanup
    testfile mkdir td1
    file type td1
} {directory}

test winFCmd-5.1 {TclpCopyDirectory: calls TraverseWinTree} {pcOnly} {
    cleanup
    file mkdir td1
    testfile cpdir td1 td2
    list [file type td1] [file type td2]
} {directory directory}

test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} {pcOnly} {
    cleanup
    file mkdir td1
    testchmod 000 td1
    testfile rmdir td1
    file exists td1
} {0}
test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} {pcOnly} {
    cleanup
    file mkdir td1/td2
    list [catch {testfile rmdir td1} msg] [file tail $msg]
} {1 {td1 EEXIST}}
test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {pcOnly} {
    # can't test this w/o removing everything on your hard disk first!
    # testfile rmdir /
} {}
test winFCmd-6.4 {TclpRemoveDirectory: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile rmdir td1} msg] [file tail $msg]
} {1 {td1 ENOENT}}
test winFCmd-6.5 {TclpRemoveDirectory: errno: ENOENT} {pcOnly} {
    cleanup
    list [catch {testfile rmdir ""} msg] $msg
} {1 ENOENT}
test winFCmd-6.6 {TclpRemoveDirectory: errno: ENOTDIR} {pcOnly} {
    cleanup
    createfile tf1
    list [catch {testfile rmdir tf1} msg] [file tail $msg]
} {1 {tf1 ENOTDIR}}
test winFCmd-6.7 {TclpRemoveDirectory: RemoveDirectory succeeds} {pcOnly} {
    cleanup
    file mkdir td1
    testfile rmdir td1
    file exists td1
} {0}
test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} {pcOnly} {
    cleanup
    createfile tf1
    list [catch {testfile rmdir tf1} msg] [file tail $msg]
} {1 {tf1 ENOTDIR}}
test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} {pcOnly} {
    cleanup
    file mkdir td1
    testchmod 000 td1
    testfile rmdir td1
    file exists td1
} {0}
test winFCmd-6.10 {TclpRemoveDirectory: attr == -1} {pcOnly 95} {
    cleanup
    list [catch {testfile rmdir nul} msg] $msg
} {1 {nul EACCES}}
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} {pcOnly nt} {
    cleanup
    set res [list [catch {testfile rmdir /} msg] $msg]
    # WinXP returns EEXIST, WinNT seems to return EACCES.  No policy
    # decision has been made as to which is correct.
    regsub {E(ACCES|EXIST)} $res "EACCES or EEXIST" res
    # Don't mind which drive we're on
    regsub {[A-Z]:} $res ""
} {1 {/ EACCES or EEXIST}}
test winFCmd-6.12 {TclpRemoveDirectory: errno == EACCES} {pcOnly 95} {
    cleanup
    createfile tf1
    list [catch {testfile rmdir tf1} msg] $msg
} {1 {tf1 ENOTDIR}}
test winFCmd-6.13 {TclpRemoveDirectory: write-protected} {pcOnly} {
    cleanup
    file mkdir td1
    testchmod 000 td1
    testfile rmdir td1
    file exists td1
} {0}
test winFCmd-6.14 {TclpRemoveDirectory: check if empty dir} {pcOnly 95} {
    cleanup
    file mkdir td1/td2
    list [catch {testfile rmdir td1} msg] $msg
} {1 {td1 EEXIST}}
test winFCmd-6.15 {TclpRemoveDirectory: !recursive} {pcOnly} {
    cleanup
    file mkdir td1/td2
    list [catch {testfile rmdir td1} msg] [file tail $msg]
} {1 {td1 EEXIST}}
test winFCmd-6.16 {TclpRemoveDirectory: recursive, but errno != EEXIST} {pcOnly} {
    cleanup
    createfile tf1
    list [catch {testfile rmdir -force tf1} msg] $msg
} {1 {tf1 ENOTDIR}}
test winFCmd-6.17 {TclpRemoveDirectory: calls TraverseWinTree} {pcOnly} {
    cleanup
    file mkdir td1/td2
    testfile rmdir -force td1
    file exists td1
} {0}

test winFCmd-7.1 {TraverseWinTree: targetPtr == NULL} {pcOnly} {
    cleanup
    file mkdir td1/td2/td3
    testfile rmdir -force td1
    file exists td1
} {0}
test winFCmd-7.2 {TraverseWinTree: targetPtr != NULL} {pcOnly} {
    cleanup
    file mkdir td1/td2/td3
    testfile cpdir td1 td2
    list [file exists td1] [file exists td2]
} {1 1}
test winFCmd-7.3 {TraverseWinTree: sourceAttr == -1} {pcOnly} {
    cleanup
    list [catch {testfile cpdir td1 td2} msg] $msg
} {1 {td1 ENOENT}}
test winFCmd-7.4 {TraverseWinTree: source isn't directory} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile cpdir td1 td2
    contents td2/tf1
} {tf1}
test winFCmd-7.5 {TraverseWinTree: call TraversalCopy: DOTREE_F} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile cpdir td1 td2
    contents td2/tf1
} {tf1}
test winFCmd-7.6 {TraverseWinTree: call TraversalDelete: DOTREE_F} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile rmdir -force td1
    file exists td1
} {0}
test winFCmd-7.7 {TraverseWinTree: append \ to source if necessary} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile cpdir td1 td2
    contents td2/tf1
} {tf1}    
test winFCmd-7.8 {TraverseWinTree: append \ to source if necessary} {pcOnly 95 cdrom} {
    # cdrom can return either d:\ or D:/, but we only care about the errcode
    list [catch {testfile rmdir $cdrom/} msg] [lindex $msg 1]
} {1 EEXIST}
test winFCmd-7.9 {TraverseWinTree: append \ to source if necessary} {pcOnly nt cdrom} {
    list [catch {testfile rmdir $cdrom/} msg]  [lindex $msg 1]
} {1 EACCES}
test winFCmd-7.10 {TraverseWinTree: can't read directory: handle == INVALID} \
	{pcOnly} {
    # can't make it happen
} {}
test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testchmod 000 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} {1 1}
test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile rmdir -force td1
    file exists td1
} {0}
test winFCmd-7.13 {TraverseWinTree: append \ to target if necessary} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile cpdir td1 td2
    contents td2/tf1
} {tf1}    
test winFCmd-7.14 {TraverseWinTree: append \ to target if necessary} {pcOnly 95} {
    cleanup
    file mkdir td1
    list [catch {testfile cpdir td1 /} msg] $msg
} {1 {/ EEXIST}}
test winFCmd-7.15 {TraverseWinTree: append \ to target if necessary} {pcOnly nt} {
    cleanup
    file mkdir td1
    list [catch {testfile cpdir td1 /} msg] $msg
} {1 {/ EACCES}}
test winFCmd-7.16 {TraverseWinTree: recurse on files: no files} {pcOnly} {
    cleanup
    file mkdir td1
    testfile cpdir td1 td2
} {}
test winFCmd-7.17 {TraverseWinTree: recurse on files: one file} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/td2
    testfile cpdir td1 td2
    glob td2/*
} {td2/td2}
test winFCmd-7.18 {TraverseWinTree: recurse on files: several files and dir} \
	{pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1
    createfile td1/tf2
    file mkdir td1/td2/td3
    createfile td1/tf3
    createfile td1/tf4
    testfile cpdir td1 td2
    lsort [glob td2/*]
} {td2/td2 td2/tf1 td2/tf2 td2/tf3 td2/tf4}
test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testchmod 000 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} {1 1}
test winFCmd-7.20 {TraverseWinTree: call TraversalDelete: DOTREE_POSTD} \
	{pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1 tf1
    testfile rmdir -force td1
    file exists td1
} {0}
test winFCmd-7.21 {TraverseWinTree: fill errorPtr} {pcOnly} {
    cleanup
    list [catch {testfile cpdir td1 td2} msg] $msg
} {1 {td1 ENOENT}}

test winFCmd-8.1 {TraversalCopy: DOTREE_F} {pcOnly} {
    cleanup
    file mkdir td1
    list [catch {testfile cpdir td1 td1} msg] $msg
} {1 {td1 EEXIST}}
test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} {pcOnly} {
    cleanup
    file mkdir td1/td2
    testchmod 000 td1
    testfile cpdir td1 td2
    list [file writable td1] [file writable td1/td2]
} {0 1}
test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} {pcOnly} {
    cleanup
    file mkdir td1
    testfile cpdir td1 td2
} {}

test winFCmd-9.1 {TraversalDelete: DOTREE_F} {pcOnly} {
    cleanup
    file mkdir td1
    createfile td1/tf1
    testfile rmdir -force td1
} {}
test winFCmd-9.2 {TraversalDelete: DOTREE_F} {pcOnly 95} {
    cleanup
    file mkdir td1
    set fd [open td1/tf1 w]
    set msg [list [catch {testfile rmdir -force td1} msg] $msg]
    close $fd
    set msg
} {1 {td1\tf1 EACCES}}
test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} {pcOnly} {
    cleanup
    file mkdir td1/td2
    testchmod 000 td1
    testfile rmdir -force td1
    file exists td1
} {0}
test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} {pcOnly} {
    cleanup
    file mkdir td1/td1/td3/td4/td5
    testfile rmdir -force td1
} {}

test winFCmd-10.1 {AttributesPosixError - get} {pcOnly} {
    cleanup
    list [catch {file attributes td1 -archive} msg] $msg
} {1 {could not read "td1": no such file or directory}}
test winFCmd-10.2 {AttributesPosixError - set} {pcOnly} {
    cleanup
    list [catch {file attributes td1 -archive 0} msg] $msg
} {1 {could not read "td1": no such file or directory}}

test winFCmd-11.1 {GetWinFileAttributes} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -archive} msg] $msg [cleanup]
} {0 1 {}}
test winFCmd-11.2 {GetWinFileAttributes} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -readonly} msg] $msg [cleanup]
} {0 0 {}}
test winFCmd-11.3 {GetWinFileAttributes} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -hidden} msg] $msg [cleanup]
} {0 0 {}}
test winFCmd-11.4 {GetWinFileAttributes} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -system} msg] $msg [cleanup]
} {0 0 {}}
test winFCmd-11.5 {GetWinFileAttributes} {pcOnly} {
    # attr of relative paths that resolve to root was failing
    # don't care about answer, just that test runs.

    set old [pwd]
    cd c:/
    file attr c:	    
    file attr c:.
    file attr . 
    cd $old
} {}
test winFCmd-11.6 {GetWinFileAttributes} {pcOnly} {
    file attr c:/ -hidden
} {0}

test winFCmd-12.1 {ConvertFileNameFormat} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {string tolower [file attributes td1 -longname]} msg] $msg [cleanup]
} {0 td1 {}}
test winFCmd-12.2 {ConvertFileNameFormat} {pcOnly} {
    cleanup
    file mkdir td1
    close [open td1/td1 w]
    list [catch {string tolower [file attributes td1/td1 -longname]} msg] $msg [cleanup]
} {0 td1/td1 {}}
test winFCmd-12.3 {ConvertFileNameFormat} {pcOnly} {
    cleanup
    file mkdir td1
    file mkdir td1/td2
    close [open td1/td3 w]
    list [catch {string tolower [file attributes td1/td2/../td3 -longname]} msg] $msg [cleanup]
} {0 td1/td2/../td3 {}}
test winFCmd-12.4 {ConvertFileNameFormat} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {string tolower [file attributes ./td1 -longname]} msg] $msg [cleanup]
} {0 ./td1 {}}
test winFCmd-12.5 {ConvertFileNameFormat: absolute path} {pcOnly} {
    list [file attributes / -longname] [file attributes \\ -longname]
} {/ /}
test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} {pcOnly} {
    catch {file delete -force -- c:/td1}
    close [open c:/td1 w]
    list [catch {string tolower [file attributes c:/td1 -longname]} msg] $msg [file delete -force -- c:/td1]
} {0 c:/td1 {}}
test winFCmd-12.7 {ConvertFileNameFormat} {nonPortable pcOnly} {
    string tolower [file attributes //bisque/tcl/ws -longname]
} {//bisque/tcl/ws}
test winFCmd-12.8 {ConvertFileNameFormat} {pcOnly longFileNames} {
    cleanup
    close [open td1 w]
    list [catch {string tolower [file attributes td1 -longname]} msg] $msg [cleanup]
} {0 td1 {}}
test winFCmd-12.10 {ConvertFileNameFormat} {longFileNames pcOnly} {
    cleanup
    close [open td1td1td1 w]
    list [catch {file attributes td1td1td1 -shortname}] [cleanup]
} {0 {}}
test winFCmd-12.11 {ConvertFileNameFormat} {longFileNames pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {string tolower [file attributes td1 -shortname]} msg] $msg [cleanup]
} {0 td1 {}}

test winFCmd-13.1 {GetWinFileLongName} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {string tolower [file attributes td1 -longname]} msg] $msg [cleanup]
} {0 td1 {}}

test winFCmd-14.1 {GetWinFileShortName} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {string tolower [file attributes td1 -shortname]} msg] $msg [cleanup]
} {0 td1 {}}

test winFCmd-15.1 {SetWinFileAttributes} {pcOnly} {
    cleanup
    list [catch {file attributes td1 -archive 0} msg] $msg
} {1 {could not read "td1": no such file or directory}}
test winFCmd-15.2 {SetWinFileAttributes - archive} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -archive 1} msg] $msg [file attributes td1 -archive] [cleanup]
} {0 {} 1 {}}
test winFCmd-15.3 {SetWinFileAttributes - archive} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -archive 0} msg] $msg [file attributes td1 -archive] [cleanup]
} {0 {} 0 {}}
test winFCmd-15.4 {SetWinFileAttributes - hidden} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -hidden 1} msg] $msg [file attributes td1 -hidden] [file attributes td1 -hidden 0] [cleanup]
} {0 {} 1 {} {}}
test winFCmd-15.5 {SetWinFileAttributes - hidden} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -hidden 0} msg] $msg [file attributes td1 -hidden] [cleanup]
} {0 {} 0 {}}
test winFCmd-15.6 {SetWinFileAttributes - readonly} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -readonly 1} msg] $msg [file attributes td1 -readonly] [cleanup]
} {0 {} 1 {}}
test winFCmd-15.7 {SetWinFileAttributes - readonly} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -readonly 0} msg] $msg [file attributes td1 -readonly] [cleanup]
} {0 {} 0 {}}
test winFCmd-15.8 {SetWinFileAttributes - system} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -system 1} msg] $msg [file attributes td1 -system] [cleanup]
} {0 {} 1 {}}
test winFCmd-15.9 {SetWinFileAttributes - system} {pcOnly} {
    cleanup
    close [open td1 w]
    list [catch {file attributes td1 -system 0} msg] $msg [file attributes td1 -system] [cleanup]
} {0 {} 0 {}}
test winFCmd-15.10 {SetWinFileAttributes - failing} {pcOnly cdrom} {
    cleanup
    catch {file attributes $cdfile -archive 1}
} {1}
test winFCmd-16.1 {Windows file normalization} {pcOnly} {
    list [file normalize c:/] [file normalize C:/]
} {C:/ C:/}
test winFCmd-16.2 {Windows file normalization} {pcOnly} {
    close [open td1... w]
    set res [file tail [file normalize td1]]
    file delete td1...
    set res
} {td1}

set pwd [pwd]
set d [string index $pwd 0]

test winFCmd-16.3 {Windows file normalization} {pcOnly} {
    file norm ${d}:foo
} [file join $pwd foo]
test winFCmd-16.4 {Windows file normalization} {pcOnly} {
    file norm [string tolower ${d}]:foo
} [file join $pwd foo]
test winFCmd-16.5 {Windows file normalization} {pcOnly} {
    file norm ${d}:foo/bar
} [file join $pwd foo/bar]
test winFCmd-16.6 {Windows file normalization} {pcOnly} {
    file norm ${d}:foo\\bar
} [file join $pwd foo/bar]
test winFCmd-16.7 {Windows file normalization} {pcOnly} {
    file norm /bar
} "${d}:/bar"
test winFCmd-16.8 {Windows file normalization} {pcOnly} {
    file norm ///bar
} "${d}:/bar"
test winFCmd-16.9 {Windows file normalization} {pcOnly} {
    file norm /bar/foo
} "${d}:/bar/foo"
if {$d eq "C"} { set dd "D" } else { set dd "C" }
test winFCmd-16.10 {Windows file normalization} {pcOnly} {
    file norm ${dd}:foo
} "${dd}:/foo"
test winFCmd-16.11 {Windows file normalization} {pcOnly cdrom} {
    cd ${d}:
    cd $cdrom
    cd ${d}:
    cd $cdrom
    # Must not crash
    set result "no crash"
} {no crash}
test winFCmd-16.12 {Windows file normalization} {pcOnly} {
    set oldhome ""
    catch {set oldhome $::env(HOME)}
    set ::env(HOME) ${d}:
    cd
    set result [pwd]; # <- Must not crash
    set ::env(HOME) $oldhome
    set result
} ${d}:/

cd $pwd
unset d dd pwd

test winFCmd-18.1 {Windows reserved path names} -constraints win -body {
    file pathtype com1
} -result "absolute"

test winFCmd-18.1.2 {Windows reserved path names} -constraints win -body {
    file pathtype com4
} -result "absolute"

test winFCmd-18.1.3 {Windows reserved path names} -constraints win -body {
    file pathtype com5
} -result "relative"

test winFCmd-18.1.4 {Windows reserved path names} -constraints win -body {
    file pathtype lpt3
} -result "absolute"

test winFCmd-18.1.5 {Windows reserved path names} -constraints win -body {
    file pathtype lpt4
} -result "relative"

test winFCmd-18.1.6 {Windows reserved path names} -constraints win -body {
    file pathtype nul
} -result "absolute"

test winFCmd-18.1.7 {Windows reserved path names} -constraints win -body {
    file pathtype null
} -result "relative"

test winFCmd-18.2 {Windows reserved path names} -constraints win -body {
    file pathtype com1:
} -result "absolute"

test winFCmd-18.3 {Windows reserved path names} -constraints win -body {
    file pathtype COM1
} -result "absolute"

test winFCmd-18.4 {Windows reserved path names} -constraints win -body {
    file pathtype CoM1:
} -result "absolute"

test winFCmd-18.5 {Windows reserved path names} -constraints win -body {
    file normalize com1:
} -result COM1

test winFCmd-18.6 {Windows reserved path names} -constraints win -body {
    file normalize COM1:
} -result COM1

test winFCmd-18.7 {Windows reserved path names} -constraints win -body {
    file normalize cOm1
} -result COM1

test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
    file normalize cOm1:
} -result COM1

# This block of code used to occur after the "return" call, so I'm
# commenting it out and assuming that this code is still under construction.
#foreach source {tef ted tnf tnd "" nul com1} {
#    foreach chmodsrc {000 755} {
#        foreach dest "tfn tfe tdn tdempty tdfull td1/td2 $p $p/td1 {} nul" {
#	    foreach chmoddst {000 755} {
#		puts hi
#		cleanup
#		file delete -force ted tef
#		file mkdir ted
#		createfile tef
#		createfile tfe
#		file mkdir tdempty
#		file mkdir tdfull/td1/td2
#
#		catch {testchmod $chmodsrc $source}
#		catch {testchmod $chmoddst $dest}
#
#		if [catch {file rename $source $dest} msg] {
#		    puts "file rename $source ($chmodsrc) $dest ($chmoddst)"
#		    puts $msg
#		}
#	    }
#	}
#    }
#}

# cleanup
cleanup
::tcltest::cleanupTests
return
