Changes On Branch 9f4f082fefc3a28c

Changes In Branch packages Through [9f4f082fef] Excluding Merge-Ins

This is equivalent to a diff from 17bbfdc417 to 9f4f082fef

2014-11-03
23:49
Updated to use package data from Fossil, which is more reliable check-in: 77faad55ab user: rkeene tags: packages
23:35
Added zlib package and support for checking hash and storing archive check-in: 9f4f082fef user: rkeene tags: packages
23:20
Emptied old ignore glob check-in: 286b0eb815 user: rkeene tags: packages
2014-09-18
05:14
Added support for a "platform" symlink pointing to the current platform check-in: 7ef423f980 user: rkeene tags: trunk
04:43
Added package building branch check-in: 07e806db4e user: rkeene tags: packages
2014-09-16
18:21
Removed blank line check-in: 17bbfdc417 user: rkeene tags: trunk
2014-09-14
04:36
Updated to normalize CPU/OS check-in: ee1a499a2e user: rkeene tags: trunk

Modified .fossil-settings/ignore-glob from [5155de6731] to [171004757d].

     1         -appfsd
     2         -appfsd.o
     3         -appfsd.tcl.h
            1  +workdir-*
            2  +ARCHIVE

Deleted Makefile version [be705a2fe3].

     1         -CC = gcc
     2         -PKG_CONFIG = pkg-config
     3         -CFLAGS = -Wall $(shell $(PKG_CONFIG) --cflags fuse) $(shell $(PKG_CONFIG) --cflags sqlite3) $(TCL_CFLAGS)
     4         -LDFLAGS = $(TCL_LDFLAGS)
     5         -LIBS = $(shell $(PKG_CONFIG) --libs fuse) $(shell $(PKG_CONFIG) --libs sqlite3) $(TCL_LIBS)
     6         -PREFIX = /usr/local
     7         -prefix = $(PREFIX)
     8         -bindir = $(prefix)/bin
     9         -sbindir = $(prefix)/sbin
    10         -
    11         -ifneq ($(TCLKIT_SDK_DIR),)
    12         -TCLCONFIG_SH_PATH = $(TCLKIT_SDK_DIR)/lib/tclConfig.sh
    13         -TCL_LDFLAGS = -Wl,-R,$(TCLKIT_SDK_DIR)/lib
    14         -export TCLKIT_SDK_DIR
    15         -else
    16         -TCLCONFIG_SH_PATH = $(shell echo 'puts [::tcl::pkgconfig get libdir,install]' | tclsh)/tclConfig.sh
    17         -endif
    18         -TCL_CFLAGS = $(shell . $(TCLCONFIG_SH_PATH); echo "$${TCL_INCLUDE_SPEC}")
    19         -TCL_LIBS = $(shell . $(TCLCONFIG_SH_PATH); echo "$${TCL_LIB_SPEC}")
    20         -
    21         -all: appfsd
    22         -
    23         -appfsd: appfsd.o
    24         -	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o appfsd appfsd.o $(LIBS)
    25         -
    26         -appfsd.o: appfsd.c appfsd.tcl.h
    27         -	$(CC) $(CPPFLAGS) $(CFLAGS) -o appfsd.o -c appfsd.c
    28         -
    29         -appfsd.tcl.h: appfsd.tcl
    30         -	sed 's@[\\"]@\\&@g;s@^@   "@;s@$$@\\n"@' appfsd.tcl > appfsd.tcl.h.new
    31         -	mv appfsd.tcl.h.new appfsd.tcl.h
    32         -
    33         -install: appfsd
    34         -	if [ ! -d '$(DESTDIR)$(sbindir)' ]; then mkdir -p '$(DESTDIR)$(sbindir)'; chmod 755 '$(DESTDIR)$(sbindir)'; fi
    35         -	cp appfsd '$(DESTDIR)$(sbindir)/'
    36         -
    37         -clean:
    38         -	rm -f appfsd appfsd.o
    39         -	rm -f appfsd.tcl.h
    40         -
    41         -distclean: clean
    42         -
    43         -.PHONY: all test clean distclean install

Deleted README.md version [209ceb6ce4].

     1         -AppFS
     2         -=====
     3         -It's sort of like LazyFS.
     4         -
     5         -Usage
     6         ------
     7         -Run:
     8         -	1. # mkdir /tmp/appfs-cache /opt/appfs
     9         -	2. # appfsd /opt/appfs
    10         -
    11         -
    12         -Paths
    13         ------
    14         -    AppFS should normally be mounted on "/opt/appfs".
    15         -
    16         -    /opt/appfs/hostname
    17         -    	Fetches: http://hostname/appfs/index
    18         -    	Contains CSV file: hash,extraData
    19         -    	Fetches: http://hostname/appfs/sha1/<hash>
    20         -    	Contains CSV file: package,version,os,cpuArch,sha1,isLatest
    21         -
    22         -    /opt/appfs/hostname/package/os-cpuArch/version
    23         -    /opt/appfs/hostname/sha1/
    24         -    	Fetches: http://hostname/appfs/sha1/<sha1>
    25         -    	Contains CSV file:
    26         -    		type,time,extraData,name
    27         -    		type == directory; extraData = (null)
    28         -    		type == symlink; extraData = source
    29         -    		type == file; extraData = size,perms,sha1
    30         -
    31         -    /opt/appfs/hostname/{sha1,package/os-cpuArch/version}/file
    32         -    	Fetches: http://hostname/appfs/sha1/<sha1>
    33         -
    34         -Database
    35         ---------
    36         -    packages(hostname, sha1, package, version, os, cpuArch, isLatest, haveManifest)
    37         -    files(package_sha1, type, time, source, size, perms, file_sha1, file_name, file_directory)
    38         -
    39         -Resources
    40         ----------
    41         -http://appfs.rkeene.org/

Deleted appfs-mkfs version [994caae026].

     1         -#! /usr/bin/env bash
     2         -
     3         -pkgsdir="$1"
     4         -appfsdir="$2"
     5         -
     6         -if [ -z  "${pkgsdir}" -o -z "${appfsdir}" ]; then
     7         -	echo 'Usage: appfs-mk <pkgsdir> <appfsdir>' >&2
     8         -
     9         -	exit 1
    10         -fi
    11         -
    12         -appfsdir="$(cd "${appfsdir}" && pwd)"
    13         -if [ -z "${appfsdir}" ]; then
    14         -	echo "Unable to find appfs directory." >&2
    15         -
    16         -	exit 1
    17         -fi
    18         -
    19         -mkdir -p "${appfsdir}/sha1"
    20         -
    21         -function sha1() {
    22         -	local filename
    23         -
    24         -	filename="$1"
    25         -
    26         -	openssl sha1 "${filename}" | sed 's@.*= @@'
    27         -}
    28         -
    29         -function emit_manifest() {
    30         -	find . -print0 | while IFS='' read -r -d $'\0' filename; do
    31         -		if [ "${filename}" = '.' ]; then
    32         -			continue
    33         -		fi
    34         -
    35         -		filename="$(echo "${filename}" | sed 's@^\./@@' | head -n 1)"
    36         -
    37         -		if [ ! -e "${filename}" ]; then
    38         -			continue
    39         -		fi
    40         -
    41         -		if [ -h "${filename}" ]; then
    42         -			type='symlink'
    43         -		elif [ -d "${filename}" ]; then
    44         -			type='directory'
    45         -		elif [ -f "${filename}" ]; then
    46         -			type='file'
    47         -		else
    48         -			continue
    49         -		fi
    50         -
    51         -		case "${type}" in
    52         -			directory)
    53         -				stat_format='%Y'
    54         -				extra_data=''
    55         -				;;
    56         -			symlink)
    57         -				stat_format='%Y'
    58         -				extra_data="$(readlink "${filename}")"
    59         -				;;
    60         -			file)
    61         -				if [ -x "${filename}" ]; then
    62         -					extra_data='x'
    63         -				else
    64         -					extra_data=''
    65         -				fi
    66         -
    67         -				stat_format='%Y,%s'
    68         -				filename_hash="$(sha1 "${filename}")"
    69         -				extra_data="${extra_data},${filename_hash}"
    70         -
    71         -				filename_intree="${appfsdir}/sha1/${filename_hash}"
    72         -
    73         -				if [ ! -e "${filename_intree}" ]; then
    74         -					cat "${filename}" > "${filename_intree}.tmp"
    75         -
    76         -					mv "${filename_intree}.tmp" "${filename_intree}"
    77         -				fi
    78         -				;;
    79         -		esac
    80         -		stat_data="$(stat --format="${stat_format}" "${filename}")"
    81         -
    82         -		if [ -z "${extra_data}" ]; then
    83         -			echo "${type},${stat_data},${filename}"
    84         -		else
    85         -			echo "${type},${stat_data},${extra_data},${filename}"
    86         -		fi
    87         -	done
    88         -}
    89         -
    90         -cd "${pkgsdir}" || exit 1
    91         -
    92         -packagelistfile="${appfsdir}/sha1/${RANDOM}${RANDOM}${RANDOM}${RANDOM}${RANDOM}.tmp"
    93         -for package in *; do
    94         -	(
    95         -		cd "${package}" || exit 1
    96         -
    97         -		for os_cpuArch in *; do
    98         -			os="$(echo "${os_cpuArch}" | cut -f 1 -d '-')"
    99         -			cpuArch="$(echo "${os_cpuArch}" | cut -f 2- -d '-')"
   100         -
   101         -			(
   102         -				cd "${os_cpuArch}" || exit 1
   103         -
   104         -				for version in *; do
   105         -					if [ -h "${version}" ]; then
   106         -						continue
   107         -					fi
   108         -
   109         -					manifestfile="${appfsdir}/sha1/${RANDOM}${RANDOM}${RANDOM}${RANDOM}${RANDOM}.tmp"
   110         -
   111         -					(
   112         -						cd "${version}" || exit 1
   113         -
   114         -						emit_manifest
   115         -					) > "${manifestfile}"
   116         -
   117         -					manifestfile_hash="$(sha1 "${manifestfile}")"
   118         -					mv "${manifestfile}" "${appfsdir}/sha1/${manifestfile_hash}"
   119         -
   120         -					# XXX:TODO: Determine if this is the latest version
   121         -					isLatest='0'
   122         -
   123         -					echo "${package},${version},${os},${cpuArch},${manifestfile_hash},${isLatest}"
   124         -				done
   125         -
   126         -			)
   127         -		done
   128         -	)
   129         -
   130         -done > "${packagelistfile}"
   131         -packagelistfile_hash="$(sha1 "${packagelistfile}")"
   132         -mv "${packagelistfile}" "${appfsdir}/sha1/${packagelistfile_hash}"
   133         -
   134         -echo "${packagelistfile_hash},sha1" > "${appfsdir}/index"

