Diff

Differences From Artifact [e49bb6021f]:

To Artifact [6216c87bde]:


     1      1   #define FUSE_USE_VERSION 26
     2      2   
     3      3   #include <sys/fsuid.h>
     4      4   #include <sys/types.h>
     5      5   #include <pthread.h>
     6      6   #include <signal.h>
            7  +#include <limits.h>
     7      8   #include <string.h>
     8      9   #include <stdarg.h>
     9     10   #include <stdlib.h>
    10     11   #include <unistd.h>
    11     12   #include <errno.h>
    12     13   #include <fcntl.h>
    13     14   #include <stdio.h>
................................................................................
   117    118   
   118    119   		if (error_string) {
   119    120   			*error_string = strdup("Unable to create Tcl interpreter.");
   120    121   		}
   121    122   
   122    123   		return(NULL);
   123    124   	}
          125  +
          126  +	Tcl_Preserve(interp);
   124    127   
   125    128   	tcl_ret = Tcl_Init(interp);
   126    129   	if (tcl_ret != TCL_OK) {
   127    130   		fprintf(stderr, "Unable to initialize Tcl.  Aborting.\n");
   128    131   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   129    132   
   130    133   		if (error_string) {
   131    134   			*error_string = strdup(Tcl_GetStringResult(interp));
   132    135   		}
   133    136   
          137  +		Tcl_Release(interp);
          138  +
          139  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          140  +
   134    141   		Tcl_DeleteInterp(interp);
   135    142   
   136    143   		return(NULL);
   137    144   	}
   138    145   
   139    146   	tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
   140    147   	if (tcl_ret != TCL_OK) {
................................................................................
   141    148   		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
   142    149   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   143    150   
   144    151   		if (error_string) {
   145    152   			*error_string = strdup(Tcl_GetStringResult(interp));
   146    153   		}
   147    154   
          155  +		Tcl_Release(interp);
          156  +
          157  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          158  +
   148    159   		Tcl_DeleteInterp(interp);
   149    160   
   150    161   		return(NULL);
   151    162   	}
   152    163   
   153    164   	tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
   154    165   	if (tcl_ret != TCL_OK) {
................................................................................
   155    166   		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
   156    167   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   157    168   
   158    169   		if (error_string) {
   159    170   			*error_string = strdup(Tcl_GetStringResult(interp));
   160    171   		}
   161    172   
          173  +		Tcl_Release(interp);
          174  +
          175  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          176  +
   162    177   		Tcl_DeleteInterp(interp);
   163    178   
   164    179   		return(NULL);
   165    180   	}
   166    181   
   167    182   	/*
   168    183   	 * Load "pki.tcl" in the same way as appfsd.tcl (see below)
................................................................................
   174    189   		fprintf(stderr, "Unable to initialize Tcl PKI.  Aborting.\n");
   175    190   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   176    191   
   177    192   		if (error_string) {
   178    193   			*error_string = strdup(Tcl_GetStringResult(interp));
   179    194   		}
   180    195   
          196  +		Tcl_Release(interp);
          197  +
          198  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          199  +
   181    200   		Tcl_DeleteInterp(interp);
   182    201   
   183    202   		return(NULL);
   184    203   	}
   185    204   
   186    205   	/*
   187    206   	 * Load the "appfsd.tcl" script, which is "compiled" into a C header
................................................................................
   195    214   		fprintf(stderr, "Unable to initialize Tcl AppFS script.  Aborting.\n");
   196    215   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   197    216   
   198    217   		if (error_string) {
   199    218   			*error_string = strdup(Tcl_GetStringResult(interp));
   200    219   		}
   201    220   
          221  +		Tcl_Release(interp);
          222  +
          223  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          224  +
   202    225   		Tcl_DeleteInterp(interp);
   203    226   
   204    227   		return(NULL);
   205    228   	}
   206    229   
   207    230   	/*
   208    231   	 * Set global variables from C to Tcl
................................................................................
   210    233   	if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) {
   211    234   		fprintf(stderr, "Unable to set cache directory.  This should never fail.\n");
   212    235   
   213    236   		if (error_string) {
   214    237   			*error_string = strdup(Tcl_GetStringResult(interp));
   215    238   		}
   216    239   
          240  +		Tcl_Release(interp);
          241  +
          242  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          243  +
   217    244   		Tcl_DeleteInterp(interp);
   218    245   
   219    246   		return(NULL);
   220    247   	}
   221    248   
   222    249   	/*
   223    250   	 * Initialize the "appfsd.tcl" environment, which must be done after
................................................................................
   228    255   		fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init).  Aborting.\n");
   229    256   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   230    257   
   231    258   		if (error_string) {
   232    259   			*error_string = strdup(Tcl_GetStringResult(interp));
   233    260   		}
   234    261   
          262  +		Tcl_Release(interp);
          263  +
          264  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          265  +
   235    266   		Tcl_DeleteInterp(interp);
   236    267   
   237    268   		return(NULL);
   238    269   	}
   239    270   
   240    271   	/*
   241    272   	 * Hide some Tcl commands that we do not care to use and which may
   242    273   	 * slow down run-time operations.
   243    274   	 */
   244    275   	Tcl_HideCommand(interp, "auto_load_index", "auto_load_index");
   245    276   	Tcl_HideCommand(interp, "unknown", "unknown");
          277  +	Tcl_HideCommand(interp, "exit", "exit");
          278  +
          279  +	/*
          280  +	 * Release the hold we have on the interpreter so that it may be
          281  +	 * deleted if needed
          282  +	 */
          283  +	Tcl_Release(interp);
   246    284   
   247    285   	/*
   248    286   	 * Return the completely initialized interpreter
   249    287   	 */
   250    288   	return(interp);
   251    289   }
   252    290   
