Lines of
lib/xvfs/xvfs.c.rvt
from check-in 717062426a
that are changed by the sequence of edits moving toward
check-in 142a373444:
1: <?
2: # Care must be taken when editing this file as
3: # it may be processed by either "xvfs-create"
4: # which uses a full Tcl and Rivet parser
5: # or by "xvfs-create-c" which uses a much
6: # simpler one that only knows about printable
7: # sections and ignores all Tcl sections
8:
9: if {[info exists ::xvfs::xvfsCoreH]} {
10: ::minirivet::_emitOutput $::xvfs::xvfsCoreH
11: } else {
12: ?>#include <xvfs-core.h><? } ?>
13: #include <sys/stat.h>
14: #include <string.h>
15: #include <tcl.h>
16:
17: #define XVFS_NAME_LOOKUP_ERROR (-1)
18: #define XVFS_FILE_BLOCKSIZE 1024
19:
20: /*
21: * XXX:TODO: Determine this automatically rather than
22: * by heuristics
23: */
24: #define HAVE_STRUCT_STAT_ST_BLKSIZE 1
25: #define HAVE_STRUCT_STAT_ST_BLOCKS 1
26: #ifdef WIN32
27: # undef HAVE_STRUCT_STAT_ST_BLKSIZE
28: # undef HAVE_STRUCT_STAT_ST_BLOCKS
29: #endif
30:
31: #ifndef MIN
32: #define MIN(a, b) (((a) < (b)) ? (a) : (b))
33: #endif
34:
35: #ifndef HAVE_DEFINED_XVFS_FILE_TYPE_T
36: #define HAVE_DEFINED_XVFS_FILE_TYPE_T 1
37: typedef enum {
38: XVFS_FILE_TYPE_REG,
39: XVFS_FILE_TYPE_DIR
40: } xvfs_file_type_t;
41: #endif
42:
43: #ifndef HAVE_DEFINED_XVFS_SIZE_T
44: #define HAVE_DEFINED_XVFS_SIZE_T 1
45: typedef Tcl_WideInt xvfs_size_t;
46: #endif
47:
48: #ifndef HAVE_DEFINED_XVFS_FILE_DATA
49: #define HAVE_DEFINED_XVFS_FILE_DATA 1
50: struct xvfs_file_data {
51: const char * const name;
52: const xvfs_file_type_t type;
53: const xvfs_size_t size;
54: union {
55: const unsigned char * const fileContents;
56: const char **dirChildren;
57: } data;
58: };
59: #endif
60:
61: <?
62: package require xvfs
63:
64: set ::xvfs::fileInfoStruct [xvfs::main $::xvfs::argv]
65: ?><?= $::xvfs::fileInfoStruct ?>
66: static long xvfs_<?= $::xvfs::fsName ?>_nameToIndex(const char *path) {
67: <?
68: set hashTable [::xvfs::generateHashTable pathIndex path pathLen XVFS_NAME_LOOKUP_ERROR $::xvfs::outputFiles prefix "\t" hashTableSize 30 validate "strcmp(path, xvfs_${::xvfs::fsName}_data\[pathIndex\].name) == 0" onValidated "return(pathIndex);"]
69: set hashTableHeader [dict get $hashTable header]
70: ?><?= $hashTableHeader ?>
71: long pathIndex;
72: size_t pathLen;
73:
74: if (path == NULL) {
75: return(XVFS_NAME_LOOKUP_ERROR);
76: }
77:
78: pathLen = strlen(path);
79:
80: <?= [dict get $hashTable body] ?>
81:
82: return(XVFS_NAME_LOOKUP_ERROR);
83: }
84:
717062426a 2020-04-13 85: static const char **xvfs_<?= $::xvfs::fsName ?>_getChildren(const char *path, Tcl_WideInt *count) {
86: const struct xvfs_file_data *fileInfo;
717062426a 2020-04-13 87: long inode;
88:
89: /*
90: * Validate input parameters
91: */
92: if (count == NULL) {
93: return(NULL);
94: }
95:
96: /*
717062426a 2020-04-13 97: * Get the inode from the lookup function
717062426a 2020-04-13 98: */
717062426a 2020-04-13 99: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
717062426a 2020-04-13 100: if (inode == XVFS_NAME_LOOKUP_ERROR) {
717062426a 2020-04-13 101: *count = XVFS_RV_ERR_ENOENT;
717062426a 2020-04-13 102: return(NULL);
103: }
104:
105: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
106:
107: /*
108: * Ensure this is a directory
109: */
110: if (fileInfo->type != XVFS_FILE_TYPE_DIR) {
111: *count = XVFS_RV_ERR_ENOTDIR;
112: return(NULL);
113: }
114:
115: *count = fileInfo->size;
116: return(fileInfo->data.dirChildren);
117: }
118:
717062426a 2020-04-13 119: static const unsigned char *xvfs_<?= $::xvfs::fsName ?>_getData(const char *path, Tcl_WideInt start, Tcl_WideInt *length) {
120: const struct xvfs_file_data *fileInfo;
121: Tcl_WideInt resultLength;
717062426a 2020-04-13 122: long inode;
123:
124: /*
125: * Validate input parameters
126: */
127: if (length == NULL) {
128: return(NULL);
129: }
130:
131: if (start < 0) {
132: *length = XVFS_RV_ERR_EINVAL;
133: return(NULL);
134: }
135:
136: if (*length < 0) {
137: *length = XVFS_RV_ERR_EINVAL;
138: return(NULL);
139: }
717062426a 2020-04-13 140:
717062426a 2020-04-13 141: /*
717062426a 2020-04-13 142: * Get the inode from the lookup function
717062426a 2020-04-13 143: */
717062426a 2020-04-13 144: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
717062426a 2020-04-13 145: if (inode == XVFS_NAME_LOOKUP_ERROR) {
717062426a 2020-04-13 146: *length = XVFS_RV_ERR_ENOENT;
717062426a 2020-04-13 147: return(NULL);
148: }
149:
150: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
151:
152: /*
153: * Ensure this is a file that can be read
154: */
155: if (fileInfo->type != XVFS_FILE_TYPE_REG) {
156: *length = XVFS_RV_ERR_EISDIR;
157: return(NULL);
158: }
159:
160: /*
161: * Validate the length
162: */
163: if (start > fileInfo->size) {
164: *length = XVFS_RV_ERR_EFAULT;
165: return(NULL);
166: }
167:
168: if (*length == 0) {
169: resultLength = fileInfo->size - start;
170: } else {
171: resultLength = MIN(fileInfo->size - start, *length);
172: }
173: *length = resultLength;
174:
175: /*
176: * Return the data
177: */
178: return(fileInfo->data.fileContents + start);
179: }
180:
717062426a 2020-04-13 181: static int xvfs_<?= $::xvfs::fsName ?>_getStat(const char *path, Tcl_StatBuf *statBuf) {
182: const struct xvfs_file_data *fileInfo;
717062426a 2020-04-13 183: long inode;
184:
185: /*
186: * Validate input parameters
187: */
188: if (!statBuf) {
189: return(XVFS_RV_ERR_EINVAL);
190: }
191:
192: /*
717062426a 2020-04-13 193: * Get the inode from the lookup function
717062426a 2020-04-13 194: */
717062426a 2020-04-13 195: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
717062426a 2020-04-13 196: if (inode == XVFS_NAME_LOOKUP_ERROR) {
717062426a 2020-04-13 197: return(XVFS_RV_ERR_ENOENT);
198: }
199:
200: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
201:
202: statBuf->st_dev = <?= [zlib adler32 $::xvfs::fsName 0] ?>;
203: statBuf->st_rdev = <?= [zlib adler32 $::xvfs::fsName 0] ?>;
204: statBuf->st_ino = inode;
205: statBuf->st_uid = 0;
206: statBuf->st_gid = 0;
207: statBuf->st_atime = 0;
208: statBuf->st_ctime = 0;
209: statBuf->st_mtime = 0;
210: #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
211: statBuf->st_blksize = XVFS_FILE_BLOCKSIZE;
212: #endif
213:
214: if (fileInfo->type == XVFS_FILE_TYPE_REG) {
215: statBuf->st_mode = 0100444;
216: statBuf->st_nlink = 1;
217: statBuf->st_size = fileInfo->size;
218: #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
219: statBuf->st_blocks = (fileInfo->size + statBuf->st_blksize - 1) / statBuf->st_blksize;
220: #endif
221: } else if (fileInfo->type == XVFS_FILE_TYPE_DIR) {
222: statBuf->st_mode = 040555;
223: statBuf->st_nlink = fileInfo->size;
224: statBuf->st_size = fileInfo->size;
225: #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
226: statBuf->st_blocks = 1;
227: #endif
228: }
229:
230: return(0);
231: }
232:
233: static struct Xvfs_FSInfo xvfs_<?= $::xvfs::fsName ?>_fsInfo = {
234: .protocolVersion = XVFS_PROTOCOL_VERSION,
235: .name = "<?= $::xvfs::fsName ?>",
236: .getChildrenProc = xvfs_<?= $::xvfs::fsName ?>_getChildren,
237: .getDataProc = xvfs_<?= $::xvfs::fsName ?>_getData,
238: .getStatProc = xvfs_<?= $::xvfs::fsName ?>_getStat
239: };
240:
241: #ifdef XVFS_<?= $::xvfs::fsName ?>_INIT_STATIC
242: static
243: #endif
244: int Xvfs_<?= $::xvfs::fsName ?>_Init(Tcl_Interp *interp) {
245: int register_ret;
246:
247: #ifdef USE_TCL_STUBS
248: const char *tclInitStubs_ret;
249: /* Initialize Stubs */
250: tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0);
251: if (!tclInitStubs_ret) {
252: return(TCL_ERROR);
253: }
254: #endif
255:
256: register_ret = Xvfs_Register(interp, &xvfs_<?= $::xvfs::fsName ?>_fsInfo);
257: if (register_ret != TCL_OK) {
258: return(register_ret);
259: }
260:
261: return(TCL_OK);
262: }
263: #undef XVFS_NAME_LOOKUP_ERROR
264: #undef XVFS_FILE_BLOCKSIZE
265: #undef XVFS_<?= $::xvfs::fsName ?>_INIT_STATIC