Lines of
xvfs-core.c
from check-in 9d3052c6f1
that are changed by the sequence of edits moving toward
check-in b8cca3a6b4:
1: #include <xvfs-core.h>
2: #include <string.h>
3: #include <tcl.h>
4:
5: #if defined(XVFS_MODE_FLEXIBLE) || defined(XVFS_MODE_SERVER)
6: #define XVFS_INTERNAL_SERVER_MAGIC "\xD4\xF3\x05\x96\x25\xCF\xAF\xFE"
7: #define XVFS_INTERNAL_SERVER_MAGIC_LEN 8
8:
9: struct xvfs_tclfs_server_info {
10: char magic[XVFS_INTERNAL_SERVER_MAGIC_LEN];
11: int (*registerProc)(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo);
12: };
13: #endif /* XVFS_MODE_FLEXIBLE || XVFS_MODE_SERVER */
14:
15: #if defined(XVFS_MODE_SERVER) || defined(XVFS_MODE_STANDALONE) || defined(XVFS_MODE_FLEXIBLE)
16: #define XVFS_ROOT_MOUNTPOINT "//xvfs:/"
17:
18: struct xvfs_tclfs_instance_info {
19: struct Xvfs_FSInfo *fsInfo;
20: Tcl_Obj *mountpoint;
21: };
22:
23: /*
24: * Internal Core Utilities
25: */
26: static const char *xvfs_relativePath(Tcl_Obj *path, struct xvfs_tclfs_instance_info *info) {
27: const char *pathStr, *rootStr;
28: int pathLen, rootLen;
29:
30: pathStr = Tcl_GetStringFromObj(path, &pathLen);
31: rootStr = Tcl_GetStringFromObj(info->mountpoint, &rootLen);
32:
33: if (pathLen < rootLen) {
34: return(NULL);
35: }
36:
37: if (memcmp(pathStr, rootStr, rootLen) != 0) {
38: return(NULL);
39: }
40:
41: if (pathLen == rootLen) {
42: return("");
43: }
44:
45: /* XXX:TODO: Should this use the native OS path separator ? */
46: if (pathStr[rootLen] != '/') {
47: return(NULL);
48: }
49:
50: return(pathStr + rootLen + 1);
51: }
52:
53: /*
54: * Internal Tcl_Filesystem functions, with the appropriate instance info
55: */
56: static int xvfs_tclfs_pathInFilesystem(Tcl_Obj *path, ClientData *dataPtr, struct xvfs_tclfs_instance_info *instanceInfo) {
57: const char *relativePath;
58:
59: relativePath = xvfs_relativePath(path, instanceInfo);
60: if (!relativePath) {
61: return(-1);
62: }
63:
64: return(TCL_OK);
65: }
66:
67: static int xvfs_tclfs_stat(Tcl_Obj *path, Tcl_StatBuf *statBuf, struct xvfs_tclfs_instance_info *instanceInfo) {
68: const char *pathStr;
69: int retval;
70:
71: pathStr = xvfs_relativePath(path, instanceInfo);
72:
73: retval = instanceInfo->fsInfo->getStatProc(pathStr, statBuf);
74:
75: return(retval);
76: }
77:
78: static Tcl_Obj *xvfs_tclfs_listVolumes(struct xvfs_tclfs_instance_info *instanceInfo) {
79: return(NULL);
80: }
81:
82: static Tcl_Channel xvfs_tclfs_openFileChannel(Tcl_Interp *interp, Tcl_Obj *path, int mode, int permissions, struct xvfs_tclfs_instance_info *instanceInfo) {
83: const char *pathStr;
84:
85: pathStr = xvfs_relativePath(path, instanceInfo);
86: /*
87: * XXX:TODO: Do something to create the Tcl_Channel we
88: * need to return here
89: */
90:
91: return(NULL);
92: }
93: #endif /* XVFS_MODE_SERVER || XVFS_MODE_STANDALONE || XVFS_MODE_FLEIXBLE */
94:
95: #if defined(XVFS_MODE_STANDALONE) || defined(XVFS_MODE_FLEXIBLE)
96: /*
97: * Tcl_Filesystem handlers for the standalone implementation
98: */
99: static struct xvfs_tclfs_instance_info xvfs_tclfs_standalone_info;
100: static int xvfs_tclfs_standalone_pathInFilesystem(Tcl_Obj *path, ClientData *dataPtr) {
101: return(xvfs_tclfs_pathInFilesystem(path, dataPtr, &xvfs_tclfs_standalone_info));
102: }
103:
104: static int xvfs_tclfs_standalone_stat(Tcl_Obj *path, Tcl_StatBuf *statBuf) {
105: return(xvfs_tclfs_stat(path, statBuf, &xvfs_tclfs_standalone_info));
106: }
107:
108: static Tcl_Obj *xvfs_tclfs_standalone_listVolumes(void) {
109: return(xvfs_tclfs_listVolumes(&xvfs_tclfs_standalone_info));
110: }
111:
112: static Tcl_Channel xvfs_tclfs_standalone_openFileChannel(Tcl_Interp *interp, Tcl_Obj *path, int mode, int permissions) {
113: return(xvfs_tclfs_openFileChannel(interp, path, mode, permissions, &xvfs_tclfs_standalone_info));
114: }
115:
116: /*
117: * There are three (3) modes of operation for Xvfs_Register:
118: * 1. standalone -- We register our own Tcl_Filesystem
119: * and handle requests under `//xvfs:/<fsName>`
120: * 2. client -- A single Tcl_Filesystem is registered for the
121: * interp to handle requests under `//xvfs:/` which
122: * then dispatches to the appropriate registered
123: * handler
124: * 3. flexible -- Attempts to find a core Xvfs instance for the
125: * process at runtime, if found do #2, otherwise
126: * fallback to #1
127: *
128: */
129: static Tcl_Filesystem xvfs_tclfs_standalone_fs;
9d3052c6f1 2019-05-08 130: int xvfs_standalone_register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
131: int tcl_ret;
132: static int registered = 0;
133:
134: /*
135: * Ensure this instance is not already registered
136: */
137: if (registered) {
138: return(TCL_OK);
139: }
140: registered = 1;
141:
142: /*
143: * In standalone mode, we only support the same protocol we are
144: * compiling for.
145: */
146: if (fsInfo->protocolVersion != XVFS_PROTOCOL_VERSION) {
147: if (interp) {
148: Tcl_SetResult(interp, "Protocol mismatch", NULL);
149: }
150: return(TCL_ERROR);
151: }
152:
153: xvfs_tclfs_standalone_fs.typeName = "xvfs";
154: xvfs_tclfs_standalone_fs.structureLength = sizeof(xvfs_tclfs_standalone_fs);
155: xvfs_tclfs_standalone_fs.version = TCL_FILESYSTEM_VERSION_1;
156: xvfs_tclfs_standalone_fs.pathInFilesystemProc = xvfs_tclfs_standalone_pathInFilesystem;
157: xvfs_tclfs_standalone_fs.dupInternalRepProc = NULL;
158: xvfs_tclfs_standalone_fs.freeInternalRepProc = NULL;
159: xvfs_tclfs_standalone_fs.internalToNormalizedProc = NULL;
160: xvfs_tclfs_standalone_fs.createInternalRepProc = NULL;
161: xvfs_tclfs_standalone_fs.normalizePathProc = NULL;
162: xvfs_tclfs_standalone_fs.filesystemPathTypeProc = NULL;
163: xvfs_tclfs_standalone_fs.filesystemSeparatorProc = NULL;
164: xvfs_tclfs_standalone_fs.statProc = xvfs_tclfs_standalone_stat;
165: xvfs_tclfs_standalone_fs.accessProc = NULL;
166: xvfs_tclfs_standalone_fs.openFileChannelProc = xvfs_tclfs_standalone_openFileChannel;
167: xvfs_tclfs_standalone_fs.matchInDirectoryProc = NULL;
168: xvfs_tclfs_standalone_fs.utimeProc = NULL;
169: xvfs_tclfs_standalone_fs.linkProc = NULL;
170: xvfs_tclfs_standalone_fs.listVolumesProc = xvfs_tclfs_standalone_listVolumes;
171: xvfs_tclfs_standalone_fs.fileAttrStringsProc = NULL;
172: xvfs_tclfs_standalone_fs.fileAttrsGetProc = NULL;
173: xvfs_tclfs_standalone_fs.fileAttrsSetProc = NULL;
174: xvfs_tclfs_standalone_fs.createDirectoryProc = NULL;
175: xvfs_tclfs_standalone_fs.removeDirectoryProc = NULL;
176: xvfs_tclfs_standalone_fs.deleteFileProc = NULL;
177: xvfs_tclfs_standalone_fs.copyFileProc = NULL;
178: xvfs_tclfs_standalone_fs.renameFileProc = NULL;
179: xvfs_tclfs_standalone_fs.copyDirectoryProc = NULL;
180: xvfs_tclfs_standalone_fs.lstatProc = NULL;
181: xvfs_tclfs_standalone_fs.loadFileProc = NULL;
182: xvfs_tclfs_standalone_fs.getCwdProc = NULL;
183: xvfs_tclfs_standalone_fs.chdirProc = NULL;
184:
185: xvfs_tclfs_standalone_info.fsInfo = fsInfo;
186: xvfs_tclfs_standalone_info.mountpoint = Tcl_NewObj();
187: Tcl_AppendStringsToObj(xvfs_tclfs_standalone_info.mountpoint, XVFS_ROOT_MOUNTPOINT, fsInfo->name, NULL);
188:
189: tcl_ret = Tcl_FSRegister(NULL, &xvfs_tclfs_standalone_fs);
190: if (tcl_ret != TCL_OK) {
191: if (interp) {
192: Tcl_SetResult(interp, "Tcl_FSRegister() failed", NULL);
193: }
194:
195: return(tcl_ret);
196: }
197:
198: return(TCL_OK);
199: }
200: #endif /* XVFS_MODE_STANDALONE || XVFS_MODE_FLEXIBLE */
201:
202: #if defined(XVFS_MODE_FLEXIBLE)
9d3052c6f1 2019-05-08 203: int xvfs_flexible_register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
204: ClientData fsHandlerDataRaw;
205: struct xvfs_tclfs_server_info *fsHandlerData;
206: const Tcl_Filesystem *fsHandler;
207: int (*xvfs_register)(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo);
208: Tcl_Obj *rootPathObj;
209:
210: xvfs_register = &xvfs_standalone_register;
211:
212: rootPathObj = Tcl_NewStringObj(XVFS_ROOT_MOUNTPOINT, -1);
213: if (!rootPathObj) {
214: return(xvfs_register(interp, fsInfo));
215: }
216:
217: Tcl_IncrRefCount(rootPathObj);
218: fsHandler = Tcl_FSGetFileSystemForPath(rootPathObj);
219: Tcl_DecrRefCount(rootPathObj);
220:
221: if (!fsHandler) {
222: return(xvfs_register(interp, fsInfo));
223: }
224:
225: fsHandlerDataRaw = Tcl_FSData(fsHandler);
226: if (!fsHandlerDataRaw) {
227: return(xvfs_register(interp, fsInfo));
228: }
229:
230: fsHandlerData = (struct xvfs_tclfs_server_info *) fsHandlerDataRaw;
231:
232: /*
233: * XXX:TODO: What is the chance that the handler for //xvfs:/ hold
234: * client data smaller than XVFS_INTERNAL_SERVER_MAGIC_LEN ?
235: */
236: if (memcmp(fsHandlerData->magic, XVFS_INTERNAL_SERVER_MAGIC, sizeof(fsHandlerData->magic)) == 0) {
237: xvfs_register = fsHandlerData->registerProc;
238: }
239:
240: return(xvfs_register(interp, fsInfo));
241: }
242: #endif /* XVFS_MODE_FLEXIBLE */
243:
244: #if defined(XVFS_MODE_SERVER)
245: int Xvfs_Register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
246: return(TCL_ERROR);
247: }
248: #endif /* XVFS_MODE_SERVER */