Deleted appfsd.c version [f1b76341ae].

     1         -#define FUSE_USE_VERSION 26
     2         -
     3         -#include <sys/types.h>
     4         -#include <sqlite3.h>
     5         -#include <pthread.h>
     6         -#include <string.h>
     7         -#include <stdarg.h>
     8         -#include <stdlib.h>
     9         -#include <unistd.h>
    10         -#include <errno.h>
    11         -#include <fcntl.h>
    12         -#include <stdio.h>
    13         -#include <fuse.h>
    14         -#include <tcl.h>
    15         -
    16         -#define APPFS_CACHEDIR "/var/cache/appfs"
    17         -
    18         -#define APPFS_DEBUG(x...) { fprintf(stderr, "[debug] %s:%i:%s: ", __FILE__, __LINE__, __func__); fprintf(stderr, x); fprintf(stderr, "\n"); }
    19         -
    20         -static pthread_key_t interpKey;
    21         -
    22         -struct appfs_thread_data {
    23         -	sqlite3 *db;
    24         -	const char *cachedir;
    25         -	time_t boottime;
    26         -};
    27         -
    28         -struct appfs_thread_data globalThread;
    29         -
    30         -typedef enum {
    31         -	APPFS_PATHTYPE_INVALID,
    32         -	APPFS_PATHTYPE_FILE,
    33         -	APPFS_PATHTYPE_DIRECTORY,
    34         -	APPFS_PATHTYPE_SYMLINK
    35         -} appfs_pathtype_t;
    36         -
    37         -struct appfs_children {
    38         -	struct appfs_children *_next;
    39         -	int counter;
    40         -
    41         -	char name[256];
    42         -};
    43         -
    44         -struct appfs_pathinfo {
    45         -	appfs_pathtype_t type;
    46         -	time_t time;
    47         -	char hostname[256];
    48         -	union {
    49         -		struct {
    50         -			int childcount;
    51         -		} dir;
    52         -		struct {
    53         -			int executable;
    54         -			off_t size;
    55         -			char sha1[41];
    56         -		} file;
    57         -		struct {
    58         -			off_t size;
    59         -			char source[256];
    60         -		} symlink;
    61         -	} typeinfo;
    62         -};
    63         -
    64         -struct appfs_sqlite3_query_cb_handle {
    65         -	struct appfs_children *head;
    66         -	int argc;
    67         -	const char *fmt;
    68         -};
    69         -
    70         -static Tcl_Interp *appfs_create_TclInterp(const char *cachedir) {
    71         -	Tcl_Interp *interp;
    72         -	int tcl_ret;
    73         -
    74         -	interp = Tcl_CreateInterp();
    75         -	if (interp == NULL) {
    76         -		fprintf(stderr, "Unable to create Tcl Interpreter.  Aborting.\n");
    77         -
    78         -		return(NULL);
    79         -	}
    80         -
    81         -	tcl_ret = Tcl_Init(interp);
    82         -	if (tcl_ret != TCL_OK) {
    83         -		fprintf(stderr, "Unable to initialize Tcl.  Aborting.\n");
    84         -
    85         -		return(NULL);
    86         -	}
    87         -
    88         -	tcl_ret = Tcl_Eval(interp, ""
    89         -#include "appfsd.tcl.h"
    90         -	"");
    91         -	if (tcl_ret != TCL_OK) {
    92         -		fprintf(stderr, "Unable to initialize Tcl AppFS script.  Aborting.\n");
    93         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
    94         -
    95         -		return(NULL);
    96         -	}
    97         -
    98         -	if (Tcl_SetVar(interp, "::appfs::cachedir", cachedir, TCL_GLOBAL_ONLY) == NULL) {
    99         -		fprintf(stderr, "Unable to set cache directory.  This should never fail.\n");
   100         -
   101         -		return(NULL);
   102         -	}
   103         -
   104         -	tcl_ret = Tcl_Eval(interp, "::appfs::init");
   105         -	if (tcl_ret != TCL_OK) {
   106         -		fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init).  Aborting.\n");
   107         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   108         -
   109         -		return(NULL);
   110         -	}
   111         -
   112         -	return(interp);
   113         -}
   114         -
   115         -static int appfs_Tcl_Eval(Tcl_Interp *interp, int objc, const char *cmd, ...) {
   116         -	Tcl_Obj **objv;
   117         -	const char *arg;
   118         -	va_list argp;
   119         -	int retval;
   120         -	int i;
   121         -
   122         -	objv = (void *) ckalloc(sizeof(*objv) * objc);
   123         -	objv[0] = Tcl_NewStringObj(cmd, -1);
   124         -	Tcl_IncrRefCount(objv[0]);
   125         -
   126         -	va_start(argp, cmd);
   127         -	for (i = 1; i < objc; i++) {
   128         -		arg = va_arg(argp, const char *);
   129         -		objv[i] = Tcl_NewStringObj(arg, -1);
   130         -		Tcl_IncrRefCount(objv[i]);
   131         -	}
   132         -	va_end(argp);
   133         -
   134         -	retval = Tcl_EvalObjv(interp, objc, objv, 0);
   135         -
   136         -	for (i = 0; i < objc; i++) {
   137         -		Tcl_DecrRefCount(objv[i]);
   138         -	}
   139         -
   140         -	ckfree((void *) objv);
   141         -
   142         -	if (retval != TCL_OK) {
   143         -		APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0));
   144         -	}
   145         -
   146         -	return(retval);
   147         -}
   148         -
   149         -static void appfs_update_index(const char *hostname) {
   150         -	Tcl_Interp *interp;
   151         -	int tcl_ret;
   152         -
   153         -	APPFS_DEBUG("Enter: hostname = %s", hostname);
   154         -
   155         -	interp = pthread_getspecific(interpKey);
   156         -	if (interp == NULL) {
   157         -		interp = appfs_create_TclInterp(globalThread.cachedir);
   158         -
   159         -		pthread_setspecific(interpKey, interp);
   160         -	}
   161         -
   162         -	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getindex", hostname);
   163         -	if (tcl_ret != TCL_OK) {
   164         -		APPFS_DEBUG("Call to ::appfs::getindex failed: %s", Tcl_GetStringResult(interp));
   165         -
   166         -		return;
   167         -	}
   168         -
   169         -	return;
   170         -}
   171         -
   172         -static const char *appfs_getfile(const char *hostname, const char *sha1) {
   173         -	Tcl_Interp *interp;
   174         -	char *retval;
   175         -	int tcl_ret;
   176         -
   177         -	interp = pthread_getspecific(interpKey);
   178         -	if (interp == NULL) {
   179         -		interp = appfs_create_TclInterp(globalThread.cachedir);
   180         -
   181         -		pthread_setspecific(interpKey, interp);
   182         -	}
   183         -
   184         -	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::download", hostname, sha1);
   185         -	if (tcl_ret != TCL_OK) {
   186         -		APPFS_DEBUG("Call to ::appfs::download failed: %s", Tcl_GetStringResult(interp));
   187         -
   188         -		return(NULL);
   189         -	}
   190         -
   191         -	retval = strdup(Tcl_GetStringResult(interp));
   192         -
   193         -	return(retval);
   194         -}
   195         -
   196         -static void appfs_update_manifest(const char *hostname, const char *sha1) {
   197         -	Tcl_Interp *interp;
   198         -	int tcl_ret;
   199         -
   200         -	interp = pthread_getspecific(interpKey);
   201         -	if (interp == NULL) {
   202         -		interp = appfs_create_TclInterp(globalThread.cachedir);
   203         -
   204         -		pthread_setspecific(interpKey, interp);
   205         -	}
   206         -
   207         -	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::getpkgmanifest", hostname, sha1);
   208         -	if (tcl_ret != TCL_OK) {
   209         -		APPFS_DEBUG("Call to ::appfs::getpkgmanifest failed: %s", Tcl_GetStringResult(interp));
   210         -
   211         -		return;
   212         -	}
   213         -
   214         -	return;
   215         -}
   216         -
   217         -#define appfs_free_list_type(id, type) static void appfs_free_list_ ## id(type *head) { \
   218         -	type *obj, *next; \
   219         -	for (obj = head; obj; obj = next) { \
   220         -		next = obj->_next; \
   221         -		ckfree((void *) obj); \
   222         -	} \
   223         -}
   224         -
   225         -appfs_free_list_type(children, struct appfs_children)
   226         -
   227         -static int appfs_getchildren_cb(void *_head, int columns, char **values, char **names) {
   228         -	struct appfs_children **head_p, *obj;
   229         -
   230         -	head_p = _head;
   231         -
   232         -	obj = (void *) ckalloc(sizeof(*obj));
   233         -
   234         -	snprintf(obj->name, sizeof(obj->name), "%s", values[0]);
   235         -
   236         -	if (*head_p == NULL) {
   237         -		obj->counter = 0;
   238         -	} else {
   239         -		obj->counter = (*head_p)->counter + 1;
   240         -	}
   241         -
   242         -	obj->_next = *head_p;
   243         -	*head_p = obj;
   244         -
   245         -	return(0);
   246         -	
   247         -}
   248         -
   249         -static struct appfs_children *appfs_getchildren(const char *hostname, const char *package_hash, const char *path, int *children_count_p) {
   250         -	struct appfs_children *head = NULL;
   251         -	char *sql;
   252         -	int sqlite_ret;
   253         -
   254         -	if (children_count_p == NULL) {
   255         -		return(NULL);
   256         -	}
   257         -
   258         -	appfs_update_index(hostname);
   259         -	appfs_update_manifest(hostname, package_hash);
   260         -
   261         -	sql = sqlite3_mprintf("SELECT file_name FROM files WHERE package_sha1 = %Q AND file_directory = %Q;", package_hash, path);
   262         -	if (sql == NULL) {
   263         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   264         -
   265         -		return(NULL);
   266         -	}
   267         -
   268         -	APPFS_DEBUG("SQL: %s", sql);
   269         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_getchildren_cb, &head, NULL);
   270         -	sqlite3_free(sql);
   271         -
   272         -	if (sqlite_ret != SQLITE_OK) {
   273         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   274         -
   275         -		return(NULL);
   276         -	}
   277         -
   278         -	if (head != NULL) {
   279         -		*children_count_p = head->counter + 1;
   280         -	}
   281         -
   282         -	return(head);
   283         -}
   284         -
   285         -static int appfs_sqlite3_query_cb(void *_cb_handle, int columns, char **values, char **names) {
   286         -	struct appfs_sqlite3_query_cb_handle *cb_handle;
   287         -	struct appfs_children *obj;
   288         -
   289         -	cb_handle = _cb_handle;
   290         -
   291         -	obj = (void *) ckalloc(sizeof(*obj));
   292         -
   293         -	switch (cb_handle->argc) {
   294         -		case 1:
   295         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0]);
   296         -			break;
   297         -		case 2:
   298         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0], values[1]);
   299         -			break;
   300         -		case 3:
   301         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0], values[1], values[2]);
   302         -			break;
   303         -		case 4:
   304         -			snprintf(obj->name, sizeof(obj->name), cb_handle->fmt, values[0], values[1], values[2], values[3]);
   305         -			break;
   306         -	}
   307         -
   308         -	if (cb_handle->head == NULL) {
   309         -		obj->counter = 0;
   310         -	} else {
   311         -		obj->counter = cb_handle->head->counter + 1;
   312         -	}
   313         -
   314         -	obj->_next = cb_handle->head;
   315         -	cb_handle->head = obj;
   316         -
   317         -	return(0);
   318         -}
   319         -
   320         -static struct appfs_children *appfs_sqlite3_query(char *sql, int argc, const char *fmt, int *results_count_p) {
   321         -	struct appfs_sqlite3_query_cb_handle cb_handle;
   322         -	int sqlite_ret;
   323         -
   324         -	if (results_count_p == NULL) {
   325         -		return(NULL);
   326         -	}
   327         -
   328         -	if (sql == NULL) {
   329         -		APPFS_DEBUG("Call to sqlite3_mprintf probably failed.");
   330         -
   331         -		return(NULL);
   332         -	}
   333         -
   334         -	if (fmt == NULL) {
   335         -		fmt = "%s";
   336         -	}
   337         -
   338         -	cb_handle.head = NULL;
   339         -	cb_handle.argc = argc;
   340         -	cb_handle.fmt  = fmt;
   341         -
   342         -	APPFS_DEBUG("SQL: %s", sql);
   343         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_sqlite3_query_cb, &cb_handle, NULL);
   344         -	sqlite3_free(sql);
   345         -
   346         -	if (sqlite_ret != SQLITE_OK) {
   347         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   348         -
   349         -		return(NULL);
   350         -	}
   351         -
   352         -	if (cb_handle.head != NULL) {
   353         -		*results_count_p = cb_handle.head->counter + 1;
   354         -	}
   355         -
   356         -	return(cb_handle.head);
   357         -}
   358         -
   359         -static int appfs_lookup_package_hash_cb(void *_retval, int columns, char **values, char **names) {
   360         -	char **retval = _retval;
   361         -
   362         -	*retval = strdup(values[0]);
   363         -
   364         -	return(0);
   365         -}
   366         -
   367         -static char *appfs_lookup_package_hash(const char *hostname, const char *package, const char *os, const char *cpuArch, const char *version) {
   368         -	char *sql;
   369         -	char *retval = NULL;
   370         -	int sqlite_ret;
   371         -
   372         -	appfs_update_index(hostname);
   373         -
   374         -	sql = sqlite3_mprintf("SELECT sha1 FROM packages WHERE hostname = %Q AND package = %Q AND os = %Q AND cpuArch = %Q AND version = %Q;",
   375         -		hostname,
   376         -		package,
   377         -		os,
   378         -		cpuArch,
   379         -		version
   380         -	);
   381         -	if (sql == NULL) {
   382         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   383         -
   384         -		return(NULL);
   385         -	}
   386         -
   387         -	APPFS_DEBUG("SQL: %s", sql);
   388         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_lookup_package_hash_cb, &retval, NULL);
   389         -	sqlite3_free(sql);
   390         -
   391         -	if (sqlite_ret != SQLITE_OK) {
   392         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   393         -
   394         -		return(NULL);
   395         -	}
   396         -
   397         -	return(retval);
   398         -}
   399         -
   400         -static int appfs_getfileinfo_cb(void *_pathinfo, int columns, char **values, char **names) {
   401         -	struct appfs_pathinfo *pathinfo = _pathinfo;
   402         -	const char *type, *time, *source, *size, *perms, *sha1;
   403         -
   404         -	type = values[0];
   405         -	time = values[1];
   406         -	source = values[2];
   407         -	size = values[3];
   408         -	perms = values[4];
   409         -	sha1 = values[5];
   410         -
   411         -	pathinfo->time = strtoull(time, NULL, 10);
   412         -
   413         -	if (strcmp(type, "file") == 0) {
   414         -		pathinfo->type = APPFS_PATHTYPE_FILE;
   415         -
   416         -		if (!size) {
   417         -			size = "0";
   418         -		}
   419         -
   420         -		if (!perms) {
   421         -			perms = "";
   422         -		}
   423         -
   424         -		if (!sha1) {
   425         -			sha1 = "";
   426         -		}
   427         -
   428         -		pathinfo->typeinfo.file.size = strtoull(size, NULL, 10);
   429         -		snprintf(pathinfo->typeinfo.file.sha1, sizeof(pathinfo->typeinfo.file.sha1), "%s", sha1);
   430         -
   431         -		if (strcmp(perms, "x") == 0) {
   432         -			pathinfo->typeinfo.file.executable = 1;
   433         -		} else {
   434         -			pathinfo->typeinfo.file.executable = 0;
   435         -		}
   436         -
   437         -		return(0);
   438         -	}
   439         -
   440         -	if (strcmp(type, "directory") == 0) {
   441         -		pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   442         -		pathinfo->typeinfo.dir.childcount = 0;
   443         -
   444         -		return(0);
   445         -	}
   446         -
   447         -	if (strcmp(type, "symlink") == 0) {
   448         -		pathinfo->type = APPFS_PATHTYPE_SYMLINK;
   449         -		pathinfo->typeinfo.dir.childcount = 0;
   450         -
   451         -		if (!source) {
   452         -			source = ".BADLINK";
   453         -		}
   454         -
   455         -		pathinfo->typeinfo.symlink.size = strlen(source);
   456         -		snprintf(pathinfo->typeinfo.symlink.source, sizeof(pathinfo->typeinfo.symlink.source), "%s", source);
   457         -
   458         -		return(0);
   459         -	}
   460         -
   461         -	return(0);
   462         -
   463         -	/* Until this is used, prevent the compiler from complaining */
   464         -	source = source;
   465         -}
   466         -
   467         -static int appfs_getfileinfo(const char *hostname, const char *package_hash, const char *_path, struct appfs_pathinfo *pathinfo) {
   468         -	char *directory, *file, *path;
   469         -	char *sql;
   470         -	int sqlite_ret;
   471         -
   472         -	if (pathinfo == NULL) {
   473         -		return(-EIO);
   474         -	}
   475         -
   476         -	appfs_update_index(hostname);
   477         -	appfs_update_manifest(hostname, package_hash);
   478         -
   479         -	path = strdup(_path);
   480         -	directory = path;
   481         -	file = strrchr(path, '/');
   482         -	if (file == NULL) {
   483         -		file = path;
   484         -		directory = "";
   485         -	} else {
   486         -		*file = '\0';
   487         -		file++;
   488         -	}
   489         -
   490         -	sql = sqlite3_mprintf("SELECT type, time, source, size, perms, file_sha1 FROM files WHERE package_sha1 = %Q AND file_directory = %Q AND file_name = %Q;", package_hash, directory, file);
   491         -	if (sql == NULL) {
   492         -		APPFS_DEBUG("Call to sqlite3_mprintf failed.");
   493         -
   494         -		free(path);
   495         -
   496         -		return(-EIO);
   497         -	}
   498         -
   499         -	free(path);
   500         -
   501         -	pathinfo->type = APPFS_PATHTYPE_INVALID;
   502         -
   503         -	APPFS_DEBUG("SQL: %s", sql);
   504         -	sqlite_ret = sqlite3_exec(globalThread.db, sql, appfs_getfileinfo_cb, pathinfo, NULL);
   505         -	sqlite3_free(sql);
   506         -
   507         -	if (sqlite_ret != SQLITE_OK) {
   508         -		APPFS_DEBUG("Call to sqlite3_exec failed.");
   509         -
   510         -		return(-EIO);
   511         -	}
   512         -
   513         -	if (pathinfo->type == APPFS_PATHTYPE_INVALID) {
   514         -		return(-ENOENT);
   515         -	}
   516         -
   517         -	return(0);
   518         -}
   519         -
   520         -static int appfs_get_path_info_sql(char *sql, int argc, const char *fmt, struct appfs_pathinfo *pathinfo, struct appfs_children **children) {
   521         -	struct appfs_children *node, *dir_children, *dir_child;
   522         -	int dir_children_count = 0;
   523         -
   524         -	dir_children = appfs_sqlite3_query(sql, argc, fmt, &dir_children_count);
   525         -
   526         -	if (dir_children == NULL || dir_children_count == 0) {
   527         -		return(-ENOENT);
   528         -	}
   529         -
   530         -	/* Request for a single hostname */
   531         -	pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   532         -	pathinfo->typeinfo.dir.childcount = dir_children_count;
   533         -	pathinfo->time = globalThread.boottime;
   534         -
   535         -	if (children) {
   536         -		for (dir_child = dir_children; dir_child; dir_child = dir_child->_next) {
   537         -			node = (void *) ckalloc(sizeof(*node));
   538         -			node->_next = *children;
   539         -			strcpy(node->name, dir_child->name);
   540         -			*children = node;
   541         -		}
   542         -	}
   543         -
   544         -	appfs_free_list_children(dir_children);
   545         -
   546         -	return(0);
   547         -}
   548         -/* Get information about a path, and optionally list children */
   549         -static int appfs_get_path_info(const char *_path, struct appfs_pathinfo *pathinfo, struct appfs_children **children) {
   550         -	struct appfs_children *dir_children;
   551         -	char *hostname, *packagename, *os_cpuArch, *os, *cpuArch, *version;
   552         -	char *path, *path_s;
   553         -	char *package_hash;
   554         -	char *sql;
   555         -	int files_count;
   556         -	int fileinfo_ret, retval;
   557         -
   558         -	if (children) {
   559         -		*children = NULL;
   560         -	}
   561         -
   562         -	if (_path == NULL) {
   563         -		return(-ENOENT);
   564         -	}
   565         -
   566         -	if (_path[0] != '/') {
   567         -		return(-ENOENT);
   568         -	}
   569         -
   570         -	if (_path[1] == '\0') {
   571         -		/* Request for the root directory */
   572         -		pathinfo->hostname[0] = '\0';
   573         -
   574         -		sql = sqlite3_mprintf("SELECT DISTINCT hostname FROM packages;");
   575         -
   576         -		retval = appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children);
   577         -
   578         -		/* The root directory always exists, even if it has no subordinates */
   579         -		if (retval != 0) {
   580         -			pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   581         -			pathinfo->typeinfo.dir.childcount = 0;
   582         -			pathinfo->time = globalThread.boottime;
   583         -
   584         -			retval = 0;
   585         -		}
   586         -
   587         -		return(retval);
   588         -	}
   589         -
   590         -	path = strdup(_path);
   591         -	path_s = path;
   592         -
   593         -	hostname = path + 1;
   594         -	packagename = strchr(hostname, '/');
   595         -
   596         -	if (packagename != NULL) {
   597         -		*packagename = '\0';
   598         -		packagename++;
   599         -	}
   600         -
   601         -	snprintf(pathinfo->hostname, sizeof(pathinfo->hostname), "%s", hostname);
   602         -
   603         -	if (packagename == NULL) {
   604         -		appfs_update_index(hostname);
   605         -
   606         -		sql = sqlite3_mprintf("SELECT DISTINCT package FROM packages WHERE hostname = %Q;", hostname);
   607         -
   608         -		free(path_s);
   609         -
   610         -		return(appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children));
   611         -	}
   612         -
   613         -	os_cpuArch = strchr(packagename, '/');
   614         -
   615         -	if (os_cpuArch != NULL) {
   616         -		*os_cpuArch = '\0';
   617         -		os_cpuArch++;
   618         -	}
   619         -
   620         -	if (os_cpuArch == NULL) {
   621         -		appfs_update_index(hostname);
   622         -
   623         -		sql = sqlite3_mprintf("SELECT DISTINCT os, cpuArch FROM packages WHERE hostname = %Q AND package = %Q;", hostname, packagename);
   624         -
   625         -		free(path_s);
   626         -
   627         -		return(appfs_get_path_info_sql(sql, 2, "%s-%s", pathinfo, children));
   628         -	}
   629         -
   630         -	version = strchr(os_cpuArch, '/');
   631         -
   632         -	if (version != NULL) {
   633         -		*version = '\0';
   634         -		version++;
   635         -	}
   636         -
   637         -	os = os_cpuArch;
   638         -	cpuArch = strchr(os_cpuArch, '-');
   639         -	if (cpuArch) {
   640         -		*cpuArch = '\0';
   641         -		cpuArch++;
   642         -	}
   643         -
   644         -	if (version == NULL) {
   645         -		/* Request for version list for a package on an OS/CPU */
   646         -		appfs_update_index(hostname);
   647         -
   648         -		sql = sqlite3_mprintf("SELECT DISTINCT version FROM packages WHERE hostname = %Q AND package = %Q AND os = %Q and cpuArch = %Q;", hostname, packagename, os, cpuArch);
   649         -
   650         -		free(path_s);
   651         -
   652         -		return(appfs_get_path_info_sql(sql, 1, NULL, pathinfo, children));
   653         -	}
   654         -
   655         -	path = strchr(version, '/');
   656         -	if (path == NULL) {
   657         -		path = "";
   658         -	} else {
   659         -		*path = '\0';
   660         -		path++;
   661         -	}
   662         -
   663         -	/* Request for a file in a specific package */
   664         -	APPFS_DEBUG("Requesting information for hostname = %s, package = %s, os = %s, cpuArch = %s, version = %s, path = %s", 
   665         -		hostname, packagename, os, cpuArch, version, path
   666         -	);
   667         -
   668         -	package_hash = appfs_lookup_package_hash(hostname, packagename, os, cpuArch, version);
   669         -	if (package_hash == NULL) {
   670         -		free(path_s);
   671         -
   672         -		return(-ENOENT);
   673         -	}
   674         -
   675         -	APPFS_DEBUG("  ... which hash a hash of %s", package_hash);
   676         -
   677         -	appfs_update_manifest(hostname, package_hash);
   678         -
   679         -	if (strcmp(path, "") == 0) {
   680         -		pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   681         -		pathinfo->time = globalThread.boottime;
   682         -	} else {
   683         -		fileinfo_ret = appfs_getfileinfo(hostname, package_hash, path, pathinfo);
   684         -		if (fileinfo_ret != 0) {
   685         -			free(path_s);
   686         -
   687         -			return(fileinfo_ret);
   688         -		}
   689         -	}
   690         -
   691         -	if (pathinfo->type == APPFS_PATHTYPE_DIRECTORY) {
   692         -		dir_children = appfs_getchildren(hostname, package_hash, path, &files_count);
   693         -
   694         -		if (dir_children != NULL) {
   695         -			pathinfo->typeinfo.dir.childcount = files_count;
   696         -		}
   697         -
   698         -		if (children) {
   699         -			*children = dir_children;
   700         -		}
   701         -	}
   702         -
   703         -	free(path_s);
   704         -
   705         -	return(0);
   706         -}
   707         -
   708         -static int appfs_fuse_readlink(const char *path, char *buf, size_t size) {
   709         -	struct appfs_pathinfo pathinfo;
   710         -	int res = 0;
   711         -
   712         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
   713         -
   714         -	pathinfo.type = APPFS_PATHTYPE_INVALID;
   715         -
   716         -	res = appfs_get_path_info(path, &pathinfo, NULL);
   717         -	if (res != 0) {
   718         -		return(res);
   719         -	}
   720         -
   721         -	if (pathinfo.type != APPFS_PATHTYPE_SYMLINK) {
   722         -		return(-EINVAL);
   723         -	}
   724         -
   725         -	if ((strlen(pathinfo.typeinfo.symlink.source) + 1) > size) {
   726         -		return(-ENAMETOOLONG);
   727         -	}
   728         -
   729         -	memcpy(buf, pathinfo.typeinfo.symlink.source, strlen(pathinfo.typeinfo.symlink.source) + 1);
   730         -
   731         -	return(0);
   732         -}
   733         -
   734         -static int appfs_fuse_getattr(const char *path, struct stat *stbuf) {
   735         -	struct appfs_pathinfo pathinfo;
   736         -	int res = 0;
   737         -
   738         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
   739         -
   740         -	pathinfo.type = APPFS_PATHTYPE_INVALID;
   741         -
   742         -	res = appfs_get_path_info(path, &pathinfo, NULL);
   743         -	if (res != 0) {
   744         -		return(res);
   745         -	}
   746         -
   747         -	memset(stbuf, 0, sizeof(struct stat));
   748         -
   749         -	stbuf->st_mtime = pathinfo.time;
   750         -	stbuf->st_ctime = pathinfo.time;
   751         -	stbuf->st_atime = pathinfo.time;
   752         -
   753         -	switch (pathinfo.type) {
   754         -		case APPFS_PATHTYPE_DIRECTORY:
   755         -			stbuf->st_mode = S_IFDIR | 0555;
   756         -			stbuf->st_nlink = 2 + pathinfo.typeinfo.dir.childcount;
   757         -			break;
   758         -		case APPFS_PATHTYPE_FILE:
   759         -			if (pathinfo.typeinfo.file.executable) {
   760         -				stbuf->st_mode = S_IFREG | 0555;
   761         -			} else {
   762         -				stbuf->st_mode = S_IFREG | 0444;
   763         -			}
   764         -
   765         -			stbuf->st_nlink = 1;
   766         -			stbuf->st_size = pathinfo.typeinfo.file.size;
   767         -			break;
   768         -		case APPFS_PATHTYPE_SYMLINK:
   769         -			stbuf->st_mode = S_IFLNK | 0555;
   770         -			stbuf->st_nlink = 1;
   771         -			stbuf->st_size = pathinfo.typeinfo.symlink.size;
   772         -			break;
   773         -		case APPFS_PATHTYPE_INVALID:
   774         -			res = -EIO;
   775         -
   776         -			break;
   777         -	}
   778         -
   779         -	return res;
   780         -}
   781         -
   782         -static int appfs_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
   783         -	struct appfs_pathinfo pathinfo;
   784         -	struct appfs_children *children, *child;
   785         -	int retval;
   786         -
   787         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
   788         -
   789         -	retval = appfs_get_path_info(path, &pathinfo, &children);
   790         -	if (retval != 0) {
   791         -		return(retval);
   792         -	}
   793         -
   794         -	filler(buf, ".", NULL, 0);
   795         -	filler(buf, "..", NULL, 0);
   796         -
   797         -	for (child = children; child; child = child->_next) {
   798         -		filler(buf, child->name, NULL, 0);
   799         -	}
   800         -
   801         -	appfs_free_list_children(children);
   802         -
   803         -	return(0);
   804         -}
   805         -
   806         -static int appfs_fuse_open(const char *path, struct fuse_file_info *fi) {
   807         -	struct appfs_pathinfo pathinfo;
   808         -	const char *real_path;
   809         -	int fh;
   810         -	int gpi_ret;
   811         -
   812         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
   813         -
   814         -	if ((fi->flags & 3) != O_RDONLY) {
   815         -                return(-EACCES);
   816         -	}
   817         -
   818         -	gpi_ret = appfs_get_path_info(path, &pathinfo, NULL);
   819         -	if (gpi_ret != 0) {
   820         -		return(gpi_ret);
   821         -	}
   822         -
   823         -	if (pathinfo.type == APPFS_PATHTYPE_DIRECTORY) {
   824         -		return(-EISDIR);
   825         -	}
   826         -
   827         -	real_path = appfs_getfile(pathinfo.hostname, pathinfo.typeinfo.file.sha1);
   828         -	if (real_path == NULL) {
   829         -		return(-EIO);
   830         -	}
   831         -
   832         -	fh = open(real_path, O_RDONLY);
   833         -	free((void *) real_path);
   834         -	if (fh < 0) {
   835         -		return(-EIO);
   836         -	}
   837         -
   838         -	fi->fh = fh;
   839         -
   840         -	return(0);
   841         -}
   842         -
   843         -static int appfs_fuse_close(const char *path, struct fuse_file_info *fi) {
   844         -	int close_ret;
   845         -
   846         -	close_ret = close(fi->fh);
   847         -	if (close_ret != 0) {
   848         -		return(-EIO);
   849         -	}
   850         -
   851         -	return(0);
   852         -}
   853         -
   854         -static int appfs_fuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
   855         -	off_t lseek_ret;
   856         -	ssize_t read_ret;
   857         -
   858         -	APPFS_DEBUG("Enter (path = %s, ...)", path);
   859         -
   860         -	lseek_ret = lseek(fi->fh, offset, SEEK_SET);
   861         -	if (lseek_ret != offset) {
   862         -		return(-EIO);
   863         -	}
   864         -
   865         -	read_ret = read(fi->fh, buf, size);
   866         -
   867         -	return(read_ret);
   868         -}
   869         -
   870         -static struct fuse_operations appfs_oper = {
   871         -	.getattr   = appfs_fuse_getattr,
   872         -	.readdir   = appfs_fuse_readdir,
   873         -	.readlink  = appfs_fuse_readlink,
   874         -	.open      = appfs_fuse_open,
   875         -	.release   = appfs_fuse_close,
   876         -	.read      = appfs_fuse_read
   877         -};
   878         -
   879         -int main(int argc, char **argv) {
   880         -	const char *cachedir = APPFS_CACHEDIR;
   881         -	char dbfilename[1024];
   882         -	int pthread_ret, snprintf_ret, sqlite_ret;
   883         -
   884         -	globalThread.cachedir = cachedir;
   885         -	globalThread.boottime = time(NULL);
   886         -
   887         -	pthread_ret = pthread_key_create(&interpKey, NULL);
   888         -	if (pthread_ret != 0) {
   889         -		fprintf(stderr, "Unable to create TSD key for Tcl.  Aborting.\n");
   890         -
   891         -		return(1);
   892         -	}
   893         -
   894         -	snprintf_ret = snprintf(dbfilename, sizeof(dbfilename), "%s/%s", cachedir, "cache.db");
   895         -	if (snprintf_ret >= sizeof(dbfilename)) {
   896         -		fprintf(stderr, "Unable to set database filename.  Aborting.\n");
   897         -
   898         -		return(1);
   899         -	}
   900         -
   901         -	sqlite_ret = sqlite3_open(dbfilename, &globalThread.db);
   902         -	if (sqlite_ret != SQLITE_OK) {
   903         -		fprintf(stderr, "Unable to open database: %s\n", dbfilename);
   904         -
   905         -		return(1);
   906         -	}
   907         -
   908         -	return(fuse_main(argc, argv, &appfs_oper, NULL));
   909         -}
   910         - 

