This file is indexed.

/usr/share/tcltk/vfs1.3/tarvfs.tcl is in tcl-vfs 1.3-20080503-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
################################################################################
# This is the first try to provide access to tar-files via
# the vfs-mechanism.
# This file is copied and adapted from zipvfs.tcl
# (and ftpvfs.tcl). The internal structure for the tar-data is stored
# analog to zipvfs so that many functions can be the same as in zipvfs.
#
# Jan 13 2003: Stefan Vogel (stefan.vogel@avinci.de)
# (reformatted to tabsize 8 by Vince).
# 
# TODOs:
# * add writable access (should be easy with tar-files)
# * add gzip-support (?)
# * more testing :-(
################################################################################

package require vfs
package provide vfs::tar 0.9

# Using the vfs, memchan and Trf extensions, we're able
# to write a Tcl-only tar filesystem.  

namespace eval vfs::tar {}

proc vfs::tar::Mount {tarfile local} {
    set fd [::tar::open [::file normalize $tarfile]]
    vfs::filesystem mount $local [list ::vfs::tar::handler $fd]
    # Register command to unmount
    vfs::RegisterMount $local [list ::vfs::tar::Unmount $fd]
    return $fd
}

proc vfs::tar::Unmount {fd local} {
    vfs::filesystem unmount $local
    ::tar::_close $fd
}

proc vfs::tar::handler {tarfd cmd root relative actualpath args} {
    if {$cmd == "matchindirectory"} {
	# e.g. called from "glob *"
	eval [list $cmd $tarfd $relative $actualpath] $args
    } else {
	# called for all other commands: access, stat
	eval [list $cmd $tarfd $relative] $args
    }
}

proc vfs::tar::attributes {tarfd} { return [list "state"] }
proc vfs::tar::state {tarfd args} {
    vfs::attributeCantConfigure "state" "readonly" $args
}

# If we implement the commands below, we will have a perfect
# virtual file system for tar files.
# Completely copied from zipvfs.tcl

proc vfs::tar::matchindirectory {tarfd path actualpath pattern type} {
    # This call to tar::getdir handles empty patterns properly as asking
    # for the existence of a single file $path only
    set res [::tar::getdir $tarfd $path $pattern]
    if {![string length $pattern]} {
	if {![::tar::exists $tarfd $path]} { return {} }
	set res [list $actualpath]
	set actualpath ""
    }

    set newres [list]
    foreach p [::vfs::matchCorrectTypes $type $res $actualpath] {
	lappend newres [file join $actualpath $p]
    }
    return $newres
}

# return the necessary "array"
proc vfs::tar::stat {tarfd name} {
    ::tar::stat $tarfd $name sb
    array get sb
}

proc vfs::tar::access {tarfd name mode} {
    if {$mode & 2} {
	vfs::filesystem posixerror $::vfs::posix(EROFS)
    }
    # Readable, Exists and Executable are treated as 'exists'
    # Could we get more information from the archive?
    if {[::tar::exists $tarfd $name]} {
	return 1
    } else {
	error "No such file"
    }
    
}

proc vfs::tar::open {tarfd name mode permissions} {
    # return a list of two elements:
    # 1. first element is the Tcl channel name which has been opened
    # 2. second element (optional) is a command to evaluate when
    #    the channel is closed.

    switch -- $mode {
	"" -
	"r" {
	    if {![::tar::exists $tarfd $name]} {
		vfs::filesystem posixerror $::vfs::posix(ENOENT)
	    }
	    
	    ::tar::stat $tarfd $name sb
	    
	    set nfd [vfs::memchan]
	    set encoding [fconfigure $nfd -encoding]
	    set eofchar [fconfigure $nfd -eofchar]
	    set translation [fconfigure $nfd -translation]
	    fconfigure $nfd -translation binary
	    
	    # get the starting point from structure
	    seek $tarfd $sb(start) start
	    tar::Data $tarfd sb data
	    
	    puts -nonewline $nfd $data
	    
	    fconfigure $nfd -translation $translation -encoding $encoding -eofchar $eofchar
	    seek $nfd 0
	    return [list $nfd]
	}
	default {
	    vfs::filesystem posixerror $::vfs::posix(EROFS)
	}
    }
}

proc vfs::tar::createdirectory {tarfd name} {
    vfs::filesystem posixerror $::vfs::posix(EROFS)
    #error "tar-archives are read-only (not implemented)"
}

proc vfs::tar::removedirectory {tarfd name recursive} {
    #::vfs::log "removedirectory $name"
    vfs::filesystem posixerror $::vfs::posix(EROFS)
    #error "tar-archives are read-only (not implemented)"
}

