Lines of
lib/xvfs/xvfs.c.rvt
from check-in c89b6aa781
that are changed by the sequence of edits moving toward
check-in 37d00c3cfb:
1: <?
2: if {[info exists ::xvfs::xvfsCoreH]} {
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:
58: xvfs::main $::xvfs::argv
59:
60: ?>
61: static long xvfs_<?= $::xvfs::fsName ?>_nameToIndex(const char *path) {
c89b6aa781 2019-10-10 62: long pathIndex;
63: ssize_t pathLen;
64:
65: if (path == NULL) {
66: return(XVFS_NAME_LOOKUP_ERROR);
67: }
68:
69: pathLen = strlen(path);
70:
71: pathIndex = <?= [::xvfs::generatePerfectHashFunctionCall "path" pathLen XVFS_NAME_LOOKUP_ERROR $::xvfs::outputFiles] ?>;
72: if (pathIndex < 0 || pathIndex >= <?= [llength $::xvfs::outputFiles] ?>) {
73: pathIndex = XVFS_NAME_LOOKUP_ERROR;
74: }
75:
76: if (pathIndex != XVFS_NAME_LOOKUP_ERROR) {
77: if (strcmp(path, xvfs_<?= $::xvfs::fsName ?>_data[pathIndex].name) == 0) {
78: return(pathIndex);
79: }
80: }
c89b6aa781 2019-10-10 81:
82: return(XVFS_NAME_LOOKUP_ERROR);
83: }
84:
85: static const char **xvfs_<?= $::xvfs::fsName ?>_getChildren(const char *path, Tcl_WideInt *count) {
86: const struct xvfs_file_data *fileInfo;
87: long inode;
88:
89: /*
90: * Validate input parameters
91: */
92: if (count == NULL) {
93: return(NULL);
94: }
95:
96: /*
97: * Get the inode from the lookup function
98: */
99: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
100: if (inode == XVFS_NAME_LOOKUP_ERROR) {
101: *count = XVFS_RV_ERR_ENOENT;
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:
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;
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: }
140:
141: /*
142: * Get the inode from the lookup function
143: */
144: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
145: if (inode == XVFS_NAME_LOOKUP_ERROR) {
146: *length = XVFS_RV_ERR_ENOENT;
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:
181: static int xvfs_<?= $::xvfs::fsName ?>_getStat(const char *path, Tcl_StatBuf *statBuf) {
182: const struct xvfs_file_data *fileInfo;
183: long inode;
184:
185: /*
186: * Validate input parameters
187: */
188: if (!statBuf) {
189: return(XVFS_RV_ERR_EINVAL);
190: }
191:
192: /*
193: * Get the inode from the lookup function
194: */
195: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
196: if (inode == XVFS_NAME_LOOKUP_ERROR) {
197: return(XVFS_RV_ERR_ENOENT);
198: }
199:
200: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
201:
202: statBuf->st_dev = <?= [zlib adler32 $::xvfs::fsName] ?>;
203: statBuf->st_rdev = <?= [zlib adler32 $::xvfs::fsName] ?>;
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: int Xvfs_<?= $::xvfs::fsName ?>_Init(Tcl_Interp *interp) {
242: int register_ret;
243:
244: #ifdef USE_TCL_STUBS
245: const char *tclInitStubs_ret;
246: /* Initialize Stubs */
247: tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0);
248: if (!tclInitStubs_ret) {
249: return(TCL_ERROR);
250: }
251: #endif
252:
253: register_ret = Xvfs_Register(interp, &xvfs_<?= $::xvfs::fsName ?>_fsInfo);
254: if (register_ret != TCL_OK) {
255: return(register_ret);
256: }
257:
258: return(TCL_OK);
259: }
260: #undef XVFS_NAME_LOOKUP_ERROR
261: #undef XVFS_FILE_BLOCKSIZE