Diff

Differences From Artifact [b7668e46f2]:

To Artifact [1768754e26]:


    51     51   /*
    52     52    * Global variables for AppFS caching
    53     53    */
    54     54   pthread_mutex_t appfs_path_info_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
    55     55   int appfs_path_info_cache_size = 8209;
    56     56   struct appfs_pathinfo *appfs_path_info_cache = NULL;
    57     57   
           58  +#ifndef TCL_THREADS
           59  +/*
           60  + * Handle unthreaded Tcl
           61  + */
           62  +pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER;
           63  +#define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock);
           64  +#define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock);
           65  +#else
           66  +#define appfs_call_libtcl_enter /**/
           67  +#define appfs_call_libtcl_exit /**/
           68  +#endif
           69  +#define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit
           70  +
    58     71   /*
    59     72    * Global variables for AppFS Tcl Interpreter restarting
    60     73    */
    61     74   int interp_reset_key = 0;
    62     75   
    63     76   /*
    64     77    * AppFS Path Type:  Describes the type of path a given file is
................................................................................
   105    118   
   106    119   /*
   107    120    * Create a new Tcl interpreter and completely initialize it
   108    121    */
   109    122   static Tcl_Interp *appfs_create_TclInterp(char **error_string) {
   110    123   	Tcl_Interp *interp;
   111    124   	int tcl_ret;
          125  +	const char *tcl_setvar_ret;
   112    126   
   113    127   	APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self());
   114    128   
   115         -	interp = Tcl_CreateInterp();
          129  +	appfs_call_libtcl(
          130  +		interp = Tcl_CreateInterp();
          131  +	)
   116    132   	if (interp == NULL) {
   117    133   		fprintf(stderr, "Unable to create Tcl Interpreter.  Aborting.\n");
   118    134   
   119    135   		if (error_string) {
   120    136   			*error_string = strdup("Unable to create Tcl interpreter.");
   121    137   		}
   122    138   
   123    139   		return(NULL);
   124    140   	}
   125    141   
   126         -	Tcl_Preserve(interp);
          142  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   127    143   
   128         -	tcl_ret = Tcl_Init(interp);
          144  +	appfs_call_libtcl(
          145  +		tcl_ret = Tcl_Init(interp);
          146  +	)
   129    147   	if (tcl_ret != TCL_OK) {
   130    148   		fprintf(stderr, "Unable to initialize Tcl.  Aborting.\n");
   131         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          149  +		appfs_call_libtcl(
          150  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          151  +		)
          152  +
          153  +		if (error_string) {
          154  +			appfs_call_libtcl(
          155  +				*error_string = strdup(Tcl_GetStringResult(interp));
          156  +			)
          157  +		}
          158  +
          159  +		appfs_call_libtcl(Tcl_Release(interp);)
          160  +
          161  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          162  +
          163  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
          164  +
          165  +		return(NULL);
          166  +	}
          167  +
          168  +	appfs_call_libtcl(
          169  +		tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
          170  +	)
          171  +	if (tcl_ret != TCL_OK) {
          172  +		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
          173  +		appfs_call_libtcl(
          174  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          175  +		)
   132    176   
   133    177   		if (error_string) {
   134         -			*error_string = strdup(Tcl_GetStringResult(interp));
          178  +			appfs_call_libtcl(
          179  +				*error_string = strdup(Tcl_GetStringResult(interp));
          180  +			)
   135    181   		}
   136    182   
   137         -		Tcl_Release(interp);
          183  +		appfs_call_libtcl(Tcl_Release(interp);)
   138    184   
   139    185   		APPFS_DEBUG("Terminating Tcl interpreter.");
   140    186   
   141         -		Tcl_DeleteInterp(interp);
          187  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   142    188   
   143    189   		return(NULL);
   144    190   	}
   145    191   
   146         -	tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
          192  +	appfs_call_libtcl(
          193  +		tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
          194  +	)
   147    195   	if (tcl_ret != TCL_OK) {
   148         -		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
   149         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          196  +		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
          197  +		appfs_call_libtcl(
          198  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          199  +		)
   150    200   
   151    201   		if (error_string) {
   152         -			*error_string = strdup(Tcl_GetStringResult(interp));
          202  +			appfs_call_libtcl(
          203  +				*error_string = strdup(Tcl_GetStringResult(interp));
          204  +			)
   153    205   		}
   154    206   
   155         -		Tcl_Release(interp);
          207  +		appfs_call_libtcl(Tcl_Release(interp);)
   156    208   
   157    209   		APPFS_DEBUG("Terminating Tcl interpreter.");
   158    210   
   159         -		Tcl_DeleteInterp(interp);
   160         -
   161         -		return(NULL);
   162         -	}
   163         -
   164         -	tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
   165         -	if (tcl_ret != TCL_OK) {
   166         -		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
   167         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   168         -
   169         -		if (error_string) {
   170         -			*error_string = strdup(Tcl_GetStringResult(interp));
   171         -		}
   172         -
   173         -		Tcl_Release(interp);
   174         -
   175         -		APPFS_DEBUG("Terminating Tcl interpreter.");
   176         -
   177         -		Tcl_DeleteInterp(interp);
          211  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   178    212   
   179    213   		return(NULL);
   180    214   	}
   181    215   
   182    216   	/*
   183    217   	 * Load "pki.tcl" in the same way as appfsd.tcl (see below)
   184    218   	 */
   185         -	tcl_ret = Tcl_Eval(interp, ""
          219  +	appfs_call_libtcl_enter
          220  +		tcl_ret = Tcl_Eval(interp, ""
   186    221   #include "pki.tcl.h"
   187         -	"");
          222  +		"");
          223  +	appfs_call_libtcl_exit
   188    224   	if (tcl_ret != TCL_OK) {
   189    225   		fprintf(stderr, "Unable to initialize Tcl PKI.  Aborting.\n");
   190         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          226  +		appfs_call_libtcl(
          227  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          228  +		)
   191    229   
   192    230   		if (error_string) {
   193         -			*error_string = strdup(Tcl_GetStringResult(interp));
          231  +			appfs_call_libtcl(
          232  +				*error_string = strdup(Tcl_GetStringResult(interp));
          233  +			)
   194    234   		}
   195    235   
   196         -		Tcl_Release(interp);
          236  +		appfs_call_libtcl(Tcl_Release(interp);)
   197    237   
   198    238   		APPFS_DEBUG("Terminating Tcl interpreter.");
   199    239   
   200         -		Tcl_DeleteInterp(interp);
          240  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   201    241   
   202    242   		return(NULL);
   203    243   	}
   204    244   
   205    245   	/*
   206    246   	 * Load the "appfsd.tcl" script, which is "compiled" into a C header
   207    247   	 * so that it does not need to exist on the filesystem and can be
   208    248   	 * directly evaluated.
   209    249   	 */
   210         -	tcl_ret = Tcl_Eval(interp, ""
          250  +	appfs_call_libtcl_enter
          251  +		tcl_ret = Tcl_Eval(interp, ""
   211    252   #include "appfsd.tcl.h"
   212         -	"");
          253  +		"");
          254  +	appfs_call_libtcl_exit
   213    255   	if (tcl_ret != TCL_OK) {
   214    256   		fprintf(stderr, "Unable to initialize Tcl AppFS script.  Aborting.\n");
   215         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          257  +		appfs_call_libtcl(
          258  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          259  +		)
   216    260   
   217    261   		if (error_string) {
   218         -			*error_string = strdup(Tcl_GetStringResult(interp));
          262  +			appfs_call_libtcl(
          263  +				*error_string = strdup(Tcl_GetStringResult(interp));
          264  +			)
   219    265   		}
   220    266   
   221         -		Tcl_Release(interp);
          267  +		appfs_call_libtcl(Tcl_Release(interp);)
   222    268   
   223    269   		APPFS_DEBUG("Terminating Tcl interpreter.");
   224    270   
   225         -		Tcl_DeleteInterp(interp);
          271  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   226    272   
   227    273   		return(NULL);
   228    274   	}
   229    275   
   230    276   	/*
   231    277   	 * Set global variables from C to Tcl
   232    278   	 */
   233         -	if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) {
          279  +	appfs_call_libtcl(
          280  +		tcl_setvar_ret = Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY);
          281  +	)
          282  +	if (tcl_setvar_ret == NULL) {
   234    283   		fprintf(stderr, "Unable to set cache directory.  This should never fail.\n");
   235    284   
   236    285   		if (error_string) {
   237         -			*error_string = strdup(Tcl_GetStringResult(interp));
          286  +			appfs_call_libtcl(
          287  +				*error_string = strdup(Tcl_GetStringResult(interp));
          288  +			)
   238    289   		}
   239    290   
   240         -		Tcl_Release(interp);
          291  +		appfs_call_libtcl(Tcl_Release(interp);)
   241    292   
   242    293   		APPFS_DEBUG("Terminating Tcl interpreter.");
   243    294   
   244         -		Tcl_DeleteInterp(interp);
          295  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   245    296   
   246    297   		return(NULL);
   247    298   	}
   248    299   
   249    300   	/*
   250    301   	 * Initialize the "appfsd.tcl" environment, which must be done after
   251    302   	 * global variables are set.
   252    303   	 */
   253         -	tcl_ret = Tcl_Eval(interp, "::appfs::init");
          304  +	appfs_call_libtcl(
          305  +		tcl_ret = Tcl_Eval(interp, "::appfs::init");
          306  +	)
   254    307   	if (tcl_ret != TCL_OK) {
   255    308   		fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init).  Aborting.\n");
   256         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          309  +		appfs_call_libtcl(
          310  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          311  +		)
   257    312   
   258    313   		if (error_string) {
   259         -			*error_string = strdup(Tcl_GetStringResult(interp));
          314  +			appfs_call_libtcl(
          315  +				*error_string = strdup(Tcl_GetStringResult(interp));
          316  +			)
   260    317   		}
   261    318   
   262         -		Tcl_Release(interp);
          319  +		appfs_call_libtcl(Tcl_Release(interp);)
   263    320   
   264    321   		APPFS_DEBUG("Terminating Tcl interpreter.");
   265    322   
   266         -		Tcl_DeleteInterp(interp);
          323  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   267    324   
   268    325   		return(NULL);
   269    326   	}
   270    327   
   271    328   	/*
   272    329   	 * Hide some Tcl commands that we do not care to use and which may
   273    330   	 * slow down run-time operations.
   274    331   	 */
   275         -	Tcl_HideCommand(interp, "auto_load_index", "auto_load_index");
   276         -	Tcl_HideCommand(interp, "unknown", "unknown");
   277         -	Tcl_HideCommand(interp, "exit", "exit");
          332  +	appfs_call_libtcl(
          333  +		Tcl_HideCommand(interp, "auto_load_index", "auto_load_index");
          334  +		Tcl_HideCommand(interp, "unknown", "unknown");
          335  +		Tcl_HideCommand(interp, "exit", "exit");
          336  +	)
   278    337   
   279    338   	/*
   280    339   	 * Release the hold we have on the interpreter so that it may be
   281    340   	 * deleted if needed
   282    341   	 */
   283         -	Tcl_Release(interp);
          342  +	appfs_call_libtcl(Tcl_Release(interp);)
   284    343   
   285    344   	/*
   286    345   	 * Return the completely initialized interpreter
   287    346   	 */
   288    347   	return(interp);
   289    348   }
   290    349   
