Check-in [424322801f]
Overview
Comment:Got KitDLL storage into workable state

Renamed some files for consistency

Added basic Makefile

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:424322801faad69fd91cb4ccc26847d2ab9e7b9a
User & Date: rkeene on 2010-09-26 04:51:16
Other Links: manifest | tags
Context
2010-09-26
04:51
Implemented vfs::kitdll::data::getData

Fixed references to Tcl_SetResult() to use TCL_STATIC as freeProc check-in: a85a20ac7a user: rkeene tags: trunk

04:51
Got KitDLL storage into workable state

Renamed some files for consistency

Added basic Makefile check-in: 424322801f user: rkeene tags: trunk

04:51
KitCreator 0.4.0.x check-in: fbf10d2c4e user: rkeene tags: trunk, 0.4.0
Changes

Added kitdll/buildsrc/kitdll-0.0/Makefile version [08cd3293c4].

            1  +CC = gcc
            2  +CFLAGS = -Wall -O3
            3  +CPPFLAGS = -DUSE_TCL_STUBS
            4  +LIBS = -ltclstub8.5
            5  +
            6  +all: vfs_kitdll_data.so
            7  +
            8  +vfs_kitdll_data.h: dir2c.tcl starpack.vfs
            9  +	./dir2c.tcl vfs_kitdll_data starpack.vfs > vfs_kitdll_data.h
           10  +
           11  +vfs_kitdll.tcl.h: vfs_kitdll.tcl
           12  +	./stringify.tcl vfs_kitdll.tcl > vfs_kitdll.tcl.h
           13  +
           14  +vfs_kitdll_data.o: vfs_kitdll_data.c vfs_kitdll_data.h vfs_kitdll.tcl.h
           15  +
           16  +vfs_kitdll_data.so: vfs_kitdll_data.o
           17  +	$(CC) $(CPPFLAGS) $(CFLAGS) -rdynamic -shared $(LDFLAGS) -o vfs_kitdll_data.so vfs_kitdll_data.o $(LIBS)
           18  +
           19  +clean:
           20  +	rm -f vfs_kitdll_data.so vfs_kitdll_data.o
           21  +	rm -f vfs_kitdll.tcl.h vfs_kitdll_data.h
           22  +
           23  +.PHONY: clean

Modified kitdll/buildsrc/kitdll-0.0/dir2c.tcl from [ce5afd32b3] to [4a88bcbca8].

     1      1   #! /usr/bin/env tclsh
     2      2   
     3      3   if {[llength $argv] != 2} {
     4         -	puts stderr "Usage: dir2c <hashkey> <startdir>"
            4  +	puts stderr "Usage: kitdll <hashkey> <startdir>"
     5      5   
     6      6   	exit 1
     7      7   }
     8      8   
     9      9   set hashkey [lindex $argv 0]
    10     10   set startdir [lindex $argv 1]
    11     11   
