summaryrefslogtreecommitdiffstats
path: root/mac/tclMacFile.c
diff options
context:
space:
mode:
authorstanton <stanton>1999-04-16 00:46:29 (GMT)
committerstanton <stanton>1999-04-16 00:46:29 (GMT)
commit97464e6cba8eb0008cf2727c15718671992b913f (patch)
treece9959f2747257d98d52ec8d18bf3b0de99b9535 /mac/tclMacFile.c
parenta8c96ddb94d1483a9de5e340b740cb74ef6cafa7 (diff)
downloadtcl-97464e6cba8eb0008cf2727c15718671992b913f.zip
tcl-97464e6cba8eb0008cf2727c15718671992b913f.tar.gz
tcl-97464e6cba8eb0008cf2727c15718671992b913f.tar.bz2
merged tcl 8.1 branch back into the main trunk
Diffstat (limited to 'mac/tclMacFile.c')
-rw-r--r--mac/tclMacFile.c660
1 files changed, 326 insertions, 334 deletions
diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c
index 2fc697e..94582bd 100644
--- a/mac/tclMacFile.c
+++ b/mac/tclMacFile.c
@@ -5,12 +5,12 @@
* files. It also comtains Macintosh version of other Tcl
* functions that deal with the file system.
*
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1995-1998 Sun Microsystems, Inc.
*
* 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.5 1999/03/10 05:52:51 stanton Exp $
+ * RCS: @(#) $Id: tclMacFile.c,v 1.6 1999/04/16 00:47:20 stanton Exp $
*/
/*
@@ -34,164 +34,10 @@
/*
* Static variables used by the TclpStat function.
*/
-static int initalized = false;
+static int initialized = false;
static long gmt_offset;
+TCL_DECLARE_MUTEX(gmtMutex)
-/*
- * The variable below caches the name of the current working directory
- * in order to avoid repeated calls to getcwd. The string is malloc-ed.
- * NULL means the cache needs to be refreshed.
- */
-
-static char *currentDir = NULL;
-
-/*
- *----------------------------------------------------------------------
- *
- * TclChdir --
- *
- * Change the current working directory.
- *
- * Results:
- * The result is a standard Tcl result. If an error occurs and
- * interp isn't NULL, an error message is left in interp->result.
- *
- * Side effects:
- * The working directory for this application is changed. Also
- * the cache maintained used by TclGetCwd is deallocated and
- * set to NULL.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclChdir(
- Tcl_Interp *interp, /* If non NULL, used for error reporting. */
- char *dirName) /* Path to new working directory. */
-{
- FSSpec spec;
- OSErr err;
- Boolean isFolder;
- long dirID;
-
- if (currentDir != NULL) {
- ckfree(currentDir);
- currentDir = NULL;
- }
-
- err = FSpLocationFromPath(strlen(dirName), dirName, &spec);
- if (err != noErr) {
- errno = ENOENT;
- goto chdirError;
- }
-
- err = FSpGetDirectoryID(&spec, &dirID, &isFolder);
- if (err != noErr) {
- errno = ENOENT;
- goto chdirError;
- }
-
- if (isFolder != true) {
- errno = ENOTDIR;
- goto chdirError;
- }
-
- err = FSpSetDefaultDir(&spec);
- if (err != noErr) {
- switch (err) {
- case afpAccessDenied:
- errno = EACCES;
- break;
- default:
- errno = ENOENT;
- }
- goto chdirError;
- }
-
- return TCL_OK;
- chdirError:
- if (interp != NULL) {
- Tcl_AppendResult(interp, "couldn't change working directory to \"",
- dirName, "\": ", Tcl_PosixError(interp), (char *) NULL);
- }
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclGetCwd --
- *
- * Return the path name of the current working directory.
- *
- * Results:
- * The result is the full path name of the current working
- * directory, or NULL if an error occurred while figuring it
- * out. If an error occurs and interp isn't NULL, an error
- * message is left in interp->result.
- *
- * Side effects:
- * The path name is cached to avoid having to recompute it
- * on future calls; if it is already cached, the cached
- * value is returned.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-TclGetCwd(
- Tcl_Interp *interp) /* If non NULL, used for error reporting. */
-{
- FSSpec theSpec;
- int length;
- Handle pathHandle = NULL;
-
- if (currentDir == NULL) {
- if (FSpGetDefaultDir(&theSpec) != noErr) {
- if (interp != NULL) {
- interp->result = "error getting working directory name";
- }
- return NULL;
- }
- if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) {
- if (interp != NULL) {
- interp->result = "error getting working directory name";
- }
- return NULL;
- }
- HLock(pathHandle);
- currentDir = (char *) ckalloc((unsigned) (length + 1));
- strcpy(currentDir, *pathHandle);
- HUnlock(pathHandle);
- DisposeHandle(pathHandle);
- }
- return currentDir;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_WaitPid --
- *
- * Fakes a call to wait pid.
- *
- * Results:
- * Always returns -1.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Pid
-Tcl_WaitPid(
- Tcl_Pid pid,
- int *statPtr,
- int options)
-{
- return (Tcl_Pid) -1;
-}
/*
*----------------------------------------------------------------------
@@ -200,7 +46,7 @@ Tcl_WaitPid(
*
* This procedure computes the absolute path name of the current
* application, given its argv[0] value. However, this
- * implementation doesn't use of need the argv[0] value. NULL
+ * implementation doesn't need the argv[0] value. NULL
* may be passed in its place.
*
* Results:
@@ -216,7 +62,7 @@ Tcl_WaitPid(
void
Tcl_FindExecutable(
- char *argv0) /* The value of the application's argv[0]. */
+ CONST char *argv0) /* The value of the application's argv[0]. */
{
ProcessSerialNumber psn;
ProcessInfoRec info;
@@ -225,6 +71,9 @@ Tcl_FindExecutable(
int pathLength;
Handle pathName = NULL;
OSErr err;
+ Tcl_DString ds;
+
+ TclInitSubsystems(argv0);
GetCurrentProcess(&psn);
info.processInfoLength = sizeof(ProcessInfoRec);
@@ -238,52 +87,28 @@ Tcl_FindExecutable(
}
err = FSpPathFromLocation(&fileSpec, &pathLength, &pathName);
-
- tclExecutableName = (char *) ckalloc((unsigned) pathLength + 1);
HLock(pathName);
- strcpy(tclExecutableName, *pathName);
+ Tcl_ExternalToUtfDString(NULL, *pathName, pathLength, &ds);
HUnlock(pathName);
DisposeHandle(pathName);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclGetUserHome --
- *
- * This function takes the passed in user name and finds the
- * corresponding home directory specified in the password file.
- *
- * Results:
- * On a Macintosh we always return a NULL.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-char *
-TclGetUserHome(
- char *name, /* User name to use to find home directory. */
- Tcl_DString *bufferPtr) /* May be used to hold result. Must not hold
- * anything at the time of the call, and need
- * not even be initialized. */
-{
- return NULL;
+ tclExecutableName = (char *) ckalloc((unsigned)
+ (Tcl_DStringLength(&ds) + 1));
+ strcpy(tclExecutableName, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
}
/*
*----------------------------------------------------------------------
*
- * TclMatchFiles --
+ * TclpMatchFiles --
*
* 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 interp->result. Otherwise, TclDoGlob is called
+ * 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.
@@ -294,13 +119,14 @@ TclGetUserHome(
*---------------------------------------------------------------------- */
int
-TclMatchFiles(
+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. */
+ * point to a location in pattern and must
+ * not be static.*/
{
char *dirName, *patternEnd = tail;
char savedChar;
@@ -313,7 +139,7 @@ TclMatchFiles(
long dirID;
short itemIndex;
Str255 fileName;
-
+ Tcl_DString fileString;
/*
* Make sure that the directory part of the name really is a
@@ -368,11 +194,12 @@ TclMatchFiles(
* directories before calling TclDoGlob. Otherwise, just add
* the file to the result.
*/
-
- p2cstr(fileName);
- if (Tcl_StringMatch((char *) fileName, pattern)) {
+
+ Tcl_ExternalToUtfDString(NULL, (char *) fileName + 1, fileName[0],
+ &fileString);
+ if (Tcl_StringMatch(Tcl_DStringValue(&fileString), pattern)) {
Tcl_DStringSetLength(dirPtr, baseLength);
- Tcl_DStringAppend(dirPtr, (char *) fileName, -1);
+ Tcl_DStringAppend(dirPtr, Tcl_DStringValue(&fileString), -1);
if (tail == NULL) {
if ((dirPtr->length > 1) &&
(strchr(dirPtr->string+1, ':') == NULL)) {
@@ -384,10 +211,12 @@ TclMatchFiles(
Tcl_DStringAppend(dirPtr, ":", 1);
result = TclDoGlob(interp, separators, dirPtr, tail);
if (result != TCL_OK) {
+ Tcl_DStringFree(&fileString);
break;
}
}
}
+ Tcl_DStringFree(&fileString);
itemIndex++;
}
@@ -399,25 +228,23 @@ TclMatchFiles(
/*
*----------------------------------------------------------------------
*
- * TclpStat --
+ * TclpAccess --
*
- * This function replaces the library version of stat. The stat
- * function provided by most Mac compiliers is rather broken and
- * incomplete.
+ * This function replaces the library version of access().
*
* Results:
- * See stat documentation.
+ * See access documentation.
*
* Side effects:
- * See stat documentation.
+ * See access documentation.
*
*----------------------------------------------------------------------
*/
int
-TclpStat(
- CONST char *path,
- struct stat *buf)
+TclpAccess(
+ CONST char *path, /* Path of file to access (UTF-8). */
+ int mode) /* Permission setting. */
{
HFileInfo fpb;
HVolumeParam vpb;
@@ -425,8 +252,14 @@ TclpStat(
FSSpec fileSpec;
Boolean isDirectory;
long dirID;
-
- err = FSpLocationFromPath(strlen(path), path, &fileSpec);
+ 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;
@@ -435,7 +268,6 @@ TclpStat(
/*
* 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;
@@ -450,101 +282,189 @@ TclpStat(
if (err == noErr) {
vpb.ioVolIndex = 0;
err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
- if (err == noErr && buf != NULL) {
+ if (err == noErr) {
/*
- * Files are always readable by everyone.
+ * 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)
*/
-
- buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
- /*
- * Use the Volume Info & File Info to fill out stat buf.
+ /*
+ * Check to see if the volume is hardware or
+ * software locked. If so we arn't W_OK.
*/
- if (fpb.ioFlAttrib & 0x10) {
- buf->st_mode |= S_IFDIR;
- buf->st_nlink = 2;
- } else {
- buf->st_nlink = 1;
- if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
- buf->st_mode |= S_IFLNK;
- } else {
- buf->st_mode |= S_IFREG;
+ if (mode & W_OK) {
+ if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) {
+ errno = EROFS;
+ return -1;
+ }
+ if (fpb.ioFlAttrib & 0x01) {
+ errno = EACCES;
+ return -1;
}
}
- if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) {
- /*
- * Directories and applications are executable by everyone.
- */
-
- buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
- }
- if ((fpb.ioFlAttrib & 0x01) == 0){
- /*
- * If not locked, then everyone has write acces.
- */
-
- buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
- }
- buf->st_ino = fpb.ioDirID;
- buf->st_dev = fpb.ioVRefNum;
- buf->st_uid = -1;
- buf->st_gid = -1;
- buf->st_rdev = 0;
- buf->st_size = fpb.ioFlLgLen;
- buf->st_blksize = vpb.ioVAlBlkSiz;
- buf->st_blocks = (buf->st_size + buf->st_blksize - 1)
- / buf->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".
+ * Directories are always searchable and executable. But only
+ * files of type 'APPL' are executable.
*/
- if (initalized == false) {
- MachineLocation loc;
-
- ReadLocation(&loc);
- gmt_offset = loc.u.gmtDelta & 0x00ffffff;
- if (gmt_offset & 0x00800000) {
- gmt_offset = gmt_offset | 0xff000000;
- }
- initalized = true;
+ if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK)
+ && (fpb.ioFlFndrInfo.fdType != 'APPL')) {
+ return -1;
}
- buf->st_atime = buf->st_mtime = fpb.ioFlMdDat - gmt_offset;
- buf->st_ctime = fpb.ioFlCrDat - gmt_offset;
-
}
}
if (err != noErr) {
errno = TclMacOSErrorToPosixError(err);
+ return -1;
}
- return (err == noErr ? 0 : -1);
+ return 0;
}
/*
*----------------------------------------------------------------------
*
- * TclMacReadlink --
+ * TclpChdir --
*
- * This function replaces the library version of readlink.
+ * This function replaces the library version of chdir().
*
* Results:
- * See readlink documentation.
+ * See chdir() documentation.
*
* Side effects:
- * None.
+ * See chdir() documentation. Also the cache maintained used by
+ * TclGetCwd() is deallocated and set to NULL.
*
*----------------------------------------------------------------------
*/
int
-TclMacReadlink(
- char *path,
- char *buf,
- int size)
+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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetCwd --
+ *
+ * This function replaces the library version of getcwd().
+ *
+ * Results:
+ * The result is a pointer to a string specifying the current
+ * directory, or NULL if the current directory could not be
+ * determined. If NULL is returned, an error message is left in the
+ * interp's result. Storage for the result string is allocated in
+ * bufferPtr; the caller must call Tcl_DStringFree() when the result
+ * is no longer needed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TclpGetCwd(
+ Tcl_Interp *interp, /* If non-NULL, used for error reporting. */
+ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled
+ * with name of current directory. */
+{
+ FSSpec theSpec;
+ int length;
+ Handle pathHandle = NULL;
+
+ if (FSpGetDefaultDir(&theSpec) != noErr) {
+ if (interp != NULL) {
+ Tcl_SetResult(interp, "error getting working directory name",
+ TCL_STATIC);
+ }
+ return NULL;
+ }
+ if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) {
+ if (interp != NULL) {
+ Tcl_SetResult(interp, "error getting working directory name",
+ TCL_STATIC);
+ }
+ return NULL;
+ }
+ HLock(pathHandle);
+ Tcl_ExternalToUtfDString(NULL, *pathHandle, length, bufferPtr);
+ HUnlock(pathHandle);
+ DisposeHandle(pathHandle);
+
+ return Tcl_DStringValue(bufferPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpReadlink --
+ *
+ * This function replaces the library version of readlink().
+ *
+ * Results:
+ * The result is a pointer to a string specifying the contents
+ * of the symbolic link given by 'path', or NULL if the symbolic
+ * link could not be read. Storage for the result string is
+ * allocated in bufferPtr; the caller must call Tcl_DStringFree()
+ * when the result is no longer needed.
+ *
+ * Side effects:
+ * See readlink() documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+char *
+TclpReadlink(
+ CONST char *path, /* Path of file to readlink (UTF-8). */
+ Tcl_DString *linkPtr) /* Uninitialized or free DString filled
+ * with contents of link (UTF-8). */
{
HFileInfo fpb;
OSErr err;
@@ -552,45 +472,54 @@ TclMacReadlink(
Boolean isDirectory;
Boolean wasAlias;
long dirID;
- char fileName[256];
+ char fileName[257];
char *end;
Handle theString = NULL;
int pathSize;
+ Tcl_DString ds;
+ char *native;
+
+ native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
/*
* Remove ending colons if they exist.
*/
- while ((strlen(path) != 0) && (path[strlen(path) - 1] == ':')) {
- path[strlen(path) - 1] = NULL;
+
+ while ((strlen(native) != 0) && (path[strlen(native) - 1] == ':')) {
+ native[strlen(native) - 1] = NULL;
}
- if (strchr(path, ':') == NULL) {
- strcpy(fileName, path);
- path = NULL;
+ if (strchr(native, ':') == NULL) {
+ strcpy(fileName + 1, native);
+ native = NULL;
} else {
- end = strrchr(path, ':') + 1;
- strcpy(fileName, end);
+ end = strrchr(native, ':') + 1;
+ strcpy(fileName + 1, end);
*end = NULL;
}
- c2pstr(fileName);
+ fileName[0] = (char) strlen(fileName + 1);
/*
* Create the file spec for the directory of the file
* we want to look at.
*/
- if (path != NULL) {
- err = FSpLocationFromPath(strlen(path), path, &fileSpec);
+
+ if (native != NULL) {
+ err = FSpLocationFromPath(strlen(native), native, &fileSpec);
if (err != noErr) {
+ Tcl_DStringFree(&ds);
errno = EINVAL;
- return -1;
+ return NULL;
}
} else {
FSMakeFSSpecCompat(0, 0, NULL, &fileSpec);
}
+ Tcl_DStringFree(&ds);
/*
* Fill the fpb struct up with info about file or directory.
*/
+
FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
fpb.ioVRefNum = fileSpec.vRefNum;
fpb.ioDirID = dirID;
@@ -600,11 +529,11 @@ TclMacReadlink(
err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
if (err != noErr) {
errno = TclMacOSErrorToPosixError(err);
- return -1;
+ return NULL;
} else {
if (fpb.ioFlAttrib & 0x10) {
errno = EINVAL;
- return -1;
+ return NULL;
} else {
if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
/*
@@ -612,7 +541,7 @@ TclMacReadlink(
*/
} else {
errno = EINVAL;
- return -1;
+ return NULL;
}
}
}
@@ -621,50 +550,49 @@ TclMacReadlink(
* If we are here it's really a link - now find out
* where it points to.
*/
- err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName, &fileSpec);
+ err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName,
+ &fileSpec);
if (err == noErr) {
err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias);
}
if ((err == fnfErr) || wasAlias) {
err = FSpPathFromLocation(&fileSpec, &pathSize, &theString);
- if ((err != noErr) || (pathSize > size)) {
+ if (err != noErr) {
DisposeHandle(theString);
errno = ENAMETOOLONG;
- return -1;
+ return NULL;
}
} else {
errno = EINVAL;
- return -1;
+ return NULL;
}
-
- strncpy(buf, *theString, pathSize);
+
+ Tcl_ExternalToUtfDString(NULL, *theString, pathSize, linkPtr);
DisposeHandle(theString);
- return pathSize;
+ return Tcl_DStringValue(linkPtr);
}
/*
*----------------------------------------------------------------------
*
- * TclpAccess --
+ * TclpStat --
*
- * This function replaces the library version of access. The
- * access function provided by most Mac compiliers is rather
- * broken or incomplete.
+ * This function replaces the library version of stat().
*
* Results:
- * See access documentation.
+ * See stat() documentation.
*
* Side effects:
- * See access documentation.
+ * See stat() documentation.
*
*----------------------------------------------------------------------
*/
int
-TclpAccess(
- const char *path,
- int mode)
+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;
@@ -672,9 +600,12 @@ TclpAccess(
FSSpec fileSpec;
Boolean isDirectory;
long dirID;
- int full_mode = 0;
-
- err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec);
+ 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;
@@ -683,6 +614,7 @@ TclpAccess(
/*
* 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;
@@ -697,46 +629,106 @@ TclpAccess(
if (err == noErr) {
vpb.ioVolIndex = 0;
err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
- if (err == noErr) {
+ if (err == noErr && bufPtr != NULL) {
/*
- * 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)
+ * Files are always readable by everyone.
*/
+
+ bufPtr->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
- /*
- * Check to see if the volume is hardware or
- * software locked. If so we arn't W_OK.
+ /*
+ * Use the Volume Info & File Info to fill out stat buf.
*/
- if (mode & W_OK) {
- if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) {
- errno = EROFS;
- return -1;
- }
- if (fpb.ioFlAttrib & 0x01) {
- errno = EACCES;
- return -1;
+ 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;
+
/*
- * Directories are always searchable and executable. But only
- * files of type 'APPL' are executable.
+ * 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".
*/
- if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK)
- && (fpb.ioFlFndrInfo.fdType != 'APPL')) {
- return -1;
+
+ 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 -1;
}
- return 0;
+ return (err == noErr ? 0 : -1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitPid --
+ *
+ * Fakes a call to wait pid.
+ *
+ * Results:
+ * Always returns -1.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Pid
+Tcl_WaitPid(
+ Tcl_Pid pid,
+ int *statPtr,
+ int options)
+{
+ return (Tcl_Pid) -1;
}
/*
@@ -759,8 +751,8 @@ TclpAccess(
#undef fopen
FILE *
TclMacFOpenHack(
- const char *path,
- const char *mode)
+ CONST char *path,
+ CONST char *mode)
{
OSErr err;
FSSpec fileSpec;