Tcl Library Source Code

Changes On Branch tkt-9f4c0e3e95-ak
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch tkt-9f4c0e3e95-ak Excluding Merge-Ins

This is equivalent to a diff from e1f5469305 to 5438cefd17

2017-05-29
18:36
Merged fix for tar::get (Ticket 9f4c0e3e95). check-in: 21cf0660cc user: aku tags: trunk
18:34
Fixed issue. Further modified tar::get to throw an error when not finding the requeste file. Updated docs and tests to match. Bumped version to 0.11. Closed-Leaf check-in: 5438cefd17 user: aku tags: tkt-9f4c0e3e95-ak
18:05
Converted example into testcases. Issue confirmed. check-in: d5f927261b user: aku tags: tkt-9f4c0e3e95-ak
17:17
Merged last bit from ticket branch. Final. check-in: e1f5469305 user: aku tags: trunk
17:16
Added another test to validate the the Critcl implementation is truly ok. Closed-Leaf check-in: 1a871993e4 user: aku tags: tkt-39ab616d8f-ak
17:05
Merged fix for ticket 39ab616d8f (struct::graph dfs pre walk multi-entry issue) check-in: 89bf85ed39 user: aku tags: trunk

Changes to modules/tar/pkgIndex.tcl.

1
2
3
4
5

1
2
3
4

5




-
+
if {![package vsatisfies [package provide Tcl] 8.4]} {
    # PRAGMA: returnok
    return
}
package ifneeded tar 0.10 [list source [file join $dir tar.tcl]]
package ifneeded tar 0.11 [list source [file join $dir tar.tcl]]

Changes to modules/tar/tar.man.

1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







[vset PACKAGE_VERSION 0.10]
[vset PACKAGE_VERSION 0.11]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tar n [vset PACKAGE_VERSION]]
[keywords archive]
[keywords {tape archive}]
[keywords tar]
[moddesc   {Tar file handling}]
[titledesc {Tar file creation, extraction & manipulation}]
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
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







-
+
-

-
+





-
-
-
-
+
+
+
+
+
+
+







% foreach {file size} [::tar::untar tarball.tar -glob *.jpg] {
puts "Extracted $file ($size bytes)"
}
}]

[call [cmd ::tar::get] [arg tarball] [arg fileName] [opt [option -chan]]]

Returns the contents of [arg fileName] from the [arg tarball]
Returns the contents of [arg fileName] from the [arg tarball].
[para]