................................................................................
    21     21   	}
    22     22   	return $file
    23     23   }
    24     24   
    25     25   proc recursive_glob {dir} {
    26     26   	set children [glob -nocomplain -directory $dir *]
    27     27   
    28         -	set ret [list]
           28  +	set ret [list $dir]
    29     29   	foreach child $children {
    30     30   		unset -nocomplain childinfo
    31     31   		catch {
    32     32   			file stat $child childinfo
    33     33   		}
    34     34   
    35     35   		if {![info exists childinfo(type)]} {
................................................................................
    37     37   		}
    38     38   
    39     39   		if {$childinfo(type) == "directory"} {
    40     40   			foreach add [recursive_glob $child] {
    41     41   				lappend ret $add
    42     42   			}
    43     43   
    44         -			lappend ret $child
    45         -
    46     44   			continue
    47     45   		}
    48     46   
    49     47   		if {$childinfo(type) != "file"} {
    50     48   			continue
    51     49   		}
    52     50   
    53     51   		lappend ret $child
    54     52   	}
    55     53   
    56     54   	return $ret
    57     55   }
    58     56   
    59         -proc dir2c_hash {path} {
    60         -	set h 0
    61         -	set g 0
    62         -
    63         -	for {set idx 0} {$idx < [string length $path]} {incr idx} {
    64         -		binary scan [string index $path $idx] H* char
    65         -		set char "0x$char"
    66         -
    67         -		set h [expr {($h << 4) + $char}]
    68         -		set g [expr {$h & 0xf0000000}]
    69         -		if {$g != 0} {
    70         -			set h [expr {($h & 0xffffffff) ^ ($g >> 24)}]
    71         -		}
    72         -
    73         -		set h [expr {$h & ((~$g) & 0xffffffff)}]
    74         -	}
    75         -
    76         -	return $h
    77         -}
    78         -
           57  +# Convert a string into a C-style binary string
           58  +## XXX: This function needs to be optimized
    79     59   proc stringify {data} {
    80     60   	set ret "\""
    81     61   	for {set idx 0} {$idx < [string length $data]} {incr idx} {
    82     62   		binary scan [string index $data $idx] H* char
    83     63   
    84     64   		append ret "\\x${char}"
    85     65   
................................................................................
    91     71   	set ret [string trim $ret "\n\""]
    92     72   
    93     73   	set ret "\"$ret\""
    94     74   
    95     75   	return $ret
    96     76   }
    97     77   
           78  +# This function must be kept in-sync with the generated C function below
           79  +proc kitdll_hash {path} {
           80  +	set h 0
           81  +	set g 0
           82  +
           83  +	for {set idx 0} {$idx < [string length $path]} {incr idx} {
           84  +		binary scan [string index $path $idx] H* char
           85  +		set char "0x$char"
           86  +
           87  +		set h [expr {($h << 4) + $char}]
           88  +		set g [expr {$h & 0xf0000000}]
           89  +		if {$g != 0} {
           90  +			set h [expr {($h & 0xffffffff) ^ ($g >> 24)}]
           91  +		}
           92  +
           93  +		set h [expr {$h & ((~$g) & 0xffffffff)}]
           94  +	}
           95  +
           96  +	return $h
           97  +}
           98  +
           99  +# Generate list of files to include in output
    98    100   set files [recursive_glob $startdir]
    99    101   
   100         -set cpp_tag "DIR2C_[string toupper $hashkey]"
   101         -set code_tag "dir2c_[string tolower $hashkey]"
          102  +# Insert dummy entry cooresponding to C dummy entry
          103  +set files [linsert $files 0 "__DUMMY__"]
          104  +
          105  +# Produce C89 compatible header
          106  +set cpp_tag "KITDLL_[string toupper $hashkey]"
          107  +set code_tag "kitdll_[string tolower $hashkey]"
   102    108   
   103    109   puts "#ifndef $cpp_tag"
   104    110   puts "#  define $cpp_tag 1"
   105         -puts {#  include <unistd.h>
          111  +puts {
          112  +#  ifdef HAVE_STDC
          113  +#    ifndef HAVE_UNISTD_H
          114  +#      define HAVE_UNISTD_H 1
          115  +#    endif
          116  +#    ifndef HAVE_STRING_H
          117  +#      define HAVE_STRING_H 1
          118  +#    endif
          119  +#  endif
          120  +#  ifdef HAVE_UNISTD_H
          121  +#    include <unistd.h>
          122  +#  endif
          123  +#  ifdef HAVE_STRING_H
          124  +#    include <string.h>
          125  +#  endif
   106    126   
   107         -#  ifndef LOADED_DIR2C_COMMON
   108         -#    define LOADED_DIR2C_COMMON 1
          127  +#  ifndef LOADED_KITDLL_COMMON
          128  +#    define LOADED_KITDLL_COMMON 1
   109    129   
   110    130   typedef enum {
   111         -	DIR2C_FILETYPE_FILE,
   112         -	DIR2C_FILETYPE_DIR
   113         -} dir2c_filetype_t;
          131  +	KITDLL_FILETYPE_FILE,
          132  +	KITDLL_FILETYPE_DIR
          133  +} kitdll_filetype_t;
   114    134   
   115         -struct dir2c_data {
   116         -	const char            *name;
   117         -	unsigned long         index;
   118         -	unsigned long         size;
   119         -	dir2c_filetype_t      type;
   120         -	const unsigned char   *data;
          135  +struct kitdll_data {
          136  +	const char *             name;
          137  +	unsigned long            index;
          138  +	unsigned long            size;
          139  +	kitdll_filetype_t        type;
          140  +	const unsigned char *    data;
   121    141   };
   122    142   
   123         -static unsigned long dir2c_hash(const unsigned char *path) {
          143  +static unsigned long kitdll_hash(const unsigned char *path) {
   124    144   	unsigned long i, h = 0, g = 0;
   125    145   
   126    146   	for (i = 0; path[i]; i++) {
   127    147   		h = (h << 4) + path[i];
   128    148   		g = h & 0xf0000000;
   129    149   		if (g) {
   130    150   			h ^= (g >> 24);
................................................................................
   131    151   		}
   132    152   		h &= ((~g) & 0xffffffffLU);
   133    153   	}
   134    154           
   135    155           return(h);
   136    156   }
   137    157   
   138         -#  endif /* !LOADED_DIR2C_COMMON */}
          158  +#  endif /* !LOADED_KITDLL_COMMON */}
   139    159   puts ""
   140    160   
   141         -puts "static struct dir2c_data ${code_tag}_data\[\] = {"
          161  +puts "static struct kitdll_data ${code_tag}_data\[\] = {"
   142    162   puts "\t{"
   143    163   puts "\t\t.name  = NULL,"
   144    164   puts "\t\t.index = 0,"
   145    165   puts "\t\t.type  = 0,"
   146    166   puts "\t\t.size  = 0,"
   147    167   puts "\t\t.data  = NULL,"
   148    168   puts "\t},"
   149         -puts "\t{"
   150         -puts "\t\t.name  = \"\","
   151         -puts "\t\t.index = 1,"
   152         -puts "\t\t.type  = DIR2C_FILETYPE_DIR,"
   153         -puts "\t\t.size  = 0,"
   154         -puts "\t\t.data  = NULL,"
   155         -puts "\t},"
   156         -for {set idx 0} {$idx < [llength $files]} {incr idx} {
          169  +for {set idx 1} {$idx < [llength $files]} {incr idx} {
   157    170   	set file [lindex $files $idx]
   158    171   	set shortfile [shorten_file $startdir $file]
   159    172   
   160    173   	unset -nocomplain finfo type
   161    174   	file stat $file finfo
   162    175   
   163    176   	switch -- $finfo(type) {
   164    177   		"file" {
   165         -			set type "DIR2C_FILETYPE_FILE"
          178  +			set type "KITDLL_FILETYPE_FILE"
   166    179   			set size $finfo(size)
   167    180   
   168    181   			set fd [open $file]
   169    182   			fconfigure $fd -translation binary
   170    183   			set data [read $fd]
   171    184   			close $fd
   172    185   
   173         -			set data [stringify $data]
          186  +			set data "(unsigned char *) [stringify $data]"
   174    187   		}
   175    188   		"directory" {
   176         -			set type "DIR2C_FILETYPE_DIR"
          189  +			set type "KITDLL_FILETYPE_DIR"
   177    190   			set data "NULL"
   178    191   			set size 0
   179    192   		}
   180    193   	}
   181    194   
   182    195   	puts "\t{"
   183    196   	puts "\t\t.name  = \"$shortfile\","
   184         -	puts "\t\t.index = [expr $idx + 2],"
          197  +	puts "\t\t.index = $idx,"
   185    198   	puts "\t\t.type  = $type,"
   186    199   	puts "\t\t.size  = $size,"
   187    200   	puts "\t\t.data  = $data,"
   188    201   	puts "\t},"
   189    202   }
   190    203   puts "};"
   191    204   puts ""
   192    205   
   193    206   puts "static unsigned long ${code_tag}_lookup_index(const char *path) {"
   194         -puts "\tswitch (dir2c_hash(path)) {"
   195         -puts "\t\tcase [dir2c_hash {}]:"
   196         -puts "\t\t\treturn(1);"
          207  +puts "\tswitch (kitdll_hash((unsigned char *) path)) {"
   197    208   
   198         -set seenhashes [list]
   199         -for {set idx 0} {$idx < [llength $files]} {incr idx} {
          209  +for {set idx 1} {$idx < [llength $files]} {incr idx} {
   200    210   	set file [lindex $files $idx]
   201    211   	set shortfile [shorten_file $startdir $file]
   202         -	set hash [dir2c_hash $shortfile]
          212  +	set hash [kitdll_hash $shortfile]
   203    213   
   204         -	if {[lsearch -exact $seenhashes $hash] != -1} {
   205         -		puts stderr "ERROR: Duplicate hash seen: $file ($hash), aborting"
          214  +	lappend indexes_per_hash($hash) [list $shortfile $idx]
          215  +}
   206    216   
   207         -		exit 1
   208         -	}
   209         -
   210         -	lappend seenhashes $hash
   211         -
          217  +foreach {hash idx_list} [array get indexes_per_hash] {
   212    218   	puts "\t\tcase $hash:"
   213         -	puts "\t\t\treturn([expr $idx + 2]);"
          219  +
          220  +	if {[llength $idx_list] == 1} {
          221  +		set idx [lindex $idx_list 0 1]
          222  +
          223  +		puts "\t\t\treturn($idx);"
          224  +	} else {
          225  +		foreach idx_ent $idx_list {
          226  +			set shortfile [lindex $idx_ent 0]
          227  +			set idx [lindex $idx_ent 1]
          228  +
          229  +			puts "\t\t\tif (strcmp(path, \"$shortfile\") == 0) return($idx);"
          230  +		}
          231  +		puts "\t\t\tbreak;"
          232  +	}
   214    233   }
   215    234   
   216    235   puts "\t}"
   217    236   puts "\treturn(0);"
   218    237   puts "}"
   219    238   puts ""
   220    239   
   221         -puts "static struct dir2c_data *${code_tag}_getData(const char *path) {"
   222         -puts "\tunsigned long index;"
          240  +puts "static struct kitdll_data *${code_tag}_getData(const char *path, unsigned long index) {"
          241  +puts "\tif (path != NULL) {"
          242  +puts "\t\tindex = ${code_tag}_lookup_index(path);"
          243  +puts "\t}"
   223    244   puts ""
   224         -puts "\tindex = ${code_tag}_lookup_index(path);"
   225    245   puts "\tif (index == 0) {"
   226    246   puts "\t\treturn(NULL);"
   227    247   puts "\t}"
          248  +puts ""
          249  +puts "\tif (path != NULL) {"
          250  +puts "\t\tif (strcmp(path, ${code_tag}_data\[index\].name) != 0) {"
          251  +puts "\t\t\treturn(NULL);"
          252  +puts "\t\t}"
          253  +puts "\t}"
   228    254   puts ""
   229    255   puts "\treturn(&${code_tag}_data\[index\]);"
   230    256   puts "}"
   231    257   puts ""
          258  +
          259  +puts "static unsigned long ${code_tag}_getChildren(const char *path, unsigned long *outbuf, unsigned long outbuf_count) {"
          260  +puts "\tunsigned long index;"
          261  +puts "\tunsigned long num_children = 0;"
          262  +puts ""
          263  +puts "\tindex = ${code_tag}_lookup_index(path);"
          264  +puts "\tif (index == 0) {"
          265  +puts "\t\treturn(0);"
          266  +puts "\t}"
          267  +puts ""
          268  +puts "\tif (${code_tag}_data\[index\].type != KITDLL_FILETYPE_DIR) {"
          269  +puts "\t\treturn(0);"
          270  +puts "\t}"
          271  +puts ""
          272  +puts "\tif (strcmp(path, ${code_tag}_data\[index\].name) != 0) {"
          273  +puts "\t\treturn(0);"
          274  +puts "\t}"
          275  +puts ""
          276  +puts "\tswitch (index) {"
          277  +
          278  +unset -nocomplain children
          279  +array set children [list]
          280  +for {set idx 1} {$idx < [llength $files]} {incr idx} {
          281  +	set file [lindex $files $idx]
          282  +	set shortfile [shorten_file $startdir $file]
          283  +
          284  +	unset -nocomplain finfo type
          285  +	file stat $file finfo
          286  +
          287  +	if {$finfo(type) != "directory"} {
          288  +		continue;
          289  +	}
          290  +
          291  +	# Determine which children are under this directory
          292  +	## Convert the current pathname to a regular expression that matches exactly
          293  +	set file_regexp [string map [list "\\" "\\\\" "." "\\." "\{" "\\\{" "\}" "\\\}" "*" "\\*"] $file]
          294  +
          295  +	## Search for pathnames which start with exactly our name, followed by a slash
          296  +	## followed by no more slashes (direct descendants)
          297  +	set child_idx_list [lsearch -regexp -all $files "^${file_regexp}/\[^/\]*$"]
          298  +
          299  +	set children($idx) $child_idx_list
          300  +
          301  +	puts "\t\tcase $idx:"
          302  +	puts "\t\t\tnum_children = [llength $child_idx_list];"
          303  +	puts "\t\t\tbreak;"
          304  +	
          305  +}
          306  +
          307  +puts "\t}"
          308  +puts ""
          309  +puts "\tif (outbuf == NULL) {"
          310  +puts "\t\treturn(num_children);"
          311  +puts "\t}"
          312  +puts ""
          313  +puts "\tif (num_children > outbuf_count) {"
          314  +puts "\t\tnum_children = outbuf_count;"
          315  +puts "\t}"
          316  +puts ""
          317  +puts "\tif (num_children == 0) {"
          318  +puts "\t\treturn(num_children);"
          319  +puts "\t}"
          320  +puts ""
          321  +puts "\tif (outbuf_count > num_children) {"
          322  +puts "\t\toutbuf_count = num_children;"
          323  +puts "\t}"
          324  +puts ""
          325  +puts "\tswitch (index) {"
          326  +
          327  +foreach {idx child_idx_list} [array get children] {
          328  +	if {[llength $child_idx_list] == 0} {
          329  +		continue
          330  +	}
          331  +
          332  +	puts "\t\tcase $idx:"
          333  +	puts "\t\t\tswitch(outbuf_count) {"
          334  +
          335  +	for {set child_idx_idx [expr {[llength $child_idx_list] - 1}]} {$child_idx_idx >= 0} {incr child_idx_idx -1} {
          336  +		set child_idx [lindex $child_idx_list $child_idx_idx]
          337  +
          338  +		puts "\t\t\t\tcase [expr {$child_idx_idx + 1}]:"
          339  +		puts "\t\t\t\t\toutbuf\[$child_idx_idx\] = $child_idx;"
          340  +	}
          341  +
          342  +	puts "\t\t\t}"
          343  +
          344  +	puts "\t\t\tbreak;"
          345  +}
          346  +
          347  +puts "\t}"
          348  +puts ""
          349  +puts "\treturn(num_children);"
          350  +puts "}"
          351  +puts ""
   232    352   
   233    353   puts "#endif /* !$cpp_tag */"

Name change from kitsh/buildsrc/kitsh-0.0/stringify.tcl to kitdll/buildsrc/kitdll-0.0/stringify.tcl.


Modified kitdll/buildsrc/kitdll-0.0/vfs_kitdll.tcl from [94451bedbe] to [3533698919].

    14     14   proc ::vfs::kitdll::Unmount {local} {
    15     15   	vfs::filesystem unmount $local
    16     16   }
    17     17   
    18     18   # Implementation
    19     19   
    20     20   ## Filesystem Data
    21         -namespace eval ::vfs::kitdll::data {}
    22         -set ::vfs::kitdll::data(joe) "Test\n"
    23         -set {::vfs::kitdll::metadata()} [list type directory ino 0 mode 0555 nlink 2 uid 0 gid 0 size 0 atime 0 mtime 0 ctime 0]
    24         -set ::vfs::kitdll::metadata(joe) [list type file ino 1 mode 0444 nlink 1 uid 0 gid 0 size 5 atime 0 mtime 0 ctime 0]
    25         -set ::vfs::kitdll::metadata(sub) [list type directory ino 2 mode 0555 nlink 1 uid 0 gid 0 size 0 atime 0 mtime 0 ctime 0]
    26         -set ::vfs::kitdll::metadata(sub/sub2) [list type directory ino 3 mode 0555 nlink 1 uid 0 gid 0 size 0 atime 0 mtime 0 ctime 0]
    27         -
    28     21   proc ::vfs::kitdll::data::getData {hashkey file {start 0} {end "end"}} {
    29     22   	if {![info exists ::vfs::kitdll::data($file)]} {
    30     23   		return -code error "Invalid operation"
    31     24   	}
    32     25   
    33     26   	return [string range $::vfs::kitdll::data($file) $start $end]
    34     27   }
    35     28   
    36         -proc ::vfs::kitdll::data::getMetadata {hashkey file} {
    37         -	if {![info exists ::vfs::kitdll::metadata($file)]} {
    38         -		return -code error "No such file"
    39         -	}
    40         -
    41         -	return $::vfs::kitdll::metadata($file)
    42         -}
    43         -
    44         -proc ::vfs::kitdll::data::getChildren {hashkey directory} {
    45         -	set pattern [file join $directory {[^/]*}]
    46         -
    47         -	set children [array names ::vfs::kitdll::metadata -regexp "^${pattern}\$"]
    48         -
    49         -	set newchildren [list]
    50         -	foreach child $children {
    51         -		if {$child == ""} {
    52         -			continue
    53         -		}
    54         -
    55         -		set tail [lindex [split $child /] end]
    56         -
    57         -		lappend newchildren $tail
    58         -	}
    59         -
    60         -	return $newchildren
    61         -}
    62         -
    63     29   ## VFS and Chan I/O
    64     30   ### Dispatchers
    65     31   proc ::vfs::kitdll::vfshandler {hashkey subcmd args} {
    66     32   	set cmd $args
    67     33   	set cmd [linsert $cmd 0 "::vfs::kitdll::vfsop_${subcmd}" $hashkey]
    68     34   
    69     35   	return [eval $cmd]
................................................................................
   212    178   		}
   213    179   
   214    180   		unset -nocomplain metadata
   215    181   		catch {
   216    182   			array set metadata [::vfs::kitdll::data::getMetadata $hashkey $child]
   217    183   		}
   218    184   
   219         -		if {[string index $actualpath end] == "/"} {
   220         -			set child "${actualpath}${child}"
          185  +		if {[string index $root end] == "/"} {
          186  +			set child "${root}${child}"
   221    187   		} else {
   222         -			set child "${actualpath}/${child}"
          188  +			set child "${root}/${child}"
   223    189   		}
   224    190   		if {[string index $child end] == "/"} {
   225    191   			set child [string range $child 0 end-1]
   226    192   		}
   227    193   
   228    194   		if {![info exists metadata(type)]} {
   229    195   			continue
................................................................................
   342    308   	vfs::filesystem posixerror $::vfs::posix(EROFS)
   343    309   }
   344    310   proc ::vfs::kitdll::vfsop_utime {} {
   345    311   	vfs::filesystem posixerror $::vfs::posix(EROFS)
   346    312   }
   347    313   
   348    314   package provide vfs::kitdll 1.0
          315  +
          316  +::vfs::kitdll::Mount vfs_kitdll_data /tmp

Added kitdll/buildsrc/kitdll-0.0/vfs_kitdll_data.c version [fdbf11d0e3].

            1  +#define HAVE_STDC 1
            2  +
            3  +#include <tcl.h>
            4  +#include <stdio.h>
            5  +#include <stdlib.h>
            6  +
            7  +#include "vfs_kitdll_data.h"
            8  +
            9  +typedef struct kitdll_data *(cmd_getData_t)(const char *, unsigned long);
           10  +typedef unsigned long (cmd_getChildren_t)(const char *, unsigned long *, unsigned long);
           11  +
           12  +static cmd_getData_t *getCmdData(const char *hashkey) {
           13  +	/* XXX: TODO: Look up symbol using dlsym() */
           14  +	if (strcmp(hashkey, "vfs_kitdll_data") == 0) {
           15  +		return(kitdll_vfs_kitdll_data_getData);
           16  +	}
           17  +
           18  +	return(NULL);
           19  +}
           20  +
           21  +static cmd_getChildren_t *getCmdChildren(const char *hashkey) {
           22  +	/* XXX: TODO: Look up symbol using dlsym() */
           23  +	if (strcmp(hashkey, "vfs_kitdll_data") == 0) {
           24  +		return(kitdll_vfs_kitdll_data_getChildren);
           25  +	}
           26  +
           27  +	return(NULL);
           28  +}
           29  +
           30  +static int getMetadata(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
           31  +	cmd_getData_t *cmd_getData;
           32  +	cmd_getChildren_t *cmd_getChildren;
           33  +	struct kitdll_data *finfo = NULL;
           34  +	Tcl_Obj *ret_list, *ret_list_items[20];
           35  +	unsigned long num_children;
           36  +	const char *hashkey;
           37  +	const char *file;
           38  +
           39  +	if (objc != 3) {
           40  +		Tcl_SetResult(interp, "wrong # args: should be \"getMetadata hashKey fileName\"", NULL);
           41  +
           42  +		return(TCL_ERROR);
           43  +	}
           44  +
           45  +	hashkey = Tcl_GetString(objv[1]);
           46  +	file = Tcl_GetString(objv[2]);
           47  +
           48  +	cmd_getData = getCmdData(hashkey);
           49  +	cmd_getChildren = getCmdChildren(hashkey);
           50  +
           51  +	if (cmd_getData == NULL || cmd_getChildren == NULL) {
           52  +		Tcl_SetResult(interp, "No such hashkey", NULL);
           53  +
           54  +		return(TCL_ERROR);
           55  +	}
           56  +
           57  +	finfo = cmd_getData(file, 0);
           58  +
           59  +	if (finfo == NULL) {
           60  +		Tcl_SetResult(interp, "No such file or directory", NULL);
           61  +
           62  +		return(TCL_ERROR);
           63  +	}
           64  +
           65  +	/* Values that can be derived from "finfo" */
           66  +	ret_list_items[0] = Tcl_NewStringObj("type", 4);
           67  +	ret_list_items[2] = Tcl_NewStringObj("mode", 4);
           68  +	ret_list_items[4] = Tcl_NewStringObj("nlink", 5);
           69  +
           70  +	if (finfo->type == KITDLL_FILETYPE_DIR) {
           71  +		num_children = cmd_getChildren(file, NULL, 0);
           72  +
           73  +		ret_list_items[1] = Tcl_NewStringObj("directory", 9);
           74  +		ret_list_items[3] = Tcl_NewLongObj(040555);
           75  +		ret_list_items[5] = Tcl_NewLongObj(num_children);
           76  +	} else {
           77  +		ret_list_items[1] = Tcl_NewStringObj("file", 4);
           78  +		ret_list_items[3] = Tcl_NewLongObj(0444);
           79  +		ret_list_items[5] = Tcl_NewLongObj(1);
           80  +	}
           81  +
           82  +	ret_list_items[6] = Tcl_NewStringObj("ino", 3);
           83  +	ret_list_items[7] = Tcl_NewLongObj(finfo->index);
           84  +
           85  +	ret_list_items[8] = Tcl_NewStringObj("size", 4);
           86  +	ret_list_items[9] = Tcl_NewLongObj(finfo->size);
           87  +
           88  +	/* Dummy values */
           89  +	ret_list_items[10] = Tcl_NewStringObj("uid", 3);
           90  +	ret_list_items[11] = Tcl_NewStringObj("0", 1);
           91  +
           92  +	ret_list_items[12] = Tcl_NewStringObj("gid", 3);
           93  +	ret_list_items[13] = Tcl_NewStringObj("0", 1);
           94  +
           95  +	ret_list_items[14] = Tcl_NewStringObj("atime", 5);
           96  +	ret_list_items[15] = Tcl_NewStringObj("0", 1);
           97  +
           98  +	ret_list_items[16] = Tcl_NewStringObj("mtime", 5);
           99  +	ret_list_items[17] = Tcl_NewStringObj("0", 1);
          100  +
          101  +	ret_list_items[18] = Tcl_NewStringObj("ctime", 5);
          102  +	ret_list_items[19] = Tcl_NewStringObj("0", 1);
          103  +
          104  +	ret_list = Tcl_NewListObj(sizeof(ret_list_items) / sizeof(ret_list_items[0]), ret_list_items);
          105  +
          106  +	Tcl_SetObjResult(interp, ret_list);
          107  +
          108  +	return(TCL_OK);
          109  +}
          110  +
          111  +static int getData(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
          112  +	if (objc < 3 || objc > 5) {
          113  +		Tcl_SetResult(interp, "wrong # args: should be \"getData hashKey fileName ?start? ?end?\"", NULL);
          114  +
          115  +		return(TCL_ERROR);
          116  +	}
          117  +	return(TCL_ERROR);
          118  +}
          119  +
          120  +static int getChildren(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
          121  +	cmd_getChildren_t *cmd_getChildren;
          122  +	cmd_getData_t *cmd_getData;
          123  +	struct kitdll_data *finfo = NULL;
          124  +	unsigned long num_children, idx;
          125  +	unsigned long *children;
          126  +	const char *hashkey;
          127  +	const char *file;
          128  +	const char *child;
          129  +	Tcl_Obj *ret_list, *ret_curr_obj;
          130  +
          131  +	if (objc != 3) {
          132  +		Tcl_SetResult(interp, "wrong # args: should be \"getChildren hashKey fileName\"", NULL);
          133  +
          134  +		return(TCL_ERROR);
          135  +	}
          136  +
          137  +	hashkey = Tcl_GetString(objv[1]);
          138  +	file = Tcl_GetString(objv[2]);
          139  +
          140  +	cmd_getData = getCmdData(hashkey);
          141  +	cmd_getChildren = getCmdChildren(hashkey);
          142  +
          143  +	if (cmd_getData == NULL || cmd_getChildren == NULL) {
          144  +		Tcl_SetResult(interp, "No such hashkey", NULL);
          145  +
          146  +		return(TCL_ERROR);
          147  +	}
          148  +
          149  +	finfo = cmd_getData(file, 0);
          150  +
          151  +	if (finfo == NULL) {
          152  +		Tcl_SetResult(interp, "No such file or directory", NULL);
          153  +
          154  +		return(TCL_ERROR);
          155  +	}
          156  +
          157  +	if (finfo->type != KITDLL_FILETYPE_DIR) {
          158  +		Tcl_SetResult(interp, "Not a directory", NULL);
          159  +
          160  +		return(TCL_ERROR);
          161  +	}
          162  +
          163  +	num_children = cmd_getChildren(file, NULL, 0);
          164  +
          165  +	if (num_children == 0) {
          166  +		/* Return immediately if there are no children */
          167  +		Tcl_SetResult(interp, "", NULL);
          168  +
          169  +		return(TCL_OK);
          170  +	}
          171  +
          172  +	ret_list = Tcl_NewObj();
          173  +	if (ret_list == NULL) {
          174  +		Tcl_SetResult(interp, "Failed to allocate new object", NULL);
          175  +
          176  +		return(TCL_ERROR);
          177  +	}
          178  +
          179  +	children = malloc(sizeof(*children) * num_children);
          180  +
          181  +	num_children = cmd_getChildren(file, children, num_children);
          182  +
          183  +	for (idx = 0; idx < num_children; idx++) {
          184  +		finfo = cmd_getData(NULL, children[idx]);
          185  +
          186  +		if (finfo == NULL || finfo->name == NULL) {
          187  +			continue;
          188  +		}
          189  +
          190  +		child = finfo->name;
          191  +
          192  +		ret_curr_obj = Tcl_NewStringObj(child, strlen(child));
          193  +
          194  +		Tcl_ListObjAppendList(interp, ret_list, ret_curr_obj);
          195  +	}
          196  +
          197  +	free(children);
          198  +
          199  +	Tcl_SetObjResult(interp, ret_list);
          200  +
          201  +	return(TCL_OK);
          202  +}
          203  +
          204  +int Vfs_kitdll_data_Init(Tcl_Interp *interp) {   
          205  +	Tcl_Command tclCreatComm_ret;
          206  +	int tclPkgProv_ret;
          207  +
          208  +	tclCreatComm_ret = Tcl_CreateObjCommand(interp, "::vfs::kitdll::data::getMetadata", getMetadata, NULL, NULL);
          209  +	if (!tclCreatComm_ret) {
          210  +		return(TCL_ERROR);
          211  +	}
          212  +
          213  +	tclCreatComm_ret = Tcl_CreateObjCommand(interp, "::vfs::kitdll::data::getData", getData, NULL, NULL);
          214  +	if (!tclCreatComm_ret) {
          215  +		return(TCL_ERROR);
          216  +	}
          217  +
          218  +	tclCreatComm_ret = Tcl_CreateObjCommand(interp, "::vfs::kitdll::data::getChildren", getChildren, NULL, NULL);
          219  +	if (!tclCreatComm_ret) {
          220  +		return(TCL_ERROR);
          221  +	}
          222  +
          223  +	tclPkgProv_ret = Tcl_PkgProvide(interp, "vfs::kitdll::data", "1.0");
          224  +
          225  +	return(tclPkgProv_ret);
          226  +}