Annotation For xvfs-core.c

Lines of xvfs-core.c from check-in 149aa89b7d that are changed by the sequence of edits moving toward check-in 38bed7cee0:

                         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;
149aa89b7d 2019-09-13   29: 	
                        30: 	pathStr = Tcl_GetStringFromObj(path, &pathLen);
                        31: 	rootStr = Tcl_GetStringFromObj(info->mountpoint, &rootLen);
149aa89b7d 2019-09-13   32: 	
                        33: 	if (pathLen < rootLen) {
                        34: 		return(NULL);
                        35: 	}
149aa89b7d 2019-09-13   36: 	
                        37: 	if (memcmp(pathStr, rootStr, rootLen) != 0) {
                        38: 		return(NULL);
                        39: 	}
149aa89b7d 2019-09-13   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: 	}
149aa89b7d 2019-09-13   49: 	
                        50: 	return(pathStr + rootLen + 1);
                        51: }
                        52: 
                        53: static const char *xvfs_perror(int xvfs_error) {
                        54: 	if (xvfs_error >= 0) {
                        55: 		return("Not an error");
                        56: 	}
                        57: 
                        58: 	switch (xvfs_error) {
                        59: 		case XVFS_RV_ERR_ENOENT:
                        60: 			return("No such file or directory");
                        61: 		case XVFS_RV_ERR_EINVAL:
                        62: 			return("Invalid argument");
                        63: 		case XVFS_RV_ERR_EISDIR:
                        64: 			return("Is a directory");
                        65: 		case XVFS_RV_ERR_ENOTDIR:
                        66: 			return("Not a directory");
                        67: 		case XVFS_RV_ERR_EFAULT:
                        68: 			return("Bad address");
                        69: 		default:
                        70: 			return("Unknown error");
                        71: 	}
                        72: }
                        73: 
                        74: /*
                        75:  * Internal Tcl_Filesystem functions, with the appropriate instance info
                        76:  */
                        77: static int xvfs_tclfs_pathInFilesystem(Tcl_Obj *path, ClientData *dataPtr, struct xvfs_tclfs_instance_info *instanceInfo) {
                        78: 	const char *relativePath;
149aa89b7d 2019-09-13   79: 	
                        80: 	relativePath = xvfs_relativePath(path, instanceInfo);
                        81: 	if (!relativePath) {
                        82: 		return(-1);
                        83: 	}
149aa89b7d 2019-09-13   84: 	
                        85: 	return(TCL_OK);
                        86: }
                        87: 
                        88: static int xvfs_tclfs_stat(Tcl_Obj *path, Tcl_StatBuf *statBuf, struct xvfs_tclfs_instance_info *instanceInfo) {
                        89: 	const char *pathStr;
                        90: 	int retval;
                        91: 
                        92: 	pathStr = xvfs_relativePath(path, instanceInfo);
149aa89b7d 2019-09-13   93: 	
                        94: 	retval = instanceInfo->fsInfo->getStatProc(pathStr, statBuf);
                        95: 	if (retval < 0) {
                        96: 		retval = -1;
                        97: 	}
149aa89b7d 2019-09-13   98: 	
                        99: 	return(retval);
                       100: }
                       101: 
                       102: static Tcl_Obj *xvfs_tclfs_listVolumes(struct xvfs_tclfs_instance_info *instanceInfo) {
                       103: 	return(NULL);
                       104: }
                       105: 
                       106: static Tcl_Channel xvfs_tclfs_openFileChannel(Tcl_Interp *interp, Tcl_Obj *path, int mode, int permissions, struct xvfs_tclfs_instance_info *instanceInfo) {
                       107: 	const char *pathStr;
149aa89b7d 2019-09-13  108: 	Tcl_WideInt length;
149aa89b7d 2019-09-13  109: 	const char *data;
                       110: 
                       111: 	pathStr = xvfs_relativePath(path, instanceInfo);
                       112: 
149aa89b7d 2019-09-13  113: 	/*
149aa89b7d 2019-09-13  114: 	 * XXX:TODO: Do something to create the Tcl_Channel we
149aa89b7d 2019-09-13  115: 	 * need to return here
149aa89b7d 2019-09-13  116: 	 */
                       117: 
149aa89b7d 2019-09-13  118: 	return(NULL);
                       119: }
                       120: #endif /* XVFS_MODE_SERVER || XVFS_MODE_STANDALONE || XVFS_MODE_FLEIXBLE */
                       121: 
                       122: #if defined(XVFS_MODE_STANDALONE) || defined(XVFS_MODE_FLEXIBLE)
                       123: /*
                       124:  * Tcl_Filesystem handlers for the standalone implementation
                       125:  */
                       126: static struct xvfs_tclfs_instance_info xvfs_tclfs_standalone_info;
                       127: static int xvfs_tclfs_standalone_pathInFilesystem(Tcl_Obj *path, ClientData *dataPtr) {
                       128: 	return(xvfs_tclfs_pathInFilesystem(path, dataPtr, &xvfs_tclfs_standalone_info));
                       129: }
                       130: 
                       131: static int xvfs_tclfs_standalone_stat(Tcl_Obj *path, Tcl_StatBuf *statBuf) {
                       132: 	return(xvfs_tclfs_stat(path, statBuf, &xvfs_tclfs_standalone_info));
                       133: }
                       134: 
                       135: static Tcl_Obj *xvfs_tclfs_standalone_listVolumes(void) {
                       136: 	return(xvfs_tclfs_listVolumes(&xvfs_tclfs_standalone_info));
                       137: }
                       138: 
                       139: static Tcl_Channel xvfs_tclfs_standalone_openFileChannel(Tcl_Interp *interp, Tcl_Obj *path, int mode, int permissions) {
                       140: 	return(xvfs_tclfs_openFileChannel(interp, path, mode, permissions, &xvfs_tclfs_standalone_info));
                       141: }
                       142: 
                       143: /*
                       144:  * There are three (3) modes of operation for Xvfs_Register:
                       145:  *    1. standalone -- We register our own Tcl_Filesystem
                       146:  *                     and handle requests under `//xvfs:/<fsName>`
                       147:  *    2. client -- A single Tcl_Filesystem is registered for the
                       148:  *                 interp to handle requests under `//xvfs:/` which
                       149:  *                 then dispatches to the appropriate registered
                       150:  *                 handler
                       151:  *    3. flexible -- Attempts to find a core Xvfs instance for the
                       152:  *                   process at runtime, if found do #2, otherwise
                       153:  *                   fallback to #1
                       154:  *
                       155:  */
                       156: static Tcl_Filesystem xvfs_tclfs_standalone_fs;
                       157: static int xvfs_standalone_register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
                       158: 	int tcl_ret;
                       159: 	static int registered = 0;
