@@ -121,10 +121,20 @@ } } return -code error "Unable to normalize CPU: $cpu" } + + proc _as_user {code} { + ::appfsd::simulate_user_fs_enter + + set retcode [catch [list uplevel $code] retstr] + + ::appfsd::simulate_user_fs_leave + + return -code $retcode $retstr + } proc init {} { if {[info exists ::appfs::init_called]} { return } @@ -158,17 +168,13 @@ db eval {CREATE INDEX IF NOT EXISTS packages_index ON packages (hostname, 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}} { - ::appfsd::simulate_user_fs_leave - set url [_construct_url $hostname $hash $method] set file [_cachefile $url $hash] - ::appfsd::simulate_user_fs_enter - if {![file exists $file]} { return -code error "Unable to fetch (file does not exist: $file)" } return $file @@ -466,35 +472,37 @@ } set retval [::appfs::db eval {SELECT DISTINCT file_name FROM files WHERE package_sha1 = $pathinfo(package_sha1) AND file_directory = $pathinfo(file);}] if {[info exists pathinfo(package)] && [info exists pathinfo(hostname)] && [info exists pathinfo(file)]} { - set dir [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)] - set whiteoutdir [string range [_whiteoutpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)] 0 end-15] - - foreach file [glob -nocomplain -tails -directory $whiteoutdir {{.,}*.APPFS.WHITEOUT}] { - set remove [string range $file 0 end-15] - set idx [lsearch -exact $retval $remove] - if {$idx != -1} { - set retval [lreplace $retval $idx $idx] - } - } - - foreach file [glob -nocomplain -tails -directory $dir -types {d f l p s} {{.,}*}] { - if {$file == "." || $file == ".."} { - continue - } - - if {$file == ".APPFS.WHITEOUT"} { - continue - } - - if {[lsearch -exact $retval $file] != -1} { - continue - } - - lappend retval $file + _as_user { + set dir [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)] + set whiteoutdir [string range [_whiteoutpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)] 0 end-15] + + foreach file [glob -nocomplain -tails -directory $whiteoutdir {{.,}*.APPFS.WHITEOUT}] { + set remove [string range $file 0 end-15] + set idx [lsearch -exact $retval $remove] + if {$idx != -1} { + set retval [lreplace $retval $idx $idx] + } + } + + foreach file [glob -nocomplain -tails -directory $dir -types {d f l p s} {{.,}*}] { + if {$file == "." || $file == ".."} { + continue + } + + if {$file == ".APPFS.WHITEOUT"} { + continue + } + + if {[lsearch -exact $retval $file] != -1} { + continue + } + + lappend retval $file + } } } return $retval } @@ -513,11 +521,11 @@ } switch -- $pathinfo(_type) { "toplevel" { set retval(type) directory - set retval(childcount) 2; + set retval(childcount) 2 } "sites" { set check [::appfs::db onecolumn {SELECT 1 FROM packages WHERE hostname = $pathinfo(hostname);}] if {$check == "1"} { set retval(type) directory @@ -566,11 +574,13 @@ set retval(whiteoutpath) $whiteoutpath if {[file exists $localpath]} { set retval(is_localfile) 1 catch { - file lstat $localpath localpathinfo + _as_user { + file lstat $localpath localpathinfo + } set retval(time) $localpathinfo(mtime) switch -- $localpathinfo(type) { "directory" { set retval(type) "directory" @@ -577,19 +587,24 @@ set retval(childcount) 2 } "file" { set retval(type) "file" set retval(size) $localpathinfo(size) - if {[file executable $localpath]} { - set retval(perms) "x" - } else { - set retval(perms) "" + _as_user { + if {[file executable $localpath]} { + set retval(perms) "x" + } else { + set retval(perms) "" + } } } "link" { set retval(type) "symlink" - set retval(source) [file readlink $localpath] + + _as_user { + set retval(source) [file readlink $localpath] + } } "fifo" { # Capitalized so that the first char is unique set retval(type) "Fifo" } @@ -653,27 +668,29 @@ } set localcachefile [download $pathinfo(hostname) $pkgpathinfo(file_sha1)] if {$mode == "write"} { - set tmplocalpath "${localpath}.[expr rand()][clock clicks]" - - set failed 0 - if {[catch { - file mkdir [file dirname $localpath] - file copy -force -- $localcachefile $tmplocalpath - - if {$pkgpathinfo(perms) == "x"} { - file attributes $tmplocalpath -permissions +x - } - - file rename -force -- $tmplocalpath $localpath - } err]} { - set failed 1 - } - catch { - file delete -force -- $tmplocalpath + _as_user { + set tmplocalpath "${localpath}.[expr rand()][clock clicks]" + + set failed 0 + if {[catch { + file mkdir [file dirname $localpath] + file copy -force -- $localcachefile $tmplocalpath + + if {$pkgpathinfo(perms) == "x"} { + file attributes $tmplocalpath -permissions +x + } + + file rename -force -- $tmplocalpath $localpath + } err]} { + set failed 1 + } + catch { + file delete -force -- $tmplocalpath + } } if {$failed} { return -code error $err } @@ -721,11 +738,13 @@ set filename [localpath $path] set dirname [file dirname $filename] - file mkdir $dirname + _as_user { + file mkdir $dirname + } return $filename } proc unlinkpath {path} { @@ -744,11 +763,13 @@ if {[llength $children] != 0} { return -code error "Asked to delete non-empty directory" } } - file delete -force -- $localpath + _as_user { + file delete -force -- $localpath + } } elseif {[info exists pathattrs(is_remotefile)]} { if {$pathattrs(type) == "directory"} { set children [getchildren $path] if {[llength $children] != 0} { @@ -759,9 +780,12 @@ return -code error "Unknown if file is remote or local !?" } set whiteoutfile $pathattrs(whiteoutpath) set whiteoutdir [file dirname $whiteoutfile] - file mkdir $whiteoutdir - close [open $whiteoutfile w] + + _as_user { + file mkdir $whiteoutdir + close [open $whiteoutfile w] + } } }