summaryrefslogtreecommitdiffstats
path: root/mac
diff options
context:
space:
mode:
Diffstat (limited to 'mac')
-rw-r--r--mac/tclMacFile.c138
1 files changed, 120 insertions, 18 deletions
diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c
index b3175d9..b6ae7a2 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.8 1999/08/10 04:21:35 jingham Exp $
+ * RCS: @(#) $Id: tclMacFile.c,v 1.9 1999/12/12 22:46:45 hobbs Exp $
*/
/*
@@ -102,7 +102,7 @@ TclpFindExecutable(
/*
*----------------------------------------------------------------------
*
- * TclpMatchFiles --
+ * TclpMatchFilesTypes --
*
* This routine is used by the globbing code to search a
* directory for all files which match a given pattern.
@@ -120,18 +120,20 @@ TclpFindExecutable(
*---------------------------------------------------------------------- */
int
-TclpMatchFiles(
+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
+ 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. */
{
- char *patternEnd = tail;
+ char *fname, *patternEnd = tail;
char savedChar;
- int result = TCL_OK;
+ int fnameLen, result = TCL_OK;
int baseLength = Tcl_DStringLength(dirPtr);
CInfoPBRec pb;
OSErr err;
@@ -141,17 +143,21 @@ TclpMatchFiles(
short itemIndex;
Str255 fileName;
Tcl_DString fileString;
+ Tcl_Obj *resultPtr;
+ OSType okType = 0;
+ OSType okCreator = 0;
/*
* Make sure that the directory part of the name really is a
* directory.
*/
- Tcl_UtfToExternalDString(NULL, dirPtr->string, dirPtr->length, &fileString);
-
+ Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(dirPtr),
+ Tcl_DStringLength(dirPtr), &fileString);
+
FSpLocationFromPath(fileString.length, fileString.string, &dirSpec);
Tcl_DStringFree(&fileString);
-
+
err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory);
if ((err != noErr) || !isDirectory) {
return TCL_OK;
@@ -165,7 +171,7 @@ TclpMatchFiles(
pb.hFileInfo.ioDirID = dirID;
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
@@ -184,6 +190,16 @@ TclpMatchFiles(
savedChar = *patternEnd;
*patternEnd = '\0';
+ resultPtr = Tcl_GetObjResult(interp);
+ if (types != NULL) {
+ if (types->macType != NULL) {
+ Tcl_GetOSTypeFromObj(NULL, types->macType, &okType);
+ }
+ if (types->macCreator != NULL) {
+ Tcl_GetOSTypeFromObj(NULL, types->macCreator, &okCreator);
+ }
+ }
+
while (1) {
pb.hFileInfo.ioFDirIndex = itemIndex;
pb.hFileInfo.ioDirID = dirID;
@@ -204,16 +220,84 @@ TclpMatchFiles(
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) {
- if ((dirPtr->length > 1) &&
- (strchr(dirPtr->string+1, ':') == NULL)) {
- Tcl_AppendElement(interp, dirPtr->string+1);
- } else {
- Tcl_AppendElement(interp, dirPtr->string);
+ 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;
+ }
+ }
+ 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) {
+ /*
+ * 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))
+#ifdef S_ISLNK
+ || ((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))
+#endif
+ ) {
+ typeOk = 1;
+ }
+ } else {
+ /* Posix error occurred */
+ }
+ }
+ 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));
+ }
}
} else if ((pb.hFileInfo.ioFlAttrib & ioDirMask) != 0) {
Tcl_DStringAppend(dirPtr, ":", 1);
- result = TclDoGlob(interp, separators, dirPtr, tail);
+ result = TclDoGlob(interp, separators, dirPtr, tail, types);
if (result != TCL_OK) {
Tcl_DStringFree(&fileString);
break;
@@ -221,7 +305,6 @@ TclpMatchFiles(
}
}
Tcl_DStringFree(&fileString);
-
itemIndex++;
}
*patternEnd = savedChar;
@@ -229,6 +312,25 @@ TclpMatchFiles(
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);
+}
+
/*
*----------------------------------------------------------------------
*
@@ -918,4 +1020,4 @@ TclMacChmod(
}
return 0;
-} \ No newline at end of file
+}