View Ticket
Ticket UUID: 0990f53b1a77cacafccaf440d277edeae0cab70a
Title: PNG files in Metakit4 VFSes fail to be read correctly
Status: Closed Type: Code Defect
Severity: Severe Priority: Immediate
Subsystem: Mk4tcl Resolution: Fixed
Last Modified: 2010-10-16 21:29:57
Version Found In: 0.5.2
Reported by JDC:

PNG files read from an mk4vfs can fail to be read.  Likely an issue in vfs::zstreamed in tclvfs.

It happens on non-KitCreator Tclkits too.

<hr /><i>rkeene added on 2010-10-13 15:29:31:</i><br />
    Create mk4vfs
      <li><tt>$ mkdir x.vfs</tt></li>
      <li><tt>$ cp cross.png x.vfs/</tt></li>
      <li><tt>$ ./tclkit-8.5.9-linux-i686 sdx.kit wrap x</tt></li>
      <li><tt>1 updates applied</tt></li>
    Test reading "cross.png" from the mk4vfs
      <li><tt>% vfs::mk4::Mount x x</tt></li>
      <li><tt>% cd x</tt></li>
      <li><tt>% glob *</tt></li>
      <li><tt>% set fd <nowiki>[open cross.png]</nowiki></tt></li>
      <li><tt>% fconfigure $fd -translation binary</tt></li>
      <li><tt>% set data <nowiki>[read $fd]</nowiki>; puts <nowiki>[string length $data]</nowiki></tt></li>
      <li><tt>% binary scan $data H* data_hex</tt></li>
      <li><tt>% puts $data_hex</tt></li>

<hr /><i>rkeene added on 2010-10-13 15:42:47:</i><br />
It works in the trivial case posted previously, but fails with the following kit:

In the kit:
% set fd [open cross.png]
% fconfigure $fd -encoding binary
% set data [read $fd]; puts [string length $data]
% file stat cross.png x
% parray x
x(atime)   = 1285147347
x(blksize) = 135312827
x(blocks)  = 583863729869319636
x(ctime)   = 1285147347
x(dev)     = -143965300
x(gid)     = 0
x(ino)     = 0
x(mode)    = 33279
x(mtime)   = 1285147347
x(nlink)   = 1
x(size)    = 655
x(type)    = file
x(uid)     = 0

<hr /><i>rkeene added on 2010-10-13 15:45:53:</i><br />
Still not sure where this is failing.

% mk::loop x db.dirs!90.files { puts "$x, [mk::get $x name]" }
db.dirs!90.files!0, cross.png
db.dirs!90.files!1, tick.png
db.dirs!90.files!2, tclp.gif
% mk::view info db.dirs!90.files  
name size:I date:I contents:B
% mk::get db.dirs!90.files!0 size
% string length [mk::get db.dirs!90.files!0 contents]
% mk::get db.dirs!90.files!0 -size contents

<hr /><i>rkeene added on 2010-10-13 15:52:42:</i><br />
Oh, wait I did "-encoding binary" in my second test where it should have been "-translation binary".

Using "-translation binary" causes it to be read correctly.

% set fd [open cross.png r]
% fconfigure $fd -translation binary         
% set data [read $fd]; puts [string length $data]
% binary scan $data H* data_hex

<hr /><i>rkeene added on 2010-10-16 21:12:41:</i><br />
The issue only occurs when using <nowiki>[fcopy]</nowiki> and mk4vfs channels without direct mode.

Simple test:
vfs::mk4::Mount /TEST
set fd [open /TEST/cross.png]
fconfigure $fd -translation binary
set out [open /dev/null w]
set ::fcopy_complete 0
proc fcopy_complete {args} { set ::fcopy_complete 1 }
fcopy $fd $out -command fcopy_complete
after 3000
puts "FCOPY: $fcopy_complete"

<hr /><i>rkeene added on 2010-10-16 21:14:10:</i><br />
P. Thoyts came up with a patch for this:

<hr /><i>rkeene added on 2010-10-16 21:15:12:</i><br />
Patch from P. Thoyts fixes the problem, but the test case segfaults on exit.

Backtrace follows:
(gdb) bt
#0  0x08075599 in Tcl_GetAssocData ()
#1  0x0804d67a in mkClose (instanceData=0x8170380, interp=0x0) at ../tcl/mk4tcl.cpp:326
#2  0x080b86de in TclFinalizeIOSubsystem ()
#3  0x0809d004 in Tcl_FinalizeThread ()
#4  0x0809d160 in Tcl_Finalize ()
#5  0x0809d518 in Tcl_Exit ()
#6  0x08080274 in Tcl_ExitObjCmd ()
#7  0x08077903 in TclEvalObjvInternal ()
#8  0x0807857d in Tcl_EvalEx ()
#9  0x080bf7d7 in Tcl_FSEvalFile ()
#10 0x080c2d52 in Tcl_Main ()
#11 0x0804c2aa in main (argc=135724192, argv=0x2004) at main.c:11

<hr /><i>rkeene added on 2010-10-16 21:29:57:</i><br />
Fixed in [ae7d9fc61b].