................................................................................
   299    358   
   300    359   	global_interp_reset_key = __sync_fetch_and_add(&interp_reset_key, 0);
   301    360   
   302    361   	interp = pthread_getspecific(interpKey);
   303    362   	if (interp != NULL && thread_interp_reset_key != global_interp_reset_key) {
   304    363   		APPFS_DEBUG("Terminating old interpreter and restarting due to reset request.");
   305    364   
   306         -		Tcl_DeleteInterp(interp);
          365  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   307    366   
   308    367   		interp = NULL;
   309    368   
   310    369   		pthread_ret = pthread_setspecific(interpKey, interp);
   311    370   	}
   312    371   
   313    372   	if (global_interp_reset_key == -1) {
................................................................................
   325    384   			return(NULL);
   326    385   		}
   327    386   
   328    387   		pthread_ret = pthread_setspecific(interpKey, interp);
   329    388   		if (pthread_ret != 0) {
   330    389   			APPFS_DEBUG("pthread_setspecific() failed.  Terminating Tcl interpreter.");
   331    390   
   332         -			Tcl_DeleteInterp(interp);
          391  +			appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   333    392   
   334    393   			return(NULL);
   335    394   		}
   336    395   	}
   337    396   
   338    397   	return(interp);
   339    398   }
................................................................................
   351    410   
   352    411   	if (interp == NULL) {
   353    412   		return(TCL_ERROR);
   354    413   	}
   355    414   
   356    415   	objv = (void *) ckalloc(sizeof(*objv) * objc);
   357    416   
   358         -	objv[0] = Tcl_NewStringObj(cmd, -1);
   359         -
   360         -	Tcl_IncrRefCount(objv[0]);
   361         -
   362         -	va_start(argp, cmd);
   363         -	for (i = 1; i < objc; i++) {
   364         -		arg = va_arg(argp, const char *);
   365         -
   366         -		objv[i] = Tcl_NewStringObj(arg, -1);
   367         -
   368         -		Tcl_IncrRefCount(objv[i]);
   369         -	}
   370         -	va_end(argp);
   371         -
   372         -	retval = Tcl_EvalObjv(interp, objc, objv, 0);
   373         -
   374         -	for (i = 0; i < objc; i++) {
   375         -		Tcl_DecrRefCount(objv[i]);
   376         -	}
          417  +	appfs_call_libtcl(
          418  +		objv[0] = Tcl_NewStringObj(cmd, -1);
          419  +
          420  +		Tcl_IncrRefCount(objv[0]);
          421  +
          422  +		va_start(argp, cmd);
          423  +		for (i = 1; i < objc; i++) {
          424  +			arg = va_arg(argp, const char *);
          425  +
          426  +			objv[i] = Tcl_NewStringObj(arg, -1);
          427  +
          428  +			Tcl_IncrRefCount(objv[i]);
          429  +		}
          430  +		va_end(argp);
          431  +	)
          432  +
          433  +	appfs_call_libtcl(
          434  +		retval = Tcl_EvalObjv(interp, objc, objv, 0);
          435  +	)
          436  +
          437  +	appfs_call_libtcl(
          438  +		for (i = 0; i < objc; i++) {
          439  +			Tcl_DecrRefCount(objv[i]);
          440  +		}
          441  +	)
   377    442   
   378    443   	ckfree((void *) objv);
   379    444   
   380    445   	if (retval != TCL_OK) {
   381         -		APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0));
          446  +		appfs_call_libtcl(
          447  +			APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0));
          448  +		)
   382    449   	}
   383    450   
   384    451   	return(retval);
   385    452   }
   386    453   
   387    454   /*
   388    455    * Request all Tcl interpreters restart
................................................................................
   696    763   	Tcl_Obj *attrs_dict, *attr_value;
   697    764   	const char *attr_value_str;
   698    765   	Tcl_WideInt attr_value_wide;
   699    766   	int attr_value_int;
   700    767   	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;
   701    768   	int cache_ret;
   702    769   	int tcl_ret;
          770  +	int retval;
   703    771   	uid_t fsuid;
          772  +
          773  +	retval = 0;
   704    774   
   705    775   	fsuid = appfs_get_fsuid();
   706    776   
   707    777   	cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo);
   708    778   	if (cache_ret == 0) {
   709    779   		if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) {
   710    780   			return(-ENOENT);
................................................................................
   718    788   	}
   719    789   
   720    790   	interp = appfs_TclInterp();
   721    791   	if (interp == NULL) {
   722    792   		return(-EIO);
   723    793   	}
   724    794   
   725         -	Tcl_Preserve(interp);
          795  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   726    796   
   727    797   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);
   728    798   	if (tcl_ret != TCL_OK) {
   729    799   		APPFS_DEBUG("::appfs::getattr(%s) failed.", path);
   730         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          800  +		appfs_call_libtcl(
          801  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          802  +		)
   731    803   
   732    804   		pathinfo->type = APPFS_PATHTYPE_DOES_NOT_EXIST;
   733    805   
   734    806   		appfs_get_path_info_cache_add(path, fsuid, pathinfo);
   735    807   
   736         -		Tcl_Release(interp);
          808  +		appfs_call_libtcl(Tcl_Release(interp);)
   737    809   
   738    810   		return(-ENOENT);
   739    811   	}
   740    812   
   741    813   	if (attr_key_type == NULL) {
   742         -		attr_key_type       = Tcl_NewStringObj("type", -1);
   743         -		attr_key_perms      = Tcl_NewStringObj("perms", -1);
   744         -		attr_key_size       = Tcl_NewStringObj("size", -1);
   745         -		attr_key_time       = Tcl_NewStringObj("time", -1);
   746         -		attr_key_source     = Tcl_NewStringObj("source", -1);
   747         -		attr_key_childcount = Tcl_NewStringObj("childcount", -1);
   748         -		attr_key_packaged   = Tcl_NewStringObj("packaged", -1);
          814  +		appfs_call_libtcl(
          815  +			attr_key_type       = Tcl_NewStringObj("type", -1);
          816  +			attr_key_perms      = Tcl_NewStringObj("perms", -1);
          817  +			attr_key_size       = Tcl_NewStringObj("size", -1);
          818  +			attr_key_time       = Tcl_NewStringObj("time", -1);
          819  +			attr_key_source     = Tcl_NewStringObj("source", -1);
          820  +			attr_key_childcount = Tcl_NewStringObj("childcount", -1);
          821  +			attr_key_packaged   = Tcl_NewStringObj("packaged", -1);
          822  +
          823  +			Tcl_IncrRefCount(attr_key_type);
          824  +			Tcl_IncrRefCount(attr_key_perms);
          825  +			Tcl_IncrRefCount(attr_key_size);
          826  +			Tcl_IncrRefCount(attr_key_time);
          827  +			Tcl_IncrRefCount(attr_key_source);
          828  +			Tcl_IncrRefCount(attr_key_childcount);
          829  +			Tcl_IncrRefCount(attr_key_packaged);
          830  +		)
   749    831   	}
   750    832   
   751         -	attrs_dict = Tcl_GetObjResult(interp);
   752         -	tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value);
          833  +	appfs_call_libtcl(
          834  +		attrs_dict = Tcl_GetObjResult(interp);
          835  +		tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value);
          836  +	)
   753    837   	if (tcl_ret != TCL_OK) {
   754    838   		APPFS_DEBUG("[dict get \"type\"] failed");
   755         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          839  +		appfs_call_libtcl(
          840  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          841  +		)
   756    842   
   757         -		Tcl_Release(interp);
          843  +		appfs_call_libtcl(Tcl_Release(interp);)
   758    844   
   759    845   		return(-EIO);
   760    846   	}
   761    847   
   762    848   	if (attr_value == NULL) {
   763         -		Tcl_Release(interp);
          849  +		appfs_call_libtcl(Tcl_Release(interp);)
   764    850   
   765    851   		return(-EIO);
   766    852   	}
   767    853   
   768    854   	pathinfo->packaged = 0;
   769    855   	pathinfo->inode = appfs_get_path_inode(path);
   770    856   
   771         -	attr_value_str = Tcl_GetString(attr_value);
          857  +	appfs_call_libtcl(
          858  +		attr_value_str = Tcl_GetString(attr_value);
   772    859   
   773         -	switch (attr_value_str[0]) {
   774         -		case 'd': /* directory */
   775         -			pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   776         -			pathinfo->typeinfo.dir.childcount = 0;
          860  +		switch (attr_value_str[0]) {
          861  +			case 'd': /* directory */
          862  +				pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
          863  +				pathinfo->typeinfo.dir.childcount = 0;
   777    864   
   778         -			Tcl_DictObjGet(interp, attrs_dict, attr_key_childcount, &attr_value);
   779         -			if (attr_value != NULL) {
   780         -				tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide);
   781         -				if (tcl_ret == TCL_OK) {
   782         -					pathinfo->typeinfo.dir.childcount = attr_value_wide;
          865  +				Tcl_DictObjGet(interp, attrs_dict, attr_key_childcount, &attr_value);
          866  +				if (attr_value != NULL) {
          867  +					tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide);
          868  +					if (tcl_ret == TCL_OK) {
          869  +						pathinfo->typeinfo.dir.childcount = attr_value_wide;
          870  +					}
          871  +				}
          872  +
          873  +				break;
          874  +			case 'f': /* file */
          875  +				pathinfo->type = APPFS_PATHTYPE_FILE;
          876  +				pathinfo->typeinfo.file.size = 0;
          877  +				pathinfo->typeinfo.file.executable = 0;
          878  +
          879  +				Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value);
          880  +				if (attr_value != NULL) {
          881  +					tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide);
          882  +					if (tcl_ret == TCL_OK) {
          883  +						pathinfo->typeinfo.file.size = attr_value_wide;
          884  +					}
   783    885   				}
   784         -			}
   785    886   
   786         -			break;
   787         -		case 'f': /* file */
   788         -			pathinfo->type = APPFS_PATHTYPE_FILE;
   789         -			pathinfo->typeinfo.file.size = 0;
   790         -			pathinfo->typeinfo.file.executable = 0;
   791         -
   792         -			Tcl_DictObjGet(interp, attrs_dict, attr_key_size, &attr_value);
   793         -			if (attr_value != NULL) {
   794         -				tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide);
   795         -				if (tcl_ret == TCL_OK) {
   796         -					pathinfo->typeinfo.file.size = attr_value_wide;
          887  +				Tcl_DictObjGet(interp, attrs_dict, attr_key_perms, &attr_value);
          888  +				if (attr_value != NULL) {
          889  +					attr_value_str = Tcl_GetString(attr_value);
          890  +					if (attr_value_str[0] == 'x') {
          891  +						pathinfo->typeinfo.file.executable = 1;
          892  +					}
   797    893   				}
   798         -			}
          894  +				break;
          895  +			case 's': /* symlink */
          896  +				pathinfo->type = APPFS_PATHTYPE_SYMLINK;
          897  +				pathinfo->typeinfo.symlink.size = 0;
          898  +				pathinfo->typeinfo.symlink.source[0] = '\0';
   799    899   
   800         -			Tcl_DictObjGet(interp, attrs_dict, attr_key_perms, &attr_value);
   801         -			if (attr_value != NULL) {
   802         -				attr_value_str = Tcl_GetString(attr_value);
   803         -				if (attr_value_str[0] == 'x') {
   804         -					pathinfo->typeinfo.file.executable = 1;
   805         -				}
   806         -			}
   807         -			break;
   808         -		case 's': /* symlink */
   809         -			pathinfo->type = APPFS_PATHTYPE_SYMLINK;
   810         -			pathinfo->typeinfo.symlink.size = 0;
   811         -			pathinfo->typeinfo.symlink.source[0] = '\0';
          900  +				Tcl_DictObjGet(interp, attrs_dict, attr_key_source, &attr_value);
          901  +				if (attr_value != NULL) {
          902  +					attr_value_str = Tcl_GetStringFromObj(attr_value, &attr_value_int); 
   812    903   
   813         -			Tcl_DictObjGet(interp, attrs_dict, attr_key_source, &attr_value);
   814         -			if (attr_value != NULL) {
   815         -				attr_value_str = Tcl_GetStringFromObj(attr_value, &attr_value_int); 
          904  +					if ((attr_value_int + 1) <= sizeof(pathinfo->typeinfo.symlink.source)) {
          905  +						pathinfo->typeinfo.symlink.size = attr_value_int;
          906  +						pathinfo->typeinfo.symlink.source[attr_value_int] = '\0';
   816    907   
   817         -				if ((attr_value_int + 1) <= sizeof(pathinfo->typeinfo.symlink.source)) {
   818         -					pathinfo->typeinfo.symlink.size = attr_value_int;
   819         -					pathinfo->typeinfo.symlink.source[attr_value_int] = '\0';
   820         -
   821         -					memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int);
          908  +						memcpy(pathinfo->typeinfo.symlink.source, attr_value_str, attr_value_int);
          909  +					}
   822    910   				}
          911  +				break;
          912  +			case 'F': /* pipe/fifo */
          913  +				pathinfo->type = APPFS_PATHTYPE_FIFO;
          914  +				break;
          915  +			case 'S': /* UNIX domain socket */
          916  +				pathinfo->type = APPFS_PATHTYPE_SOCKET;
          917  +				break;
          918  +			default:
          919  +				retval = -EIO;
          920  +		}
          921  +
          922  +		Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value);
          923  +		if (attr_value != NULL) {
          924  +			pathinfo->packaged = 1;
          925  +		}
          926  +
          927  +		Tcl_DictObjGet(interp, attrs_dict, attr_key_time, &attr_value);
          928  +		if (attr_value != NULL) {
          929  +			tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide);
          930  +			if (tcl_ret == TCL_OK) {
          931  +				pathinfo->time = attr_value_wide;
   823    932   			}
   824         -			break;
   825         -		case 'F': /* pipe/fifo */
   826         -			pathinfo->type = APPFS_PATHTYPE_FIFO;
   827         -			break;
   828         -		case 'S': /* UNIX domain socket */
   829         -			pathinfo->type = APPFS_PATHTYPE_SOCKET;
   830         -			break;
   831         -		default:
   832         -			Tcl_Release(interp);
   833         -
   834         -			return(-EIO);
   835         -	}
   836         -
   837         -	Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value);
   838         -	if (attr_value != NULL) {
   839         -		pathinfo->packaged = 1;
   840         -	}
   841         -
   842         -	Tcl_DictObjGet(interp, attrs_dict, attr_key_time, &attr_value);
   843         -	if (attr_value != NULL) {
   844         -		tcl_ret = Tcl_GetWideIntFromObj(NULL, attr_value, &attr_value_wide);
   845         -		if (tcl_ret == TCL_OK) {
   846         -			pathinfo->time = attr_value_wide;
          933  +		} else {
          934  +			pathinfo->time = 0;
   847    935   		}
   848         -	} else {
   849         -		pathinfo->time = 0;
          936  +
          937  +		Tcl_Release(interp);
          938  +	)
          939  +
          940  +	if (retval == 0) {
          941  +		appfs_get_path_info_cache_add(path, fsuid, pathinfo);
   850    942   	}
   851    943   
   852         -	Tcl_Release(interp);
   853         -
   854         -	appfs_get_path_info_cache_add(path, fsuid, pathinfo);
   855         -
   856         -	return(0);
          944  +	return(retval);
   857    945   }
   858    946   
   859    947   static char *appfs_prepare_to_create(const char *path) {
   860    948   	Tcl_Interp *interp;
   861    949   	const char *real_path;
   862    950   	int tcl_ret;
   863    951   
................................................................................
   864    952   	appfs_get_path_info_cache_flush(appfs_get_fsuid(), -1);
   865    953   
   866    954   	interp = appfs_TclInterp();
   867    955   	if (interp == NULL) {
   868    956   		return(NULL);
   869    957   	}
   870    958   
   871         -	Tcl_Preserve(interp);
          959  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   872    960   
   873         -	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path);
          961  +	appfs_call_libtcl(
          962  +		tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path);
          963  +	)
   874    964   	if (tcl_ret != TCL_OK) {
   875    965   		APPFS_DEBUG("::appfs::prepare_to_create(%s) failed.", path);
   876         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          966  +		appfs_call_libtcl(
          967  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          968  +		)
   877    969   
   878         -		Tcl_Release(interp);
          970  +		appfs_call_libtcl(Tcl_Release(interp);)
   879    971   
   880    972   		return(NULL);
   881    973   	}
   882    974   
   883         -	real_path = Tcl_GetStringResult(interp);
          975  +	appfs_call_libtcl(
          976  +		real_path = Tcl_GetStringResult(interp);
          977  +	)
   884    978   
   885         -	Tcl_Release(interp);
          979  +	appfs_call_libtcl(Tcl_Release(interp);)
   886    980   
   887    981   	if (real_path == NULL) {
   888    982   		return(NULL);
   889    983   	}
   890    984   
   891    985   	return(strdup(real_path));
   892    986   }
