Lines of
lib/xvfs/xvfs.c.rvt
from check-in 09e53d3c38
that are changed by the sequence of edits moving toward
check-in a719156faf:
1: <?
2: if {[info exists ::xvfs::xvfsCoreH]} {
3: ?><?= $::xvfs::xvfsCoreH ?><?
4: } else {
5: ?>#include <xvfs-core.h><? } ?>
6: #include <sys/stat.h>
7: #include <unistd.h>
8: #include <string.h>
9: #include <tcl.h>
10:
11: #define XVFS_NAME_LOOKUP_ERROR (-1)
12: #define XVFS_FILE_BLOCKSIZE 1024
13:
14: /*
15: * XXX:TODO: Determine this automatically rather than
16: * by heuristics
17: */
18: #define HAVE_STRUCT_STAT_ST_BLKSIZE 1
19: #define HAVE_STRUCT_STAT_ST_BLOCKS 1
20: #ifdef WIN32
21: # undef HAVE_STRUCT_STAT_ST_BLKSIZE
22: # undef HAVE_STRUCT_STAT_ST_BLOCKS
23: #endif
24:
25: #ifndef MIN
26: #define MIN(a, b) (((a) < (b)) ? (a) : (b))
27: #endif
28:
29: #ifndef HAVE_DEFINED_XVFS_FILE_TYPE_T
30: #define HAVE_DEFINED_XVFS_FILE_TYPE_T 1
31: typedef enum {
32: XVFS_FILE_TYPE_REG,
33: XVFS_FILE_TYPE_DIR
34: } xvfs_file_type_t;
35: #endif
36:
37: #ifndef HAVE_DEFINED_XVFS_SIZE_T
38: #define HAVE_DEFINED_XVFS_SIZE_T 1
39: typedef Tcl_WideInt xvfs_size_t;
40: #endif
41:
42: #ifndef HAVE_DEFINED_XVFS_FILE_DATA
43: #define HAVE_DEFINED_XVFS_FILE_DATA 1
44: struct xvfs_file_data {
09e53d3c38 2019-09-20 45: const char *name;
09e53d3c38 2019-09-20 46: xvfs_file_type_t type;
09e53d3c38 2019-09-20 47: xvfs_size_t size;
48: union {
09e53d3c38 2019-09-20 49: const unsigned char *fileContents;
50: const char **dirChildren;
51: } data;
52: };
53: #endif
54:
55: <?
56: package require xvfs
57:
09e53d3c38 2019-09-20 58: set ::xvfs::hashNameThreshold 3
09e53d3c38 2019-09-20 59: if {[info exists ::env(XVFS_CREATE_HASH_NAME_THRESHOLD)]} {
09e53d3c38 2019-09-20 60: set ::xvfs::hashNameThreshold $::env(XVFS_CREATE_HASH_NAME_THRESHOLD)
09e53d3c38 2019-09-20 61: }
09e53d3c38 2019-09-20 62: if {$::xvfs::hashNameThreshold < 0} {
09e53d3c38 2019-09-20 63: set ::xvfs::hashNameThreshold [expr {2**31}]
09e53d3c38 2019-09-20 64: }
65: xvfs::main $::xvfs::argv
66:
09e53d3c38 2019-09-20 67: proc emitFilenameVerification {indentLevel outputFileNameLen outputFileIndexes} {
09e53d3c38 2019-09-20 68: set indent [string repeat "\t" $indentLevel]
09e53d3c38 2019-09-20 69: foreach outputFileIndex $outputFileIndexes {
09e53d3c38 2019-09-20 70: ?><?= $indent ?>if (memcmp(path, xvfs_<?= $::xvfs::fsName ?>_data[<?= $outputFileIndex ?>].name, <?= $outputFileNameLen ?>) == 0) {
09e53d3c38 2019-09-20 71: <?= $indent ?> return(<?= $outputFileIndex ?>);
09e53d3c38 2019-09-20 72: <?= $indent ?>}
09e53d3c38 2019-09-20 73: <?
09e53d3c38 2019-09-20 74: }
09e53d3c38 2019-09-20 75: }
76: ?>
77: static long xvfs_<?= $::xvfs::fsName ?>_nameToIndex(const char *path) {
09e53d3c38 2019-09-20 78: <?
09e53d3c38 2019-09-20 79: for {set index 0} {$index < [llength $::xvfs::outputFiles]} {incr index} {
09e53d3c38 2019-09-20 80: set outputFileName [lindex $::xvfs::outputFiles $index]
09e53d3c38 2019-09-20 81: set outputFileNameLen [string length $outputFileName]
09e53d3c38 2019-09-20 82: set outputFileNameHash [zlib adler32 $outputFileName 0]
09e53d3c38 2019-09-20 83: lappend outputFileNameHashToIndex([list $outputFileNameLen $outputFileNameHash]) $index
09e53d3c38 2019-09-20 84: lappend outputFileNameLenToIndex($outputFileNameLen) $index
09e53d3c38 2019-09-20 85: }
86:
09e53d3c38 2019-09-20 87: set needZlib false
09e53d3c38 2019-09-20 88: foreach {outputFileNameLen outputFileIndexes} [lsort -stride 2 -dictionary [array get outputFileNameLenToIndex]] {
09e53d3c38 2019-09-20 89: if {[llength $outputFileIndexes] > $::xvfs::hashNameThreshold} {
09e53d3c38 2019-09-20 90: set needZlib true
09e53d3c38 2019-09-20 91: break;
09e53d3c38 2019-09-20 92: }
09e53d3c38 2019-09-20 93: }
09e53d3c38 2019-09-20 94: ?><?
09e53d3c38 2019-09-20 95: if {$needZlib} {
09e53d3c38 2019-09-20 96: ?> unsigned int pathHash;
09e53d3c38 2019-09-20 97: <? } ?> size_t pathLen;
09e53d3c38 2019-09-20 98:
99: if (path == NULL) {
100: return(XVFS_NAME_LOOKUP_ERROR);
101: }
102:
103: pathLen = strlen(path);
09e53d3c38 2019-09-20 104: switch (pathLen) {
09e53d3c38 2019-09-20 105: <?
09e53d3c38 2019-09-20 106:
09e53d3c38 2019-09-20 107: foreach {outputFileNameLen outputFileIndexes} [lsort -stride 2 -dictionary [array get outputFileNameLenToIndex]] {
09e53d3c38 2019-09-20 108: ?> case <?= $outputFileNameLen ?>:
09e53d3c38 2019-09-20 109: <?
09e53d3c38 2019-09-20 110: if {[llength $outputFileIndexes] > $::xvfs::hashNameThreshold} {
09e53d3c38 2019-09-20 111: ?> pathHash = Tcl_ZlibAdler32(0, (const unsigned char *) path, <?= $outputFileNameLen ?>);
09e53d3c38 2019-09-20 112: switch (pathHash) {
09e53d3c38 2019-09-20 113: <?
09e53d3c38 2019-09-20 114: foreach {key outputFileIndexes} [lsort -stride 2 -dictionary [array get outputFileNameHashToIndex [list $outputFileNameLen *]]] {
09e53d3c38 2019-09-20 115: set outputFileNameHash [lindex $key 1]
09e53d3c38 2019-09-20 116: ?> case <?= $outputFileNameHash ?>:
09e53d3c38 2019-09-20 117: <?
09e53d3c38 2019-09-20 118: emitFilenameVerification 5 $outputFileNameLen $outputFileIndexes
09e53d3c38 2019-09-20 119: ?> break;
09e53d3c38 2019-09-20 120: <?
09e53d3c38 2019-09-20 121: }
09e53d3c38 2019-09-20 122: ?> }
09e53d3c38 2019-09-20 123: <?
09e53d3c38 2019-09-20 124: } else {
09e53d3c38 2019-09-20 125: emitFilenameVerification 3 $outputFileNameLen $outputFileIndexes
09e53d3c38 2019-09-20 126: }
09e53d3c38 2019-09-20 127: ?> break;
09e53d3c38 2019-09-20 128: <? } ?> }
129:
130: return(XVFS_NAME_LOOKUP_ERROR);
131: }
132:
133: static const char **xvfs_<?= $::xvfs::fsName ?>_getChildren(const char *path, Tcl_WideInt *count) {
134: const struct xvfs_file_data *fileInfo;
135: long inode;
136:
137: /*
138: * Validate input parameters
139: */
140: if (count == NULL) {
141: return(NULL);
142: }
143:
144: /*
145: * Get the inode from the lookup function
146: */
147: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
148: if (inode == XVFS_NAME_LOOKUP_ERROR) {
149: *count = XVFS_RV_ERR_ENOENT;
150: return(NULL);
151: }
152:
153: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
154:
155: /*
156: * Ensure this is a directory
157: */
158: if (fileInfo->type != XVFS_FILE_TYPE_DIR) {
159: *count = XVFS_RV_ERR_ENOTDIR;
160: return(NULL);
161: }
162:
163: *count = fileInfo->size;
164: return(fileInfo->data.dirChildren);
165: }
166:
167: static const unsigned char *xvfs_<?= $::xvfs::fsName ?>_getData(const char *path, Tcl_WideInt start, Tcl_WideInt *length) {
168: const struct xvfs_file_data *fileInfo;
169: Tcl_WideInt resultLength;
170: long inode;
171:
172: /*
173: * Validate input parameters
174: */
175: if (length == NULL) {
176: return(NULL);
177: }
178:
179: if (start < 0) {
180: *length = XVFS_RV_ERR_EINVAL;
181: return(NULL);
182: }
183:
184: if (*length < 0) {
185: *length = XVFS_RV_ERR_EINVAL;
186: return(NULL);
187: }
188:
189: /*
190: * Get the inode from the lookup function
191: */
192: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
193: if (inode == XVFS_NAME_LOOKUP_ERROR) {
194: *length = XVFS_RV_ERR_ENOENT;
195: return(NULL);
196: }
197:
198: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
199:
200: /*
201: * Ensure this is a file that can be read
202: */
203: if (fileInfo->type != XVFS_FILE_TYPE_REG) {
204: *length = XVFS_RV_ERR_EISDIR;
205: return(NULL);
206: }
207:
208: /*
209: * Validate the length
210: */
211: if (start > fileInfo->size) {
212: *length = XVFS_RV_ERR_EFAULT;
213: return(NULL);
214: }
215:
216: if (*length == 0) {
217: resultLength = fileInfo->size - start;
218: } else {
219: resultLength = MIN(fileInfo->size - start, *length);
220: }
221: *length = resultLength;
222:
223: /*
224: * Return the data
225: */
226: return(fileInfo->data.fileContents + start);
227: }
228:
229: static int xvfs_<?= $::xvfs::fsName ?>_getStat(const char *path, Tcl_StatBuf *statBuf) {
230: const struct xvfs_file_data *fileInfo;
231: long inode;
232:
233: /*
234: * Validate input parameters
235: */
236: if (!statBuf) {
237: return(XVFS_RV_ERR_EINVAL);
238: }
239:
240: /*
241: * Get the inode from the lookup function
242: */
243: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
244: if (inode == XVFS_NAME_LOOKUP_ERROR) {
245: return(XVFS_RV_ERR_ENOENT);
246: }
247:
248: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
249:
250: statBuf->st_dev = <?= [zlib adler32 $::xvfs::fsName] ?>;
251: statBuf->st_rdev = <?= [zlib adler32 $::xvfs::fsName] ?>;
252: statBuf->st_ino = inode;
253: statBuf->st_uid = 0;
254: statBuf->st_gid = 0;
255: statBuf->st_atime = 0;
256: statBuf->st_ctime = 0;
257: statBuf->st_mtime = 0;
258: #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
259: statBuf->st_blksize = XVFS_FILE_BLOCKSIZE;
260: #endif
261:
262: if (fileInfo->type == XVFS_FILE_TYPE_REG) {
263: statBuf->st_mode = 0100444;
264: statBuf->st_nlink = 1;
265: statBuf->st_size = fileInfo->size;
266: #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
267: statBuf->st_blocks = (fileInfo->size + statBuf->st_blksize - 1) / statBuf->st_blksize;
268: #endif
269: } else if (fileInfo->type == XVFS_FILE_TYPE_DIR) {
270: statBuf->st_mode = 040555;
271: statBuf->st_nlink = fileInfo->size;
272: statBuf->st_size = fileInfo->size;
273: #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
274: statBuf->st_blocks = 1;
275: #endif
276: }
277:
278: return(0);
279: }
280:
281: static struct Xvfs_FSInfo xvfs_<?= $::xvfs::fsName ?>_fsInfo = {
282: .protocolVersion = XVFS_PROTOCOL_VERSION,
283: .name = "<?= $::xvfs::fsName ?>",
284: .getChildrenProc = xvfs_<?= $::xvfs::fsName ?>_getChildren,
285: .getDataProc = xvfs_<?= $::xvfs::fsName ?>_getData,
286: .getStatProc = xvfs_<?= $::xvfs::fsName ?>_getStat
287: };
288:
289: int Xvfs_<?= $::xvfs::fsName ?>_Init(Tcl_Interp *interp) {
290: int register_ret;
291:
292: #ifdef USE_TCL_STUBS
293: const char *tclInitStubs_ret;
294: /* Initialize Stubs */
295: tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0);
296: if (!tclInitStubs_ret) {
297: return(TCL_ERROR);
298: }
299: #endif
300:
301: register_ret = Xvfs_Register(interp, &xvfs_<?= $::xvfs::fsName ?>_fsInfo);
302: if (register_ret != TCL_OK) {
303: return(register_ret);
304: }
305:
306: return(TCL_OK);
307: }
308: #undef XVFS_NAME_LOOKUP_ERROR
309: #undef XVFS_FILE_BLOCKSIZE