proc vfs::tar::deletefile {tarfd name} {
    vfs::filesystem posixerror $::vfs::posix(EROFS)
    #error "tar-archives are read-only (not implemented)"
}

# don't care about platform-specific attributes
proc vfs::tar::fileattributes {tarfd name args} {
    #::vfs::log "fileattributes $args"
    switch -- [llength $args] {
	0 {
	    # list strings
	    return [list]
	}
	1 {
	    # get value
	    set index [lindex $args 0]
	    return ""
	}
	2 {
	    # set value
	    set index [lindex $args 0]
	    set val [lindex $args 1]
	    vfs::filesystem posixerror $::vfs::posix(EROFS)
	}
    }
}

# set the 'mtime' of a file.
proc vfs::tar::utime {fd path actime mtime} {
    vfs::filesystem posixerror $::vfs::posix(EROFS)
}

#
# tar decoder:
#
# Format of tar file:
# see http://www.gnu.org/manual/tar/html_node/tar_123.html
# "comments" are put into the the arrays for readability
# the fields in aPosixHeader are stored inside a
# 512-byte-block. Not all header-fields are used here.
#
# Here are some excerpts from the above resource for information
# only:
#
# name, linkname, magic, uname, and gname are null-terminated strings.
# All other fileds are zero-filled octal numbers in ASCII.
# Each numeric field of width w contains
#   w minus 2 digits, a space, and a null,
#   except size, and mtime, which do not contain the trailing null

# mtime field is the modification time of the file at the time it was
# archived. It is the ASCII representation of the octal value of the
# last time the file was modified, represented as an integer number
# of seconds since January 1, 1970, 00:00 Coordinated Universal Time


namespace eval tar {
    
    set HEADER_SIZE 500
    set BLOCK_SIZE 512
    
    # fields of header with start/end-index in "comments": length of
    # field in bytes (just for documentation) prefix is the
    # "datatype": s == null-terminated string o == zero-filled octal
    # number (numeric but leave it octal e.g mode) n == numeric -->
    # integer change to decimal) "not used" is marked when the field
    # is not needed anywhere here
    array set aPosixHeader {
	name      {s 0    99}     # 100
	mode      {o 100 107}     # "8   - not used now"
	uid       {n 108 115}     # 8
	gid       {n 116 123}     # 8
	size      {n 124 135}     # 12
	mtime     {n 136 147}     # 12
	chksum    {o 148 155}     # "8   - not used"
	typeflag  {o 156 156}     # 1
	linkname  {s 157 256}     # "100 - not used"
	magic     {s 257 262}     # "6   - not used"
	version   {o 263 264}     # "2   - not used"
	uname     {s 265 296}     # "32  - not used"
	gname     {s 297 328}     # "32  - not used"
	devmajor  {o 329 336}     # "8   - not used"
	devminor  {o 337 344}     # "8   - not used"
	prefix    {o 345 499}     # "155 - not used"
    }
    
    # just for compatibility with posix-header
    # only DIRTYPE is used
    array set aTypeFlag {
	REGTYPE  0            # "regular file"
	AREGTYPE \000         # "regular file"
	LNKTYPE  1            # link
	SYMTYPE  2            # reserved
	CHRTYPE  3            # "character special"
	BLKTYPE  4            # "block special"
	DIRTYPE  5            # directory
	FIFOTYPE 6            # "FIFO special"
	CONTTYPE 7            # reserved
    }
}

proc tar::Data {fd arr {varPtr ""}} {
    upvar 1 $arr sb

    if { $varPtr != "" } {
	upvar 1 $varPtr data
    }

    if { $varPtr == "" } {
	seek $fd $sb(size) current
    } else {
	set data [read $fd $sb(size)]
    }

    if { $varPtr == "" } {
	return ""
    }
}