................................................................................
   897    991   	int tcl_ret;
   898    992   
   899    993   	interp = appfs_TclInterp();
   900    994   	if (interp == NULL) {
   901    995   		return(NULL);
   902    996   	}
   903    997   
   904         -	Tcl_Preserve(interp);
          998  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   905    999   
   906         -	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path);
         1000  +	appfs_call_libtcl(
         1001  +		tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path);
         1002  +	)
   907   1003   	if (tcl_ret != TCL_OK) {
   908   1004   		APPFS_DEBUG("::appfs::localpath(%s) failed.", path);
   909         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1005  +		appfs_call_libtcl(
         1006  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1007  +		)
   910   1008   
   911   1009   		return(NULL);
   912   1010   	}
   913   1011   
   914         -	real_path = Tcl_GetStringResult(interp);
         1012  +	appfs_call_libtcl(
         1013  +		real_path = Tcl_GetStringResult(interp);
         1014  +	)
   915   1015   
   916         -	Tcl_Release(interp);
         1016  +	appfs_call_libtcl(Tcl_Release(interp);)
   917   1017   
   918   1018   	if (real_path == NULL) {
   919   1019   		return(NULL);
   920   1020   	}
   921   1021   
   922   1022   	return(strdup(real_path));
   923   1023   }
................................................................................
  1064   1164   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1065   1165   
  1066   1166   	interp = appfs_TclInterp();
  1067   1167   	if (interp == NULL) {
  1068   1168   		return(0);
  1069   1169   	}
  1070   1170   
  1071         -	Tcl_Preserve(interp);
         1171  +	appfs_call_libtcl(Tcl_Preserve(interp);)
  1072   1172   
  1073   1173   	filler(buf, ".", NULL, 0);
  1074   1174   	filler(buf, "..", NULL, 0);
  1075   1175   
  1076   1176   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path);
  1077   1177   	if (tcl_ret != TCL_OK) {
  1078   1178   		APPFS_DEBUG("::appfs::getchildren(%s) failed.", path);
  1079         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1179  +		appfs_call_libtcl(
         1180  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1181  +		)
  1080   1182   
  1081         -		Tcl_Release(interp);
         1183  +		appfs_call_libtcl(Tcl_Release(interp);)
  1082   1184   
  1083   1185   		return(0);
  1084   1186   	}
  1085   1187   
  1086         -	tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children);
         1188  +	appfs_call_libtcl(
         1189  +		tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children);
         1190  +	)
  1087   1191   	if (tcl_ret != TCL_OK) {
  1088   1192   		APPFS_DEBUG("Parsing list of children on path %s failed.", path);
  1089         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1193  +		appfs_call_libtcl(
         1194  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1195  +		)
  1090   1196   
  1091         -		Tcl_Release(interp);
         1197  +		appfs_call_libtcl(Tcl_Release(interp);)
  1092   1198   
  1093   1199   		return(0);
  1094   1200   	}
  1095   1201   
  1096   1202   	for (idx = 0; idx < children_count; idx++) {
  1097         -		filler(buf, Tcl_GetString(children[idx]), NULL, 0);
         1203  +		appfs_call_libtcl(
         1204  +			filler(buf, Tcl_GetString(children[idx]), NULL, 0);
         1205  +		)
  1098   1206   	}
  1099   1207   
  1100         -	Tcl_Release(interp);
         1208  +	appfs_call_libtcl(Tcl_Release(interp);)
  1101   1209   
  1102   1210   	return(0);
  1103   1211   }
  1104   1212   
  1105   1213   static int appfs_fuse_open(const char *path, struct fuse_file_info *fi) {
  1106   1214   	Tcl_Interp *interp;
  1107   1215   	struct appfs_pathinfo pathinfo;
................................................................................
  1144   1252   	}
  1145   1253   
  1146   1254   	interp = appfs_TclInterp();
  1147   1255   	if (interp == NULL) {
  1148   1256   		return(-EIO);
  1149   1257   	}
  1150   1258   
  1151         -	Tcl_Preserve(interp);
         1259  +	appfs_call_libtcl(Tcl_Preserve(interp);)
  1152   1260   
  1153   1261   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode);
  1154   1262   	if (tcl_ret != TCL_OK) {
  1155   1263   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode);
  1156         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1264  +		appfs_call_libtcl(
         1265  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1266  +		)
  1157   1267   
  1158         -		Tcl_Release(interp);
         1268  +		appfs_call_libtcl(Tcl_Release(interp);)
  1159   1269   
  1160   1270   		return(-EIO);
  1161   1271   	}
  1162   1272   
  1163         -	real_path = Tcl_GetStringResult(interp);
         1273  +	appfs_call_libtcl(
         1274  +		real_path = Tcl_GetStringResult(interp);
         1275  +	)
  1164   1276   
  1165         -	Tcl_Release(interp);
         1277  +	appfs_call_libtcl(Tcl_Release(interp);)
  1166   1278   
  1167   1279   	if (real_path == NULL) {
  1168   1280   		return(-EIO);
  1169   1281   	}
  1170   1282   
  1171   1283   	APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode);
  1172   1284   