149aa89b7d 2019-09-13  160: 	
                       161: 	/*
                       162: 	 * Ensure this instance is not already registered
                       163: 	 */
                       164: 	if (registered) {
                       165: 		return(TCL_OK);
                       166: 	}
                       167: 	registered = 1;
                       168: 
                       169: 	/*
                       170: 	 * In standalone mode, we only support the same protocol we are
                       171: 	 * compiling for.
                       172: 	 */
                       173: 	if (fsInfo->protocolVersion != XVFS_PROTOCOL_VERSION) {
                       174: 		if (interp) {
                       175: 			Tcl_SetResult(interp, "Protocol mismatch", NULL);
                       176: 		}
                       177: 		return(TCL_ERROR);
                       178: 	}
149aa89b7d 2019-09-13  179: 	
                       180: 	xvfs_tclfs_standalone_fs.typeName                   = "xvfs";
                       181: 	xvfs_tclfs_standalone_fs.structureLength            = sizeof(xvfs_tclfs_standalone_fs);
                       182: 	xvfs_tclfs_standalone_fs.version                    = TCL_FILESYSTEM_VERSION_1;
                       183: 	xvfs_tclfs_standalone_fs.pathInFilesystemProc       = xvfs_tclfs_standalone_pathInFilesystem;
                       184: 	xvfs_tclfs_standalone_fs.dupInternalRepProc         = NULL;
                       185: 	xvfs_tclfs_standalone_fs.freeInternalRepProc        = NULL;
                       186: 	xvfs_tclfs_standalone_fs.internalToNormalizedProc   = NULL;
                       187: 	xvfs_tclfs_standalone_fs.createInternalRepProc      = NULL;
                       188: 	xvfs_tclfs_standalone_fs.normalizePathProc          = NULL;
                       189: 	xvfs_tclfs_standalone_fs.filesystemPathTypeProc     = NULL;
                       190: 	xvfs_tclfs_standalone_fs.filesystemSeparatorProc    = NULL;
                       191: 	xvfs_tclfs_standalone_fs.statProc                   = xvfs_tclfs_standalone_stat;
                       192: 	xvfs_tclfs_standalone_fs.accessProc                 = NULL;
                       193: 	xvfs_tclfs_standalone_fs.openFileChannelProc        = xvfs_tclfs_standalone_openFileChannel;
