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