................................................................................
  1338   1450   	if (interp == NULL) {
  1339   1451   		return(-EIO);
  1340   1452   	}
  1341   1453   
  1342   1454   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::unlinkpath", path);
  1343   1455   	if (tcl_ret != TCL_OK) {
  1344   1456   		APPFS_DEBUG("::appfs::unlinkpath(%s) failed.", path);
  1345         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1457  +		appfs_call_libtcl(
         1458  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1459  +		)
  1346   1460   
  1347         -		Tcl_Release(interp);
         1461  +		appfs_call_libtcl(Tcl_Release(interp);)
  1348   1462   
  1349   1463   		return(-EIO);
  1350   1464   	}
  1351   1465   
  1352         -	Tcl_Release(interp);
         1466  +	appfs_call_libtcl(Tcl_Release(interp);)
  1353   1467   
  1354   1468   	return(0);
  1355   1469   }
  1356   1470   
  1357   1471   static int appfs_fuse_mkdir(const char *path, mode_t mode) {
  1358   1472   	char *real_path;
  1359   1473   	int mkdir_ret;
................................................................................
  1392   1506   	appfs_get_path_info_cache_rm(path, appfs_get_fsuid());
  1393   1507   
  1394   1508   	interp = appfs_TclInterp();
  1395   1509   	if (interp == NULL) {
  1396   1510   		return(-EIO);
  1397   1511   	}
  1398   1512   
  1399         -	Tcl_Preserve(interp);
         1513  +	appfs_call_libtcl(Tcl_Preserve(interp);)
  1400   1514   
  1401   1515   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, "write");
  1402   1516   	if (tcl_ret != TCL_OK) {
  1403   1517   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, "write");
  1404         -		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1518  +		appfs_call_libtcl(
         1519  +			APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1520  +		)
  1405   1521   
  1406         -		Tcl_Release(interp);
         1522  +		appfs_call_libtcl(Tcl_Release(interp);)
  1407   1523   
  1408   1524   		return(-EIO);
  1409   1525   	}
  1410   1526   
  1411         -	real_path = Tcl_GetStringResult(interp);
         1527  +	appfs_call_libtcl(
         1528  +		real_path = Tcl_GetStringResult(interp);
         1529  +	)
  1412   1530   
  1413         -	Tcl_Release(interp);
         1531  +	appfs_call_libtcl(Tcl_Release(interp);)
  1414   1532   
  1415   1533   	if (real_path == NULL) {
  1416   1534   		return(-EIO);
  1417   1535   	}
  1418   1536   
  1419   1537   	appfs_simulate_user_fs_enter();
  1420   1538   
