0000: 23 21 20 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 #! /usr/bin/env
0010: 74 63 6c 73 68 0a 0a 70 61 63 6b 61 67 65 20 72 tclsh..package r
0020: 65 71 75 69 72 65 20 68 74 74 70 20 32 2e 37 0a equire http 2.7.
0030: 70 61 63 6b 61 67 65 20 72 65 71 75 69 72 65 20 package require
0040: 73 71 6c 69 74 65 33 0a 70 61 63 6b 61 67 65 20 sqlite3.package
0050: 72 65 71 75 69 72 65 20 73 68 61 31 0a 70 61 63 require sha1.pac
0060: 6b 61 67 65 20 72 65 71 75 69 72 65 20 61 70 70 kage require app
0070: 66 73 64 0a 70 61 63 6b 61 67 65 20 72 65 71 75 fsd.package requ
0080: 69 72 65 20 70 6c 61 74 66 6f 72 6d 0a 70 61 63 ire platform.pac
0090: 6b 61 67 65 20 72 65 71 75 69 72 65 20 70 6b 69 kage require pki
00a0: 0a 0a 23 20 46 75 6e 63 74 69 6f 6e 73 20 73 70 ..# Functions sp
00b0: 65 63 69 66 69 63 61 6c 6c 79 20 6d 65 61 6e 74 ecifically meant
00c0: 20 66 6f 72 20 75 73 65 72 73 20 74 6f 20 72 65 for users to re
00d0: 70 6c 61 63 65 20 61 73 20 61 20 70 61 72 74 20 place as a part
00e0: 6f 66 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e of configuration
00f0: 0a 6e 61 6d 65 73 70 61 63 65 20 65 76 61 6c 20 .namespace eval
0100: 3a 3a 61 70 70 66 73 3a 3a 75 73 65 72 20 7b 0a ::appfs::user {.
0110: 09 23 20 55 73 65 72 2d 72 65 70 6c 61 63 61 62 .# User-replacab
0120: 6c 65 20 66 75 6e 63 74 69 6f 6e 20 74 6f 20 63 le function to c
0130: 6f 6e 76 65 72 74 20 61 20 68 6f 73 74 6e 61 6d onvert a hostnam
0140: 65 2f 68 61 73 68 2f 6d 65 74 68 6f 64 20 74 6f e/hash/method to
0150: 20 61 6e 20 55 52 4c 0a 09 70 72 6f 63 20 63 6f an URL..proc co
0160: 6e 73 74 72 75 63 74 5f 75 72 6c 20 7b 68 6f 73 nstruct_url {hos
0170: 74 6e 61 6d 65 20 68 61 73 68 20 6d 65 74 68 6f tname hash metho
0180: 64 7d 20 7b 0a 09 09 72 65 74 75 72 6e 20 22 68 d} {...return "h
0190: 74 74 70 3a 2f 2f 24 68 6f 73 74 6e 61 6d 65 2f ttp://$hostname/
01a0: 61 70 70 66 73 2f 24 6d 65 74 68 6f 64 2f 24 68 appfs/$method/$h
01b0: 61 73 68 22 0a 09 7d 0a 0a 09 23 20 55 73 65 72 ash"..}...# User
01c0: 2d 72 65 70 6c 61 63 65 61 62 6c 65 20 66 75 6e -replaceable fun
01d0: 63 74 69 6f 6e 20 67 65 74 20 74 68 65 20 68 6f ction get the ho
01e0: 6d 65 20 64 69 72 65 63 74 6f 72 79 20 6f 66 20 me directory of
01f0: 74 68 65 20 63 75 72 72 65 6e 74 20 75 73 65 72 the current user
0200: 0a 09 70 72 6f 63 20 67 65 74 5f 68 6f 6d 65 64 ..proc get_homed
0210: 69 72 20 7b 7d 20 7b 0a 09 09 72 65 74 75 72 6e ir {} {...return
0220: 20 5b 3a 3a 61 70 70 66 73 64 3a 3a 67 65 74 5f [::appfsd::get_
0230: 68 6f 6d 65 64 69 72 5d 0a 09 7d 0a 7d 0a 0a 6e homedir]..}.}..n
0240: 61 6d 65 73 70 61 63 65 20 65 76 61 6c 20 3a 3a amespace eval ::
0250: 61 70 70 66 73 20 7b 0a 09 76 61 72 69 61 62 6c appfs {..variabl
0260: 65 20 63 61 63 68 65 64 69 72 20 22 2f 74 6d 70 e cachedir "/tmp
0270: 2f 61 70 70 66 73 2d 63 61 63 68 65 22 0a 09 76 /appfs-cache"..v
0280: 61 72 69 61 62 6c 65 20 74 74 6c 20 33 36 30 30 ariable ttl 3600
0290: 0a 09 76 61 72 69 61 62 6c 65 20 6e 74 74 6c 20 ..variable nttl
02a0: 36 30 0a 09 76 61 72 69 61 62 6c 65 20 74 72 75 60..variable tru
02b0: 73 74 65 64 5f 63 61 73 20 5b 6c 69 73 74 5d 0a sted_cas [list].
02c0: 0a 09 70 72 6f 63 20 5f 68 61 73 68 5f 73 65 70 ..proc _hash_sep
02d0: 20 7b 68 61 73 68 20 7b 73 65 70 73 20 34 7d 7d {hash {seps 4}}
02e0: 20 7b 0a 09 09 66 6f 72 20 7b 73 65 74 20 69 64 {...for {set id
02f0: 78 20 30 7d 20 7b 24 69 64 78 20 3c 20 24 73 65 x 0} {$idx < $se
0300: 70 73 7d 20 7b 69 6e 63 72 20 69 64 78 7d 20 7b ps} {incr idx} {
0310: 0a 09 09 09 61 70 70 65 6e 64 20 72 65 74 76 61 ....append retva
0320: 6c 20 22 5b 73 74 72 69 6e 67 20 72 61 6e 67 65 l "[string range
0330: 20 24 68 61 73 68 20 5b 65 78 70 72 20 7b 24 69 $hash [expr {$i
0340: 64 78 20 2a 20 32 7d 5d 20 5b 65 78 70 72 20 7b dx * 2}] [expr {
0350: 28 24 69 64 78 20 2a 20 32 29 20 2b 20 31 7d 5d ($idx * 2) + 1}]
0360: 5d 2f 22 0a 09 09 7d 0a 09 09 61 70 70 65 6e 64 ]/"...}...append
0370: 20 72 65 74 76 61 6c 20 22 5b 73 74 72 69 6e 67 retval "[string
0380: 20 72 61 6e 67 65 20 24 68 61 73 68 20 5b 65 78 range $hash [ex
0390: 70 72 20 7b 24 69 64 78 20 2a 20 32 7d 5d 20 65 pr {$idx * 2}] e
03a0: 6e 64 5d 22 0a 0a 09 09 72 65 74 75 72 6e 20 24 nd]"....return $
03b0: 72 65 74 76 61 6c 0a 09 7d 0a 0a 09 70 72 6f 63 retval..}...proc
03c0: 20 5f 63 61 63 68 65 66 69 6c 65 20 7b 75 72 6c _cachefile {url
03d0: 20 6b 65 79 20 7b 6b 65 79 49 73 48 61 73 68 20 key {keyIsHash
03e0: 31 7d 7d 20 7b 0a 09 09 73 65 74 20 66 69 6c 65 1}} {...set file
03f0: 6b 65 79 20 24 6b 65 79 0a 09 09 69 66 20 7b 24 key $key...if {$
0400: 6b 65 79 49 73 48 61 73 68 7d 20 7b 0a 09 09 09 keyIsHash} {....
0410: 73 65 74 20 66 69 6c 65 6b 65 79 20 5b 5f 68 61 set filekey [_ha
0420: 73 68 5f 73 65 70 20 24 66 69 6c 65 6b 65 79 5d sh_sep $filekey]
0430: 0a 09 09 7d 0a 0a 09 09 73 65 74 20 66 69 6c 65 ...}....set file
0440: 20 5b 66 69 6c 65 20 6a 6f 69 6e 20 24 3a 3a 61 [file join $::a
0450: 70 70 66 73 3a 3a 63 61 63 68 65 64 69 72 20 24 ppfs::cachedir $
0460: 66 69 6c 65 6b 65 79 5d 0a 0a 09 09 66 69 6c 65 filekey]....file
0470: 20 6d 6b 64 69 72 20 5b 66 69 6c 65 20 64 69 72 mkdir [file dir
0480: 6e 61 6d 65 20 24 66 69 6c 65 5d 0a 0a 09 09 69 name $file]....i
0490: 66 20 7b 5b 66 69 6c 65 20 65 78 69 73 74 73 20 f {[file exists
04a0: 24 66 69 6c 65 5d 7d 20 7b 0a 09 09 09 72 65 74 $file]} {....ret
04b0: 75 72 6e 20 24 66 69 6c 65 0a 09 09 7d 0a 0a 09 urn $file...}...
04c0: 09 73 65 74 20 74 6d 70 66 69 6c 65 20 22 24 7b .set tmpfile "${
04d0: 66 69 6c 65 7d 2e 5b 65 78 70 72 20 7b 72 61 6e file}.[expr {ran
04e0: 64 28 29 7d 5d 5b 63 6c 6f 63 6b 20 63 6c 69 63 d()}][clock clic
04f0: 6b 73 5d 22 0a 0a 09 09 73 65 74 20 66 64 20 5b ks]"....set fd [
0500: 6f 70 65 6e 20 24 74 6d 70 66 69 6c 65 20 22 77 open $tmpfile "w
0510: 22 5d 0a 09 09 66 63 6f 6e 66 69 67 75 72 65 20 "]...fconfigure
0520: 24 66 64 20 2d 74 72 61 6e 73 6c 61 74 69 6f 6e $fd -translation
0530: 20 62 69 6e 61 72 79 0a 0a 09 09 63 61 74 63 68 binary....catch
0540: 20 7b 0a 09 09 09 73 65 74 20 74 6f 6b 65 6e 20 {....set token
0550: 5b 3a 3a 68 74 74 70 3a 3a 67 65 74 75 72 6c 20 [::http::geturl
0560: 24 75 72 6c 20 2d 63 68 61 6e 6e 65 6c 20 24 66 $url -channel $f
0570: 64 20 2d 62 69 6e 61 72 79 20 74 72 75 65 5d 0a d -binary true].
0580: 09 09 7d 0a 0a 09 09 69 66 20 7b 5b 69 6e 66 6f ..}....if {[info
0590: 20 65 78 69 73 74 73 20 74 6f 6b 65 6e 5d 7d 20 exists token]}
05a0: 7b 0a 09 09 09 73 65 74 20 6e 63 6f 64 65 20 5b {....set ncode [
05b0: 3a 3a 68 74 74 70 3a 3a 6e 63 6f 64 65 20 24 74 ::http::ncode $t
05c0: 6f 6b 65 6e 5d 0a 09 09 09 3a 3a 68 74 74 70 3a oken]....::http:
05d0: 3a 72 65 73 65 74 20 24 74 6f 6b 65 6e 0a 09 09 :reset $token...
05e0: 7d 20 65 6c 73 65 20 7b 0a 09 09 09 73 65 74 20 } else {....set
05f0: 6e 63 6f 64 65 20 22 39 30 30 22 0a 09 09 7d 0a ncode "900"...}.
0600: 0a 09 09 63 6c 6f 73 65 20 24 66 64 0a 0a 09 09 ...close $fd....
0610: 69 66 20 7b 24 6b 65 79 49 73 48 61 73 68 7d 20 if {$keyIsHash}
0620: 7b 0a 09 09 09 73 65 74 20 68 61 73 68 20 5b 73 {....set hash [s
0630: 74 72 69 6e 67 20 74 6f 6c 6f 77 65 72 20 5b 73 tring tolower [s
0640: 68 61 31 3a 3a 73 68 61 31 20 2d 68 65 78 20 2d ha1::sha1 -hex -
0650: 66 69 6c 65 20 24 74 6d 70 66 69 6c 65 5d 5d 0a file $tmpfile]].
0660: 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 73 65 ..} else {....se
0670: 74 20 68 61 73 68 20 24 6b 65 79 0a 09 09 7d 0a t hash $key...}.
0680: 0a 09 09 69 66 20 7b 24 6e 63 6f 64 65 20 3d 3d ...if {$ncode ==
0690: 20 22 32 30 30 22 20 26 26 20 24 68 61 73 68 20 "200" && $hash
06a0: 3d 3d 20 24 6b 65 79 7d 20 7b 0a 09 09 09 66 69 == $key} {....fi
06b0: 6c 65 20 72 65 6e 61 6d 65 20 2d 66 6f 72 63 65 le rename -force
06c0: 20 2d 2d 20 24 74 6d 70 66 69 6c 65 20 24 66 69 -- $tmpfile $fi
06d0: 6c 65 0a 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 le...} else {...
06e0: 09 66 69 6c 65 20 64 65 6c 65 74 65 20 2d 66 6f .file delete -fo
06f0: 72 63 65 20 2d 2d 20 24 74 6d 70 66 69 6c 65 0a rce -- $tmpfile.
0700: 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e 20 24 66 ..}....return $f
0710: 69 6c 65 0a 09 7d 0a 0a 0a 09 70 72 6f 63 20 5f ile..}....proc _
0720: 69 73 48 61 73 68 20 7b 76 61 6c 75 65 7d 20 7b isHash {value} {
0730: 0a 09 09 73 65 74 20 76 61 6c 75 65 20 5b 73 74 ...set value [st
0740: 72 69 6e 67 20 74 6f 6c 6f 77 65 72 20 24 76 61 ring tolower $va
0750: 6c 75 65 5d 0a 0a 09 09 69 66 20 7b 5b 73 74 72 lue]....if {[str
0760: 69 6e 67 20 6c 65 6e 67 74 68 20 24 76 61 6c 75 ing length $valu
0770: 65 5d 20 21 3d 20 34 30 7d 20 7b 0a 09 09 09 72 e] != 40} {....r
0780: 65 74 75 72 6e 20 66 61 6c 73 65 0a 09 09 7d 0a eturn false...}.
0790: 0a 09 09 69 66 20 7b 21 5b 72 65 67 65 78 70 20 ...if {![regexp
07a0: 7b 5e 5b 30 2d 39 61 2d 66 5d 2a 24 7d 20 24 76 {^[0-9a-f]*$} $v
07b0: 61 6c 75 65 5d 7d 20 7b 0a 09 09 09 72 65 74 75 alue]} {....retu
07c0: 72 6e 20 66 61 6c 73 65 0a 09 09 7d 0a 0a 09 09 rn false...}....
07d0: 72 65 74 75 72 6e 20 74 72 75 65 0a 09 7d 0a 0a return true..}..
07e0: 09 70 72 6f 63 20 5f 76 65 72 69 66 79 53 69 67 .proc _verifySig
07f0: 6e 61 74 75 72 65 41 6e 64 43 65 72 74 69 66 69 natureAndCertifi
0800: 63 61 74 65 20 7b 68 6f 73 74 6e 61 6d 65 20 63 cate {hostname c
0810: 65 72 74 69 66 69 63 61 74 65 20 73 69 67 6e 61 ertificate signa
0820: 74 75 72 65 20 68 61 73 68 7d 20 7b 0a 09 09 73 ture hash} {...s
0830: 65 74 20 63 65 72 74 69 66 69 63 61 74 65 20 5b et certificate [
0840: 62 69 6e 61 72 79 20 66 6f 72 6d 61 74 20 22 48 binary format "H
0850: 2a 22 20 24 63 65 72 74 69 66 69 63 61 74 65 5d *" $certificate]
0860: 0a 09 09 73 65 74 20 73 69 67 6e 61 74 75 72 65 ...set signature
0870: 20 20 20 5b 62 69 6e 61 72 79 20 66 6f 72 6d 61 [binary forma
0880: 74 20 22 48 2a 22 20 24 73 69 67 6e 61 74 75 72 t "H*" $signatur
0890: 65 5d 0a 0a 09 09 73 65 74 20 63 65 72 74 69 66 e]....set certif
08a0: 69 63 61 74 65 20 5b 3a 3a 70 6b 69 3a 3a 78 35 icate [::pki::x5
08b0: 30 39 3a 3a 70 61 72 73 65 5f 63 65 72 74 20 24 09::parse_cert $
08c0: 63 65 72 74 69 66 69 63 61 74 65 5d 0a 0a 09 09 certificate]....
08d0: 61 72 72 61 79 20 73 65 74 20 63 65 72 74 69 66 array set certif
08e0: 69 63 61 74 65 5f 61 72 72 20 24 63 65 72 74 69 icate_arr $certi
08f0: 66 69 63 61 74 65 0a 09 09 73 65 74 20 63 65 72 ficate...set cer
0900: 74 69 66 69 63 61 74 65 5f 63 6e 20 5b 3a 3a 70 tificate_cn [::p
0910: 6b 69 3a 3a 78 35 30 39 3a 3a 5f 64 6e 5f 74 6f ki::x509::_dn_to
0920: 5f 63 6e 20 24 63 65 72 74 69 66 69 63 61 74 65 _cn $certificate
0930: 5f 61 72 72 28 73 75 62 6a 65 63 74 29 5d 0a 0a _arr(subject)]..
0940: 09 09 69 66 20 7b 21 5b 3a 3a 70 6b 69 3a 3a 76 ..if {![::pki::v
0950: 65 72 69 66 79 20 24 73 69 67 6e 61 74 75 72 65 erify $signature
0960: 20 22 24 68 61 73 68 2c 73 68 61 31 22 20 24 63 "$hash,sha1" $c
0970: 65 72 74 69 66 69 63 61 74 65 5d 7d 20 7b 0a 09 ertificate]} {..
0980: 09 09 72 65 74 75 72 6e 20 66 61 6c 73 65 0a 09 ..return false..
0990: 09 7d 0a 0a 09 09 69 66 20 7b 5b 73 74 72 69 6e .}....if {[strin
09a0: 67 20 74 6f 6c 6f 77 65 72 20 24 63 65 72 74 69 g tolower $certi
09b0: 66 69 63 61 74 65 5f 63 6e 5d 20 21 3d 20 5b 73 ficate_cn] != [s
09c0: 74 72 69 6e 67 20 74 6f 6c 6f 77 65 72 20 24 68 tring tolower $h
09d0: 6f 73 74 6e 61 6d 65 5d 7d 20 7b 0a 09 09 09 72 ostname]} {....r
09e0: 65 74 75 72 6e 20 66 61 6c 73 65 0a 09 09 7d 0a eturn false...}.
09f0: 0a 09 09 69 66 20 7b 21 5b 3a 3a 70 6b 69 3a 3a ...if {![::pki::
0a00: 78 35 30 39 3a 3a 76 65 72 69 66 79 5f 63 65 72 x509::verify_cer
0a10: 74 20 24 63 65 72 74 69 66 69 63 61 74 65 20 24 t $certificate $
0a20: 3a 3a 61 70 70 66 73 3a 3a 74 72 75 73 74 65 64 ::appfs::trusted
0a30: 5f 63 61 73 5d 7d 20 7b 0a 09 09 09 72 65 74 75 _cas]} {....retu
0a40: 72 6e 20 66 61 6c 73 65 0a 09 09 7d 0a 0a 09 09 rn false...}....
0a50: 72 65 74 75 72 6e 20 74 72 75 65 0a 09 7d 0a 0a return true..}..
0a60: 09 70 72 6f 63 20 5f 6e 6f 72 6d 61 6c 69 7a 65 .proc _normalize
0a70: 4f 53 20 7b 6f 73 7d 20 7b 0a 09 09 73 65 74 20 OS {os} {...set
0a80: 6f 73 20 5b 73 74 72 69 6e 67 20 74 6f 6c 6f 77 os [string tolow
0a90: 65 72 20 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 er [string trim
0aa0: 24 6f 73 5d 5d 0a 0a 09 09 73 77 69 74 63 68 20 $os]]....switch
0ab0: 2d 2d 20 24 6f 73 20 7b 0a 09 09 09 22 6c 69 6e -- $os {...."lin
0ac0: 75 78 22 20 2d 20 22 66 72 65 65 62 73 64 22 20 ux" - "freebsd"
0ad0: 2d 20 22 6f 70 65 6e 62 73 64 22 20 2d 20 22 6e - "openbsd" - "n
0ae0: 65 74 62 73 64 22 20 7b 0a 09 09 09 09 72 65 74 etbsd" {.....ret
0af0: 75 72 6e 20 24 6f 73 0a 09 09 09 7d 0a 09 09 09 urn $os....}....
0b00: 22 73 75 6e 6f 73 22 20 7b 0a 09 09 09 09 72 65 "sunos" {.....re
0b10: 74 75 72 6e 20 22 73 6f 6c 61 72 69 73 22 0a 09 turn "solaris"..
0b20: 09 09 7d 0a 09 09 09 22 6e 6f 61 72 63 68 22 20 ..}...."noarch"
0b30: 2d 20 22 6e 6f 6e 65 22 20 2d 20 22 61 6e 79 22 - "none" - "any"
0b40: 20 2d 20 22 61 6c 6c 22 20 7b 0a 09 09 09 09 72 - "all" {.....r
0b50: 65 74 75 72 6e 20 22 6e 6f 61 72 63 68 22 0a 09 eturn "noarch"..
0b60: 09 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 ..}...}....retur
0b70: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 55 n -code error "U
0b80: 6e 61 62 6c 65 20 74 6f 20 6e 6f 72 6d 61 6c 69 nable to normali
0b90: 7a 65 20 4f 53 3a 20 24 6f 73 22 0a 09 7d 0a 0a ze OS: $os"..}..
0ba0: 09 70 72 6f 63 20 5f 6e 6f 72 6d 61 6c 69 7a 65 .proc _normalize
0bb0: 43 50 55 20 7b 63 70 75 7d 20 7b 0a 09 09 73 65 CPU {cpu} {...se
0bc0: 74 20 63 70 75 20 5b 73 74 72 69 6e 67 20 74 6f t cpu [string to
0bd0: 6c 6f 77 65 72 20 5b 73 74 72 69 6e 67 20 74 72 lower [string tr
0be0: 69 6d 20 24 63 70 75 5d 5d 0a 0a 09 09 73 77 69 im $cpu]]....swi
0bf0: 74 63 68 20 2d 67 6c 6f 62 20 2d 2d 20 24 63 70 tch -glob -- $cp
0c00: 75 20 7b 0a 09 09 09 22 69 3f 38 36 22 20 7b 0a u {...."i?86" {.
0c10: 09 09 09 09 72 65 74 75 72 6e 20 22 69 78 38 36 ....return "ix86
0c20: 22 0a 09 09 09 7d 0a 09 09 09 22 78 38 36 5f 36 "....}...."x86_6
0c30: 34 22 20 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 4" {.....return
0c40: 24 63 70 75 0a 09 09 09 7d 0a 09 09 09 22 6e 6f $cpu....}...."no
0c50: 61 72 63 68 22 20 2d 20 22 6e 6f 6e 65 22 20 2d arch" - "none" -
0c60: 20 22 61 6e 79 22 20 2d 20 22 61 6c 6c 22 20 7b "any" - "all" {
0c70: 0a 09 09 09 09 72 65 74 75 72 6e 20 22 6e 6f 61 .....return "noa
0c80: 72 63 68 22 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 rch"....}...}...
0c90: 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 .return -code er
0ca0: 72 6f 72 20 22 55 6e 61 62 6c 65 20 74 6f 20 6e ror "Unable to n
0cb0: 6f 72 6d 61 6c 69 7a 65 20 43 50 55 3a 20 24 63 ormalize CPU: $c
0cc0: 70 75 22 0a 09 7d 0a 0a 09 70 72 6f 63 20 5f 61 pu"..}...proc _a
0cd0: 73 5f 75 73 65 72 20 7b 63 6f 64 65 7d 20 7b 0a s_user {code} {.
0ce0: 09 09 3a 3a 61 70 70 66 73 64 3a 3a 73 69 6d 75 ..::appfsd::simu
0cf0: 6c 61 74 65 5f 75 73 65 72 5f 66 73 5f 65 6e 74 late_user_fs_ent
0d00: 65 72 0a 0a 09 09 73 65 74 20 72 65 74 63 6f 64 er....set retcod
0d10: 65 20 5b 63 61 74 63 68 20 5b 6c 69 73 74 20 75 e [catch [list u
0d20: 70 6c 65 76 65 6c 20 24 63 6f 64 65 5d 20 72 65 plevel $code] re
0d30: 74 73 74 72 5d 0a 0a 09 09 3a 3a 61 70 70 66 73 tstr]....::appfs
0d40: 64 3a 3a 73 69 6d 75 6c 61 74 65 5f 75 73 65 72 d::simulate_user
0d50: 5f 66 73 5f 6c 65 61 76 65 0a 0a 09 09 72 65 74 _fs_leave....ret
0d60: 75 72 6e 20 2d 63 6f 64 65 20 24 72 65 74 63 6f urn -code $retco
0d70: 64 65 20 24 72 65 74 73 74 72 0a 09 7d 0a 0a 09 de $retstr..}...
0d80: 70 72 6f 63 20 69 6e 69 74 20 7b 7d 20 7b 0a 09 proc init {} {..
0d90: 09 69 66 20 7b 5b 69 6e 66 6f 20 65 78 69 73 74 .if {[info exist
0da0: 73 20 3a 3a 61 70 70 66 73 3a 3a 69 6e 69 74 5f s ::appfs::init_
0db0: 63 61 6c 6c 65 64 5d 7d 20 7b 0a 09 09 09 72 65 called]} {....re
0dc0: 74 75 72 6e 0a 09 09 7d 0a 0a 09 09 23 20 46 6f turn...}....# Fo
0dd0: 72 63 65 20 5b 70 61 72 72 61 79 5d 20 61 6e 64 rce [parray] and
0de0: 20 5b 63 6c 6f 63 6b 5d 20 74 6f 20 62 65 20 6c [clock] to be l
0df0: 6f 61 64 65 64 0a 09 09 63 61 74 63 68 20 7b 0a oaded...catch {.
0e00: 09 09 09 70 61 72 72 61 79 20 64 6f 65 73 5f 6e ...parray does_n
0e10: 6f 74 5f 65 78 69 73 74 0a 09 09 7d 0a 09 09 63 ot_exist...}...c
0e20: 61 74 63 68 20 7b 0a 09 09 09 63 6c 6f 63 6b 20 atch {....clock
0e30: 73 65 63 6f 6e 64 73 0a 09 09 7d 0a 09 09 63 61 seconds...}...ca
0e40: 74 63 68 20 7b 0a 09 09 09 63 6c 6f 63 6b 20 61 tch {....clock a
0e50: 64 64 20 5b 63 6c 6f 63 6b 20 73 65 63 6f 6e 64 dd [clock second
0e60: 73 5d 20 33 20 73 65 63 6f 6e 64 73 0a 09 09 7d s] 3 seconds...}
0e70: 0a 0a 09 09 73 65 74 20 3a 3a 61 70 70 66 73 3a ....set ::appfs:
0e80: 3a 69 6e 69 74 5f 63 61 6c 6c 65 64 20 31 0a 0a :init_called 1..
0e90: 09 09 23 20 41 64 64 20 61 20 64 65 66 61 75 6c ..# Add a defaul
0ea0: 74 20 43 41 20 74 6f 20 6c 69 73 74 20 6f 66 20 t CA to list of
0eb0: 74 72 75 73 74 65 64 20 43 41 73 0a 09 09 6c 61 trusted CAs...la
0ec0: 70 70 65 6e 64 20 3a 3a 61 70 70 66 73 3a 3a 74 ppend ::appfs::t
0ed0: 72 75 73 74 65 64 5f 63 61 73 20 5b 3a 3a 70 6b rusted_cas [::pk
0ee0: 69 3a 3a 78 35 30 39 3a 3a 70 61 72 73 65 5f 63 i::x509::parse_c
0ef0: 65 72 74 20 7b 0a 2d 2d 2d 2d 2d 42 45 47 49 4e ert {.-----BEGIN
0f00: 20 43 45 52 54 49 46 49 43 41 54 45 2d 2d 2d 2d CERTIFICATE----
0f10: 2d 0a 4d 49 49 43 37 44 43 43 41 64 53 67 41 77 -.MIIC7DCCAdSgAw
0f20: 49 42 41 67 49 42 41 54 41 4e 42 67 6b 71 68 6b IBAgIBATANBgkqhk
0f30: 69 47 39 77 30 42 41 51 55 46 41 44 41 76 4d 52 iG9w0BAQUFADAvMR
0f40: 49 77 45 41 59 44 56 51 51 4b 45 77 6c 53 62 33 IwEAYDVQQKEwlSb3
0f50: 6b 67 0a 53 32 56 6c 62 6d 55 78 47 54 41 58 42 kg.S2VlbmUxGTAXB
0f60: 67 4e 56 42 41 4d 54 45 45 46 77 63 45 5a 54 49 gNVBAMTEEFwcEZTI
0f70: 45 74 6c 65 53 42 4e 59 58 4e 30 5a 58 49 77 48 EtleSBNYXN0ZXIwH
0f80: 68 63 4e 4d 54 51 78 4d 54 45 33 4d 6a 41 78 4e hcNMTQxMTE3MjAxN
0f90: 7a 49 34 0a 57 68 63 4e 4d 54 6b 78 4d 54 45 33 zI4.WhcNMTkxMTE3
0fa0: 4d 6a 41 78 4e 7a 49 34 57 6a 41 76 4d 52 49 77 MjAxNzI4WjAvMRIw
0fb0: 45 41 59 44 56 51 51 4b 45 77 6c 53 62 33 6b 67 EAYDVQQKEwlSb3kg
0fc0: 53 32 56 6c 62 6d 55 78 47 54 41 58 42 67 4e 56 S2VlbmUxGTAXBgNV
0fd0: 42 41 4d 54 0a 45 45 46 77 63 45 5a 54 49 45 74 BAMT.EEFwcEZTIEt
0fe0: 6c 65 53 42 4e 59 58 4e 30 5a 58 49 77 67 67 45 leSBNYXN0ZXIwggE
0ff0: 69 4d 41 30 47 43 53 71 47 53 49 62 33 44 51 45 iMA0GCSqGSIb3DQE
1000: 42 41 51 55 41 41 34 49 42 44 77 41 77 67 67 45 BAQUAA4IBDwAwggE
1010: 4b 41 6f 49 42 0a 41 51 43 71 36 75 53 4b 34 36 KAoIB.AQCq6uSK46
1020: 79 47 35 62 36 52 4a 57 77 52 6c 76 77 35 67 6c yG5b6RJWwRlvw5gl
1030: 41 6e 6a 73 63 31 47 69 58 33 64 75 58 41 30 76 Anjsc1GiX3duXA0v
1040: 47 34 71 6e 4b 55 6e 44 74 6c 2f 6a 63 4d 6d 71 G4qnKUnDtl/jcMmq
1050: 32 47 4d 4f 42 39 0a 49 79 31 74 6a 61 62 45 48 2GMOB9.Iy1tjabEH
1060: 41 30 4d 68 57 32 6a 37 56 77 65 2f 4f 39 4d 4c A0MhW2j7Vwe/O9ML
1070: 46 4a 6b 4a 33 30 4d 31 50 56 44 37 59 5a 52 52 FJkJ30M1PVD7YZRR
1080: 4e 61 41 73 7a 33 55 57 49 4b 45 6a 50 49 37 42 NaAsz3UWIKEjPI7B
1090: 42 63 33 32 4b 4f 6d 0a 42 4c 33 43 54 58 43 43 Bc32KOm.BL3CTXCC
10a0: 64 7a 6c 6c 4c 31 48 68 56 62 6e 4d 35 69 43 41 dzllL1HhVbnM5iCA
10b0: 6d 67 48 63 67 31 44 55 6b 2f 45 76 57 58 76 6e mgHcg1DUk/EvWXvn
10c0: 45 44 78 58 52 79 32 6c 56 39 6d 51 73 6d 44 65 EDxXRy2lV9mQsmDe
10d0: 64 72 66 66 59 37 57 6c 0a 4f 72 35 37 6e 6c 63 drffY7Wl.Or57nlc
10e0: 7a 61 4d 75 50 4c 70 79 52 53 6b 76 37 35 50 41 zaMuPLpyRSkv75PA
10f0: 6e 6a 51 4a 78 54 33 73 57 6c 42 70 79 2b 2f 48 njQJxT3sWlBpy+/H
1100: 39 49 6d 75 64 51 64 70 4a 4e 66 2f 46 74 78 63 9ImudQdpJNf/Ftxc
1110: 71 4e 37 69 44 77 48 35 42 0a 76 49 63 65 59 45 qN7iDwH5B.vIceYE
1120: 74 44 56 78 46 73 76 6f 35 48 4f 56 6b 53 6c 39 tDVxFsvo5HOVkSl9
1130: 6a 65 6f 35 45 34 47 70 65 33 77 79 66 52 68 6f jeo5E4Gpe3wyfRho
1140: 71 42 32 55 6b 61 57 31 4b 71 30 69 48 35 52 2b qB2UkaW1Kq0iH5R+
1150: 30 30 53 37 36 30 78 51 4d 78 0a 4c 4c 39 4c 31 00S760xQMx.LL9L1
1160: 64 75 68 75 31 64 4c 37 48 73 6d 45 77 37 49 65 duhu1dL7HsmEw7Ie
1170: 59 55 52 41 67 4d 42 41 41 47 6a 45 7a 41 52 4d YURAgMBAAGjEzARM
1180: 41 38 47 41 31 55 64 45 77 45 42 2f 77 51 46 4d A8GA1UdEwEB/wQFM
1190: 41 4d 42 41 66 38 77 44 51 59 4a 0a 4b 6f 5a 49 AMBAf8wDQYJ.KoZI
11a0: 68 76 63 4e 41 51 45 46 42 51 41 44 67 67 45 42 hvcNAQEFBQADggEB
11b0: 41 4b 68 4f 34 5a 53 7a 59 50 33 37 42 71 69 78 AKhO4ZSzYP37Bqix
11c0: 4e 48 4b 4b 39 2b 67 53 65 43 36 46 67 61 38 35 NHKK9+gSeC6Fga85
11d0: 69 4c 57 68 77 70 50 57 30 6b 53 6c 0a 7a 30 33 iLWhwpPW0kSl.z03
11e0: 68 61 6c 38 30 4b 5a 2b 6b 50 4d 7a 62 38 43 35 hal80KZ+kPMzb8C5
11f0: 32 4e 32 38 33 74 51 4e 41 71 4a 39 51 38 61 6b 2N283tQNAqJ9Q8ak
1200: 44 50 5a 78 53 7a 7a 4d 55 56 4f 47 70 47 77 32 DPZxSzzMUVOGpGw2
1210: 70 4a 37 5a 73 77 4b 44 7a 30 5a 54 61 0a 30 65 pJ7ZswKDz0ZTa.0e
1220: 64 71 2f 67 64 54 2f 48 72 64 65 67 76 4e 74 44 dq/gdT/HrdegvNtD
1230: 50 63 32 6a 6f 6e 61 35 46 56 4f 59 71 77 64 63 Pc2jona5FVOYqwdc
1240: 7a 35 6b 62 6c 31 55 57 42 61 42 70 33 56 58 55 z5kbl1UWBaBp3VXU
1250: 67 63 59 6a 58 53 52 61 42 4b 34 33 57 64 0a 63 gcYjXSRaBK43Wd.c
1260: 76 65 69 44 55 65 5a 77 37 67 48 71 52 53 4e 2f veiDUeZw7gHqRSN/
1270: 41 79 59 55 43 74 4a 7a 57 6d 76 47 73 4a 75 49 AyYUCtJzWmvGsJuI
1280: 46 68 4d 42 6f 6e 75 7a 38 6a 79 6c 68 79 4d 4a FhMBonuz8jylhyMJ
1290: 43 59 4a 46 54 34 69 4d 55 43 38 4d 4e 49 77 0a CYJFT4iMUC8MNIw.
12a0: 6e 69 58 31 78 78 2b 4e 75 36 66 50 56 35 5a 5a niX1xx+Nu6fPV5ZZ
12b0: 48 6a 39 72 62 68 69 42 61 4c 6a 6d 2b 74 6b 44 Hj9rbhiBaLjm+tkD
12c0: 77 74 50 67 41 33 6a 32 70 78 76 48 4b 59 70 74 wtPgA3j2pxvHKYpt
12d0: 75 57 78 65 59 4f 2b 39 44 44 4e 61 39 73 43 62 uWxeYO+9DDNa9sCb
12e0: 0a 45 35 41 6e 4a 49 6c 4f 6e 64 2f 74 47 65 30 .E5AnJIlOnd/tGe0
12f0: 43 68 66 30 73 46 51 67 2b 6c 39 6e 4e 69 4e 72 Chf0sFQg+l9nNiNr
1300: 57 47 67 7a 64 64 39 5a 50 4a 4b 34 3d 0a 2d 2d WGgzdd9ZPJK4=.--
1310: 2d 2d 2d 45 4e 44 20 43 45 52 54 49 46 49 43 41 ---END CERTIFICA
1320: 54 45 2d 2d 2d 2d 2d 0a 7d 5d 0a 0a 09 09 23 20 TE-----.}]....#
1330: 4c 6f 61 64 20 63 6f 6e 66 69 67 75 72 61 74 69 Load configurati
1340: 6f 6e 20 66 69 6c 65 0a 09 09 73 65 74 20 63 6f on file...set co
1350: 6e 66 69 67 5f 66 69 6c 65 20 5b 66 69 6c 65 20 nfig_file [file
1360: 6a 6f 69 6e 20 24 3a 3a 61 70 70 66 73 3a 3a 63 join $::appfs::c
1370: 61 63 68 65 64 69 72 20 63 6f 6e 66 69 67 5d 0a achedir config].
1380: 09 09 69 66 20 7b 5b 66 69 6c 65 20 65 78 69 73 ..if {[file exis
1390: 74 73 20 24 63 6f 6e 66 69 67 5f 66 69 6c 65 5d ts $config_file]
13a0: 7d 20 7b 0a 09 09 09 73 6f 75 72 63 65 20 24 63 } {....source $c
13b0: 6f 6e 66 69 67 5f 66 69 6c 65 0a 09 09 7d 0a 0a onfig_file...}..
13c0: 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 ..if {![info exi
13d0: 73 74 73 20 3a 3a 61 70 70 66 73 3a 3a 64 62 5d sts ::appfs::db]
13e0: 7d 20 7b 0a 09 09 09 66 69 6c 65 20 6d 6b 64 69 } {....file mkdi
13f0: 72 20 24 3a 3a 61 70 70 66 73 3a 3a 63 61 63 68 r $::appfs::cach
1400: 65 64 69 72 0a 0a 09 09 09 73 71 6c 69 74 65 33 edir.....sqlite3
1410: 20 3a 3a 61 70 70 66 73 3a 3a 64 62 20 5b 66 69 ::appfs::db [fi
1420: 6c 65 20 6a 6f 69 6e 20 24 3a 3a 61 70 70 66 73 le join $::appfs
1430: 3a 3a 63 61 63 68 65 64 69 72 20 63 61 63 68 65 ::cachedir cache
1440: 2e 64 62 5d 0a 0a 09 09 09 3a 3a 61 70 70 66 73 .db].....::appfs
1450: 3a 3a 64 62 20 74 69 6d 65 6f 75 74 20 33 30 30 ::db timeout 300
1460: 30 30 0a 09 09 7d 0a 0a 09 09 23 20 43 72 65 61 00...}....# Crea
1470: 74 65 20 74 61 62 6c 65 73 0a 09 09 64 62 20 65 te tables...db e
1480: 76 61 6c 20 7b 43 52 45 41 54 45 20 54 41 42 4c val {CREATE TABL
1490: 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53 20 E IF NOT EXISTS
14a0: 73 69 74 65 73 28 68 6f 73 74 6e 61 6d 65 20 50 sites(hostname P
14b0: 52 49 4d 41 52 59 20 4b 45 59 2c 20 6c 61 73 74 RIMARY KEY, last
14c0: 55 70 64 61 74 65 2c 20 74 74 6c 29 3b 7d 0a 09 Update, ttl);}..
14d0: 09 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54 45 .db eval {CREATE
14e0: 20 54 41 42 4c 45 20 49 46 20 4e 4f 54 20 45 58 TABLE IF NOT EX
14f0: 49 53 54 53 20 70 61 63 6b 61 67 65 73 28 68 6f ISTS packages(ho
1500: 73 74 6e 61 6d 65 2c 20 73 68 61 31 2c 20 70 61 stname, sha1, pa
1510: 63 6b 61 67 65 2c 20 76 65 72 73 69 6f 6e 2c 20 ckage, version,
1520: 6f 73 2c 20 63 70 75 41 72 63 68 2c 20 69 73 4c os, cpuArch, isL
1530: 61 74 65 73 74 2c 20 68 61 76 65 4d 61 6e 69 66 atest, haveManif
1540: 65 73 74 29 3b 7d 0a 09 09 64 62 20 65 76 61 6c est);}...db eval
1550: 20 7b 43 52 45 41 54 45 20 54 41 42 4c 45 20 49 {CREATE TABLE I
1560: 46 20 4e 4f 54 20 45 58 49 53 54 53 20 66 69 6c F NOT EXISTS fil
1570: 65 73 28 70 61 63 6b 61 67 65 5f 73 68 61 31 2c es(package_sha1,
1580: 20 74 79 70 65 2c 20 74 69 6d 65 2c 20 73 6f 75 type, time, sou
1590: 72 63 65 2c 20 73 69 7a 65 2c 20 70 65 72 6d 73 rce, size, perms
15a0: 2c 20 66 69 6c 65 5f 73 68 61 31 2c 20 66 69 6c , file_sha1, fil
15b0: 65 5f 6e 61 6d 65 2c 20 66 69 6c 65 5f 64 69 72 e_name, file_dir
15c0: 65 63 74 6f 72 79 29 3b 7d 0a 0a 09 09 23 20 43 ectory);}....# C
15d0: 72 65 61 74 65 20 69 6e 64 65 78 65 73 0a 09 09 reate indexes...
15e0: 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54 45 20 db eval {CREATE
15f0: 49 4e 44 45 58 20 49 46 20 4e 4f 54 20 45 58 49 INDEX IF NOT EXI
1600: 53 54 53 20 73 69 74 65 73 5f 69 6e 64 65 78 20 STS sites_index
1610: 4f 4e 20 73 69 74 65 73 20 28 68 6f 73 74 6e 61 ON sites (hostna
1620: 6d 65 29 3b 7d 0a 09 09 64 62 20 65 76 61 6c 20 me);}...db eval
1630: 7b 43 52 45 41 54 45 20 49 4e 44 45 58 20 49 46 {CREATE INDEX IF
1640: 20 4e 4f 54 20 45 58 49 53 54 53 20 70 61 63 6b NOT EXISTS pack
1650: 61 67 65 73 5f 69 6e 64 65 78 20 4f 4e 20 70 61 ages_index ON pa
1660: 63 6b 61 67 65 73 20 28 68 6f 73 74 6e 61 6d 65 ckages (hostname
1670: 2c 20 73 68 61 31 2c 20 70 61 63 6b 61 67 65 2c , sha1, package,
1680: 20 76 65 72 73 69 6f 6e 2c 20 6f 73 2c 20 63 70 version, os, cp
1690: 75 41 72 63 68 29 3b 7d 0a 09 09 64 62 20 65 76 uArch);}...db ev
16a0: 61 6c 20 7b 43 52 45 41 54 45 20 49 4e 44 45 58 al {CREATE INDEX
16b0: 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53 20 66 IF NOT EXISTS f
16c0: 69 6c 65 73 5f 69 6e 64 65 78 20 4f 4e 20 66 69 iles_index ON fi
16d0: 6c 65 73 20 28 70 61 63 6b 61 67 65 5f 73 68 61 les (package_sha
16e0: 31 2c 20 66 69 6c 65 5f 6e 61 6d 65 2c 20 66 69 1, file_name, fi
16f0: 6c 65 5f 64 69 72 65 63 74 6f 72 79 29 3b 7d 0a le_directory);}.
1700: 09 7d 0a 0a 09 70 72 6f 63 20 64 6f 77 6e 6c 6f .}...proc downlo
1710: 61 64 20 7b 68 6f 73 74 6e 61 6d 65 20 68 61 73 ad {hostname has
1720: 68 20 7b 6d 65 74 68 6f 64 20 73 68 61 31 7d 7d h {method sha1}}
1730: 20 7b 0a 09 09 73 65 74 20 75 72 6c 20 5b 3a 3a {...set url [::
1740: 61 70 70 66 73 3a 3a 75 73 65 72 3a 3a 63 6f 6e appfs::user::con
1750: 73 74 72 75 63 74 5f 75 72 6c 20 24 68 6f 73 74 struct_url $host
1760: 6e 61 6d 65 20 24 68 61 73 68 20 24 6d 65 74 68 name $hash $meth
1770: 6f 64 5d 0a 09 09 73 65 74 20 66 69 6c 65 20 5b od]...set file [
1780: 5f 63 61 63 68 65 66 69 6c 65 20 24 75 72 6c 20 _cachefile $url
1790: 24 68 61 73 68 5d 0a 0a 09 09 69 66 20 7b 21 5b $hash]....if {![
17a0: 66 69 6c 65 20 65 78 69 73 74 73 20 24 66 69 6c file exists $fil
17b0: 65 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 e]} {....return
17c0: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 55 6e 61 -code error "Una
17d0: 62 6c 65 20 74 6f 20 66 65 74 63 68 20 28 66 69 ble to fetch (fi
17e0: 6c 65 20 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 le does not exis
17f0: 74 3a 20 24 66 69 6c 65 29 22 0a 09 09 7d 0a 0a t: $file)"...}..
1800: 09 09 72 65 74 75 72 6e 20 24 66 69 6c 65 0a 09 ..return $file..
1810: 7d 0a 0a 09 70 72 6f 63 20 67 65 74 69 6e 64 65 }...proc getinde
1820: 78 20 7b 68 6f 73 74 6e 61 6d 65 7d 20 7b 0a 09 x {hostname} {..
1830: 09 73 65 74 20 6e 6f 77 20 5b 63 6c 6f 63 6b 20 .set now [clock
1840: 73 65 63 6f 6e 64 73 5d 0a 0a 09 09 73 65 74 20 seconds]....set
1850: 6c 61 73 74 55 70 64 61 74 65 73 20 5b 64 62 20 lastUpdates [db
1860: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 6c 61 73 eval {SELECT las
1870: 74 55 70 64 61 74 65 2c 20 74 74 6c 20 46 52 4f tUpdate, ttl FRO
1880: 4d 20 73 69 74 65 73 20 57 48 45 52 45 20 68 6f M sites WHERE ho
1890: 73 74 6e 61 6d 65 20 3d 20 24 68 6f 73 74 6e 61 stname = $hostna
18a0: 6d 65 20 4c 49 4d 49 54 20 31 3b 7d 5d 0a 09 09 me LIMIT 1;}]...
18b0: 69 66 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 6c 61 if {[llength $la
18c0: 73 74 55 70 64 61 74 65 73 5d 20 3d 3d 20 30 7d stUpdates] == 0}
18d0: 20 7b 0a 09 09 09 73 65 74 20 6c 61 73 74 55 70 {....set lastUp
18e0: 64 61 74 65 20 30 0a 09 09 09 73 65 74 20 74 74 date 0....set tt
18f0: 6c 20 30 0a 09 09 7d 20 65 6c 73 65 20 7b 0a 09 l 0...} else {..
1900: 09 09 73 65 74 20 6c 61 73 74 55 70 64 61 74 65 ..set lastUpdate
1910: 20 5b 6c 69 6e 64 65 78 20 24 6c 61 73 74 55 70 [lindex $lastUp
1920: 64 61 74 65 73 20 30 5d 0a 09 09 09 73 65 74 20 dates 0]....set
1930: 74 74 6c 20 5b 6c 69 6e 64 65 78 20 24 6c 61 73 ttl [lindex $las
1940: 74 55 70 64 61 74 65 73 20 31 5d 0a 09 09 7d 0a tUpdates 1]...}.
1950: 0a 09 09 69 66 20 7b 24 6e 6f 77 20 3c 20 28 24 ...if {$now < ($
1960: 6c 61 73 74 55 70 64 61 74 65 20 2b 20 24 74 74 lastUpdate + $tt
1970: 6c 29 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 l)} {....return
1980: 43 4f 4d 50 4c 45 54 45 0a 09 09 7d 0a 0a 09 09 COMPLETE...}....
1990: 69 66 20 7b 5b 73 74 72 69 6e 67 20 6d 61 74 63 if {[string matc
19a0: 68 20 22 2a 5c 5b 2f 7e 5c 5d 2a 22 20 24 68 6f h "*\[/~\]*" $ho
19b0: 73 74 6e 61 6d 65 5d 7d 20 7b 0a 09 09 09 72 65 stname]} {....re
19c0: 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 turn -code error
19d0: 20 22 49 6e 76 61 6c 69 64 20 68 6f 73 74 6e 61 "Invalid hostna
19e0: 6d 65 22 0a 09 09 7d 0a 0a 09 09 73 65 74 20 75 me"...}....set u
19f0: 72 6c 20 22 68 74 74 70 3a 2f 2f 24 68 6f 73 74 rl "http://$host
1a00: 6e 61 6d 65 2f 61 70 70 66 73 2f 69 6e 64 65 78 name/appfs/index
1a10: 22 0a 0a 09 09 63 61 74 63 68 20 7b 0a 09 09 09 "....catch {....
1a20: 73 65 74 20 74 6f 6b 65 6e 20 5b 3a 3a 68 74 74 set token [::htt
1a30: 70 3a 3a 67 65 74 75 72 6c 20 24 75 72 6c 5d 0a p::geturl $url].
1a40: 09 09 09 69 66 20 7b 5b 3a 3a 68 74 74 70 3a 3a ...if {[::http::
1a50: 6e 63 6f 64 65 20 24 74 6f 6b 65 6e 5d 20 3d 3d ncode $token] ==
1a60: 20 22 32 30 30 22 7d 20 7b 0a 09 09 09 09 73 65 "200"} {.....se
1a70: 74 20 69 6e 64 65 78 68 61 73 68 5f 64 61 74 61 t indexhash_data
1a80: 20 5b 3a 3a 68 74 74 70 3a 3a 64 61 74 61 20 24 [::http::data $
1a90: 74 6f 6b 65 6e 5d 0a 09 09 09 7d 0a 09 09 09 3a token]....}....:
1aa0: 3a 68 74 74 70 3a 3a 72 65 73 65 74 20 24 74 6f :http::reset $to
1ab0: 6b 65 6e 0a 09 09 09 3a 3a 68 74 74 70 3a 3a 63 ken....::http::c
1ac0: 6c 65 61 6e 75 70 20 24 74 6f 6b 65 6e 0a 09 09 leanup $token...
1ad0: 7d 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20 }....if {![info
1ae0: 65 78 69 73 74 73 20 69 6e 64 65 78 68 61 73 68 exists indexhash
1af0: 5f 64 61 74 61 5d 7d 20 7b 0a 09 09 09 23 20 43 _data]} {....# C
1b00: 61 63 68 65 20 74 68 69 73 20 72 65 73 75 6c 74 ache this result
1b10: 20 66 6f 72 20 36 30 20 73 65 63 6f 6e 64 73 0a for 60 seconds.
1b20: 09 09 09 64 62 20 65 76 61 6c 20 7b 49 4e 53 45 ...db eval {INSE
1b30: 52 54 20 4f 52 20 52 45 50 4c 41 43 45 20 49 4e RT OR REPLACE IN
1b40: 54 4f 20 73 69 74 65 73 20 28 68 6f 73 74 6e 61 TO sites (hostna
1b50: 6d 65 2c 20 6c 61 73 74 55 70 64 61 74 65 2c 20 me, lastUpdate,
1b60: 74 74 6c 29 20 56 41 4c 55 45 53 20 28 24 68 6f ttl) VALUES ($ho
1b70: 73 74 6e 61 6d 65 2c 20 24 6e 6f 77 2c 20 24 3a stname, $now, $:
1b80: 3a 61 70 70 66 73 3a 3a 6e 74 74 6c 29 3b 7d 0a :appfs::nttl);}.
1b90: 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 ....return -code
1ba0: 20 65 72 72 6f 72 20 22 55 6e 61 62 6c 65 20 74 error "Unable t
1bb0: 6f 20 66 65 74 63 68 20 24 75 72 6c 22 0a 09 09 o fetch $url"...
1bc0: 7d 0a 0a 09 09 73 65 74 20 69 6e 64 65 78 68 61 }....set indexha
1bd0: 73 68 5f 64 61 74 61 20 5b 73 74 72 69 6e 67 20 sh_data [string
1be0: 74 72 69 6d 20 24 69 6e 64 65 78 68 61 73 68 5f trim $indexhash_
1bf0: 64 61 74 61 20 22 5c 72 5c 6e 22 5d 0a 09 09 73 data "\r\n"]...s
1c00: 65 74 20 69 6e 64 65 78 68 61 73 68 5f 64 61 74 et indexhash_dat
1c10: 61 20 5b 73 70 6c 69 74 20 24 69 6e 64 65 78 68 a [split $indexh
1c20: 61 73 68 5f 64 61 74 61 20 22 2c 22 5d 0a 09 09 ash_data ","]...
1c30: 73 65 74 20 69 6e 64 65 78 68 61 73 68 20 20 20 set indexhash
1c40: 20 20 20 20 5b 6c 69 6e 64 65 78 20 24 69 6e 64 [lindex $ind
1c50: 65 78 68 61 73 68 5f 64 61 74 61 20 30 5d 0a 09 exhash_data 0]..
1c60: 09 73 65 74 20 69 6e 64 65 78 68 61 73 68 6d 65 .set indexhashme
1c70: 74 68 6f 64 20 5b 6c 69 6e 64 65 78 20 24 69 6e thod [lindex $in
1c80: 64 65 78 68 61 73 68 5f 64 61 74 61 20 31 5d 0a dexhash_data 1].
1c90: 09 09 73 65 74 20 69 6e 64 65 78 68 61 73 68 63 ..set indexhashc
1ca0: 65 72 74 20 20 20 5b 6c 69 6e 64 65 78 20 24 69 ert [lindex $i
1cb0: 6e 64 65 78 68 61 73 68 5f 64 61 74 61 20 32 5d ndexhash_data 2]
1cc0: 0a 09 09 73 65 74 20 69 6e 64 65 78 68 61 73 68 ...set indexhash
1cd0: 73 69 67 20 20 20 20 5b 6c 69 6e 64 65 78 20 24 sig [lindex $
1ce0: 69 6e 64 65 78 68 61 73 68 5f 64 61 74 61 20 33 indexhash_data 3
1cf0: 5d 0a 0a 09 09 69 66 20 7b 21 5b 5f 69 73 48 61 ]....if {![_isHa
1d00: 73 68 20 24 69 6e 64 65 78 68 61 73 68 5d 7d 20 sh $indexhash]}
1d10: 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 {....return -cod
1d20: 65 20 65 72 72 6f 72 20 22 49 6e 76 61 6c 69 64 e error "Invalid
1d30: 20 68 61 73 68 3a 20 24 69 6e 64 65 78 68 61 73 hash: $indexhas
1d40: 68 22 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 21 5b h"...}....if {![
1d50: 5f 76 65 72 69 66 79 53 69 67 6e 61 74 75 72 65 _verifySignature
1d60: 41 6e 64 43 65 72 74 69 66 69 63 61 74 65 20 24 AndCertificate $
1d70: 68 6f 73 74 6e 61 6d 65 20 24 69 6e 64 65 78 68 hostname $indexh
1d80: 61 73 68 63 65 72 74 20 24 69 6e 64 65 78 68 61 ashcert $indexha
1d90: 73 68 73 69 67 20 24 69 6e 64 65 78 68 61 73 68 shsig $indexhash
1da0: 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d ]} {....return -
1db0: 63 6f 64 65 20 65 72 72 6f 72 20 22 49 6e 76 61 code error "Inva
1dc0: 6c 69 64 20 73 69 67 6e 61 74 75 72 65 20 6f 72 lid signature or
1dd0: 20 63 65 72 74 69 66 69 63 61 74 65 20 66 72 6f certificate fro
1de0: 6d 20 24 68 6f 73 74 6e 61 6d 65 22 0a 09 09 7d m $hostname"...}
1df0: 0a 0a 09 09 73 65 74 20 66 69 6c 65 20 5b 64 6f ....set file [do
1e00: 77 6e 6c 6f 61 64 20 24 68 6f 73 74 6e 61 6d 65 wnload $hostname
1e10: 20 24 69 6e 64 65 78 68 61 73 68 5d 0a 09 09 73 $indexhash]...s
1e20: 65 74 20 66 64 20 5b 6f 70 65 6e 20 24 66 69 6c et fd [open $fil
1e30: 65 5d 0a 09 09 73 65 74 20 64 61 74 61 20 5b 72 e]...set data [r
1e40: 65 61 64 20 24 66 64 5d 0a 09 09 63 6c 6f 73 65 ead $fd]...close
1e50: 20 24 66 64 0a 0a 09 09 73 65 74 20 63 75 72 72 $fd....set curr
1e60: 5f 70 61 63 6b 61 67 65 73 20 5b 6c 69 73 74 5d _packages [list]
1e70: 0a 09 09 66 6f 72 65 61 63 68 20 6c 69 6e 65 20 ...foreach line
1e80: 5b 73 70 6c 69 74 20 24 64 61 74 61 20 22 5c 6e [split $data "\n
1e90: 22 5d 20 7b 0a 09 09 09 73 65 74 20 6c 69 6e 65 "] {....set line
1ea0: 20 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 24 6c [string trim $l
1eb0: 69 6e 65 5d 0a 0a 09 09 09 69 66 20 7b 5b 73 74 ine].....if {[st
1ec0: 72 69 6e 67 20 6d 61 74 63 68 20 22 2a 2f 2a 22 ring match "*/*"
1ed0: 20 24 6c 69 6e 65 5d 7d 20 7b 0a 09 09 09 09 63 $line]} {.....c
1ee0: 6f 6e 74 69 6e 75 65 0a 09 09 09 7d 0a 0a 09 09 ontinue....}....
1ef0: 09 69 66 20 7b 24 6c 69 6e 65 20 3d 3d 20 22 22 .if {$line == ""
1f00: 7d 20 7b 0a 09 09 09 09 63 6f 6e 74 69 6e 75 65 } {.....continue
1f10: 0a 09 09 09 7d 0a 0a 09 09 09 73 65 74 20 77 6f ....}.....set wo
1f20: 72 6b 20 5b 73 70 6c 69 74 20 24 6c 69 6e 65 20 rk [split $line
1f30: 22 2c 22 5d 0a 0a 09 09 09 75 6e 73 65 74 20 2d ","].....unset -
1f40: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 70 6b 67 49 6e nocomplain pkgIn
1f50: 66 6f 0a 09 09 09 69 66 20 7b 5b 63 61 74 63 68 fo....if {[catch
1f60: 20 7b 0a 09 09 09 09 73 65 74 20 70 6b 67 49 6e {.....set pkgIn
1f70: 66 6f 28 70 61 63 6b 61 67 65 29 20 20 5b 6c 69 fo(package) [li
1f80: 6e 64 65 78 20 24 77 6f 72 6b 20 30 5d 0a 09 09 ndex $work 0]...
1f90: 09 09 73 65 74 20 70 6b 67 49 6e 66 6f 28 76 65 ..set pkgInfo(ve
1fa0: 72 73 69 6f 6e 29 20 20 5b 6c 69 6e 64 65 78 20 rsion) [lindex
1fb0: 24 77 6f 72 6b 20 31 5d 0a 09 09 09 09 73 65 74 $work 1].....set
1fc0: 20 70 6b 67 49 6e 66 6f 28 6f 73 29 20 20 20 20 pkgInfo(os)
1fd0: 20 20 20 5b 5f 6e 6f 72 6d 61 6c 69 7a 65 4f 53 [_normalizeOS
1fe0: 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 32 [lindex $work 2
1ff0: 5d 5d 0a 09 09 09 09 73 65 74 20 70 6b 67 49 6e ]].....set pkgIn
2000: 66 6f 28 63 70 75 41 72 63 68 29 20 20 5b 5f 6e fo(cpuArch) [_n
2010: 6f 72 6d 61 6c 69 7a 65 43 50 55 20 5b 6c 69 6e ormalizeCPU [lin
2020: 64 65 78 20 24 77 6f 72 6b 20 33 5d 5d 0a 09 09 dex $work 3]]...
2030: 09 09 73 65 74 20 70 6b 67 49 6e 66 6f 28 68 61 ..set pkgInfo(ha
2040: 73 68 29 20 20 20 20 20 5b 73 74 72 69 6e 67 20 sh) [string
2050: 74 6f 6c 6f 77 65 72 20 5b 6c 69 6e 64 65 78 20 tolower [lindex
2060: 24 77 6f 72 6b 20 34 5d 5d 0a 09 09 09 09 73 65 $work 4]].....se
2070: 74 20 70 6b 67 49 6e 66 6f 28 68 61 73 68 5f 74 t pkgInfo(hash_t
2080: 79 70 65 29 20 22 73 68 61 31 22 0a 09 09 09 09 ype) "sha1".....
2090: 73 65 74 20 70 6b 67 49 6e 66 6f 28 69 73 4c 61 set pkgInfo(isLa
20a0: 74 65 73 74 29 20 5b 65 78 70 72 20 7b 21 21 5b test) [expr {!![
20b0: 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 35 5d 7d lindex $work 5]}
20c0: 5d 0a 09 09 09 7d 5d 7d 20 7b 0a 09 09 09 09 63 ]....}]} {.....c
20d0: 6f 6e 74 69 6e 75 65 0a 09 09 09 7d 0a 0a 09 09 ontinue....}....
20e0: 09 69 66 20 7b 21 5b 5f 69 73 48 61 73 68 20 24 .if {![_isHash $
20f0: 70 6b 67 49 6e 66 6f 28 68 61 73 68 29 5d 7d 20 pkgInfo(hash)]}
2100: 7b 0a 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 {.....continue..
2110: 09 09 7d 0a 0a 09 09 09 6c 61 70 70 65 6e 64 20 ..}.....lappend
2120: 63 75 72 72 5f 70 61 63 6b 61 67 65 73 20 24 70 curr_packages $p
2130: 6b 67 49 6e 66 6f 28 68 61 73 68 29 0a 0a 09 09 kgInfo(hash)....
2140: 09 23 20 44 6f 20 6e 6f 74 20 64 6f 20 61 6e 79 .# Do not do any
2150: 20 61 64 64 69 74 69 6f 6e 61 6c 20 77 6f 72 6b additional work
2160: 20 69 66 20 77 65 20 61 6c 72 65 61 64 79 20 68 if we already h
2170: 61 76 65 20 74 68 69 73 20 70 61 63 6b 61 67 65 ave this package
2180: 0a 09 09 09 73 65 74 20 65 78 69 73 74 69 6e 67 ....set existing
2190: 5f 70 61 63 6b 61 67 65 73 20 5b 64 62 20 65 76 _packages [db ev
21a0: 61 6c 20 7b 53 45 4c 45 43 54 20 70 61 63 6b 61 al {SELECT packa
21b0: 67 65 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 ge FROM packages
21c0: 20 57 48 45 52 45 20 68 6f 73 74 6e 61 6d 65 20 WHERE hostname
21d0: 3d 20 24 68 6f 73 74 6e 61 6d 65 20 41 4e 44 20 = $hostname AND
21e0: 73 68 61 31 20 3d 20 24 70 6b 67 49 6e 66 6f 28 sha1 = $pkgInfo(
21f0: 68 61 73 68 29 3b 7d 5d 0a 09 09 09 69 66 20 7b hash);}]....if {
2200: 5b 6c 73 65 61 72 63 68 20 2d 65 78 61 63 74 20 [lsearch -exact
2210: 24 65 78 69 73 74 69 6e 67 5f 70 61 63 6b 61 67 $existing_packag
2220: 65 73 20 24 70 6b 67 49 6e 66 6f 28 70 61 63 6b es $pkgInfo(pack
2230: 61 67 65 29 5d 20 21 3d 20 2d 31 7d 20 7b 0a 09 age)] != -1} {..
2240: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 7d ...continue....}
2250: 0a 0a 09 09 09 69 66 20 7b 24 70 6b 67 49 6e 66 .....if {$pkgInf
2260: 6f 28 69 73 4c 61 74 65 73 74 29 7d 20 7b 0a 09 o(isLatest)} {..
2270: 09 09 09 64 62 20 65 76 61 6c 20 7b 55 50 44 41 ...db eval {UPDA
2280: 54 45 20 70 61 63 6b 61 67 65 73 20 53 45 54 20 TE packages SET
2290: 69 73 4c 61 74 65 73 74 20 3d 20 30 20 57 48 45 isLatest = 0 WHE
22a0: 52 45 20 68 6f 73 74 6e 61 6d 65 20 3d 20 24 68 RE hostname = $h
22b0: 6f 73 74 6e 61 6d 65 20 41 4e 44 20 70 61 63 6b ostname AND pack
22c0: 61 67 65 20 3d 20 24 70 6b 67 49 6e 66 6f 28 24 age = $pkgInfo($
22d0: 70 61 63 6b 61 67 65 29 20 41 4e 44 20 6f 73 20 package) AND os
22e0: 3d 20 24 70 6b 67 49 6e 66 6f 28 24 70 61 63 6b = $pkgInfo($pack
22f0: 61 67 65 29 20 41 4e 44 20 63 70 75 41 72 63 68 age) AND cpuArch
2300: 20 3d 20 24 70 6b 67 49 6e 66 6f 28 63 70 75 41 = $pkgInfo(cpuA
2310: 72 63 68 29 3b 7d 0a 09 09 09 7d 0a 0a 09 09 09 rch);}....}.....
2320: 64 62 20 65 76 61 6c 20 7b 49 4e 53 45 52 54 20 db eval {INSERT
2330: 49 4e 54 4f 20 70 61 63 6b 61 67 65 73 20 28 68 INTO packages (h
2340: 6f 73 74 6e 61 6d 65 2c 20 73 68 61 31 2c 20 70 ostname, sha1, p
2350: 61 63 6b 61 67 65 2c 20 76 65 72 73 69 6f 6e 2c ackage, version,
2360: 20 6f 73 2c 20 63 70 75 41 72 63 68 2c 20 69 73 os, cpuArch, is
2370: 4c 61 74 65 73 74 2c 20 68 61 76 65 4d 61 6e 69 Latest, haveMani
2380: 66 65 73 74 29 20 56 41 4c 55 45 53 20 28 24 68 fest) VALUES ($h
2390: 6f 73 74 6e 61 6d 65 2c 20 24 70 6b 67 49 6e 66 ostname, $pkgInf
23a0: 6f 28 68 61 73 68 29 2c 20 24 70 6b 67 49 6e 66 o(hash), $pkgInf
23b0: 6f 28 70 61 63 6b 61 67 65 29 2c 20 24 70 6b 67 o(package), $pkg
23c0: 49 6e 66 6f 28 76 65 72 73 69 6f 6e 29 2c 20 24 Info(version), $
23d0: 70 6b 67 49 6e 66 6f 28 6f 73 29 2c 20 24 70 6b pkgInfo(os), $pk
23e0: 67 49 6e 66 6f 28 63 70 75 41 72 63 68 29 2c 20 gInfo(cpuArch),
23f0: 24 70 6b 67 49 6e 66 6f 28 69 73 4c 61 74 65 73 $pkgInfo(isLates
2400: 74 29 2c 20 30 29 3b 7d 0a 0a 09 09 7d 0a 0a 09 t), 0);}....}...
2410: 09 23 20 4c 6f 6f 6b 20 66 6f 72 20 70 61 63 6b .# Look for pack
2420: 61 67 65 73 20 74 68 61 74 20 68 61 76 65 20 62 ages that have b
2430: 65 65 6e 20 64 65 6c 65 74 65 64 0a 09 09 73 65 een deleted...se
2440: 74 20 66 6f 75 6e 64 5f 70 61 63 6b 61 67 65 73 t found_packages
2450: 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 [db eval {SELEC
2460: 54 20 73 68 61 31 20 46 52 4f 4d 20 70 61 63 6b T sha1 FROM pack
2470: 61 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e ages WHERE hostn
2480: 61 6d 65 20 3d 20 24 68 6f 73 74 6e 61 6d 65 3b ame = $hostname;
2490: 7d 5d 0a 09 09 66 6f 72 65 61 63 68 20 70 61 63 }]...foreach pac
24a0: 6b 61 67 65 20 24 66 6f 75 6e 64 5f 70 61 63 6b kage $found_pack
24b0: 61 67 65 73 20 7b 0a 09 09 09 73 65 74 20 66 6f ages {....set fo
24c0: 75 6e 64 5f 70 61 63 6b 61 67 65 73 5f 61 72 72 und_packages_arr
24d0: 28 24 70 61 63 6b 61 67 65 29 20 31 0a 09 09 7d ($package) 1...}
24e0: 0a 0a 09 09 66 6f 72 65 61 63 68 20 70 61 63 6b ....foreach pack
24f0: 61 67 65 20 24 63 75 72 72 5f 70 61 63 6b 61 67 age $curr_packag
2500: 65 73 20 7b 0a 09 09 09 75 6e 73 65 74 20 2d 6e es {....unset -n
2510: 6f 63 6f 6d 70 6c 61 69 6e 20 66 6f 75 6e 64 5f ocomplain found_
2520: 70 61 63 6b 61 67 65 73 5f 61 72 72 28 24 70 61 packages_arr($pa
2530: 63 6b 61 67 65 29 0a 09 09 7d 0a 0a 09 09 66 6f ckage)...}....fo
2540: 72 65 61 63 68 20 70 61 63 6b 61 67 65 20 5b 61 reach package [a
2550: 72 72 61 79 20 6e 61 6d 65 73 20 66 6f 75 6e 64 rray names found
2560: 5f 70 61 63 6b 61 67 65 73 5f 61 72 72 5d 20 7b _packages_arr] {
2570: 0a 09 09 09 64 62 20 65 76 61 6c 20 7b 44 45 4c ....db eval {DEL
2580: 45 54 45 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 ETE FROM package
2590: 73 20 57 48 45 52 45 20 68 6f 73 74 6e 61 6d 65 s WHERE hostname
25a0: 20 3d 20 24 68 6f 73 74 6e 61 6d 65 20 41 4e 44 = $hostname AND
25b0: 20 73 68 61 31 20 3d 20 24 70 61 63 6b 61 67 65 sha1 = $package
25c0: 3b 7d 0a 09 09 7d 0a 0a 09 09 64 62 20 65 76 61 ;}...}....db eva
25d0: 6c 20 7b 49 4e 53 45 52 54 20 4f 52 20 52 45 50 l {INSERT OR REP
25e0: 4c 41 43 45 20 49 4e 54 4f 20 73 69 74 65 73 20 LACE INTO sites
25f0: 28 68 6f 73 74 6e 61 6d 65 2c 20 6c 61 73 74 55 (hostname, lastU
2600: 70 64 61 74 65 2c 20 74 74 6c 29 20 56 41 4c 55 pdate, ttl) VALU
2610: 45 53 20 28 24 68 6f 73 74 6e 61 6d 65 2c 20 24 ES ($hostname, $
2620: 6e 6f 77 2c 20 24 3a 3a 61 70 70 66 73 3a 3a 74 now, $::appfs::t
2630: 74 6c 29 3b 7d 0a 0a 09 09 61 70 70 66 73 64 3a tl);}....appfsd:
2640: 3a 67 65 74 5f 70 61 74 68 5f 69 6e 66 6f 5f 63 :get_path_info_c
2650: 61 63 68 65 5f 66 6c 75 73 68 0a 0a 09 09 72 65 ache_flush....re
2660: 74 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 7d turn COMPLETE..}
2670: 0a 0a 09 70 72 6f 63 20 67 65 74 70 6b 67 6d 61 ...proc getpkgma
2680: 6e 69 66 65 73 74 20 7b 68 6f 73 74 6e 61 6d 65 nifest {hostname
2690: 20 70 61 63 6b 61 67 65 5f 73 68 61 31 7d 20 7b package_sha1} {
26a0: 0a 09 09 73 65 74 20 68 61 76 65 4d 61 6e 69 66 ...set haveManif
26b0: 65 73 74 20 5b 64 62 20 6f 6e 65 63 6f 6c 75 6d est [db onecolum
26c0: 6e 20 7b 53 45 4c 45 43 54 20 68 61 76 65 4d 61 n {SELECT haveMa
26d0: 6e 69 66 65 73 74 20 46 52 4f 4d 20 70 61 63 6b nifest FROM pack
26e0: 61 67 65 73 20 57 48 45 52 45 20 73 68 61 31 20 ages WHERE sha1
26f0: 3d 20 24 70 61 63 6b 61 67 65 5f 73 68 61 31 20 = $package_sha1
2700: 4c 49 4d 49 54 20 31 3b 7d 5d 0a 0a 09 09 69 66 LIMIT 1;}]....if
2710: 20 7b 24 68 61 76 65 4d 61 6e 69 66 65 73 74 20 {$haveManifest
2720: 3d 3d 20 22 31 22 7d 20 7b 0a 09 09 09 72 65 74 == "1"} {....ret
2730: 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 09 7d urn COMPLETE...}
2740: 0a 0a 09 09 69 66 20 7b 21 5b 5f 69 73 48 61 73 ....if {![_isHas
2750: 68 20 24 70 61 63 6b 61 67 65 5f 73 68 61 31 5d h $package_sha1]
2760: 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 46 41 } {....return FA
2770: 49 4c 0a 09 09 7d 0a 0a 09 09 73 65 74 20 66 69 IL...}....set fi
2780: 6c 65 20 5b 64 6f 77 6e 6c 6f 61 64 20 24 68 6f le [download $ho
2790: 73 74 6e 61 6d 65 20 24 70 61 63 6b 61 67 65 5f stname $package_
27a0: 73 68 61 31 5d 0a 09 09 73 65 74 20 66 64 20 5b sha1]...set fd [
27b0: 6f 70 65 6e 20 24 66 69 6c 65 5d 0a 09 09 73 65 open $file]...se
27c0: 74 20 70 6b 67 64 61 74 61 20 5b 72 65 61 64 20 t pkgdata [read
27d0: 24 66 64 5d 0a 09 09 63 6c 6f 73 65 20 24 66 64 $fd]...close $fd
27e0: 0a 0a 09 09 64 62 20 74 72 61 6e 73 61 63 74 69 ....db transacti
27f0: 6f 6e 20 7b 0a 09 09 09 66 6f 72 65 61 63 68 20 on {....foreach
2800: 6c 69 6e 65 20 5b 73 70 6c 69 74 20 24 70 6b 67 line [split $pkg
2810: 64 61 74 61 20 22 5c 6e 22 5d 20 7b 0a 09 09 09 data "\n"] {....
2820: 09 73 65 74 20 6c 69 6e 65 20 5b 73 74 72 69 6e .set line [strin
2830: 67 20 74 72 69 6d 20 24 6c 69 6e 65 5d 0a 0a 09 g trim $line]...
2840: 09 09 09 69 66 20 7b 24 6c 69 6e 65 20 3d 3d 20 ...if {$line ==
2850: 22 22 7d 20 7b 0a 09 09 09 09 09 63 6f 6e 74 69 ""} {......conti
2860: 6e 75 65 0a 09 09 09 09 7d 0a 0a 09 09 09 09 73 nue.....}......s
2870: 65 74 20 77 6f 72 6b 20 5b 73 70 6c 69 74 20 24 et work [split $
2880: 6c 69 6e 65 20 22 2c 22 5d 0a 0a 09 09 09 09 75 line ","]......u
2890: 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e nset -nocomplain
28a0: 20 66 69 6c 65 49 6e 66 6f 0a 09 09 09 09 73 65 fileInfo.....se
28b0: 74 20 66 69 6c 65 49 6e 66 6f 28 74 79 70 65 29 t fileInfo(type)
28c0: 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 30 [lindex $work 0
28d0: 5d 0a 09 09 09 09 73 65 74 20 66 69 6c 65 49 6e ].....set fileIn
28e0: 66 6f 28 74 69 6d 65 29 20 5b 6c 69 6e 64 65 78 fo(time) [lindex
28f0: 20 24 77 6f 72 6b 20 31 5d 0a 0a 09 09 09 09 73 $work 1]......s
2900: 65 74 20 77 6f 72 6b 20 5b 6c 72 61 6e 67 65 20 et work [lrange
2910: 24 77 6f 72 6b 20 32 20 65 6e 64 5d 0a 09 09 09 $work 2 end]....
2920: 09 73 77 69 74 63 68 20 2d 2d 20 24 66 69 6c 65 .switch -- $file
2930: 49 6e 66 6f 28 74 79 70 65 29 20 7b 0a 09 09 09 Info(type) {....
2940: 09 09 22 23 6d 61 6e 69 66 65 73 74 6d 65 74 61 .."#manifestmeta
2950: 64 61 74 61 22 20 7b 0a 09 09 09 09 09 09 75 6e data" {.......un
2960: 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 set -nocomplain
2970: 66 69 6c 65 49 6e 66 6f 0a 09 09 09 09 09 09 63 fileInfo.......c
2980: 6f 6e 74 69 6e 75 65 0a 09 09 09 09 09 7d 0a 09 ontinue......}..
2990: 09 09 09 09 22 66 69 6c 65 22 20 7b 0a 09 09 09 ...."file" {....
29a0: 09 09 09 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 ...set fileInfo(
29b0: 73 69 7a 65 29 20 5b 6c 69 6e 64 65 78 20 24 77 size) [lindex $w
29c0: 6f 72 6b 20 30 5d 0a 09 09 09 09 09 09 73 65 74 ork 0].......set
29d0: 20 66 69 6c 65 49 6e 66 6f 28 70 65 72 6d 73 29 fileInfo(perms)
29e0: 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 31 [lindex $work 1
29f0: 5d 0a 09 09 09 09 09 09 73 65 74 20 66 69 6c 65 ].......set file
2a00: 49 6e 66 6f 28 73 68 61 31 29 20 5b 6c 69 6e 64 Info(sha1) [lind
2a10: 65 78 20 24 77 6f 72 6b 20 32 5d 0a 0a 09 09 09 ex $work 2].....
2a20: 09 09 09 73 65 74 20 77 6f 72 6b 20 5b 6c 72 61 ...set work [lra
2a30: 6e 67 65 20 24 77 6f 72 6b 20 33 20 65 6e 64 5d nge $work 3 end]
2a40: 0a 09 09 09 09 09 7d 0a 09 09 09 09 09 22 73 79 ......}......"sy
2a50: 6d 6c 69 6e 6b 22 20 7b 0a 09 09 09 09 09 09 73 mlink" {.......s
2a60: 65 74 20 66 69 6c 65 49 6e 66 6f 28 73 6f 75 72 et fileInfo(sour
2a70: 63 65 29 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 ce) [lindex $wor
2a80: 6b 20 30 5d 0a 09 09 09 09 09 09 73 65 74 20 77 k 0].......set w
2a90: 6f 72 6b 20 5b 6c 72 61 6e 67 65 20 24 77 6f 72 ork [lrange $wor
2aa0: 6b 20 31 20 65 6e 64 5d 0a 09 09 09 09 09 7d 0a k 1 end]......}.
2ab0: 09 09 09 09 09 22 64 69 72 65 63 74 6f 72 79 22 ....."directory"
2ac0: 20 7b 0a 09 09 09 09 09 09 23 20 4e 6f 20 65 78 {.......# No ex
2ad0: 74 72 61 20 64 61 74 61 20 72 65 71 75 69 72 65 tra data require
2ae0: 64 0a 09 09 09 09 09 7d 0a 09 09 09 09 09 64 65 d......}......de
2af0: 66 61 75 6c 74 20 7b 0a 09 09 09 09 09 09 23 20 fault {.......#
2b00: 48 61 6e 64 6c 65 20 75 6e 6b 6e 6f 77 6e 20 74 Handle unknown t
2b10: 79 70 65 73 0a 09 09 09 09 09 09 69 66 20 7b 5b ypes.......if {[
2b20: 73 74 72 69 6e 67 20 69 6e 64 65 78 20 24 66 69 string index $fi
2b30: 6c 65 49 6e 66 6f 28 74 79 70 65 29 20 30 5d 20 leInfo(type) 0]
2b40: 3d 3d 20 22 23 22 7d 20 7b 0a 09 09 09 09 09 09 == "#"} {.......
2b50: 09 23 20 4d 65 74 61 64 61 74 61 20 74 79 70 65 .# Metadata type
2b60: 2c 20 69 67 6e 6f 72 65 0a 09 09 09 09 09 09 09 , ignore........
2b70: 23 20 69 74 20 69 66 20 77 65 20 64 6f 6e 27 74 # it if we don't
2b80: 0a 09 09 09 09 09 09 09 23 20 75 6e 64 65 72 73 ........# unders
2b90: 74 61 6e 64 20 74 68 69 73 20 74 79 70 65 0a 09 tand this type..
2ba0: 09 09 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 ......continue..
2bb0: 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 .....} else {...
2bc0: 09 09 09 09 09 23 20 55 6e 6b 6e 6f 77 6e 20 74 .....# Unknown t
2bd0: 79 70 65 2c 0a 09 09 09 09 09 09 09 23 20 67 65 ype,........# ge
2be0: 6e 65 72 61 74 65 20 61 6e 20 65 72 72 6f 72 0a nerate an error.
2bf0: 09 09 09 09 09 09 09 65 72 72 6f 72 20 22 4d 61 .......error "Ma
2c00: 6e 69 66 65 73 74 20 63 61 6e 6e 6f 74 20 62 65 nifest cannot be
2c10: 20 70 61 72 73 65 64 22 0a 09 09 09 09 09 09 7d parsed".......}
2c20: 0a 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 0a 09 ......}.....}...
2c30: 09 09 09 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 ...set fileInfo(
2c40: 6e 61 6d 65 29 20 5b 6a 6f 69 6e 20 24 77 6f 72 name) [join $wor
2c50: 6b 20 22 2c 22 5d 0a 09 09 09 09 73 65 74 20 66 k ","].....set f
2c60: 69 6c 65 49 6e 66 6f 28 6e 61 6d 65 29 20 5b 73 ileInfo(name) [s
2c70: 70 6c 69 74 20 5b 73 74 72 69 6e 67 20 74 72 69 plit [string tri
2c80: 6d 20 24 66 69 6c 65 49 6e 66 6f 28 6e 61 6d 65 m $fileInfo(name
2c90: 29 20 22 2f 22 5d 20 22 2f 22 5d 0a 09 09 09 09 ) "/"] "/"].....
2ca0: 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 64 69 72 set fileInfo(dir
2cb0: 65 63 74 6f 72 79 29 20 5b 6a 6f 69 6e 20 5b 6c ectory) [join [l
2cc0: 72 61 6e 67 65 20 24 66 69 6c 65 49 6e 66 6f 28 range $fileInfo(
2cd0: 6e 61 6d 65 29 20 30 20 65 6e 64 2d 31 5d 20 22 name) 0 end-1] "
2ce0: 2f 22 5d 0a 09 09 09 09 73 65 74 20 66 69 6c 65 /"].....set file
2cf0: 49 6e 66 6f 28 6e 61 6d 65 29 20 5b 6c 69 6e 64 Info(name) [lind
2d00: 65 78 20 24 66 69 6c 65 49 6e 66 6f 28 6e 61 6d ex $fileInfo(nam
2d10: 65 29 20 65 6e 64 5d 0a 0a 09 09 09 09 64 62 20 e) end]......db
2d20: 65 76 61 6c 20 7b 49 4e 53 45 52 54 20 49 4e 54 eval {INSERT INT
2d30: 4f 20 66 69 6c 65 73 20 28 70 61 63 6b 61 67 65 O files (package
2d40: 5f 73 68 61 31 2c 20 74 79 70 65 2c 20 74 69 6d _sha1, type, tim
2d50: 65 2c 20 73 6f 75 72 63 65 2c 20 73 69 7a 65 2c e, source, size,
2d60: 20 70 65 72 6d 73 2c 20 66 69 6c 65 5f 73 68 61 perms, file_sha
2d70: 31 2c 20 66 69 6c 65 5f 6e 61 6d 65 2c 20 66 69 1, file_name, fi
2d80: 6c 65 5f 64 69 72 65 63 74 6f 72 79 29 20 56 41 le_directory) VA
2d90: 4c 55 45 53 20 28 24 70 61 63 6b 61 67 65 5f 73 LUES ($package_s
2da0: 68 61 31 2c 20 24 66 69 6c 65 49 6e 66 6f 28 74 ha1, $fileInfo(t
2db0: 79 70 65 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28 ype), $fileInfo(
2dc0: 74 69 6d 65 29 2c 20 24 66 69 6c 65 49 6e 66 6f time), $fileInfo
2dd0: 28 73 6f 75 72 63 65 29 2c 20 24 66 69 6c 65 49 (source), $fileI
2de0: 6e 66 6f 28 73 69 7a 65 29 2c 20 24 66 69 6c 65 nfo(size), $file
2df0: 49 6e 66 6f 28 70 65 72 6d 73 29 2c 20 24 66 69 Info(perms), $fi
2e00: 6c 65 49 6e 66 6f 28 73 68 61 31 29 2c 20 24 66 leInfo(sha1), $f
2e10: 69 6c 65 49 6e 66 6f 28 6e 61 6d 65 29 2c 20 24 ileInfo(name), $
2e20: 66 69 6c 65 49 6e 66 6f 28 64 69 72 65 63 74 6f fileInfo(directo
2e30: 72 79 29 20 29 3b 7d 0a 09 09 09 09 64 62 20 65 ry) );}.....db e
2e40: 76 61 6c 20 7b 55 50 44 41 54 45 20 70 61 63 6b val {UPDATE pack
2e50: 61 67 65 73 20 53 45 54 20 68 61 76 65 4d 61 6e ages SET haveMan
2e60: 69 66 65 73 74 20 3d 20 31 20 57 48 45 52 45 20 ifest = 1 WHERE
2e70: 73 68 61 31 20 3d 20 24 70 61 63 6b 61 67 65 5f sha1 = $package_
2e80: 73 68 61 31 3b 7d 0a 09 09 09 7d 0a 09 09 7d 0a sha1;}....}...}.
2e90: 0a 09 09 61 70 70 66 73 64 3a 3a 67 65 74 5f 70 ...appfsd::get_p
2ea0: 61 74 68 5f 69 6e 66 6f 5f 63 61 63 68 65 5f 66 ath_info_cache_f
2eb0: 6c 75 73 68 0a 0a 09 09 72 65 74 75 72 6e 20 43 lush....return C
2ec0: 4f 4d 50 4c 45 54 45 0a 09 7d 0a 0a 09 70 72 6f OMPLETE..}...pro
2ed0: 63 20 5f 6c 6f 63 61 6c 70 61 74 68 20 7b 70 61 c _localpath {pa
2ee0: 63 6b 61 67 65 20 68 6f 73 74 6e 61 6d 65 20 66 ckage hostname f
2ef0: 69 6c 65 7d 20 7b 0a 09 09 73 65 74 20 64 69 72 ile} {...set dir
2f00: 20 22 22 0a 09 09 63 61 74 63 68 20 7b 0a 09 09 ""...catch {...
2f10: 09 73 65 74 20 68 6f 6d 65 64 69 72 20 5b 3a 3a .set homedir [::
2f20: 61 70 70 66 73 3a 3a 75 73 65 72 3a 3a 67 65 74 appfs::user::get
2f30: 5f 68 6f 6d 65 64 69 72 5d 0a 09 09 09 73 65 74 _homedir]....set
2f40: 20 64 69 72 20 5b 66 69 6c 65 20 6a 6f 69 6e 20 dir [file join
2f50: 24 68 6f 6d 65 64 69 72 20 2e 61 70 70 66 73 20 $homedir .appfs
2f60: 22 2e 2f 24 7b 70 61 63 6b 61 67 65 7d 40 24 7b "./${package}@${
2f70: 68 6f 73 74 6e 61 6d 65 7d 22 20 22 2e 2f 24 7b hostname}" "./${
2f80: 66 69 6c 65 7d 22 5d 0a 09 09 7d 0a 09 09 72 65 file}"]...}...re
2f90: 74 75 72 6e 20 24 64 69 72 0a 09 7d 0a 0a 09 70 turn $dir..}...p
2fa0: 72 6f 63 20 5f 77 68 69 74 65 6f 75 74 70 61 74 roc _whiteoutpat
2fb0: 68 20 7b 70 61 63 6b 61 67 65 20 68 6f 73 74 6e h {package hostn
2fc0: 61 6d 65 20 66 69 6c 65 7d 20 7b 0a 09 09 73 65 ame file} {...se
2fd0: 74 20 64 69 72 20 22 22 0a 09 09 63 61 74 63 68 t dir ""...catch
2fe0: 20 7b 0a 09 09 09 73 65 74 20 68 6f 6d 65 64 69 {....set homedi
2ff0: 72 20 5b 3a 3a 61 70 70 66 73 3a 3a 75 73 65 72 r [::appfs::user
3000: 3a 3a 67 65 74 5f 68 6f 6d 65 64 69 72 5d 0a 09 ::get_homedir]..
3010: 09 09 73 65 74 20 64 69 72 20 5b 66 69 6c 65 20 ..set dir [file
3020: 6a 6f 69 6e 20 24 68 6f 6d 65 64 69 72 20 2e 61 join $homedir .a
3030: 70 70 66 73 20 22 2e 2f 24 7b 70 61 63 6b 61 67 ppfs "./${packag
3040: 65 7d 40 24 7b 68 6f 73 74 6e 61 6d 65 7d 22 20 e}@${hostname}"
3050: 22 2e 41 50 50 46 53 2e 57 48 49 54 45 4f 55 54 ".APPFS.WHITEOUT
3060: 22 20 22 2e 2f 24 7b 66 69 6c 65 7d 2e 41 50 50 " "./${file}.APP
3070: 46 53 2e 57 48 49 54 45 4f 55 54 22 5d 0a 09 09 FS.WHITEOUT"]...
3080: 7d 0a 09 09 72 65 74 75 72 6e 20 24 64 69 72 0a }...return $dir.
3090: 09 7d 0a 0a 09 70 72 6f 63 20 5f 70 61 72 73 65 .}...proc _parse
30a0: 70 61 74 68 20 7b 70 61 74 68 7d 20 7b 0a 09 09 path {path} {...
30b0: 73 65 74 20 70 61 74 68 20 5b 73 74 72 69 6e 67 set path [string
30c0: 20 74 72 69 6d 20 24 70 61 74 68 20 22 2f 22 5d trim $path "/"]
30d0: 0a 09 09 73 65 74 20 70 61 74 68 20 5b 73 70 6c ...set path [spl
30e0: 69 74 20 24 70 61 74 68 20 22 2f 22 5d 0a 09 09 it $path "/"]...
30f0: 73 65 74 20 70 61 74 68 6c 65 6e 20 5b 6c 6c 65 set pathlen [lle
3100: 6e 67 74 68 20 24 70 61 74 68 5d 0a 0a 09 09 61 ngth $path]....a
3110: 72 72 61 79 20 73 65 74 20 72 65 74 76 61 6c 20 rray set retval
3120: 5b 6c 69 73 74 20 5f 63 68 69 6c 64 72 65 6e 20 [list _children
3130: 73 69 74 65 73 20 5f 74 79 70 65 20 74 6f 70 6c sites _type topl
3140: 65 76 65 6c 5d 0a 0a 09 09 69 66 20 7b 24 70 61 evel]....if {$pa
3150: 74 68 6c 65 6e 20 3e 20 30 7d 20 7b 0a 09 09 09 thlen > 0} {....
3160: 73 65 74 20 72 65 74 76 61 6c 28 68 6f 73 74 6e set retval(hostn
3170: 61 6d 65 29 20 5b 6c 69 6e 64 65 78 20 24 70 61 ame) [lindex $pa
3180: 74 68 20 30 5d 0a 09 09 09 73 65 74 20 72 65 74 th 0]....set ret
3190: 76 61 6c 28 5f 63 68 69 6c 64 72 65 6e 29 20 70 val(_children) p
31a0: 61 63 6b 61 67 65 73 0a 09 09 09 73 65 74 20 72 ackages....set r
31b0: 65 74 76 61 6c 28 5f 74 79 70 65 29 20 73 69 74 etval(_type) sit
31c0: 65 73 0a 0a 09 09 09 69 66 20 7b 24 70 61 74 68 es.....if {$path
31d0: 6c 65 6e 20 3e 20 31 7d 20 7b 0a 09 09 09 09 73 len > 1} {.....s
31e0: 65 74 20 70 61 63 6b 61 67 65 20 5b 6c 69 6e 64 et package [lind
31f0: 65 78 20 24 70 61 74 68 20 31 5d 0a 09 09 09 09 ex $path 1].....
3200: 69 66 20 7b 5b 73 74 72 69 6e 67 20 6c 65 6e 67 if {[string leng
3210: 74 68 20 24 70 61 63 6b 61 67 65 5d 20 3d 3d 20 th $package] ==
3220: 22 34 30 22 20 26 26 20 5b 72 65 67 65 78 70 20 "40" && [regexp
3230: 7b 5e 5b 61 2d 66 41 2d 46 30 2d 39 5d 2a 24 7d {^[a-fA-F0-9]*$}
3240: 20 24 70 61 63 6b 61 67 65 5d 7d 20 7b 0a 09 09 $package]} {...
3250: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 70 61 ...set retval(pa
3260: 63 6b 61 67 65 5f 73 68 61 31 29 20 24 70 61 63 ckage_sha1) $pac
3270: 6b 61 67 65 0a 09 09 09 09 09 73 65 74 20 72 65 kage......set re
3280: 74 76 61 6c 28 5f 63 68 69 6c 64 72 65 6e 29 20 tval(_children)
3290: 66 69 6c 65 73 0a 09 09 09 09 09 73 65 74 20 72 files......set r
32a0: 65 74 76 61 6c 28 5f 74 79 70 65 29 20 66 69 6c etval(_type) fil
32b0: 65 73 0a 0a 09 09 09 09 09 3a 3a 61 70 70 66 73 es.......::appfs
32c0: 3a 3a 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 ::db eval {SELEC
32d0: 54 20 70 61 63 6b 61 67 65 2c 20 6f 73 2c 20 63 T package, os, c
32e0: 70 75 41 72 63 68 2c 20 76 65 72 73 69 6f 6e 20 puArch, version
32f0: 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 20 57 48 FROM packages WH
3300: 45 52 45 20 73 68 61 31 20 3d 20 24 72 65 74 76 ERE sha1 = $retv
3310: 61 6c 28 70 61 63 6b 61 67 65 5f 73 68 61 31 29 al(package_sha1)
3320: 3b 7d 20 70 6b 67 69 6e 66 6f 20 7b 7d 0a 09 09 ;} pkginfo {}...
3330: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 70 61 ...set retval(pa
3340: 63 6b 61 67 65 29 20 24 70 6b 67 69 6e 66 6f 28 ckage) $pkginfo(
3350: 70 61 63 6b 61 67 65 29 0a 09 09 09 09 09 73 65 package)......se
3360: 74 20 72 65 74 76 61 6c 28 6f 73 29 20 24 70 6b t retval(os) $pk
3370: 67 69 6e 66 6f 28 6f 73 29 0a 09 09 09 09 09 73 ginfo(os)......s
3380: 65 74 20 72 65 74 76 61 6c 28 63 70 75 29 20 24 et retval(cpu) $
3390: 70 6b 67 69 6e 66 6f 28 63 70 75 41 72 63 68 29 pkginfo(cpuArch)
33a0: 0a 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
33b0: 28 76 65 72 73 69 6f 6e 29 20 24 70 6b 67 69 6e (version) $pkgin
33c0: 66 6f 28 76 65 72 73 69 6f 6e 29 0a 0a 09 09 09 fo(version).....
33d0: 09 09 69 66 20 7b 24 70 61 74 68 6c 65 6e 20 3e ..if {$pathlen >
33e0: 20 32 7d 20 7b 0a 09 09 09 09 09 09 73 65 74 20 2} {.......set
33f0: 72 65 74 76 61 6c 28 66 69 6c 65 29 20 5b 6a 6f retval(file) [jo
3400: 69 6e 20 5b 6c 72 61 6e 67 65 20 24 70 61 74 68 in [lrange $path
3410: 20 32 20 65 6e 64 5d 20 22 2f 22 5d 0a 09 09 09 2 end] "/"]....
3420: 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 ..} else {......
3430: 09 73 65 74 20 72 65 74 76 61 6c 28 66 69 6c 65 .set retval(file
3440: 29 20 22 22 0a 09 09 09 09 09 7d 0a 09 09 09 09 ) ""......}.....
3450: 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 73 65 } else {......se
3460: 74 20 72 65 74 76 61 6c 28 70 61 63 6b 61 67 65 t retval(package
3470: 29 20 24 70 61 63 6b 61 67 65 0a 09 09 09 09 09 ) $package......
3480: 73 65 74 20 72 65 74 76 61 6c 28 5f 63 68 69 6c set retval(_chil
3490: 64 72 65 6e 29 20 6f 73 2d 63 70 75 0a 09 09 09 dren) os-cpu....
34a0: 09 09 73 65 74 20 72 65 74 76 61 6c 28 5f 74 79 ..set retval(_ty
34b0: 70 65 29 20 70 61 63 6b 61 67 65 73 0a 0a 09 09 pe) packages....
34c0: 09 09 09 69 66 20 7b 24 70 61 74 68 6c 65 6e 20 ...if {$pathlen
34d0: 3e 20 32 7d 20 7b 0a 09 09 09 09 09 09 73 65 74 > 2} {.......set
34e0: 20 6f 73 5f 63 70 75 20 5b 6c 69 6e 64 65 78 20 os_cpu [lindex
34f0: 24 70 61 74 68 20 32 5d 0a 09 09 09 09 09 09 73 $path 2].......s
3500: 65 74 20 6f 73 5f 63 70 75 20 5b 73 70 6c 69 74 et os_cpu [split
3510: 20 24 6f 73 5f 63 70 75 20 22 2d 22 5d 0a 0a 09 $os_cpu "-"]...
3520: 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
3530: 6f 73 29 20 5b 6c 69 6e 64 65 78 20 24 6f 73 5f os) [lindex $os_
3540: 63 70 75 20 30 5d 0a 09 09 09 09 09 09 73 65 74 cpu 0].......set
3550: 20 72 65 74 76 61 6c 28 63 70 75 29 20 5b 6c 69 retval(cpu) [li
3560: 6e 64 65 78 20 24 6f 73 5f 63 70 75 20 31 5d 0a ndex $os_cpu 1].
3570: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
3580: 28 5f 63 68 69 6c 64 72 65 6e 29 20 76 65 72 73 (_children) vers
3590: 69 6f 6e 73 0a 09 09 09 09 09 09 73 65 74 20 72 ions.......set r
35a0: 65 74 76 61 6c 28 5f 74 79 70 65 29 20 6f 73 2d etval(_type) os-
35b0: 63 70 75 0a 0a 09 09 09 09 09 09 69 66 20 7b 24 cpu........if {$
35c0: 70 61 74 68 6c 65 6e 20 3e 20 33 7d 20 7b 0a 09 pathlen > 3} {..
35d0: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
35e0: 28 76 65 72 73 69 6f 6e 29 20 5b 6c 69 6e 64 65 (version) [linde
35f0: 78 20 24 70 61 74 68 20 33 5d 0a 09 09 09 09 09 x $path 3]......
3600: 09 09 73 65 74 20 72 65 74 76 61 6c 28 5f 63 68 ..set retval(_ch
3610: 69 6c 64 72 65 6e 29 20 66 69 6c 65 73 0a 09 09 ildren) files...
3620: 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
3630: 5f 74 79 70 65 29 20 76 65 72 73 69 6f 6e 73 0a _type) versions.
3640: 0a 09 09 09 09 09 09 09 73 65 74 20 72 65 74 76 ........set retv
3650: 61 6c 28 70 61 63 6b 61 67 65 5f 73 68 61 31 29 al(package_sha1)
3660: 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 6f 6e [::appfs::db on
3670: 65 63 6f 6c 75 6d 6e 20 7b 53 45 4c 45 43 54 20 ecolumn {SELECT
3680: 73 68 61 31 20 46 52 4f 4d 20 70 61 63 6b 61 67 sha1 FROM packag
3690: 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e 61 6d es WHERE hostnam
36a0: 65 20 3d 20 24 72 65 74 76 61 6c 28 68 6f 73 74 e = $retval(host
36b0: 6e 61 6d 65 29 20 41 4e 44 20 70 61 63 6b 61 67 name) AND packag
36c0: 65 20 3d 20 24 72 65 74 76 61 6c 28 70 61 63 6b e = $retval(pack
36d0: 61 67 65 29 20 41 4e 44 20 6f 73 20 3d 20 24 72 age) AND os = $r
36e0: 65 74 76 61 6c 28 6f 73 29 20 41 4e 44 20 63 70 etval(os) AND cp
36f0: 75 41 72 63 68 20 3d 20 24 72 65 74 76 61 6c 28 uArch = $retval(
3700: 63 70 75 29 20 41 4e 44 20 76 65 72 73 69 6f 6e cpu) AND version
3710: 20 3d 20 24 72 65 74 76 61 6c 28 76 65 72 73 69 = $retval(versi
3720: 6f 6e 29 3b 7d 5d 0a 09 09 09 09 09 09 09 69 66 on);}]........if
3730: 20 7b 24 72 65 74 76 61 6c 28 70 61 63 6b 61 67 {$retval(packag
3740: 65 5f 73 68 61 31 29 20 3d 3d 20 22 22 7d 20 7b e_sha1) == ""} {
3750: 0a 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 .........set ret
3760: 76 61 6c 28 5f 63 68 69 6c 64 72 65 6e 29 20 64 val(_children) d
3770: 65 61 64 0a 09 09 09 09 09 09 09 09 72 65 74 75 ead.........retu
3780: 72 6e 20 5b 61 72 72 61 79 20 67 65 74 20 72 65 rn [array get re
3790: 74 76 61 6c 5d 0a 09 09 09 09 09 09 09 7d 0a 0a tval]........}..
37a0: 09 09 09 09 09 09 09 69 66 20 7b 24 70 61 74 68 .......if {$path
37b0: 6c 65 6e 20 3e 20 34 7d 20 7b 0a 09 09 09 09 09 len > 4} {......
37c0: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 5f 74 ...set retval(_t
37d0: 79 70 65 29 20 66 69 6c 65 73 0a 09 09 09 09 09 ype) files......
37e0: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 66 69 ...set retval(fi
37f0: 6c 65 29 20 5b 6a 6f 69 6e 20 5b 6c 72 61 6e 67 le) [join [lrang
3800: 65 20 24 70 61 74 68 20 34 20 65 6e 64 5d 20 22 e $path 4 end] "
3810: 2f 22 5d 0a 09 09 09 09 09 09 09 7d 20 65 6c 73 /"]........} els
3820: 65 20 7b 0a 09 09 09 09 09 09 09 09 73 65 74 20 e {.........set
3830: 72 65 74 76 61 6c 28 5f 74 79 70 65 29 20 66 69 retval(_type) fi
3840: 6c 65 73 0a 09 09 09 09 09 09 09 09 73 65 74 20 les.........set
3850: 72 65 74 76 61 6c 28 66 69 6c 65 29 20 22 22 0a retval(file) "".
3860: 09 09 09 09 09 09 09 7d 0a 09 09 09 09 09 09 7d .......}.......}
3870: 0a 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 09 09 ......}.....}...
3880: 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e .}...}....return
3890: 20 5b 61 72 72 61 79 20 67 65 74 20 72 65 74 76 [array get retv
38a0: 61 6c 5d 0a 09 7d 0a 0a 09 70 72 6f 63 20 67 65 al]..}...proc ge
38b0: 74 63 68 69 6c 64 72 65 6e 20 7b 64 69 72 7d 20 tchildren {dir}
38c0: 7b 0a 09 09 61 72 72 61 79 20 73 65 74 20 70 61 {...array set pa
38d0: 74 68 69 6e 66 6f 20 5b 5f 70 61 72 73 65 70 61 thinfo [_parsepa
38e0: 74 68 20 24 64 69 72 5d 0a 0a 09 09 73 77 69 74 th $dir]....swit
38f0: 63 68 20 2d 2d 20 24 70 61 74 68 69 6e 66 6f 28 ch -- $pathinfo(
3900: 5f 63 68 69 6c 64 72 65 6e 29 20 7b 0a 09 09 09 _children) {....
3910: 22 73 69 74 65 73 22 20 7b 0a 09 09 09 09 72 65 "sites" {.....re
3920: 74 75 72 6e 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 turn [::appfs::d
3930: 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 44 b eval {SELECT D
3940: 49 53 54 49 4e 43 54 20 68 6f 73 74 6e 61 6d 65 ISTINCT hostname
3950: 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 3b 7d FROM packages;}
3960: 5d 0a 09 09 09 7d 0a 09 09 09 22 70 61 63 6b 61 ]....}...."packa
3970: 67 65 73 22 20 7b 0a 09 09 09 09 63 61 74 63 68 ges" {.....catch
3980: 20 7b 0a 09 09 09 09 09 3a 3a 61 70 70 66 73 3a {......::appfs:
3990: 3a 67 65 74 69 6e 64 65 78 20 24 70 61 74 68 69 :getindex $pathi
39a0: 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 0a 09 09 nfo(hostname)...
39b0: 09 09 7d 0a 0a 09 09 09 09 72 65 74 75 72 6e 20 ..}......return
39c0: 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 65 76 61 [::appfs::db eva
39d0: 6c 20 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e l {SELECT DISTIN
39e0: 43 54 20 70 61 63 6b 61 67 65 20 46 52 4f 4d 20 CT package FROM
39f0: 70 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 68 packages WHERE h
3a00: 6f 73 74 6e 61 6d 65 20 3d 20 24 70 61 74 68 69 ostname = $pathi
3a10: 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 3b 7d 5d nfo(hostname);}]
3a20: 0a 09 09 09 7d 0a 09 09 09 22 6f 73 2d 63 70 75 ....}...."os-cpu
3a30: 22 20 7b 0a 09 09 09 09 73 65 74 20 72 65 74 76 " {.....set retv
3a40: 61 6c 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 al [::appfs::db
3a50: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 44 49 53 eval {SELECT DIS
3a60: 54 49 4e 43 54 20 6f 73 20 7c 7c 20 22 2d 22 20 TINCT os || "-"
3a70: 7c 7c 20 63 70 75 41 72 63 68 20 46 52 4f 4d 20 || cpuArch FROM
3a80: 70 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 68 packages WHERE h
3a90: 6f 73 74 6e 61 6d 65 20 3d 20 24 70 61 74 68 69 ostname = $pathi
3aa0: 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 41 4e nfo(hostname) AN
3ab0: 44 20 70 61 63 6b 61 67 65 20 3d 20 24 70 61 74 D package = $pat
3ac0: 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 3b 7d hinfo(package);}
3ad0: 5d 0a 0a 09 09 09 09 6c 61 70 70 65 6e 64 20 72 ]......lappend r
3ae0: 65 74 76 61 6c 20 22 70 6c 61 74 66 6f 72 6d 22 etval "platform"
3af0: 0a 0a 09 09 09 09 72 65 74 75 72 6e 20 24 72 65 ......return $re
3b00: 74 76 61 6c 0a 09 09 09 7d 0a 09 09 09 22 76 65 tval....}...."ve
3b10: 72 73 69 6f 6e 73 22 20 7b 0a 09 09 09 09 73 65 rsions" {.....se
3b20: 74 20 72 65 74 76 61 6c 20 5b 3a 3a 61 70 70 66 t retval [::appf
3b30: 73 3a 3a 64 62 20 65 76 61 6c 20 7b 0a 09 09 09 s::db eval {....
3b40: 09 09 53 45 4c 45 43 54 20 44 49 53 54 49 4e 43 ..SELECT DISTINC
3b50: 54 20 76 65 72 73 69 6f 6e 20 46 52 4f 4d 20 70 T version FROM p
3b60: 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 68 6f ackages WHERE ho
3b70: 73 74 6e 61 6d 65 20 3d 20 24 70 61 74 68 69 6e stname = $pathin
3b80: 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 41 4e 44 fo(hostname) AND
3b90: 20 70 61 63 6b 61 67 65 20 3d 20 24 70 61 74 68 package = $path
3ba0: 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 20 41 4e info(package) AN
3bb0: 44 20 6f 73 20 3d 20 24 70 61 74 68 69 6e 66 6f D os = $pathinfo
3bc0: 28 6f 73 29 20 41 4e 44 20 63 70 75 41 72 63 68 (os) AND cpuArch
3bd0: 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 63 70 75 = $pathinfo(cpu
3be0: 29 3b 0a 09 09 09 09 7d 5d 0a 0a 09 09 09 09 3a );.....}]......:
3bf0: 3a 61 70 70 66 73 3a 3a 64 62 20 65 76 61 6c 20 :appfs::db eval
3c00: 7b 53 45 4c 45 43 54 20 76 65 72 73 69 6f 6e 20 {SELECT version
3c10: 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 20 57 48 FROM packages WH
3c20: 45 52 45 20 69 73 4c 61 74 65 73 74 20 3d 20 31 ERE isLatest = 1
3c30: 20 41 4e 44 20 68 6f 73 74 6e 61 6d 65 20 3d 20 AND hostname =
3c40: 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 $pathinfo(hostna
3c50: 6d 65 29 20 41 4e 44 20 70 61 63 6b 61 67 65 20 me) AND package
3c60: 3d 20 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b = $pathinfo(pack
3c70: 61 67 65 29 20 41 4e 44 20 6f 73 20 3d 20 24 70 age) AND os = $p
3c80: 61 74 68 69 6e 66 6f 28 6f 73 29 20 41 4e 44 20 athinfo(os) AND
3c90: 63 70 75 41 72 63 68 20 3d 20 24 70 61 74 68 69 cpuArch = $pathi
3ca0: 6e 66 6f 28 63 70 75 29 20 4c 49 4d 49 54 20 31 nfo(cpu) LIMIT 1
3cb0: 3b 7d 20 6c 61 74 65 73 74 5f 69 6e 66 6f 20 7b ;} latest_info {
3cc0: 7d 0a 0a 09 09 09 09 69 66 20 7b 5b 69 6e 66 6f }......if {[info
3cd0: 20 65 78 69 73 74 73 20 6c 61 74 65 73 74 5f 69 exists latest_i
3ce0: 6e 66 6f 28 76 65 72 73 69 6f 6e 29 5d 7d 20 7b nfo(version)]} {
3cf0: 0a 09 09 09 09 09 6c 61 70 70 65 6e 64 20 72 65 ......lappend re
3d00: 74 76 61 6c 20 22 6c 61 74 65 73 74 22 0a 09 09 tval "latest"...
3d10: 09 09 7d 0a 0a 09 09 09 09 72 65 74 75 72 6e 20 ..}......return
3d20: 24 72 65 74 76 61 6c 0a 09 09 09 7d 0a 09 09 09 $retval....}....
3d30: 22 66 69 6c 65 73 22 20 7b 0a 09 09 09 09 63 61 "files" {.....ca
3d40: 74 63 68 20 7b 0a 09 09 09 09 09 3a 3a 61 70 70 tch {......::app
3d50: 66 73 3a 3a 67 65 74 69 6e 64 65 78 20 24 70 61 fs::getindex $pa
3d60: 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 thinfo(hostname)
3d70: 0a 09 09 09 09 09 3a 3a 61 70 70 66 73 3a 3a 67 ......::appfs::g
3d80: 65 74 70 6b 67 6d 61 6e 69 66 65 73 74 20 24 70 etpkgmanifest $p
3d90: 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 athinfo(hostname
3da0: 29 20 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b ) $pathinfo(pack
3db0: 61 67 65 5f 73 68 61 31 29 0a 09 09 09 09 7d 0a age_sha1).....}.
3dc0: 0a 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 20 .....set retval
3dd0: 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 65 76 61 [::appfs::db eva
3de0: 6c 20 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e l {SELECT DISTIN
3df0: 43 54 20 66 69 6c 65 5f 6e 61 6d 65 20 46 52 4f CT file_name FRO
3e00: 4d 20 66 69 6c 65 73 20 57 48 45 52 45 20 70 61 M files WHERE pa
3e10: 63 6b 61 67 65 5f 73 68 61 31 20 3d 20 24 70 61 ckage_sha1 = $pa
3e20: 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 5f 73 thinfo(package_s
3e30: 68 61 31 29 20 41 4e 44 20 66 69 6c 65 5f 64 69 ha1) AND file_di
3e40: 72 65 63 74 6f 72 79 20 3d 20 24 70 61 74 68 69 rectory = $pathi
3e50: 6e 66 6f 28 66 69 6c 65 29 3b 7d 5d 0a 0a 09 09 nfo(file);}]....
3e60: 09 09 69 66 20 7b 5b 69 6e 66 6f 20 65 78 69 73 ..if {[info exis
3e70: 74 73 20 70 61 74 68 69 6e 66 6f 28 70 61 63 6b ts pathinfo(pack
3e80: 61 67 65 29 5d 20 26 26 20 5b 69 6e 66 6f 20 65 age)] && [info e
3e90: 78 69 73 74 73 20 70 61 74 68 69 6e 66 6f 28 68 xists pathinfo(h
3ea0: 6f 73 74 6e 61 6d 65 29 5d 20 26 26 20 5b 69 6e ostname)] && [in
3eb0: 66 6f 20 65 78 69 73 74 73 20 70 61 74 68 69 6e fo exists pathin
3ec0: 66 6f 28 66 69 6c 65 29 5d 7d 20 7b 0a 09 09 09 fo(file)]} {....
3ed0: 09 09 5f 61 73 5f 75 73 65 72 20 7b 0a 09 09 09 .._as_user {....
3ee0: 09 09 09 73 65 74 20 64 69 72 20 5b 5f 6c 6f 63 ...set dir [_loc
3ef0: 61 6c 70 61 74 68 20 24 70 61 74 68 69 6e 66 6f alpath $pathinfo
3f00: 28 70 61 63 6b 61 67 65 29 20 24 70 61 74 68 69 (package) $pathi
3f10: 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 24 70 nfo(hostname) $p
3f20: 61 74 68 69 6e 66 6f 28 66 69 6c 65 29 5d 0a 09 athinfo(file)]..
3f30: 09 09 09 09 09 73 65 74 20 77 68 69 74 65 6f 75 .....set whiteou
3f40: 74 64 69 72 20 5b 73 74 72 69 6e 67 20 72 61 6e tdir [string ran
3f50: 67 65 20 5b 5f 77 68 69 74 65 6f 75 74 70 61 74 ge [_whiteoutpat
3f60: 68 20 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b h $pathinfo(pack
3f70: 61 67 65 29 20 24 70 61 74 68 69 6e 66 6f 28 68 age) $pathinfo(h
3f80: 6f 73 74 6e 61 6d 65 29 20 24 70 61 74 68 69 6e ostname) $pathin
3f90: 66 6f 28 66 69 6c 65 29 5d 20 30 20 65 6e 64 2d fo(file)] 0 end-
3fa0: 31 35 5d 0a 0a 09 09 09 09 09 09 69 66 20 7b 24 15]........if {$
3fb0: 77 68 69 74 65 6f 75 74 64 69 72 20 21 3d 20 22 whiteoutdir != "
3fc0: 22 7d 20 7b 0a 09 09 09 09 09 09 09 66 6f 72 65 "} {........fore
3fd0: 61 63 68 20 66 69 6c 65 20 5b 67 6c 6f 62 20 2d ach file [glob -
3fe0: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 2d 74 61 69 6c nocomplain -tail
3ff0: 73 20 2d 64 69 72 65 63 74 6f 72 79 20 24 77 68 s -directory $wh
4000: 69 74 65 6f 75 74 64 69 72 20 7b 7b 2e 2c 7d 2a iteoutdir {{.,}*
4010: 2e 41 50 50 46 53 2e 57 48 49 54 45 4f 55 54 7d .APPFS.WHITEOUT}
4020: 5d 20 7b 0a 09 09 09 09 09 09 09 09 73 65 74 20 ] {.........set
4030: 72 65 6d 6f 76 65 20 5b 73 74 72 69 6e 67 20 72 remove [string r
4040: 61 6e 67 65 20 24 66 69 6c 65 20 30 20 65 6e 64 ange $file 0 end
4050: 2d 31 35 5d 0a 09 09 09 09 09 09 09 09 73 65 74 -15].........set
4060: 20 69 64 78 20 5b 6c 73 65 61 72 63 68 20 2d 65 idx [lsearch -e
4070: 78 61 63 74 20 24 72 65 74 76 61 6c 20 24 72 65 xact $retval $re
4080: 6d 6f 76 65 5d 0a 09 09 09 09 09 09 09 09 69 66 move].........if
4090: 20 7b 24 69 64 78 20 21 3d 20 2d 31 7d 20 7b 0a {$idx != -1} {.
40a0: 09 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 .........set ret
40b0: 76 61 6c 20 5b 6c 72 65 70 6c 61 63 65 20 24 72 val [lreplace $r
40c0: 65 74 76 61 6c 20 24 69 64 78 20 24 69 64 78 5d etval $idx $idx]
40d0: 0a 09 09 09 09 09 09 09 09 7d 0a 09 09 09 09 09 .........}......
40e0: 09 09 7d 0a 09 09 09 09 09 09 7d 0a 0a 09 09 09 ..}.......}.....
40f0: 09 09 09 69 66 20 7b 24 64 69 72 20 21 3d 20 22 ...if {$dir != "
4100: 22 7d 20 7b 0a 09 09 09 09 09 09 09 66 6f 72 65 "} {........fore
4110: 61 63 68 20 66 69 6c 65 20 5b 67 6c 6f 62 20 2d ach file [glob -
4120: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 2d 74 61 69 6c nocomplain -tail
4130: 73 20 2d 64 69 72 65 63 74 6f 72 79 20 24 64 69 s -directory $di
4140: 72 20 7b 7b 2e 2c 7d 2a 7d 5d 20 7b 0a 09 09 09 r {{.,}*}] {....
4150: 09 09 09 09 09 69 66 20 7b 24 66 69 6c 65 20 3d .....if {$file =
4160: 3d 20 22 2e 22 20 7c 7c 20 24 66 69 6c 65 20 3d = "." || $file =
4170: 3d 20 22 2e 2e 22 7d 20 7b 0a 09 09 09 09 09 09 = ".."} {.......
4180: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09 ...continue.....
4190: 09 09 09 09 7d 0a 0a 09 09 09 09 09 09 09 09 69 ....}..........i
41a0: 66 20 7b 24 66 69 6c 65 20 3d 3d 20 22 2e 41 50 f {$file == ".AP
41b0: 50 46 53 2e 57 48 49 54 45 4f 55 54 22 7d 20 7b PFS.WHITEOUT"} {
41c0: 0a 09 09 09 09 09 09 09 09 09 63 6f 6e 74 69 6e ..........contin
41d0: 75 65 0a 09 09 09 09 09 09 09 09 7d 0a 0a 09 09 ue.........}....
41e0: 09 09 09 09 09 09 69 66 20 7b 5b 6c 73 65 61 72 ......if {[lsear
41f0: 63 68 20 2d 65 78 61 63 74 20 24 72 65 74 76 61 ch -exact $retva
4200: 6c 20 24 66 69 6c 65 5d 20 21 3d 20 2d 31 7d 20 l $file] != -1}
4210: 7b 0a 09 09 09 09 09 09 09 09 09 63 6f 6e 74 69 {..........conti
4220: 6e 75 65 0a 09 09 09 09 09 09 09 09 7d 0a 0a 09 nue.........}...
4230: 09 09 09 09 09 09 09 6c 61 70 70 65 6e 64 20 72 .......lappend r
4240: 65 74 76 61 6c 20 24 66 69 6c 65 0a 09 09 09 09 etval $file.....
4250: 09 09 09 7d 0a 09 09 09 09 09 09 7d 0a 09 09 09 ...}.......}....
4260: 09 09 7d 0a 09 09 09 09 7d 0a 0a 09 09 09 09 72 ..}.....}......r
4270: 65 74 75 72 6e 20 24 72 65 74 76 61 6c 0a 09 09 eturn $retval...
4280: 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e .}...}....return
4290: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 49 6e -code error "In
42a0: 76 61 6c 69 64 20 6f 72 20 75 6e 61 63 63 65 70 valid or unaccep
42b0: 74 61 62 6c 65 20 70 61 74 68 3a 20 24 64 69 72 table path: $dir
42c0: 22 0a 09 7d 0a 0a 09 70 72 6f 63 20 67 65 74 61 "..}...proc geta
42d0: 74 74 72 20 7b 70 61 74 68 7d 20 7b 0a 09 09 61 ttr {path} {...a
42e0: 72 72 61 79 20 73 65 74 20 70 61 74 68 69 6e 66 rray set pathinf
42f0: 6f 20 5b 5f 70 61 72 73 65 70 61 74 68 20 24 70 o [_parsepath $p
4300: 61 74 68 5d 0a 09 09 61 72 72 61 79 20 73 65 74 ath]...array set
4310: 20 72 65 74 76 61 6c 20 5b 6c 69 73 74 5d 0a 0a retval [list]..
4320: 09 09 63 61 74 63 68 20 7b 0a 09 09 09 3a 3a 61 ..catch {....::a
4330: 70 70 66 73 3a 3a 67 65 74 69 6e 64 65 78 20 24 ppfs::getindex $
4340: 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d pathinfo(hostnam
4350: 65 29 0a 09 09 09 3a 3a 61 70 70 66 73 3a 3a 67 e)....::appfs::g
4360: 65 74 70 6b 67 6d 61 6e 69 66 65 73 74 20 24 70 etpkgmanifest $p
4370: 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 athinfo(hostname
4380: 29 20 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b ) $pathinfo(pack
4390: 61 67 65 5f 73 68 61 31 29 0a 09 09 7d 0a 0a 09 age_sha1)...}...
43a0: 09 73 77 69 74 63 68 20 2d 2d 20 24 70 61 74 68 .switch -- $path
43b0: 69 6e 66 6f 28 5f 74 79 70 65 29 20 7b 0a 09 09 info(_type) {...
43c0: 09 22 74 6f 70 6c 65 76 65 6c 22 20 7b 0a 09 09 ."toplevel" {...
43d0: 09 09 73 65 74 20 72 65 74 76 61 6c 28 74 79 70 ..set retval(typ
43e0: 65 29 20 64 69 72 65 63 74 6f 72 79 0a 09 09 09 e) directory....
43f0: 09 73 65 74 20 72 65 74 76 61 6c 28 63 68 69 6c .set retval(chil
4400: 64 63 6f 75 6e 74 29 20 5b 6c 6c 65 6e 67 74 68 dcount) [llength
4410: 20 5b 67 65 74 63 68 69 6c 64 72 65 6e 20 24 70 [getchildren $p
4420: 61 74 68 5d 5d 0a 09 09 09 7d 0a 09 09 09 22 73 ath]]....}...."s
4430: 69 74 65 73 22 20 7b 0a 09 09 09 09 73 65 74 20 ites" {.....set
4440: 63 68 65 63 6b 20 5b 3a 3a 61 70 70 66 73 3a 3a check [::appfs::
4450: 64 62 20 6f 6e 65 63 6f 6c 75 6d 6e 20 7b 53 45 db onecolumn {SE
4460: 4c 45 43 54 20 31 20 46 52 4f 4d 20 70 61 63 6b LECT 1 FROM pack
4470: 61 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e ages WHERE hostn
4480: 61 6d 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 ame = $pathinfo(
4490: 68 6f 73 74 6e 61 6d 65 29 3b 7d 5d 0a 09 09 09 hostname);}]....
44a0: 09 69 66 20 7b 24 63 68 65 63 6b 20 3d 3d 20 22 .if {$check == "
44b0: 31 22 7d 20 7b 0a 09 09 09 09 09 73 65 74 20 72 1"} {......set r
44c0: 65 74 76 61 6c 28 74 79 70 65 29 20 64 69 72 65 etval(type) dire
44d0: 63 74 6f 72 79 0a 09 09 09 09 09 73 65 74 20 72 ctory......set r
44e0: 65 74 76 61 6c 28 63 68 69 6c 64 63 6f 75 6e 74 etval(childcount
44f0: 29 20 5b 6c 6c 65 6e 67 74 68 20 5b 67 65 74 63 ) [llength [getc
4500: 68 69 6c 64 72 65 6e 20 24 70 61 74 68 5d 5d 0a hildren $path]].
4510: 09 09 09 09 7d 0a 09 09 09 7d 0a 09 09 09 22 70 ....}....}...."p
4520: 61 63 6b 61 67 65 73 22 20 7b 0a 09 09 09 09 73 ackages" {.....s
4530: 65 74 20 63 68 65 63 6b 20 5b 3a 3a 61 70 70 66 et check [::appf
4540: 73 3a 3a 64 62 20 6f 6e 65 63 6f 6c 75 6d 6e 20 s::db onecolumn
4550: 7b 53 45 4c 45 43 54 20 31 20 46 52 4f 4d 20 70 {SELECT 1 FROM p
4560: 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 68 6f ackages WHERE ho
4570: 73 74 6e 61 6d 65 20 3d 20 24 70 61 74 68 69 6e stname = $pathin
4580: 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 41 4e 44 fo(hostname) AND
4590: 20 70 61 63 6b 61 67 65 20 3d 20 24 70 61 74 68 package = $path
45a0: 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 3b 7d 5d info(package);}]
45b0: 0a 09 09 09 09 69 66 20 7b 24 63 68 65 63 6b 20 .....if {$check
45c0: 3d 3d 20 22 31 22 7d 20 7b 0a 09 09 09 09 09 73 == "1"} {......s
45d0: 65 74 20 72 65 74 76 61 6c 28 74 79 70 65 29 20 et retval(type)
45e0: 64 69 72 65 63 74 6f 72 79 0a 09 09 09 09 09 73 directory......s
45f0: 65 74 20 72 65 74 76 61 6c 28 63 68 69 6c 64 63 et retval(childc
4600: 6f 75 6e 74 29 20 5b 6c 6c 65 6e 67 74 68 20 5b ount) [llength [
4610: 67 65 74 63 68 69 6c 64 72 65 6e 20 24 70 61 74 getchildren $pat
4620: 68 5d 5d 0a 09 09 09 09 7d 0a 09 09 09 7d 0a 09 h]].....}....}..
4630: 09 09 22 6f 73 2d 63 70 75 22 20 7b 0a 09 09 09 .."os-cpu" {....
4640: 09 69 66 20 7b 24 70 61 74 68 69 6e 66 6f 28 6f .if {$pathinfo(o
4650: 73 29 20 3d 3d 20 22 70 6c 61 74 66 6f 72 6d 22 s) == "platform"
4660: 20 26 26 20 24 70 61 74 68 69 6e 66 6f 28 63 70 && $pathinfo(cp
4670: 75 29 20 3d 3d 20 22 22 7d 20 7b 0a 09 09 09 09 u) == ""} {.....
4680: 09 73 65 74 20 72 65 74 76 61 6c 28 74 79 70 65 .set retval(type
4690: 29 20 73 79 6d 6c 69 6e 6b 0a 09 09 09 09 09 73 ) symlink......s
46a0: 65 74 20 72 65 74 76 61 6c 28 73 6f 75 72 63 65 et retval(source
46b0: 29 20 5b 70 6c 61 74 66 6f 72 6d 3a 3a 67 65 6e ) [platform::gen
46c0: 65 72 69 63 5d 0a 09 09 09 09 7d 20 65 6c 73 65 eric].....} else
46d0: 20 7b 0a 09 09 09 09 09 73 65 74 20 63 68 65 63 {......set chec
46e0: 6b 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 6f k [::appfs::db o
46f0: 6e 65 63 6f 6c 75 6d 6e 20 7b 0a 09 09 09 09 09 necolumn {......
4700: 09 53 45 4c 45 43 54 20 31 20 46 52 4f 4d 20 70 .SELECT 1 FROM p
4710: 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 68 6f ackages WHERE ho
4720: 73 74 6e 61 6d 65 20 3d 20 24 70 61 74 68 69 6e stname = $pathin
4730: 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 41 4e 44 fo(hostname) AND
4740: 20 70 61 63 6b 61 67 65 20 3d 20 24 70 61 74 68 package = $path
4750: 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 20 41 4e info(package) AN
4760: 44 20 6f 73 20 3d 20 24 70 61 74 68 69 6e 66 6f D os = $pathinfo
4770: 28 6f 73 29 20 41 4e 44 20 63 70 75 41 72 63 68 (os) AND cpuArch
4780: 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 63 70 75 = $pathinfo(cpu
4790: 29 3b 0a 09 09 09 09 09 7d 5d 0a 09 09 09 09 09 );......}]......
47a0: 69 66 20 7b 24 63 68 65 63 6b 20 3d 3d 20 22 31 if {$check == "1
47b0: 22 7d 20 7b 0a 09 09 09 09 09 09 73 65 74 20 72 "} {.......set r
47c0: 65 74 76 61 6c 28 74 79 70 65 29 20 64 69 72 65 etval(type) dire
47d0: 63 74 6f 72 79 0a 09 09 09 09 09 09 73 65 74 20 ctory.......set
47e0: 72 65 74 76 61 6c 28 63 68 69 6c 64 63 6f 75 6e retval(childcoun
47f0: 74 29 20 5b 6c 6c 65 6e 67 74 68 20 5b 67 65 74 t) [llength [get
4800: 63 68 69 6c 64 72 65 6e 20 24 70 61 74 68 5d 5d children $path]]
4810: 0a 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 09 09 ......}.....}...
4820: 09 7d 0a 09 09 09 22 76 65 72 73 69 6f 6e 73 22 .}...."versions"
4830: 20 7b 0a 09 09 09 09 69 66 20 7b 24 70 61 74 68 {.....if {$path
4840: 69 6e 66 6f 28 76 65 72 73 69 6f 6e 29 20 3d 3d info(version) ==
4850: 20 22 6c 61 74 65 73 74 22 7d 20 7b 0a 09 09 09 "latest"} {....
4860: 09 09 3a 3a 61 70 70 66 73 3a 3a 64 62 20 65 76 ..::appfs::db ev
4870: 61 6c 20 7b 53 45 4c 45 43 54 20 76 65 72 73 69 al {SELECT versi
4880: 6f 6e 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 on FROM packages
4890: 20 57 48 45 52 45 20 69 73 4c 61 74 65 73 74 20 WHERE isLatest
48a0: 3d 20 31 20 41 4e 44 20 68 6f 73 74 6e 61 6d 65 = 1 AND hostname
48b0: 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 = $pathinfo(hos
48c0: 74 6e 61 6d 65 29 20 41 4e 44 20 70 61 63 6b 61 tname) AND packa
48d0: 67 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 70 ge = $pathinfo(p
48e0: 61 63 6b 61 67 65 29 20 41 4e 44 20 6f 73 20 3d ackage) AND os =
48f0: 20 24 70 61 74 68 69 6e 66 6f 28 6f 73 29 20 41 $pathinfo(os) A
4900: 4e 44 20 63 70 75 41 72 63 68 20 3d 20 24 70 61 ND cpuArch = $pa
4910: 74 68 69 6e 66 6f 28 63 70 75 29 20 4c 49 4d 49 thinfo(cpu) LIMI
4920: 54 20 31 3b 7d 20 6c 61 74 65 73 74 5f 69 6e 66 T 1;} latest_inf
4930: 6f 20 7b 7d 0a 0a 09 09 09 09 09 69 66 20 7b 5b o {}.......if {[
4940: 69 6e 66 6f 20 65 78 69 73 74 73 20 6c 61 74 65 info exists late
4950: 73 74 5f 69 6e 66 6f 28 76 65 72 73 69 6f 6e 29 st_info(version)
4960: 5d 7d 20 7b 0a 09 09 09 09 09 09 73 65 74 20 72 ]} {.......set r
4970: 65 74 76 61 6c 28 74 79 70 65 29 20 73 79 6d 6c etval(type) syml
4980: 69 6e 6b 0a 09 09 09 09 09 09 73 65 74 20 72 65 ink.......set re
4990: 74 76 61 6c 28 73 6f 75 72 63 65 29 20 24 6c 61 tval(source) $la
49a0: 74 65 73 74 5f 69 6e 66 6f 28 76 65 72 73 69 6f test_info(versio
49b0: 6e 29 0a 09 09 09 09 09 7d 0a 09 09 09 09 7d 20 n)......}.....}
49c0: 65 6c 73 65 20 7b 0a 09 09 09 09 09 69 66 20 7b else {......if {
49d0: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 70 61 74 [info exists pat
49e0: 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 5f 73 68 hinfo(package_sh
49f0: 61 31 29 5d 20 26 26 20 24 70 61 74 68 69 6e 66 a1)] && $pathinf
4a00: 6f 28 70 61 63 6b 61 67 65 5f 73 68 61 31 29 20 o(package_sha1)
4a10: 21 3d 20 22 22 7d 20 7b 0a 09 09 09 09 09 09 73 != ""} {.......s
4a20: 65 74 20 72 65 74 76 61 6c 28 74 79 70 65 29 20 et retval(type)
4a30: 64 69 72 65 63 74 6f 72 79 0a 09 09 09 09 09 09 directory.......
4a40: 73 65 74 20 72 65 74 76 61 6c 28 63 68 69 6c 64 set retval(child
4a50: 63 6f 75 6e 74 29 20 5b 6c 6c 65 6e 67 74 68 20 count) [llength
4a60: 5b 67 65 74 63 68 69 6c 64 72 65 6e 20 24 70 61 [getchildren $pa
4a70: 74 68 5d 5d 0a 09 09 09 09 09 7d 0a 09 09 09 09 th]]......}.....
4a80: 7d 0a 09 09 09 7d 0a 09 09 09 22 66 69 6c 65 73 }....}...."files
4a90: 22 20 7b 0a 09 09 09 09 73 65 74 20 72 65 74 76 " {.....set retv
4aa0: 61 6c 28 70 61 63 6b 61 67 65 64 29 20 31 0a 0a al(packaged) 1..
4ab0: 09 09 09 09 73 65 74 20 6c 6f 63 61 6c 70 61 74 ....set localpat
4ac0: 68 20 5b 5f 6c 6f 63 61 6c 70 61 74 68 20 24 70 h [_localpath $p
4ad0: 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 athinfo(package)
4ae0: 20 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e $pathinfo(hostn
4af0: 61 6d 65 29 20 24 70 61 74 68 69 6e 66 6f 28 66 ame) $pathinfo(f
4b00: 69 6c 65 29 5d 0a 09 09 09 09 73 65 74 20 77 68 ile)].....set wh
4b10: 69 74 65 6f 75 74 70 61 74 68 20 20 5b 5f 77 68 iteoutpath [_wh
4b20: 69 74 65 6f 75 74 70 61 74 68 20 24 70 61 74 68 iteoutpath $path
4b30: 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 20 24 70 info(package) $p
4b40: 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 athinfo(hostname
4b50: 29 20 24 70 61 74 68 69 6e 66 6f 28 66 69 6c 65 ) $pathinfo(file
4b60: 29 5d 0a 0a 09 09 09 09 73 65 74 20 72 65 74 76 )]......set retv
4b70: 61 6c 28 6c 6f 63 61 6c 70 61 74 68 29 20 24 6c al(localpath) $l
4b80: 6f 63 61 6c 70 61 74 68 0a 09 09 09 09 73 65 74 ocalpath.....set
4b90: 20 72 65 74 76 61 6c 28 77 68 69 74 65 6f 75 74 retval(whiteout
4ba0: 70 61 74 68 29 20 24 77 68 69 74 65 6f 75 74 70 path) $whiteoutp
4bb0: 61 74 68 0a 0a 09 09 09 09 75 6e 73 65 74 20 2d ath......unset -
4bc0: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 6c 6f 63 61 6c nocomplain local
4bd0: 70 61 74 68 69 6e 66 6f 0a 09 09 09 09 69 66 20 pathinfo.....if
4be0: 7b 24 6c 6f 63 61 6c 70 61 74 68 20 21 3d 20 22 {$localpath != "
4bf0: 22 7d 20 7b 0a 09 09 09 09 09 5f 61 73 5f 75 73 "} {......_as_us
4c00: 65 72 20 7b 0a 09 09 09 09 09 09 63 61 74 63 68 er {.......catch
4c10: 20 7b 0a 09 09 09 09 09 09 09 66 69 6c 65 20 6c {........file l
4c20: 73 74 61 74 20 24 6c 6f 63 61 6c 70 61 74 68 20 stat $localpath
4c30: 6c 6f 63 61 6c 70 61 74 68 69 6e 66 6f 0a 09 09 localpathinfo...
4c40: 09 09 09 09 7d 0a 09 09 09 09 09 7d 0a 09 09 09 ....}......}....
4c50: 09 7d 0a 0a 09 09 09 09 69 66 20 7b 24 6c 6f 63 .}......if {$loc
4c60: 61 6c 70 61 74 68 20 21 3d 20 22 22 20 26 26 20 alpath != "" &&
4c70: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 6c 6f 63 [info exists loc
4c80: 61 6c 70 61 74 68 69 6e 66 6f 5d 7d 20 7b 0a 09 alpathinfo]} {..
4c90: 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 69 ....set retval(i
4ca0: 73 5f 6c 6f 63 61 6c 66 69 6c 65 29 20 31 0a 09 s_localfile) 1..
4cb0: 09 09 09 09 63 61 74 63 68 20 7b 0a 09 09 09 09 ....catch {.....
4cc0: 09 09 73 65 74 20 72 65 74 76 61 6c 28 74 69 6d ..set retval(tim
4cd0: 65 29 20 24 6c 6f 63 61 6c 70 61 74 68 69 6e 66 e) $localpathinf
4ce0: 6f 28 6d 74 69 6d 65 29 0a 0a 09 09 09 09 09 09 o(mtime)........
4cf0: 73 77 69 74 63 68 20 2d 2d 20 24 6c 6f 63 61 6c switch -- $local
4d00: 70 61 74 68 69 6e 66 6f 28 74 79 70 65 29 20 7b pathinfo(type) {
4d10: 0a 09 09 09 09 09 09 09 22 64 69 72 65 63 74 6f ........"directo
4d20: 72 79 22 20 7b 0a 09 09 09 09 09 09 09 09 73 65 ry" {.........se
4d30: 74 20 72 65 74 76 61 6c 28 74 79 70 65 29 20 22 t retval(type) "
4d40: 64 69 72 65 63 74 6f 72 79 22 0a 09 09 09 09 09 directory"......
4d50: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 63 68 ...set retval(ch
4d60: 69 6c 64 63 6f 75 6e 74 29 20 5b 6c 6c 65 6e 67 ildcount) [lleng
4d70: 74 68 20 5b 67 65 74 63 68 69 6c 64 72 65 6e 20 th [getchildren
4d80: 24 70 61 74 68 5d 5d 0a 09 09 09 09 09 09 09 7d $path]]........}
4d90: 0a 09 09 09 09 09 09 09 22 66 69 6c 65 22 20 7b ........"file" {
4da0: 0a 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 .........set ret
4db0: 76 61 6c 28 74 79 70 65 29 20 22 66 69 6c 65 22 val(type) "file"
4dc0: 0a 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 .........set ret
4dd0: 76 61 6c 28 73 69 7a 65 29 20 24 6c 6f 63 61 6c val(size) $local
4de0: 70 61 74 68 69 6e 66 6f 28 73 69 7a 65 29 0a 09 pathinfo(size)..
4df0: 09 09 09 09 09 09 09 5f 61 73 5f 75 73 65 72 20 ......._as_user
4e00: 7b 0a 09 09 09 09 09 09 09 09 09 69 66 20 7b 5b {..........if {[
4e10: 66 69 6c 65 20 65 78 65 63 75 74 61 62 6c 65 20 file executable
4e20: 24 6c 6f 63 61 6c 70 61 74 68 5d 7d 20 7b 0a 09 $localpath]} {..
4e30: 09 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 .........set ret
4e40: 76 61 6c 28 70 65 72 6d 73 29 20 22 78 22 0a 09 val(perms) "x"..
4e50: 09 09 09 09 09 09 09 09 7d 20 65 6c 73 65 20 7b ........} else {
4e60: 0a 09 09 09 09 09 09 09 09 09 09 73 65 74 20 72 ...........set r
4e70: 65 74 76 61 6c 28 70 65 72 6d 73 29 20 22 22 0a etval(perms) "".
4e80: 09 09 09 09 09 09 09 09 09 7d 0a 09 09 09 09 09 .........}......
4e90: 09 09 09 7d 0a 09 09 09 09 09 09 09 7d 0a 09 09 ...}........}...
4ea0: 09 09 09 09 09 22 6c 69 6e 6b 22 20 7b 0a 09 09 ....."link" {...
4eb0: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
4ec0: 28 74 79 70 65 29 20 22 73 79 6d 6c 69 6e 6b 22 (type) "symlink"
4ed0: 0a 0a 09 09 09 09 09 09 09 09 5f 61 73 5f 75 73 .........._as_us
4ee0: 65 72 20 7b 0a 09 09 09 09 09 09 09 09 09 73 65 er {..........se
4ef0: 74 20 72 65 74 76 61 6c 28 73 6f 75 72 63 65 29 t retval(source)
4f00: 20 5b 66 69 6c 65 20 72 65 61 64 6c 69 6e 6b 20 [file readlink
4f10: 24 6c 6f 63 61 6c 70 61 74 68 5d 0a 09 09 09 09 $localpath].....
4f20: 09 09 09 09 7d 0a 09 09 09 09 09 09 09 7d 0a 09 ....}........}..
4f30: 09 09 09 09 09 09 22 66 69 66 6f 22 20 7b 0a 09 ......"fifo" {..
4f40: 09 09 09 09 09 09 09 23 20 43 61 70 69 74 61 6c .......# Capital
4f50: 69 7a 65 64 20 73 6f 20 74 68 61 74 20 74 68 65 ized so that the
4f60: 20 66 69 72 73 74 20 63 68 61 72 20 69 73 20 75 first char is u
4f70: 6e 69 71 75 65 0a 09 09 09 09 09 09 09 09 73 65 nique.........se
4f80: 74 20 72 65 74 76 61 6c 28 74 79 70 65 29 20 22 t retval(type) "
4f90: 46 69 66 6f 22 0a 09 09 09 09 09 09 09 7d 0a 09 Fifo"........}..
4fa0: 09 09 09 09 09 09 22 73 6f 63 6b 65 74 22 20 7b ......"socket" {
4fb0: 0a 09 09 09 09 09 09 09 09 23 20 43 61 70 69 74 .........# Capit
4fc0: 61 6c 69 7a 65 64 20 73 6f 20 74 68 61 74 20 74 alized so that t
4fd0: 68 65 20 66 69 72 73 74 20 63 68 61 72 20 69 73 he first char is
4fe0: 20 75 6e 69 71 75 65 0a 09 09 09 09 09 09 09 09 unique.........
4ff0: 73 65 74 20 72 65 74 76 61 6c 28 74 79 70 65 29 set retval(type)
5000: 20 22 53 6f 63 6b 65 74 22 0a 09 09 09 09 09 09 "Socket".......
5010: 09 7d 0a 09 09 09 09 09 09 7d 0a 09 09 09 09 09 .}.......}......
5020: 7d 20 65 72 72 0a 09 09 09 09 7d 20 65 6c 73 65 } err.....} else
5030: 20 7b 0a 09 09 09 09 09 69 66 20 7b 24 77 68 69 {......if {$whi
5040: 74 65 6f 75 74 70 61 74 68 20 3d 3d 20 22 22 20 teoutpath == ""
5050: 7c 7c 20 21 5b 66 69 6c 65 20 65 78 69 73 74 73 || ![file exists
5060: 20 24 77 68 69 74 65 6f 75 74 70 61 74 68 5d 7d $whiteoutpath]}
5070: 20 7b 0a 09 09 09 09 09 09 73 65 74 20 72 65 74 {.......set ret
5080: 76 61 6c 28 69 73 5f 72 65 6d 6f 74 65 66 69 6c val(is_remotefil
5090: 65 29 20 31 0a 0a 09 09 09 09 09 09 73 65 74 20 e) 1........set
50a0: 77 6f 72 6b 20 5b 73 70 6c 69 74 20 24 70 61 74 work [split $pat
50b0: 68 69 6e 66 6f 28 66 69 6c 65 29 20 22 2f 22 5d hinfo(file) "/"]
50c0: 0a 09 09 09 09 09 09 73 65 74 20 64 69 72 65 63 .......set direc
50d0: 74 6f 72 79 20 5b 6a 6f 69 6e 20 5b 6c 72 61 6e tory [join [lran
50e0: 67 65 20 24 77 6f 72 6b 20 30 20 65 6e 64 2d 31 ge $work 0 end-1
50f0: 5d 20 22 2f 22 5d 0a 09 09 09 09 09 09 73 65 74 ] "/"].......set
5100: 20 66 69 6c 65 20 5b 6c 69 6e 64 65 78 20 24 77 file [lindex $w
5110: 6f 72 6b 20 65 6e 64 5d 0a 0a 09 09 09 09 09 09 ork end]........
5120: 69 66 20 7b 24 64 69 72 65 63 74 6f 72 79 20 3d if {$directory =
5130: 3d 20 22 22 20 26 26 20 24 66 69 6c 65 20 3d 3d = "" && $file ==
5140: 20 22 22 7d 20 7b 0a 09 09 09 09 09 09 09 61 72 ""} {........ar
5150: 72 61 79 20 73 65 74 20 72 65 74 76 61 6c 20 5b ray set retval [
5160: 6c 69 73 74 20 74 79 70 65 20 64 69 72 65 63 74 list type direct
5170: 6f 72 79 5d 0a 09 09 09 09 09 09 7d 0a 0a 09 09 ory].......}....
5180: 09 09 09 09 3a 3a 61 70 70 66 73 3a 3a 64 62 20 ....::appfs::db
5190: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 74 79 70 eval {SELECT typ
51a0: 65 2c 20 74 69 6d 65 2c 20 73 6f 75 72 63 65 2c e, time, source,
51b0: 20 73 69 7a 65 2c 20 70 65 72 6d 73 20 46 52 4f size, perms FRO
51c0: 4d 20 66 69 6c 65 73 20 57 48 45 52 45 20 70 61 M files WHERE pa
51d0: 63 6b 61 67 65 5f 73 68 61 31 20 3d 20 24 70 61 ckage_sha1 = $pa
51e0: 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 5f 73 thinfo(package_s
51f0: 68 61 31 29 20 41 4e 44 20 66 69 6c 65 5f 64 69 ha1) AND file_di
5200: 72 65 63 74 6f 72 79 20 3d 20 24 64 69 72 65 63 rectory = $direc
5210: 74 6f 72 79 20 41 4e 44 20 66 69 6c 65 5f 6e 61 tory AND file_na
5220: 6d 65 20 3d 20 24 66 69 6c 65 3b 7d 20 72 65 74 me = $file;} ret
5230: 76 61 6c 20 7b 7d 0a 0a 09 09 09 09 09 09 69 66 val {}........if
5240: 20 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 72 {[info exists r
5250: 65 74 76 61 6c 28 74 79 70 65 29 5d 20 26 26 20 etval(type)] &&
5260: 24 72 65 74 76 61 6c 28 74 79 70 65 29 20 3d 3d $retval(type) ==
5270: 20 22 64 69 72 65 63 74 6f 72 79 22 7d 20 7b 0a "directory"} {.
5280: 09 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 .......set retva
5290: 6c 28 63 68 69 6c 64 63 6f 75 6e 74 29 20 5b 6c l(childcount) [l
52a0: 6c 65 6e 67 74 68 20 5b 67 65 74 63 68 69 6c 64 length [getchild
52b0: 72 65 6e 20 24 70 61 74 68 5d 5d 0a 09 09 09 09 ren $path]].....
52c0: 09 09 7d 0a 0a 09 09 09 09 09 09 75 6e 73 65 74 ..}........unset
52d0: 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 72 65 74 -nocomplain ret
52e0: 76 61 6c 28 2a 29 0a 09 09 09 09 09 7d 0a 09 09 val(*)......}...
52f0: 09 09 7d 0a 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 ..}.....}...}...
5300: 09 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 73 .if {![info exis
5310: 74 73 20 72 65 74 76 61 6c 28 74 79 70 65 29 5d ts retval(type)]
5320: 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 } {....return -c
5330: 6f 64 65 20 65 72 72 6f 72 20 22 4e 6f 20 73 75 ode error "No su
5340: 63 68 20 66 69 6c 65 20 6f 72 20 64 69 72 65 63 ch file or direc
5350: 74 6f 72 79 22 0a 09 09 7d 0a 0a 09 09 72 65 74 tory"...}....ret
5360: 75 72 6e 20 5b 61 72 72 61 79 20 67 65 74 20 72 urn [array get r
5370: 65 74 76 61 6c 5d 0a 09 7d 0a 0a 09 70 72 6f 63 etval]..}...proc
5380: 20 6f 70 65 6e 70 61 74 68 20 7b 70 61 74 68 20 openpath {path
5390: 6d 6f 64 65 7d 20 7b 0a 09 09 61 72 72 61 79 20 mode} {...array
53a0: 73 65 74 20 70 61 74 68 69 6e 66 6f 20 5b 5f 70 set pathinfo [_p
53b0: 61 72 73 65 70 61 74 68 20 24 70 61 74 68 5d 0a arsepath $path].
53c0: 0a 09 09 69 66 20 7b 24 70 61 74 68 69 6e 66 6f ...if {$pathinfo
53d0: 28 5f 74 79 70 65 29 20 21 3d 20 22 66 69 6c 65 (_type) != "file
53e0: 73 22 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 s"} {....return
53f0: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 69 6e 76 -code error "inv
5400: 61 6c 69 64 20 74 79 70 65 22 0a 09 09 7d 0a 0a alid type"...}..
5410: 09 09 73 65 74 20 6c 6f 63 61 6c 70 61 74 68 20 ..set localpath
5420: 5b 5f 6c 6f 63 61 6c 70 61 74 68 20 24 70 61 74 [_localpath $pat
5430: 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 20 24 hinfo(package) $
5440: 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d pathinfo(hostnam
5450: 65 29 20 24 70 61 74 68 69 6e 66 6f 28 66 69 6c e) $pathinfo(fil
5460: 65 29 5d 0a 0a 09 09 69 66 20 7b 24 6d 6f 64 65 e)]....if {$mode
5470: 20 3d 3d 20 22 63 72 65 61 74 65 22 7d 20 7b 0a == "create"} {.
5480: 09 09 09 69 66 20 7b 24 6c 6f 63 61 6c 70 61 74 ...if {$localpat
5490: 68 20 3d 3d 20 22 22 7d 20 7b 0a 09 09 09 09 72 h == ""} {.....r
54a0: 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f eturn -code erro
54b0: 72 20 22 41 73 6b 65 64 20 74 6f 20 63 72 65 61 r "Asked to crea
54c0: 74 65 2c 20 62 75 74 20 6e 6f 20 68 6f 6d 65 20 te, but no home
54d0: 64 69 72 65 63 74 6f 72 79 2e 22 0a 09 09 09 7d directory."....}
54e0: 0a 0a 09 09 09 72 65 74 75 72 6e 20 24 6c 6f 63 .....return $loc
54f0: 61 6c 70 61 74 68 0a 09 09 7d 0a 0a 09 09 69 66 alpath...}....if
5500: 20 7b 24 6c 6f 63 61 6c 70 61 74 68 20 21 3d 20 {$localpath !=
5510: 22 22 20 26 26 20 5b 66 69 6c 65 20 65 78 69 73 "" && [file exis
5520: 74 73 20 24 6c 6f 63 61 6c 70 61 74 68 5d 7d 20 ts $localpath]}
5530: 7b 0a 09 09 09 72 65 74 75 72 6e 20 24 6c 6f 63 {....return $loc
5540: 61 6c 70 61 74 68 0a 09 09 7d 0a 0a 09 09 73 65 alpath...}....se
5550: 74 20 77 6f 72 6b 20 5b 73 70 6c 69 74 20 24 70 t work [split $p
5560: 61 74 68 69 6e 66 6f 28 66 69 6c 65 29 20 22 2f athinfo(file) "/
5570: 22 5d 0a 09 09 73 65 74 20 64 69 72 65 63 74 6f "]...set directo
5580: 72 79 20 5b 6a 6f 69 6e 20 5b 6c 72 61 6e 67 65 ry [join [lrange
5590: 20 24 77 6f 72 6b 20 30 20 65 6e 64 2d 31 5d 20 $work 0 end-1]
55a0: 22 2f 22 5d 0a 09 09 73 65 74 20 66 69 6c 65 20 "/"]...set file
55b0: 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 65 6e [lindex $work en
55c0: 64 5d 0a 09 09 3a 3a 61 70 70 66 73 3a 3a 64 62 d]...::appfs::db
55d0: 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 66 69 eval {SELECT fi
55e0: 6c 65 5f 73 68 61 31 2c 20 70 65 72 6d 73 20 46 le_sha1, perms F
55f0: 52 4f 4d 20 66 69 6c 65 73 20 57 48 45 52 45 20 ROM files WHERE
5600: 70 61 63 6b 61 67 65 5f 73 68 61 31 20 3d 20 24 package_sha1 = $
5610: 70 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 pathinfo(package
5620: 5f 73 68 61 31 29 20 41 4e 44 20 66 69 6c 65 5f _sha1) AND file_
5630: 6e 61 6d 65 20 3d 20 24 66 69 6c 65 20 41 4e 44 name = $file AND
5640: 20 66 69 6c 65 5f 64 69 72 65 63 74 6f 72 79 20 file_directory
5650: 3d 20 24 64 69 72 65 63 74 6f 72 79 3b 7d 20 70 = $directory;} p
5660: 6b 67 70 61 74 68 69 6e 66 6f 20 7b 7d 0a 0a 09 kgpathinfo {}...
5670: 09 69 66 20 7b 24 70 6b 67 70 61 74 68 69 6e 66 .if {$pkgpathinf
5680: 6f 28 66 69 6c 65 5f 73 68 61 31 29 20 3d 3d 20 o(file_sha1) ==
5690: 22 22 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 ""} {....return
56a0: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4e 6f 20 -code error "No
56b0: 73 75 63 68 20 66 69 6c 65 20 6f 72 20 64 69 72 such file or dir
56c0: 65 63 74 6f 72 79 22 0a 09 09 7d 0a 0a 09 09 73 ectory"...}....s
56d0: 65 74 20 6c 6f 63 61 6c 63 61 63 68 65 66 69 6c et localcachefil
56e0: 65 20 5b 64 6f 77 6e 6c 6f 61 64 20 24 70 61 74 e [download $pat
56f0: 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 hinfo(hostname)
5700: 24 70 6b 67 70 61 74 68 69 6e 66 6f 28 66 69 6c $pkgpathinfo(fil
5710: 65 5f 73 68 61 31 29 5d 0a 0a 09 09 69 66 20 7b e_sha1)]....if {
5720: 24 6d 6f 64 65 20 3d 3d 20 22 77 72 69 74 65 22 $mode == "write"
5730: 7d 20 7b 0a 09 09 09 5f 61 73 5f 75 73 65 72 20 } {...._as_user
5740: 7b 0a 09 09 09 09 73 65 74 20 74 6d 70 6c 6f 63 {.....set tmploc
5750: 61 6c 70 61 74 68 20 22 24 7b 6c 6f 63 61 6c 70 alpath "${localp
5760: 61 74 68 7d 2e 5b 65 78 70 72 20 72 61 6e 64 28 ath}.[expr rand(
5770: 29 5d 5b 63 6c 6f 63 6b 20 63 6c 69 63 6b 73 5d )][clock clicks]
5780: 22 0a 0a 09 09 09 09 73 65 74 20 66 61 69 6c 65 "......set faile
5790: 64 20 30 0a 09 09 09 09 69 66 20 7b 5b 63 61 74 d 0.....if {[cat
57a0: 63 68 20 7b 0a 09 09 09 09 09 66 69 6c 65 20 6d ch {......file m
57b0: 6b 64 69 72 20 5b 66 69 6c 65 20 64 69 72 6e 61 kdir [file dirna
57c0: 6d 65 20 24 6c 6f 63 61 6c 70 61 74 68 5d 0a 09 me $localpath]..
57d0: 09 09 09 09 66 69 6c 65 20 63 6f 70 79 20 2d 66 ....file copy -f
57e0: 6f 72 63 65 20 2d 2d 20 24 6c 6f 63 61 6c 63 61 orce -- $localca
57f0: 63 68 65 66 69 6c 65 20 24 74 6d 70 6c 6f 63 61 chefile $tmploca
5800: 6c 70 61 74 68 0a 0a 09 09 09 09 09 69 66 20 7b lpath.......if {
5810: 24 70 6b 67 70 61 74 68 69 6e 66 6f 28 70 65 72 $pkgpathinfo(per
5820: 6d 73 29 20 3d 3d 20 22 78 22 7d 20 7b 0a 09 09 ms) == "x"} {...
5830: 09 09 09 09 66 69 6c 65 20 61 74 74 72 69 62 75 ....file attribu
5840: 74 65 73 20 24 74 6d 70 6c 6f 63 61 6c 70 61 74 tes $tmplocalpat
5850: 68 20 2d 70 65 72 6d 69 73 73 69 6f 6e 73 20 2b h -permissions +
5860: 78 0a 09 09 09 09 09 7d 0a 0a 09 09 09 09 09 66 x......}.......f
5870: 69 6c 65 20 72 65 6e 61 6d 65 20 2d 66 6f 72 63 ile rename -forc
5880: 65 20 2d 2d 20 24 74 6d 70 6c 6f 63 61 6c 70 61 e -- $tmplocalpa
5890: 74 68 20 24 6c 6f 63 61 6c 70 61 74 68 0a 09 09 th $localpath...
58a0: 09 09 7d 20 65 72 72 5d 7d 20 7b 0a 09 09 09 09 ..} err]} {.....
58b0: 09 73 65 74 20 66 61 69 6c 65 64 20 31 0a 09 09 .set failed 1...
58c0: 09 09 7d 0a 09 09 09 09 63 61 74 63 68 20 7b 0a ..}.....catch {.
58d0: 09 09 09 09 09 66 69 6c 65 20 64 65 6c 65 74 65 .....file delete
58e0: 20 2d 66 6f 72 63 65 20 2d 2d 20 24 74 6d 70 6c -force -- $tmpl
58f0: 6f 63 61 6c 70 61 74 68 0a 09 09 09 09 7d 0a 09 ocalpath.....}..
5900: 09 09 7d 0a 0a 09 09 09 69 66 20 7b 24 66 61 69 ..}.....if {$fai
5910: 6c 65 64 7d 20 7b 0a 09 09 09 09 72 65 74 75 72 led} {.....retur
5920: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 24 65 n -code error $e
5930: 72 72 0a 09 09 09 7d 0a 0a 09 09 09 72 65 74 75 rr....}.....retu
5940: 72 6e 20 24 6c 6f 63 61 6c 70 61 74 68 0a 09 09 rn $localpath...
5950: 7d 0a 0a 09 09 72 65 74 75 72 6e 20 24 6c 6f 63 }....return $loc
5960: 61 6c 63 61 63 68 65 66 69 6c 65 0a 09 7d 0a 0a alcachefile..}..
5970: 09 70 72 6f 63 20 6c 6f 63 61 6c 70 61 74 68 20 .proc localpath
5980: 7b 70 61 74 68 7d 20 7b 0a 09 09 61 72 72 61 79 {path} {...array
5990: 20 73 65 74 20 70 61 74 68 69 6e 66 6f 20 5b 5f set pathinfo [_
59a0: 70 61 72 73 65 70 61 74 68 20 24 70 61 74 68 5d parsepath $path]
59b0: 0a 0a 09 09 69 66 20 7b 24 70 61 74 68 69 6e 66 ....if {$pathinf
59c0: 6f 28 5f 74 79 70 65 29 20 21 3d 20 22 66 69 6c o(_type) != "fil
59d0: 65 73 22 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e es"} {....return
59e0: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 69 6e -code error "in
59f0: 76 61 6c 69 64 20 74 79 70 65 22 0a 09 09 7d 0a valid type"...}.
5a00: 0a 09 09 73 65 74 20 6c 6f 63 61 6c 70 61 74 68 ...set localpath
5a10: 20 5b 5f 6c 6f 63 61 6c 70 61 74 68 20 24 70 61 [_localpath $pa
5a20: 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 20 thinfo(package)
5a30: 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 $pathinfo(hostna
5a40: 6d 65 29 20 24 70 61 74 68 69 6e 66 6f 28 66 69 me) $pathinfo(fi
5a50: 6c 65 29 5d 0a 0a 09 09 72 65 74 75 72 6e 20 24 le)]....return $
5a60: 6c 6f 63 61 6c 70 61 74 68 0a 09 7d 0a 0a 09 70 localpath..}...p
5a70: 72 6f 63 20 65 78 69 73 74 73 20 7b 70 61 74 68 roc exists {path
5a80: 7d 20 7b 0a 09 09 63 61 74 63 68 20 7b 0a 09 09 } {...catch {...
5a90: 09 73 65 74 20 69 6e 66 6f 20 5b 67 65 74 61 74 .set info [getat
5aa0: 74 72 20 24 70 61 74 68 5d 0a 09 09 7d 20 65 72 tr $path]...} er
5ab0: 72 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20 r....if {![info
5ac0: 65 78 69 73 74 73 20 69 6e 66 6f 5d 7d 20 7b 0a exists info]} {.
5ad0: 09 09 09 69 66 20 7b 24 65 72 72 20 3d 3d 20 22 ...if {$err == "
5ae0: 4e 6f 20 73 75 63 68 20 66 69 6c 65 20 6f 72 20 No such file or
5af0: 64 69 72 65 63 74 6f 72 79 22 7d 20 7b 0a 09 09 directory"} {...
5b00: 09 09 72 65 74 75 72 6e 20 5b 6c 69 73 74 5d 0a ..return [list].
5b10: 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 ...} else {.....
5b20: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 return -code err
5b30: 6f 72 20 24 65 72 72 0a 09 09 09 7d 0a 09 09 7d or $err....}...}
5b40: 0a 0a 09 09 72 65 74 75 72 6e 20 24 69 6e 66 6f ....return $info
5b50: 0a 09 7d 0a 0a 09 70 72 6f 63 20 70 72 65 70 61 ..}...proc prepa
5b60: 72 65 5f 74 6f 5f 63 72 65 61 74 65 20 7b 70 61 re_to_create {pa
5b70: 74 68 20 7b 6d 75 73 74 5f 6e 6f 74 5f 65 78 69 th {must_not_exi
5b80: 73 74 20 31 7d 7d 20 7b 0a 09 09 69 66 20 7b 24 st 1}} {...if {$
5b90: 6d 75 73 74 5f 6e 6f 74 5f 65 78 69 73 74 7d 20 must_not_exist}
5ba0: 7b 0a 09 09 09 69 66 20 7b 5b 65 78 69 73 74 73 {....if {[exists
5bb0: 20 24 70 61 74 68 5d 20 21 3d 20 22 22 7d 20 7b $path] != ""} {
5bc0: 0a 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 .....return -cod
5bd0: 65 20 65 72 72 6f 72 20 22 46 69 6c 65 20 61 6c e error "File al
5be0: 72 65 61 64 79 20 65 78 69 73 74 73 22 0a 09 09 ready exists"...
5bf0: 09 7d 0a 09 09 7d 0a 0a 09 09 73 65 74 20 66 69 .}...}....set fi
5c00: 6c 65 6e 61 6d 65 20 5b 6c 6f 63 61 6c 70 61 74 lename [localpat
5c10: 68 20 24 70 61 74 68 5d 0a 0a 09 09 69 66 20 7b h $path]....if {
5c20: 24 66 69 6c 65 6e 61 6d 65 20 3d 3d 20 22 22 7d $filename == ""}
5c30: 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f {....return -co
5c40: 64 65 20 65 72 72 6f 72 20 22 41 73 6b 65 64 20 de error "Asked
5c50: 74 6f 20 63 72 65 61 74 65 2c 20 62 75 74 20 6e to create, but n
5c60: 6f 20 68 6f 6d 65 20 64 69 72 65 63 74 6f 72 79 o home directory
5c70: 2e 22 0a 09 09 7d 0a 0a 09 09 73 65 74 20 64 69 ."...}....set di
5c80: 72 6e 61 6d 65 20 5b 66 69 6c 65 20 64 69 72 6e rname [file dirn
5c90: 61 6d 65 20 24 66 69 6c 65 6e 61 6d 65 5d 0a 0a ame $filename]..
5ca0: 09 09 5f 61 73 5f 75 73 65 72 20 7b 0a 09 09 09 .._as_user {....
5cb0: 66 69 6c 65 20 6d 6b 64 69 72 20 24 64 69 72 6e file mkdir $dirn
5cc0: 61 6d 65 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 ame...}....retur
5cd0: 6e 20 24 66 69 6c 65 6e 61 6d 65 0a 09 7d 0a 0a n $filename..}..
5ce0: 09 70 72 6f 63 20 75 6e 6c 69 6e 6b 70 61 74 68 .proc unlinkpath
5cf0: 20 7b 70 61 74 68 7d 20 7b 0a 09 09 61 72 72 61 {path} {...arra
5d00: 79 20 73 65 74 20 70 61 74 68 61 74 74 72 73 20 y set pathattrs
5d10: 5b 65 78 69 73 74 73 20 24 70 61 74 68 5d 0a 0a [exists $path]..
5d20: 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 ..if {![info exi
5d30: 73 74 73 20 70 61 74 68 61 74 74 72 73 28 70 61 sts pathattrs(pa
5d40: 63 6b 61 67 65 64 29 5d 7d 20 7b 0a 09 09 09 72 ckaged)]} {....r
5d50: 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f eturn -code erro
5d60: 72 20 22 69 6e 76 61 6c 69 64 20 74 79 70 65 22 r "invalid type"
5d70: 0a 09 09 7d 0a 0a 09 09 73 65 74 20 6c 6f 63 61 ...}....set loca
5d80: 6c 70 61 74 68 20 24 70 61 74 68 61 74 74 72 73 lpath $pathattrs
5d90: 28 6c 6f 63 61 6c 70 61 74 68 29 0a 0a 09 09 69 (localpath)....i
5da0: 66 20 7b 24 6c 6f 63 61 6c 70 61 74 68 20 3d 3d f {$localpath ==
5db0: 20 22 22 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e ""} {....return
5dc0: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 41 73 -code error "As
5dd0: 6b 65 64 20 74 6f 20 64 65 6c 65 74 65 2c 20 62 ked to delete, b
5de0: 75 74 20 6e 6f 20 68 6f 6d 65 20 64 69 72 65 63 ut no home direc
5df0: 74 6f 72 79 2e 22 0a 09 09 7d 0a 0a 09 09 69 66 tory."...}....if
5e00: 20 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 70 {[info exists p
5e10: 61 74 68 61 74 74 72 73 28 69 73 5f 6c 6f 63 61 athattrs(is_loca
5e20: 6c 66 69 6c 65 29 5d 7d 20 7b 0a 09 09 09 69 66 lfile)]} {....if
5e30: 20 7b 5b 66 69 6c 65 20 69 73 64 69 72 65 63 74 {[file isdirect
5e40: 6f 72 79 20 24 6c 6f 63 61 6c 70 61 74 68 5d 7d ory $localpath]}
5e50: 20 7b 0a 09 09 09 09 73 65 74 20 63 68 69 6c 64 {.....set child
5e60: 72 65 6e 20 5b 67 65 74 63 68 69 6c 64 72 65 6e ren [getchildren
5e70: 20 24 70 61 74 68 5d 0a 0a 09 09 09 09 69 66 20 $path]......if
5e80: 7b 5b 6c 6c 65 6e 67 74 68 20 24 63 68 69 6c 64 {[llength $child
5e90: 72 65 6e 5d 20 21 3d 20 30 7d 20 7b 0a 09 09 09 ren] != 0} {....
5ea0: 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 ..return -code e
5eb0: 72 72 6f 72 20 22 41 73 6b 65 64 20 74 6f 20 64 rror "Asked to d
5ec0: 65 6c 65 74 65 20 6e 6f 6e 2d 65 6d 70 74 79 20 elete non-empty
5ed0: 64 69 72 65 63 74 6f 72 79 22 0a 09 09 09 09 7d directory".....}
5ee0: 0a 09 09 09 7d 0a 0a 09 09 09 5f 61 73 5f 75 73 ....}....._as_us
5ef0: 65 72 20 7b 0a 09 09 09 09 66 69 6c 65 20 64 65 er {.....file de
5f00: 6c 65 74 65 20 2d 66 6f 72 63 65 20 2d 2d 20 24 lete -force -- $
5f10: 6c 6f 63 61 6c 70 61 74 68 0a 09 09 09 7d 0a 09 localpath....}..
5f20: 09 7d 20 65 6c 73 65 69 66 20 7b 5b 69 6e 66 6f .} elseif {[info
5f30: 20 65 78 69 73 74 73 20 70 61 74 68 61 74 74 72 exists pathattr
5f40: 73 28 69 73 5f 72 65 6d 6f 74 65 66 69 6c 65 29 s(is_remotefile)
5f50: 5d 7d 20 7b 0a 09 09 09 69 66 20 7b 24 70 61 74 ]} {....if {$pat
5f60: 68 61 74 74 72 73 28 74 79 70 65 29 20 3d 3d 20 hattrs(type) ==
5f70: 22 64 69 72 65 63 74 6f 72 79 22 7d 20 7b 0a 09 "directory"} {..
5f80: 09 09 09 73 65 74 20 63 68 69 6c 64 72 65 6e 20 ...set children
5f90: 5b 67 65 74 63 68 69 6c 64 72 65 6e 20 24 70 61 [getchildren $pa
5fa0: 74 68 5d 0a 0a 09 09 09 09 69 66 20 7b 5b 6c 6c th]......if {[ll
5fb0: 65 6e 67 74 68 20 24 63 68 69 6c 64 72 65 6e 5d ength $children]
5fc0: 20 21 3d 20 30 7d 20 7b 0a 09 09 09 09 09 72 65 != 0} {......re
5fd0: 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 turn -code error
5fe0: 20 22 41 73 6b 65 64 20 74 6f 20 64 65 6c 65 74 "Asked to delet
5ff0: 65 20 6e 6f 6e 2d 65 6d 70 74 79 20 64 69 72 65 e non-empty dire
6000: 63 74 6f 72 79 22 0a 09 09 09 09 7d 0a 09 09 09 ctory".....}....
6010: 7d 0a 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 }...} else {....
6020: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 return -code err
6030: 6f 72 20 22 55 6e 6b 6e 6f 77 6e 20 69 66 20 66 or "Unknown if f
6040: 69 6c 65 20 69 73 20 72 65 6d 6f 74 65 20 6f 72 ile is remote or
6050: 20 6c 6f 63 61 6c 20 21 3f 22 0a 09 09 7d 0a 0a local !?"...}..
6060: 09 09 73 65 74 20 77 68 69 74 65 6f 75 74 66 69 ..set whiteoutfi
6070: 6c 65 20 24 70 61 74 68 61 74 74 72 73 28 77 68 le $pathattrs(wh
6080: 69 74 65 6f 75 74 70 61 74 68 29 0a 09 09 73 65 iteoutpath)...se
6090: 74 20 77 68 69 74 65 6f 75 74 64 69 72 20 5b 66 t whiteoutdir [f
60a0: 69 6c 65 20 64 69 72 6e 61 6d 65 20 24 77 68 69 ile dirname $whi
60b0: 74 65 6f 75 74 66 69 6c 65 5d 0a 0a 09 09 5f 61 teoutfile]...._a
60c0: 73 5f 75 73 65 72 20 7b 0a 09 09 09 66 69 6c 65 s_user {....file
60d0: 20 6d 6b 64 69 72 20 24 77 68 69 74 65 6f 75 74 mkdir $whiteout
60e0: 64 69 72 0a 09 09 09 63 6c 6f 73 65 20 5b 6f 70 dir....close [op
60f0: 65 6e 20 24 77 68 69 74 65 6f 75 74 66 69 6c 65 en $whiteoutfile
6100: 20 77 5d 0a 09 09 7d 0a 09 7d 0a 7d 0a w]...}..}.}.