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 0a 6e 61 ire platform..na
0090: 6d 65 73 70 61 63 65 20 65 76 61 6c 20 3a 3a 61 mespace eval ::a
00a0: 70 70 66 73 20 7b 0a 09 76 61 72 69 61 62 6c 65 ppfs {..variable
00b0: 20 63 61 63 68 65 64 69 72 20 22 2f 74 6d 70 2f cachedir "/tmp/
00c0: 61 70 70 66 73 2d 63 61 63 68 65 22 0a 09 76 61 appfs-cache"..va
00d0: 72 69 61 62 6c 65 20 74 74 6c 20 33 36 30 30 0a riable ttl 3600.
00e0: 09 76 61 72 69 61 62 6c 65 20 6e 74 74 6c 20 36 .variable nttl 6
00f0: 30 0a 0a 09 23 20 55 73 65 72 2d 72 65 70 6c 61 0...# User-repla
0100: 63 61 62 6c 65 20 66 75 6e 63 74 69 6f 6e 20 74 cable function t
0110: 6f 20 63 6f 6e 76 65 72 74 20 61 20 68 6f 73 74 o convert a host
0120: 6e 61 6d 65 2f 68 61 73 68 2f 6d 65 74 68 6f 64 name/hash/method
0130: 20 74 6f 20 61 6e 20 55 52 4c 0a 09 70 72 6f 63 to an URL..proc
0140: 20 5f 63 6f 6e 73 74 72 75 63 74 5f 75 72 6c 20 _construct_url
0150: 7b 68 6f 73 74 6e 61 6d 65 20 68 61 73 68 20 6d {hostname hash m
0160: 65 74 68 6f 64 7d 20 7b 0a 09 09 72 65 74 75 72 ethod} {...retur
0170: 6e 20 22 68 74 74 70 3a 2f 2f 24 68 6f 73 74 6e n "http://$hostn
0180: 61 6d 65 2f 61 70 70 66 73 2f 24 6d 65 74 68 6f ame/appfs/$metho
0190: 64 2f 24 68 61 73 68 22 0a 09 7d 0a 0a 09 70 72 d/$hash"..}...pr
01a0: 6f 63 20 5f 68 61 73 68 5f 73 65 70 20 7b 68 61 oc _hash_sep {ha
01b0: 73 68 20 7b 73 65 70 73 20 34 7d 7d 20 7b 0a 09 sh {seps 4}} {..
01c0: 09 66 6f 72 20 7b 73 65 74 20 69 64 78 20 30 7d .for {set idx 0}
01d0: 20 7b 24 69 64 78 20 3c 20 24 73 65 70 73 7d 20 {$idx < $seps}
01e0: 7b 69 6e 63 72 20 69 64 78 7d 20 7b 0a 09 09 09 {incr idx} {....
01f0: 61 70 70 65 6e 64 20 72 65 74 76 61 6c 20 22 5b append retval "[
0200: 73 74 72 69 6e 67 20 72 61 6e 67 65 20 24 68 61 string range $ha
0210: 73 68 20 5b 65 78 70 72 20 7b 24 69 64 78 20 2a sh [expr {$idx *
0220: 20 32 7d 5d 20 5b 65 78 70 72 20 7b 28 24 69 64 2}] [expr {($id
0230: 78 20 2a 20 32 29 20 2b 20 31 7d 5d 5d 2f 22 0a x * 2) + 1}]]/".
0240: 09 09 7d 0a 09 09 61 70 70 65 6e 64 20 72 65 74 ..}...append ret
0250: 76 61 6c 20 22 5b 73 74 72 69 6e 67 20 72 61 6e val "[string ran
0260: 67 65 20 24 68 61 73 68 20 5b 65 78 70 72 20 7b ge $hash [expr {
0270: 24 69 64 78 20 2a 20 32 7d 5d 20 65 6e 64 5d 22 $idx * 2}] end]"
0280: 0a 0a 09 09 72 65 74 75 72 6e 20 24 72 65 74 76 ....return $retv
0290: 61 6c 0a 09 7d 0a 0a 09 70 72 6f 63 20 5f 63 61 al..}...proc _ca
02a0: 63 68 65 66 69 6c 65 20 7b 75 72 6c 20 6b 65 79 chefile {url key
02b0: 20 7b 6b 65 79 49 73 48 61 73 68 20 31 7d 7d 20 {keyIsHash 1}}
02c0: 7b 0a 09 09 73 65 74 20 66 69 6c 65 6b 65 79 20 {...set filekey
02d0: 24 6b 65 79 0a 09 09 69 66 20 7b 24 6b 65 79 49 $key...if {$keyI
02e0: 73 48 61 73 68 7d 20 7b 0a 09 09 09 73 65 74 20 sHash} {....set
02f0: 66 69 6c 65 6b 65 79 20 5b 5f 68 61 73 68 5f 73 filekey [_hash_s
0300: 65 70 20 24 66 69 6c 65 6b 65 79 5d 0a 09 09 7d ep $filekey]...}
0310: 0a 0a 09 09 73 65 74 20 66 69 6c 65 20 5b 66 69 ....set file [fi
0320: 6c 65 20 6a 6f 69 6e 20 24 3a 3a 61 70 70 66 73 le join $::appfs
0330: 3a 3a 63 61 63 68 65 64 69 72 20 24 66 69 6c 65 ::cachedir $file
0340: 6b 65 79 5d 0a 0a 09 09 66 69 6c 65 20 6d 6b 64 key]....file mkd
0350: 69 72 20 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65 ir [file dirname
0360: 20 24 66 69 6c 65 5d 0a 0a 09 09 69 66 20 7b 5b $file]....if {[
0370: 66 69 6c 65 20 65 78 69 73 74 73 20 24 66 69 6c file exists $fil
0380: 65 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 e]} {....return
0390: 24 66 69 6c 65 0a 09 09 7d 0a 0a 09 09 73 65 74 $file...}....set
03a0: 20 74 6d 70 66 69 6c 65 20 22 24 7b 66 69 6c 65 tmpfile "${file
03b0: 7d 2e 5b 65 78 70 72 20 7b 72 61 6e 64 28 29 7d }.[expr {rand()}
03c0: 5d 5b 63 6c 6f 63 6b 20 63 6c 69 63 6b 73 5d 22 ][clock clicks]"
03d0: 0a 0a 09 09 73 65 74 20 66 64 20 5b 6f 70 65 6e ....set fd [open
03e0: 20 24 74 6d 70 66 69 6c 65 20 22 77 22 5d 0a 09 $tmpfile "w"]..
03f0: 09 66 63 6f 6e 66 69 67 75 72 65 20 24 66 64 20 .fconfigure $fd
0400: 2d 74 72 61 6e 73 6c 61 74 69 6f 6e 20 62 69 6e -translation bin
0410: 61 72 79 0a 0a 09 09 63 61 74 63 68 20 7b 0a 09 ary....catch {..
0420: 09 09 73 65 74 20 74 6f 6b 65 6e 20 5b 3a 3a 68 ..set token [::h
0430: 74 74 70 3a 3a 67 65 74 75 72 6c 20 24 75 72 6c ttp::geturl $url
0440: 20 2d 63 68 61 6e 6e 65 6c 20 24 66 64 20 2d 62 -channel $fd -b
0450: 69 6e 61 72 79 20 74 72 75 65 5d 0a 09 09 7d 0a inary true]...}.
0460: 0a 09 09 69 66 20 7b 5b 69 6e 66 6f 20 65 78 69 ...if {[info exi
0470: 73 74 73 20 74 6f 6b 65 6e 5d 7d 20 7b 0a 09 09 sts token]} {...
0480: 09 73 65 74 20 6e 63 6f 64 65 20 5b 3a 3a 68 74 .set ncode [::ht
0490: 74 70 3a 3a 6e 63 6f 64 65 20 24 74 6f 6b 65 6e tp::ncode $token
04a0: 5d 0a 09 09 09 3a 3a 68 74 74 70 3a 3a 72 65 73 ]....::http::res
04b0: 65 74 20 24 74 6f 6b 65 6e 0a 09 09 7d 20 65 6c et $token...} el
04c0: 73 65 20 7b 0a 09 09 09 73 65 74 20 6e 63 6f 64 se {....set ncod
04d0: 65 20 22 39 30 30 22 0a 09 09 7d 0a 0a 09 09 63 e "900"...}....c
04e0: 6c 6f 73 65 20 24 66 64 0a 0a 09 09 69 66 20 7b lose $fd....if {
04f0: 24 6b 65 79 49 73 48 61 73 68 7d 20 7b 0a 09 09 $keyIsHash} {...
0500: 09 73 65 74 20 68 61 73 68 20 5b 73 74 72 69 6e .set hash [strin
0510: 67 20 74 6f 6c 6f 77 65 72 20 5b 73 68 61 31 3a g tolower [sha1:
0520: 3a 73 68 61 31 20 2d 68 65 78 20 2d 66 69 6c 65 :sha1 -hex -file
0530: 20 24 74 6d 70 66 69 6c 65 5d 5d 0a 09 09 7d 20 $tmpfile]]...}
0540: 65 6c 73 65 20 7b 0a 09 09 09 73 65 74 20 68 61 else {....set ha
0550: 73 68 20 24 6b 65 79 0a 09 09 7d 0a 0a 09 09 69 sh $key...}....i
0560: 66 20 7b 24 6e 63 6f 64 65 20 3d 3d 20 22 32 30 f {$ncode == "20
0570: 30 22 20 26 26 20 24 68 61 73 68 20 3d 3d 20 24 0" && $hash == $
0580: 6b 65 79 7d 20 7b 0a 09 09 09 66 69 6c 65 20 72 key} {....file r
0590: 65 6e 61 6d 65 20 2d 66 6f 72 63 65 20 2d 2d 20 ename -force --
05a0: 24 74 6d 70 66 69 6c 65 20 24 66 69 6c 65 0a 09 $tmpfile $file..
05b0: 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 66 69 6c .} else {....fil
05c0: 65 20 64 65 6c 65 74 65 20 2d 66 6f 72 63 65 20 e delete -force
05d0: 2d 2d 20 24 74 6d 70 66 69 6c 65 0a 09 09 7d 0a -- $tmpfile...}.
05e0: 0a 09 09 72 65 74 75 72 6e 20 24 66 69 6c 65 0a ...return $file.
05f0: 09 7d 0a 0a 0a 09 70 72 6f 63 20 5f 69 73 48 61 .}....proc _isHa
0600: 73 68 20 7b 76 61 6c 75 65 7d 20 7b 0a 09 09 73 sh {value} {...s
0610: 65 74 20 76 61 6c 75 65 20 5b 73 74 72 69 6e 67 et value [string
0620: 20 74 6f 6c 6f 77 65 72 20 24 76 61 6c 75 65 5d tolower $value]
0630: 0a 0a 09 09 69 66 20 7b 5b 73 74 72 69 6e 67 20 ....if {[string
0640: 6c 65 6e 67 74 68 20 24 76 61 6c 75 65 5d 20 21 length $value] !
0650: 3d 20 34 30 7d 20 7b 0a 09 09 09 72 65 74 75 72 = 40} {....retur
0660: 6e 20 66 61 6c 73 65 0a 09 09 7d 0a 0a 09 09 69 n false...}....i
0670: 66 20 7b 21 5b 72 65 67 65 78 70 20 7b 5e 5b 30 f {![regexp {^[0
0680: 2d 39 61 2d 66 5d 2a 24 7d 20 24 76 61 6c 75 65 -9a-f]*$} $value
0690: 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 66 ]} {....return f
06a0: 61 6c 73 65 0a 09 09 7d 0a 0a 09 09 72 65 74 75 alse...}....retu
06b0: 72 6e 20 74 72 75 65 0a 09 7d 0a 0a 09 70 72 6f rn true..}...pro
06c0: 63 20 5f 6e 6f 72 6d 61 6c 69 7a 65 4f 53 20 7b c _normalizeOS {
06d0: 6f 73 7d 20 7b 0a 09 09 73 65 74 20 6f 73 20 5b os} {...set os [
06e0: 73 74 72 69 6e 67 20 74 6f 6c 6f 77 65 72 20 5b string tolower [
06f0: 73 74 72 69 6e 67 20 74 72 69 6d 20 24 6f 73 5d string trim $os]
0700: 5d 0a 0a 09 09 73 77 69 74 63 68 20 2d 2d 20 24 ]....switch -- $
0710: 6f 73 20 7b 0a 09 09 09 22 6c 69 6e 75 78 22 20 os {...."linux"
0720: 2d 20 22 66 72 65 65 62 73 64 22 20 2d 20 22 6f - "freebsd" - "o
0730: 70 65 6e 62 73 64 22 20 2d 20 22 6e 65 74 62 73 penbsd" - "netbs
0740: 64 22 20 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 d" {.....return
0750: 24 6f 73 0a 09 09 09 7d 0a 09 09 09 22 73 75 6e $os....}...."sun
0760: 6f 73 22 20 7b 0a 09 09 09 09 72 65 74 75 72 6e os" {.....return
0770: 20 22 73 6f 6c 61 72 69 73 22 0a 09 09 09 7d 0a "solaris"....}.
0780: 09 09 09 22 6e 6f 61 72 63 68 22 20 2d 20 22 6e ..."noarch" - "n
0790: 6f 6e 65 22 20 2d 20 22 61 6e 79 22 20 2d 20 22 one" - "any" - "
07a0: 61 6c 6c 22 20 7b 0a 09 09 09 09 72 65 74 75 72 all" {.....retur
07b0: 6e 20 22 6e 6f 61 72 63 68 22 0a 09 09 09 7d 0a n "noarch"....}.
07c0: 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e 20 2d 63 ..}....return -c
07d0: 6f 64 65 20 65 72 72 6f 72 20 22 55 6e 61 62 6c ode error "Unabl
07e0: 65 20 74 6f 20 6e 6f 72 6d 61 6c 69 7a 65 20 4f e to normalize O
07f0: 53 3a 20 24 6f 73 22 0a 09 7d 0a 0a 09 70 72 6f S: $os"..}...pro
0800: 63 20 5f 6e 6f 72 6d 61 6c 69 7a 65 43 50 55 20 c _normalizeCPU
0810: 7b 63 70 75 7d 20 7b 0a 09 09 73 65 74 20 63 70 {cpu} {...set cp
0820: 75 20 5b 73 74 72 69 6e 67 20 74 6f 6c 6f 77 65 u [string tolowe
0830: 72 20 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 24 r [string trim $
0840: 63 70 75 5d 5d 0a 0a 09 09 73 77 69 74 63 68 20 cpu]]....switch
0850: 2d 67 6c 6f 62 20 2d 2d 20 24 63 70 75 20 7b 0a -glob -- $cpu {.
0860: 09 09 09 22 69 3f 38 36 22 20 7b 0a 09 09 09 09 ..."i?86" {.....
0870: 72 65 74 75 72 6e 20 22 69 78 38 36 22 0a 09 09 return "ix86"...
0880: 09 7d 0a 09 09 09 22 78 38 36 5f 36 34 22 20 7b .}...."x86_64" {
0890: 0a 09 09 09 09 72 65 74 75 72 6e 20 24 63 70 75 .....return $cpu
08a0: 0a 09 09 09 7d 0a 09 09 09 22 6e 6f 61 72 63 68 ....}...."noarch
08b0: 22 20 2d 20 22 6e 6f 6e 65 22 20 2d 20 22 61 6e " - "none" - "an
08c0: 79 22 20 2d 20 22 61 6c 6c 22 20 7b 0a 09 09 09 y" - "all" {....
08d0: 09 72 65 74 75 72 6e 20 22 6e 6f 61 72 63 68 22 .return "noarch"
08e0: 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74 ....}...}....ret
08f0: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 urn -code error
0900: 22 55 6e 61 62 6c 65 20 74 6f 20 6e 6f 72 6d 61 "Unable to norma
0910: 6c 69 7a 65 20 43 50 55 3a 20 24 63 70 75 22 0a lize CPU: $cpu".
0920: 09 7d 0a 0a 09 70 72 6f 63 20 69 6e 69 74 20 7b .}...proc init {
0930: 7d 20 7b 0a 09 09 69 66 20 7b 5b 69 6e 66 6f 20 } {...if {[info
0940: 65 78 69 73 74 73 20 3a 3a 61 70 70 66 73 3a 3a exists ::appfs::
0950: 69 6e 69 74 5f 63 61 6c 6c 65 64 5d 7d 20 7b 0a init_called]} {.
0960: 09 09 09 72 65 74 75 72 6e 0a 09 09 7d 0a 0a 09 ...return...}...
0970: 09 23 20 46 6f 72 63 65 20 5b 70 61 72 72 61 79 .# Force [parray
0980: 5d 20 74 6f 20 62 65 20 6c 6f 61 64 65 64 0a 09 ] to be loaded..
0990: 09 63 61 74 63 68 20 7b 0a 09 09 09 70 61 72 72 .catch {....parr
09a0: 61 79 20 64 6f 65 73 5f 6e 6f 74 5f 65 78 69 73 ay does_not_exis
09b0: 74 0a 09 09 7d 0a 0a 09 09 73 65 74 20 3a 3a 61 t...}....set ::a
09c0: 70 70 66 73 3a 3a 69 6e 69 74 5f 63 61 6c 6c 65 ppfs::init_calle
09d0: 64 20 31 0a 0a 09 09 23 20 4c 6f 61 64 20 63 6f d 1....# Load co
09e0: 6e 66 69 67 75 72 61 74 69 6f 6e 20 66 69 6c 65 nfiguration file
09f0: 0a 09 09 73 65 74 20 63 6f 6e 66 69 67 5f 66 69 ...set config_fi
0a00: 6c 65 20 5b 66 69 6c 65 20 6a 6f 69 6e 20 24 3a le [file join $:
0a10: 3a 61 70 70 66 73 3a 3a 63 61 63 68 65 64 69 72 :appfs::cachedir
0a20: 20 63 6f 6e 66 69 67 5d 0a 09 09 69 66 20 7b 5b config]...if {[
0a30: 66 69 6c 65 20 65 78 69 73 74 73 20 24 63 6f 6e file exists $con
0a40: 66 69 67 5f 66 69 6c 65 5d 7d 20 7b 0a 09 09 09 fig_file]} {....
0a50: 73 6f 75 72 63 65 20 24 63 6f 6e 66 69 67 5f 66 source $config_f
0a60: 69 6c 65 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 21 ile...}....if {!
0a70: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 3a 3a 61 [info exists ::a
0a80: 70 70 66 73 3a 3a 64 62 5d 7d 20 7b 0a 09 09 09 ppfs::db]} {....
0a90: 66 69 6c 65 20 6d 6b 64 69 72 20 24 3a 3a 61 70 file mkdir $::ap
0aa0: 70 66 73 3a 3a 63 61 63 68 65 64 69 72 0a 0a 09 pfs::cachedir...
0ab0: 09 09 73 71 6c 69 74 65 33 20 3a 3a 61 70 70 66 ..sqlite3 ::appf
0ac0: 73 3a 3a 64 62 20 5b 66 69 6c 65 20 6a 6f 69 6e s::db [file join
0ad0: 20 24 3a 3a 61 70 70 66 73 3a 3a 63 61 63 68 65 $::appfs::cache
0ae0: 64 69 72 20 63 61 63 68 65 2e 64 62 5d 0a 09 09 dir cache.db]...
0af0: 7d 0a 0a 09 09 23 20 43 72 65 61 74 65 20 74 61 }....# Create ta
0b00: 62 6c 65 73 0a 09 09 64 62 20 65 76 61 6c 20 7b bles...db eval {
0b10: 43 52 45 41 54 45 20 54 41 42 4c 45 20 49 46 20 CREATE TABLE IF
0b20: 4e 4f 54 20 45 58 49 53 54 53 20 73 69 74 65 73 NOT EXISTS sites
0b30: 28 68 6f 73 74 6e 61 6d 65 20 50 52 49 4d 41 52 (hostname PRIMAR
0b40: 59 20 4b 45 59 2c 20 6c 61 73 74 55 70 64 61 74 Y KEY, lastUpdat
0b50: 65 2c 20 74 74 6c 29 3b 7d 0a 09 09 64 62 20 65 e, ttl);}...db e
0b60: 76 61 6c 20 7b 43 52 45 41 54 45 20 54 41 42 4c val {CREATE TABL
0b70: 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53 20 E IF NOT EXISTS
0b80: 70 61 63 6b 61 67 65 73 28 68 6f 73 74 6e 61 6d packages(hostnam
0b90: 65 2c 20 73 68 61 31 2c 20 70 61 63 6b 61 67 65 e, sha1, package
0ba0: 2c 20 76 65 72 73 69 6f 6e 2c 20 6f 73 2c 20 63 , version, os, c
0bb0: 70 75 41 72 63 68 2c 20 69 73 4c 61 74 65 73 74 puArch, isLatest
0bc0: 2c 20 68 61 76 65 4d 61 6e 69 66 65 73 74 29 3b , haveManifest);
0bd0: 7d 0a 09 09 64 62 20 65 76 61 6c 20 7b 43 52 45 }...db eval {CRE
0be0: 41 54 45 20 54 41 42 4c 45 20 49 46 20 4e 4f 54 ATE TABLE IF NOT
0bf0: 20 45 58 49 53 54 53 20 66 69 6c 65 73 28 70 61 EXISTS files(pa
0c00: 63 6b 61 67 65 5f 73 68 61 31 2c 20 74 79 70 65 ckage_sha1, type
0c10: 2c 20 74 69 6d 65 2c 20 73 6f 75 72 63 65 2c 20 , time, source,
0c20: 73 69 7a 65 2c 20 70 65 72 6d 73 2c 20 66 69 6c size, perms, fil
0c30: 65 5f 73 68 61 31 2c 20 66 69 6c 65 5f 6e 61 6d e_sha1, file_nam
0c40: 65 2c 20 66 69 6c 65 5f 64 69 72 65 63 74 6f 72 e, file_director
0c50: 79 29 3b 7d 0a 0a 09 09 23 20 43 72 65 61 74 65 y);}....# Create
0c60: 20 69 6e 64 65 78 65 73 0a 09 09 64 62 20 65 76 indexes...db ev
0c70: 61 6c 20 7b 43 52 45 41 54 45 20 49 4e 44 45 58 al {CREATE INDEX
0c80: 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53 20 73 IF NOT EXISTS s
0c90: 69 74 65 73 5f 69 6e 64 65 78 20 4f 4e 20 73 69 ites_index ON si
0ca0: 74 65 73 20 28 68 6f 73 74 6e 61 6d 65 29 3b 7d tes (hostname);}
0cb0: 0a 09 09 64 62 20 65 76 61 6c 20 7b 43 52 45 41 ...db eval {CREA
0cc0: 54 45 20 49 4e 44 45 58 20 49 46 20 4e 4f 54 20 TE INDEX IF NOT
0cd0: 45 58 49 53 54 53 20 70 61 63 6b 61 67 65 73 5f EXISTS packages_
0ce0: 69 6e 64 65 78 20 4f 4e 20 70 61 63 6b 61 67 65 index ON package
0cf0: 73 20 28 68 6f 73 74 6e 61 6d 65 2c 20 70 61 63 s (hostname, pac
0d00: 6b 61 67 65 2c 20 76 65 72 73 69 6f 6e 2c 20 6f kage, version, o
0d10: 73 2c 20 63 70 75 41 72 63 68 29 3b 7d 0a 09 09 s, cpuArch);}...
0d20: 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54 45 20 db eval {CREATE
0d30: 49 4e 44 45 58 20 49 46 20 4e 4f 54 20 45 58 49 INDEX IF NOT EXI
0d40: 53 54 53 20 66 69 6c 65 73 5f 69 6e 64 65 78 20 STS files_index
0d50: 4f 4e 20 66 69 6c 65 73 20 28 70 61 63 6b 61 67 ON files (packag
0d60: 65 5f 73 68 61 31 2c 20 66 69 6c 65 5f 6e 61 6d e_sha1, file_nam
0d70: 65 2c 20 66 69 6c 65 5f 64 69 72 65 63 74 6f 72 e, file_director
0d80: 79 29 3b 7d 0a 09 7d 0a 0a 09 70 72 6f 63 20 64 y);}..}...proc d
0d90: 6f 77 6e 6c 6f 61 64 20 7b 68 6f 73 74 6e 61 6d ownload {hostnam
0da0: 65 20 68 61 73 68 20 7b 6d 65 74 68 6f 64 20 73 e hash {method s
0db0: 68 61 31 7d 7d 20 7b 0a 09 09 73 65 74 20 75 72 ha1}} {...set ur
0dc0: 6c 20 5b 5f 63 6f 6e 73 74 72 75 63 74 5f 75 72 l [_construct_ur
0dd0: 6c 20 24 68 6f 73 74 6e 61 6d 65 20 24 68 61 73 l $hostname $has
0de0: 68 20 24 6d 65 74 68 6f 64 5d 0a 09 09 73 65 74 h $method]...set
0df0: 20 66 69 6c 65 20 5b 5f 63 61 63 68 65 66 69 6c file [_cachefil
0e00: 65 20 24 75 72 6c 20 24 68 61 73 68 5d 0a 0a 09 e $url $hash]...
0e10: 09 69 66 20 7b 21 5b 66 69 6c 65 20 65 78 69 73 .if {![file exis
0e20: 74 73 20 24 66 69 6c 65 5d 7d 20 7b 0a 09 09 09 ts $file]} {....
0e30: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 return -code err
0e40: 6f 72 20 22 55 6e 61 62 6c 65 20 74 6f 20 66 65 or "Unable to fe
0e50: 74 63 68 20 28 66 69 6c 65 20 64 6f 65 73 20 6e tch (file does n
0e60: 6f 74 20 65 78 69 73 74 3a 20 24 66 69 6c 65 29 ot exist: $file)
0e70: 22 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e 20 "...}....return
0e80: 24 66 69 6c 65 0a 09 7d 0a 0a 09 70 72 6f 63 20 $file..}...proc
0e90: 67 65 74 69 6e 64 65 78 20 7b 68 6f 73 74 6e 61 getindex {hostna
0ea0: 6d 65 7d 20 7b 0a 09 09 73 65 74 20 6e 6f 77 20 me} {...set now
0eb0: 5b 63 6c 6f 63 6b 20 73 65 63 6f 6e 64 73 5d 0a [clock seconds].
0ec0: 0a 09 09 73 65 74 20 6c 61 73 74 55 70 64 61 74 ...set lastUpdat
0ed0: 65 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 4c es [db eval {SEL
0ee0: 45 43 54 20 6c 61 73 74 55 70 64 61 74 65 2c 20 ECT lastUpdate,
0ef0: 74 74 6c 20 46 52 4f 4d 20 73 69 74 65 73 20 57 ttl FROM sites W
0f00: 48 45 52 45 20 68 6f 73 74 6e 61 6d 65 20 3d 20 HERE hostname =
0f10: 24 68 6f 73 74 6e 61 6d 65 20 4c 49 4d 49 54 20 $hostname LIMIT
0f20: 31 3b 7d 5d 0a 09 09 69 66 20 7b 5b 6c 6c 65 6e 1;}]...if {[llen
0f30: 67 74 68 20 24 6c 61 73 74 55 70 64 61 74 65 73 gth $lastUpdates
0f40: 5d 20 3d 3d 20 30 7d 20 7b 0a 09 09 09 73 65 74 ] == 0} {....set
0f50: 20 6c 61 73 74 55 70 64 61 74 65 20 30 0a 09 09 lastUpdate 0...
0f60: 09 73 65 74 20 74 74 6c 20 30 0a 09 09 7d 20 65 .set ttl 0...} e
0f70: 6c 73 65 20 7b 0a 09 09 09 73 65 74 20 6c 61 73 lse {....set las
0f80: 74 55 70 64 61 74 65 20 5b 6c 69 6e 64 65 78 20 tUpdate [lindex
0f90: 24 6c 61 73 74 55 70 64 61 74 65 73 20 30 5d 0a $lastUpdates 0].
0fa0: 09 09 09 73 65 74 20 74 74 6c 20 5b 6c 69 6e 64 ...set ttl [lind
0fb0: 65 78 20 24 6c 61 73 74 55 70 64 61 74 65 73 20 ex $lastUpdates
0fc0: 31 5d 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 24 6e 1]...}....if {$n
0fd0: 6f 77 20 3c 20 28 24 6c 61 73 74 55 70 64 61 74 ow < ($lastUpdat
0fe0: 65 20 2b 20 24 74 74 6c 29 7d 20 7b 0a 09 09 09 e + $ttl)} {....
0ff0: 72 65 74 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a return COMPLETE.
1000: 09 09 7d 0a 0a 09 09 69 66 20 7b 5b 73 74 72 69 ..}....if {[stri
1010: 6e 67 20 6d 61 74 63 68 20 22 2a 5c 5b 2f 7e 5c ng match "*\[/~\
1020: 5d 2a 22 20 24 68 6f 73 74 6e 61 6d 65 5d 7d 20 ]*" $hostname]}
1030: 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 {....return -cod
1040: 65 20 65 72 72 6f 72 20 22 49 6e 76 61 6c 69 64 e error "Invalid
1050: 20 68 6f 73 74 6e 61 6d 65 22 0a 09 09 7d 0a 0a hostname"...}..
1060: 09 09 73 65 74 20 75 72 6c 20 22 68 74 74 70 3a ..set url "http:
1070: 2f 2f 24 68 6f 73 74 6e 61 6d 65 2f 61 70 70 66 //$hostname/appf
1080: 73 2f 69 6e 64 65 78 22 0a 0a 09 09 63 61 74 63 s/index"....catc
1090: 68 20 7b 0a 09 09 09 73 65 74 20 74 6f 6b 65 6e h {....set token
10a0: 20 5b 3a 3a 68 74 74 70 3a 3a 67 65 74 75 72 6c [::http::geturl
10b0: 20 24 75 72 6c 5d 0a 09 09 09 69 66 20 7b 5b 3a $url]....if {[:
10c0: 3a 68 74 74 70 3a 3a 6e 63 6f 64 65 20 24 74 6f :http::ncode $to
10d0: 6b 65 6e 5d 20 3d 3d 20 22 32 30 30 22 7d 20 7b ken] == "200"} {
10e0: 0a 09 09 09 09 73 65 74 20 69 6e 64 65 78 68 61 .....set indexha
10f0: 73 68 5f 64 61 74 61 20 5b 3a 3a 68 74 74 70 3a sh_data [::http:
1100: 3a 64 61 74 61 20 24 74 6f 6b 65 6e 5d 0a 09 09 :data $token]...
1110: 09 7d 0a 09 09 09 3a 3a 68 74 74 70 3a 3a 72 65 .}....::http::re
1120: 73 65 74 20 24 74 6f 6b 65 6e 0a 09 09 09 3a 3a set $token....::
1130: 68 74 74 70 3a 3a 63 6c 65 61 6e 75 70 20 24 74 http::cleanup $t
1140: 6f 6b 65 6e 0a 09 09 7d 0a 0a 09 09 69 66 20 7b oken...}....if {
1150: 21 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 69 6e ![info exists in
1160: 64 65 78 68 61 73 68 5f 64 61 74 61 5d 7d 20 7b dexhash_data]} {
1170: 0a 09 09 09 23 20 43 61 63 68 65 20 74 68 69 73 ....# Cache this
1180: 20 72 65 73 75 6c 74 20 66 6f 72 20 36 30 20 73 result for 60 s
1190: 65 63 6f 6e 64 73 0a 09 09 09 64 62 20 65 76 61 econds....db eva
11a0: 6c 20 7b 49 4e 53 45 52 54 20 4f 52 20 52 45 50 l {INSERT OR REP
11b0: 4c 41 43 45 20 49 4e 54 4f 20 73 69 74 65 73 20 LACE INTO sites
11c0: 28 68 6f 73 74 6e 61 6d 65 2c 20 6c 61 73 74 55 (hostname, lastU
11d0: 70 64 61 74 65 2c 20 74 74 6c 29 20 56 41 4c 55 pdate, ttl) VALU
11e0: 45 53 20 28 24 68 6f 73 74 6e 61 6d 65 2c 20 24 ES ($hostname, $
11f0: 6e 6f 77 2c 20 24 3a 3a 61 70 70 66 73 3a 3a 6e now, $::appfs::n
1200: 74 74 6c 29 3b 7d 0a 0a 09 09 09 72 65 74 75 72 ttl);}.....retur
1210: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 55 n -code error "U
1220: 6e 61 62 6c 65 20 74 6f 20 66 65 74 63 68 20 24 nable to fetch $
1230: 75 72 6c 22 0a 09 09 7d 0a 0a 09 09 73 65 74 20 url"...}....set
1240: 69 6e 64 65 78 68 61 73 68 20 5b 6c 69 6e 64 65 indexhash [linde
1250: 78 20 5b 73 70 6c 69 74 20 24 69 6e 64 65 78 68 x [split $indexh
1260: 61 73 68 5f 64 61 74 61 20 22 2c 22 5d 20 30 5d ash_data ","] 0]
1270: 0a 0a 09 09 69 66 20 7b 21 5b 5f 69 73 48 61 73 ....if {![_isHas
1280: 68 20 24 69 6e 64 65 78 68 61 73 68 5d 7d 20 7b h $indexhash]} {
1290: 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 ....return -code
12a0: 20 65 72 72 6f 72 20 22 49 6e 76 61 6c 69 64 20 error "Invalid
12b0: 68 61 73 68 3a 20 24 69 6e 64 65 78 68 61 73 68 hash: $indexhash
12c0: 22 0a 09 09 7d 0a 0a 09 09 73 65 74 20 66 69 6c "...}....set fil
12d0: 65 20 5b 64 6f 77 6e 6c 6f 61 64 20 24 68 6f 73 e [download $hos
12e0: 74 6e 61 6d 65 20 24 69 6e 64 65 78 68 61 73 68 tname $indexhash
12f0: 5d 0a 09 09 73 65 74 20 66 64 20 5b 6f 70 65 6e ]...set fd [open
1300: 20 24 66 69 6c 65 5d 0a 09 09 73 65 74 20 64 61 $file]...set da
1310: 74 61 20 5b 72 65 61 64 20 24 66 64 5d 0a 09 09 ta [read $fd]...
1320: 63 6c 6f 73 65 20 24 66 64 0a 0a 09 09 73 65 74 close $fd....set
1330: 20 63 75 72 72 5f 70 61 63 6b 61 67 65 73 20 5b curr_packages [
1340: 6c 69 73 74 5d 0a 09 09 66 6f 72 65 61 63 68 20 list]...foreach
1350: 6c 69 6e 65 20 5b 73 70 6c 69 74 20 24 64 61 74 line [split $dat
1360: 61 20 22 5c 6e 22 5d 20 7b 0a 09 09 09 73 65 74 a "\n"] {....set
1370: 20 6c 69 6e 65 20 5b 73 74 72 69 6e 67 20 74 72 line [string tr
1380: 69 6d 20 24 6c 69 6e 65 5d 0a 0a 09 09 09 69 66 im $line].....if
1390: 20 7b 5b 73 74 72 69 6e 67 20 6d 61 74 63 68 20 {[string match
13a0: 22 2a 2f 2a 22 20 24 6c 69 6e 65 5d 7d 20 7b 0a "*/*" $line]} {.
13b0: 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 ....continue....
13c0: 7d 0a 0a 09 09 09 69 66 20 7b 24 6c 69 6e 65 20 }.....if {$line
13d0: 3d 3d 20 22 22 7d 20 7b 0a 09 09 09 09 63 6f 6e == ""} {.....con
13e0: 74 69 6e 75 65 0a 09 09 09 7d 0a 0a 09 09 09 73 tinue....}.....s
13f0: 65 74 20 77 6f 72 6b 20 5b 73 70 6c 69 74 20 24 et work [split $
1400: 6c 69 6e 65 20 22 2c 22 5d 0a 0a 09 09 09 75 6e line ","].....un
1410: 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 set -nocomplain
1420: 70 6b 67 49 6e 66 6f 0a 09 09 09 69 66 20 7b 5b pkgInfo....if {[
1430: 63 61 74 63 68 20 7b 0a 09 09 09 09 73 65 74 20 catch {.....set
1440: 70 6b 67 49 6e 66 6f 28 70 61 63 6b 61 67 65 29 pkgInfo(package)
1450: 20 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 [lindex $work
1460: 30 5d 0a 09 09 09 09 73 65 74 20 70 6b 67 49 6e 0].....set pkgIn
1470: 66 6f 28 76 65 72 73 69 6f 6e 29 20 20 5b 6c 69 fo(version) [li
1480: 6e 64 65 78 20 24 77 6f 72 6b 20 31 5d 0a 09 09 ndex $work 1]...
1490: 09 09 73 65 74 20 70 6b 67 49 6e 66 6f 28 6f 73 ..set pkgInfo(os
14a0: 29 20 20 20 20 20 20 20 5b 5f 6e 6f 72 6d 61 6c ) [_normal
14b0: 69 7a 65 4f 53 20 5b 6c 69 6e 64 65 78 20 24 77 izeOS [lindex $w
14c0: 6f 72 6b 20 32 5d 5d 0a 09 09 09 09 73 65 74 20 ork 2]].....set
14d0: 70 6b 67 49 6e 66 6f 28 63 70 75 41 72 63 68 29 pkgInfo(cpuArch)
14e0: 20 20 5b 5f 6e 6f 72 6d 61 6c 69 7a 65 43 50 55 [_normalizeCPU
14f0: 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 33 [lindex $work 3
1500: 5d 5d 0a 09 09 09 09 73 65 74 20 70 6b 67 49 6e ]].....set pkgIn
1510: 66 6f 28 68 61 73 68 29 20 20 20 20 20 5b 73 74 fo(hash) [st
1520: 72 69 6e 67 20 74 6f 6c 6f 77 65 72 20 5b 6c 69 ring tolower [li
1530: 6e 64 65 78 20 24 77 6f 72 6b 20 34 5d 5d 0a 09 ndex $work 4]]..
1540: 09 09 09 73 65 74 20 70 6b 67 49 6e 66 6f 28 68 ...set pkgInfo(h
1550: 61 73 68 5f 74 79 70 65 29 20 22 73 68 61 31 22 ash_type) "sha1"
1560: 0a 09 09 09 09 73 65 74 20 70 6b 67 49 6e 66 6f .....set pkgInfo
1570: 28 69 73 4c 61 74 65 73 74 29 20 5b 65 78 70 72 (isLatest) [expr
1580: 20 7b 21 21 5b 6c 69 6e 64 65 78 20 24 77 6f 72 {!![lindex $wor
1590: 6b 20 35 5d 7d 5d 0a 09 09 09 7d 5d 7d 20 7b 0a k 5]}]....}]} {.
15a0: 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 ....continue....
15b0: 7d 0a 0a 09 09 09 69 66 20 7b 21 5b 5f 69 73 48 }.....if {![_isH
15c0: 61 73 68 20 24 70 6b 67 49 6e 66 6f 28 68 61 73 ash $pkgInfo(has
15d0: 68 29 5d 7d 20 7b 0a 09 09 09 09 63 6f 6e 74 69 h)]} {.....conti
15e0: 6e 75 65 0a 09 09 09 7d 0a 0a 09 09 09 6c 61 70 nue....}.....lap
15f0: 70 65 6e 64 20 63 75 72 72 5f 70 61 63 6b 61 67 pend curr_packag
1600: 65 73 20 24 70 6b 67 49 6e 66 6f 28 68 61 73 68 es $pkgInfo(hash
1610: 29 0a 0a 09 09 09 23 20 44 6f 20 6e 6f 74 20 64 ).....# Do not d
1620: 6f 20 61 6e 79 20 61 64 64 69 74 69 6f 6e 61 6c o any additional
1630: 20 77 6f 72 6b 20 69 66 20 77 65 20 61 6c 72 65 work if we alre
1640: 61 64 79 20 68 61 76 65 20 74 68 69 73 20 70 61 ady have this pa
1650: 63 6b 61 67 65 0a 09 09 09 73 65 74 20 65 78 69 ckage....set exi
1660: 73 74 69 6e 67 5f 70 61 63 6b 61 67 65 73 20 5b sting_packages [
1670: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 db eval {SELECT
1680: 70 61 63 6b 61 67 65 20 46 52 4f 4d 20 70 61 63 package FROM pac
1690: 6b 61 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 kages WHERE host
16a0: 6e 61 6d 65 20 3d 20 24 68 6f 73 74 6e 61 6d 65 name = $hostname
16b0: 20 41 4e 44 20 73 68 61 31 20 3d 20 24 70 6b 67 AND sha1 = $pkg
16c0: 49 6e 66 6f 28 68 61 73 68 29 3b 7d 5d 0a 09 09 Info(hash);}]...
16d0: 09 69 66 20 7b 5b 6c 73 65 61 72 63 68 20 2d 65 .if {[lsearch -e
16e0: 78 61 63 74 20 24 65 78 69 73 74 69 6e 67 5f 70 xact $existing_p
16f0: 61 63 6b 61 67 65 73 20 24 70 6b 67 49 6e 66 6f ackages $pkgInfo
1700: 28 70 61 63 6b 61 67 65 29 5d 20 21 3d 20 2d 31 (package)] != -1
1710: 7d 20 7b 0a 09 09 09 09 63 6f 6e 74 69 6e 75 65 } {.....continue
1720: 0a 09 09 09 7d 0a 0a 09 09 09 69 66 20 7b 24 70 ....}.....if {$p
1730: 6b 67 49 6e 66 6f 28 69 73 4c 61 74 65 73 74 29 kgInfo(isLatest)
1740: 7d 20 7b 0a 09 09 09 09 64 62 20 65 76 61 6c 20 } {.....db eval
1750: 7b 55 50 44 41 54 45 20 70 61 63 6b 61 67 65 73 {UPDATE packages
1760: 20 53 45 54 20 69 73 4c 61 74 65 73 74 20 3d 20 SET isLatest =
1770: 30 20 57 48 45 52 45 20 68 6f 73 74 6e 61 6d 65 0 WHERE hostname
1780: 20 3d 20 24 68 6f 73 74 6e 61 6d 65 20 41 4e 44 = $hostname AND
1790: 20 70 61 63 6b 61 67 65 20 3d 20 24 70 6b 67 49 package = $pkgI
17a0: 6e 66 6f 28 24 70 61 63 6b 61 67 65 29 20 41 4e nfo($package) AN
17b0: 44 20 6f 73 20 3d 20 24 70 6b 67 49 6e 66 6f 28 D os = $pkgInfo(
17c0: 24 70 61 63 6b 61 67 65 29 20 41 4e 44 20 63 70 $package) AND cp
17d0: 75 41 72 63 68 20 3d 20 24 70 6b 67 49 6e 66 6f uArch = $pkgInfo
17e0: 28 63 70 75 41 72 63 68 29 3b 7d 0a 09 09 09 7d (cpuArch);}....}
17f0: 0a 0a 09 09 09 64 62 20 65 76 61 6c 20 7b 49 4e .....db eval {IN
1800: 53 45 52 54 20 49 4e 54 4f 20 70 61 63 6b 61 67 SERT INTO packag
1810: 65 73 20 28 68 6f 73 74 6e 61 6d 65 2c 20 73 68 es (hostname, sh
1820: 61 31 2c 20 70 61 63 6b 61 67 65 2c 20 76 65 72 a1, package, ver
1830: 73 69 6f 6e 2c 20 6f 73 2c 20 63 70 75 41 72 63 sion, os, cpuArc
1840: 68 2c 20 69 73 4c 61 74 65 73 74 2c 20 68 61 76 h, isLatest, hav
1850: 65 4d 61 6e 69 66 65 73 74 29 20 56 41 4c 55 45 eManifest) VALUE
1860: 53 20 28 24 68 6f 73 74 6e 61 6d 65 2c 20 24 70 S ($hostname, $p
1870: 6b 67 49 6e 66 6f 28 68 61 73 68 29 2c 20 24 70 kgInfo(hash), $p
1880: 6b 67 49 6e 66 6f 28 70 61 63 6b 61 67 65 29 2c kgInfo(package),
1890: 20 24 70 6b 67 49 6e 66 6f 28 76 65 72 73 69 6f $pkgInfo(versio
18a0: 6e 29 2c 20 24 70 6b 67 49 6e 66 6f 28 6f 73 29 n), $pkgInfo(os)
18b0: 2c 20 24 70 6b 67 49 6e 66 6f 28 63 70 75 41 72 , $pkgInfo(cpuAr
18c0: 63 68 29 2c 20 24 70 6b 67 49 6e 66 6f 28 69 73 ch), $pkgInfo(is
18d0: 4c 61 74 65 73 74 29 2c 20 30 29 3b 7d 0a 09 09 Latest), 0);}...
18e0: 7d 0a 0a 09 09 23 20 4c 6f 6f 6b 20 66 6f 72 20 }....# Look for
18f0: 70 61 63 6b 61 67 65 73 20 74 68 61 74 20 68 61 packages that ha
1900: 76 65 20 62 65 65 6e 20 64 65 6c 65 74 65 64 0a ve been deleted.
1910: 09 09 73 65 74 20 66 6f 75 6e 64 5f 70 61 63 6b ..set found_pack
1920: 61 67 65 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 ages [db eval {S
1930: 45 4c 45 43 54 20 73 68 61 31 20 46 52 4f 4d 20 ELECT sha1 FROM
1940: 70 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 68 packages WHERE h
1950: 6f 73 74 6e 61 6d 65 20 3d 20 24 68 6f 73 74 6e ostname = $hostn
1960: 61 6d 65 3b 7d 5d 0a 09 09 66 6f 72 65 61 63 68 ame;}]...foreach
1970: 20 70 61 63 6b 61 67 65 20 24 66 6f 75 6e 64 5f package $found_
1980: 70 61 63 6b 61 67 65 73 20 7b 0a 09 09 09 73 65 packages {....se
1990: 74 20 66 6f 75 6e 64 5f 70 61 63 6b 61 67 65 73 t found_packages
19a0: 5f 61 72 72 28 24 70 61 63 6b 61 67 65 29 20 31 _arr($package) 1
19b0: 0a 09 09 7d 0a 0a 09 09 66 6f 72 65 61 63 68 20 ...}....foreach
19c0: 70 61 63 6b 61 67 65 20 24 63 75 72 72 5f 70 61 package $curr_pa
19d0: 63 6b 61 67 65 73 20 7b 0a 09 09 09 75 6e 73 65 ckages {....unse
19e0: 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 66 6f t -nocomplain fo
19f0: 75 6e 64 5f 70 61 63 6b 61 67 65 73 5f 61 72 72 und_packages_arr
1a00: 28 24 70 61 63 6b 61 67 65 29 0a 09 09 7d 0a 0a ($package)...}..
1a10: 09 09 66 6f 72 65 61 63 68 20 70 61 63 6b 61 67 ..foreach packag
1a20: 65 20 5b 61 72 72 61 79 20 6e 61 6d 65 73 20 66 e [array names f
1a30: 6f 75 6e 64 5f 70 61 63 6b 61 67 65 73 5f 61 72 ound_packages_ar
1a40: 72 5d 20 7b 0a 09 09 09 64 62 20 65 76 61 6c 20 r] {....db eval
1a50: 7b 44 45 4c 45 54 45 20 46 52 4f 4d 20 70 61 63 {DELETE FROM pac
1a60: 6b 61 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 kages WHERE host
1a70: 6e 61 6d 65 20 3d 20 24 68 6f 73 74 6e 61 6d 65 name = $hostname
1a80: 20 41 4e 44 20 73 68 61 31 20 3d 20 24 70 61 63 AND sha1 = $pac
1a90: 6b 61 67 65 3b 7d 0a 09 09 7d 0a 0a 09 09 64 62 kage;}...}....db
1aa0: 20 65 76 61 6c 20 7b 49 4e 53 45 52 54 20 4f 52 eval {INSERT OR
1ab0: 20 52 45 50 4c 41 43 45 20 49 4e 54 4f 20 73 69 REPLACE INTO si
1ac0: 74 65 73 20 28 68 6f 73 74 6e 61 6d 65 2c 20 6c tes (hostname, l
1ad0: 61 73 74 55 70 64 61 74 65 2c 20 74 74 6c 29 20 astUpdate, ttl)
1ae0: 56 41 4c 55 45 53 20 28 24 68 6f 73 74 6e 61 6d VALUES ($hostnam
1af0: 65 2c 20 24 6e 6f 77 2c 20 24 3a 3a 61 70 70 66 e, $now, $::appf
1b00: 73 3a 3a 74 74 6c 29 3b 7d 0a 0a 09 09 72 65 74 s::ttl);}....ret
1b10: 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 7d 0a urn COMPLETE..}.
1b20: 0a 09 70 72 6f 63 20 67 65 74 70 6b 67 6d 61 6e ..proc getpkgman
1b30: 69 66 65 73 74 20 7b 68 6f 73 74 6e 61 6d 65 20 ifest {hostname
1b40: 70 61 63 6b 61 67 65 5f 73 68 61 31 7d 20 7b 0a package_sha1} {.
1b50: 09 09 73 65 74 20 68 61 76 65 4d 61 6e 69 66 65 ..set haveManife
1b60: 73 74 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 sts [db eval {SE
1b70: 4c 45 43 54 20 68 61 76 65 4d 61 6e 69 66 65 73 LECT haveManifes
1b80: 74 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 20 t FROM packages
1b90: 57 48 45 52 45 20 73 68 61 31 20 3d 20 24 70 61 WHERE sha1 = $pa
1ba0: 63 6b 61 67 65 5f 73 68 61 31 20 4c 49 4d 49 54 ckage_sha1 LIMIT
1bb0: 20 31 3b 7d 5d 0a 09 09 73 65 74 20 68 61 76 65 1;}]...set have
1bc0: 4d 61 6e 69 66 65 73 74 20 5b 6c 69 6e 64 65 78 Manifest [lindex
1bd0: 20 24 68 61 76 65 4d 61 6e 69 66 65 73 74 73 20 $haveManifests
1be0: 30 5d 0a 0a 09 09 69 66 20 7b 24 68 61 76 65 4d 0]....if {$haveM
1bf0: 61 6e 69 66 65 73 74 7d 20 7b 0a 09 09 09 72 65 anifest} {....re
1c00: 74 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 09 turn COMPLETE...
1c10: 7d 0a 0a 09 09 69 66 20 7b 21 5b 5f 69 73 48 61 }....if {![_isHa
1c20: 73 68 20 24 70 61 63 6b 61 67 65 5f 73 68 61 31 sh $package_sha1
1c30: 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 46 ]} {....return F
1c40: 41 49 4c 0a 09 09 7d 0a 0a 09 09 73 65 74 20 66 AIL...}....set f
1c50: 69 6c 65 20 5b 64 6f 77 6e 6c 6f 61 64 20 24 68 ile [download $h
1c60: 6f 73 74 6e 61 6d 65 20 24 70 61 63 6b 61 67 65 ostname $package
1c70: 5f 73 68 61 31 5d 0a 09 09 73 65 74 20 66 64 20 _sha1]...set fd
1c80: 5b 6f 70 65 6e 20 24 66 69 6c 65 5d 0a 09 09 73 [open $file]...s
1c90: 65 74 20 70 6b 67 64 61 74 61 20 5b 72 65 61 64 et pkgdata [read
1ca0: 20 24 66 64 5d 0a 09 09 63 6c 6f 73 65 20 24 66 $fd]...close $f
1cb0: 64 0a 0a 09 09 64 62 20 74 72 61 6e 73 61 63 74 d....db transact
1cc0: 69 6f 6e 20 7b 0a 09 09 09 66 6f 72 65 61 63 68 ion {....foreach
1cd0: 20 6c 69 6e 65 20 5b 73 70 6c 69 74 20 24 70 6b line [split $pk
1ce0: 67 64 61 74 61 20 22 5c 6e 22 5d 20 7b 0a 09 09 gdata "\n"] {...
1cf0: 09 09 73 65 74 20 6c 69 6e 65 20 5b 73 74 72 69 ..set line [stri
1d00: 6e 67 20 74 72 69 6d 20 24 6c 69 6e 65 5d 0a 0a ng trim $line]..
1d10: 09 09 09 09 69 66 20 7b 24 6c 69 6e 65 20 3d 3d ....if {$line ==
1d20: 20 22 22 7d 20 7b 0a 09 09 09 09 09 63 6f 6e 74 ""} {......cont
1d30: 69 6e 75 65 0a 09 09 09 09 7d 0a 0a 09 09 09 09 inue.....}......
1d40: 73 65 74 20 77 6f 72 6b 20 5b 73 70 6c 69 74 20 set work [split
1d50: 24 6c 69 6e 65 20 22 2c 22 5d 0a 0a 09 09 09 09 $line ","]......
1d60: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 unset -nocomplai
1d70: 6e 20 66 69 6c 65 49 6e 66 6f 0a 09 09 09 09 73 n fileInfo.....s
1d80: 65 74 20 66 69 6c 65 49 6e 66 6f 28 74 79 70 65 et fileInfo(type
1d90: 29 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 ) [lindex $work
1da0: 30 5d 0a 09 09 09 09 73 65 74 20 66 69 6c 65 49 0].....set fileI
1db0: 6e 66 6f 28 74 69 6d 65 29 20 5b 6c 69 6e 64 65 nfo(time) [linde
1dc0: 78 20 24 77 6f 72 6b 20 31 5d 0a 0a 09 09 09 09 x $work 1]......
1dd0: 73 65 74 20 77 6f 72 6b 20 5b 6c 72 61 6e 67 65 set work [lrange
1de0: 20 24 77 6f 72 6b 20 32 20 65 6e 64 5d 0a 09 09 $work 2 end]...
1df0: 09 09 73 77 69 74 63 68 20 2d 2d 20 24 66 69 6c ..switch -- $fil
1e00: 65 49 6e 66 6f 28 74 79 70 65 29 20 7b 0a 09 09 eInfo(type) {...
1e10: 09 09 09 22 66 69 6c 65 22 20 7b 0a 09 09 09 09 ..."file" {.....
1e20: 09 09 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 73 ..set fileInfo(s
1e30: 69 7a 65 29 20 5b 6c 69 6e 64 65 78 20 24 77 6f ize) [lindex $wo
1e40: 72 6b 20 30 5d 0a 09 09 09 09 09 09 73 65 74 20 rk 0].......set
1e50: 66 69 6c 65 49 6e 66 6f 28 70 65 72 6d 73 29 20 fileInfo(perms)
1e60: 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 31 5d [lindex $work 1]
1e70: 0a 09 09 09 09 09 09 73 65 74 20 66 69 6c 65 49 .......set fileI
1e80: 6e 66 6f 28 73 68 61 31 29 20 5b 6c 69 6e 64 65 nfo(sha1) [linde
1e90: 78 20 24 77 6f 72 6b 20 32 5d 0a 0a 09 09 09 09 x $work 2]......
1ea0: 09 09 73 65 74 20 77 6f 72 6b 20 5b 6c 72 61 6e ..set work [lran
1eb0: 67 65 20 24 77 6f 72 6b 20 33 20 65 6e 64 5d 0a ge $work 3 end].
1ec0: 09 09 09 09 09 7d 0a 09 09 09 09 09 22 73 79 6d .....}......"sym
1ed0: 6c 69 6e 6b 22 20 7b 0a 09 09 09 09 09 09 73 65 link" {.......se
1ee0: 74 20 66 69 6c 65 49 6e 66 6f 28 73 6f 75 72 63 t fileInfo(sourc
1ef0: 65 29 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b e) [lindex $work
1f00: 20 30 5d 0a 09 09 09 09 09 09 73 65 74 20 77 6f 0].......set wo
1f10: 72 6b 20 5b 6c 72 61 6e 67 65 20 24 77 6f 72 6b rk [lrange $work
1f20: 20 31 20 65 6e 64 5d 0a 09 09 09 09 09 7d 0a 09 1 end]......}..
1f30: 09 09 09 7d 0a 0a 09 09 09 09 73 65 74 20 66 69 ...}......set fi
1f40: 6c 65 49 6e 66 6f 28 6e 61 6d 65 29 20 5b 6a 6f leInfo(name) [jo
1f50: 69 6e 20 24 77 6f 72 6b 20 22 2c 22 5d 0a 09 09 in $work ","]...
1f60: 09 09 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 6e ..set fileInfo(n
1f70: 61 6d 65 29 20 5b 73 70 6c 69 74 20 5b 73 74 72 ame) [split [str
1f80: 69 6e 67 20 74 72 69 6d 20 24 66 69 6c 65 49 6e ing trim $fileIn
1f90: 66 6f 28 6e 61 6d 65 29 20 22 2f 22 5d 20 22 2f fo(name) "/"] "/
1fa0: 22 5d 0a 09 09 09 09 73 65 74 20 66 69 6c 65 49 "].....set fileI
1fb0: 6e 66 6f 28 64 69 72 65 63 74 6f 72 79 29 20 5b nfo(directory) [
1fc0: 6a 6f 69 6e 20 5b 6c 72 61 6e 67 65 20 24 66 69 join [lrange $fi
1fd0: 6c 65 49 6e 66 6f 28 6e 61 6d 65 29 20 30 20 65 leInfo(name) 0 e
1fe0: 6e 64 2d 31 5d 20 22 2f 22 5d 0a 09 09 09 09 73 nd-1] "/"].....s
1ff0: 65 74 20 66 69 6c 65 49 6e 66 6f 28 6e 61 6d 65 et fileInfo(name
2000: 29 20 5b 6c 69 6e 64 65 78 20 24 66 69 6c 65 49 ) [lindex $fileI
2010: 6e 66 6f 28 6e 61 6d 65 29 20 65 6e 64 5d 0a 0a nfo(name) end]..
2020: 09 09 09 09 64 62 20 65 76 61 6c 20 7b 49 4e 53 ....db eval {INS
2030: 45 52 54 20 49 4e 54 4f 20 66 69 6c 65 73 20 28 ERT INTO files (
2040: 70 61 63 6b 61 67 65 5f 73 68 61 31 2c 20 74 79 package_sha1, ty
2050: 70 65 2c 20 74 69 6d 65 2c 20 73 6f 75 72 63 65 pe, time, source
2060: 2c 20 73 69 7a 65 2c 20 70 65 72 6d 73 2c 20 66 , size, perms, f
2070: 69 6c 65 5f 73 68 61 31 2c 20 66 69 6c 65 5f 6e ile_sha1, file_n
2080: 61 6d 65 2c 20 66 69 6c 65 5f 64 69 72 65 63 74 ame, file_direct
2090: 6f 72 79 29 20 56 41 4c 55 45 53 20 28 24 70 61 ory) VALUES ($pa
20a0: 63 6b 61 67 65 5f 73 68 61 31 2c 20 24 66 69 6c ckage_sha1, $fil
20b0: 65 49 6e 66 6f 28 74 79 70 65 29 2c 20 24 66 69 eInfo(type), $fi
20c0: 6c 65 49 6e 66 6f 28 74 69 6d 65 29 2c 20 24 66 leInfo(time), $f
20d0: 69 6c 65 49 6e 66 6f 28 73 6f 75 72 63 65 29 2c ileInfo(source),
20e0: 20 24 66 69 6c 65 49 6e 66 6f 28 73 69 7a 65 29 $fileInfo(size)
20f0: 2c 20 24 66 69 6c 65 49 6e 66 6f 28 70 65 72 6d , $fileInfo(perm
2100: 73 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28 73 68 s), $fileInfo(sh
2110: 61 31 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28 6e a1), $fileInfo(n
2120: 61 6d 65 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28 ame), $fileInfo(
2130: 64 69 72 65 63 74 6f 72 79 29 20 29 3b 7d 0a 09 directory) );}..
2140: 09 09 09 64 62 20 65 76 61 6c 20 7b 55 50 44 41 ...db eval {UPDA
2150: 54 45 20 70 61 63 6b 61 67 65 73 20 53 45 54 20 TE packages SET
2160: 68 61 76 65 4d 61 6e 69 66 65 73 74 20 3d 20 31 haveManifest = 1
2170: 20 57 48 45 52 45 20 73 68 61 31 20 3d 20 24 70 WHERE sha1 = $p
2180: 61 63 6b 61 67 65 5f 73 68 61 31 3b 7d 0a 09 09 ackage_sha1;}...
2190: 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e .}...}....return
21a0: 20 43 4f 4d 50 4c 45 54 45 0a 09 7d 0a 0a 09 70 COMPLETE..}...p
21b0: 72 6f 63 20 5f 6c 6f 63 61 6c 70 61 74 68 20 7b roc _localpath {
21c0: 70 61 63 6b 61 67 65 20 68 6f 73 74 6e 61 6d 65 package hostname
21d0: 20 66 69 6c 65 7d 20 7b 0a 09 09 73 65 74 20 68 file} {...set h
21e0: 6f 6d 65 64 69 72 20 5b 3a 3a 61 70 70 66 73 64 omedir [::appfsd
21f0: 3a 3a 67 65 74 5f 68 6f 6d 65 64 69 72 5d 0a 09 ::get_homedir]..
2200: 09 73 65 74 20 64 69 72 20 5b 66 69 6c 65 20 6a .set dir [file j
2210: 6f 69 6e 20 24 68 6f 6d 65 64 69 72 20 2e 61 70 oin $homedir .ap
2220: 70 66 73 20 22 2e 2f 24 7b 70 61 63 6b 61 67 65 pfs "./${package
2230: 7d 40 24 7b 68 6f 73 74 6e 61 6d 65 7d 22 20 22 }@${hostname}" "
2240: 2e 2f 24 7b 66 69 6c 65 7d 22 5d 0a 09 09 72 65 ./${file}"]...re
2250: 74 75 72 6e 20 24 64 69 72 0a 09 7d 0a 0a 09 70 turn $dir..}...p
2260: 72 6f 63 20 5f 70 61 72 73 65 70 61 74 68 20 7b roc _parsepath {
2270: 70 61 74 68 7d 20 7b 0a 09 09 73 65 74 20 70 61 path} {...set pa
2280: 74 68 20 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 th [string trim
2290: 24 70 61 74 68 20 22 2f 22 5d 0a 09 09 73 65 74 $path "/"]...set
22a0: 20 70 61 74 68 20 5b 73 70 6c 69 74 20 24 70 61 path [split $pa
22b0: 74 68 20 22 2f 22 5d 0a 09 09 73 65 74 20 70 61 th "/"]...set pa
22c0: 74 68 6c 65 6e 20 5b 6c 6c 65 6e 67 74 68 20 24 thlen [llength $
22d0: 70 61 74 68 5d 0a 0a 09 09 61 72 72 61 79 20 73 path]....array s
22e0: 65 74 20 72 65 74 76 61 6c 20 5b 6c 69 73 74 20 et retval [list
22f0: 5f 63 68 69 6c 64 72 65 6e 20 73 69 74 65 73 20 _children sites
2300: 5f 74 79 70 65 20 74 6f 70 6c 65 76 65 6c 5d 0a _type toplevel].
2310: 0a 09 09 69 66 20 7b 24 70 61 74 68 6c 65 6e 20 ...if {$pathlen
2320: 3e 20 30 7d 20 7b 0a 09 09 09 73 65 74 20 72 65 > 0} {....set re
2330: 74 76 61 6c 28 68 6f 73 74 6e 61 6d 65 29 20 5b tval(hostname) [
2340: 6c 69 6e 64 65 78 20 24 70 61 74 68 20 30 5d 0a lindex $path 0].
2350: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 5f 63 ...set retval(_c
2360: 68 69 6c 64 72 65 6e 29 20 70 61 63 6b 61 67 65 hildren) package
2370: 73 0a 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 s....set retval(
2380: 5f 74 79 70 65 29 20 73 69 74 65 73 0a 0a 09 09 _type) sites....
2390: 09 69 66 20 7b 24 70 61 74 68 6c 65 6e 20 3e 20 .if {$pathlen >
23a0: 31 7d 20 7b 0a 09 09 09 09 73 65 74 20 70 61 63 1} {.....set pac
23b0: 6b 61 67 65 20 5b 6c 69 6e 64 65 78 20 24 70 61 kage [lindex $pa
23c0: 74 68 20 31 5d 0a 09 09 09 09 69 66 20 7b 5b 73 th 1].....if {[s
23d0: 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 24 70 61 tring length $pa
23e0: 63 6b 61 67 65 5d 20 3d 3d 20 22 34 30 22 20 26 ckage] == "40" &
23f0: 26 20 5b 72 65 67 65 78 70 20 7b 5e 5b 61 2d 66 & [regexp {^[a-f
2400: 41 2d 46 30 2d 39 5d 2a 24 7d 20 24 70 61 63 6b A-F0-9]*$} $pack
2410: 61 67 65 5d 7d 20 7b 0a 09 09 09 09 09 73 65 74 age]} {......set
2420: 20 72 65 74 76 61 6c 28 70 61 63 6b 61 67 65 5f retval(package_
2430: 73 68 61 31 29 20 24 70 61 63 6b 61 67 65 0a 09 sha1) $package..
2440: 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 5f ....set retval(_
2450: 63 68 69 6c 64 72 65 6e 29 20 66 69 6c 65 73 0a children) files.
2460: 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
2470: 5f 74 79 70 65 29 20 66 69 6c 65 73 0a 0a 09 09 _type) files....
2480: 09 09 09 3a 3a 61 70 70 66 73 3a 3a 64 62 20 65 ...::appfs::db e
2490: 76 61 6c 20 7b 53 45 4c 45 43 54 20 70 61 63 6b val {SELECT pack
24a0: 61 67 65 2c 20 6f 73 2c 20 63 70 75 41 72 63 68 age, os, cpuArch
24b0: 2c 20 76 65 72 73 69 6f 6e 20 46 52 4f 4d 20 70 , version FROM p
24c0: 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 73 68 ackages WHERE sh
24d0: 61 31 20 3d 20 24 72 65 74 76 61 6c 28 70 61 63 a1 = $retval(pac
24e0: 6b 61 67 65 5f 73 68 61 31 29 3b 7d 20 70 6b 67 kage_sha1);} pkg
24f0: 69 6e 66 6f 20 7b 7d 0a 09 09 09 09 09 73 65 74 info {}......set
2500: 20 72 65 74 76 61 6c 28 70 61 63 6b 61 67 65 29 retval(package)
2510: 20 24 70 6b 67 69 6e 66 6f 28 70 61 63 6b 61 67 $pkginfo(packag
2520: 65 29 0a 09 09 09 09 09 73 65 74 20 72 65 74 76 e)......set retv
2530: 61 6c 28 6f 73 29 20 24 70 6b 67 69 6e 66 6f 28 al(os) $pkginfo(
2540: 6f 73 29 0a 09 09 09 09 09 73 65 74 20 72 65 74 os)......set ret
2550: 76 61 6c 28 63 70 75 29 20 24 70 6b 67 69 6e 66 val(cpu) $pkginf
2560: 6f 28 63 70 75 41 72 63 68 29 0a 09 09 09 09 09 o(cpuArch)......
2570: 73 65 74 20 72 65 74 76 61 6c 28 76 65 72 73 69 set retval(versi
2580: 6f 6e 29 20 24 70 6b 67 69 6e 66 6f 28 76 65 72 on) $pkginfo(ver
2590: 73 69 6f 6e 29 0a 0a 09 09 09 09 09 69 66 20 7b sion).......if {
25a0: 24 70 61 74 68 6c 65 6e 20 3e 20 32 7d 20 7b 0a $pathlen > 2} {.
25b0: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
25c0: 28 66 69 6c 65 29 20 5b 6a 6f 69 6e 20 5b 6c 72 (file) [join [lr
25d0: 61 6e 67 65 20 24 70 61 74 68 20 32 20 65 6e 64 ange $path 2 end
25e0: 5d 20 22 2f 22 5d 0a 09 09 09 09 09 7d 20 65 6c ] "/"]......} el
25f0: 73 65 20 7b 0a 09 09 09 09 09 09 73 65 74 20 72 se {.......set r
2600: 65 74 76 61 6c 28 66 69 6c 65 29 20 22 22 0a 09 etval(file) ""..
2610: 09 09 09 09 7d 0a 09 09 09 09 7d 20 65 6c 73 65 ....}.....} else
2620: 20 7b 0a 09 09 09 09 09 73 65 74 20 72 65 74 76 {......set retv
2630: 61 6c 28 70 61 63 6b 61 67 65 29 20 24 70 61 63 al(package) $pac
2640: 6b 61 67 65 0a 09 09 09 09 09 73 65 74 20 72 65 kage......set re
2650: 74 76 61 6c 28 5f 63 68 69 6c 64 72 65 6e 29 20 tval(_children)
2660: 6f 73 2d 63 70 75 0a 09 09 09 09 09 73 65 74 20 os-cpu......set
2670: 72 65 74 76 61 6c 28 5f 74 79 70 65 29 20 70 61 retval(_type) pa
2680: 63 6b 61 67 65 73 0a 0a 09 09 09 09 09 69 66 20 ckages.......if
2690: 7b 24 70 61 74 68 6c 65 6e 20 3e 20 32 7d 20 7b {$pathlen > 2} {
26a0: 0a 09 09 09 09 09 09 73 65 74 20 6f 73 5f 63 70 .......set os_cp
26b0: 75 20 5b 6c 69 6e 64 65 78 20 24 70 61 74 68 20 u [lindex $path
26c0: 32 5d 0a 09 09 09 09 09 09 73 65 74 20 6f 73 5f 2].......set os_
26d0: 63 70 75 20 5b 73 70 6c 69 74 20 24 6f 73 5f 63 cpu [split $os_c
26e0: 70 75 20 22 2d 22 5d 0a 0a 09 09 09 09 09 09 73 pu "-"]........s
26f0: 65 74 20 72 65 74 76 61 6c 28 6f 73 29 20 5b 6c et retval(os) [l
2700: 69 6e 64 65 78 20 24 6f 73 5f 63 70 75 20 30 5d index $os_cpu 0]
2710: 0a 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 .......set retva
2720: 6c 28 63 70 75 29 20 5b 6c 69 6e 64 65 78 20 24 l(cpu) [lindex $
2730: 6f 73 5f 63 70 75 20 31 5d 0a 09 09 09 09 09 09 os_cpu 1].......
2740: 73 65 74 20 72 65 74 76 61 6c 28 5f 63 68 69 6c set retval(_chil
2750: 64 72 65 6e 29 20 76 65 72 73 69 6f 6e 73 0a 09 dren) versions..
2760: 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
2770: 5f 74 79 70 65 29 20 6f 73 2d 63 70 75 0a 0a 09 _type) os-cpu...
2780: 09 09 09 09 09 69 66 20 7b 24 70 61 74 68 6c 65 .....if {$pathle
2790: 6e 20 3e 20 33 7d 20 7b 0a 09 09 09 09 09 09 09 n > 3} {........
27a0: 73 65 74 20 72 65 74 76 61 6c 28 76 65 72 73 69 set retval(versi
27b0: 6f 6e 29 20 5b 6c 69 6e 64 65 78 20 24 70 61 74 on) [lindex $pat
27c0: 68 20 33 5d 0a 09 09 09 09 09 09 09 73 65 74 20 h 3]........set
27d0: 72 65 74 76 61 6c 28 5f 63 68 69 6c 64 72 65 6e retval(_children
27e0: 29 20 66 69 6c 65 73 0a 09 09 09 09 09 09 09 73 ) files........s
27f0: 65 74 20 72 65 74 76 61 6c 28 5f 74 79 70 65 29 et retval(_type)
2800: 20 76 65 72 73 69 6f 6e 73 0a 0a 09 09 09 09 09 versions.......
2810: 09 09 73 65 74 20 72 65 74 76 61 6c 28 70 61 63 ..set retval(pac
2820: 6b 61 67 65 5f 73 68 61 31 29 20 5b 3a 3a 61 70 kage_sha1) [::ap
2830: 70 66 73 3a 3a 64 62 20 6f 6e 65 63 6f 6c 75 6d pfs::db onecolum
2840: 6e 20 7b 53 45 4c 45 43 54 20 73 68 61 31 20 46 n {SELECT sha1 F
2850: 52 4f 4d 20 70 61 63 6b 61 67 65 73 20 57 48 45 ROM packages WHE
2860: 52 45 20 68 6f 73 74 6e 61 6d 65 20 3d 20 24 72 RE hostname = $r
2870: 65 74 76 61 6c 28 68 6f 73 74 6e 61 6d 65 29 20 etval(hostname)
2880: 41 4e 44 20 6f 73 20 3d 20 24 72 65 74 76 61 6c AND os = $retval
2890: 28 6f 73 29 20 41 4e 44 20 63 70 75 41 72 63 68 (os) AND cpuArch
28a0: 20 3d 20 24 72 65 74 76 61 6c 28 63 70 75 29 20 = $retval(cpu)
28b0: 41 4e 44 20 76 65 72 73 69 6f 6e 20 3d 20 24 72 AND version = $r
28c0: 65 74 76 61 6c 28 76 65 72 73 69 6f 6e 29 3b 7d etval(version);}
28d0: 5d 0a 09 09 09 09 09 09 09 69 66 20 7b 24 72 65 ]........if {$re
28e0: 74 76 61 6c 28 70 61 63 6b 61 67 65 5f 73 68 61 tval(package_sha
28f0: 31 29 20 3d 3d 20 22 22 7d 20 7b 0a 09 09 09 09 1) == ""} {.....
2900: 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 5f ....set retval(_
2910: 63 68 69 6c 64 72 65 6e 29 20 64 65 61 64 0a 09 children) dead..
2920: 09 09 09 09 09 09 09 72 65 74 75 72 6e 20 5b 61 .......return [a
2930: 72 72 61 79 20 67 65 74 20 72 65 74 76 61 6c 5d rray get retval]
2940: 0a 09 09 09 09 09 09 09 7d 0a 0a 09 09 09 09 09 ........}.......
2950: 09 09 69 66 20 7b 24 70 61 74 68 6c 65 6e 20 3e ..if {$pathlen >
2960: 20 34 7d 20 7b 0a 09 09 09 09 09 09 09 09 73 65 4} {.........se
2970: 74 20 72 65 74 76 61 6c 28 5f 74 79 70 65 29 20 t retval(_type)
2980: 66 69 6c 65 73 0a 09 09 09 09 09 09 09 09 73 65 files.........se
2990: 74 20 72 65 74 76 61 6c 28 66 69 6c 65 29 20 5b t retval(file) [
29a0: 6a 6f 69 6e 20 5b 6c 72 61 6e 67 65 20 24 70 61 join [lrange $pa
29b0: 74 68 20 34 20 65 6e 64 5d 20 22 2f 22 5d 0a 09 th 4 end] "/"]..
29c0: 09 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 ......} else {..
29d0: 09 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 .......set retva
29e0: 6c 28 5f 74 79 70 65 29 20 66 69 6c 65 73 0a 09 l(_type) files..
29f0: 09 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 .......set retva
2a00: 6c 28 66 69 6c 65 29 20 22 22 0a 09 09 09 09 09 l(file) ""......
2a10: 09 09 7d 0a 09 09 09 09 09 09 7d 0a 09 09 09 09 ..}.......}.....
2a20: 09 7d 0a 09 09 09 09 7d 0a 09 09 09 7d 0a 09 09 .}.....}....}...
2a30: 7d 0a 0a 09 09 72 65 74 75 72 6e 20 5b 61 72 72 }....return [arr
2a40: 61 79 20 67 65 74 20 72 65 74 76 61 6c 5d 0a 09 ay get retval]..
2a50: 7d 0a 0a 09 70 72 6f 63 20 67 65 74 63 68 69 6c }...proc getchil
2a60: 64 72 65 6e 20 7b 64 69 72 7d 20 7b 0a 09 09 61 dren {dir} {...a
2a70: 72 72 61 79 20 73 65 74 20 70 61 74 68 69 6e 66 rray set pathinf
2a80: 6f 20 5b 5f 70 61 72 73 65 70 61 74 68 20 24 64 o [_parsepath $d
2a90: 69 72 5d 0a 0a 09 09 73 77 69 74 63 68 20 2d 2d ir]....switch --
2aa0: 20 24 70 61 74 68 69 6e 66 6f 28 5f 63 68 69 6c $pathinfo(_chil
2ab0: 64 72 65 6e 29 20 7b 0a 09 09 09 22 73 69 74 65 dren) {...."site
2ac0: 73 22 20 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 s" {.....return
2ad0: 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 65 76 61 [::appfs::db eva
2ae0: 6c 20 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e l {SELECT DISTIN
2af0: 43 54 20 68 6f 73 74 6e 61 6d 65 20 46 52 4f 4d CT hostname FROM
2b00: 20 70 61 63 6b 61 67 65 73 3b 7d 5d 0a 09 09 09 packages;}]....
2b10: 7d 0a 09 09 09 22 70 61 63 6b 61 67 65 73 22 20 }...."packages"
2b20: 7b 0a 09 09 09 09 63 61 74 63 68 20 7b 0a 09 09 {.....catch {...
2b30: 09 09 09 3a 3a 61 70 70 66 73 3a 3a 67 65 74 69 ...::appfs::geti
2b40: 6e 64 65 78 20 24 70 61 74 68 69 6e 66 6f 28 68 ndex $pathinfo(h
2b50: 6f 73 74 6e 61 6d 65 29 0a 09 09 09 09 7d 0a 0a ostname).....}..
2b60: 09 09 09 09 72 65 74 75 72 6e 20 5b 3a 3a 61 70 ....return [::ap
2b70: 70 66 73 3a 3a 64 62 20 65 76 61 6c 20 7b 53 45 pfs::db eval {SE
2b80: 4c 45 43 54 20 44 49 53 54 49 4e 43 54 20 70 61 LECT DISTINCT pa
2b90: 63 6b 61 67 65 20 46 52 4f 4d 20 70 61 63 6b 61 ckage FROM packa
2ba0: 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e 61 ges WHERE hostna
2bb0: 6d 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 68 me = $pathinfo(h
2bc0: 6f 73 74 6e 61 6d 65 29 3b 7d 5d 0a 09 09 09 7d ostname);}]....}
2bd0: 0a 09 09 09 22 6f 73 2d 63 70 75 22 20 7b 0a 09 ...."os-cpu" {..
2be0: 09 09 09 73 65 74 20 72 65 74 76 61 6c 20 5b 3a ...set retval [:
2bf0: 3a 61 70 70 66 73 3a 3a 64 62 20 65 76 61 6c 20 :appfs::db eval
2c00: 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e 43 54 {SELECT DISTINCT
2c10: 20 6f 73 20 7c 7c 20 22 2d 22 20 7c 7c 20 63 70 os || "-" || cp
2c20: 75 41 72 63 68 20 46 52 4f 4d 20 70 61 63 6b 61 uArch FROM packa
2c30: 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e 61 ges WHERE hostna
2c40: 6d 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 68 me = $pathinfo(h
2c50: 6f 73 74 6e 61 6d 65 29 20 41 4e 44 20 70 61 63 ostname) AND pac
2c60: 6b 61 67 65 20 3d 20 24 70 61 74 68 69 6e 66 6f kage = $pathinfo
2c70: 28 70 61 63 6b 61 67 65 29 3b 7d 5d 0a 0a 09 09 (package);}]....
2c80: 09 09 6c 61 70 70 65 6e 64 20 72 65 74 76 61 6c ..lappend retval
2c90: 20 22 70 6c 61 74 66 6f 72 6d 22 0a 0a 09 09 09 "platform".....
2ca0: 09 72 65 74 75 72 6e 20 24 72 65 74 76 61 6c 0a .return $retval.
2cb0: 09 09 09 7d 0a 09 09 09 22 76 65 72 73 69 6f 6e ...}...."version
2cc0: 73 22 20 7b 0a 09 09 09 09 73 65 74 20 72 65 74 s" {.....set ret
2cd0: 76 61 6c 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 val [::appfs::db
2ce0: 20 65 76 61 6c 20 7b 0a 09 09 09 09 09 53 45 4c eval {......SEL
2cf0: 45 43 54 20 44 49 53 54 49 4e 43 54 20 76 65 72 ECT DISTINCT ver
2d00: 73 69 6f 6e 20 46 52 4f 4d 20 70 61 63 6b 61 67 sion FROM packag
2d10: 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e 61 6d es WHERE hostnam
2d20: 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 68 6f e = $pathinfo(ho
2d30: 73 74 6e 61 6d 65 29 20 41 4e 44 20 70 61 63 6b stname) AND pack
2d40: 61 67 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 age = $pathinfo(
2d50: 70 61 63 6b 61 67 65 29 20 41 4e 44 20 6f 73 20 package) AND os
2d60: 3d 20 24 70 61 74 68 69 6e 66 6f 28 6f 73 29 20 = $pathinfo(os)
2d70: 41 4e 44 20 63 70 75 41 72 63 68 20 3d 20 24 70 AND cpuArch = $p
2d80: 61 74 68 69 6e 66 6f 28 63 70 75 29 3b 0a 09 09 athinfo(cpu);...
2d90: 09 09 7d 5d 0a 0a 09 09 09 09 6c 61 70 70 65 6e ..}]......lappen
2da0: 64 20 72 65 74 76 61 6c 20 22 6c 61 74 65 73 74 d retval "latest
2db0: 22 0a 0a 09 09 09 09 72 65 74 75 72 6e 20 24 72 "......return $r
2dc0: 65 74 76 61 6c 0a 09 09 09 7d 0a 09 09 09 22 66 etval....}...."f
2dd0: 69 6c 65 73 22 20 7b 0a 09 09 09 09 63 61 74 63 iles" {.....catc
2de0: 68 20 7b 0a 09 09 09 09 09 3a 3a 61 70 70 66 73 h {......::appfs
2df0: 3a 3a 67 65 74 70 6b 67 6d 61 6e 69 66 65 73 74 ::getpkgmanifest
2e00: 20 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e $pathinfo(hostn
2e10: 61 6d 65 29 20 24 70 61 74 68 69 6e 66 6f 28 70 ame) $pathinfo(p
2e20: 61 63 6b 61 67 65 5f 73 68 61 31 29 0a 09 09 09 ackage_sha1)....
2e30: 09 7d 0a 0a 09 09 09 09 73 65 74 20 72 65 74 76 .}......set retv
2e40: 61 6c 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 20 al [::appfs::db
2e50: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 44 49 53 eval {SELECT DIS
2e60: 54 49 4e 43 54 20 66 69 6c 65 5f 6e 61 6d 65 20 TINCT file_name
2e70: 46 52 4f 4d 20 66 69 6c 65 73 20 57 48 45 52 45 FROM files WHERE
2e80: 20 70 61 63 6b 61 67 65 5f 73 68 61 31 20 3d 20 package_sha1 =
2e90: 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 $pathinfo(packag
2ea0: 65 5f 73 68 61 31 29 20 41 4e 44 20 66 69 6c 65 e_sha1) AND file
2eb0: 5f 64 69 72 65 63 74 6f 72 79 20 3d 20 24 70 61 _directory = $pa
2ec0: 74 68 69 6e 66 6f 28 66 69 6c 65 29 3b 7d 5d 0a thinfo(file);}].
2ed0: 0a 09 09 09 09 69 66 20 7b 5b 69 6e 66 6f 20 65 .....if {[info e
2ee0: 78 69 73 74 73 20 70 61 74 68 69 6e 66 6f 28 70 xists pathinfo(p
2ef0: 61 63 6b 61 67 65 29 5d 20 26 26 20 5b 69 6e 66 ackage)] && [inf
2f00: 6f 20 65 78 69 73 74 73 20 70 61 74 68 69 6e 66 o exists pathinf
2f10: 6f 28 68 6f 73 74 6e 61 6d 65 29 5d 20 26 26 20 o(hostname)] &&
2f20: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 70 61 74 [info exists pat
2f30: 68 69 6e 66 6f 28 66 69 6c 65 29 5d 7d 20 7b 0a hinfo(file)]} {.
2f40: 09 09 09 09 09 73 65 74 20 64 69 72 20 5b 5f 6c .....set dir [_l
2f50: 6f 63 61 6c 70 61 74 68 20 24 70 61 74 68 69 6e ocalpath $pathin
2f60: 66 6f 28 70 61 63 6b 61 67 65 29 20 24 70 61 74 fo(package) $pat
2f70: 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 hinfo(hostname)
2f80: 24 70 61 74 68 69 6e 66 6f 28 66 69 6c 65 29 5d $pathinfo(file)]
2f90: 0a 09 09 09 09 09 66 6f 72 65 61 63 68 20 66 69 ......foreach fi
2fa0: 6c 65 20 5b 67 6c 6f 62 20 2d 6e 6f 63 6f 6d 70 le [glob -nocomp
2fb0: 6c 61 69 6e 20 2d 74 61 69 6c 73 20 2d 64 69 72 lain -tails -dir
2fc0: 65 63 74 6f 72 79 20 24 64 69 72 20 2d 74 79 70 ectory $dir -typ
2fd0: 65 73 20 7b 64 20 66 20 6c 7d 20 7b 7b 2e 2c 7d es {d f l} {{.,}
2fe0: 2a 7d 5d 20 7b 0a 09 09 09 09 09 09 69 66 20 7b *}] {.......if {
2ff0: 24 66 69 6c 65 20 3d 3d 20 22 2e 22 20 7c 7c 20 $file == "." ||
3000: 24 66 69 6c 65 20 3d 3d 20 22 2e 2e 22 7d 20 7b $file == ".."} {
3010: 0a 09 09 09 09 09 09 09 63 6f 6e 74 69 6e 75 65 ........continue
3020: 0a 09 09 09 09 09 09 7d 0a 0a 09 09 09 09 09 09 .......}........
3030: 69 66 20 7b 5b 73 74 72 69 6e 67 20 6d 61 74 63 if {[string matc
3040: 68 20 22 2a 2e 41 50 50 46 53 2e 57 48 49 54 45 h "*.APPFS.WHITE
3050: 4f 55 54 22 20 24 66 69 6c 65 5d 7d 20 7b 0a 09 OUT" $file]} {..
3060: 09 09 09 09 09 09 73 65 74 20 72 65 6d 6f 76 65 ......set remove
3070: 20 5b 73 74 72 69 6e 67 20 72 61 6e 67 65 20 24 [string range $
3080: 66 69 6c 65 20 30 20 65 6e 64 2d 31 35 5d 0a 09 file 0 end-15]..
3090: 09 09 09 09 09 09 73 65 74 20 69 64 78 20 5b 6c ......set idx [l
30a0: 73 65 61 72 63 68 20 2d 65 78 61 63 74 20 24 72 search -exact $r
30b0: 65 74 76 61 6c 20 24 72 65 6d 6f 76 65 5d 0a 09 etval $remove]..
30c0: 09 09 09 09 09 09 69 66 20 7b 24 69 64 78 20 21 ......if {$idx !
30d0: 3d 20 2d 31 7d 20 7b 0a 09 09 09 09 09 09 09 09 = -1} {.........
30e0: 73 65 74 20 72 65 74 76 61 6c 20 5b 6c 72 65 70 set retval [lrep
30f0: 6c 61 63 65 20 24 72 65 74 76 61 6c 20 24 69 64 lace $retval $id
3100: 78 20 24 69 64 78 5d 0a 09 09 09 09 09 09 09 7d x $idx]........}
3110: 0a 09 09 09 09 09 09 09 63 6f 6e 74 69 6e 75 65 ........continue
3120: 0a 09 09 09 09 09 09 7d 0a 0a 09 09 09 09 09 09 .......}........
3130: 69 66 20 7b 5b 6c 73 65 61 72 63 68 20 2d 65 78 if {[lsearch -ex
3140: 61 63 74 20 24 72 65 74 76 61 6c 20 24 66 69 6c act $retval $fil
3150: 65 5d 20 21 3d 20 2d 31 7d 20 7b 0a 09 09 09 09 e] != -1} {.....
3160: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09 ...continue.....
3170: 09 09 7d 0a 0a 09 09 09 09 09 09 6c 61 70 70 65 ..}........lappe
3180: 6e 64 20 72 65 74 76 61 6c 20 24 66 69 6c 65 0a nd retval $file.
3190: 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 0a 09 09 .....}.....}....
31a0: 09 09 72 65 74 75 72 6e 20 24 72 65 74 76 61 6c ..return $retval
31b0: 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74 ....}...}....ret
31c0: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 urn -code error
31d0: 22 49 6e 76 61 6c 69 64 20 6f 72 20 75 6e 61 63 "Invalid or unac
31e0: 63 65 70 74 61 62 6c 65 20 70 61 74 68 3a 20 24 ceptable path: $
31f0: 64 69 72 22 0a 09 7d 0a 0a 09 70 72 6f 63 20 67 dir"..}...proc g
3200: 65 74 61 74 74 72 20 7b 70 61 74 68 7d 20 7b 0a etattr {path} {.
3210: 09 09 61 72 72 61 79 20 73 65 74 20 70 61 74 68 ..array set path
3220: 69 6e 66 6f 20 5b 5f 70 61 72 73 65 70 61 74 68 info [_parsepath
3230: 20 24 70 61 74 68 5d 0a 09 09 61 72 72 61 79 20 $path]...array
3240: 73 65 74 20 72 65 74 76 61 6c 20 5b 6c 69 73 74 set retval [list
3250: 5d 0a 0a 09 09 63 61 74 63 68 20 7b 0a 09 09 09 ]....catch {....
3260: 3a 3a 61 70 70 66 73 3a 3a 67 65 74 69 6e 64 65 ::appfs::getinde
3270: 78 20 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 x $pathinfo(host
3280: 6e 61 6d 65 29 0a 09 09 09 3a 3a 61 70 70 66 73 name)....::appfs
3290: 3a 3a 67 65 74 70 6b 67 6d 61 6e 69 66 65 73 74 ::getpkgmanifest
32a0: 20 24 70 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e $pathinfo(hostn
32b0: 61 6d 65 29 20 24 70 61 74 68 69 6e 66 6f 28 70 ame) $pathinfo(p
32c0: 61 63 6b 61 67 65 5f 73 68 61 31 29 0a 09 09 7d ackage_sha1)...}
32d0: 0a 0a 09 09 73 77 69 74 63 68 20 2d 2d 20 24 70 ....switch -- $p
32e0: 61 74 68 69 6e 66 6f 28 5f 74 79 70 65 29 20 7b athinfo(_type) {
32f0: 0a 09 09 09 22 74 6f 70 6c 65 76 65 6c 22 20 7b ...."toplevel" {
3300: 0a 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
3310: 74 79 70 65 29 20 64 69 72 65 63 74 6f 72 79 0a type) directory.
3320: 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 63 ....set retval(c
3330: 68 69 6c 64 63 6f 75 6e 74 29 20 32 3b 0a 09 09 hildcount) 2;...
3340: 09 7d 0a 09 09 09 22 73 69 74 65 73 22 20 7b 0a .}...."sites" {.
3350: 09 09 09 09 73 65 74 20 63 68 65 63 6b 20 5b 3a ....set check [:
3360: 3a 61 70 70 66 73 3a 3a 64 62 20 6f 6e 65 63 6f :appfs::db oneco
3370: 6c 75 6d 6e 20 7b 53 45 4c 45 43 54 20 31 20 46 lumn {SELECT 1 F
3380: 52 4f 4d 20 70 61 63 6b 61 67 65 73 20 57 48 45 ROM packages WHE
3390: 52 45 20 68 6f 73 74 6e 61 6d 65 20 3d 20 24 70 RE hostname = $p
33a0: 61 74 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 athinfo(hostname
33b0: 29 3b 7d 5d 0a 09 09 09 09 69 66 20 7b 24 63 68 );}].....if {$ch
33c0: 65 63 6b 20 3d 3d 20 22 31 22 7d 20 7b 0a 09 09 eck == "1"} {...
33d0: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 74 79 ...set retval(ty
33e0: 70 65 29 20 64 69 72 65 63 74 6f 72 79 0a 09 09 pe) directory...
33f0: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 63 68 ...set retval(ch
3400: 69 6c 64 63 6f 75 6e 74 29 20 32 3b 0a 09 09 09 ildcount) 2;....
3410: 09 7d 0a 09 09 09 7d 0a 09 09 09 22 70 61 63 6b .}....}...."pack
3420: 61 67 65 73 22 20 7b 0a 09 09 09 09 73 65 74 20 ages" {.....set
3430: 63 68 65 63 6b 20 5b 3a 3a 61 70 70 66 73 3a 3a check [::appfs::
3440: 64 62 20 6f 6e 65 63 6f 6c 75 6d 6e 20 7b 53 45 db onecolumn {SE
3450: 4c 45 43 54 20 31 20 46 52 4f 4d 20 70 61 63 6b LECT 1 FROM pack
3460: 61 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e ages WHERE hostn
3470: 61 6d 65 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 ame = $pathinfo(
3480: 68 6f 73 74 6e 61 6d 65 29 20 41 4e 44 20 70 61 hostname) AND pa
3490: 63 6b 61 67 65 20 3d 20 24 70 61 74 68 69 6e 66 ckage = $pathinf
34a0: 6f 28 70 61 63 6b 61 67 65 29 3b 7d 5d 0a 09 09 o(package);}]...
34b0: 09 09 69 66 20 7b 24 63 68 65 63 6b 20 3d 3d 20 ..if {$check ==
34c0: 22 31 22 7d 20 7b 0a 09 09 09 09 09 73 65 74 20 "1"} {......set
34d0: 72 65 74 76 61 6c 28 74 79 70 65 29 20 64 69 72 retval(type) dir
34e0: 65 63 74 6f 72 79 0a 09 09 09 09 09 73 65 74 20 ectory......set
34f0: 72 65 74 76 61 6c 28 63 68 69 6c 64 63 6f 75 6e retval(childcoun
3500: 74 29 20 32 3b 0a 09 09 09 09 7d 0a 09 09 09 7d t) 2;.....}....}
3510: 0a 09 09 09 22 6f 73 2d 63 70 75 22 20 7b 0a 09 ...."os-cpu" {..
3520: 09 09 09 69 66 20 7b 24 70 61 74 68 69 6e 66 6f ...if {$pathinfo
3530: 28 6f 73 29 20 3d 3d 20 22 70 6c 61 74 66 6f 72 (os) == "platfor
3540: 6d 22 20 26 26 20 24 70 61 74 68 69 6e 66 6f 28 m" && $pathinfo(
3550: 63 70 75 29 20 3d 3d 20 22 22 7d 20 7b 0a 09 09 cpu) == ""} {...
3560: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 74 79 ...set retval(ty
3570: 70 65 29 20 73 79 6d 6c 69 6e 6b 0a 09 09 09 09 pe) symlink.....
3580: 09 73 65 74 20 72 65 74 76 61 6c 28 73 6f 75 72 .set retval(sour
3590: 63 65 29 20 5b 70 6c 61 74 66 6f 72 6d 3a 3a 67 ce) [platform::g
35a0: 65 6e 65 72 69 63 5d 0a 09 09 09 09 7d 20 65 6c eneric].....} el
35b0: 73 65 20 7b 0a 09 09 09 09 09 73 65 74 20 63 68 se {......set ch
35c0: 65 63 6b 20 5b 3a 3a 61 70 70 66 73 3a 3a 64 62 eck [::appfs::db
35d0: 20 6f 6e 65 63 6f 6c 75 6d 6e 20 7b 0a 09 09 09 onecolumn {....
35e0: 09 09 09 53 45 4c 45 43 54 20 31 20 46 52 4f 4d ...SELECT 1 FROM
35f0: 20 70 61 63 6b 61 67 65 73 20 57 48 45 52 45 20 packages WHERE
3600: 68 6f 73 74 6e 61 6d 65 20 3d 20 24 70 61 74 68 hostname = $path
3610: 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 41 info(hostname) A
3620: 4e 44 20 70 61 63 6b 61 67 65 20 3d 20 24 70 61 ND package = $pa
3630: 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 29 20 thinfo(package)
3640: 41 4e 44 20 6f 73 20 3d 20 24 70 61 74 68 69 6e AND os = $pathin
3650: 66 6f 28 6f 73 29 20 41 4e 44 20 63 70 75 41 72 fo(os) AND cpuAr
3660: 63 68 20 3d 20 24 70 61 74 68 69 6e 66 6f 28 63 ch = $pathinfo(c
3670: 70 75 29 3b 0a 09 09 09 09 09 7d 5d 0a 09 09 09 pu);......}]....
3680: 09 09 69 66 20 7b 24 63 68 65 63 6b 20 3d 3d 20 ..if {$check ==
3690: 22 31 22 7d 20 7b 0a 09 09 09 09 09 09 73 65 74 "1"} {.......set
36a0: 20 72 65 74 76 61 6c 28 74 79 70 65 29 20 64 69 retval(type) di
36b0: 72 65 63 74 6f 72 79 0a 09 09 09 09 09 09 73 65 rectory.......se
36c0: 74 20 72 65 74 76 61 6c 28 63 68 69 6c 64 63 6f t retval(childco
36d0: 75 6e 74 29 20 32 3b 0a 09 09 09 09 09 7d 0a 09 unt) 2;......}..
36e0: 09 09 09 7d 0a 09 09 09 7d 0a 09 09 09 22 76 65 ...}....}...."ve
36f0: 72 73 69 6f 6e 73 22 20 7b 0a 09 09 09 09 69 66 rsions" {.....if
3700: 20 7b 24 70 61 74 68 69 6e 66 6f 28 76 65 72 73 {$pathinfo(vers
3710: 69 6f 6e 29 20 3d 3d 20 22 6c 61 74 65 73 74 22 ion) == "latest"
3720: 7d 20 7b 0a 09 09 09 09 09 73 65 74 20 72 65 74 } {......set ret
3730: 76 61 6c 28 74 79 70 65 29 20 73 79 6d 6c 69 6e val(type) symlin
3740: 6b 0a 09 09 09 09 09 73 65 74 20 72 65 74 76 61 k......set retva
3750: 6c 28 73 6f 75 72 63 65 29 20 22 31 2e 30 22 0a l(source) "1.0".
3760: 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 ....} else {....
3770: 09 09 69 66 20 7b 5b 69 6e 66 6f 20 65 78 69 73 ..if {[info exis
3780: 74 73 20 70 61 74 68 69 6e 66 6f 28 70 61 63 6b ts pathinfo(pack
3790: 61 67 65 5f 73 68 61 31 29 5d 20 26 26 20 24 70 age_sha1)] && $p
37a0: 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 5f athinfo(package_
37b0: 73 68 61 31 29 20 21 3d 20 22 22 7d 20 7b 0a 09 sha1) != ""} {..
37c0: 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
37d0: 74 79 70 65 29 20 64 69 72 65 63 74 6f 72 79 0a type) directory.
37e0: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
37f0: 28 63 68 69 6c 64 63 6f 75 6e 74 29 20 32 3b 0a (childcount) 2;.
3800: 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 09 09 09 .....}.....}....
3810: 7d 0a 09 09 09 22 66 69 6c 65 73 22 20 7b 0a 09 }...."files" {..
3820: 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 70 61 ...set retval(pa
3830: 63 6b 61 67 65 64 29 20 31 0a 0a 09 09 09 09 73 ckaged) 1......s
3840: 65 74 20 6c 6f 63 61 6c 70 61 74 68 20 5b 5f 6c et localpath [_l
3850: 6f 63 61 6c 70 61 74 68 20 24 70 61 74 68 69 6e ocalpath $pathin
3860: 66 6f 28 70 61 63 6b 61 67 65 29 20 24 70 61 74 fo(package) $pat
3870: 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 hinfo(hostname)
3880: 24 70 61 74 68 69 6e 66 6f 28 66 69 6c 65 29 5d $pathinfo(file)]
3890: 0a 0a 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
38a0: 28 6c 6f 63 61 6c 70 61 74 68 29 20 24 6c 6f 63 (localpath) $loc
38b0: 61 6c 70 61 74 68 0a 0a 09 09 09 09 69 66 20 7b alpath......if {
38c0: 21 5b 66 69 6c 65 20 65 78 69 73 74 73 20 22 24 ![file exists "$
38d0: 7b 6c 6f 63 61 6c 70 61 74 68 7d 2e 41 50 50 46 {localpath}.APPF
38e0: 53 2e 57 48 49 54 45 4f 55 54 22 5d 7d 20 7b 0a S.WHITEOUT"]} {.
38f0: 09 09 09 09 09 69 66 20 7b 5b 66 69 6c 65 20 65 .....if {[file e
3900: 78 69 73 74 73 20 24 6c 6f 63 61 6c 70 61 74 68 xists $localpath
3910: 5d 7d 20 7b 0a 09 09 09 09 09 09 73 65 74 20 72 ]} {.......set r
3920: 65 74 76 61 6c 28 69 73 5f 6c 6f 63 61 6c 66 69 etval(is_localfi
3930: 6c 65 29 20 31 0a 09 09 09 09 09 09 63 61 74 63 le) 1.......catc
3940: 68 20 7b 0a 09 09 09 09 09 09 09 66 69 6c 65 20 h {........file
3950: 6c 73 74 61 74 20 24 6c 6f 63 61 6c 70 61 74 68 lstat $localpath
3960: 20 6c 6f 63 61 6c 70 61 74 68 69 6e 66 6f 0a 09 localpathinfo..
3970: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
3980: 28 74 69 6d 65 29 20 24 6c 6f 63 61 6c 70 61 74 (time) $localpat
3990: 68 69 6e 66 6f 28 6d 74 69 6d 65 29 0a 0a 09 09 hinfo(mtime)....
39a0: 09 09 09 09 09 73 77 69 74 63 68 20 2d 2d 20 24 .....switch -- $
39b0: 6c 6f 63 61 6c 70 61 74 68 69 6e 66 6f 28 74 79 localpathinfo(ty
39c0: 70 65 29 20 7b 0a 09 09 09 09 09 09 09 09 22 64 pe) {........."d
39d0: 69 72 65 63 74 6f 72 79 22 20 7b 0a 09 09 09 09 irectory" {.....
39e0: 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c 28 .....set retval(
39f0: 74 79 70 65 29 20 22 64 69 72 65 63 74 6f 72 79 type) "directory
3a00: 22 0a 09 09 09 09 09 09 09 09 09 73 65 74 20 72 "..........set r
3a10: 65 74 76 61 6c 28 63 68 69 6c 64 63 6f 75 6e 74 etval(childcount
3a20: 29 20 32 0a 09 09 09 09 09 09 09 09 7d 0a 09 09 ) 2.........}...
3a30: 09 09 09 09 09 09 22 66 69 6c 65 22 20 7b 0a 09 ......"file" {..
3a40: 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 76 ........set retv
3a50: 61 6c 28 74 79 70 65 29 20 22 66 69 6c 65 22 0a al(type) "file".
3a60: 09 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 .........set ret
3a70: 76 61 6c 28 73 69 7a 65 29 20 24 6c 6f 63 61 6c val(size) $local
3a80: 70 61 74 68 69 6e 66 6f 28 73 69 7a 65 29 0a 09 pathinfo(size)..
3a90: 09 09 09 09 09 09 09 09 69 66 20 7b 5b 66 69 6c ........if {[fil
3aa0: 65 20 65 78 65 63 75 74 61 62 6c 65 20 24 6c 6f e executable $lo
3ab0: 63 61 6c 70 61 74 68 5d 7d 20 7b 0a 09 09 09 09 calpath]} {.....
3ac0: 09 09 09 09 09 09 73 65 74 20 72 65 74 76 61 6c ......set retval
3ad0: 28 70 65 72 6d 73 29 20 22 78 22 0a 09 09 09 09 (perms) "x".....
3ae0: 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 .....} else {...
3af0: 09 09 09 09 09 09 09 09 73 65 74 20 72 65 74 76 ........set retv
3b00: 61 6c 28 70 65 72 6d 73 29 20 22 22 0a 09 09 09 al(perms) ""....
3b10: 09 09 09 09 09 09 7d 0a 09 09 09 09 09 09 09 09 ......}.........
3b20: 7d 0a 09 09 09 09 09 09 09 09 22 6c 69 6e 6b 22 }........."link"
3b30: 20 7b 0a 09 09 09 09 09 09 09 09 09 73 65 74 20 {..........set
3b40: 72 65 74 76 61 6c 28 74 79 70 65 29 20 22 73 79 retval(type) "sy
3b50: 6d 6c 69 6e 6b 22 0a 09 09 09 09 09 09 09 09 09 mlink"..........
3b60: 73 65 74 20 72 65 74 76 61 6c 28 73 6f 75 72 63 set retval(sourc
3b70: 65 29 20 5b 66 69 6c 65 20 72 65 61 64 6c 69 6e e) [file readlin
3b80: 6b 20 24 6c 6f 63 61 6c 70 61 74 68 5d 0a 09 09 k $localpath]...
3b90: 09 09 09 09 09 09 7d 0a 09 09 09 09 09 09 09 7d ......}........}
3ba0: 0a 09 09 09 09 09 09 7d 20 65 72 72 0a 09 09 09 .......} err....
3bb0: 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 ..} else {......
3bc0: 09 73 65 74 20 72 65 74 76 61 6c 28 69 73 5f 72 .set retval(is_r
3bd0: 65 6d 6f 74 65 66 69 6c 65 29 20 31 0a 0a 09 09 emotefile) 1....
3be0: 09 09 09 09 73 65 74 20 77 6f 72 6b 20 5b 73 70 ....set work [sp
3bf0: 6c 69 74 20 24 70 61 74 68 69 6e 66 6f 28 66 69 lit $pathinfo(fi
3c00: 6c 65 29 20 22 2f 22 5d 0a 09 09 09 09 09 09 73 le) "/"].......s
3c10: 65 74 20 64 69 72 65 63 74 6f 72 79 20 5b 6a 6f et directory [jo
3c20: 69 6e 20 5b 6c 72 61 6e 67 65 20 24 77 6f 72 6b in [lrange $work
3c30: 20 30 20 65 6e 64 2d 31 5d 20 22 2f 22 5d 0a 09 0 end-1] "/"]..
3c40: 09 09 09 09 09 73 65 74 20 66 69 6c 65 20 5b 6c .....set file [l
3c50: 69 6e 64 65 78 20 24 77 6f 72 6b 20 65 6e 64 5d index $work end]
3c60: 0a 09 09 09 09 09 09 3a 3a 61 70 70 66 73 3a 3a .......::appfs::
3c70: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 db eval {SELECT
3c80: 74 79 70 65 2c 20 74 69 6d 65 2c 20 73 6f 75 72 type, time, sour
3c90: 63 65 2c 20 73 69 7a 65 2c 20 70 65 72 6d 73 20 ce, size, perms
3ca0: 46 52 4f 4d 20 66 69 6c 65 73 20 57 48 45 52 45 FROM files WHERE
3cb0: 20 70 61 63 6b 61 67 65 5f 73 68 61 31 20 3d 20 package_sha1 =
3cc0: 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 $pathinfo(packag
3cd0: 65 5f 73 68 61 31 29 20 41 4e 44 20 66 69 6c 65 e_sha1) AND file
3ce0: 5f 64 69 72 65 63 74 6f 72 79 20 3d 20 24 64 69 _directory = $di
3cf0: 72 65 63 74 6f 72 79 20 41 4e 44 20 66 69 6c 65 rectory AND file
3d00: 5f 6e 61 6d 65 20 3d 20 24 66 69 6c 65 3b 7d 20 _name = $file;}
3d10: 72 65 74 76 61 6c 20 7b 7d 0a 09 09 09 09 09 09 retval {}.......
3d20: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 unset -nocomplai
3d30: 6e 20 72 65 74 76 61 6c 28 2a 29 0a 09 09 09 09 n retval(*).....
3d40: 09 7d 0a 09 09 09 09 7d 0a 0a 09 09 09 7d 0a 09 .}.....}.....}..
3d50: 09 7d 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f .}....if {![info
3d60: 20 65 78 69 73 74 73 20 72 65 74 76 61 6c 28 74 exists retval(t
3d70: 79 70 65 29 5d 7d 20 7b 0a 09 09 09 72 65 74 75 ype)]} {....retu
3d80: 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 rn -code error "
3d90: 4e 6f 20 73 75 63 68 20 66 69 6c 65 20 6f 72 20 No such file or
3da0: 64 69 72 65 63 74 6f 72 79 22 0a 09 09 7d 0a 0a directory"...}..
3db0: 09 09 72 65 74 75 72 6e 20 5b 61 72 72 61 79 20 ..return [array
3dc0: 67 65 74 20 72 65 74 76 61 6c 5d 0a 09 7d 0a 0a get retval]..}..
3dd0: 09 70 72 6f 63 20 6f 70 65 6e 70 61 74 68 20 7b .proc openpath {
3de0: 70 61 74 68 20 6d 6f 64 65 7d 20 7b 0a 09 09 61 path mode} {...a
3df0: 72 72 61 79 20 73 65 74 20 70 61 74 68 69 6e 66 rray set pathinf
3e00: 6f 20 5b 5f 70 61 72 73 65 70 61 74 68 20 24 70 o [_parsepath $p
3e10: 61 74 68 5d 0a 0a 09 09 69 66 20 7b 24 70 61 74 ath]....if {$pat
3e20: 68 69 6e 66 6f 28 5f 74 79 70 65 29 20 21 3d 20 hinfo(_type) !=
3e30: 22 66 69 6c 65 73 22 7d 20 7b 0a 09 09 09 72 65 "files"} {....re
3e40: 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 turn -code error
3e50: 20 22 69 6e 76 61 6c 69 64 20 74 79 70 65 22 0a "invalid type".
3e60: 09 09 7d 0a 0a 09 09 73 65 74 20 6c 6f 63 61 6c ..}....set local
3e70: 70 61 74 68 20 5b 5f 6c 6f 63 61 6c 70 61 74 68 path [_localpath
3e80: 20 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 $pathinfo(packa
3e90: 67 65 29 20 24 70 61 74 68 69 6e 66 6f 28 68 6f ge) $pathinfo(ho
3ea0: 73 74 6e 61 6d 65 29 20 24 70 61 74 68 69 6e 66 stname) $pathinf
3eb0: 6f 28 66 69 6c 65 29 5d 0a 0a 09 09 69 66 20 7b o(file)]....if {
3ec0: 24 6d 6f 64 65 20 3d 3d 20 22 63 72 65 61 74 65 $mode == "create
3ed0: 22 7d 20 7b 0a 09 09 09 66 69 6c 65 20 64 65 6c "} {....file del
3ee0: 65 74 65 20 2d 2d 20 22 24 7b 6c 6f 63 61 6c 70 ete -- "${localp
3ef0: 61 74 68 7d 2e 41 50 50 46 53 2e 57 48 49 54 45 ath}.APPFS.WHITE
3f00: 4f 55 54 22 0a 0a 09 09 09 72 65 74 75 72 6e 20 OUT".....return
3f10: 24 6c 6f 63 61 6c 70 61 74 68 0a 09 09 7d 0a 0a $localpath...}..
3f20: 09 09 69 66 20 7b 5b 66 69 6c 65 20 65 78 69 73 ..if {[file exis
3f30: 74 73 20 24 6c 6f 63 61 6c 70 61 74 68 5d 7d 20 ts $localpath]}
3f40: 7b 0a 09 09 09 72 65 74 75 72 6e 20 24 6c 6f 63 {....return $loc
3f50: 61 6c 70 61 74 68 0a 09 09 7d 0a 0a 09 09 73 65 alpath...}....se
3f60: 74 20 77 6f 72 6b 20 5b 73 70 6c 69 74 20 24 70 t work [split $p
3f70: 61 74 68 69 6e 66 6f 28 66 69 6c 65 29 20 22 2f athinfo(file) "/
3f80: 22 5d 0a 09 09 73 65 74 20 64 69 72 65 63 74 6f "]...set directo
3f90: 72 79 20 5b 6a 6f 69 6e 20 5b 6c 72 61 6e 67 65 ry [join [lrange
3fa0: 20 24 77 6f 72 6b 20 30 20 65 6e 64 2d 31 5d 20 $work 0 end-1]
3fb0: 22 2f 22 5d 0a 09 09 73 65 74 20 66 69 6c 65 20 "/"]...set file
3fc0: 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 65 6e [lindex $work en
3fd0: 64 5d 0a 09 09 3a 3a 61 70 70 66 73 3a 3a 64 62 d]...::appfs::db
3fe0: 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 66 69 eval {SELECT fi
3ff0: 6c 65 5f 73 68 61 31 2c 20 70 65 72 6d 73 20 46 le_sha1, perms F
4000: 52 4f 4d 20 66 69 6c 65 73 20 57 48 45 52 45 20 ROM files WHERE
4010: 70 61 63 6b 61 67 65 5f 73 68 61 31 20 3d 20 24 package_sha1 = $
4020: 70 61 74 68 69 6e 66 6f 28 70 61 63 6b 61 67 65 pathinfo(package
4030: 5f 73 68 61 31 29 20 41 4e 44 20 66 69 6c 65 5f _sha1) AND file_
4040: 6e 61 6d 65 20 3d 20 24 66 69 6c 65 20 41 4e 44 name = $file AND
4050: 20 66 69 6c 65 5f 64 69 72 65 63 74 6f 72 79 20 file_directory
4060: 3d 20 24 64 69 72 65 63 74 6f 72 79 3b 7d 20 70 = $directory;} p
4070: 6b 67 70 61 74 68 69 6e 66 6f 20 7b 7d 0a 0a 09 kgpathinfo {}...
4080: 09 69 66 20 7b 24 70 6b 67 70 61 74 68 69 6e 66 .if {$pkgpathinf
4090: 6f 28 66 69 6c 65 5f 73 68 61 31 29 20 3d 3d 20 o(file_sha1) ==
40a0: 22 22 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 ""} {....return
40b0: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4e 6f 20 -code error "No
40c0: 73 75 63 68 20 66 69 6c 65 20 6f 72 20 64 69 72 such file or dir
40d0: 65 63 74 6f 72 79 22 0a 09 09 7d 0a 0a 09 09 73 ectory"...}....s
40e0: 65 74 20 6c 6f 63 61 6c 63 61 63 68 65 66 69 6c et localcachefil
40f0: 65 20 5b 64 6f 77 6e 6c 6f 61 64 20 24 70 61 74 e [download $pat
4100: 68 69 6e 66 6f 28 68 6f 73 74 6e 61 6d 65 29 20 hinfo(hostname)
4110: 24 70 6b 67 70 61 74 68 69 6e 66 6f 28 66 69 6c $pkgpathinfo(fil
4120: 65 5f 73 68 61 31 29 5d 0a 0a 09 09 69 66 20 7b e_sha1)]....if {
4130: 24 6d 6f 64 65 20 3d 3d 20 22 77 72 69 74 65 22 $mode == "write"
4140: 7d 20 7b 0a 09 09 09 73 65 74 20 74 6d 70 6c 6f } {....set tmplo
4150: 63 61 6c 70 61 74 68 20 22 24 7b 6c 6f 63 61 6c calpath "${local
4160: 70 61 74 68 7d 2e 5b 65 78 70 72 20 72 61 6e 64 path}.[expr rand
4170: 28 29 5d 5b 63 6c 6f 63 6b 20 63 6c 69 63 6b 73 ()][clock clicks
4180: 5d 22 0a 0a 09 09 09 73 65 74 20 66 61 69 6c 65 ]".....set faile
4190: 64 20 30 0a 09 09 09 69 66 20 7b 5b 63 61 74 63 d 0....if {[catc
41a0: 68 20 7b 0a 09 09 09 09 66 69 6c 65 20 6d 6b 64 h {.....file mkd
41b0: 69 72 20 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65 ir [file dirname
41c0: 20 24 6c 6f 63 61 6c 70 61 74 68 5d 0a 09 09 09 $localpath]....
41d0: 09 66 69 6c 65 20 63 6f 70 79 20 2d 66 6f 72 63 .file copy -forc
41e0: 65 20 2d 2d 20 24 6c 6f 63 61 6c 63 61 63 68 65 e -- $localcache
41f0: 66 69 6c 65 20 24 74 6d 70 6c 6f 63 61 6c 70 61 file $tmplocalpa
4200: 74 68 0a 0a 09 09 09 09 69 66 20 7b 24 70 6b 67 th......if {$pkg
4210: 70 61 74 68 69 6e 66 6f 28 70 65 72 6d 73 29 20 pathinfo(perms)
4220: 3d 3d 20 22 78 22 7d 20 7b 0a 09 09 09 09 09 66 == "x"} {......f
4230: 69 6c 65 20 61 74 74 72 69 62 75 74 65 73 20 24 ile attributes $
4240: 74 6d 70 6c 6f 63 61 6c 70 61 74 68 20 2d 70 65 tmplocalpath -pe
4250: 72 6d 69 73 73 69 6f 6e 73 20 2b 78 0a 09 09 09 rmissions +x....
4260: 09 7d 0a 0a 09 09 09 09 66 69 6c 65 20 72 65 6e .}......file ren
4270: 61 6d 65 20 2d 66 6f 72 63 65 20 2d 2d 20 24 74 ame -force -- $t
4280: 6d 70 6c 6f 63 61 6c 70 61 74 68 20 24 6c 6f 63 mplocalpath $loc
4290: 61 6c 70 61 74 68 0a 09 09 09 7d 20 65 72 72 5d alpath....} err]
42a0: 7d 20 7b 0a 09 09 09 09 73 65 74 20 66 61 69 6c } {.....set fail
42b0: 65 64 20 31 0a 09 09 09 7d 0a 09 09 09 63 61 74 ed 1....}....cat
42c0: 63 68 20 7b 0a 09 09 09 09 66 69 6c 65 20 64 65 ch {.....file de
42d0: 6c 65 74 65 20 2d 66 6f 72 63 65 20 2d 2d 20 24 lete -force -- $
42e0: 74 6d 70 6c 6f 63 61 6c 70 61 74 68 0a 09 09 09 tmplocalpath....
42f0: 7d 0a 0a 09 09 09 69 66 20 7b 24 66 61 69 6c 65 }.....if {$faile
4300: 64 7d 20 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 d} {.....return
4310: 2d 63 6f 64 65 20 65 72 72 6f 72 20 24 65 72 72 -code error $err
4320: 0a 09 09 09 7d 0a 0a 09 09 09 72 65 74 75 72 6e ....}.....return
4330: 20 24 6c 6f 63 61 6c 70 61 74 68 0a 09 09 7d 0a $localpath...}.
4340: 0a 09 09 72 65 74 75 72 6e 20 24 6c 6f 63 61 6c ...return $local
4350: 63 61 63 68 65 66 69 6c 65 0a 09 7d 0a 0a 09 70 cachefile..}...p
4360: 72 6f 63 20 65 78 69 73 74 73 20 7b 70 61 74 68 roc exists {path
4370: 7d 20 7b 0a 09 09 63 61 74 63 68 20 7b 0a 09 09 } {...catch {...
4380: 09 73 65 74 20 69 6e 66 6f 20 5b 67 65 74 61 74 .set info [getat
4390: 74 72 20 24 70 61 74 68 5d 0a 09 09 7d 20 65 72 tr $path]...} er
43a0: 72 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20 r....if {![info
43b0: 65 78 69 73 74 73 20 69 6e 66 6f 5d 7d 20 7b 0a exists info]} {.
43c0: 09 09 09 69 66 20 7b 24 65 72 72 20 3d 3d 20 22 ...if {$err == "
43d0: 4e 6f 20 73 75 63 68 20 66 69 6c 65 20 6f 72 20 No such file or
43e0: 64 69 72 65 63 74 6f 72 79 22 7d 20 7b 0a 09 09 directory"} {...
43f0: 09 09 72 65 74 75 72 6e 20 5b 6c 69 73 74 5d 0a ..return [list].
4400: 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 ...} else {.....
4410: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 return -code err
4420: 6f 72 20 24 65 72 72 0a 09 09 09 7d 0a 09 09 7d or $err....}...}
4430: 0a 0a 09 09 72 65 74 75 72 6e 20 24 69 6e 66 6f ....return $info
4440: 0a 09 7d 0a 0a 09 70 72 6f 63 20 70 72 65 70 61 ..}...proc prepa
4450: 72 65 5f 74 6f 5f 63 72 65 61 74 65 20 7b 70 61 re_to_create {pa
4460: 74 68 7d 20 7b 0a 09 09 69 66 20 7b 5b 65 78 69 th} {...if {[exi
4470: 73 74 73 20 24 70 61 74 68 5d 20 21 3d 20 22 22 sts $path] != ""
4480: 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 } {....return -c
4490: 6f 64 65 20 65 72 72 6f 72 20 22 46 69 6c 65 20 ode error "File
44a0: 61 6c 72 65 61 64 79 20 65 78 69 73 74 73 22 0a already exists".
44b0: 09 09 7d 0a 0a 09 09 73 65 74 20 66 69 6c 65 6e ..}....set filen
44c0: 61 6d 65 20 5b 6f 70 65 6e 70 61 74 68 20 24 70 ame [openpath $p
44d0: 61 74 68 20 22 63 72 65 61 74 65 22 5d 0a 0a 09 ath "create"]...
44e0: 09 73 65 74 20 64 69 72 6e 61 6d 65 20 5b 66 69 .set dirname [fi
44f0: 6c 65 20 64 69 72 6e 61 6d 65 20 24 66 69 6c 65 le dirname $file
4500: 6e 61 6d 65 5d 0a 0a 09 09 66 69 6c 65 20 6d 6b name]....file mk
4510: 64 69 72 20 24 64 69 72 6e 61 6d 65 0a 0a 09 09 dir $dirname....
4520: 72 65 74 75 72 6e 20 24 66 69 6c 65 6e 61 6d 65 return $filename
4530: 0a 09 7d 0a 0a 09 70 72 6f 63 20 6c 6f 63 61 6c ..}...proc local
4540: 70 61 74 68 20 7b 70 61 74 68 7d 20 7b 0a 09 09 path {path} {...
4550: 61 72 72 61 79 20 73 65 74 20 70 61 74 68 69 6e array set pathin
4560: 66 6f 20 5b 5f 70 61 72 73 65 70 61 74 68 20 24 fo [_parsepath $
4570: 70 61 74 68 5d 0a 0a 09 09 69 66 20 7b 24 70 61 path]....if {$pa
4580: 74 68 69 6e 66 6f 28 5f 74 79 70 65 29 20 21 3d thinfo(_type) !=
4590: 20 22 66 69 6c 65 73 22 7d 20 7b 0a 09 09 09 72 "files"} {....r
45a0: 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f eturn -code erro
45b0: 72 20 22 69 6e 76 61 6c 69 64 20 74 79 70 65 22 r "invalid type"
45c0: 0a 09 09 7d 0a 0a 09 09 73 65 74 20 6c 6f 63 61 ...}....set loca
45d0: 6c 70 61 74 68 20 5b 5f 6c 6f 63 61 6c 70 61 74 lpath [_localpat
45e0: 68 20 24 70 61 74 68 69 6e 66 6f 28 70 61 63 6b h $pathinfo(pack
45f0: 61 67 65 29 20 24 70 61 74 68 69 6e 66 6f 28 68 age) $pathinfo(h
4600: 6f 73 74 6e 61 6d 65 29 20 24 70 61 74 68 69 6e ostname) $pathin
4610: 66 6f 28 66 69 6c 65 29 5d 0a 0a 09 09 72 65 74 fo(file)]....ret
4620: 75 72 6e 20 24 6c 6f 63 61 6c 70 61 74 68 0a 09 urn $localpath..
4630: 7d 0a 0a 09 70 72 6f 63 20 75 6e 6c 69 6e 6b 70 }...proc unlinkp
4640: 61 74 68 20 7b 70 61 74 68 7d 20 7b 0a 09 09 61 ath {path} {...a
4650: 72 72 61 79 20 73 65 74 20 70 61 74 68 61 74 74 rray set pathatt
4660: 72 73 20 5b 65 78 69 73 74 73 20 24 70 61 74 68 rs [exists $path
4670: 5d 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20 ]....if {![info
4680: 65 78 69 73 74 73 20 70 61 74 68 61 74 74 72 73 exists pathattrs
4690: 28 70 61 63 6b 61 67 65 64 29 5d 7d 20 7b 0a 09 (packaged)]} {..
46a0: 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 ..return -code e
46b0: 72 72 6f 72 20 22 69 6e 76 61 6c 69 64 20 74 79 rror "invalid ty
46c0: 70 65 22 0a 09 09 7d 0a 0a 09 09 73 65 74 20 6c pe"...}....set l
46d0: 6f 63 61 6c 70 61 74 68 20 24 70 61 74 68 61 74 ocalpath $pathat
46e0: 74 72 73 28 6c 6f 63 61 6c 70 61 74 68 29 0a 0a trs(localpath)..
46f0: 09 09 73 65 74 20 77 68 69 74 65 6f 75 74 20 30 ..set whiteout 0
4700: 0a 09 09 73 65 74 20 69 73 64 69 72 65 63 74 6f ...set isdirecto
4710: 72 79 20 30 0a 09 09 69 66 20 7b 5b 69 6e 66 6f ry 0...if {[info
4720: 20 65 78 69 73 74 73 20 70 61 74 68 61 74 74 72 exists pathattr
4730: 73 28 69 73 5f 6c 6f 63 61 6c 66 69 6c 65 29 5d s(is_localfile)]
4740: 7d 20 7b 0a 09 09 09 69 66 20 7b 5b 66 69 6c 65 } {....if {[file
4750: 20 69 73 64 69 72 65 63 74 6f 72 79 20 24 6c 6f isdirectory $lo
4760: 63 61 6c 70 61 74 68 5d 7d 20 7b 0a 09 09 09 09 calpath]} {.....
4770: 73 65 74 20 69 73 64 69 72 65 63 74 6f 72 79 20 set isdirectory
4780: 31 0a 09 09 09 09 73 65 74 20 77 68 69 74 65 6f 1.....set whiteo
4790: 75 74 20 31 0a 09 09 09 7d 20 65 6c 73 65 20 7b ut 1....} else {
47a0: 0a 09 09 09 09 66 69 6c 65 20 64 65 6c 65 74 65 .....file delete
47b0: 20 2d 66 6f 72 63 65 20 2d 2d 20 24 6c 6f 63 61 -force -- $loca
47c0: 6c 70 61 74 68 0a 09 09 09 7d 0a 09 09 7d 20 65 lpath....}...} e
47d0: 6c 73 65 69 66 20 7b 5b 69 6e 66 6f 20 65 78 69 lseif {[info exi
47e0: 73 74 73 20 70 61 74 68 61 74 74 72 73 28 69 73 sts pathattrs(is
47f0: 5f 72 65 6d 6f 74 65 66 69 6c 65 29 5d 7d 20 7b _remotefile)]} {
4800: 0a 09 09 09 69 66 20 7b 24 70 61 74 68 61 74 74 ....if {$pathatt
4810: 72 73 28 74 79 70 65 29 20 3d 3d 20 22 64 69 72 rs(type) == "dir
4820: 65 63 74 6f 72 79 22 7d 20 7b 0a 09 09 09 09 73 ectory"} {.....s
4830: 65 74 20 69 73 64 69 72 65 63 74 6f 72 79 20 31 et isdirectory 1
4840: 0a 09 09 09 7d 0a 0a 09 09 09 73 65 74 20 77 68 ....}.....set wh
4850: 69 74 65 6f 75 74 20 31 0a 09 09 7d 20 65 6c 73 iteout 1...} els
4860: 65 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 e {....return -c
4870: 6f 64 65 20 65 72 72 6f 72 20 22 55 6e 6b 6e 6f ode error "Unkno
4880: 77 6e 20 69 66 20 66 69 6c 65 20 69 73 20 72 65 wn if file is re
4890: 6d 6f 74 65 20 6f 72 20 6c 6f 63 61 6c 20 21 3f mote or local !?
48a0: 22 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 24 69 73 "...}....if {$is
48b0: 64 69 72 65 63 74 6f 72 79 7d 20 7b 0a 09 09 09 directory} {....
48c0: 73 65 74 20 63 68 69 6c 64 72 65 6e 20 5b 67 65 set children [ge
48d0: 74 63 68 69 6c 64 72 65 6e 20 24 70 61 74 68 5d tchildren $path]
48e0: 0a 09 09 09 69 66 20 7b 24 63 68 69 6c 64 72 65 ....if {$childre
48f0: 6e 20 21 3d 20 5b 6c 69 73 74 5d 7d 20 7b 0a 09 n != [list]} {..
4900: 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 ...return -code
4910: 65 72 72 6f 72 20 22 41 73 6b 65 64 20 74 6f 20 error "Asked to
4920: 64 65 6c 65 74 65 20 6e 6f 6e 2d 65 6d 70 74 79 delete non-empty
4930: 20 64 69 72 65 63 74 6f 72 79 22 0a 09 09 09 7d directory"....}
4940: 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 24 77 68 69 ...}....if {$whi
4950: 74 65 6f 75 74 7d 20 7b 0a 09 09 09 73 65 74 20 teout} {....set
4960: 77 68 69 74 65 6f 75 74 66 69 6c 65 20 22 24 7b whiteoutfile "${
4970: 6c 6f 63 61 6c 70 61 74 68 7d 2e 41 50 50 46 53 localpath}.APPFS
4980: 2e 57 48 49 54 45 4f 55 54 22 0a 09 09 09 73 65 .WHITEOUT"....se
4990: 74 20 77 68 69 74 65 6f 75 74 64 69 72 20 5b 66 t whiteoutdir [f
49a0: 69 6c 65 20 64 69 72 6e 61 6d 65 20 24 77 68 69 ile dirname $whi
49b0: 74 65 6f 75 74 66 69 6c 65 5d 0a 09 09 09 66 69 teoutfile]....fi
49c0: 6c 65 20 6d 6b 64 69 72 20 24 77 68 69 74 65 6f le mkdir $whiteo
49d0: 75 74 64 69 72 0a 09 09 09 63 6c 6f 73 65 20 5b utdir....close [
49e0: 6f 70 65 6e 20 24 77 68 69 74 65 6f 75 74 66 69 open $whiteoutfi
49f0: 6c 65 20 77 5d 0a 09 09 7d 0a 09 7d 0a 7d 0a le w]...}..}.}.