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