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