Index: appfsd.c ================================================================== --- appfsd.c +++ appfsd.c @@ -53,10 +53,23 @@ */ pthread_mutex_t appfs_path_info_cache_mutex = PTHREAD_MUTEX_INITIALIZER; int appfs_path_info_cache_size = 8209; struct appfs_pathinfo *appfs_path_info_cache = NULL; +#ifndef TCL_THREADS +/* + * Handle unthreaded Tcl + */ +pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER; +#define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock); +#define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock); +#else +#define appfs_call_libtcl_enter /**/ +#define appfs_call_libtcl_exit /**/ +#endif +#define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit + /* * Global variables for AppFS Tcl Interpreter restarting */ int interp_reset_key = 0; @@ -107,14 +120,17 @@ * Create a new Tcl interpreter and completely initialize it */ static Tcl_Interp *appfs_create_TclInterp(char **error_string) { Tcl_Interp *interp; int tcl_ret; + const char *tcl_setvar_ret; APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self()); - interp = Tcl_CreateInterp(); + appfs_call_libtcl( + interp = Tcl_CreateInterp(); + ) if (interp == NULL) { fprintf(stderr, "Unable to create Tcl Interpreter. Aborting.\n"); if (error_string) { *error_string = strdup("Unable to create Tcl interpreter."); @@ -121,168 +137,211 @@ } return(NULL); } - Tcl_Preserve(interp); - - tcl_ret = Tcl_Init(interp); - if (tcl_ret != TCL_OK) { - fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); - - if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); - } - - Tcl_Release(interp); - - APPFS_DEBUG("Terminating Tcl interpreter."); - - Tcl_DeleteInterp(interp); - - return(NULL); - } - - tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]"); - if (tcl_ret != TCL_OK) { - fprintf(stderr, "Unable to initialize Tcl SHA1. Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); - - if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); - } - - Tcl_Release(interp); - - APPFS_DEBUG("Terminating Tcl interpreter."); - - Tcl_DeleteInterp(interp); - - return(NULL); - } - - tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]"); - if (tcl_ret != TCL_OK) { - fprintf(stderr, "Unable to initialize Tcl AppFS Package. Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); - - if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); - } - - Tcl_Release(interp); - - APPFS_DEBUG("Terminating Tcl interpreter."); - - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) + + appfs_call_libtcl( + tcl_ret = Tcl_Init(interp); + ) + if (tcl_ret != TCL_OK) { + fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); + appfs_call_libtcl( + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + ) + + if (error_string) { + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) + } + + appfs_call_libtcl(Tcl_Release(interp);) + + APPFS_DEBUG("Terminating Tcl interpreter."); + + appfs_call_libtcl(Tcl_DeleteInterp(interp);) + + return(NULL); + } + + appfs_call_libtcl( + tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]"); + ) + if (tcl_ret != TCL_OK) { + fprintf(stderr, "Unable to initialize Tcl SHA1. Aborting.\n"); + appfs_call_libtcl( + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + ) + + if (error_string) { + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) + } + + appfs_call_libtcl(Tcl_Release(interp);) + + APPFS_DEBUG("Terminating Tcl interpreter."); + + appfs_call_libtcl(Tcl_DeleteInterp(interp);) + + return(NULL); + } + + appfs_call_libtcl( + tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]"); + ) + if (tcl_ret != TCL_OK) { + fprintf(stderr, "Unable to initialize Tcl AppFS Package. Aborting.\n"); + appfs_call_libtcl( + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + ) + + if (error_string) { + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) + } + + appfs_call_libtcl(Tcl_Release(interp);) + + APPFS_DEBUG("Terminating Tcl interpreter."); + + appfs_call_libtcl(Tcl_DeleteInterp(interp);) return(NULL); } /* * Load "pki.tcl" in the same way as appfsd.tcl (see below) */ - tcl_ret = Tcl_Eval(interp, "" + appfs_call_libtcl_enter + tcl_ret = Tcl_Eval(interp, "" #include "pki.tcl.h" - ""); + ""); + appfs_call_libtcl_exit if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl PKI. Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + ) if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) } - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) APPFS_DEBUG("Terminating Tcl interpreter."); - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_DeleteInterp(interp);) return(NULL); } /* * Load the "appfsd.tcl" script, which is "compiled" into a C header * so that it does not need to exist on the filesystem and can be * directly evaluated. */ - tcl_ret = Tcl_Eval(interp, "" + appfs_call_libtcl_enter + tcl_ret = Tcl_Eval(interp, "" #include "appfsd.tcl.h" - ""); + ""); + appfs_call_libtcl_exit if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl AppFS script. Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + ) if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) } - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) APPFS_DEBUG("Terminating Tcl interpreter."); - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_DeleteInterp(interp);) return(NULL); } /* * Set global variables from C to Tcl */ - if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) { + appfs_call_libtcl( + tcl_setvar_ret = Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY); + ) + if (tcl_setvar_ret == NULL) { fprintf(stderr, "Unable to set cache directory. This should never fail.\n"); if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) } - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) APPFS_DEBUG("Terminating Tcl interpreter."); - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_DeleteInterp(interp);) return(NULL); } /* * Initialize the "appfsd.tcl" environment, which must be done after * global variables are set. */ - tcl_ret = Tcl_Eval(interp, "::appfs::init"); + appfs_call_libtcl( + tcl_ret = Tcl_Eval(interp, "::appfs::init"); + ) if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init). Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + ) if (error_string) { - *error_string = strdup(Tcl_GetStringResult(interp)); + appfs_call_libtcl( + *error_string = strdup(Tcl_GetStringResult(interp)); + ) } - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) APPFS_DEBUG("Terminating Tcl interpreter."); - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_DeleteInterp(interp);) return(NULL); } /* * Hide some Tcl commands that we do not care to use and which may * slow down run-time operations. */ - Tcl_HideCommand(interp, "auto_load_index", "auto_load_index"); - Tcl_HideCommand(interp, "unknown", "unknown"); - Tcl_HideCommand(interp, "exit", "exit"); + appfs_call_libtcl( + Tcl_HideCommand(interp, "auto_load_index", "auto_load_index"); + Tcl_HideCommand(interp, "unknown", "unknown"); + Tcl_HideCommand(interp, "exit", "exit"); + ) /* * Release the hold we have on the interpreter so that it may be * deleted if needed */ - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) /* * Return the completely initialized interpreter */ return(interp); @@ -301,11 +360,11 @@ interp = pthread_getspecific(interpKey); if (interp != NULL && thread_interp_reset_key != global_interp_reset_key) { APPFS_DEBUG("Terminating old interpreter and restarting due to reset request."); - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_DeleteInterp(interp);) interp = NULL; pthread_ret = pthread_setspecific(interpKey, interp); } @@ -327,11 +386,11 @@ pthread_ret = pthread_setspecific(interpKey, interp); if (pthread_ret != 0) { APPFS_DEBUG("pthread_setspecific() failed. Terminating Tcl interpreter."); - Tcl_DeleteInterp(interp); + appfs_call_libtcl(Tcl_DeleteInterp(interp);) return(NULL); } } @@ -353,34 +412,42 @@ 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); - - for (i = 0; i < objc; i++) { - Tcl_DecrRefCount(objv[i]); - } + appfs_call_libtcl( + 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); + ) + + appfs_call_libtcl( + retval = Tcl_EvalObjv(interp, objc, objv, 0); + ) + + appfs_call_libtcl( + for (i = 0; i < objc; i++) { + Tcl_DecrRefCount(objv[i]); + } + ) ckfree((void *) objv); if (retval != TCL_OK) { - APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0)); + ) } return(retval); } @@ -698,11 +765,14 @@ Tcl_WideInt attr_value_wide; int attr_value_int; static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL, *attr_key_packaged = NULL; int cache_ret; int tcl_ret; + int retval; uid_t fsuid; + + retval = 0; fsuid = appfs_get_fsuid(); cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo); if (cache_ret == 0) { @@ -720,142 +790,160 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(-EIO); } - Tcl_Preserve(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::getattr(%s) failed.", path); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) pathinfo->type = APPFS_PATHTYPE_DOES_NOT_EXIST; appfs_get_path_info_cache_add(path, fsuid, pathinfo); - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(-ENOENT); } if (attr_key_type == NULL) { - attr_key_type = Tcl_NewStringObj("type", -1); - attr_key_perms = Tcl_NewStringObj("perms", -1); - attr_key_size = Tcl_NewStringObj("size", -1); - attr_key_time = Tcl_NewStringObj("time", -1); - attr_key_source = Tcl_NewStringObj("source", -1); - attr_key_childcount = Tcl_NewStringObj("childcount", -1); - attr_key_packaged = Tcl_NewStringObj("packaged", -1); + appfs_call_libtcl( + attr_key_type = Tcl_NewStringObj("type", -1); + attr_key_perms = Tcl_NewStringObj("perms", -1); + attr_key_size = Tcl_NewStringObj("size", -1); + attr_key_time = Tcl_NewStringObj("time", -1); + attr_key_source = Tcl_NewStringObj("source", -1); + attr_key_childcount = Tcl_NewStringObj("childcount", -1); + attr_key_packaged = Tcl_NewStringObj("packaged", -1); + + Tcl_IncrRefCount(attr_key_type); + Tcl_IncrRefCount(attr_key_perms); + Tcl_IncrRefCount(attr_key_size); + Tcl_IncrRefCount(attr_key_time); + Tcl_IncrRefCount(attr_key_source); + Tcl_IncrRefCount(attr_key_childcount); + Tcl_IncrRefCount(attr_key_packaged); + ) } - attrs_dict = Tcl_GetObjResult(interp); - tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value); + appfs_call_libtcl( + attrs_dict = Tcl_GetObjResult(interp); + tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value); + ) if (tcl_ret != TCL_OK) { APPFS_DEBUG("[dict get \"type\"] failed"); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } if (attr_value == NULL) { - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } pathinfo->packaged = 0; pathinfo->inode = appfs_get_path_inode(path); - attr_value_str = Tcl_GetString(attr_value); - - switch (attr_value_str[0]) { - case 'd': /* directory */ - pathinfo->type = APPFS_PATHTYPE_DIRECTORY; - pathinfo->typeinfo.dir.childcount = 0; - - Tcl_DictObjGet(interp, attrs_dict, attr_key_childcount, &attr_value); - 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; - } - } - - break; - case 'f': /* file */ - pathinfo->type = APPFS_PATHTYPE_FILE; - pathinfo->typeinfo.file.size = 0; - pathinfo->typeinfo.file.executable = 0; - - Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value); - 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_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; - } - } - break; - case 's': /* symlink */ - pathinfo->type = APPFS_PATHTYPE_SYMLINK; - pathinfo->typeinfo.symlink.size = 0; - pathinfo->typeinfo.symlink.source[0] = '\0'; - - Tcl_DictObjGet(interp, attrs_dict, attr_key_source, &attr_value); - if (attr_value != NULL) { - attr_value_str = Tcl_GetStringFromObj(attr_value, &attr_value_int); - - if ((attr_value_int + 1) <= sizeof(pathinfo->typeinfo.symlink.source)) { - 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); - } - } - break; - case 'F': /* pipe/fifo */ - pathinfo->type = APPFS_PATHTYPE_FIFO; - break; - case 'S': /* UNIX domain socket */ - pathinfo->type = APPFS_PATHTYPE_SOCKET; - break; - default: - Tcl_Release(interp); - - return(-EIO); - } - - Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value); - if (attr_value != NULL) { - pathinfo->packaged = 1; - } - - 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; - } - } else { - pathinfo->time = 0; - } - - Tcl_Release(interp); - - appfs_get_path_info_cache_add(path, fsuid, pathinfo); - - return(0); + appfs_call_libtcl( + attr_value_str = Tcl_GetString(attr_value); + + switch (attr_value_str[0]) { + case 'd': /* directory */ + pathinfo->type = APPFS_PATHTYPE_DIRECTORY; + pathinfo->typeinfo.dir.childcount = 0; + + Tcl_DictObjGet(interp, attrs_dict, attr_key_childcount, &attr_value); + 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; + } + } + + break; + case 'f': /* file */ + pathinfo->type = APPFS_PATHTYPE_FILE; + pathinfo->typeinfo.file.size = 0; + pathinfo->typeinfo.file.executable = 0; + + Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value); + 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_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; + } + } + break; + case 's': /* symlink */ + pathinfo->type = APPFS_PATHTYPE_SYMLINK; + pathinfo->typeinfo.symlink.size = 0; + pathinfo->typeinfo.symlink.source[0] = '\0'; + + Tcl_DictObjGet(interp, attrs_dict, attr_key_source, &attr_value); + if (attr_value != NULL) { + attr_value_str = Tcl_GetStringFromObj(attr_value, &attr_value_int); + + if ((attr_value_int + 1) <= sizeof(pathinfo->typeinfo.symlink.source)) { + 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); + } + } + break; + case 'F': /* pipe/fifo */ + pathinfo->type = APPFS_PATHTYPE_FIFO; + break; + case 'S': /* UNIX domain socket */ + pathinfo->type = APPFS_PATHTYPE_SOCKET; + break; + default: + retval = -EIO; + } + + Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value); + if (attr_value != NULL) { + pathinfo->packaged = 1; + } + + 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; + } + } else { + pathinfo->time = 0; + } + + Tcl_Release(interp); + ) + + if (retval == 0) { + appfs_get_path_info_cache_add(path, fsuid, pathinfo); + } + + return(retval); } static char *appfs_prepare_to_create(const char *path) { Tcl_Interp *interp; const char *real_path; @@ -866,25 +954,31 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(NULL); } - Tcl_Preserve(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) - tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path); + appfs_call_libtcl( + tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path); + ) if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::prepare_to_create(%s) failed.", path); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(NULL); } - real_path = Tcl_GetStringResult(interp); + appfs_call_libtcl( + real_path = Tcl_GetStringResult(interp); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) if (real_path == NULL) { return(NULL); } @@ -899,23 +993,29 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(NULL); } - Tcl_Preserve(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) - tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path); + appfs_call_libtcl( + tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path); + ) if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::localpath(%s) failed.", path); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) return(NULL); } - real_path = Tcl_GetStringResult(interp); + appfs_call_libtcl( + real_path = Tcl_GetStringResult(interp); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) if (real_path == NULL) { return(NULL); } @@ -1066,40 +1166,48 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(0); } - Tcl_Preserve(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::getchildren(%s) failed.", path); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(0); } - tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children); + appfs_call_libtcl( + tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children); + ) if (tcl_ret != TCL_OK) { APPFS_DEBUG("Parsing list of children on path %s failed.", path); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(0); } for (idx = 0; idx < children_count; idx++) { - filler(buf, Tcl_GetString(children[idx]), NULL, 0); + appfs_call_libtcl( + filler(buf, Tcl_GetString(children[idx]), NULL, 0); + ) } - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(0); } static int appfs_fuse_open(const char *path, struct fuse_file_info *fi) { @@ -1146,25 +1254,29 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(-EIO); } - Tcl_Preserve(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } - real_path = Tcl_GetStringResult(interp); + appfs_call_libtcl( + real_path = Tcl_GetStringResult(interp); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) if (real_path == NULL) { return(-EIO); } @@ -1340,18 +1452,20 @@ } tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::unlinkpath", path); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::unlinkpath(%s) failed.", path); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(0); } static int appfs_fuse_mkdir(const char *path, mode_t mode) { @@ -1394,25 +1508,29 @@ interp = appfs_TclInterp(); if (interp == NULL) { return(-EIO); } - Tcl_Preserve(interp); + appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, "write"); if (tcl_ret != TCL_OK) { APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, "write"); - APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + appfs_call_libtcl( + APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } - real_path = Tcl_GetStringResult(interp); + appfs_call_libtcl( + real_path = Tcl_GetStringResult(interp); + ) - Tcl_Release(interp); + appfs_call_libtcl(Tcl_Release(interp);) if (real_path == NULL) { return(-EIO); } @@ -1510,10 +1628,12 @@ fsuid = appfs_get_fsuid(); if (fsuid == last_fsuid && last_homedir_obj != NULL) { homedir_obj = last_homedir_obj; + + Tcl_IncrRefCount(homedir_obj); } else { homedir = appfs_get_homedir(appfs_get_fsuid()); if (homedir == NULL) { return(TCL_ERROR); @@ -1520,22 +1640,26 @@ } homedir_obj = Tcl_NewStringObj(homedir, -1); free(homedir); + + Tcl_IncrRefCount(homedir_obj); if (last_homedir_obj != NULL) { Tcl_DecrRefCount(last_homedir_obj); } last_homedir_obj = homedir_obj; last_fsuid = fsuid; - Tcl_IncrRefCount(last_homedir_obj); + Tcl_IncrRefCount(homedir_obj); } Tcl_SetObjResult(interp, homedir_obj); + + Tcl_DecrRefCount(homedir_obj); return(TCL_OK); } static int tcl_appfs_simulate_user_fs_enter(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { @@ -1657,11 +1781,13 @@ interp = _interp; APPFS_DEBUG("Terminating interpreter due to thread termination"); - Tcl_DeleteInterp(interp); + appfs_call_libtcl( + Tcl_DeleteInterp(interp); + ) return; } /* @@ -1793,11 +1919,13 @@ fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n"); fprintf(stderr, "%s\n", test_interp_error); return(1); } + Tcl_DeleteInterp(test_interp); + Tcl_FinalizeNotifier(NULL); /* * Register a signal handler for hot-restart requests */