[example {
[para][example {
% set readme [::tar::get tarball.tar doc/README] {
% puts $readme
}
}]

[para]
If the option [option -chan] is present [arg tarball] is interpreted as an open channel.
It is assumed that the channel was opened for reading, and configured for binary input.
The command will [emph not] close the channel.
[para] If the option [option -chan] is present [arg tarball] is
interpreted as an open channel.  It is assumed that the channel was
opened for reading, and configured for binary input.  The command will
[emph not] close the channel.

[para] An error is thrown when [arg fileName] is not found in the tar
archive.

[call [cmd ::tar::create] [arg tarball] [arg files] [arg args]]

Creates a new tar file containing the [arg files]. [arg files] must be specified
as a single argument which is a proper list of filenames.

[list_begin options]

Changes to modules/tar/tar.tcl.

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
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







-
+











-
+
+
+
+







#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: tar.tcl,v 1.17 2012/09/11 17:22:24 andreas_kupries Exp $

package require Tcl 8.4
package provide tar 0.10
package provide tar 0.11

namespace eval ::tar {}

proc ::tar::parseOpts {acc opts} {
    array set flags $acc
    foreach {x y} $acc {upvar $x $x}
    
    set len [llength $opts]
    set i 0
    while {$i < $len} {
        set name [string trimleft [lindex $opts $i] -]
        if {![info exists flags($name)]} {return -code error "unknown option \"$name\""}
        if {![info exists flags($name)]} {
	    return -errorcode {TAR INVALID OPTION} \
		-code error "unknown option \"$name\""
	}
        if {$flags($name) == 1} {
            set $name [lindex $opts [expr {$i + 1}]]
            incr i $flags($name)
        } elseif {$flags($name) > 1} {
            set $name [lrange $opts [expr {$i + 1}] [expr {$i + $flags($name)}]]
            incr i $flags($name)
        } else {
43
44
45
46
47
48
49

50

51
52
53
54
55
56
57
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61







+
-
+







    if {$pad == 512} {return 0}
    return $pad
}

proc ::tar::seekorskip {ch off wh} {
    if {[tell $ch] < 0} {
	if {$wh!="current"} {
	    return -code error -errorcode [LIST TAR INVALID WHENCE $wh] \
	    error "WHENCE=$wh not supported on non-seekable channel $ch"
		"WHENCE=$wh not supported on non-seekable channel $ch"
	}
	skip $ch $off
	return
    }
    seek $ch $off $wh
    return
}
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
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







-
-
+
+

-
+











-
+
+







	set fh [::open $tar]
	fconfigure $fh -encoding binary -translation lf -eofchar {}
    }
    while {![eof $fh]} {
	set data [read $fh 512]
        array set header [readHeader $data]
	HandleLongLink $fh header
        if {$header(name) == ""} break
	if {$header(prefix) != ""} {append header(prefix) /}
        if {$header(name) eq ""} break
	if {$header(prefix) ne ""} {append header(prefix) /}
        set name [string trimleft $header(prefix)$header(name) /]
        if {$name == $file} {
        if {$name eq $file} {
            set file [read $fh $header(size)]
            if {!$chan} {
		close $fh
	    }
            return $file
        }
        seekorskip $fh [expr {$header(size) + [pad $header(size)]}] current
    }
    if {!$chan} {
	close $fh
    }
    return {}
    return -code error -errorcode {TAR MISSING FILE} \
	"Tar \"$tar\": File \"$file\" not found"
}

proc ::tar::untar {tar args} {
    set nooverwrite 0
    set data 0
    set nomtime 0
    set noperms 0
375
376
377
378
379
380
381

382

383
384
385

386

387
388
389
390
391
392
393
380
381
382
383
384
385
386
387

388
389
390
391
392

393
394
395
396
397
398
399
400







+
-
+



+
-
+







    set osize  [format %o $A(size)]
    set ogid   [format %o $A(gid)]
    set ouid   [format %o $A(uid)]
    set omtime [format %o $A(mtime)]
    
    set name [string trimleft $name /]
    if {[string length $name] > 255} {
        return -code error -errorcode {TAR BAD PATH LENGTH} \
        return -code error "path name over 255 chars"
	    "path name over 255 chars"
    } elseif {[string length $name] > 100} {
	set common [string range $name end-99 154]
	if {[set splitpoint [string first / $common]] == -1} {
	    return -code error -errorcode {TAR BAD PATH UNSPLITTABLE} \
	    return -code error "path name cannot be split into prefix and name"
		"path name cannot be split into prefix and name"
	}
	set prefix [string range $name 0 end-100][string range $common 0 $splitpoint-1]
	set name   [string range $common $splitpoint+1 end][string range $name 155 end]
    } else {
        set prefix ""
    }

Changes to modules/tar/tar.test.

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
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







-
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



    seek $chan1 0
    lappend res [string trim [tar::get $chan1 $tmpdir/one/two/a -chan]]
} -cleanup {
    cleanup1
} -result {tartest/one/a tartest/one/two/a tartest/one/three/a hello2}


test tar-bug-2840180 {} -setup {
test tar-bug-2840180 {Ticket 2840180} -setup {
    setup2
} -body {
    tar::create $chan1 [list $tmpdir/[large-path]/a] -chan
    seek $chan1 0

    # What the package sees.
    lappend res {*}[tar::contents $chan1 -chan]
    close $chan1

    # What a regular tar package sees.
    lappend res [exec 2> $tmpfile.err tar tvf $tmpfile]
    join $res \n
} -cleanup {
    cleanup2
} -match glob -result [join [list \
				 tartest/[large-path]/a \
				 "* tartest/[large-path]/a" \
				] \n]

# -------------------------------------------------------------------------

test tar-tkt-9f4c0e3e95-1.0 {Ticket 9f4c0e3e95, A} -setup {
    set tarfile [setup-tkt-9f4c0e3e95]
} -body {
    string trim [tar::get $tarfile 02]
} -cleanup {
    cleanup-tkt-9f4c0e3e95
    unset tarfile
} -result {zero-two}

test tar-tkt-9f4c0e3e95-1.1 {Ticket 9f4c0e3e95, B, } -setup {
    set tarfile [setup-tkt-9f4c0e3e95]
} -body {
    tar::get $tarfile 0b10
} -cleanup {
    cleanup-tkt-9f4c0e3e95
    unset tarfile
} -returnCodes error -result {Tar "tartest/t.tar": File "0b10" not found}

# -------------------------------------------------------------------------
testsuiteCleanup

Changes to modules/tar/tests/support.tcl.

120
121
122
123
124
125
126























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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
	    uid 15103
	    gid 19103
	    size 100
	    mtime 5706776103
	}
    }
}

proc setup-tkt-9f4c0e3e95 {} {
    variable tmpdir tartest

    tcltest::makeDirectory $tmpdir
    tcltest::makeFile {zero-two}   $tmpdir/02
    tcltest::makeFile {number two} $tmpdir/2

    set here [pwd]
    cd $tmpdir
    tar::create t.tar {2 02}
    cd $here

    return $tmpdir/t.tar
}

proc cleanup-tkt-9f4c0e3e95 {} {
    variable tmpdir
    tcltest::removeFile      $tmpdir/2
    tcltest::removeFile      $tmpdir/02
    tcltest::removeDirectory $tmpdir
    return
}