Deleted appfsd.tcl version [fc1c954390].

     1         -#! /usr/bin/env tclsh
     2         -
     3         -package require http 2.7
     4         -package require sqlite3
     5         -
     6         -namespace eval ::appfs {
     7         -	variable cachedir "/tmp/appfs-cache"
     8         -	variable ttl 3600
     9         -	variable nttl 60
    10         -
    11         -	proc _hash_sep {hash {seps 4}} {
    12         -		for {set idx 0} {$idx < $seps} {incr idx} {
    13         -			append retval "[string range $hash [expr {$idx * 2}] [expr {($idx * 2) + 1}]]/"
    14         -		}
    15         -		append retval "[string range $hash [expr {$idx * 2}] end]"
    16         -
    17         -		return $retval
    18         -	}
    19         -
    20         -	proc _cachefile {url key {keyIsHash 1}} {
    21         -		set filekey $key
    22         -		if {$keyIsHash} {
    23         -			set filekey [_hash_sep $filekey]
    24         -		}
    25         -
    26         -		set file [file join $::appfs::cachedir $filekey]
    27         -
    28         -		file mkdir [file dirname $file]
    29         -
    30         -		if {![file exists $file]} {
    31         -			set tmpfile "${file}.new"
    32         -
    33         -			set fd [open $tmpfile "w"]
    34         -			fconfigure $fd -translation binary
    35         -
    36         -			catch {
    37         -				set token [::http::geturl $url -channel $fd -binary true]
    38         -			}
    39         -
    40         -			if {[info exists token]} {
    41         -				set ncode [::http::ncode $token]
    42         -				::http::reset $token
    43         -			} else {
    44         -				set ncode "900"
    45         -			}
    46         -
    47         -			close $fd
    48         -
    49         -			if {$keyIsHash} {
    50         -				catch {
    51         -					set hash [string tolower [exec openssl sha1 $tmpfile]]
    52         -					regsub {.*= *} $hash {} hash
    53         -				}
    54         -			} else {
    55         -				set hash $key
    56         -			}
    57         -
    58         -			if {$ncode == "200" && $hash == $key} {
    59         -				file rename -force -- $tmpfile $file
    60         -			} else {
    61         -				file delete -force -- $tmpfile
    62         -			}
    63         -		}
    64         -
    65         -		return $file
    66         -	}
    67         -
    68         -
    69         -	proc _isHash {value} {
    70         -		set value [string tolower $value]
    71         -
    72         -		if {[string length $value] != 40} {
    73         -			return false
    74         -		}
    75         -
    76         -		if {![regexp {^[0-9a-f]*$} $value]} {
    77         -			return false
    78         -		}
    79         -
    80         -		return true
    81         -	}
    82         -
    83         -	proc _db {args} {
    84         -		return [uplevel 1 [list ::appfs::db {*}$args]]
    85         -	}
    86         -
    87         -	proc _normalizeOS {os} {
    88         -		set os [string tolower [string trim $os]]
    89         -
    90         -		switch -- $os {
    91         -			"linux" - "freebsd" - "openbsd" - "netbsd" {
    92         -				return $os
    93         -			}
    94         -			"sunos" {
    95         -				return "solaris"
    96         -			}
    97         -		}
    98         -
    99         -		return -code error "Unable to normalize OS: $os"
   100         -	}
   101         -
   102         -	proc _normalizeCPU {cpu} {
   103         -		set cpu [string tolower [string trim $cpu]]
   104         -
   105         -		switch -glob -- $cpu {
   106         -			"i?86" {
   107         -				return "ix86"
   108         -			}
   109         -			"x86_64" {
   110         -				return $cpu
   111         -			}
   112         -		}
   113         -
   114         -		return -code error "Unable to normalize CPU: $cpu"
   115         -	}
   116         -
   117         -	proc init {} {
   118         -		if {[info exists ::appfs::init_called]} {
   119         -			return
   120         -		}
   121         -
   122         -		set ::appfs::init_called 1
   123         -
   124         -		if {![info exists ::appfs::db]} {
   125         -			file mkdir $::appfs::cachedir
   126         -
   127         -			sqlite3 ::appfs::db [file join $::appfs::cachedir cache.db]
   128         -		}
   129         -
   130         -		_db eval {CREATE TABLE IF NOT EXISTS sites(hostname PRIMARY KEY, lastUpdate, ttl);}
   131         -		_db eval {CREATE TABLE IF NOT EXISTS packages(hostname, sha1, package, version, os, cpuArch, isLatest, haveManifest);}
   132         -		_db eval {CREATE TABLE IF NOT EXISTS files(package_sha1, type, time, source, size, perms, file_sha1, file_name, file_directory);}
   133         -	}
   134         -
   135         -	proc download {hostname hash {method sha1}} {
   136         -		set url "http://$hostname/appfs/$method/$hash"
   137         -		set file [_cachefile $url $hash]
   138         -
   139         -		if {![file exists $file]} {
   140         -			return -code error "Unable to fetch"
   141         -		}
   142         -
   143         -		return $file
   144         -	}
   145         -
   146         -	proc getindex {hostname} {
   147         -		set now [clock seconds]
   148         -
   149         -		set lastUpdates [_db eval {SELECT lastUpdate, ttl FROM sites WHERE hostname = $hostname LIMIT 1;}]
   150         -		if {[llength $lastUpdates] == 0} {
   151         -			set lastUpdate 0
   152         -			set ttl 0
   153         -		} else {
   154         -			set lastUpdate [lindex $lastUpdates 0]
   155         -			set ttl [lindex $lastUpdates 1]
   156         -		}
   157         -
   158         -		if {$now < ($lastUpdate + $ttl)} {
   159         -			return COMPLETE
   160         -		}
   161         -
   162         -		if {[string match "*\[/~\]*" $hostname]} {
   163         -			return -code error "Invalid hostname"
   164         -		}
   165         -
   166         -		set url "http://$hostname/appfs/index"
   167         -
   168         -		catch {
   169         -			set token [::http::geturl $url]
   170         -			if {[::http::ncode $token] == "200"} {
   171         -				set indexhash_data [::http::data $token]
   172         -			}
   173         -			::http::reset $token
   174         -			$token cleanup
   175         -		}
   176         -
   177         -		if {![info exists indexhash_data]} {
   178         -			# Cache this result for 60 seconds
   179         -			_db eval {INSERT OR REPLACE INTO sites (hostname, lastUpdate, ttl) VALUES ($hostname, $now, $::appfs::nttl);}
   180         -
   181         -			return -code error "Unable to fetch $url"
   182         -		}
   183         -
   184         -		set indexhash [lindex [split $indexhash_data ","] 0]
   185         -
   186         -		if {![_isHash $indexhash]} {
   187         -			return -code error "Invalid hash: $indexhash"
   188         -		}
   189         -
   190         -		set file [download $hostname $indexhash]
   191         -		set fd [open $file]
   192         -		set data [read $fd]
   193         -		close $fd
   194         -
   195         -		set curr_packages [list]
   196         -		foreach line [split $data "\n"] {
   197         -			set line [string trim $line]
   198         -
   199         -			if {[string match "*/*" $line]} {
   200         -				continue
   201         -			}
   202         -
   203         -			if {$line == ""} {
   204         -				continue
   205         -			}
   206         -
   207         -			set work [split $line ","]
   208         -
   209         -			unset -nocomplain pkgInfo
   210         -			set pkgInfo(package)  [lindex $work 0]
   211         -			set pkgInfo(version)  [lindex $work 1]
   212         -			set pkgInfo(os)       [_normalizeOS [lindex $work 2]]
   213         -			set pkgInfo(cpuArch)  [_normalizeCPU [lindex $work 3]]
   214         -			set pkgInfo(hash)     [string tolower [lindex $work 4]]
   215         -			set pkgInfo(hash_type) "sha1"
   216         -			set pkgInfo(isLatest) [expr {!![lindex $work 5]}]
   217         -
   218         -			if {![_isHash $pkgInfo(hash)]} {
   219         -				continue
   220         -			}
   221         -
   222         -			lappend curr_packages $pkgInfo(hash)
   223         -
   224         -			# Do not do any additional work if we already have this package
   225         -			set existing_packages [_db eval {SELECT package FROM packages WHERE hostname = $hostname AND sha1 = $pkgInfo(hash);}]
   226         -			if {[lsearch -exact $existing_packages $pkgInfo(package)] != -1} {
   227         -				continue
   228         -			}
   229         -
   230         -			if {$pkgInfo(isLatest)} {
   231         -				_db eval {UPDATE packages SET isLatest = 0 WHERE hostname = $hostname AND package = $pkgInfo($package) AND os = $pkgInfo($package) AND cpuArch = $pkgInfo(cpuArch);}
   232         -			}
   233         -
   234         -			_db eval {INSERT INTO packages (hostname, sha1, package, version, os, cpuArch, isLatest, haveManifest) VALUES ($hostname, $pkgInfo(hash), $pkgInfo(package), $pkgInfo(version), $pkgInfo(os), $pkgInfo(cpuArch), $pkgInfo(isLatest), 0);}
   235         -		}
   236         -
   237         -		# Look for packages that have been deleted
   238         -		set found_packages [_db eval {SELECT sha1 FROM packages WHERE hostname = $hostname;}]
   239         -		foreach package $found_packages {
   240         -			set found_packages_arr($package) 1
   241         -		}
   242         -
   243         -		foreach package $curr_packages {
   244         -			unset -nocomplain found_packages_arr($package)
   245         -		}
   246         -
   247         -		foreach package [array names found_packages_arr] {
   248         -			_db eval {DELETE FROM packages WHERE hostname = $hostname AND sha1 = $package;}
   249         -		}
   250         -
   251         -		_db eval {INSERT OR REPLACE INTO sites (hostname, lastUpdate, ttl) VALUES ($hostname, $now, $::appfs::ttl);}
   252         -
   253         -		return COMPLETE
   254         -	}
   255         -
   256         -	proc getpkgmanifest {hostname package_sha1} {
   257         -		set haveManifests [_db eval {SELECT haveManifest FROM packages WHERE sha1 = $package_sha1 LIMIT 1;}]
   258         -		set haveManifest [lindex $haveManifests 0]
   259         -
   260         -		if {$haveManifest} {
   261         -			return COMPLETE
   262         -		}
   263         -
   264         -		if {![_isHash $package_sha1]} {
   265         -			return FAIL
   266         -		}
   267         -
   268         -		set file [download $hostname $package_sha1]
   269         -		set fd [open $file]
   270         -		set pkgdata [read $fd]
   271         -		close $fd
   272         -
   273         -		_db transaction {
   274         -			foreach line [split $pkgdata "\n"] {
   275         -				set line [string trim $line]
   276         -
   277         -				if {$line == ""} {
   278         -					continue
   279         -				}
   280         -
   281         -				set work [split $line ","]
   282         -
   283         -				unset -nocomplain fileInfo
   284         -				set fileInfo(type) [lindex $work 0]
   285         -				set fileInfo(time) [lindex $work 1]
   286         -
   287         -				set work [lrange $work 2 end]
   288         -				switch -- $fileInfo(type) {
   289         -					"file" {
   290         -						set fileInfo(size) [lindex $work 0]
   291         -						set fileInfo(perms) [lindex $work 1]
   292         -						set fileInfo(sha1) [lindex $work 2]
   293         -
   294         -						set work [lrange $work 3 end]
   295         -					}
   296         -					"symlink" {
   297         -						set fileInfo(source) [lindex $work 0]
   298         -						set work [lrange $work 1 end]
   299         -					}
   300         -				}
   301         -
   302         -				set fileInfo(name) [join $work ","]
   303         -				set fileInfo(name) [split [string trim $fileInfo(name) "/"] "/"]
   304         -				set fileInfo(directory) [join [lrange $fileInfo(name) 0 end-1] "/"]
   305         -				set fileInfo(name) [lindex $fileInfo(name) end]
   306         -
   307         -				_db eval {INSERT INTO files (package_sha1, type, time, source, size, perms, file_sha1, file_name, file_directory) VALUES ($package_sha1, $fileInfo(type), $fileInfo(time), $fileInfo(source), $fileInfo(size), $fileInfo(perms), $fileInfo(sha1), $fileInfo(name), $fileInfo(directory) );}
   308         -				_db eval {UPDATE packages SET haveManifest = 1 WHERE sha1 = $package_sha1;}
   309         -			}
   310         -		}
   311         -
   312         -		return COMPLETE
   313         -	}
   314         -}

