Check-in [aca3a93d56]
Overview
Comment:Work towards gutting AppFSd to rewrite
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tcl-ops
Files: files | file ages | folders
SHA1:aca3a93d56aeab2902fed4f583aa4bd86e57818b
User & Date: rkeene on 2014-11-06 17:11:01
Other Links: manifest | tags
Context
2014-11-06
18:29
Minor update check-in: 5bd7399e05 user: rkeene tags: tcl-ops
17:11
Work towards gutting AppFSd to rewrite check-in: aca3a93d56 user: rkeene tags: tcl-ops
16:20
Merged in internal_sha1 branch since we should use that as the basis going forward check-in: 5ffd966f05 user: rkeene tags: tcl-ops
Changes

Modified appfsd.c from [a8794a7145] to [8dc47d059d].

     1      1   #define FUSE_USE_VERSION 26
     2      2   
     3      3   #include <sys/types.h>
     4         -#include <sqlite3.h>
     5      4   #include <pthread.h>
     6      5   #include <string.h>
     7      6   #include <stdarg.h>
     8      7   #include <stdlib.h>
     9      8   #include <unistd.h>
    10      9   #include <errno.h>
    11     10   #include <fcntl.h>
................................................................................
    26     25   #else
    27     26   #define APPFS_DEBUG(x...) /**/
    28     27   #endif
    29     28   
    30     29   static pthread_key_t interpKey;
    31     30   
    32     31   struct appfs_thread_data {
    33         -	sqlite3 *db;
    34     32   	const char *cachedir;
    35     33   	time_t boottime;
    36         -	const char *platform;
    37     34   	struct {
    38     35   		int writable;
    39     36   	} options;
    40     37   };
    41     38   
    42     39   struct appfs_thread_data globalThread;
    43     40   
................................................................................
    73     70   		struct {
    74     71   			off_t size;
    75     72   			char source[256];
    76     73   		} symlink;
    77     74   	} typeinfo;
    78     75   };
    79     76   
    80         -struct appfs_sqlite3_query_cb_handle {
    81         -	struct appfs_children *head;
    82         -	int argc;
    83         -	const char *fmt;
    84         -};
    85         -
    86     77   static Tcl_Interp *appfs_create_TclInterp(const char *cachedir) {
    87     78   	Tcl_Interp *interp;
    88     79   	int tcl_ret;
    89     80   
    90     81   	APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self());
    91     82   
    92     83   	interp = Tcl_CreateInterp();
