Overview
Comment: | Added support for allowing the user to completely control how downloads are performed as well as configure the default method |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | 3864351ad443a845f4479be044e9bf5eafb0dc44 |
User & Date: | rkeene on 2016-07-10 19:26:13 |
Other Links: | manifest | tags |
Context
2017-02-06
| ||
15:57 | Added support for a Tcl "exec" target to be compiled in check-in: 3d73fc5750 user: rkeene tags: trunk | |
2017-01-19
| ||
17:49 | Started work on completely supporting multiple hashing algorithms check-in: 2460a1ddab user: rkeene tags: complete-multihash | |
2016-07-10
| ||
19:26 | Added support for allowing the user to completely control how downloads are performed as well as configure the default method check-in: 3864351ad4 user: rkeene tags: trunk | |
19:05 | Fixed typo in debug message check-in: 936a791a4a user: rkeene tags: trunk | |
Changes
Modified appfsd.tcl from [865f14848a] to [985d2df621].
27 28 29 30 31 32 33 34 35 36 37 38 39 40 .. 49 50 51 52 53 54 55 56 57 58 59 60 61 62 .. 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 .. 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 ... 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
package require sha1 package require appfsd package require platform package require pki # Functions specifically meant for users to replace as a part of configuration namespace eval ::appfs::user { # User-replacable function to convert a hostname/hash/method to an URL proc construct_url {hostname hash method} { return "http://$hostname/appfs/$method/$hash" } # User-replaceable function get the home directory of the current user proc get_homedir {} { ................................................................................ if {[info exists ::appfs::user::add_perms($sha1)]} { append perms $::appfs::user::add_perms($sha1) } return $perms } } namespace eval ::appfs { variable cachedir "/tmp/appfs-cache" variable ttl 3600 variable nttl 60 variable trusted_cas [list] ................................................................................ append retval "[string range $hash [expr {$idx * 2}] [expr {($idx * 2) + 1}]]/" } append retval "[string range $hash [expr {$idx * 2}] end]" return $retval } proc _cachefile {url key {keyIsHash 1}} { set filekey $key if {$keyIsHash} { set filekey [_hash_sep $filekey] } set file [file join $::appfs::cachedir $filekey] ................................................................................ set tmpfile "${file}.[expr {rand()}][clock clicks]" set fd [open $tmpfile "w"] fconfigure $fd -translation binary catch { set token [::http::geturl $url -channel $fd -binary true] } if {[info exists token]} { set ncode [::http::ncode $token] ::http::reset $token } else { set ncode "900" } close $fd if {$keyIsHash} { set hash [string tolower [sha1::sha1 -hex -file $tmpfile]] } else { set hash $key } if {$ncode == "200" && $hash == $key} { file rename -force -- $tmpfile $file } else { file delete -force -- $tmpfile } return $file } ................................................................................ db eval {CREATE INDEX IF NOT EXISTS sites_index ON sites (hostname);} db eval {CREATE INDEX IF NOT EXISTS packages_index ON packages (hostname, sha1, package, version, os, cpuArch);} db eval {CREATE INDEX IF NOT EXISTS files_index ON files (package_sha1, file_name, file_directory);} } proc download {hostname hash {method sha1}} { set url [::appfs::user::construct_url $hostname $hash $method] set file [_cachefile $url $hash] if {![file exists $file]} { return -code error "Unable to fetch (file does not exist: $file)" } return $file } ................................................................................ if {$now < ($lastUpdate + $ttl)} { return COMPLETE } set url "http://$hostname/appfs/index" catch { set token [::http::geturl $url] if {[::http::ncode $token] == "200"} { set indexhash_data [::http::data $token] } ::http::reset $token ::http::cleanup $token } # Note that we attempted to fetch this index and do not try # again for a while db eval {INSERT OR REPLACE INTO sites (hostname, lastUpdate, ttl) VALUES ($hostname, $now, $::appfs::nttl);} if {![info exists indexhash_data]} { |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | < < < < < < < | | < < | < < < |
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 .. 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ... 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 ... 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 ... 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 ... 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
package require sha1 package require appfsd package require platform package require pki # Functions specifically meant for users to replace as a part of configuration namespace eval ::appfs::user { variable download_method "tcl" # User-replacable function to convert a hostname/hash/method to an URL proc construct_url {hostname hash method} { return "http://$hostname/appfs/$method/$hash" } # User-replaceable function get the home directory of the current user proc get_homedir {} { ................................................................................ if {[info exists ::appfs::user::add_perms($sha1)]} { append perms $::appfs::user::add_perms($sha1) } return $perms } # User-replacable function to fetch a remote file proc download_file {url {outputChannel ""}} { switch -- $::appfs::user::download_method { "curl" { if {$outputChannel eq ""} { return [exec curl -sS -L -- $url] } else { exec curl -sS -L -- $url >@ $outputChannel return "" } } "tcl" { catch { if {$outputChannel eq ""} { set token [http::geturl $url] set retval [http::data $token] } else { set token [http::geturl $url -binary true -channel $outputChannel] set retval "" } } err if {![info exists token]} { return -code error "Unable to download \"$url\": $err" } set tokenCode [http::ncode $token] http::cleanup $token if {$tokenCode != "200"} { return -code error "Unable to download \"$url\": Site did not return a 200 (returned $tokenCode)" } if {![info exists retval]} { return -code error "Unable to download \"$url\": Site did not return proper data: $err" } return $retval } } return -code error "Unable to download" } } namespace eval ::appfs { variable cachedir "/tmp/appfs-cache" variable ttl 3600 variable nttl 60 variable trusted_cas [list] ................................................................................ append retval "[string range $hash [expr {$idx * 2}] [expr {($idx * 2) + 1}]]/" } append retval "[string range $hash [expr {$idx * 2}] end]" return $retval } proc _cachefile {url key method {keyIsHash 1}} { if {$keyIsHash && $method != "sha1"} { return -code error "Only SHA1 hashing method is supported" } set filekey $key if {$keyIsHash} { set filekey [_hash_sep $filekey] } set file [file join $::appfs::cachedir $filekey] ................................................................................ set tmpfile "${file}.[expr {rand()}][clock clicks]" set fd [open $tmpfile "w"] fconfigure $fd -translation binary catch { ::appfs::user::download_file $url $fd } close $fd if {$keyIsHash} { set hash [string tolower [sha1::sha1 -hex -file $tmpfile]] } else { set hash $key } if {$hash == $key} { file rename -force -- $tmpfile $file } else { file delete -force -- $tmpfile } return $file } ................................................................................ db eval {CREATE INDEX IF NOT EXISTS sites_index ON sites (hostname);} db eval {CREATE INDEX IF NOT EXISTS packages_index ON packages (hostname, sha1, package, version, os, cpuArch);} db eval {CREATE INDEX IF NOT EXISTS files_index ON files (package_sha1, file_name, file_directory);} } proc download {hostname hash {method sha1}} { set url [::appfs::user::construct_url $hostname $hash $method] set file [_cachefile $url $hash $method] if {![file exists $file]} { return -code error "Unable to fetch (file does not exist: $file)" } return $file } ................................................................................ if {$now < ($lastUpdate + $ttl)} { return COMPLETE } set url "http://$hostname/appfs/index" catch { set indexhash_data [::appfs::user::download_file $url] } # Note that we attempted to fetch this index and do not try # again for a while db eval {INSERT OR REPLACE INTO sites (hostname, lastUpdate, ttl) VALUES ($hostname, $now, $::appfs::nttl);} if {![info exists indexhash_data]} { |