Added build version [4cb097f703].

            1  +#! /usr/bin/env bash
            2  +
            3  +pkg="$(echo "$1" | sed 's@/*$@@;s@^\.*/*@@')"
            4  +
            5  +if [ -z "${pkg}" ]; then
            6  +	echo "Usage: build <package>" 2>&1
            7  +
            8  +	exit 1
            9  +fi
           10  +
           11  +function determineOsArch() {
           12  +	os="$(uname -s | dd conv=lcase 2>/dev/null)"
           13  +	arch="$(uname -m | dd conv=lcase 2>/dev/null)"
           14  +
           15  +	case "${arch}" in
           16  +		i?86)
           17  +			arch='ix86'
           18  +			;;
           19  +	esac
           20  +}
           21  +
           22  +function determinePrefix() {
           23  +	determineOsArch
           24  +
           25  +	prefixsuffix="${pkg}/${os}-${arch}/${version}"
           26  +	prefix="/opt/appfs/${domain}/${prefixsuffix}"
           27  +	destdir="$(pwd)/INST"
           28  +
           29  +	mkdir "${destdir}" || die
           30  +}
           31  +
           32  +function preconfigure() {
           33  +	:
           34  +}
           35  +
           36  +function postconfigure() {
           37  +	:
           38  +}
           39  +
           40  +function configure() {
           41  +	glibcvers=2.20
           42  +	glibcdir="/opt/appfs/core.appfs.rkeene.org/glibc/platform/${glibcvers}"
           43  +	dynlinker="$(ls "${glibcdir}"/lib/ld-linux*.so.* | tail -n 1)"
           44  +
           45  +	CFLAGS="-I${glibcdir}/include"
           46  +	CPPFLAGS="-I${glibcdir}/include"
           47  +	LDFLAGS="-Wl,--rpath,${glibcdir}/lib -Wl,--dynamic-linker,${dynlinker}"
           48  +	export CFLAGS CPPFLAGS LDFLAGS
           49  +
           50  +	./configure --prefix="${prefix}" --sysconfdir=/etc --localstatedir=/var
           51  +}
           52  +
           53  +function prebuild() {
           54  +	:
           55  +}
           56  +
           57  +function postbuild() {
           58  +	:
           59  +}
           60  +
           61  +function build() {
           62  +	grep "DESTDIR" Makefile || die "Don't know how to build this software"
           63  +
           64  +	make
           65  +}
           66  +
           67  +function preinstall() {
           68  +	:
           69  +}
           70  +
           71  +function postinstall() {
           72  +	:
           73  +}
           74  +
           75  +function install() {
           76  +	make install DESTDIR="${destdir}"
           77  +}
           78  +
           79  +function cleanup() {
           80  +	cd "${workdir}" || exit 1
           81  +	cd .. || exit 1
           82  +	rm -rf "${workdir}"
           83  +}
           84  +
           85  +function die() {
           86  +	local message
           87  +
           88  +	message="$1"
           89  +
           90  +	if [ -n "${message}" ]; then
           91  +		echo "error: ${message}" >&2
           92  +	fi
           93  +
           94  +	cleanup
           95  +
           96  +	exit 1
           97  +}
           98  +
           99  +cd "$(dirname "$(which "$0")")" || exit 1
          100  +
          101  +if [ -f 'build.conf' ]; then
          102  +	. 'build.conf'
          103  +fi
          104  +
          105  +if [ -d "pkgs/${pkg}" ]; then
          106  +	pkgdir="pkgs/${pkg}"
          107  +	pkgfile="${pkgdir}/info"
          108  +else
          109  +	pkgfile="pkgs/${pkg}"
          110  +	pkgdir="${pkgfile}"
          111  +fi
          112  +
          113  +if [ ! -e "${pkgfile}" ]; then
          114  +	echo "Invalid package." >&2
          115  +
          116  +	exit 1
          117  +fi
          118  +
          119  +pkgdate="$(find "${pkgdir}" -type f -printf '%TY%Tm%Td%TH%TM.%TS\n' 2>/dev/null | cut -f 1-2 -d '.' | sort -n | tail -n 1)"
          120  +
          121  +. "${pkgfile}"
          122  +
          123  +archivedir="$(pwd)/ARCHIVE"
          124  +workdir="workdir-$$${RANDOM}${RANDOM}${RANDOM}"
          125  +srcfile="${archivedir}/${pkg}"
          126  +mkdir "${archivedir}" >/dev/null 2>/dev/null
          127  +mkdir "${workdir}" || exit 1
          128  +cd "${workdir}" || exit 1
          129  +workdir="$(pwd)"
          130  +
          131  +if [ ! -e "${srcfile}" ]; then
          132  +	# Download
          133  +	## Cleanup
          134  +	rm -f src.new src
          135  +
          136  +	## Fetch file
          137  +	wget -O src.new "${url}" || exit 1
          138  +
          139  +	## Verify signature
          140  +	src_sha256="$(openssl sha256 'src.new' | sed 's@^.*= @@')"
          141  +	if [ "${src_sha256}" != "${sha256}" ]; then
          142  +		echo "SHA256 mismatch:  Downloaded: ${src_sha256} != Expected: ${sha256}" >&2
          143  +
          144  +		exit 1
          145  +	fi
          146  +
          147  +	## Move file into place
          148  +	mv src.new "${archivedir}/${pkg}"
          149  +fi
          150  +
          151  +# Decompress archive
          152  +## Determine type of archive
          153  +case "${url}" in
          154  +	*.tar.xz|*.tar.xz'?'*|*.txz)
          155  +		decompress='xz'
          156  +		;;
          157  +	*.tar.gz|*.tar.gz'?'*|*.tgz)
          158  +		decompress='gzip'
          159  +		;;
          160  +	*.tar.bz2|*.tar.bz2'?'*|*.tbz2)
          161  +		decompress='bzip2'
          162  +		;;
          163  +	*.zip|*.zip'?'*)
          164  +		decompress='unzip'
          165  +		;;
          166  +	*)
          167  +		echo "Unknown compression method: ${url}" >&2
          168  +
          169  +		exit 1
          170  +		;;
          171  +esac
          172  +
          173  +## Do decompression
          174  +case "${decompress}" in
          175  +	unzip)
          176  +		unzip "${srcfile}" || die 'Unable to uncompress archive'
          177  +		;;
          178  +	*)
          179  +		"${decompress}" -dc "${srcfile}" | tar -xf - || die 'Unable to uncompress archive'
          180  +		;;
          181  +esac
          182  +
          183  +## Cleanup source
          184  +rm -f src
          185  +
          186  +# If we just have one directory, use that directory
          187  +dir="$(echo *)"
          188  +if [ -e "${dir}" ]; then
          189  +	mv "${dir}"/* .
          190  +fi
          191  +
          192  +# Start logging
          193  +set -x
          194  +
          195  +# Determine properties
          196  +determinePrefix
          197  +
          198  +# Start the build
          199  +preconfigure || die 'preconfigure failed'
          200  +configure || die 'configure failed'
          201  +postconfigure || die 'postconfigure failed'
          202  +
          203  +prebuild || die 'prebuild failed'
          204  +build || die 'build failed'
          205  +postbuild || die 'postbuild failed'
          206  +
          207  +preinstall || die 'preinstall failed'
          208  +install || die 'install failed'
          209  +postinstall || die 'postinstall failed'
          210  +
          211  +(
          212  +	appdir="$(appfsinstalldir)/${prefixsuffix}"
          213  +	mkdir -p "${appdir}"
          214  +
          215  +	cd "${destdir}/${prefix}" || exit 1
          216  +	cp -rp * "${appdir}"
          217  +	find "${appdir}" -print0 | xargs -0 touch -t "${pkgdate}"
          218  +)
          219  +
          220  +cleanup
          221  +
          222  +exit 0

Added build.conf version [501534cf12].

            1  +domain=rkeene.org
            2  +function appfsinstalldir() {
            3  +	case "${domain}" in
            4  +		rkeene.org)
            5  +			echo "/web/rkeene/appfs/applications"
            6  +			;;
            7  +		appfs.rkeene.org)
            8  +			echo "/web/customers/appfs.rkeene.org/appfs/applications"
            9  +			;;
           10  +		core.appfs.rkeene.org)
           11  +			echo "/web/static/core.appfs.rkeene.org/appfs/applications"
           12  +			;;
           13  +	esac
           14  +}

Added pkgs/glibc version [a1708aed89].

            1  +#! /usr/bin/env bash
            2  +
            3  +version=2.20
            4  +url="http://ftp.gnu.org/gnu/glibc/glibc-${version}.tar.xz"
            5  +domain=core.appfs.rkeene.org
            6  +sha256='f84b6d42aecc288d593c397b0a3d02260a33ee686bce0c634eb9b32798f36ba5'
            7  +
            8  +function configure() {
            9  +	mkdir BUILD
           10  +	cd BUILD
           11  +
           12  +	../configure --prefix="${prefix}" --sysconfdir=/etc --localstatedir=/var || return 1
           13  +
           14  +	echo '# Ignore: DESTDIR' >> Makefile
           15  +}

Added pkgs/readline version [4f5b78a41f].

            1  +#! /usr/bin/env bash
            2  +
            3  +version=6.3
            4  +url="https://ftp.gnu.org/gnu/readline/readline-${version}.tar.gz"
            5  +domain=core.appfs.rkeene.org
            6  +sha256='56ba6071b9462f980c5a72ab0023893b65ba6debb4eeb475d7a563dc65cafd43'

Added pkgs/zlib version [e788328143].

            1  +#! /usr/bin/env bash
            2  +
            3  +version=1.2.8
            4  +url="http://zlib.net/zlib-${version}.tar.gz"
            5  +domain=core.appfs.rkeene.org
            6  +sha256='36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d'