Index: appfsd.c ================================================================== --- appfsd.c +++ appfsd.c @@ -431,10 +431,22 @@ Tcl_SetObjResult(interp, homedir_obj); return(TCL_OK); } + +static int tcl_appfs_simulate_user_fs_enter(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + appfs_simulate_user_fs_enter(); + + return(TCL_OK); +} + +static int tcl_appfs_simulate_user_fs_leave(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + appfs_simulate_user_fs_leave(); + + return(TCL_OK); +} /* * Generate an inode for a given path. The inode should be computed in such * a way that it is unlikely to be duplicated and remains the same for a given * file @@ -469,12 +481,17 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(-EIO); } + + appfs_simulate_user_fs_enter(); tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); + + appfs_simulate_user_fs_leave(); + if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::getattr(%s) failed.", path); APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); return(-ENOENT); @@ -557,13 +574,15 @@ memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int); } } break; - case 'p': /* pipe/fifo */ + case 'F': /* pipe/fifo */ + pathinfo->type = APPFS_PATHTYPE_FIFO; break; case 'S': /* UNIX domain socket */ + pathinfo->type = APPFS_PATHTYPE_SOCKET; break; default: return(-EIO); } @@ -707,11 +726,19 @@ stbuf->st_mode = S_IFLNK | 0555; stbuf->st_nlink = 1; stbuf->st_size = pathinfo.typeinfo.symlink.size; break; case APPFS_PATHTYPE_SOCKET: + stbuf->st_mode = S_IFSOCK | 0555; + stbuf->st_nlink = 1; + stbuf->st_size = 0; + break; case APPFS_PATHTYPE_FIFO: + stbuf->st_mode = S_IFIFO | 0555; + stbuf->st_nlink = 1; + stbuf->st_size = 0; + break; case APPFS_PATHTYPE_INVALID: retval = -ENOENT; break; } @@ -736,12 +763,17 @@ return(0); } filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); + + appfs_simulate_user_fs_enter(); tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path); + + appfs_simulate_user_fs_leave(); + if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::getchildren(%s) failed.", path); APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); return(0); @@ -1147,10 +1179,12 @@ return(TCL_ERROR); } #endif Tcl_CreateObjCommand(interp, "appfsd::get_homedir", tcl_appfs_get_homedir, NULL, NULL); + Tcl_CreateObjCommand(interp, "appfsd::simulate_user_fs_enter", tcl_appfs_simulate_user_fs_enter, NULL, NULL); + Tcl_CreateObjCommand(interp, "appfsd::simulate_user_fs_leave", tcl_appfs_simulate_user_fs_leave, NULL, NULL); Tcl_PkgProvide(interp, "appfsd", "1.0"); return(TCL_OK); } Index: appfsd.tcl ================================================================== --- appfsd.tcl +++ appfsd.tcl @@ -157,12 +157,16 @@ 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)" } @@ -472,11 +476,11 @@ if {$idx != -1} { set retval [lreplace $retval $idx $idx] } } - foreach file [glob -nocomplain -tails -directory $dir -types {d f l} {{.,}*}] { + foreach file [glob -nocomplain -tails -directory $dir -types {d f l p s} {{.,}*}] { if {$file == "." || $file == ".."} { continue } if {$file == ".APPFS.WHITEOUT"} { @@ -582,10 +586,18 @@ } "link" { set retval(type) "symlink" set retval(source) [file readlink $localpath] } + "fifo" { + # Capitalized so that the first char is unique + set retval(type) "Fifo" + } + "socket" { + # Capitalized so that the first char is unique + set retval(type) "Socket" + } } } err } else { if {![file exists $whiteoutpath]} { set retval(is_remotefile) 1 @@ -722,40 +734,33 @@ return -code error "invalid type" } set localpath $pathattrs(localpath) - set whiteout 0 - set isdirectory 0 if {[info exists pathattrs(is_localfile)]} { if {[file isdirectory $localpath]} { - set whiteout 1 + set children [getchildren $path] - set isdirectory 1 - set children [getchildren $path] + if {[llength $children] != 0} { + return -code error "Asked to delete non-empty directory" + } } + file delete -force -- $localpath } elseif {[info exists pathattrs(is_remotefile)]} { if {$pathattrs(type) == "directory"} { - set isdirectory 1 set children [getchildren $path] - } - set whiteout 1 + if {[llength $children] != 0} { + return -code error "Asked to delete non-empty directory" + } + } } else { return -code error "Unknown if file is remote or local !?" } - if {$isdirectory} { - if {$children != [list]} { - return -code error "Asked to delete non-empty directory" - } - } - - if {$whiteout} { - set whiteoutfile $pathattrs(whiteoutpath) - set whiteoutdir [file dirname $whiteoutfile] - file mkdir $whiteoutdir - close [open $whiteoutfile w] - } + set whiteoutfile $pathattrs(whiteoutpath) + set whiteoutdir [file dirname $whiteoutfile] + file mkdir $whiteoutdir + close [open $whiteoutfile w] } }