Lines of
xvfs.c.rvt
from check-in fb9dd5d783
that are changed by the sequence of edits moving toward
check-in 73cbe7370b:
1: #include <xvfs-core.h>
2: #include <unistd.h>
3: #include <string.h>
4: #include <tcl.h>
5: #include <sys/stat.h>
6:
7: #define XVFS_NAME_LOOKUP_ERROR (-1)
8: #define XVFS_FILE_BLOCKSIZE 1024
9:
10: #define MIN(a, b) (((a) < (b)) ? (a) : (b))
11:
12: typedef enum {
13: XVFS_FILE_TYPE_REG,
14: XVFS_FILE_TYPE_DIR
15: } xvfs_file_type_t;
16:
17: typedef Tcl_WideInt xvfs_size_t;
18:
19: struct xvfs_file_data {
20: const char *name;
21: xvfs_file_type_t type;
22: xvfs_size_t size;
23: union {
24: const unsigned char *fileContents;
25: const char **dirChildren;
26: } data;
27: };
28:
29: <?
30: package require xvfs
31: xvfs::main $argv
32: ?>
33: static long xvfs_<?= $::xvfs::fsName ?>_nameToIndex(const char *path) {
34: unsigned int pathHash;
35:
36: if (path == NULL) {
37: return(XVFS_NAME_LOOKUP_ERROR);
38: }
fb9dd5d783 2019-05-03 39:
fb9dd5d783 2019-05-03 40: pathHash = Tcl_ZlibAdler32(0, (const unsigned char *) path, strlen(path));
41: switch (pathHash) {
42: <?
43: for {set index 0} {$index < [llength $::xvfs::outputFiles]} {incr index} {
44: set outputFile [lindex $::xvfs::outputFiles $index]
45: set outputFileHash [zlib adler32 $outputFile 0]
46: lappend outputFileHashToIndex($outputFileHash) $index
47: }
48:
49: foreach {outputFileHash outputFileIndexes} [lsort -stride 2 -dictionary [array get outputFileHashToIndex]] {
50: ?> case <?= $outputFileHash ?>:
51: <?
52: foreach outputFileIndex $outputFileIndexes {
fb9dd5d783 2019-05-03 53: ?> if (strcmp(path, xvfs_<?= $::xvfs::fsName ?>_data[<?= $outputFileIndex ?>].name) == 0) {
54: return(<?= $outputFileIndex ?>);
55: }
56: <?
57: }
58: ?> break;
59: <? } ?>
60: }
61:
62: return(XVFS_NAME_LOOKUP_ERROR);
63: }
64:
65: static const char **xvfs_<?= $::xvfs::fsName ?>_getChildren(const char *path, Tcl_WideInt *count) {
66: struct xvfs_file_data *fileInfo;
67: long inode;
68:
69: /*
70: * Validate input parameters
71: */
72: if (count == NULL) {
73: return(NULL);
74: }
75:
76: /*
77: * Get the inode from the lookup function
78: */
79: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
80: if (inode == XVFS_NAME_LOOKUP_ERROR) {
81: return(NULL);
82: }
83:
84: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
85:
86: /*
87: * Ensure this is a directory
88: */
89: if (fileInfo->type != XVFS_FILE_TYPE_DIR) {
90: return(NULL);
91: }
92:
93: *count = fileInfo->size;
94: return(fileInfo->data.dirChildren);
95: }
96:
97: static const unsigned char *xvfs_<?= $::xvfs::fsName ?>_getData(const char *path, Tcl_WideInt start, Tcl_WideInt *length) {
98: struct xvfs_file_data *fileInfo;
99: Tcl_WideInt resultLength;
100: long inode;
101:
102: /*
103: * Validate input parameters
104: */
105: if (start < 0) {
106: return(NULL);
107: }
108:
109: if (length == NULL) {
110: return(NULL);
111: }
112:
113: if (*length < 0) {
114: return(NULL);
115: }
116:
117: /*
118: * Get the inode from the lookup function
119: */
120: inode = xvfs_<?= $::xvfs::fsName ?>_nameToIndex(path);
121: if (inode == XVFS_NAME_LOOKUP_ERROR) {
122: return(NULL);
123: }
124:
125: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
126:
127: /*
128: * Ensure this is a file that can be read
129: */
130: if (fileInfo->type != XVFS_FILE_TYPE_REG) {
131: return(NULL);
132: }
133:
134: /*
135: * Validate the length
136: */
137: if (start > fileInfo->size) {
138: *length = -1;
139: return(NULL);
140: }
141:
142: if (*length == 0) {
143: resultLength = fileInfo->size - start;
144: } else {
145: resultLength = MIN(fileInfo->size - start, *length);
146: }
147: *length = resultLength;
148:
149: /*
150: * Return the data
151: */
152: return(fileInfo->data.fileContents + start);
153: }
154:
155: static int xvfs_<?= $::xvfs::fsName ?>_getInfo(const char *path, Tcl_StatBuf *statBuf) {
156: struct xvfs_file_data *fileInfo;
157: long inode;
158:
159: /*
160: * Validate input parameters
161: */
162: if (!statBuf) {
163: return(-1);
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: return(-1);
172: }
173:
174: fileInfo = &xvfs_<?= $::xvfs::fsName ?>_data[inode];
175:
176: statBuf->st_dev = 0;
177: statBuf->st_rdev = 0;
178: statBuf->st_ino = inode;
179: statBuf->st_uid = -1;
180: statBuf->st_gid = -1;
181: statBuf->st_atime = 0;
182: statBuf->st_ctime = 0;
183: statBuf->st_mtime = 0;
184: statBuf->st_blksize = XVFS_FILE_BLOCKSIZE;
185:
186: if (fileInfo->type == XVFS_FILE_TYPE_REG) {
187: statBuf->st_mode = 0400;
188: statBuf->st_nlink = 1;
189: statBuf->st_size = fileInfo->size;
190: statBuf->st_blocks = (fileInfo->size + statBuf->st_blksize - 1) / statBuf->st_blksize;
191: } else if (fileInfo->type == XVFS_FILE_TYPE_DIR) {
192: statBuf->st_mode = 0500;
193: statBuf->st_nlink = fileInfo->size;
194: statBuf->st_size = fileInfo->size;
195: statBuf->st_blocks = 1;
196: }
197:
198: return(0);
199: }
200:
201:
202: static struct Xvfs_FSInfo xvfs_<?= $::xvfs::fsName ?>_fsInfo = {
203: .protocolVersion = XVFS_PROTOCOL_VERSION,
204: .name = "<?= $::xvfs::fsName ?>",
205: .getChildrenProc = xvfs_<?= $::xvfs::fsName ?>_getChildren,
206: .getDataProc = xvfs_<?= $::xvfs::fsName ?>_getData,
207: .getInfoProc = xvfs_<?= $::xvfs::fsName ?>_getInfo
208: };
209:
210: int Xvfs_<?= $::xvfs::fsName ?>_Init(Tcl_Interp *interp) {
211: int register_ret;
212:
213: #ifdef USE_TCL_STUBS
214: const char *tclInitStubs_ret;
215: /* Initialize Stubs */
216: tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0);
217: if (!tclInitStubs_ret) {
218: return(TCL_ERROR);
219: }
220: #endif
221:
222: register_ret = Xvfs_Register(interp, &xvfs_<?= $::xvfs::fsName ?>_fsInfo);
223: if (register_ret != TCL_OK) {
224: return(register_ret);
225: }
226:
227: return(TCL_OK);
228: }