................................................................................
  1508   1626                   return(TCL_ERROR);
  1509   1627           }
  1510   1628   
  1511   1629   	fsuid = appfs_get_fsuid();
  1512   1630   
  1513   1631   	if (fsuid == last_fsuid && last_homedir_obj != NULL) {
  1514   1632   		homedir_obj = last_homedir_obj;
         1633  +
         1634  +		Tcl_IncrRefCount(homedir_obj);
  1515   1635   	} else {
  1516   1636   		homedir = appfs_get_homedir(appfs_get_fsuid());
  1517   1637   
  1518   1638   		if (homedir == NULL) {
  1519   1639   			return(TCL_ERROR);
  1520   1640   		}
  1521   1641   
  1522   1642   		homedir_obj = Tcl_NewStringObj(homedir, -1);
  1523   1643   
  1524   1644   		free(homedir);
         1645  +
         1646  +		Tcl_IncrRefCount(homedir_obj);
  1525   1647   
  1526   1648   		if (last_homedir_obj != NULL) {
  1527   1649   			Tcl_DecrRefCount(last_homedir_obj);
  1528   1650   		}
  1529   1651   
  1530   1652   		last_homedir_obj = homedir_obj;
  1531   1653   		last_fsuid = fsuid;
  1532   1654   
  1533         -		Tcl_IncrRefCount(last_homedir_obj);
         1655  +		Tcl_IncrRefCount(homedir_obj);
  1534   1656   	}
  1535   1657   
  1536   1658          	Tcl_SetObjResult(interp, homedir_obj);
         1659  +
         1660  +	Tcl_DecrRefCount(homedir_obj);
  1537   1661   
  1538   1662           return(TCL_OK);
  1539   1663   }
  1540   1664   
  1541   1665   static int tcl_appfs_simulate_user_fs_enter(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  1542   1666   	appfs_simulate_user_fs_enter();
  1543   1667   
................................................................................
  1655   1779   		return;
  1656   1780   	}
  1657   1781   
  1658   1782   	interp = _interp;
  1659   1783   
  1660   1784   	APPFS_DEBUG("Terminating interpreter due to thread termination");
  1661   1785   
  1662         -	Tcl_DeleteInterp(interp);
         1786  +	appfs_call_libtcl(
         1787  +		Tcl_DeleteInterp(interp);
         1788  +	)
  1663   1789   
  1664   1790   	return;
  1665   1791   }
  1666   1792   
  1667   1793   /*
  1668   1794    * FUSE operations structure
  1669   1795    */
................................................................................
  1791   1917   		}
  1792   1918   
  1793   1919   		fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n");
  1794   1920   		fprintf(stderr, "%s\n", test_interp_error);
  1795   1921   
  1796   1922   		return(1);
  1797   1923   	}
         1924  +
  1798   1925   	Tcl_DeleteInterp(test_interp);
         1926  +
  1799   1927   	Tcl_FinalizeNotifier(NULL);
  1800   1928   
  1801   1929   	/*
  1802   1930   	 * Register a signal handler for hot-restart requests
  1803   1931   	 */
  1804   1932   	signal_ret = signal(SIGHUP, appfs_signal_handler);
  1805   1933   	if (signal_ret == SIG_ERR) {