149aa89b7d 2019-09-13  194: 	xvfs_tclfs_standalone_fs.matchInDirectoryProc       = NULL;
                       195: 	xvfs_tclfs_standalone_fs.utimeProc                  = NULL;
                       196: 	xvfs_tclfs_standalone_fs.linkProc                   = NULL;
                       197: 	xvfs_tclfs_standalone_fs.listVolumesProc            = xvfs_tclfs_standalone_listVolumes;
                       198: 	xvfs_tclfs_standalone_fs.fileAttrStringsProc        = NULL;
                       199: 	xvfs_tclfs_standalone_fs.fileAttrsGetProc           = NULL;
                       200: 	xvfs_tclfs_standalone_fs.fileAttrsSetProc           = NULL;
                       201: 	xvfs_tclfs_standalone_fs.createDirectoryProc        = NULL;
                       202: 	xvfs_tclfs_standalone_fs.removeDirectoryProc        = NULL;
                       203: 	xvfs_tclfs_standalone_fs.deleteFileProc             = NULL;
                       204: 	xvfs_tclfs_standalone_fs.copyFileProc               = NULL;
                       205: 	xvfs_tclfs_standalone_fs.renameFileProc             = NULL;
                       206: 	xvfs_tclfs_standalone_fs.copyDirectoryProc          = NULL;
                       207: 	xvfs_tclfs_standalone_fs.lstatProc                  = NULL;
                       208: 	xvfs_tclfs_standalone_fs.loadFileProc               = NULL;
                       209: 	xvfs_tclfs_standalone_fs.getCwdProc                 = NULL;
                       210: 	xvfs_tclfs_standalone_fs.chdirProc                  = NULL;
                       211: 
                       212: 	xvfs_tclfs_standalone_info.fsInfo = fsInfo;
                       213: 	xvfs_tclfs_standalone_info.mountpoint = Tcl_NewObj();
                       214: 	Tcl_AppendStringsToObj(xvfs_tclfs_standalone_info.mountpoint, XVFS_ROOT_MOUNTPOINT, fsInfo->name, NULL);
149aa89b7d 2019-09-13  215: 	
                       216: 	tcl_ret = Tcl_FSRegister(NULL, &xvfs_tclfs_standalone_fs);
                       217: 	if (tcl_ret != TCL_OK) {
                       218: 		if (interp) {
                       219: 			Tcl_SetResult(interp, "Tcl_FSRegister() failed", NULL);
                       220: 		}
149aa89b7d 2019-09-13  221: 		
                       222: 		return(tcl_ret);
                       223: 	}
149aa89b7d 2019-09-13  224: 	
                       225: 	return(TCL_OK);
                       226: }
                       227: #endif /* XVFS_MODE_STANDALONE || XVFS_MODE_FLEXIBLE */
                       228: 
                       229: #if defined(XVFS_MODE_FLEXIBLE)
                       230: static int xvfs_flexible_register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
                       231: 	ClientData fsHandlerDataRaw;
                       232: 	struct xvfs_tclfs_server_info *fsHandlerData;
                       233: 	const Tcl_Filesystem *fsHandler;
                       234: 	int (*xvfs_register)(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo);
                       235: 	Tcl_Obj *rootPathObj;
                       236: 
                       237: 	xvfs_register = &xvfs_standalone_register;
                       238: 
                       239: 	rootPathObj = Tcl_NewStringObj(XVFS_ROOT_MOUNTPOINT, -1);
                       240: 	if (!rootPathObj) {
                       241: 		return(xvfs_register(interp, fsInfo));
                       242: 	}
                       243: 
                       244: 	Tcl_IncrRefCount(rootPathObj);
                       245: 	fsHandler = Tcl_FSGetFileSystemForPath(rootPathObj);
                       246: 	Tcl_DecrRefCount(rootPathObj);
                       247: 
                       248: 	if (!fsHandler) {
                       249: 		return(xvfs_register(interp, fsInfo));
                       250: 	}
                       251: 
                       252: 	fsHandlerDataRaw = Tcl_FSData(fsHandler);
                       253: 	if (!fsHandlerDataRaw) {
                       254: 		return(xvfs_register(interp, fsInfo));
                       255: 	}
                       256: 
                       257: 	fsHandlerData = (struct xvfs_tclfs_server_info *) fsHandlerDataRaw;
                       258: 
                       259: 	/*
                       260: 	 * XXX:TODO: What is the chance that the handler for //xvfs:/ hold
                       261: 	 * client data smaller than XVFS_INTERNAL_SERVER_MAGIC_LEN ?
                       262: 	 */
                       263: 	if (memcmp(fsHandlerData->magic, XVFS_INTERNAL_SERVER_MAGIC, sizeof(fsHandlerData->magic)) == 0) {
                       264: 		xvfs_register = fsHandlerData->registerProc;
                       265: 	}
                       266: 
                       267: 	return(xvfs_register(interp, fsInfo));
                       268: }
                       269: #endif /* XVFS_MODE_FLEXIBLE */
                       270: 
                       271: #if defined(XVFS_MODE_SERVER)
                       272: int Xvfs_Register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
                       273: 	return(TCL_ERROR);
                       274: }
                       275: #endif /* XVFS_MODE_SERVER */