@@ -307,10 +307,16 @@ interp = NULL; pthread_ret = pthread_setspecific(interpKey, interp); } + + if (global_interp_reset_key == -1) { + APPFS_DEBUG("Not creating a new interpreter since we are terminating."); + + return(NULL); + } thread_interp_reset_key = global_interp_reset_key; if (interp == NULL) { interp = appfs_create_TclInterp(NULL); @@ -346,17 +352,21 @@ if (interp == NULL) { return(TCL_ERROR); } objv = (void *) ckalloc(sizeof(*objv) * objc); + objv[0] = Tcl_NewStringObj(cmd, -1); + Tcl_IncrRefCount(objv[0]); va_start(argp, cmd); for (i = 1; i < objc; i++) { arg = va_arg(argp, const char *); + objv[i] = Tcl_NewStringObj(arg, -1); + Tcl_IncrRefCount(objv[i]); } va_end(argp); retval = Tcl_EvalObjv(interp, objc, objv, 0); @@ -758,12 +768,10 @@ pathinfo->packaged = 0; pathinfo->inode = appfs_get_path_inode(path); attr_value_str = Tcl_GetString(attr_value); - Tcl_DecrRefCount(attr_value); - switch (attr_value_str[0]) { case 'd': /* directory */ pathinfo->type = APPFS_PATHTYPE_DIRECTORY; pathinfo->typeinfo.dir.childcount = 0; @@ -771,12 +779,10 @@ if (attr_value != NULL) { tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); if (tcl_ret == TCL_OK) { pathinfo->typeinfo.dir.childcount = attr_value_wide; } - - Tcl_DecrRefCount(attr_value); } break; case 'f': /* file */ pathinfo->type = APPFS_PATHTYPE_FILE; @@ -787,22 +793,18 @@ if (attr_value != NULL) { tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); if (tcl_ret == TCL_OK) { pathinfo->typeinfo.file.size = attr_value_wide; } - - Tcl_DecrRefCount(attr_value); } Tcl_DictObjGet(interp, attrs_dict, attr_key_perms, &attr_value); if (attr_value != NULL) { attr_value_str = Tcl_GetString(attr_value); if (attr_value_str[0] == 'x') { pathinfo->typeinfo.file.executable = 1; } - - Tcl_DecrRefCount(attr_value); } break; case 's': /* symlink */ pathinfo->type = APPFS_PATHTYPE_SYMLINK; pathinfo->typeinfo.symlink.size = 0; @@ -816,43 +818,35 @@ pathinfo->typeinfo.symlink.size = attr_value_int; pathinfo->typeinfo.symlink.source[attr_value_int] = '\0'; memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int); } - - Tcl_DecrRefCount(attr_value); } break; case 'F': /* pipe/fifo */ pathinfo->type = APPFS_PATHTYPE_FIFO; break; case 'S': /* UNIX domain socket */ pathinfo->type = APPFS_PATHTYPE_SOCKET; break; default: - Tcl_DecrRefCount(attrs_dict); - Tcl_Release(interp); return(-EIO); } Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value); if (attr_value != NULL) { pathinfo->packaged = 1; - - Tcl_DecrRefCount(attr_value); } Tcl_DictObjGet(interp, attrs_dict, attr_key_time, &attr_value); if (attr_value != NULL) { tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide); if (tcl_ret == TCL_OK) { pathinfo->time = attr_value_wide; } - - Tcl_DecrRefCount(attr_value); } else { pathinfo->time = 0; } Tcl_Release(interp); @@ -925,10 +919,34 @@ return(NULL); } return(strdup(real_path)); } + +#ifdef APPFS_EXIT_PATH +static void appfs_exit(void) { + int global_interp_reset_key; + + global_interp_reset_key = __sync_fetch_and_add(&interp_reset_key, 0); + __sync_fetch_and_sub(&interp_reset_key, global_interp_reset_key); + + while (__sync_sub_and_fetch(&interp_reset_key, 1) >= 0) { + /* Busy Loop */ + } + + global_interp_reset_key = __sync_fetch_and_add(&interp_reset_key, 0); + if (global_interp_reset_key != -1) { + APPFS_DEBUG("Error sending kill signal to all threads, aborting anyway."); + } + + fuse_exit(fuse_get_context()->fuse); + + appfs_get_path_info_cache_flush(-1, -1); + + return; +} +#endif static int appfs_fuse_readlink(const char *path, char *buf, size_t size) { struct appfs_pathinfo pathinfo; int retval = 0; @@ -959,10 +977,21 @@ int retval; retval = 0; APPFS_DEBUG("Enter (path = %s, ...)", path); + +#if (defined(DEBUG) && defined(APPFS_EXIT_PATH)) || defined(APPFS_EXIT_PATH_ENABLE_MAJOR_SECURITY_HOLE) + /* + * This is a major security issue so we cannot let it be compiled into + * any release + */ + + if (strcmp(path, "/exit") == 0) { + appfs_exit(); + } +#endif pathinfo.type = APPFS_PATHTYPE_INVALID; retval = appfs_get_path_info(path, &pathinfo); if (retval != 0) { @@ -1066,12 +1095,10 @@ for (idx = 0; idx < children_count; idx++) { filler(buf, Tcl_GetString(children[idx]), NULL, 0); } - Tcl_DecrRefCount(children); - Tcl_Release(interp); return(0); }