diff options
Diffstat (limited to 'mac')
-rw-r--r-- | mac/tclMacFCmd.c | 240 | ||||
-rw-r--r-- | mac/tclMacFile.c | 827 | ||||
-rw-r--r-- | mac/tclMacInit.c | 38 | ||||
-rw-r--r-- | mac/tclMacPort.h | 22 | ||||
-rw-r--r-- | mac/tclMacResource.c | 5 | ||||
-rw-r--r-- | mac/tclMacTime.c | 119 |
6 files changed, 807 insertions, 444 deletions
diff --git a/mac/tclMacFCmd.c b/mac/tclMacFCmd.c index a83011d..462d48e 100644 --- a/mac/tclMacFCmd.c +++ b/mac/tclMacFCmd.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacFCmd.c,v 1.7 1999/10/15 04:47:03 jingham Exp $ + * RCS: @(#) $Id: tclMacFCmd.c,v 1.8 2001/07/31 19:12:07 vincentdarley Exp $ */ #include "tclInt.h" @@ -25,6 +25,7 @@ #include <Script.h> #include <string.h> #include <Finder.h> +#include <Aliases.h> /* * Callback for the file attributes code. @@ -97,6 +98,73 @@ static OSErr MoveRename _ANSI_ARGS_((const FSSpec *srcSpecPtr, static int Pstrequal _ANSI_ARGS_((ConstStr255Param stringA, ConstStr255Param stringB)); +int +TclpObjCreateDirectory(pathPtr) + Tcl_Obj *pathPtr; +{ + return TclpCreateDirectory(Tcl_FSGetTranslatedPath(NULL, pathPtr)); +} + +int +TclpObjDeleteFile(pathPtr) + Tcl_Obj *pathPtr; +{ + return TclpDeleteFile(Tcl_FSGetTranslatedPath(NULL, pathPtr)); +} + +int +TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr) + Tcl_Obj *srcPathPtr; + Tcl_Obj *destPathPtr; + Tcl_Obj **errorPtr; +{ + Tcl_DString ds; + int ret; + ret = TclpCopyDirectory(Tcl_FSGetTranslatedPath(NULL,srcPathPtr), + Tcl_FSGetTranslatedPath(NULL,destPathPtr), &ds); + if (ret != TCL_OK) { + *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); + Tcl_DStringFree(&ds); + Tcl_IncrRefCount(*errorPtr); + } + return ret; +} + +int +TclpObjCopyFile(srcPathPtr, destPathPtr) + Tcl_Obj *srcPathPtr; + Tcl_Obj *destPathPtr; +{ + return TclpCopyFile(Tcl_FSGetTranslatedPath(NULL,srcPathPtr), + Tcl_FSGetTranslatedPath(NULL,destPathPtr)); +} + +int +TclpObjRemoveDirectory(pathPtr, recursive, errorPtr) + Tcl_Obj *pathPtr; + int recursive; + Tcl_Obj **errorPtr; +{ + Tcl_DString ds; + int ret; + ret = TclpRemoveDirectory(Tcl_FSGetTranslatedPath(NULL, pathPtr),recursive, &ds); + if (ret != TCL_OK) { + *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); + Tcl_DStringFree(&ds); + Tcl_IncrRefCount(*errorPtr); + } + return ret; +} + +int +TclpObjRenameFile(srcPathPtr, destPathPtr) + Tcl_Obj *srcPathPtr; + Tcl_Obj *destPathPtr; +{ + return TclpRenameFile(Tcl_FSGetTranslatedPath(NULL,srcPathPtr), + Tcl_FSGetTranslatedPath(NULL,destPathPtr)); +} + /* *--------------------------------------------------------------------------- * @@ -1548,4 +1616,174 @@ TclpListVolumes( Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } + +/* + *--------------------------------------------------------------------------- + * + * TclpObjNormalizePath -- + * + * This function scans through a path specification and replaces + * it, in place, with a normalized version. On MacOS, this means + * resolving all aliases present in the path and replacing the head of + * pathPtr with the absolute case-sensitive path to the last file or + * directory that could be validated in the path. + * + * Results: + * The new 'nextCheckpoint' value, giving as far as we could + * understand in the path. + * + * Side effects: + * The pathPtr string, which must contain a valid path, is + * possibly modified in place. + * + *--------------------------------------------------------------------------- + */ + +int +TclpObjNormalizePath(interp, pathPtr, nextCheckpoint) + Tcl_Interp *interp; + Tcl_Obj *pathPtr; + int nextCheckpoint; +{ + #define MAXMACFILENAMELEN 31 /* assumed to be < sizeof(StrFileName) */ + + StrFileName fileName; + StringPtr fileNamePtr; + int fileNameLen,newPathLen; + Handle newPathHandle; + OSErr err; + short vRefNum; + long dirID; + Boolean isDirectory; + Boolean wasAlias; + FSSpec fileSpec; + + Tcl_DString nativeds; + + char cur; + int firstCheckpoint=nextCheckpoint, lastCheckpoint; + int origPathLen; + char *path = Tcl_GetStringFromObj(pathPtr,&origPathLen); + + { + int currDirValid=0; + /* + * check if substring to first ':' after initial + * nextCheckpoint is a valid relative or absolute + * path to a directory, if not we return without + * normalizing anything + */ + + while (1) { + cur = path[nextCheckpoint]; + if (cur == ':' || cur == 0) { + if (cur == ':') { nextCheckpoint++; cur = path[nextCheckpoint]; } /* jump over separator */ + Tcl_UtfToExternalDString(NULL,path,nextCheckpoint,&nativeds); + err = FSpLocationFromPath(Tcl_DStringLength(&nativeds), Tcl_DStringValue(&nativeds), &fileSpec); + Tcl_DStringFree(&nativeds); + if (err == noErr) { + err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + currDirValid = ((err == noErr) && isDirectory); + vRefNum = fileSpec.vRefNum; + } + break; + } + nextCheckpoint++; + } + + if(!currDirValid) return firstCheckpoint; /* can't determine root dir, bail out */ + } + + /* + * Now vRefNum and dirID point to a valid + * directory, so walk the rest of the path + * ( code adapted from FSpLocationFromPath() ) + */ + + lastCheckpoint=nextCheckpoint; + while (1) { + cur = path[nextCheckpoint]; + if (cur == ':' || cur == 0) { + fileNameLen=nextCheckpoint-lastCheckpoint; + fileNamePtr=fileName; + if(fileNameLen==0) { + if (cur == ':') { + /* + * special case for empty dirname i.e. encountered + * a '::' path component: get parent dir of currDir + */ + fileName[0]=2; + strcpy((char *) fileName + 1, "::"); + lastCheckpoint--; + } else { + /* + * empty filename, i.e. want FSSpec for currDir + */ + fileNamePtr=NULL; + } + } else { + Tcl_UtfToExternalDString(NULL,&path[lastCheckpoint],fileNameLen,&nativeds); + fileNameLen=Tcl_DStringLength(&nativeds); + if(fileNameLen > MAXMACFILENAMELEN) fileNameLen=MAXMACFILENAMELEN; + fileName[0]=fileNameLen; + strncpy((char *) fileName + 1, Tcl_DStringValue(&nativeds), fileNameLen); + Tcl_DStringFree(&nativeds); + } + err=FSMakeFSSpecCompat(vRefNum, dirID, fileNamePtr, &fileSpec); + if(err != noErr) { + if(err != fnfErr) { + /* + * this can if trying to get parent of a root volume via '::' + * or when using an illegal filename + * revert to last checkpoint and stop processing path further + */ + err=FSMakeFSSpecCompat(vRefNum, dirID, NULL, &fileSpec); + if(err != noErr) return firstCheckpoint; /* should never happen, bail out */ + nextCheckpoint=lastCheckpoint; + cur = path[lastCheckpoint]; + } + break; /* arrived at nonexistent file or dir */ + } else { + /* fileSpec could point to an alias, resolve it */ + err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias); + if (err != noErr || !isDirectory) break; /* fileSpec doesn't point to a dir */ + } + if (cur == 0) break; /* arrived at end of path */ + + /* fileSpec points to possibly nonexisting subdirectory; validate */ + err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + if (err != noErr || !isDirectory) break; /* fileSpec doesn't point to existing dir */ + vRefNum = fileSpec.vRefNum; + + /* found a new valid subdir in path, continue processing path */ + lastCheckpoint=nextCheckpoint+1; + } + nextCheckpoint++; + } + + /* + * fileSpec now points to a possibly nonexisting file or dir + * inside a valid dir; get full path name to it + */ + + err=FSpPathFromLocation(&fileSpec, &newPathLen, &newPathHandle); + if(err != noErr) return firstCheckpoint; /* should not see any errors here, bail out */ + + HLock(newPathHandle); + Tcl_ExternalToUtfDString(NULL,*newPathHandle,newPathLen,&nativeds); + if (cur != 0) { + /* not at end, append remaining path */ + if ( newPathLen==0 || *(*newPathHandle+(newPathLen-1))!=':') { + Tcl_DStringAppend(&nativeds, ":" , 1); + } + Tcl_DStringAppend(&nativeds, &path[nextCheckpoint+1], strlen(&path[nextCheckpoint+1])); + } + DisposeHandle(newPathHandle); + + fileNameLen=Tcl_DStringLength(&nativeds); + Tcl_SetStringObj(pathPtr,Tcl_DStringValue(&nativeds),fileNameLen); + Tcl_DStringFree(&nativeds); + + return nextCheckpoint+(fileNameLen-origPathLen); +} diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c index b6ae7a2..fd186b7 100644 --- a/mac/tclMacFile.c +++ b/mac/tclMacFile.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacFile.c,v 1.9 1999/12/12 22:46:45 hobbs Exp $ + * RCS: @(#) $Id: tclMacFile.c,v 1.10 2001/07/31 19:12:07 vincentdarley Exp $ */ /* @@ -31,12 +31,16 @@ #include <MoreFilesExtras.h> #include <FSpCompat.h> -/* - * Static variables used by the TclpStat function. - */ -static int initialized = false; -static long gmt_offset; -TCL_DECLARE_MUTEX(gmtMutex) +static OSErr FspLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr, FSSpec* specPtr)); + +OSErr +FspLocationFromFsPath(pathPtr, specPtr) + Tcl_Obj *pathPtr; + FSSpec* specPtr; +{ + char *native = Tcl_FSGetNativePath(pathPtr); + return FSpLocationFromPath(strlen(native), native, specPtr); +} /* @@ -102,17 +106,16 @@ TclpFindExecutable( /* *---------------------------------------------------------------------- * - * TclpMatchFilesTypes -- + * TclpMatchInDirectory -- * * This routine is used by the globbing code to search a * directory for all files which match a given pattern. * * Results: - * If the tail argument is NULL, then the matching files are - * added to the the interp's result. Otherwise, TclDoGlob is called - * recursively for each matching subdirectory. The return value - * is a standard Tcl result indicating whether an error occurred - * in globbing. + * + * The return value is a standard Tcl result indicating whether an + * error occurred in globbing. Errors are left in interp, good + * results are lappended to resultPtr (which must be a valid object) * * Side effects: * None. @@ -120,21 +123,18 @@ TclpFindExecutable( *---------------------------------------------------------------------- */ int -TclpMatchFilesTypes( - Tcl_Interp *interp, /* Interpreter to receive results. */ - char *separators, /* Directory separators to pass to TclDoGlob. */ - Tcl_DString *dirPtr, /* Contains path to directory to search. */ - char *pattern, /* Pattern to match against. */ - char *tail, /* Pointer to end of pattern. Tail must - * point to a location in pattern and must - * not be static.*/ - GlobTypeData *types) /* Object containing list of acceptable types. - * May be NULL. */ +TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) + Tcl_Interp *interp; /* Interpreter to receive errors. */ + Tcl_Obj *resultPtr; /* List object to lappend results. */ + Tcl_Obj *pathPtr; /* Contains path to directory to search. */ + char *pattern; /* Pattern to match against. */ + Tcl_GlobTypeData *types; /* Object containing list of acceptable types. + * May be NULL. In particular the directory + * flag is very important. */ { - char *fname, *patternEnd = tail; - char savedChar; + char *fname; int fnameLen, result = TCL_OK; - int baseLength = Tcl_DStringLength(dirPtr); + int baseLength; CInfoPBRec pb; OSErr err; FSSpec dirSpec; @@ -143,26 +143,59 @@ TclpMatchFilesTypes( short itemIndex; Str255 fileName; Tcl_DString fileString; - Tcl_Obj *resultPtr; OSType okType = 0; OSType okCreator = 0; + Tcl_DString dsOrig; + char *fileName2; + + fileName2 = Tcl_FSGetTranslatedPath(interp, pathPtr); + if (fileName2 == NULL) { + return TCL_ERROR; + } + Tcl_DStringInit(&dsOrig); + Tcl_DStringAppend(&dsOrig, fileName2, -1); + baseLength = Tcl_DStringLength(&dsOrig); /* * Make sure that the directory part of the name really is a * directory. */ - Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(dirPtr), - Tcl_DStringLength(dirPtr), &fileString); + Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&dsOrig), + Tcl_DStringLength(&dsOrig), &fileString); - FSpLocationFromPath(fileString.length, fileString.string, &dirSpec); + err = FSpLocationFromPath(Tcl_DStringLength(&fileString), Tcl_DStringValue(&fileString), &dirSpec); Tcl_DStringFree(&fileString); + if (err == noErr) + err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory); + if ((err != noErr) || !isDirectory) { + /* + * Check if we had a relative path (unix style rel path compatibility for glob) + */ + Tcl_DStringFree(&dsOrig); + Tcl_DStringAppend(&dsOrig, ":", 1); + Tcl_DStringAppend(&dsOrig, fileName2, -1); + baseLength = Tcl_DStringLength(&dsOrig); + Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&dsOrig), + Tcl_DStringLength(&dsOrig), &fileString); + + err = FSpLocationFromPath(Tcl_DStringLength(&fileString), Tcl_DStringValue(&fileString), &dirSpec); + Tcl_DStringFree(&fileString); + if (err == noErr) err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory); if ((err != noErr) || !isDirectory) { - return TCL_OK; + Tcl_DStringFree(&dsOrig); + return TCL_OK; + } } + /* Make sure we have a trailing directory delimiter */ + if (Tcl_DStringValue(&dsOrig)[baseLength-1] != ':') { + Tcl_DStringAppend(&dsOrig, ":", 1); + baseLength++; + } + /* * Now open the directory for reading and iterate over the contents. */ @@ -172,25 +205,6 @@ TclpMatchFilesTypes( pb.hFileInfo.ioNamePtr = (StringPtr) fileName; pb.hFileInfo.ioFDirIndex = itemIndex = 1; - /* - * Clean up the end of the pattern and the tail pointer. Leave - * the tail pointing to the first character after the path separator - * following the pattern, or NULL. Also, ensure that the pattern - * is null-terminated. - */ - - if (*tail == '\\') { - tail++; - } - if (*tail == '\0') { - tail = NULL; - } else { - tail++; - } - savedChar = *patternEnd; - *patternEnd = '\0'; - - resultPtr = Tcl_GetObjResult(interp); if (types != NULL) { if (types->macType != NULL) { Tcl_GetOSTypeFromObj(NULL, types->macType, &okType); @@ -209,128 +223,112 @@ TclpMatchFilesTypes( } /* - * Now check to see if the file matches. If there are more - * characters to be processed, then ensure matching files are - * directories before calling TclDoGlob. Otherwise, just add - * the file to the result. + * Now check to see if the file matches. */ Tcl_ExternalToUtfDString(NULL, (char *) fileName + 1, fileName[0], &fileString); if (Tcl_StringMatch(Tcl_DStringValue(&fileString), pattern)) { - Tcl_DStringSetLength(dirPtr, baseLength); - Tcl_DStringAppend(dirPtr, Tcl_DStringValue(&fileString), -1); - fname = Tcl_DStringValue(dirPtr); - fnameLen = Tcl_DStringLength(dirPtr); - if (tail == NULL) { - int typeOk = 1; - if (types != NULL) { - if (types->perm != 0) { - if ( - ((types->perm & TCL_GLOB_PERM_RONLY) && - !(pb.hFileInfo.ioFlAttrib & 1)) || - ((types->perm & TCL_GLOB_PERM_HIDDEN) && - !(pb.hFileInfo.ioFlFndrInfo.fdFlags & - kIsInvisible)) || - ((types->perm & TCL_GLOB_PERM_R) && - (TclpAccess(fname, R_OK) != 0)) || - ((types->perm & TCL_GLOB_PERM_W) && - (TclpAccess(fname, W_OK) != 0)) || - ((types->perm & TCL_GLOB_PERM_X) && - (TclpAccess(fname, X_OK) != 0)) - ) { - typeOk = 0; - } + int typeOk = 1; + Tcl_DStringSetLength(&dsOrig, baseLength); + Tcl_DStringAppend(&dsOrig, Tcl_DStringValue(&fileString), -1); + fname = Tcl_DStringValue(&dsOrig); + fnameLen = Tcl_DStringLength(&dsOrig); + + if (types == NULL) { + /* If invisible, don't return the file */ + if (pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) { + typeOk = 0; + } + } else { + if (pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) { + /* If invisible */ + if ((types->perm == 0) || + !(types->perm & TCL_GLOB_PERM_HIDDEN)) { + typeOk = 0; } - if (typeOk == 1 && types->type != 0) { - struct stat buf; + } else { + /* Visible */ + if (types->perm & TCL_GLOB_PERM_HIDDEN) { + typeOk = 0; + } + } + if (typeOk == 1 && types->perm != 0) { + if ( + ((types->perm & TCL_GLOB_PERM_RONLY) && + !(pb.hFileInfo.ioFlAttrib & 1)) || + ((types->perm & TCL_GLOB_PERM_R) && + (TclpAccess(fname, R_OK) != 0)) || + ((types->perm & TCL_GLOB_PERM_W) && + (TclpAccess(fname, W_OK) != 0)) || + ((types->perm & TCL_GLOB_PERM_X) && + (TclpAccess(fname, X_OK) != 0)) + ) { + typeOk = 0; + } + } + if (typeOk == 1 && types->type != 0) { + struct stat buf; + /* + * We must match at least one flag to be listed + */ + typeOk = 0; + if (TclpLstat(fname, &buf) >= 0) { /* - * We must match at least one flag to be listed + * In order bcdpfls as in 'find -t' */ - typeOk = 0; - if (TclpLstat(fname, &buf) >= 0) { - /* - * In order bcdpfls as in 'find -t' - */ - if ( - ((types->type & TCL_GLOB_TYPE_BLOCK) && - S_ISBLK(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_CHAR) && - S_ISCHR(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_DIR) && - S_ISDIR(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_PIPE) && - S_ISFIFO(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_FILE) && - S_ISREG(buf.st_mode)) + if ( + ((types->type & TCL_GLOB_TYPE_BLOCK) && + S_ISBLK(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_CHAR) && + S_ISCHR(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_DIR) && + S_ISDIR(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_PIPE) && + S_ISFIFO(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_FILE) && + S_ISREG(buf.st_mode)) #ifdef S_ISLNK - || ((types->type & TCL_GLOB_TYPE_LINK) && - S_ISLNK(buf.st_mode)) + || ((types->type & TCL_GLOB_TYPE_LINK) && + S_ISLNK(buf.st_mode)) #endif #ifdef S_ISSOCK - || ((types->type & TCL_GLOB_TYPE_SOCK) && - S_ISSOCK(buf.st_mode)) + || ((types->type & TCL_GLOB_TYPE_SOCK) && + S_ISSOCK(buf.st_mode)) #endif - ) { - typeOk = 1; - } - } else { - /* Posix error occurred */ + ) { + typeOk = 1; } - } - if (typeOk && ( - ((okType != 0) && (okType != - pb.hFileInfo.ioFlFndrInfo.fdType)) || - ((okCreator != 0) && (okCreator != - pb.hFileInfo.ioFlFndrInfo.fdCreator)))) { - typeOk = 0; - } - } - if (typeOk) { - if ((fnameLen > 1) && (strchr(fname+1, ':') == NULL)) { - Tcl_ListObjAppendElement(interp, resultPtr, - Tcl_NewStringObj(fname+1, fnameLen-1)); } else { - Tcl_ListObjAppendElement(interp, resultPtr, - Tcl_NewStringObj(fname, fnameLen)); + /* Posix error occurred */ } } - } else if ((pb.hFileInfo.ioFlAttrib & ioDirMask) != 0) { - Tcl_DStringAppend(dirPtr, ":", 1); - result = TclDoGlob(interp, separators, dirPtr, tail, types); - if (result != TCL_OK) { - Tcl_DStringFree(&fileString); - break; + if (typeOk && ( + ((okType != 0) && (okType != + pb.hFileInfo.ioFlFndrInfo.fdType)) || + ((okCreator != 0) && (okCreator != + pb.hFileInfo.ioFlFndrInfo.fdCreator)))) { + typeOk = 0; + } + } + if (typeOk) { + if ((fnameLen > 1) && (strchr(fname+1, ':') == NULL)) { + Tcl_ListObjAppendElement(interp, resultPtr, + Tcl_NewStringObj(fname+1, fnameLen-1)); + } else { + Tcl_ListObjAppendElement(interp, resultPtr, + Tcl_NewStringObj(fname, fnameLen)); } } } Tcl_DStringFree(&fileString); itemIndex++; } - *patternEnd = savedChar; + Tcl_DStringFree(&dsOrig); return result; } -/* - * TclpMatchFiles -- - * - * This function is now obsolete. Call the above function - * 'TclpMatchFilesTypes' instead. - */ -int -TclpMatchFiles( - Tcl_Interp *interp, /* Interpreter to receive results. */ - char *separators, /* Directory separators to pass to TclDoGlob. */ - Tcl_DString *dirPtr, /* Contains path to directory to search. */ - char *pattern, /* Pattern to match against. */ - char *tail) /* Pointer to end of pattern. Tail must - * point to a location in pattern and must - * not be static.*/ -{ - return TclpMatchFilesTypes(interp,separators,dirPtr,pattern,tail,NULL); -} - /* *---------------------------------------------------------------------- * @@ -352,82 +350,12 @@ TclpAccess( CONST char *path, /* Path of file to access (UTF-8). */ int mode) /* Permission setting. */ { - HFileInfo fpb; - HVolumeParam vpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - long dirID; - Tcl_DString ds; - char *native; - int full_mode = 0; - - native = Tcl_UtfToExternalDString(NULL, path, -1, &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &fileSpec); - Tcl_DStringFree(&ds); - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return -1; - } - - /* - * Fill the fpb & vpb struct up with info about file or directory. - */ - FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); - vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; - vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; - if (isDirectory) { - fpb.ioDirID = fileSpec.parID; - } else { - fpb.ioDirID = dirID; - } - - fpb.ioFDirIndex = 0; - err = PBGetCatInfoSync((CInfoPBPtr)&fpb); - if (err == noErr) { - vpb.ioVolIndex = 0; - err = PBHGetVInfoSync((HParmBlkPtr)&vpb); - if (err == noErr) { - /* - * Use the Volume Info & File Info to determine - * access information. If we have got this far - * we know the directory is searchable or the file - * exists. (We have F_OK) - */ - - /* - * Check to see if the volume is hardware or - * software locked. If so we arn't W_OK. - */ - if (mode & W_OK) { - if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) { - errno = EROFS; - return -1; - } - if (fpb.ioFlAttrib & 0x01) { - errno = EACCES; - return -1; - } - } - - /* - * Directories are always searchable and executable. But only - * files of type 'APPL' are executable. - */ - if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK) - && (fpb.ioFlFndrInfo.fdType != 'APPL')) { - return -1; - } - } - } - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return -1; - } - - return 0; + int ret; + Tcl_Obj *obj = Tcl_NewStringObj(path,-1); + Tcl_IncrRefCount(obj); + ret = TclpObjAccess(obj,mode); + Tcl_DecrRefCount(obj); + return ret; } /* @@ -451,46 +379,12 @@ int TclpChdir( CONST char *dirName) /* Path to new working directory (UTF-8). */ { - FSSpec spec; - OSErr err; - Boolean isFolder; - long dirID; - Tcl_DString ds; - char *native; - - native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &spec); - Tcl_DStringFree(&ds); - - if (err != noErr) { - errno = ENOENT; - return -1; - } - - err = FSpGetDirectoryID(&spec, &dirID, &isFolder); - if (err != noErr) { - errno = ENOENT; - return -1; - } - - if (isFolder != true) { - errno = ENOTDIR; - return -1; - } - - err = FSpSetDefaultDir(&spec); - if (err != noErr) { - switch (err) { - case afpAccessDenied: - errno = EACCES; - break; - default: - errno = ENOENT; - } - return -1; - } - - return 0; + int ret; + Tcl_Obj *obj = Tcl_NewStringObj(dirName,-1); + Tcl_IncrRefCount(obj); + ret = TclpObjChdir(obj); + Tcl_DecrRefCount(obj); + return ret; } /* @@ -728,116 +622,12 @@ TclpStat( CONST char *path, /* Path of file to stat (in UTF-8). */ struct stat *bufPtr) /* Filled with results of stat call. */ { - HFileInfo fpb; - HVolumeParam vpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - long dirID; - Tcl_DString ds; - - path = Tcl_UtfToExternalDString(NULL, path, -1, &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), path, &fileSpec); - Tcl_DStringFree(&ds); - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - return -1; - } - - /* - * Fill the fpb & vpb struct up with info about file or directory. - */ - - FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); - vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; - vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; - if (isDirectory) { - fpb.ioDirID = fileSpec.parID; - } else { - fpb.ioDirID = dirID; - } - - fpb.ioFDirIndex = 0; - err = PBGetCatInfoSync((CInfoPBPtr)&fpb); - if (err == noErr) { - vpb.ioVolIndex = 0; - err = PBHGetVInfoSync((HParmBlkPtr)&vpb); - if (err == noErr && bufPtr != NULL) { - /* - * Files are always readable by everyone. - */ - - bufPtr->st_mode = S_IRUSR | S_IRGRP | S_IROTH; - - /* - * Use the Volume Info & File Info to fill out stat buf. - */ - if (fpb.ioFlAttrib & 0x10) { - bufPtr->st_mode |= S_IFDIR; - bufPtr->st_nlink = 2; - } else { - bufPtr->st_nlink = 1; - if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { - bufPtr->st_mode |= S_IFLNK; - } else { - bufPtr->st_mode |= S_IFREG; - } - } - if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) { - /* - * Directories and applications are executable by everyone. - */ - - bufPtr->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; - } - if ((fpb.ioFlAttrib & 0x01) == 0){ - /* - * If not locked, then everyone has write acces. - */ - - bufPtr->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - } - bufPtr->st_ino = fpb.ioDirID; - bufPtr->st_dev = fpb.ioVRefNum; - bufPtr->st_uid = -1; - bufPtr->st_gid = -1; - bufPtr->st_rdev = 0; - bufPtr->st_size = fpb.ioFlLgLen; - bufPtr->st_blksize = vpb.ioVAlBlkSiz; - bufPtr->st_blocks = (bufPtr->st_size + bufPtr->st_blksize - 1) - / bufPtr->st_blksize; - - /* - * The times returned by the Mac file system are in the - * local time zone. We convert them to GMT so that the - * epoch starts from GMT. This is also consistant with - * what is returned from "clock seconds". - */ - - Tcl_MutexLock(&gmtMutex); - if (initialized == false) { - MachineLocation loc; - - ReadLocation(&loc); - gmt_offset = loc.u.gmtDelta & 0x00ffffff; - if (gmt_offset & 0x00800000) { - gmt_offset = gmt_offset | 0xff000000; - } - initialized = true; - } - Tcl_MutexUnlock(&gmtMutex); - - bufPtr->st_atime = bufPtr->st_mtime = fpb.ioFlMdDat - gmt_offset; - bufPtr->st_ctime = fpb.ioFlCrDat - gmt_offset; - } - } - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - } - - return (err == noErr ? 0 : -1); + int ret; + Tcl_Obj *obj = Tcl_NewStringObj(path,-1); + Tcl_IncrRefCount(obj); + ret = TclpObjStat(obj,bufPtr); + Tcl_DecrRefCount(obj); + return ret; } /* @@ -994,6 +784,7 @@ TclMacOSErrorToPosixError( return EINVAL; } } + int TclMacChmod( char *path, @@ -1021,3 +812,295 @@ TclMacChmod( return 0; } + +int +TclpObjStat(pathPtr, bufPtr) + Tcl_Obj *pathPtr; + struct stat *bufPtr; +{ + HFileInfo fpb; + HVolumeParam vpb; + OSErr err; + FSSpec fileSpec; + Boolean isDirectory; + long dirID; + + err = FspLocationFromFsPath(pathPtr, &fileSpec); + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return -1; + } + + /* + * Fill the fpb & vpb struct up with info about file or directory. + */ + + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; + vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; + if (isDirectory) { + fpb.ioDirID = fileSpec.parID; + } else { + fpb.ioDirID = dirID; + } + + fpb.ioFDirIndex = 0; + err = PBGetCatInfoSync((CInfoPBPtr)&fpb); + if (err == noErr) { + vpb.ioVolIndex = 0; + err = PBHGetVInfoSync((HParmBlkPtr)&vpb); + if (err == noErr && bufPtr != NULL) { + /* + * Files are always readable by everyone. + */ + + bufPtr->st_mode = S_IRUSR | S_IRGRP | S_IROTH; + + /* + * Use the Volume Info & File Info to fill out stat buf. + */ + if (fpb.ioFlAttrib & 0x10) { + bufPtr->st_mode |= S_IFDIR; + bufPtr->st_nlink = 2; + } else { + bufPtr->st_nlink = 1; + if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { + bufPtr->st_mode |= S_IFLNK; + } else { + bufPtr->st_mode |= S_IFREG; + } + } + if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) { + /* + * Directories and applications are executable by everyone. + */ + + bufPtr->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + } + if ((fpb.ioFlAttrib & 0x01) == 0){ + /* + * If not locked, then everyone has write acces. + */ + + bufPtr->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + } + bufPtr->st_ino = fpb.ioDirID; + bufPtr->st_dev = fpb.ioVRefNum; + bufPtr->st_uid = -1; + bufPtr->st_gid = -1; + bufPtr->st_rdev = 0; + bufPtr->st_size = fpb.ioFlLgLen; + bufPtr->st_blksize = vpb.ioVAlBlkSiz; + bufPtr->st_blocks = (bufPtr->st_size + bufPtr->st_blksize - 1) + / bufPtr->st_blksize; + + /* + * The times returned by the Mac file system are in the + * local time zone. We convert them to GMT so that the + * epoch starts from GMT. This is also consistant with + * what is returned from "clock seconds". + */ + + bufPtr->st_atime = bufPtr->st_mtime = fpb.ioFlMdDat - TclpGetGMTOffset() + tcl_mac_epoch_offset; + bufPtr->st_ctime = fpb.ioFlCrDat - TclpGetGMTOffset() + tcl_mac_epoch_offset; + } + } + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + } + + return (err == noErr ? 0 : -1); +} + +Tcl_Obj* +TclpObjGetCwd(interp) + Tcl_Interp *interp; +{ + Tcl_DString ds; + if (TclpGetCwd(interp, &ds) != NULL) { + Tcl_Obj *cwdPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); + Tcl_IncrRefCount(cwdPtr); + Tcl_DStringFree(&ds); + return cwdPtr; + } else { + return NULL; + } +} + +int +TclpObjChdir(pathPtr) + Tcl_Obj *pathPtr; +{ + FSSpec spec; + OSErr err; + Boolean isFolder; + long dirID; + + err = FspLocationFromFsPath(pathPtr, &spec); + + if (err != noErr) { + errno = ENOENT; + return -1; + } + + err = FSpGetDirectoryID(&spec, &dirID, &isFolder); + if (err != noErr) { + errno = ENOENT; + return -1; + } + + if (isFolder != true) { + errno = ENOTDIR; + return -1; + } + + err = FSpSetDefaultDir(&spec); + if (err != noErr) { + switch (err) { + case afpAccessDenied: + errno = EACCES; + break; + default: + errno = ENOENT; + } + return -1; + } + + return 0; +} + +int +TclpObjAccess(pathPtr, mode) + Tcl_Obj *pathPtr; + int mode; +{ + HFileInfo fpb; + HVolumeParam vpb; + OSErr err; + FSSpec fileSpec; + Boolean isDirectory; + long dirID; + int full_mode = 0; + + err = FspLocationFromFsPath(pathPtr, &fileSpec); + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return -1; + } + + /* + * Fill the fpb & vpb struct up with info about file or directory. + */ + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; + vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; + if (isDirectory) { + fpb.ioDirID = fileSpec.parID; + } else { + fpb.ioDirID = dirID; + } + + fpb.ioFDirIndex = 0; + err = PBGetCatInfoSync((CInfoPBPtr)&fpb); + if (err == noErr) { + vpb.ioVolIndex = 0; + err = PBHGetVInfoSync((HParmBlkPtr)&vpb); + if (err == noErr) { + /* + * Use the Volume Info & File Info to determine + * access information. If we have got this far + * we know the directory is searchable or the file + * exists. (We have F_OK) + */ + + /* + * Check to see if the volume is hardware or + * software locked. If so we arn't W_OK. + */ + if (mode & W_OK) { + if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) { + errno = EROFS; + return -1; + } + if (fpb.ioFlAttrib & 0x01) { + errno = EACCES; + return -1; + } + } + + /* + * Directories are always searchable and executable. But only + * files of type 'APPL' are executable. + */ + if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK) + && (fpb.ioFlFndrInfo.fdType != 'APPL')) { + return -1; + } + } + } + + if (err != noErr) { + errno = TclMacOSErrorToPosixError(err); + return -1; + } + + return 0; +} + +int +TclpObjLstat(pathPtr, buf) + Tcl_Obj *pathPtr; + struct stat *buf; +{ + return TclpObjStat(pathPtr, buf); +} + + +/* + *---------------------------------------------------------------------- + * + * TclpTempFileName -- + * + * This function returns a unique filename. + * + * Results: + * Returns a valid Tcl_Obj* with refCount 0, or NULL on failure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj* +TclpTempFileName() +{ + char fileName[L_tmpnam]; + + if (tmpnam(fileName) == NULL) { /* INTL: Native. */ + return NULL; + } + + return TclpNativeToNormalized((ClientData) fileName); +} + +#ifdef S_IFLNK + +Tcl_Obj* +TclpObjReadlink(pathPtr) + Tcl_Obj *pathPtr; +{ + Tcl_DString ds; + Tcl_Obj* link = NULL; + if (TclpReadlink(Tcl_FSGetTranslatedPath(NULL, pathPtr), &ds) != NULL) { + link = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); + Tcl_IncrRefCount(link); + Tcl_DStringFree(&ds); + } + return link; +} + +#endif diff --git a/mac/tclMacInit.c b/mac/tclMacInit.c index 53ab851..eb6a066 100644 --- a/mac/tclMacInit.c +++ b/mac/tclMacInit.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacInit.c,v 1.4 1999/05/11 07:12:16 jingham Exp $ + * RCS: @(#) $Id: tclMacInit.c,v 1.5 2001/07/31 19:12:07 vincentdarley Exp $ */ #include <AppleEvents.h> @@ -132,6 +132,11 @@ static Map cyrillicMap[] = { static int GetFinderFont(int *finderID); +/* Used to store the encoding used for binary files */ +static Tcl_Encoding binaryEncoding = NULL; +/* Has the basic library path encoding issue been fixed */ +static int libraryPathEncodingFixed = 0; + /* *---------------------------------------------------------------------- @@ -393,13 +398,18 @@ TclpInitLibraryPath(argv0) * Based on the locale, determine the encoding of the operating * system and the default encoding for newly opened files. * - * Called at process initialization time. + * Called at process initialization time, and part way through + * startup, we verify that the initial encodings were correctly + * setup. Depending on Tcl's environment, there may not have been + * enough information first time through (above). * * Results: * None. * * Side effects: - * The Tcl library path is converted from native encoding to UTF-8. + * The Tcl library path is converted from native encoding to UTF-8, + * on the first call, and the encodings may be changed on first or + * second call. * *--------------------------------------------------------------------------- */ @@ -419,7 +429,9 @@ TclpSetInitialEncodings() } Tcl_SetSystemEncoding(NULL, encoding); - + + if (libraryPathEncodingFixed == 0) { + /* * Until the system encoding was actually set, the library path was * actually in the native multi-byte encoding, and not really UTF-8 @@ -461,13 +473,17 @@ TclpSetInitialEncodings() Tcl_DStringFree(&ds); } } - - /* - * Keep the iso8859-1 encoding preloaded. The IO package uses it for - * gets on a binary channel. - */ - - Tcl_GetEncoding(NULL, "iso8859-1"); + libraryPathEncodingFixed = 1; + } + + /* This is only ever called from the startup thread */ + if (binaryEncoding == NULL) { + /* + * Keep the iso8859-1 encoding preloaded. The IO package uses + * it for gets on a binary channel. + */ + binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } } /* diff --git a/mac/tclMacPort.h b/mac/tclMacPort.h index 18b0f2d..1336f87 100644 --- a/mac/tclMacPort.h +++ b/mac/tclMacPort.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacPort.h,v 1.11 2000/07/26 01:28:24 davidg Exp $ + * RCS: @(#) $Id: tclMacPort.h,v 1.12 2001/07/31 19:12:07 vincentdarley Exp $ */ @@ -219,6 +219,26 @@ extern char **environ; #define HAVE_TM_ZONE + +/* + * If we're using the Metrowerks MSL, we need to convert time_t values from + * the mac epoch to the msl epoch (== unix epoch) by adding the offset from + * <time.mac.h> to mac time_t values, as MSL is using its epoch for file + * access routines such as stat or utime + */ + +#ifdef __MSL__ +#include <time.mac.h> +#ifdef _mac_msl_epoch_offset_ +#define tcl_mac_epoch_offset _mac_msl_epoch_offset_ +#define TCL_MAC_USE_MSL_EPOCH /* flag for TclDate.c */ +#else +#define tcl_mac_epoch_offset 0L +#endif +#else +#define tcl_mac_epoch_offset 0L +#endif + /* * The following macros have trivial definitions, allowing generic code to * address platform-specific issues. diff --git a/mac/tclMacResource.c b/mac/tclMacResource.c index 4362ede..4c06237 100644 --- a/mac/tclMacResource.c +++ b/mac/tclMacResource.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacResource.c,v 1.7 1999/08/15 04:54:03 jingham Exp $ + * RCS: @(#) $Id: tclMacResource.c,v 1.8 2001/07/31 19:12:07 vincentdarley Exp $ */ #include <Errors.h> @@ -954,8 +954,7 @@ Tcl_MacSourceObjCmd( } if (objc == 2) { - string = Tcl_GetStringFromObj(objv[1], &length); - return Tcl_EvalFile(interp, string); + return Tcl_FSEvalFile(interp, objv[1]); } /* diff --git a/mac/tclMacTime.c b/mac/tclMacTime.c index 1a2d1ed..25bf08e 100644 --- a/mac/tclMacTime.c +++ b/mac/tclMacTime.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacTime.c,v 1.3 1999/03/10 05:52:51 stanton Exp $ + * RCS: @(#) $Id: tclMacTime.c,v 1.4 2001/07/31 19:12:07 vincentdarley Exp $ */ #include "tclInt.h" @@ -26,6 +26,13 @@ static int initalized = false; static unsigned long baseSeconds; static UnsignedWide microOffset; +static int gmt_initialized = false; +static long gmt_offset; +static int gmt_isdst; +TCL_DECLARE_MUTEX(gmtMutex) + +static int gmt_lastGetDateUseGMT = 0; + /* * Prototypes for procedures that are private to this file: */ @@ -36,6 +43,43 @@ static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x, /* *----------------------------------------------------------------------------- * + * TclpGetGMTOffset -- + * + * This procedure gets the offset seconds that needs to be _added_ to tcl time + * in seconds (i.e. GMT time) to get local time needed as input to various + * Mac OS APIs, to convert Mac OS API output to tcl time, _subtract_ this value. + * + * Results: + * Number of seconds separating GMT time and mac. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +long +TclpGetGMTOffset() +{ + if (gmt_initialized == false) { + MachineLocation loc; + + Tcl_MutexLock(&gmtMutex); + ReadLocation(&loc); + gmt_offset = loc.u.gmtDelta & 0x00ffffff; + if (gmt_offset & 0x00800000) { + gmt_offset = gmt_offset | 0xff000000; + } + gmt_isdst=(loc.u.dlsDelta < 0); + gmt_initialized = true; + Tcl_MutexUnlock(&gmtMutex); + } + return (gmt_offset); +} + +/* + *----------------------------------------------------------------------------- + * * TclpGetSeconds -- * * This procedure returns the number of seconds from the epoch. On @@ -57,21 +101,9 @@ unsigned long TclpGetSeconds() { unsigned long seconds; - MachineLocation loc; - long int offset; - - ReadLocation(&loc); - offset = loc.u.gmtDelta & 0x00ffffff; - if (offset & 0x00800000) { - offset = offset | 0xff000000; - } - if (ReadDateTime(&seconds) == noErr) { - return (seconds - offset); - } else { - panic("Can't get time."); - return 0; - } + GetDateTime(&seconds); + return (seconds - TclpGetGMTOffset() + tcl_mac_epoch_offset); } /* @@ -123,22 +155,15 @@ int TclpGetTimeZone ( unsigned long currentTime) /* Ignored on Mac. */ { - MachineLocation loc; - long int offset; - - ReadLocation(&loc); - offset = loc.u.gmtDelta & 0x00ffffff; - if (offset & 0x00700000) { - offset |= 0xff000000; - } + long offset; /* * Convert the Mac offset from seconds to minutes and * add an hour if we have daylight savings time. */ - offset = -offset; + offset = -TclpGetGMTOffset(); offset /= 60; - if (loc.u.dlsDelta < 0) { + if (gmt_isdst) { offset += 60; } @@ -172,24 +197,11 @@ TclpGetTime( #endif if (initalized == false) { - MachineLocation loc; - long int offset; - - ReadLocation(&loc); - offset = loc.u.gmtDelta & 0x00ffffff; - if (offset & 0x00800000) { - offset = offset | 0xff000000; - } - if (ReadDateTime(&baseSeconds) != noErr) { - /* - * This should never happen! - */ - return; - } + GetDateTime(&baseSeconds); /* * Remove the local offset that ReadDateTime() adds. */ - baseSeconds -= offset; + baseSeconds -= TclpGetGMTOffset() - tcl_mac_epoch_offset; Microseconds(µOffset); initalized = true; } @@ -246,25 +258,16 @@ TclpGetDate( { const time_t *tp = (const time_t *)time; DateTimeRec dtr; - MachineLocation loc; - long int offset; + unsigned long offset=0L; static struct tm statictime; static const short monthday[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - - ReadLocation(&loc); + + if(useGMT) + SecondsToDate(*tp - tcl_mac_epoch_offset, &dtr); + else + SecondsToDate(*tp + TclpGetGMTOffset() - tcl_mac_epoch_offset, &dtr); - if (useGMT) { - SecondsToDate(*tp, &dtr); - } else { - offset = loc.u.gmtDelta & 0x00ffffff; - if (offset & 0x00700000) { - offset |= 0xff000000; - } - - SecondsToDate(*tp + offset, &dtr); - } - statictime.tm_sec = dtr.second; statictime.tm_min = dtr.minute; statictime.tm_hour = dtr.hour; @@ -277,7 +280,11 @@ TclpGetDate( if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) { ++statictime.tm_yday; } - statictime.tm_isdst = loc.u.dlsDelta; + if(useGMT) + statictime.tm_isdst = 0; + else + statictime.tm_isdst = gmt_isdst; + gmt_lastGetDateUseGMT=useGMT; /* hack to make TclpGetTZName below work */ return(&statictime); } |