69e476dcd5 2019-05-02 1: #include <xvfs-core.h>
d121970301 2019-05-02 2: #include <string.h>
38bed7cee0 2019-09-13 3: #include <sys/stat.h>
38bed7cee0 2019-09-13 4: #include <errno.h>
38bed7cee0 2019-09-13 5: #include <fcntl.h>
69e476dcd5 2019-05-02 6: #include <tcl.h>
d92ba3d36d 2019-05-08 7:
d92ba3d36d 2019-05-08 8: #if defined(XVFS_MODE_FLEXIBLE) || defined(XVFS_MODE_SERVER)
d92ba3d36d 2019-05-08 9: #define XVFS_INTERNAL_SERVER_MAGIC "\xD4\xF3\x05\x96\x25\xCF\xAF\xFE"
d92ba3d36d 2019-05-08 10: #define XVFS_INTERNAL_SERVER_MAGIC_LEN 8
d92ba3d36d 2019-05-08 11:
d92ba3d36d 2019-05-08 12: struct xvfs_tclfs_server_info {
b586d5b0a1 2019-05-08 13: char magic[XVFS_INTERNAL_SERVER_MAGIC_LEN];
d92ba3d36d 2019-05-08 14: int (*registerProc)(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo);
d92ba3d36d 2019-05-08 15: };
d92ba3d36d 2019-05-08 16: #endif /* XVFS_MODE_FLEXIBLE || XVFS_MODE_SERVER */
3e44e1def1 2019-05-02 17:
3e44e1def1 2019-05-02 18: #if defined(XVFS_MODE_SERVER) || defined(XVFS_MODE_STANDALONE) || defined(XVFS_MODE_FLEXIBLE)
d121970301 2019-05-02 19: #define XVFS_ROOT_MOUNTPOINT "//xvfs:/"
d121970301 2019-05-02 20:
d121970301 2019-05-02 21: struct xvfs_tclfs_instance_info {
d121970301 2019-05-02 22: struct Xvfs_FSInfo *fsInfo;
d121970301 2019-05-02 23: Tcl_Obj *mountpoint;
d121970301 2019-05-02 24: };
d121970301 2019-05-02 25:
d121970301 2019-05-02 26: /*
d121970301 2019-05-02 27: * Internal Core Utilities
d121970301 2019-05-02 28: */
d121970301 2019-05-02 29: static const char *xvfs_relativePath(Tcl_Obj *path, struct xvfs_tclfs_instance_info *info) {
5ae034e55e 2019-09-14 30: Tcl_Obj *currentDirectory;
d121970301 2019-05-02 31: const char *pathStr, *rootStr;
5583d77f1c 2019-09-14 32: const char *pathFinal;
d121970301 2019-05-02 33: int pathLen, rootLen;
38bed7cee0 2019-09-13 34:
d121970301 2019-05-02 35: rootStr = Tcl_GetStringFromObj(info->mountpoint, &rootLen);
12ff77016f 2019-09-14 36: pathStr = Tcl_GetStringFromObj(path, &pathLen);
12ff77016f 2019-09-14 37: if (pathStr[0] != '/') {
5ae034e55e 2019-09-14 38: currentDirectory = Tcl_FSGetCwd(NULL);
5ae034e55e 2019-09-14 39: Tcl_IncrRefCount(currentDirectory);
5ae034e55e 2019-09-14 40:
5ae034e55e 2019-09-14 41: /* XXX:TODO: Free this */
5ae034e55e 2019-09-14 42: path = Tcl_ObjPrintf("%s/%s", Tcl_GetString(currentDirectory), pathStr);
5ae034e55e 2019-09-14 43: Tcl_IncrRefCount(path);
5ae034e55e 2019-09-14 44: Tcl_DecrRefCount(currentDirectory);
5ae034e55e 2019-09-14 45:
12ff77016f 2019-09-14 46: pathStr = Tcl_GetStringFromObj(path, &pathLen);
12ff77016f 2019-09-14 47: }
38bed7cee0 2019-09-13 48:
d121970301 2019-05-02 49: if (pathLen < rootLen) {
d121970301 2019-05-02 50: return(NULL);
d121970301 2019-05-02 51: }
38bed7cee0 2019-09-13 52:
d121970301 2019-05-02 53: if (memcmp(pathStr, rootStr, rootLen) != 0) {
d121970301 2019-05-02 54: return(NULL);
d121970301 2019-05-02 55: }
38bed7cee0 2019-09-13 56:
d121970301 2019-05-02 57: if (pathLen == rootLen) {
d121970301 2019-05-02 58: return("");
d121970301 2019-05-02 59: }
d121970301 2019-05-02 60:
d121970301 2019-05-02 61: /* XXX:TODO: Should this use the native OS path separator ? */
d121970301 2019-05-02 62: if (pathStr[rootLen] != '/') {
d121970301 2019-05-02 63: return(NULL);
d121970301 2019-05-02 64: }
38bed7cee0 2019-09-13 65:
5583d77f1c 2019-09-14 66: pathFinal = pathStr + rootLen + 1;
5583d77f1c 2019-09-14 67: pathLen -= rootLen + 1;
5583d77f1c 2019-09-14 68:
5583d77f1c 2019-09-14 69: if (pathLen == 1 && memcmp(pathFinal, ".", 1) == 0) {
5583d77f1c 2019-09-14 70: return("");
5583d77f1c 2019-09-14 71: }
5583d77f1c 2019-09-14 72:
5583d77f1c 2019-09-14 73: while (pathLen >= 2 && memcmp(pathFinal, "./", 2) == 0) {
5583d77f1c 2019-09-14 74: pathFinal += 2;
5583d77f1c 2019-09-14 75: pathLen -= 2;
5583d77f1c 2019-09-14 76: }
5583d77f1c 2019-09-14 77:
5583d77f1c 2019-09-14 78: return(pathFinal);
149aa89b7d 2019-09-13 79: }
149aa89b7d 2019-09-13 80:
149aa89b7d 2019-09-13 81: static const char *xvfs_perror(int xvfs_error) {
149aa89b7d 2019-09-13 82: if (xvfs_error >= 0) {
149aa89b7d 2019-09-13 83: return("Not an error");
149aa89b7d 2019-09-13 84: }
149aa89b7d 2019-09-13 85:
149aa89b7d 2019-09-13 86: switch (xvfs_error) {
149aa89b7d 2019-09-13 87: case XVFS_RV_ERR_ENOENT:
149aa89b7d 2019-09-13 88: return("No such file or directory");
149aa89b7d 2019-09-13 89: case XVFS_RV_ERR_EINVAL:
149aa89b7d 2019-09-13 90: return("Invalid argument");
149aa89b7d 2019-09-13 91: case XVFS_RV_ERR_EISDIR:
149aa89b7d 2019-09-13 92: return("Is a directory");
149aa89b7d 2019-09-13 93: case XVFS_RV_ERR_ENOTDIR:
149aa89b7d 2019-09-13 94: return("Not a directory");
149aa89b7d 2019-09-13 95: case XVFS_RV_ERR_EFAULT:
149aa89b7d 2019-09-13 96: return("Bad address");
5583d77f1c 2019-09-14 97: case XVFS_RV_ERR_INTERNAL:
5583d77f1c 2019-09-14 98: return("Internal error");
149aa89b7d 2019-09-13 99: default:
149aa89b7d 2019-09-13 100: return("Unknown error");
149aa89b7d 2019-09-13 101: }
38bed7cee0 2019-09-13 102: }
38bed7cee0 2019-09-13 103:
38bed7cee0 2019-09-13 104: static int xvfs_errorToErrno(int xvfs_error) {
38bed7cee0 2019-09-13 105: if (xvfs_error >= 0) {
38bed7cee0 2019-09-13 106: return(0);
38bed7cee0 2019-09-13 107: }
38bed7cee0 2019-09-13 108:
38bed7cee0 2019-09-13 109: switch (xvfs_error) {
38bed7cee0 2019-09-13 110: case XVFS_RV_ERR_ENOENT:
38bed7cee0 2019-09-13 111: return(ENOENT);
38bed7cee0 2019-09-13 112: case XVFS_RV_ERR_EINVAL:
38bed7cee0 2019-09-13 113: return(EINVAL);
38bed7cee0 2019-09-13 114: case XVFS_RV_ERR_EISDIR:
38bed7cee0 2019-09-13 115: return(EISDIR);
38bed7cee0 2019-09-13 116: case XVFS_RV_ERR_ENOTDIR:
38bed7cee0 2019-09-13 117: return(ENOTDIR);
38bed7cee0 2019-09-13 118: case XVFS_RV_ERR_EFAULT:
38bed7cee0 2019-09-13 119: return(EFAULT);
5583d77f1c 2019-09-14 120: case XVFS_RV_ERR_INTERNAL:
5583d77f1c 2019-09-14 121: return(EINVAL);
38bed7cee0 2019-09-13 122: default:
38bed7cee0 2019-09-13 123: return(ERANGE);
38bed7cee0 2019-09-13 124: }
38bed7cee0 2019-09-13 125: }
38bed7cee0 2019-09-13 126:
38bed7cee0 2019-09-13 127: /*
38bed7cee0 2019-09-13 128: * Xvfs Memory Channel
38bed7cee0 2019-09-13 129: */
38bed7cee0 2019-09-13 130: struct xvfs_tclfs_channel_id {
38bed7cee0 2019-09-13 131: Tcl_Channel channel;
38bed7cee0 2019-09-13 132: struct xvfs_tclfs_instance_info *fsInstanceInfo;
38bed7cee0 2019-09-13 133: Tcl_Obj *path;
38bed7cee0 2019-09-13 134: Tcl_WideInt currentOffset;
38bed7cee0 2019-09-13 135: Tcl_WideInt fileSize;
7d74392642 2019-09-13 136: int eofMarked;
aa08a4a749 2019-09-14 137: int queuedEvents;
aa08a4a749 2019-09-14 138: int closed;
7d74392642 2019-09-13 139: };
7d74392642 2019-09-13 140: struct xvfs_tclfs_channel_event {
7d74392642 2019-09-13 141: Tcl_Event tcl;
7d74392642 2019-09-13 142: struct xvfs_tclfs_channel_id *channelInstanceData;
38bed7cee0 2019-09-13 143: };
38bed7cee0 2019-09-13 144: static Tcl_ChannelType xvfs_tclfs_channelType;
38bed7cee0 2019-09-13 145:
38bed7cee0 2019-09-13 146: static Tcl_Channel xvfs_tclfs_openChannel(Tcl_Obj *path, struct xvfs_tclfs_instance_info *instanceInfo) {
38bed7cee0 2019-09-13 147: struct xvfs_tclfs_channel_id *channelInstanceData;
38bed7cee0 2019-09-13 148: Tcl_Channel channel;
38bed7cee0 2019-09-13 149: Tcl_StatBuf fileInfo;
7d74392642 2019-09-13 150: Tcl_Obj *channelName;
38bed7cee0 2019-09-13 151: int statRet;
38bed7cee0 2019-09-13 152:
38bed7cee0 2019-09-13 153: statRet = instanceInfo->fsInfo->getStatProc(Tcl_GetString(path), &fileInfo);
38bed7cee0 2019-09-13 154: if (statRet < 0) {
38bed7cee0 2019-09-13 155: return(NULL);
38bed7cee0 2019-09-13 156: }
38bed7cee0 2019-09-13 157:
38bed7cee0 2019-09-13 158: channelInstanceData = (struct xvfs_tclfs_channel_id *) Tcl_Alloc(sizeof(*channelInstanceData));
38bed7cee0 2019-09-13 159: channelInstanceData->currentOffset = 0;
7d74392642 2019-09-13 160: channelInstanceData->eofMarked = 0;
aa08a4a749 2019-09-14 161: channelInstanceData->queuedEvents = 0;
aa08a4a749 2019-09-14 162: channelInstanceData->closed = 0;
38bed7cee0 2019-09-13 163: channelInstanceData->channel = NULL;
38bed7cee0 2019-09-13 164:
7d74392642 2019-09-13 165: channelName = Tcl_ObjPrintf("xvfs0x%llx", (unsigned long long) channelInstanceData);
7d74392642 2019-09-13 166: if (!channelName) {
7d74392642 2019-09-13 167: Tcl_Free((char *) channelInstanceData);
7d74392642 2019-09-13 168:
7d74392642 2019-09-13 169: return(NULL);
7d74392642 2019-09-13 170: }
7d74392642 2019-09-13 171: Tcl_IncrRefCount(channelName);
7d74392642 2019-09-13 172:
38bed7cee0 2019-09-13 173: channelInstanceData->fsInstanceInfo = instanceInfo;
38bed7cee0 2019-09-13 174: channelInstanceData->fileSize = fileInfo.st_size;
7d74392642 2019-09-13 175: channelInstanceData->path = path;
38bed7cee0 2019-09-13 176: Tcl_IncrRefCount(path);
38bed7cee0 2019-09-13 177:
7d74392642 2019-09-13 178: channel = Tcl_CreateChannel(&xvfs_tclfs_channelType, Tcl_GetString(channelName), channelInstanceData, TCL_READABLE);
7d74392642 2019-09-13 179: Tcl_DecrRefCount(channelName);
38bed7cee0 2019-09-13 180: if (!channel) {
38bed7cee0 2019-09-13 181: Tcl_DecrRefCount(path);
38bed7cee0 2019-09-13 182: Tcl_Free((char *) channelInstanceData);
38bed7cee0 2019-09-13 183:
38bed7cee0 2019-09-13 184: return(NULL);
38bed7cee0 2019-09-13 185: }
38bed7cee0 2019-09-13 186:
38bed7cee0 2019-09-13 187: channelInstanceData->channel = channel;
38bed7cee0 2019-09-13 188:
38bed7cee0 2019-09-13 189: return(channel);
38bed7cee0 2019-09-13 190: }
38bed7cee0 2019-09-13 191:
aa08a4a749 2019-09-14 192: static int xvfs_tclfs_closeChannel(ClientData channelInstanceData_p, Tcl_Interp *interp);
aa08a4a749 2019-09-14 193: static int xvfs_tclfs_closeChannelEvent(Tcl_Event *event_p, int flags) {
aa08a4a749 2019-09-14 194: struct xvfs_tclfs_channel_id *channelInstanceData;
aa08a4a749 2019-09-14 195: struct xvfs_tclfs_channel_event *event;
aa08a4a749 2019-09-14 196:
aa08a4a749 2019-09-14 197: event = (struct xvfs_tclfs_channel_event *) event_p;
aa08a4a749 2019-09-14 198: channelInstanceData = event->channelInstanceData;
aa08a4a749 2019-09-14 199:
aa08a4a749 2019-09-14 200: channelInstanceData->queuedEvents--;
aa08a4a749 2019-09-14 201:
aa08a4a749 2019-09-14 202: xvfs_tclfs_closeChannel((ClientData) channelInstanceData, NULL);
aa08a4a749 2019-09-14 203:
aa08a4a749 2019-09-14 204: return(1);
aa08a4a749 2019-09-14 205: }
aa08a4a749 2019-09-14 206:
38bed7cee0 2019-09-13 207: static int xvfs_tclfs_closeChannel(ClientData channelInstanceData_p, Tcl_Interp *interp) {
38bed7cee0 2019-09-13 208: struct xvfs_tclfs_channel_id *channelInstanceData;
aa08a4a749 2019-09-14 209: struct xvfs_tclfs_channel_event *event;
38bed7cee0 2019-09-13 210:
38bed7cee0 2019-09-13 211: channelInstanceData = (struct xvfs_tclfs_channel_id *) channelInstanceData_p;
aa08a4a749 2019-09-14 212:
aa08a4a749 2019-09-14 213: channelInstanceData->closed = 1;
aa08a4a749 2019-09-14 214:
aa08a4a749 2019-09-14 215: if (channelInstanceData->queuedEvents != 0) {
aa08a4a749 2019-09-14 216: event = (struct xvfs_tclfs_channel_event *) Tcl_Alloc(sizeof(*event));
aa08a4a749 2019-09-14 217: event->tcl.proc = xvfs_tclfs_closeChannelEvent;
aa08a4a749 2019-09-14 218: event->tcl.nextPtr = NULL;
aa08a4a749 2019-09-14 219: event->channelInstanceData = channelInstanceData;
aa08a4a749 2019-09-14 220:
aa08a4a749 2019-09-14 221: channelInstanceData->queuedEvents++;
aa08a4a749 2019-09-14 222:
aa08a4a749 2019-09-14 223: Tcl_QueueEvent((Tcl_Event *) event, TCL_QUEUE_TAIL);
aa08a4a749 2019-09-14 224:
aa08a4a749 2019-09-14 225: return(0);
aa08a4a749 2019-09-14 226: }
38bed7cee0 2019-09-13 227:
38bed7cee0 2019-09-13 228: Tcl_DecrRefCount(channelInstanceData->path);
38bed7cee0 2019-09-13 229: Tcl_Free((char *) channelInstanceData);
38bed7cee0 2019-09-13 230:
38bed7cee0 2019-09-13 231: return(0);
38bed7cee0 2019-09-13 232: }
38bed7cee0 2019-09-13 233:
38bed7cee0 2019-09-13 234: static int xvfs_tclfs_readChannel(ClientData channelInstanceData_p, char *buf, int bufSize, int *errorCodePtr) {
38bed7cee0 2019-09-13 235: struct xvfs_tclfs_channel_id *channelInstanceData;
38bed7cee0 2019-09-13 236: const unsigned char *data;
38bed7cee0 2019-09-13 237: Tcl_WideInt offset, length;
38bed7cee0 2019-09-13 238: char *path;
38bed7cee0 2019-09-13 239:
38bed7cee0 2019-09-13 240: channelInstanceData = (struct xvfs_tclfs_channel_id *) channelInstanceData_p;
38bed7cee0 2019-09-13 241:
7d74392642 2019-09-13 242: /*
7d74392642 2019-09-13 243: * If we are already at the end of the file we can skip
7d74392642 2019-09-13 244: * attempting to read it
7d74392642 2019-09-13 245: */
7d74392642 2019-09-13 246: if (channelInstanceData->eofMarked) {
7d74392642 2019-09-13 247: return(0);
7d74392642 2019-09-13 248: }
7d74392642 2019-09-13 249:
38bed7cee0 2019-09-13 250: path = Tcl_GetString(channelInstanceData->path);
38bed7cee0 2019-09-13 251: offset = channelInstanceData->currentOffset;
38bed7cee0 2019-09-13 252: length = bufSize;
38bed7cee0 2019-09-13 253:
38bed7cee0 2019-09-13 254: data = channelInstanceData->fsInstanceInfo->fsInfo->getDataProc(path, offset, &length);
38bed7cee0 2019-09-13 255:
38bed7cee0 2019-09-13 256: if (length < 0) {
38bed7cee0 2019-09-13 257: *errorCodePtr = xvfs_errorToErrno(length);
38bed7cee0 2019-09-13 258:
38bed7cee0 2019-09-13 259: return(-1);
38bed7cee0 2019-09-13 260: }
38bed7cee0 2019-09-13 261:
7d74392642 2019-09-13 262: if (length == 0) {
7d74392642 2019-09-13 263: channelInstanceData->eofMarked = 1;
7d74392642 2019-09-13 264: } else {
7d74392642 2019-09-13 265: memcpy(buf, data, length);
38bed7cee0 2019-09-13 266:
7d74392642 2019-09-13 267: channelInstanceData->currentOffset += length;
7d74392642 2019-09-13 268: }
38bed7cee0 2019-09-13 269:
38bed7cee0 2019-09-13 270: return(length);
38bed7cee0 2019-09-13 271: }
38bed7cee0 2019-09-13 272:
7d74392642 2019-09-13 273: static int xvfs_tclfs_watchChannelEvent(Tcl_Event *event_p, int flags) {
7d74392642 2019-09-13 274: struct xvfs_tclfs_channel_id *channelInstanceData;
7d74392642 2019-09-13 275: struct xvfs_tclfs_channel_event *event;
7d74392642 2019-09-13 276:
7d74392642 2019-09-13 277: event = (struct xvfs_tclfs_channel_event *) event_p;
7d74392642 2019-09-13 278: channelInstanceData = event->channelInstanceData;
7d74392642 2019-09-13 279:
aa08a4a749 2019-09-14 280: channelInstanceData->queuedEvents--;
aa08a4a749 2019-09-14 281:
aa08a4a749 2019-09-14 282: if (channelInstanceData->closed) {
aa08a4a749 2019-09-14 283: return(1);
aa08a4a749 2019-09-14 284: }
aa08a4a749 2019-09-14 285:
7d74392642 2019-09-13 286: Tcl_NotifyChannel(channelInstanceData->channel, TCL_READABLE);
7d74392642 2019-09-13 287:
aa08a4a749 2019-09-14 288: return(1);
7d74392642 2019-09-13 289: }
7d74392642 2019-09-13 290:
38bed7cee0 2019-09-13 291: static void xvfs_tclfs_watchChannel(ClientData channelInstanceData_p, int mask) {
7d74392642 2019-09-13 292: struct xvfs_tclfs_channel_id *channelInstanceData;
7d74392642 2019-09-13 293: struct xvfs_tclfs_channel_event *event;
7d74392642 2019-09-13 294:
38bed7cee0 2019-09-13 295: if ((mask & TCL_READABLE) != TCL_READABLE) {
38bed7cee0 2019-09-13 296: return;
38bed7cee0 2019-09-13 297: }
38bed7cee0 2019-09-13 298:
7d74392642 2019-09-13 299: channelInstanceData = (struct xvfs_tclfs_channel_id *) channelInstanceData_p;
7d74392642 2019-09-13 300:
7d74392642 2019-09-13 301: /*
7d74392642 2019-09-13 302: * If the read call has marked that we have reached EOF,
7d74392642 2019-09-13 303: * do not signal any further
7d74392642 2019-09-13 304: */
7d74392642 2019-09-13 305: if (channelInstanceData->eofMarked) {
7d74392642 2019-09-13 306: return;
7d74392642 2019-09-13 307: }
7d74392642 2019-09-13 308:
7d74392642 2019-09-13 309: event = (struct xvfs_tclfs_channel_event *) Tcl_Alloc(sizeof(*event));
7d74392642 2019-09-13 310: event->tcl.proc = xvfs_tclfs_watchChannelEvent;
7d74392642 2019-09-13 311: event->tcl.nextPtr = NULL;
7d74392642 2019-09-13 312: event->channelInstanceData = channelInstanceData;
aa08a4a749 2019-09-14 313:
aa08a4a749 2019-09-14 314: channelInstanceData->queuedEvents++;
7d74392642 2019-09-13 315:
7d74392642 2019-09-13 316: Tcl_QueueEvent((Tcl_Event *) event, TCL_QUEUE_TAIL);
7d74392642 2019-09-13 317:
38bed7cee0 2019-09-13 318: return;
38bed7cee0 2019-09-13 319: }
38bed7cee0 2019-09-13 320:
38bed7cee0 2019-09-13 321: static int xvfs_tclfs_seekChannel(ClientData channelInstanceData_p, long offset, int mode, int *errorCodePtr) {
38bed7cee0 2019-09-13 322: struct xvfs_tclfs_channel_id *channelInstanceData;
38bed7cee0 2019-09-13 323: Tcl_WideInt newOffset, fileSize;
38bed7cee0 2019-09-13 324:
38bed7cee0 2019-09-13 325: channelInstanceData = (struct xvfs_tclfs_channel_id *) channelInstanceData_p;
38bed7cee0 2019-09-13 326:
38bed7cee0 2019-09-13 327: newOffset = channelInstanceData->currentOffset;
38bed7cee0 2019-09-13 328: fileSize = channelInstanceData->fileSize;
38bed7cee0 2019-09-13 329:
38bed7cee0 2019-09-13 330: switch (mode) {
38bed7cee0 2019-09-13 331: case SEEK_CUR:
38bed7cee0 2019-09-13 332: newOffset += offset;
38bed7cee0 2019-09-13 333: break;
38bed7cee0 2019-09-13 334: case SEEK_SET:
38bed7cee0 2019-09-13 335: newOffset = offset;
38bed7cee0 2019-09-13 336: break;
38bed7cee0 2019-09-13 337: case SEEK_END:
38bed7cee0 2019-09-13 338: newOffset = fileSize + offset;
38bed7cee0 2019-09-13 339: break;
38bed7cee0 2019-09-13 340: default:
38bed7cee0 2019-09-13 341: *errorCodePtr = xvfs_errorToErrno(XVFS_RV_ERR_EINVAL);
38bed7cee0 2019-09-13 342:
38bed7cee0 2019-09-13 343: return(-1);
38bed7cee0 2019-09-13 344: }
38bed7cee0 2019-09-13 345:
38bed7cee0 2019-09-13 346: /*
38bed7cee0 2019-09-13 347: * We allow users to seek right up to the end of the buffer, but
38bed7cee0 2019-09-13 348: * no further, this way if they want to seek backwards from there
38bed7cee0 2019-09-13 349: * it is possible to do so.
38bed7cee0 2019-09-13 350: */
38bed7cee0 2019-09-13 351: if (newOffset < 0 || newOffset > fileSize) {
38bed7cee0 2019-09-13 352: *errorCodePtr = xvfs_errorToErrno(XVFS_RV_ERR_EINVAL);
38bed7cee0 2019-09-13 353:
38bed7cee0 2019-09-13 354: return(-1);
38bed7cee0 2019-09-13 355: }
38bed7cee0 2019-09-13 356:
7d74392642 2019-09-13 357: if (newOffset != channelInstanceData->currentOffset) {
7d74392642 2019-09-13 358: channelInstanceData->eofMarked = 0;
7d74392642 2019-09-13 359: channelInstanceData->currentOffset = newOffset;
7d74392642 2019-09-13 360: }
38bed7cee0 2019-09-13 361:
38bed7cee0 2019-09-13 362: return(channelInstanceData->currentOffset);
38bed7cee0 2019-09-13 363: }
38bed7cee0 2019-09-13 364:
38bed7cee0 2019-09-13 365: static void xvfs_tclfs_prepareChannelType(void) {
38bed7cee0 2019-09-13 366: xvfs_tclfs_channelType.typeName = "xvfs";
38bed7cee0 2019-09-13 367: xvfs_tclfs_channelType.version = TCL_CHANNEL_VERSION_2;
38bed7cee0 2019-09-13 368: xvfs_tclfs_channelType.closeProc = xvfs_tclfs_closeChannel;
38bed7cee0 2019-09-13 369: xvfs_tclfs_channelType.inputProc = xvfs_tclfs_readChannel;
38bed7cee0 2019-09-13 370: xvfs_tclfs_channelType.outputProc = NULL;
38bed7cee0 2019-09-13 371: xvfs_tclfs_channelType.watchProc = xvfs_tclfs_watchChannel;
38bed7cee0 2019-09-13 372: xvfs_tclfs_channelType.getHandleProc = NULL;
38bed7cee0 2019-09-13 373: xvfs_tclfs_channelType.seekProc = xvfs_tclfs_seekChannel;
38bed7cee0 2019-09-13 374: xvfs_tclfs_channelType.setOptionProc = NULL;
38bed7cee0 2019-09-13 375: xvfs_tclfs_channelType.getOptionProc = NULL;
38bed7cee0 2019-09-13 376: xvfs_tclfs_channelType.close2Proc = NULL;
38bed7cee0 2019-09-13 377: xvfs_tclfs_channelType.blockModeProc = NULL;
38bed7cee0 2019-09-13 378: xvfs_tclfs_channelType.flushProc = NULL;
38bed7cee0 2019-09-13 379: xvfs_tclfs_channelType.handlerProc = NULL;
38bed7cee0 2019-09-13 380: xvfs_tclfs_channelType.wideSeekProc = NULL;
38bed7cee0 2019-09-13 381: xvfs_tclfs_channelType.threadActionProc = NULL;
38bed7cee0 2019-09-13 382: xvfs_tclfs_channelType.truncateProc = NULL;
d121970301 2019-05-02 383: }
d121970301 2019-05-02 384:
d121970301 2019-05-02 385: /*
d121970301 2019-05-02 386: * Internal Tcl_Filesystem functions, with the appropriate instance info
d121970301 2019-05-02 387: */
d121970301 2019-05-02 388: static int xvfs_tclfs_pathInFilesystem(Tcl_Obj *path, ClientData *dataPtr, struct xvfs_tclfs_instance_info *instanceInfo) {
d121970301 2019-05-02 389: const char *relativePath;
38bed7cee0 2019-09-13 390:
d121970301 2019-05-02 391: relativePath = xvfs_relativePath(path, instanceInfo);
d121970301 2019-05-02 392: if (!relativePath) {
d121970301 2019-05-02 393: return(-1);
d121970301 2019-05-02 394: }
38bed7cee0 2019-09-13 395:
d121970301 2019-05-02 396: return(TCL_OK);
d121970301 2019-05-02 397: }
d121970301 2019-05-02 398:
d121970301 2019-05-02 399: static int xvfs_tclfs_stat(Tcl_Obj *path, Tcl_StatBuf *statBuf, struct xvfs_tclfs_instance_info *instanceInfo) {
d121970301 2019-05-02 400: const char *pathStr;
d121970301 2019-05-02 401: int retval;
d121970301 2019-05-02 402:
d121970301 2019-05-02 403: pathStr = xvfs_relativePath(path, instanceInfo);
38bed7cee0 2019-09-13 404:
daf25f5222 2019-05-03 405: retval = instanceInfo->fsInfo->getStatProc(pathStr, statBuf);
149aa89b7d 2019-09-13 406: if (retval < 0) {
149aa89b7d 2019-09-13 407: retval = -1;
149aa89b7d 2019-09-13 408: }
38bed7cee0 2019-09-13 409:
d121970301 2019-05-02 410: return(retval);
38bed7cee0 2019-09-13 411: }
38bed7cee0 2019-09-13 412:
12ff77016f 2019-09-14 413: static int xvfs_tclfs_access(Tcl_Obj *path, int mode, struct xvfs_tclfs_instance_info *instanceInfo) {
12ff77016f 2019-09-14 414: const char *pathStr;
12ff77016f 2019-09-14 415: Tcl_StatBuf fileInfo;
12ff77016f 2019-09-14 416: int statRetVal;
12ff77016f 2019-09-14 417:
12ff77016f 2019-09-14 418: pathStr = xvfs_relativePath(path, instanceInfo);
12ff77016f 2019-09-14 419:
12ff77016f 2019-09-14 420: if (mode & W_OK) {
12ff77016f 2019-09-14 421: return(-1);
12ff77016f 2019-09-14 422: }
12ff77016f 2019-09-14 423:
12ff77016f 2019-09-14 424: statRetVal = instanceInfo->fsInfo->getStatProc(pathStr, &fileInfo);
12ff77016f 2019-09-14 425: if (statRetVal < 0) {
12ff77016f 2019-09-14 426: return(-1);
12ff77016f 2019-09-14 427: }
12ff77016f 2019-09-14 428:
12ff77016f 2019-09-14 429: if (mode & X_OK) {
12ff77016f 2019-09-14 430: if (!(fileInfo.st_mode & 040000)) {
12ff77016f 2019-09-14 431: return(-1);
12ff77016f 2019-09-14 432: }
12ff77016f 2019-09-14 433: }
12ff77016f 2019-09-14 434:
12ff77016f 2019-09-14 435: return(0);
12ff77016f 2019-09-14 436: }
12ff77016f 2019-09-14 437:
d121970301 2019-05-02 438: static Tcl_Obj *xvfs_tclfs_listVolumes(struct xvfs_tclfs_instance_info *instanceInfo) {
d121970301 2019-05-02 439: return(NULL);
d121970301 2019-05-02 440: }
d121970301 2019-05-02 441:
d121970301 2019-05-02 442: static Tcl_Channel xvfs_tclfs_openFileChannel(Tcl_Interp *interp, Tcl_Obj *path, int mode, int permissions, struct xvfs_tclfs_instance_info *instanceInfo) {
d121970301 2019-05-02 443: const char *pathStr;
38bed7cee0 2019-09-13 444:
38bed7cee0 2019-09-13 445: pathStr = xvfs_relativePath(path, instanceInfo);
38bed7cee0 2019-09-13 446:
38bed7cee0 2019-09-13 447: if (mode & O_WRONLY) {
38bed7cee0 2019-09-13 448: return(NULL);
38bed7cee0 2019-09-13 449: }
38bed7cee0 2019-09-13 450:
38bed7cee0 2019-09-13 451: return(xvfs_tclfs_openChannel(Tcl_NewStringObj(pathStr, -1), instanceInfo));
5583d77f1c 2019-09-14 452: }
5583d77f1c 2019-09-14 453:
5583d77f1c 2019-09-14 454: static int xvfs_tclfs_verifyType(Tcl_Obj *path, Tcl_GlobTypeData *types, struct xvfs_tclfs_instance_info *instanceInfo) {
5583d77f1c 2019-09-14 455: const char *pathStr;
5583d77f1c 2019-09-14 456: Tcl_StatBuf fileInfo;
5583d77f1c 2019-09-14 457: int statRetVal;
5583d77f1c 2019-09-14 458:
5583d77f1c 2019-09-14 459: statRetVal = xvfs_tclfs_stat(path, &fileInfo, instanceInfo);
5583d77f1c 2019-09-14 460: if (statRetVal != 0) {
5583d77f1c 2019-09-14 461: return(0);
5583d77f1c 2019-09-14 462: }
5583d77f1c 2019-09-14 463:
5583d77f1c 2019-09-14 464: if (!types) {
5583d77f1c 2019-09-14 465: return(1);
5583d77f1c 2019-09-14 466: }
5583d77f1c 2019-09-14 467:
5583d77f1c 2019-09-14 468: if (types->perm != TCL_GLOB_PERM_RONLY) {
12ff77016f 2019-09-14 469: if (types->perm & (TCL_GLOB_PERM_W | TCL_GLOB_PERM_HIDDEN)) {
5583d77f1c 2019-09-14 470: return(0);
12ff77016f 2019-09-14 471: }
12ff77016f 2019-09-14 472:
12ff77016f 2019-09-14 473: if ((types->perm & TCL_GLOB_PERM_X) == TCL_GLOB_PERM_X) {
12ff77016f 2019-09-14 474: if (!(fileInfo.st_mode & 040000)) {
12ff77016f 2019-09-14 475: return(0);
12ff77016f 2019-09-14 476: }
5583d77f1c 2019-09-14 477: }
5583d77f1c 2019-09-14 478: }
5583d77f1c 2019-09-14 479:
5583d77f1c 2019-09-14 480: if (types->type & (TCL_GLOB_TYPE_BLOCK | TCL_GLOB_TYPE_CHAR | TCL_GLOB_TYPE_PIPE | TCL_GLOB_TYPE_SOCK | TCL_GLOB_TYPE_LINK)) {
5583d77f1c 2019-09-14 481: return(0);
5583d77f1c 2019-09-14 482: }
5583d77f1c 2019-09-14 483:
5583d77f1c 2019-09-14 484: if ((types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR) {
5583d77f1c 2019-09-14 485: if (!(fileInfo.st_mode & 040000)) {
5583d77f1c 2019-09-14 486: return(0);
5583d77f1c 2019-09-14 487: }
5583d77f1c 2019-09-14 488: }
5583d77f1c 2019-09-14 489:
5583d77f1c 2019-09-14 490: if ((types->type & TCL_GLOB_TYPE_FILE) == TCL_GLOB_TYPE_FILE) {
5583d77f1c 2019-09-14 491: if (!(fileInfo.st_mode & 0100000)) {
5583d77f1c 2019-09-14 492: return(0);
5583d77f1c 2019-09-14 493: }
5583d77f1c 2019-09-14 494: }
5583d77f1c 2019-09-14 495:
5583d77f1c 2019-09-14 496: if ((types->type & TCL_GLOB_TYPE_MOUNT) == TCL_GLOB_TYPE_MOUNT) {
5583d77f1c 2019-09-14 497: pathStr = xvfs_relativePath(path, instanceInfo);
5583d77f1c 2019-09-14 498: if (!pathStr) {
5583d77f1c 2019-09-14 499: return(0);
5583d77f1c 2019-09-14 500: }
5583d77f1c 2019-09-14 501:
5583d77f1c 2019-09-14 502: if (strlen(pathStr) != 0) {
5583d77f1c 2019-09-14 503: return(0);
5583d77f1c 2019-09-14 504: }
5583d77f1c 2019-09-14 505: }
5583d77f1c 2019-09-14 506:
5583d77f1c 2019-09-14 507: return(1);
5583d77f1c 2019-09-14 508: }
5583d77f1c 2019-09-14 509:
5583d77f1c 2019-09-14 510: static int xvfs_tclfs_matchInDir(Tcl_Interp *interp, Tcl_Obj *resultPtr, Tcl_Obj *path, const char *pattern, Tcl_GlobTypeData *types, struct xvfs_tclfs_instance_info *instanceInfo) {
5583d77f1c 2019-09-14 511: const char *pathStr;
5583d77f1c 2019-09-14 512: const char **children, *child;
5583d77f1c 2019-09-14 513: Tcl_WideInt childrenCount, idx;
5583d77f1c 2019-09-14 514: Tcl_Obj *childObj;
5583d77f1c 2019-09-14 515: int tclRetVal;
5583d77f1c 2019-09-14 516:
5583d77f1c 2019-09-14 517: if (pattern == NULL) {
5583d77f1c 2019-09-14 518: if (xvfs_tclfs_verifyType(path, types, instanceInfo)) {
5583d77f1c 2019-09-14 519: return(TCL_OK);
5583d77f1c 2019-09-14 520: }
5583d77f1c 2019-09-14 521:
5583d77f1c 2019-09-14 522: return(TCL_ERROR);
5583d77f1c 2019-09-14 523: }
5583d77f1c 2019-09-14 524:
5583d77f1c 2019-09-14 525: pathStr = xvfs_relativePath(path, instanceInfo);
5583d77f1c 2019-09-14 526: if (!pathStr) {
5583d77f1c 2019-09-14 527: if (interp) {
5583d77f1c 2019-09-14 528: Tcl_SetResult(interp, (char *) xvfs_perror(XVFS_RV_ERR_ENOENT), NULL);
5583d77f1c 2019-09-14 529: }
5583d77f1c 2019-09-14 530:
5583d77f1c 2019-09-14 531: return(TCL_ERROR);
5583d77f1c 2019-09-14 532: }
5583d77f1c 2019-09-14 533:
5583d77f1c 2019-09-14 534: childrenCount = 0;
5583d77f1c 2019-09-14 535: children = instanceInfo->fsInfo->getChildrenProc(pathStr, &childrenCount);
5583d77f1c 2019-09-14 536: if (childrenCount < 0) {
5583d77f1c 2019-09-14 537: if (interp) {
5583d77f1c 2019-09-14 538: Tcl_SetResult(interp, (char *) xvfs_perror(childrenCount), NULL);
5583d77f1c 2019-09-14 539: }
5583d77f1c 2019-09-14 540:
5583d77f1c 2019-09-14 541: return(TCL_ERROR);
5583d77f1c 2019-09-14 542: }
5583d77f1c 2019-09-14 543:
5583d77f1c 2019-09-14 544: for (idx = 0; idx < childrenCount; idx++) {
5583d77f1c 2019-09-14 545: child = children[idx];
5583d77f1c 2019-09-14 546:
5583d77f1c 2019-09-14 547: if (!Tcl_StringMatch(child, pattern)) {
5583d77f1c 2019-09-14 548: continue;
5583d77f1c 2019-09-14 549: }
5583d77f1c 2019-09-14 550:
5583d77f1c 2019-09-14 551: childObj = Tcl_DuplicateObj(path);
5583d77f1c 2019-09-14 552: Tcl_IncrRefCount(childObj);
5ae034e55e 2019-09-14 553: Tcl_AppendStringsToObj(childObj, "/", child, NULL);
5583d77f1c 2019-09-14 554:
5583d77f1c 2019-09-14 555: if (!xvfs_tclfs_verifyType(childObj, types, instanceInfo)) {
5583d77f1c 2019-09-14 556: Tcl_DecrRefCount(childObj);
5583d77f1c 2019-09-14 557:
5583d77f1c 2019-09-14 558: continue;
5583d77f1c 2019-09-14 559: }
5583d77f1c 2019-09-14 560:
5583d77f1c 2019-09-14 561: tclRetVal = Tcl_ListObjAppendElement(interp, resultPtr, childObj);
5583d77f1c 2019-09-14 562: Tcl_DecrRefCount(childObj);
5583d77f1c 2019-09-14 563:
5583d77f1c 2019-09-14 564: if (tclRetVal != TCL_OK) {
5583d77f1c 2019-09-14 565: return(tclRetVal);
5583d77f1c 2019-09-14 566: }
5583d77f1c 2019-09-14 567: }
5583d77f1c 2019-09-14 568:
5583d77f1c 2019-09-14 569: return(TCL_OK);
d121970301 2019-05-02 570: }
3e44e1def1 2019-05-02 571: #endif /* XVFS_MODE_SERVER || XVFS_MODE_STANDALONE || XVFS_MODE_FLEIXBLE */
d121970301 2019-05-02 572:
88f96696b7 2019-05-03 573: #if defined(XVFS_MODE_STANDALONE) || defined(XVFS_MODE_FLEXIBLE)
d121970301 2019-05-02 574: /*
d121970301 2019-05-02 575: * Tcl_Filesystem handlers for the standalone implementation
d121970301 2019-05-02 576: */
acfc5037c6 2019-05-02 577: static struct xvfs_tclfs_instance_info xvfs_tclfs_standalone_info;
d121970301 2019-05-02 578: static int xvfs_tclfs_standalone_pathInFilesystem(Tcl_Obj *path, ClientData *dataPtr) {
d121970301 2019-05-02 579: return(xvfs_tclfs_pathInFilesystem(path, dataPtr, &xvfs_tclfs_standalone_info));
d121970301 2019-05-02 580: }
d121970301 2019-05-02 581:
d121970301 2019-05-02 582: static int xvfs_tclfs_standalone_stat(Tcl_Obj *path, Tcl_StatBuf *statBuf) {
d121970301 2019-05-02 583: return(xvfs_tclfs_stat(path, statBuf, &xvfs_tclfs_standalone_info));
12ff77016f 2019-09-14 584: }
12ff77016f 2019-09-14 585:
12ff77016f 2019-09-14 586: static int xvfs_tclfs_standalone_access(Tcl_Obj *path, int mode) {
12ff77016f 2019-09-14 587: return(xvfs_tclfs_access(path, mode, &xvfs_tclfs_standalone_info));
5583d77f1c 2019-09-14 588: }
5583d77f1c 2019-09-14 589:
d121970301 2019-05-02 590: static Tcl_Obj *xvfs_tclfs_standalone_listVolumes(void) {
d121970301 2019-05-02 591: return(xvfs_tclfs_listVolumes(&xvfs_tclfs_standalone_info));
e5b6962adf 2019-05-02 592: }
e5b6962adf 2019-05-02 593:
d121970301 2019-05-02 594: static Tcl_Channel xvfs_tclfs_standalone_openFileChannel(Tcl_Interp *interp, Tcl_Obj *path, int mode, int permissions) {
d121970301 2019-05-02 595: return(xvfs_tclfs_openFileChannel(interp, path, mode, permissions, &xvfs_tclfs_standalone_info));
5583d77f1c 2019-09-14 596: }
5583d77f1c 2019-09-14 597:
5583d77f1c 2019-09-14 598: static int xvfs_tclfs_standalone_matchInDir(Tcl_Interp *interp, Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types) {
5583d77f1c 2019-09-14 599: return(xvfs_tclfs_matchInDir(interp, resultPtr, pathPtr, pattern, types, &xvfs_tclfs_standalone_info));
e5b6962adf 2019-05-02 600: }
32b55a907b 2019-05-02 601:
32b55a907b 2019-05-02 602: /*
32b55a907b 2019-05-02 603: * There are three (3) modes of operation for Xvfs_Register:
32b55a907b 2019-05-02 604: * 1. standalone -- We register our own Tcl_Filesystem
32b55a907b 2019-05-02 605: * and handle requests under `//xvfs:/<fsName>`
32b55a907b 2019-05-02 606: * 2. client -- A single Tcl_Filesystem is registered for the
32b55a907b 2019-05-02 607: * interp to handle requests under `//xvfs:/` which
32b55a907b 2019-05-02 608: * then dispatches to the appropriate registered
32b55a907b 2019-05-02 609: * handler
32b55a907b 2019-05-02 610: * 3. flexible -- Attempts to find a core Xvfs instance for the
32b55a907b 2019-05-02 611: * process at runtime, if found do #2, otherwise
32b55a907b 2019-05-02 612: * fallback to #1
32b55a907b 2019-05-02 613: *
32b55a907b 2019-05-02 614: */
cb77ecfb24 2019-05-06 615: static Tcl_Filesystem xvfs_tclfs_standalone_fs;
b8cca3a6b4 2019-05-08 616: static int xvfs_standalone_register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
e5b6962adf 2019-05-02 617: int tcl_ret;
d121970301 2019-05-02 618: static int registered = 0;
38bed7cee0 2019-09-13 619:
d121970301 2019-05-02 620: /*
d121970301 2019-05-02 621: * Ensure this instance is not already registered
d121970301 2019-05-02 622: */
d121970301 2019-05-02 623: if (registered) {
d121970301 2019-05-02 624: return(TCL_OK);
d121970301 2019-05-02 625: }
d121970301 2019-05-02 626: registered = 1;
d121970301 2019-05-02 627:
e5b6962adf 2019-05-02 628: /*
e5b6962adf 2019-05-02 629: * In standalone mode, we only support the same protocol we are
e5b6962adf 2019-05-02 630: * compiling for.
e5b6962adf 2019-05-02 631: */
e5b6962adf 2019-05-02 632: if (fsInfo->protocolVersion != XVFS_PROTOCOL_VERSION) {
e5b6962adf 2019-05-02 633: if (interp) {
e5b6962adf 2019-05-02 634: Tcl_SetResult(interp, "Protocol mismatch", NULL);
e5b6962adf 2019-05-02 635: }
e5b6962adf 2019-05-02 636: return(TCL_ERROR);
e5b6962adf 2019-05-02 637: }
38bed7cee0 2019-09-13 638:
cb77ecfb24 2019-05-06 639: xvfs_tclfs_standalone_fs.typeName = "xvfs";
cb77ecfb24 2019-05-06 640: xvfs_tclfs_standalone_fs.structureLength = sizeof(xvfs_tclfs_standalone_fs);
cb77ecfb24 2019-05-06 641: xvfs_tclfs_standalone_fs.version = TCL_FILESYSTEM_VERSION_1;
cb77ecfb24 2019-05-06 642: xvfs_tclfs_standalone_fs.pathInFilesystemProc = xvfs_tclfs_standalone_pathInFilesystem;
cb77ecfb24 2019-05-06 643: xvfs_tclfs_standalone_fs.dupInternalRepProc = NULL;
cb77ecfb24 2019-05-06 644: xvfs_tclfs_standalone_fs.freeInternalRepProc = NULL;
cb77ecfb24 2019-05-06 645: xvfs_tclfs_standalone_fs.internalToNormalizedProc = NULL;
cb77ecfb24 2019-05-06 646: xvfs_tclfs_standalone_fs.createInternalRepProc = NULL;
cb77ecfb24 2019-05-06 647: xvfs_tclfs_standalone_fs.normalizePathProc = NULL;
cb77ecfb24 2019-05-06 648: xvfs_tclfs_standalone_fs.filesystemPathTypeProc = NULL;
cb77ecfb24 2019-05-06 649: xvfs_tclfs_standalone_fs.filesystemSeparatorProc = NULL;
cb77ecfb24 2019-05-06 650: xvfs_tclfs_standalone_fs.statProc = xvfs_tclfs_standalone_stat;
12ff77016f 2019-09-14 651: xvfs_tclfs_standalone_fs.accessProc = xvfs_tclfs_standalone_access;
cb77ecfb24 2019-05-06 652: xvfs_tclfs_standalone_fs.openFileChannelProc = xvfs_tclfs_standalone_openFileChannel;
5583d77f1c 2019-09-14 653: xvfs_tclfs_standalone_fs.matchInDirectoryProc = xvfs_tclfs_standalone_matchInDir;
cb77ecfb24 2019-05-06 654: xvfs_tclfs_standalone_fs.utimeProc = NULL;
cb77ecfb24 2019-05-06 655: xvfs_tclfs_standalone_fs.linkProc = NULL;
cb77ecfb24 2019-05-06 656: xvfs_tclfs_standalone_fs.listVolumesProc = xvfs_tclfs_standalone_listVolumes;
cb77ecfb24 2019-05-06 657: xvfs_tclfs_standalone_fs.fileAttrStringsProc = NULL;
cb77ecfb24 2019-05-06 658: xvfs_tclfs_standalone_fs.fileAttrsGetProc = NULL;
cb77ecfb24 2019-05-06 659: xvfs_tclfs_standalone_fs.fileAttrsSetProc = NULL;
cb77ecfb24 2019-05-06 660: xvfs_tclfs_standalone_fs.createDirectoryProc = NULL;
cb77ecfb24 2019-05-06 661: xvfs_tclfs_standalone_fs.removeDirectoryProc = NULL;
cb77ecfb24 2019-05-06 662: xvfs_tclfs_standalone_fs.deleteFileProc = NULL;
cb77ecfb24 2019-05-06 663: xvfs_tclfs_standalone_fs.copyFileProc = NULL;
cb77ecfb24 2019-05-06 664: xvfs_tclfs_standalone_fs.renameFileProc = NULL;
cb77ecfb24 2019-05-06 665: xvfs_tclfs_standalone_fs.copyDirectoryProc = NULL;
cb77ecfb24 2019-05-06 666: xvfs_tclfs_standalone_fs.lstatProc = NULL;
cb77ecfb24 2019-05-06 667: xvfs_tclfs_standalone_fs.loadFileProc = NULL;
cb77ecfb24 2019-05-06 668: xvfs_tclfs_standalone_fs.getCwdProc = NULL;
cb77ecfb24 2019-05-06 669: xvfs_tclfs_standalone_fs.chdirProc = NULL;
d121970301 2019-05-02 670:
d121970301 2019-05-02 671: xvfs_tclfs_standalone_info.fsInfo = fsInfo;
d121970301 2019-05-02 672: xvfs_tclfs_standalone_info.mountpoint = Tcl_NewObj();
5ae034e55e 2019-09-14 673:
5ae034e55e 2019-09-14 674: Tcl_IncrRefCount(xvfs_tclfs_standalone_info.mountpoint);
d121970301 2019-05-02 675: Tcl_AppendStringsToObj(xvfs_tclfs_standalone_info.mountpoint, XVFS_ROOT_MOUNTPOINT, fsInfo->name, NULL);
5ae034e55e 2019-09-14 676:
cb77ecfb24 2019-05-06 677: tcl_ret = Tcl_FSRegister(NULL, &xvfs_tclfs_standalone_fs);
e5b6962adf 2019-05-02 678: if (tcl_ret != TCL_OK) {
5ae034e55e 2019-09-14 679: Tcl_DecrRefCount(xvfs_tclfs_standalone_info.mountpoint);
5ae034e55e 2019-09-14 680:
e5b6962adf 2019-05-02 681: if (interp) {
e5b6962adf 2019-05-02 682: Tcl_SetResult(interp, "Tcl_FSRegister() failed", NULL);
e5b6962adf 2019-05-02 683: }
38bed7cee0 2019-09-13 684:
e5b6962adf 2019-05-02 685: return(tcl_ret);
e5b6962adf 2019-05-02 686: }
38bed7cee0 2019-09-13 687:
38bed7cee0 2019-09-13 688: xvfs_tclfs_prepareChannelType();
38bed7cee0 2019-09-13 689:
e5b6962adf 2019-05-02 690: return(TCL_OK);
e5b6962adf 2019-05-02 691: }
d92ba3d36d 2019-05-08 692: #endif /* XVFS_MODE_STANDALONE || XVFS_MODE_FLEXIBLE */
88f96696b7 2019-05-03 693:
88f96696b7 2019-05-03 694: #if defined(XVFS_MODE_FLEXIBLE)
b8cca3a6b4 2019-05-08 695: static int xvfs_flexible_register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
9bcf758fef 2019-05-08 696: ClientData fsHandlerDataRaw;
9bcf758fef 2019-05-08 697: struct xvfs_tclfs_server_info *fsHandlerData;
9bcf758fef 2019-05-08 698: const Tcl_Filesystem *fsHandler;
9bcf758fef 2019-05-08 699: int (*xvfs_register)(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo);
9bcf758fef 2019-05-08 700: Tcl_Obj *rootPathObj;
9bcf758fef 2019-05-08 701:
9bcf758fef 2019-05-08 702: xvfs_register = &xvfs_standalone_register;
9bcf758fef 2019-05-08 703:
9bcf758fef 2019-05-08 704: rootPathObj = Tcl_NewStringObj(XVFS_ROOT_MOUNTPOINT, -1);
9bcf758fef 2019-05-08 705: if (!rootPathObj) {
9bcf758fef 2019-05-08 706: return(xvfs_register(interp, fsInfo));
9bcf758fef 2019-05-08 707: }
9bcf758fef 2019-05-08 708:
9bcf758fef 2019-05-08 709: Tcl_IncrRefCount(rootPathObj);
9bcf758fef 2019-05-08 710: fsHandler = Tcl_FSGetFileSystemForPath(rootPathObj);
9bcf758fef 2019-05-08 711: Tcl_DecrRefCount(rootPathObj);
9bcf758fef 2019-05-08 712:
9bcf758fef 2019-05-08 713: if (!fsHandler) {
9bcf758fef 2019-05-08 714: return(xvfs_register(interp, fsInfo));
9bcf758fef 2019-05-08 715: }
9bcf758fef 2019-05-08 716:
9bcf758fef 2019-05-08 717: fsHandlerDataRaw = Tcl_FSData(fsHandler);
9bcf758fef 2019-05-08 718: if (!fsHandlerDataRaw) {
9bcf758fef 2019-05-08 719: return(xvfs_register(interp, fsInfo));
9bcf758fef 2019-05-08 720: }
9bcf758fef 2019-05-08 721:
9bcf758fef 2019-05-08 722: fsHandlerData = (struct xvfs_tclfs_server_info *) fsHandlerDataRaw;
88f96696b7 2019-05-03 723:
88f96696b7 2019-05-03 724: /*
9bcf758fef 2019-05-08 725: * XXX:TODO: What is the chance that the handler for //xvfs:/ hold
b586d5b0a1 2019-05-08 726: * client data smaller than XVFS_INTERNAL_SERVER_MAGIC_LEN ?
88f96696b7 2019-05-03 727: */
b586d5b0a1 2019-05-08 728: if (memcmp(fsHandlerData->magic, XVFS_INTERNAL_SERVER_MAGIC, sizeof(fsHandlerData->magic)) == 0) {
9bcf758fef 2019-05-08 729: xvfs_register = fsHandlerData->registerProc;
88f96696b7 2019-05-03 730: }
9bcf758fef 2019-05-08 731:
88f96696b7 2019-05-03 732: return(xvfs_register(interp, fsInfo));
88f96696b7 2019-05-03 733: }
d92ba3d36d 2019-05-08 734: #endif /* XVFS_MODE_FLEXIBLE */
3e44e1def1 2019-05-02 735:
3e44e1def1 2019-05-02 736: #if defined(XVFS_MODE_SERVER)
e5b6962adf 2019-05-02 737: int Xvfs_Register(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo) {
acfc5037c6 2019-05-02 738: return(TCL_ERROR);
69e476dcd5 2019-05-02 739: }
d92ba3d36d 2019-05-08 740: #endif /* XVFS_MODE_SERVER */