Friday, 16 April 2010

Howto tcl copy file and check for error

# is there a better way to check if file copy worked or not in tcl?
proc fileCopy {sFrom sTo} {
    set bUpdateFile 0
    if {[catch {file stat "$sFrom" aFromStat} r]} {
        FAIL "no 'from' file? $sFrom $::errorCode $::errorInfo"
    if {[catch {file stat "$sTo" aToStat} r]} {
        # no to file to compare with, do update
        set bUpdateFile 1
    if {! $bUpdateFile} {
        # compare file stat info: mtime and size
        #log "stat from=[parray aFromStat] to=[parray aToStat] "
        if {$aFromStat(mtime) != $aToStat(mtime) || $aFromStat(size) != $aToStat(size)} {
            set bUpdateFile 1
            log "stat mtime from=$aFromStat(mtime) to=$aToStat(mtime)"
            log "stat size  from=$aFromStat(size)  to=$aToStat(size)"
        } else {
            log "no update needed. stat from=[parray aFromStat {mtime,size}] to=[parray aToStat {mtime,size}]"
            # did nothing
            PASS "update not needed to:$sTo"
    if {$bUpdateFile} {
        log "file copy -force $sFrom $sTo"
        if {[catch {file copy -force "$sFrom" "$sTo"} sError]} {
            FAIL "file copy failed: err:$sError to:$sTo"
        # check for fail (mutters silly tcl manual!? how check success of file copy?)
        if {[catch {file stat "$sTo" aNewToStat} r]} {
            FAIL "cannot check file stat for copied file? to:$sTo"
        } else {
            if {$aFromStat(mtime) == $aNewToStat(mtime) && $aFromStat(size) == $aNewToStat(size)} {
                PASS "update done to:$sTo"
            } else {
                FAIL "update fstat doesn't match to:$sTo"
                parray aFromStat
                parray aNewToStat

proc log {s} {
    puts "$s"

proc PASS {s} {
    log "PASS: $s"

proc FAIL {s} {
    log "FAIL: $s"

exec touch a.txt
fileCopy a.txt b.txt
exec rm -f ne.txt
fileCopy ne.txt b.txt

## OH! you must catch calls to file copy!
fileCopy a.txt notexistdir/fu/b.txt
fileCopy a.txt "K:/notexistdir/fu/b.txt"

log "test finish"


$ tclsh Tests/OLC/fileCopy.tcl
stat mtime from=1271431590 to=1271431430
stat size  from=0  to=0
file copy -force a.txt b.txt
PASS: update done to:b.txt
FAIL: no 'from' file? ne.txt POSIX ENOENT {no such file or directory} could not read "ne.txt": no such file or directory
    while executing
"file stat "$sFrom" aFromStat"
file copy -force a.txt notexistdir/fu/b.txt
FAIL: file copy failed: err:error copying "a.txt" to "notexistdir/fu/b.txt": no such file or directory to:notexistdir/fu/b.txt
FAIL: cannot check file stat for copied file? to:notexistdir/fu/b.txt
file copy -force a.txt K:/notexistdir/fu/b.txt
FAIL: file copy failed: err:error copying "a.txt" to "K:/notexistdir/fu/b.txt": no such file or directory to:K:/notexistdir/fu/b.txt
FAIL: cannot check file stat for copied file? to:K:/notexistdir/fu/b.txt
test finish

HELP! How to get tcl expect session to not wrap lines at 80 columns?

Is it possible to get Windows + tcl + tcl expect session to not wrap lines at 80 columns?
I've spent a couple of days over past few months blipping into try and investigate and solve this but for a simple/stupid thing it's proving troublesome.

Somewhere in a tcl + tcl expect function which telnet's into qnx hardware cards or VMs:

    # I had a big argument trying to get tcl+expect to set it's session to not t
    # runcate columns at 80 chars (which causes various annoying parsing difficu
    # lties). No matter what teminal tcl script was invoked from or what termina
    # l environment/settings were used the expect session negotiated at telnet p
    # rotocol level a terminal with 80 chars width. Also could not solve problem
    # with sttying and setting terminal environment on qnx after login.
    # If anyone can solve this please send info.

Wrapping at 80 chars is very annoying isn't it! But more annoying for trying to parse command-line interaction in a reliable way. Surely this has been solved by someone before? But after googling and grepping web it appears it might not have been ever solved + published on teh hinternet (in keeping with the tcl philosophy of hack it and get it working messily and move on).

    # Wherever tcl is invoked from terminal then settings are passed through int
    # o tcl process (environment set, terminal escapes, stty), and THESE are pas
    # sed into telnet process invoked by tcl. BUT tcl + expect + telnet windows
    # telnet sends NegotiateWindowSize 80x25 no matter what else is done.
    # If a telnet session running in windows terminal or putty has window resize
    # then telnet option messages are sent again. For now I can't find how to te
    # ll that telnet session to set column width. Setting stty rows/cols or send
    # ing ansi escape sequences doesn't seem to have an effect.

I have some wireshark logs with the telnet negotiation packets captured. I suppose we also have tcl expect source code ... but it is the telnet invoked which queries the environment it has and decides column setting to use.   

    # This causes Invalid telnet packet sent:
    # sent telnetSuboptionBegin Negotiate about window size
    # width \x02\x00 height \x00\x35
    #olc::sendCli "\xff\xfa\x1f\x02\x00\x00\x35\xff\xf0"

stty-ing (or changing terminal program used) before tcl called or inside tcl before expect session started or sending ansi/other ESC sequences didn't work for me.

    # stty rows 52 columns 512 < $spawn_out(slave,name)
    # log::logarray expect_out
    # log::logarray spawn_out
    #LOG: log::logarray:spawn_out(slave,name) = ExpectInjector_pid8148
    #?×?×?×8L?×ÐÝ: redirection not supported on Windows NT
    #(ù8ùHùàmXùhùÀn: redirection not supported on Windows NT

Tried lots of different things but need to collect information on what works and how it works:

[Windows application] - [tclsh - [tcl expect - [spawn telnet]]] - [QNX VM or hardware]

Try Windows application =
 cygwin rxvt
 windows shell
 eclipse (running tcl with DLTK plugin)

Try outside tcl telnet in from each application, then  each of these:
 * resizing window possible? + results in line wrapping? Negotiated at telnet level?
 * stty settings before telnet
 * stty settings on qnx after telnet in
 * control using ansi ESC codes: disable line wrap OR set terminal width (OR other settings)

Try inside tcl invoked from each application and try each of the above and add:
 * in tcl set stty things
 * in tcl set environment things
 * in tcl expect set things

Last thing: try all of the above from a linux machine with equivalent linux applications (terminal tool, xterm, eclipse).

Too many variants affect the problem!
It comes down to what qnx's bash does with it's output SO would be good if we could start there.
So ansi ESC codes / environment settings?