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