Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -7,11 +7,11 @@ TCLSH := tclsh LIB_SUFFIX := $(shell . "${TCL_CONFIG_SH}"; echo "$${TCL_SHLIB_SUFFIX:-.so}") all: example-standalone$(LIB_SUFFIX) example-client$(LIB_SUFFIX) example-flexible$(LIB_SUFFIX) xvfs$(LIB_SUFFIX) -example.c: $(shell find example -type f) $(shell find lib -type f) xvfs.c.rvt xvfs-create Makefile +example.c: $(shell find example -type f) $(shell find lib -type f) lib/xvfs/xvfs.c.rvt xvfs-create Makefile ./xvfs-create --directory example --name example > example.c.new mv example.c.new example.c example-standalone.o: example.c xvfs-core.h xvfs-core.c Makefile $(CC) $(CPPFLAGS) -DXVFS_MODE_STANDALONE $(CFLAGS) -o example-standalone.o -c example.c @@ -37,11 +37,11 @@ xvfs$(LIB_SUFFIX): xvfs.o Makefile $(CC) $(CFLAGS) $(LDFLAGS) -shared -o xvfs$(LIB_SUFFIX) xvfs.o $(LIBS) # xvfs-create-standalone is a standalone (i.e., no external dependencies # like lib/minirivet, xvfs-core.c, etc) version of "xvfs-create" -xvfs-create-standalone: $(shell find lib -type f) xvfs-create xvfs-core.c xvfs-core.h xvfs.c.rvt Makefile +xvfs-create-standalone: $(shell find lib -type f) xvfs-create xvfs-core.c xvfs-core.h lib/xvfs/xvfs.c.rvt Makefile rm -f xvfs-create-standalone.new xvfs-create-standalone ./xvfs-create --dump-tcl --remove-debug > xvfs-create-standalone.new chmod +x xvfs-create-standalone.new mv xvfs-create-standalone.new xvfs-create-standalone ADDED lib/xvfs/xvfs.c.rvt Index: lib/xvfs/xvfs.c.rvt ================================================================== --- /dev/null +++ lib/xvfs/xvfs.c.rvt @@ -0,0 +1,294 @@ +#include +#include +#include +#include +#include + +#define XVFS_NAME_LOOKUP_ERROR (-1) +#define XVFS_FILE_BLOCKSIZE 1024 + +/* + * XXX:TODO: Determine this automatically rather than + * by heuristics + */ +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#define HAVE_STRUCT_STAT_ST_BLOCKS 1 +#ifdef WIN32 +# undef HAVE_STRUCT_STAT_ST_BLKSIZE +# undef HAVE_STRUCT_STAT_ST_BLOCKS +#endif + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +typedef enum { + XVFS_FILE_TYPE_REG, + XVFS_FILE_TYPE_DIR +} xvfs_file_type_t; + +typedef Tcl_WideInt xvfs_size_t; + +struct xvfs_file_data { + const char *name; + xvfs_file_type_t type; + xvfs_size_t size; + union { + const unsigned char *fileContents; + const char **dirChildren; + } data; +}; + +if (memcmp(path, xvfs__data[].name, ) == 0) { + return(); +} + +static long xvfs__nameToIndex(const char *path) { + $::xvfs::hashNameThreshold} { + set needZlib true + break; + } + } +?> unsigned int pathHash; + size_t pathLen; + + if (path == NULL) { + return(XVFS_NAME_LOOKUP_ERROR); + } + + pathLen = strlen(path); + switch (pathLen) { + case : + $::xvfs::hashNameThreshold} { +?> pathHash = Tcl_ZlibAdler32(0, (const unsigned char *) path, ); + switch (pathHash) { + case : + break; + } + break; + } + + return(XVFS_NAME_LOOKUP_ERROR); +} + +static const char **xvfs__getChildren(const char *path, Tcl_WideInt *count) { + const struct xvfs_file_data *fileInfo; + long inode; + + /* + * Validate input parameters + */ + if (count == NULL) { + return(NULL); + } + + /* + * Get the inode from the lookup function + */ + inode = xvfs__nameToIndex(path); + if (inode == XVFS_NAME_LOOKUP_ERROR) { + *count = XVFS_RV_ERR_ENOENT; + return(NULL); + } + + fileInfo = &xvfs__data[inode]; + + /* + * Ensure this is a directory + */ + if (fileInfo->type != XVFS_FILE_TYPE_DIR) { + *count = XVFS_RV_ERR_ENOTDIR; + return(NULL); + } + + *count = fileInfo->size; + return(fileInfo->data.dirChildren); +} + +static const unsigned char *xvfs__getData(const char *path, Tcl_WideInt start, Tcl_WideInt *length) { + const struct xvfs_file_data *fileInfo; + Tcl_WideInt resultLength; + long inode; + + /* + * Validate input parameters + */ + if (length == NULL) { + return(NULL); + } + + if (start < 0) { + *length = XVFS_RV_ERR_EINVAL; + return(NULL); + } + + if (*length < 0) { + *length = XVFS_RV_ERR_EINVAL; + return(NULL); + } + + /* + * Get the inode from the lookup function + */ + inode = xvfs__nameToIndex(path); + if (inode == XVFS_NAME_LOOKUP_ERROR) { + *length = XVFS_RV_ERR_ENOENT; + return(NULL); + } + + fileInfo = &xvfs__data[inode]; + + /* + * Ensure this is a file that can be read + */ + if (fileInfo->type != XVFS_FILE_TYPE_REG) { + *length = XVFS_RV_ERR_EISDIR; + return(NULL); + } + + /* + * Validate the length + */ + if (start > fileInfo->size) { + *length = XVFS_RV_ERR_EFAULT; + return(NULL); + } + + if (*length == 0) { + resultLength = fileInfo->size - start; + } else { + resultLength = MIN(fileInfo->size - start, *length); + } + *length = resultLength; + + /* + * Return the data + */ + return(fileInfo->data.fileContents + start); +} + +static int xvfs__getStat(const char *path, Tcl_StatBuf *statBuf) { + const struct xvfs_file_data *fileInfo; + long inode; + + /* + * Validate input parameters + */ + if (!statBuf) { + return(XVFS_RV_ERR_EINVAL); + } + + /* + * Get the inode from the lookup function + */ + inode = xvfs__nameToIndex(path); + if (inode == XVFS_NAME_LOOKUP_ERROR) { + return(XVFS_RV_ERR_ENOENT); + } + + fileInfo = &xvfs__data[inode]; + + statBuf->st_dev = ; + statBuf->st_rdev = ; + statBuf->st_ino = inode; + statBuf->st_uid = 0; + statBuf->st_gid = 0; + statBuf->st_atime = 0; + statBuf->st_ctime = 0; + statBuf->st_mtime = 0; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + statBuf->st_blksize = XVFS_FILE_BLOCKSIZE; +#endif + + if (fileInfo->type == XVFS_FILE_TYPE_REG) { + statBuf->st_mode = 0100444; + statBuf->st_nlink = 1; + statBuf->st_size = fileInfo->size; +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + statBuf->st_blocks = (fileInfo->size + statBuf->st_blksize - 1) / statBuf->st_blksize; +#endif + } else if (fileInfo->type == XVFS_FILE_TYPE_DIR) { + statBuf->st_mode = 040555; + statBuf->st_nlink = fileInfo->size; + statBuf->st_size = fileInfo->size; +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + statBuf->st_blocks = 1; +#endif + } + + return(0); +} + +static struct Xvfs_FSInfo xvfs__fsInfo = { + .protocolVersion = XVFS_PROTOCOL_VERSION, + .name = "", + .getChildrenProc = xvfs__getChildren, + .getDataProc = xvfs__getData, + .getStatProc = xvfs__getStat +}; + +int Xvfs__Init(Tcl_Interp *interp) { + int register_ret; + +#ifdef USE_TCL_STUBS + const char *tclInitStubs_ret; + /* Initialize Stubs */ + tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0); + if (!tclInitStubs_ret) { + return(TCL_ERROR); + } +#endif + + register_ret = Xvfs_Register(interp, &xvfs__fsInfo); + if (register_ret != TCL_OK) { + return(register_ret); + } + + return(TCL_OK); +} +#undef XVFS_NAME_LOOKUP_ERROR +#undef XVFS_FILE_BLOCKSIZE Index: lib/xvfs/xvfs.tcl ================================================================== --- lib/xvfs/xvfs.tcl +++ lib/xvfs/xvfs.tcl @@ -1,9 +1,11 @@ #! /usr/bin/env tclsh namespace eval ::xvfs {} +set ::xvfs::_xvfsDir [file dirname [info script]] + # Functions proc ::xvfs::_emitLine {line} { ::minirivet::_emitOutput "${line}\n" } @@ -244,7 +246,12 @@ set ::xvfs::outputFiles [processDirectory $fsName $rootDirectory] set ::xvfs::fsName $fsName set ::xvfs::rootDirectory $rootDirectory } + +proc ::xvfs::run {} { + ::minirivet::parse [file join $::xvfs::_xvfsDir xvfs.c.rvt] +} + package provide xvfs 1 Index: xvfs-create ================================================================== --- xvfs-create +++ xvfs-create @@ -2,11 +2,11 @@ set sourceDirectory [file dirname [file normalize [info script]]] lappend auto_path [file join $sourceDirectory lib] -set template [file join $sourceDirectory xvfs.c.rvt] +set template [file join $sourceDirectory lib xvfs xvfs.c.rvt] package require minirivet set mode "run" if {[lindex $argv 0] == "--dump-tcl"} { @@ -46,11 +46,13 @@ if {[info exists outputFile]} { set fd [open $outputFile w] ::minirivet::setOutputChannel $fd } - ::minirivet::parse $template + package require xvfs + set ::xvfs::argv $argv + ::xvfs::run if {[info exists fd]} { close $fd } } @@ -75,16 +77,30 @@ puts "#! /usr/bin/env tclsh" puts "" puts [list namespace eval ::minirivet {}] puts [list set ::minirivet::_outputChannel stdout] puts [list proc ::minirivet::_emitOutput [info args ::minirivet::_emitOutput] [info body ::minirivet::_emitOutput]] + puts "" puts [read [open $xvfs_tcl]] puts "" - puts [list puts -nonewline $core_header_data] + puts {set ::xvfs::argv $::argv} + puts { + foreach {arg val} $argv { + switch -exact -- $arg { + "--output" { + set ::minirivet::_outputChannel [open $val w] + } + } + } + } + puts "" + puts [list ::minirivet::_emitOutput $core_header_data] + puts "" + puts "" puts [string map $cleanup [::minirivet::parseStringToCode [read [open $template]]]] } default { puts stderr "error: Invalid mode: $mode" exit 1 } } DELETED xvfs.c.rvt Index: xvfs.c.rvt ================================================================== --- xvfs.c.rvt +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include -#include -#include - -#define XVFS_NAME_LOOKUP_ERROR (-1) -#define XVFS_FILE_BLOCKSIZE 1024 - -/* - * XXX:TODO: Determine this automatically rather than - * by heuristics - */ -#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 -#define HAVE_STRUCT_STAT_ST_BLOCKS 1 -#ifdef WIN32 -# undef HAVE_STRUCT_STAT_ST_BLKSIZE -# undef HAVE_STRUCT_STAT_ST_BLOCKS -#endif - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -typedef enum { - XVFS_FILE_TYPE_REG, - XVFS_FILE_TYPE_DIR -} xvfs_file_type_t; - -typedef Tcl_WideInt xvfs_size_t; - -struct xvfs_file_data { - const char *name; - xvfs_file_type_t type; - xvfs_size_t size; - union { - const unsigned char *fileContents; - const char **dirChildren; - } data; -}; - -if (memcmp(path, xvfs__data[].name, ) == 0) { - return(); -} - -static long xvfs__nameToIndex(const char *path) { - $::xvfs::hashNameThreshold} { - set needZlib true - break; - } - } -?> unsigned int pathHash; - size_t pathLen; - - if (path == NULL) { - return(XVFS_NAME_LOOKUP_ERROR); - } - - pathLen = strlen(path); - switch (pathLen) { - case : - $::xvfs::hashNameThreshold} { -?> pathHash = Tcl_ZlibAdler32(0, (const unsigned char *) path, ); - switch (pathHash) { - case : - break; - } - break; - } - - return(XVFS_NAME_LOOKUP_ERROR); -} - -static const char **xvfs__getChildren(const char *path, Tcl_WideInt *count) { - const struct xvfs_file_data *fileInfo; - long inode; - - /* - * Validate input parameters - */ - if (count == NULL) { - return(NULL); - } - - /* - * Get the inode from the lookup function - */ - inode = xvfs__nameToIndex(path); - if (inode == XVFS_NAME_LOOKUP_ERROR) { - *count = XVFS_RV_ERR_ENOENT; - return(NULL); - } - - fileInfo = &xvfs__data[inode]; - - /* - * Ensure this is a directory - */ - if (fileInfo->type != XVFS_FILE_TYPE_DIR) { - *count = XVFS_RV_ERR_ENOTDIR; - return(NULL); - } - - *count = fileInfo->size; - return(fileInfo->data.dirChildren); -} - -static const unsigned char *xvfs__getData(const char *path, Tcl_WideInt start, Tcl_WideInt *length) { - const struct xvfs_file_data *fileInfo; - Tcl_WideInt resultLength; - long inode; - - /* - * Validate input parameters - */ - if (length == NULL) { - return(NULL); - } - - if (start < 0) { - *length = XVFS_RV_ERR_EINVAL; - return(NULL); - } - - if (*length < 0) { - *length = XVFS_RV_ERR_EINVAL; - return(NULL); - } - - /* - * Get the inode from the lookup function - */ - inode = xvfs__nameToIndex(path); - if (inode == XVFS_NAME_LOOKUP_ERROR) { - *length = XVFS_RV_ERR_ENOENT; - return(NULL); - } - - fileInfo = &xvfs__data[inode]; - - /* - * Ensure this is a file that can be read - */ - if (fileInfo->type != XVFS_FILE_TYPE_REG) { - *length = XVFS_RV_ERR_EISDIR; - return(NULL); - } - - /* - * Validate the length - */ - if (start > fileInfo->size) { - *length = XVFS_RV_ERR_EFAULT; - return(NULL); - } - - if (*length == 0) { - resultLength = fileInfo->size - start; - } else { - resultLength = MIN(fileInfo->size - start, *length); - } - *length = resultLength; - - /* - * Return the data - */ - return(fileInfo->data.fileContents + start); -} - -static int xvfs__getStat(const char *path, Tcl_StatBuf *statBuf) { - const struct xvfs_file_data *fileInfo; - long inode; - - /* - * Validate input parameters - */ - if (!statBuf) { - return(XVFS_RV_ERR_EINVAL); - } - - /* - * Get the inode from the lookup function - */ - inode = xvfs__nameToIndex(path); - if (inode == XVFS_NAME_LOOKUP_ERROR) { - return(XVFS_RV_ERR_ENOENT); - } - - fileInfo = &xvfs__data[inode]; - - statBuf->st_dev = ; - statBuf->st_rdev = ; - statBuf->st_ino = inode; - statBuf->st_uid = 0; - statBuf->st_gid = 0; - statBuf->st_atime = 0; - statBuf->st_ctime = 0; - statBuf->st_mtime = 0; -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - statBuf->st_blksize = XVFS_FILE_BLOCKSIZE; -#endif - - if (fileInfo->type == XVFS_FILE_TYPE_REG) { - statBuf->st_mode = 0100444; - statBuf->st_nlink = 1; - statBuf->st_size = fileInfo->size; -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - statBuf->st_blocks = (fileInfo->size + statBuf->st_blksize - 1) / statBuf->st_blksize; -#endif - } else if (fileInfo->type == XVFS_FILE_TYPE_DIR) { - statBuf->st_mode = 040555; - statBuf->st_nlink = fileInfo->size; - statBuf->st_size = fileInfo->size; -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - statBuf->st_blocks = 1; -#endif - } - - return(0); -} - -static struct Xvfs_FSInfo xvfs__fsInfo = { - .protocolVersion = XVFS_PROTOCOL_VERSION, - .name = "", - .getChildrenProc = xvfs__getChildren, - .getDataProc = xvfs__getData, - .getStatProc = xvfs__getStat -}; - -int Xvfs__Init(Tcl_Interp *interp) { - int register_ret; - -#ifdef USE_TCL_STUBS - const char *tclInitStubs_ret; - /* Initialize Stubs */ - tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0); - if (!tclInitStubs_ret) { - return(TCL_ERROR); - } -#endif - - register_ret = Xvfs_Register(interp, &xvfs__fsInfo); - if (register_ret != TCL_OK) { - return(register_ret); - } - - return(TCL_OK); -} -#undef XVFS_NAME_LOOKUP_ERROR -#undef XVFS_FILE_BLOCKSIZE