proc tar::TOC {fd arr toc} {
    variable aPosixHeader
    variable aTypeFlag
    variable HEADER_SIZE
    variable BLOCK_SIZE
    
    upvar 1 $arr sb
    upvar 1 $toc _toc
    
    set pos 0
    set sb(nitems) 0
    
    # loop through file in blocks of BLOCK_SIZE
    while {![eof $fd]} {
	seek $fd $pos
	set hdr [read $fd $BLOCK_SIZE]
	
	# read header-fields from block (see aPosixHeader)
	foreach key {name typeflag size mtime uid gid} {
	    set type [lindex $aPosixHeader($key) 0]
	    set positions [lrange $aPosixHeader($key) 1 2]
	    switch $type {
		s {
		    set $key [eval string range [list $hdr] $positions]
		    # cut the trailing Nulls
		    set $key [string range [set $key] 0 [expr [string first "\000" [set $key]]-1]]
		}
		o {
		    # leave it as is (octal value)
		    set $key [eval string range [list $hdr] $positions]
		}
		n {
		    set $key [eval string range [list $hdr] $positions]
		    # change to integer
		    scan [set $key] "%o" $key
		    # if not set, set default-value "0"
		    # (size == "" is not a very good value)
		    if {![string is integer [set $key]] || [set $key] == ""} { set $key 0 }
		}
		default {
		    error "tar::TOC: '$fd' wrong type for header-field: '$type'"
		}
	    }
	}
	
	# only the last three octals are interesting for mode
	# ignore mode now, should this be added??
	# set mode 0[string range $mode end-3 end]
	
	# get the increment to the next valid block
	# (ignore file-blocks in between)
	# if size == 0 the minimum incr is 512
	set incr [expr int(ceil($size/double($BLOCK_SIZE)))*$BLOCK_SIZE+$BLOCK_SIZE]
	
	set startPosition [expr $pos+$BLOCK_SIZE]
	# make it relative to this working-directory, remove the
	# leading "relative"-paths
	regexp -- {^(?:\.\.?/)*/?(.*)} $name -> name
	
	if {$name != ""} {
	    incr sb(nitems)
	    set sb($name,start) [expr $pos+$BLOCK_SIZE]
	    set sb($name,size) $size
	    set type "file"
	    # the mode should be 0777?? or must be changed to decimal?
	    if {$typeflag == $aTypeFlag(DIRTYPE)} {
		# directory! append this without /
		# leave mode: 0777
		# (else we might not be able to walk through archive)
		set type "directory"
		lappend _toc([string trimright $name "/"]) \
		  name [string trimright $name "/"] \
		  type $type mtime $mtime size $size mode 0777 \
		  ino -1 start $startPosition \
		  depth [llength [file split $name]] \
		  uid $uid gid $gid
	    }
	    lappend _toc($name) \
	      name $name \
	      type $type mtime $mtime size $size mode 0777 \
	      ino -1 start $startPosition depth [llength [file split $name]] \
	      uid $uid gid $gid
	}
	incr pos $incr
    }
    return
}

proc tar::open {path} {
    set fd [::open $path]
    
    if {[catch {
	upvar #0 tar::$fd.toc toc
	
	fconfigure $fd -translation binary ;#-buffering none
	
	tar::TOC $fd sb toc
    } err]} {
	close $fd
	return -code error $err
    }
    
    return $fd
}

proc tar::exists {fd path} {
    #::vfs::log "$fd $path"
    if {$path == ""} {
	return 1
    } else {
	upvar #0 tar::$fd.toc toc
	return [expr [info exists toc($path)] || [info exists toc([string trimright $path "/"]/)]]
    }
}

proc tar::stat {fd path arr} {
    upvar #0 tar::$fd.toc toc
    upvar 1 $arr sb

    if { $path == "" || $path == "." } {
	array set sb {
	    type directory mtime 0 size 0 mode 0777 
	    ino -1 depth 0 name ""
	}
    } elseif {![info exists toc($path)] } {
	return -code error "could not read \"$path\": no such file or directory"
    } else {
	array set sb $toc($path)
    }

	# set missing attributes
    set sb(dev) -1
    set sb(nlink) 1
    set sb(atime) $sb(mtime)
    set sb(ctime) $sb(mtime)

    return ""
}

# Treats empty pattern as asking for a particular file only.
# Directly copied from zipvfs.
proc tar::getdir {fd path {pat *}} {
    upvar #0 tar::$fd.toc toc
    
    if { $path == "." || $path == "" } {
	set path $pat
    } else {
	set path [string tolower $path]
	if {$pat != ""} {
	    append path /$pat
	}
    }
    set depth [llength [file split $path]]
    
    if {$depth} {
	set ret {}
	foreach key [array names toc $path] {
	    if {[string index $key end] == "/"} {
		# Directories are listed twice: both with and without
		# the trailing '/', so we ignore the one with
		continue
	    }
	    array set sb $toc($key)
	    
	    if { $sb(depth) == $depth } {
		if {[info exists toc(${key}/)]} {
		    array set sb $toc(${key}/)
		}
		# remove sb(name) (because == $key)
		lappend ret [file tail $key]
	    }
	    unset sb
	}
	return $ret
    } else {
	# just the 'root' of the zip archive.  This obviously exists and
	# is a directory.
	return [list {}]
    }
}

proc tar::_close {fd} {
    variable $fd.toc
    unset -nocomplain $fd.toc
    ::close $fd
}