................................................................................
   107     98   	}
   108     99   
   109    100   	tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
   110    101   	if (tcl_ret != TCL_OK) {
   111    102   		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
   112    103   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   113    104   
          105  +		Tcl_DeleteInterp(interp);
          106  +
          107  +		return(NULL);
          108  +	}
          109  +
          110  +	tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
          111  +	if (tcl_ret != TCL_OK) {
          112  +		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
          113  +		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          114  +
   114    115   		Tcl_DeleteInterp(interp);
   115    116   
   116    117   		return(NULL);
   117    118   	}
   118    119   
   119    120   	tcl_ret = Tcl_Eval(interp, ""
   120    121   #include "appfsd.tcl.h"
................................................................................
   269    270   
   270    271   		return;
   271    272   	}
   272    273   
   273    274   	return;
   274    275   }
   275    276   
   276         -#define appfs_free_list_type(id, type) static void appfs_free_list_ ## id(type *head) { \
   277         -	type *obj, *next; \
   278         -	for (obj = head; obj; obj = next) { \
   279         -		next = obj->_next; \
   280         -		ckfree((void *) obj); \
   281         -	} \
   282         -}
   283         -
   284         -appfs_free_list_type(children, struct appfs_children)
   285         -
   286    277   static uid_t appfs_get_fsuid(void) {
   287    278   	struct fuse_context *ctx;
   288    279   
   289    280   	ctx = fuse_get_context();
   290    281   	if (ctx == NULL) {
   291    282   		return(1);
   292    283   	}
   293    284   
   294    285   	return(ctx->uid);
   295    286   }
   296    287   
   297         -static const char *appfs_get_homedir(uid_t fsuid) {
          288  +static char *appfs_get_homedir(uid_t fsuid) {
   298    289   	struct passwd entry, *result;
   299    290   	struct stat stbuf;
   300    291   	char buf[1024], *retval;
   301    292   	int gpu_ret, stat_ret;
   302    293   
   303    294   	gpu_ret = getpwuid_r(fsuid, &entry, buf, sizeof(buf), &result);
   304    295   	if (gpu_ret != 0) {
................................................................................
   332    323   		    result->pw_dir,
   333    324   		    (unsigned long long) stbuf.st_uid
   334    325   		);
   335    326   
   336    327   		return(NULL);
   337    328   	}
   338    329   
   339         -	retval = sqlite3_mprintf("%s", result->pw_dir);
          330  +	retval = strdup(result->pw_dir);
   340    331   
   341    332   	return(retval);
   342    333   }
   343    334   
   344         -static int appfs_getpackage_name_cb(void *_package_name, int columns, char **values, char **names) {
   345         -	char **package_name;
   346         -
   347         -	if (columns != 1) {
   348         -		return(1);
   349         -	}
   350         -
   351         -	package_name = _package_name;
   352         -
   353         -	*package_name = sqlite3_mprintf("%s", values[0]);
   354         -
   355         -	return(0);
   356         -}
   357         -
   358         -static char *appfs_getpackage_name(const char *hostname, const char *package_hash) {
   359         -	char *sql;
   360         -	int sqlite_ret;
   361         -	char *package_name = NULL;
   362         -
   363         -	sql = sqlite3_mprintf("SELECT package FROM packages WHERE hostname = %Q AND sha1 = %Q LIMIT 1;", hostname, package_hash);
   364         -	if (sql == NULL) {
   365         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   366         -
   367         -		return(sqlite3_mprintf("%s", "unknown-package-name"));
   368         -	}
   369         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_getpackage_name_cb, &package_name, NULL);
   370         -	sqlite3_free(sql);
   371         -
   372         -	if (sqlite_ret != SQLITE_OK) {
   373         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   374         -
   375         -		return(sqlite3_mprintf("%s", "unknown-package-name"));
   376         -	}
   377         -
   378         -	return(package_name);
   379         -}
   380         -
   381         -static struct appfs_children *appfs_getchildren_fs(struct appfs_children *in_children, const char *fspath) {
   382         -	APPFS_DEBUG("Searching %s", fspath);
   383         -
   384         -	return(in_children);
   385         -}
   386         -
   387         -static int appfs_getchildren_cb(void *_head, int columns, char **values, char **names) {
   388         -	struct appfs_children **head_p, *obj;
   389         -
   390         -	head_p = _head;
   391         -
   392         -	obj = (void *) ckalloc(sizeof(*obj));
   393         -
   394         -	snprintf(obj->name, sizeof(obj->name), "%s", values[0]);
   395         -
   396         -	if (*head_p == NULL) {
   397         -		obj->counter = 0;
   398         -	} else {
   399         -		obj->counter = (*head_p)->counter + 1;
   400         -	}
   401         -
   402         -	obj->_next = *head_p;
   403         -	*head_p = obj;
   404         -
   405         -	return(0);
   406         -	
          335  +static int tcl_appfs_get_homedir(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
          336  +	char *homedir;
          337  +
          338  +        if (objc != 1) {
          339  +                Tcl_WrongNumArgs(interp, 1, objv, NULL);
          340  +                return(TCL_ERROR);
          341  +        }
          342  +
          343  +	homedir = appfs_get_homedir(appfs_get_fsuid());
          344  +
          345  +	if (homedir == NULL) {
          346  +		return(TCL_ERROR);
          347  +	}
          348  +
          349  +        Tcl_SetObjResult(interp, Tcl_NewStringObj(homedir, -1));
          350  +
          351  +	free(homedir);
          352  +
          353  +        return(TCL_OK);
   407    354   }
   408    355   
   409    356   static struct appfs_children *appfs_getchildren(const char *hostname, const char *package_hash, const char *path, int *children_count_p) {
   410         -	struct appfs_children *head = NULL;
   411         -	char *sql, *filebuf, *homedir = NULL;
   412         -	int sqlite_ret;
   413         -	uid_t fsuid;
   414         -
   415         -	if (children_count_p == NULL) {
   416         -		return(NULL);
   417         -	}
   418         -
   419         -	appfs_update_index(hostname);
   420         -	appfs_update_manifest(hostname, package_hash);
   421         -
   422         -	sql = sqlite3_mprintf("SELECT file_name FROM files WHERE package_sha1 = %Q AND file_directory = %Q;", package_hash, path);
   423         -	if (sql == NULL) {
   424         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   425         -
   426         -		return(NULL);
   427         -	}
   428         -
   429         -	APPFS_DEBUG("SQL: %s", sql);
   430         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_getchildren_cb, &head, NULL);
   431         -	sqlite3_free(sql);
   432         -
   433         -	if (sqlite_ret != SQLITE_OK) {
   434         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   435         -
   436         -		appfs_free_list_children(head);
   437         -
   438         -		return(NULL);
   439         -	}
   440         -
   441         -	if (globalThread.options.writable) {
   442         -		/* Determine user of process accessing this file */
   443         -		fsuid = appfs_get_fsuid();
   444         -
   445         -		/* Check filesystem paths for updated files */
   446         -		/** Check the global directory (/etc) **/
   447         -		filebuf = sqlite3_mprintf("/etc/appfs/%z@%s/%s", appfs_getpackage_name(hostname, package_hash), hostname, path);
   448         -		if (filebuf == NULL) {
   449         -			APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   450         -
   451         -			return(NULL);
   452         -		}
   453         -
   454         -		head = appfs_getchildren_fs(head, filebuf);
   455         -
   456         -		sqlite3_free(filebuf);
   457         -
   458         -		/** Check the user's directory, if we are not root **/
   459         -		if (fsuid != 0) {
   460         -			homedir = (char *) appfs_get_homedir(fsuid);
   461         -		}
   462         -
   463         -		if (homedir != NULL) {
   464         -			filebuf = sqlite3_mprintf("%z/.appfs/%z@%s/%s", homedir, appfs_getpackage_name(hostname, package_hash), hostname, path);
   465         -
   466         -			if (filebuf == NULL) {
   467         -				APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   468         -
   469         -				return(NULL);
   470         -			}
   471         -
   472         -			head = appfs_getchildren_fs(head, filebuf);
   473         -
   474         -			sqlite3_free(filebuf);
   475         -		}
   476         -	}
   477         -
   478         -	if (head != NULL) {
   479         -		*children_count_p = head->counter + 1;
   480         -	} else {
   481         -		*children_count_p = 0;
   482         -	}
   483         -
   484         -	return(head);
   485         -}
   486         -
   487         -static int appfs_sqlite3_query_cb(void *_cb_handle, int columns, char **values, char **names) {
   488         -	struct appfs_sqlite3_query_cb_handle *cb_handle;
   489         -	struct appfs_children *obj;
   490         -
   491         -	cb_handle = _cb_handle;
   492         -
   493         -	obj = (void *) ckalloc(sizeof(*obj));
   494         -
   495         -	switch (cb_handle->argc) {
   496         -		case 1:
   497         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0]);
   498         -			break;
   499         -		case 2:
   500         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0], values[1]);
   501         -			break;
   502         -		case 3:
   503         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0], values[1], values[2]);
   504         -			break;
   505         -		case 4:
   506         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0], values[1], values[2], values[3]);
   507         -			break;
   508         -	}
   509         -
   510         -	if (cb_handle->head == NULL) {
   511         -		obj->counter = 0;
   512         -	} else {
   513         -		obj->counter = cb_handle->head->counter + 1;
   514         -	}
   515         -
   516         -	obj->_next = cb_handle->head;
   517         -	cb_handle->head = obj;
   518         -
   519         -	return(0);
   520         -}
   521         -
   522         -static struct appfs_children *appfs_sqlite3_query(char *sql, int argc, const char *fmt, int *results_count_p) {
   523         -	struct appfs_sqlite3_query_cb_handle cb_handle;
   524         -	int sqlite_ret;
   525         -
   526         -	if (results_count_p == NULL) {
   527         -		return(NULL);
   528         -	}
   529         -
   530         -	if (sql == NULL) {
   531         -		APPFS_DEBUG("Call to sqlite3_mprintf probably failed.");
   532         -
   533         -		return(NULL);
   534         -	}
   535         -
   536         -	if (fmt == NULL) {
   537         -		fmt = "%s";
   538         -	}
   539         -
   540         -	cb_handle.head = NULL;
   541         -	cb_handle.argc = argc;
   542         -	cb_handle.fmt  = fmt;
   543         -
   544         -	APPFS_DEBUG("SQL: %s", sql);
   545         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_sqlite3_query_cb, &cb_handle, NULL);
   546         -	sqlite3_free(sql);
   547         -
   548         -	if (sqlite_ret != SQLITE_OK) {
   549         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   550         -
   551         -		return(NULL);
   552         -	}
   553         -
   554         -	if (cb_handle.head != NULL) {
   555         -		*results_count_p = cb_handle.head->counter + 1;
   556         -	}
   557         -
   558         -	return(cb_handle.head);
   559         -}
   560         -
   561         -static int appfs_lookup_package_hash_cb(void *_retval, int columns, char **values, char **names) {
   562         -	char **retval = _retval;
   563         -
   564         -	*retval = strdup(values[0]);
   565         -
   566         -	return(0);
   567    357   }
   568    358   
   569    359   static char *appfs_lookup_package_hash(const char *hostname, const char *package, const char *os, const char *cpuArch, const char *version) {
   570         -	char *sql;
   571         -	char *retval = NULL;
   572         -	int sqlite_ret;
   573         -
   574         -	appfs_update_index(hostname);
   575         -
   576         -	sql = sqlite3_mprintf("SELECT sha1 FROM packages WHERE hostname = %Q AND package = %Q AND os = %Q AND cpuArch = %Q AND version = %Q;",
   577         -		hostname,
   578         -		package,
   579         -		os,
   580         -		cpuArch,
   581         -		version
   582         -	);
   583         -	if (sql == NULL) {
   584         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   585         -
   586         -		return(NULL);
   587         -	}
   588         -
   589         -	APPFS_DEBUG("SQL: %s", sql);
   590         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_lookup_package_hash_cb, &retval, NULL);
   591         -	sqlite3_free(sql);
   592         -
   593         -	if (sqlite_ret != SQLITE_OK) {
   594         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   595         -
   596         -		return(NULL);
   597         -	}
   598         -
   599         -	return(retval);
   600         -}
   601         -
   602         -static int appfs_getfileinfo_cb(void *_pathinfo, int columns, char **values, char **names) {
   603         -	struct appfs_pathinfo *pathinfo = _pathinfo;
   604         -	const char *type, *time, *source, *size, *perms, *sha1, *rowid;
   605         -
   606         -	type = values[0];
   607         -	time = values[1];
   608         -	source = values[2];
   609         -	size = values[3];
   610         -	perms = values[4];
   611         -	sha1 = values[5];
   612         -	rowid = values[6];
   613         -
   614         -	pathinfo->time = strtoull(time, NULL, 10);
   615         -
   616         -	/* Package file inodes start at 2^32, fake inodes are before then */
   617         -	pathinfo->inode = strtoull(rowid, NULL, 10) + 4294967296ULL;
   618         -
   619         -	if (strcmp(type, "file") == 0) {
   620         -		pathinfo->type = APPFS_PATHTYPE_FILE;
   621         -
   622         -		if (!size) {
   623         -			size = "0";
   624         -		}
   625         -
   626         -		if (!perms) {
   627         -			perms = "";
   628         -		}
   629         -
   630         -		if (!sha1) {
   631         -			sha1 = "";
   632         -		}
   633         -
   634         -		pathinfo->typeinfo.file.size = strtoull(size, NULL, 10);
   635         -		snprintf(pathinfo->typeinfo.file.sha1, sizeof(pathinfo->typeinfo.file.sha1), "%s", sha1);
   636         -
   637         -		if (strcmp(perms, "x") == 0) {
   638         -			pathinfo->typeinfo.file.executable = 1;
   639         -		} else {
   640         -			pathinfo->typeinfo.file.executable = 0;
   641         -		}
   642         -
   643         -		return(0);
   644         -	}
   645         -
   646         -	if (strcmp(type, "directory") == 0) {
   647         -		pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   648         -		pathinfo->typeinfo.dir.childcount = 0;
   649         -
   650         -		return(0);
   651         -	}
   652         -
   653         -	if (strcmp(type, "symlink") == 0) {
   654         -		pathinfo->type = APPFS_PATHTYPE_SYMLINK;
   655         -		pathinfo->typeinfo.dir.childcount = 0;
   656         -
   657         -		if (!source) {
   658         -			source = ".BADLINK";
   659         -		}
   660         -
   661         -		pathinfo->typeinfo.symlink.size = strlen(source);
   662         -		snprintf(pathinfo->typeinfo.symlink.source, sizeof(pathinfo->typeinfo.symlink.source), "%s", source);
   663         -
   664         -		return(0);
   665         -	}
   666         -
   667         -	return(0);
   668         -
   669         -	/* Until this is used, prevent the compiler from complaining */
   670         -	source = source;
   671    360   }
   672    361   
   673    362   static int appfs_getfileinfo(const char *hostname, const char *package_hash, const char *_path, struct appfs_pathinfo *pathinfo) {
   674         -	char *directory, *file, *path;
   675         -	char *sql;
   676         -	int sqlite_ret;
   677         -
   678         -	if (pathinfo == NULL) {
   679         -		return(-EIO);
   680         -	}
   681         -
   682         -	appfs_update_index(hostname);
   683         -	appfs_update_manifest(hostname, package_hash);
   684         -
   685         -	path = strdup(_path);
   686         -	directory = path;
   687         -	file = strrchr(path, '/');
   688         -	if (file == NULL) {
   689         -		file = path;
   690         -		directory = "";
   691         -	} else {
   692         -		*file = '\0';
   693         -		file++;
   694         -	}
   695         -
   696         -	sql = sqlite3_mprintf("SELECT type, time, source, size, perms, file_sha1, rowid FROM files WHERE package_sha1 = %Q AND file_directory = %Q AND file_name = %Q;", package_hash, directory, file);
   697         -	if (sql == NULL) {
   698         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   699         -
   700         -		free(path);
   701         -
   702         -		return(-EIO);
   703         -	}
   704         -
   705         -	free(path);
   706         -
   707         -	pathinfo->type = APPFS_PATHTYPE_INVALID;
   708         -
   709         -	APPFS_DEBUG("SQL: %s", sql);
   710         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_getfileinfo_cb, pathinfo, NULL);
   711         -	sqlite3_free(sql);
   712         -
   713         -	if (sqlite_ret != SQLITE_OK) {
   714         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   715         -
   716         -		return(-EIO);
   717         -	}
   718         -
   719         -	if (pathinfo->type == APPFS_PATHTYPE_INVALID) {
   720         -		return(-ENOENT);
   721         -	}
   722         -
   723         -	return(0);
   724         -}
   725         -
   726         -static int appfs_get_path_info_sql(char *sql, int argc, const char *fmt, struct appfs_pathinfo *pathinfo, struct appfs_children **children) {
   727         -	struct appfs_children *node, *dir_children, *dir_child;
   728         -	int dir_children_count = 0;
   729         -
   730         -	dir_children = appfs_sqlite3_query(sql, argc, fmt, &dir_children_count);
   731         -
   732         -	if (dir_children == NULL || dir_children_count == 0) {
   733         -		return(-ENOENT);
   734         -	}
   735         -
   736         -	/* Request for a single hostname */
   737         -	pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   738         -	pathinfo->typeinfo.dir.childcount = dir_children_count;
   739         -	pathinfo->time = globalThread.boottime;
   740         -
   741         -	if (children) {
   742         -		for (dir_child = dir_children; dir_child; dir_child = dir_child->_next) {
   743         -			node = (void *) ckalloc(sizeof(*node));
   744         -			node->_next = *children;
   745         -			strcpy(node->name, dir_child->name);
   746         -			*children = node;
   747         -		}
   748         -	}
   749         -
   750         -	appfs_free_list_children(dir_children);
   751         -
   752         -	return(0);
   753         -}
   754         -
   755         -static int appfs_add_path_child(const char *name, struct appfs_pathinfo *pathinfo, struct appfs_children **children) {
   756         -	struct appfs_children *new_child;
   757         -
   758         -	pathinfo->typeinfo.dir.childcount++;
   759         -
   760         -	if (children) {
   761         -		new_child = (void *) ckalloc(sizeof(*new_child));
   762         -		new_child->_next = *children;
   763         -
   764         -		snprintf(new_child->name, sizeof(new_child->name), "%s", name);
   765         -
   766         -		*children = new_child;
   767         -	}
   768         -
   769         -	return(0);
   770    363   }
   771    364   
   772    365   /* Generate an inode for a given path */
   773    366   static long long appfs_get_path_inode(const char *path) {
   774    367   	long long retval;
   775    368   	const char *p;
   776    369   
................................................................................
   786    379   	retval %= 4294967296ULL;
   787    380   
   788    381   	return(retval);
   789    382   }
   790    383   
   791    384   /* Get information about a path, and optionally list children */
   792    385   static int appfs_get_path_info(const char *_path, struct appfs_pathinfo *pathinfo, struct appfs_children **children) {
   793         -	struct appfs_children *dir_children;
   794         -	char *hostname, *packagename, *os_cpuArch, *os, *cpuArch, *version;
   795         -	char *path, *path_s;
   796         -	char *package_hash;
   797         -	char *sql;
   798         -	int files_count;
   799         -	int fileinfo_ret, retval;
   800         -
   801         -	/* Initialize return */
   802         -	if (children) {
   803         -		*children = NULL;
   804         -	}
   805         -
   806         -	/* Verify that this is a valid request */
   807         -	if (_path == NULL) {
   808         -		return(-ENOENT);
   809         -	}
   810         -
   811         -	if (_path[0] != '/') {
   812         -		return(-ENOENT);
   813         -	}
   814         -
   815         -	/* Note that this is not a "real" directory from a package */
   816         -	pathinfo->packaged = 0;
   817         -
   818         -	if (_path[1] == '\0') {
   819         -		/* Request for the root directory */
   820         -		pathinfo->hostname[0] = '\0';
   821         -		pathinfo->inode = 1;
   822         -
   823         -		sql = sqlite3_mprintf("SELECT DISTINCT hostname FROM packages;");
   824         -
   825         -		retval = appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children);
   826         -
   827         -		/* The root directory always exists, even if it has no subordinates */
   828         -		if (retval != 0) {
   829         -			pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   830         -			pathinfo->typeinfo.dir.childcount = 0;
   831         -			pathinfo->time = globalThread.boottime;
   832         -
   833         -			retval = 0;
   834         -		}
   835         -
   836         -		return(retval);
   837         -	}
   838         -
   839         -	path = strdup(_path);
   840         -	path_s = path;
   841         -
   842         -	pathinfo->inode = appfs_get_path_inode(path);
   843         -
   844         -	hostname = path + 1;
   845         -	packagename = strchr(hostname, '/');
   846         -
   847         -	if (packagename != NULL) {
   848         -		*packagename = '\0';
   849         -		packagename++;
   850         -	}
   851         -
   852         -	snprintf(pathinfo->hostname, sizeof(pathinfo->hostname), "%s", hostname);
   853         -
   854         -	if (packagename == NULL) {
   855         -		appfs_update_index(hostname);
   856         -
   857         -		sql = sqlite3_mprintf("SELECT DISTINCT package FROM packages WHERE hostname = %Q;", hostname);
   858         -
   859         -		free(path_s);
   860         -
   861         -		return(appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children));
   862         -	}
   863         -
   864         -	os_cpuArch = strchr(packagename, '/');
   865         -
   866         -	if (os_cpuArch != NULL) {
   867         -		*os_cpuArch = '\0';
   868         -		os_cpuArch++;
   869         -	}
   870         -
   871         -	if (os_cpuArch == NULL) {
   872         -		appfs_update_index(hostname);
   873         -
   874         -		sql = sqlite3_mprintf("SELECT DISTINCT os, cpuArch FROM packages WHERE hostname = %Q AND package = %Q;", hostname, packagename);
   875         -
   876         -		free(path_s);
   877         -
   878         -		retval = appfs_get_path_info_sql(sql, 2, "%s-%s", pathinfo, children);
   879         -
   880         -		if (retval != 0) {
   881         -			return(retval);
   882         -		}
   883         -
   884         -		appfs_add_path_child("platform", pathinfo, children);
   885         -
   886         -		return(retval);
   887         -	}
   888         -
   889         -	version = strchr(os_cpuArch, '/');
   890         -
   891         -	if (version != NULL) {
   892         -		*version = '\0';
   893         -		version++;
   894         -	}
   895         -
   896         -	os = os_cpuArch;
   897         -	cpuArch = strchr(os_cpuArch, '-');
   898         -	if (cpuArch) {
   899         -		*cpuArch = '\0';
   900         -		cpuArch++;
   901         -	} else {
   902         -		cpuArch = "";
   903         -	}
   904         -
   905         -	if (version == NULL) {
   906         -		if (strcmp(os, "platform") == 0 && strcmp(cpuArch, "") == 0) {
   907         -			pathinfo->type = APPFS_PATHTYPE_SYMLINK;
   908         -			pathinfo->time = globalThread.boottime;
   909         -			pathinfo->typeinfo.dir.childcount = 0;
   910         -			pathinfo->typeinfo.symlink.size = strlen(globalThread.platform);
   911         -
   912         -			snprintf(pathinfo->typeinfo.symlink.source, sizeof(pathinfo->typeinfo.symlink.source), "%s", globalThread.platform);
   913         -
   914         -			free(path_s);
   915         -
   916         -			return(0);
   917         -		}
   918         -
   919         -		/* Request for version list for a package on an OS/CPU */
   920         -		appfs_update_index(hostname);
   921         -
   922         -		sql = sqlite3_mprintf("SELECT DISTINCT version FROM packages WHERE hostname = %Q AND package = %Q AND os = %Q and cpuArch = %Q;", hostname, packagename, os, cpuArch);
   923         -
   924         -		free(path_s);
   925         -
   926         -		return(appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children));
   927         -	}
   928         -
   929         -	path = strchr(version, '/');
   930         -	if (path == NULL) {
   931         -		path = "";
   932         -	} else {
   933         -		*path = '\0';
   934         -		path++;
   935         -	}
   936         -
   937         -	/* Request for a file in a specific package */
   938         -	pathinfo->packaged = 1;
   939         -	APPFS_DEBUG("Requesting information for hostname = %s, package = %s, os = %s, cpuArch = %s, version = %s, path = %s", 
   940         -		hostname, packagename, os, cpuArch, version, path
   941         -	);
   942         -
   943         -	package_hash = appfs_lookup_package_hash(hostname, packagename, os, cpuArch, version);
   944         -	if (package_hash == NULL) {
   945         -		free(path_s);
   946         -
   947         -		return(-ENOENT);
   948         -	}
   949         -
   950         -	APPFS_DEBUG("  ... which hash a hash of %s", package_hash);
   951         -
   952         -	appfs_update_manifest(hostname, package_hash);
   953         -
   954         -	if (strcmp(path, "") == 0) {
   955         -		pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   956         -		pathinfo->time = globalThread.boottime;
   957         -	} else {
   958         -		fileinfo_ret = appfs_getfileinfo(hostname, package_hash, path, pathinfo);
   959         -		if (fileinfo_ret != 0) {
   960         -			free(path_s);
   961         -
   962         -			return(fileinfo_ret);
   963         -		}
   964         -	}
   965         -
   966         -	if (pathinfo->type == APPFS_PATHTYPE_DIRECTORY) {
   967         -		dir_children = appfs_getchildren(hostname, package_hash, path, &files_count);
   968         -
   969         -		if (dir_children != NULL) {
   970         -			pathinfo->typeinfo.dir.childcount = files_count;
   971         -		}
   972         -
   973         -		if (children) {
   974         -			*children = dir_children;
   975         -		} else {
   976         -			appfs_free_list_children(dir_children);
   977         -		}
   978         -	}
   979         -
   980         -	free(path_s);
   981         -
   982         -	return(0);
   983         -}
   984         -
   985         -static int appfs_fuse_readlink(const char *path, char *buf, size_t size) {
   986         -	struct appfs_pathinfo pathinfo;
   987         -	int res = 0;
   988         -
   989         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
   990         -
   991         -	pathinfo.type = APPFS_PATHTYPE_INVALID;
   992         -
   993         -	res = appfs_get_path_info(path, &pathinfo, NULL);
   994         -	if (res != 0) {
   995         -		return(res);
   996         -	}
   997         -
   998         -	if (pathinfo.type != APPFS_PATHTYPE_SYMLINK) {
   999         -		return(-EINVAL);
  1000         -	}
  1001         -
  1002         -	if ((strlen(pathinfo.typeinfo.symlink.source) + 1) > size) {
  1003         -		return(-ENAMETOOLONG);
  1004         -	}
  1005         -
  1006         -	memcpy(buf, pathinfo.typeinfo.symlink.source, strlen(pathinfo.typeinfo.symlink.source) + 1);
  1007         -
  1008         -	return(0);
  1009    386   }
  1010    387   
  1011    388   static int appfs_fuse_getattr(const char *path, struct stat *stbuf) {
  1012    389   	struct appfs_pathinfo pathinfo;
  1013    390   	int res = 0;
  1014    391   
  1015    392   	APPFS_DEBUG("Enter (path = %s, ...)", path);
................................................................................
  1156    533   	.getattr   = appfs_fuse_getattr,
  1157    534   	.readdir   = appfs_fuse_readdir,
  1158    535   	.readlink  = appfs_fuse_readlink,
  1159    536   	.open      = appfs_fuse_open,
  1160    537   	.release   = appfs_fuse_close,
  1161    538   	.read      = appfs_fuse_read
  1162    539   };
          540  +
          541  +int Appfsd_Init(Tcl_Interp *interp) {
          542  +#ifdef USE_TCL_STUBS
          543  +	if (Tcl_InitStubs(interp, TCL_VERSION, 0) == 0L) {
          544  +		return(TCL_ERROR);
          545  +	}
          546  +#endif
          547  +
          548  +	Tcl_CreateObjCommand(interp, "appfsd::get_homedir", tcl_appfs_get_homedir, NULL, NULL);
          549  +
          550  +	Tcl_PkgProvide(interp, "appfsd", "1.0");
          551  +
          552  +	return(TCL_OK);
          553  +}
  1163    554   
  1164    555   int main(int argc, char **argv) {
  1165    556   	const char *cachedir = APPFS_CACHEDIR;
  1166    557   	char dbfilename[1024];
  1167         -	int pthread_ret, snprintf_ret, sqlite_ret;
          558  +	int pthread_ret, snprintf_ret;
  1168    559   
  1169    560   	globalThread.cachedir = cachedir;
  1170    561   	globalThread.boottime = time(NULL);
  1171         -	globalThread.platform = "linux-x86_64";
  1172    562   	globalThread.options.writable = 1;
  1173    563   
  1174    564   	Tcl_StaticPackage(NULL, "sha1", Sha1_Init, NULL);
          565  +	Tcl_StaticPackage(NULL, "appfsd", Appfsd_Init, NULL);
  1175    566   
  1176    567   	pthread_ret = pthread_key_create(&interpKey, NULL);
  1177    568   	if (pthread_ret != 0) {
  1178    569   		fprintf(stderr, "Unable to create TSD key for Tcl.  Aborting.\n");
  1179    570   
  1180    571   		return(1);
  1181    572   	}
  1182    573   
  1183    574   	snprintf_ret = snprintf(dbfilename, sizeof(dbfilename), "%s/%s", cachedir, "cache.db");
  1184    575   	if (snprintf_ret >= sizeof(dbfilename)) {
  1185    576   		fprintf(stderr, "Unable to set database filename.  Aborting.\n");
  1186    577   
  1187         -		return(1);
  1188         -	}
  1189         -
  1190         -	sqlite_ret = sqlite3_open(dbfilename, &globalThread.db);
  1191         -	if (sqlite_ret != SQLITE_OK) {
  1192         -		fprintf(stderr, "Unable to open database: %s\n", dbfilename);
  1193         -
  1194    578   		return(1);
  1195    579   	}
  1196    580   
  1197    581   	return(fuse_main(argc, argv, &appfs_oper, NULL));
  1198    582   }
  1199    583