................................................................................
   265    303   	if (interp != NULL && thread_interp_reset_key != global_interp_reset_key) {
   266    304   		APPFS_DEBUG("Terminating old interpreter and restarting due to reset request.");
   267    305   
   268    306   		Tcl_DeleteInterp(interp);
   269    307   
   270    308   		interp = NULL;
   271    309   
   272         -		thread_interp_reset_key = global_interp_reset_key;
          310  +		pthread_ret = pthread_setspecific(interpKey, interp);
   273    311   	}
          312  +
          313  +	thread_interp_reset_key = global_interp_reset_key;
   274    314   
   275    315   	if (interp == NULL) {
   276    316   		interp = appfs_create_TclInterp(NULL);
   277    317   
   278    318   		if (interp == NULL) {
   279    319   			return(NULL);
   280    320   		}
   281    321   
   282    322   		pthread_ret = pthread_setspecific(interpKey, interp);
   283    323   		if (pthread_ret != 0) {
          324  +			APPFS_DEBUG("pthread_setspecific() failed.  Terminating Tcl interpreter.");
          325  +
   284    326   			Tcl_DeleteInterp(interp);
   285    327   
   286    328   			return(NULL);
   287    329   		}
   288    330   	}
   289    331   
   290    332   	return(interp);
................................................................................
   451    493   }
   452    494   
   453    495   /*
   454    496    * Generate an inode for a given path.  The inode should be computed in such
   455    497    * a way that it is unlikely to be duplicated and remains the same for a given
   456    498    * file
   457    499    */
          500  +#if UINT_MAX < 4294967295
          501  +#error Integer size is too small 
          502  +#endif
   458    503   static long long appfs_get_path_inode(const char *path) {
   459         -	long long retval;
          504  +	int retval;
   460    505   	const char *p;
   461    506   
   462    507   	retval = 10;
   463    508   
   464    509   	for (p = path; *p; p++) {
   465    510   		retval %= 4290960290ULL;
   466    511   		retval += *p;
   467         -		retval <<= 7;
          512  +		retval <<= 6;
   468    513   	}
   469    514   
   470    515   	retval += 10;
   471         -	retval %= 4294967296ULL;
          516  +	retval %= 4294967286ULL;
          517  +	retval += 10;
   472    518   
   473    519   	return(retval);
   474    520   }
   475    521   
   476    522   /*
   477    523    * Cache Get Path Info lookups for speed
   478    524    */
................................................................................
   640    686   	Tcl_Obj *attrs_dict, *attr_value;
   641    687   	const char *attr_value_str;
   642    688   	Tcl_WideInt attr_value_wide;
   643    689   	int attr_value_int;
   644    690   	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;
   645    691   	int cache_ret;
   646    692   	int tcl_ret;
          693  +	uid_t fsuid;
   647    694   
   648         -	cache_ret = appfs_get_path_info_cache_get(path, appfs_get_fsuid(), pathinfo);
          695  +	fsuid = appfs_get_fsuid();
          696  +
          697  +	cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo);
   649    698   	if (cache_ret == 0) {
   650    699   		if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) {
   651    700   			return(-ENOENT);
   652    701   		}
   653    702   
   654    703   		if (pathinfo->type == APPFS_PATHTYPE_INVALID) {
   655    704   			return(-EIO);
................................................................................
   668    717   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);
   669    718   	if (tcl_ret != TCL_OK) {
   670    719   		APPFS_DEBUG("::appfs::getattr(%s) failed.", path);
   671    720   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
   672    721   
   673    722   		pathinfo->type = APPFS_PATHTYPE_DOES_NOT_EXIST;
   674    723   
   675         -		appfs_get_path_info_cache_add(path, appfs_get_fsuid(), pathinfo);
          724  +		appfs_get_path_info_cache_add(path, fsuid, pathinfo);
   676    725   
   677    726   		Tcl_Release(interp);
   678    727   
   679    728   		return(-ENOENT);
   680    729   	}
   681    730   
   682    731   	if (attr_key_type == NULL) {
................................................................................
   787    836   		}
   788    837   	} else {
   789    838   		pathinfo->time = 0;
   790    839   	}
   791    840   
   792    841   	Tcl_Release(interp);
   793    842   
   794         -	appfs_get_path_info_cache_add(path, appfs_get_fsuid(), pathinfo);
          843  +	appfs_get_path_info_cache_add(path, fsuid, pathinfo);
   795    844   
   796    845   	return(0);
   797    846   }
   798    847   
   799    848   static char *appfs_prepare_to_create(const char *path) {
   800    849   	Tcl_Interp *interp;
   801    850   	const char *real_path;
................................................................................
  1541   1590   	/* Request to perform a "hot" restart */
  1542   1591   	if (sig == SIGHUP) {
  1543   1592   		appfs_hot_restart();
  1544   1593   	}
  1545   1594   
  1546   1595   	return;
  1547   1596   }
         1597  +
         1598  +/*
         1599  + * Terminate a thread
         1600  + */
         1601  +static void appfs_terminate_interp(void *_interp) {
         1602  +	Tcl_Interp *interp;
         1603  +
         1604  +	APPFS_DEBUG("Called: _interp = %p", _interp);
         1605  +
         1606  +	if (_interp == NULL) {
         1607  +		APPFS_DEBUG("Terminating thread with no interpreter");
         1608  +
         1609  +		return;
         1610  +	}
         1611  +
         1612  +	interp = _interp;
         1613  +
         1614  +	APPFS_DEBUG("Terminating interpreter due to thread termination");
         1615  +
         1616  +	Tcl_DeleteInterp(interp);
         1617  +
         1618  +	return;
         1619  +}
  1548   1620   
  1549   1621   /*
  1550   1622    * FUSE operations structure
  1551   1623    */
  1552   1624   static struct fuse_operations appfs_operations = {
  1553   1625   	.getattr   = appfs_fuse_getattr,
  1554   1626   	.readdir   = appfs_fuse_readdir,
................................................................................
  1622   1694   	Tcl_StaticPackage(NULL, "appfsd", Appfsd_Init, NULL);
  1623   1695   
  1624   1696   	/*
  1625   1697   	 * Create a thread-specific-data (TSD) key for each thread to refer
  1626   1698   	 * to its own Tcl interpreter.  Tcl interpreters must be unique per
  1627   1699   	 * thread and new threads are dynamically created by FUSE.
  1628   1700   	 */
  1629         -	pthread_ret = pthread_key_create(&interpKey, NULL);
         1701  +	pthread_ret = pthread_key_create(&interpKey, appfs_terminate_interp);
  1630   1702   	if (pthread_ret != 0) {
  1631   1703   		fprintf(stderr, "Unable to create TSD key for Tcl.  Aborting.\n");
  1632   1704   
  1633   1705   		return(1);
  1634   1706   	}
  1635   1707   
  1636   1708   	/*