diff options
Diffstat (limited to 'macosx/tclMacOSXFCmd.c')
| -rw-r--r-- | macosx/tclMacOSXFCmd.c | 291 | 
1 files changed, 158 insertions, 133 deletions
| diff --git a/macosx/tclMacOSXFCmd.c b/macosx/tclMacOSXFCmd.c index d230f4a..8ecfd0b 100644 --- a/macosx/tclMacOSXFCmd.c +++ b/macosx/tclMacOSXFCmd.c @@ -8,8 +8,6 @@   *   * See the file "license.terms" for information on usage and redistribution of   * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclMacOSXFCmd.c,v 1.13 2008/04/27 22:21:33 dkf Exp $   */  #include "tclInt.h" @@ -24,26 +22,37 @@  #ifdef HAVE_COPYFILE  #ifdef HAVE_COPYFILE_H  #include <copyfile.h> -#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +#if defined(HAVE_WEAK_IMPORT) && (MAC_OS_X_VERSION_MIN_REQUIRED < 1040)  /* Support for weakly importing copyfile. */  #define WEAK_IMPORT_COPYFILE -extern int copyfile(const char *from, const char *to, copyfile_state_t state, -		    copyfile_flags_t flags) WEAK_IMPORT_ATTRIBUTE; +extern int		copyfile(const char *from, const char *to, +			    copyfile_state_t state, copyfile_flags_t flags) +			    WEAK_IMPORT_ATTRIBUTE;  #endif /* HAVE_WEAK_IMPORT */  #else /* HAVE_COPYFILE_H */ -int copyfile(const char *from, const char *to, void *state, uint32_t flags); -#define COPYFILE_ACL            (1<<0) -#define COPYFILE_XATTR          (1<<2) -#define COPYFILE_NOFOLLOW_SRC   (1<<18) -#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +int			copyfile(const char *from, const char *to, +			    void *state, uint32_t flags); +#define COPYFILE_ACL		(1<<0) +#define COPYFILE_XATTR		(1<<2) +#define COPYFILE_NOFOLLOW_SRC	(1<<18) +#if defined(HAVE_WEAK_IMPORT) && (MAC_OS_X_VERSION_MIN_REQUIRED < 1040)  /* Support for weakly importing copyfile. */  #define WEAK_IMPORT_COPYFILE -extern int copyfile(const char *from, const char *to, void *state, -                    uint32_t flags) WEAK_IMPORT_ATTRIBUTE; +extern int		copyfile(const char *from, const char *to, +			    void *state, uint32_t flags) +			    WEAK_IMPORT_ATTRIBUTE;  #endif /* HAVE_WEAK_IMPORT */  #endif /* HAVE_COPYFILE_H */  #endif /* HAVE_COPYFILE */ +#ifdef WEAK_IMPORT_COPYFILE +#define MayUseCopyFile()	(copyfile != NULL) +#elif defined(HAVE_COPYFILE) +#define MayUseCopyFile()	(1) +#else +#define MayUseCopyFile()	(0) +#endif +  #include <libkern/OSByteOrder.h>  /* @@ -74,7 +83,7 @@ static Tcl_Obj *	NewOSTypeObj(const OSType newOSType);  static int		SetOSTypeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);  static void		UpdateStringOfOSType(Tcl_Obj *objPtr); -static Tcl_ObjType tclOSTypeType = { +static const Tcl_ObjType tclOSTypeType = {      "osType",				/* name */      NULL,				/* freeIntRepProc */      NULL,				/* dupIntRepProc */ @@ -83,10 +92,10 @@ static Tcl_ObjType tclOSTypeType = {  };  enum { -   kIsInvisible = 0x4000, +    kIsInvisible = 0x4000,  }; -#define kFinfoIsInvisible (OSSwapHostToBigConstInt16(kIsInvisible)) +#define kFinfoIsInvisible	(OSSwapHostToBigConstInt16(kIsInvisible))  typedef	struct finderinfo {      u_int32_t type; @@ -132,15 +141,16 @@ TclMacOSXGetFileAttribute(      Tcl_StatBuf statBuf;      struct attrlist alist;      fileinfobuf finfo; -    finderinfo *finder = (finderinfo*)(&finfo.data); -    off_t *rsrcForkSize = (off_t*)(&finfo.data); +    finderinfo *finder = (finderinfo *) &finfo.data; +    off_t *rsrcForkSize = (off_t *) &finfo.data;      const char *native;      result = TclpObjStat(fileName, &statBuf);      if (result != 0) { -	Tcl_AppendResult(interp, "could not read \"", -		TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"could not read \"%s\": %s", +		TclGetString(fileName), Tcl_PosixError(interp)));  	return TCL_ERROR;      } @@ -150,8 +160,8 @@ TclMacOSXGetFileAttribute(  	 */  	errno = EISDIR; -	Tcl_AppendResult(interp, "invalid attribute: ", -		Tcl_PosixError(interp), NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"invalid attribute: %s", Tcl_PosixError(interp)));  	return TCL_ERROR;      } @@ -166,8 +176,9 @@ TclMacOSXGetFileAttribute(      result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);      if (result != 0) { -	Tcl_AppendResult(interp, "could not read attributes of \"", -		TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"could not read attributes of \"%s\": %s", +		TclGetString(fileName), Tcl_PosixError(interp)));  	return TCL_ERROR;      } @@ -190,9 +201,11 @@ TclMacOSXGetFileAttribute(      }      return TCL_OK;  #else -    Tcl_AppendResult(interp, "Mac OS X file attributes not supported", NULL); +    Tcl_SetObjResult(interp, Tcl_NewStringObj( +	    "Mac OS X file attributes not supported", -1)); +    Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);      return TCL_ERROR; -#endif +#endif /* HAVE_GETATTRLIST */  }  /* @@ -224,15 +237,16 @@ TclMacOSXSetFileAttribute(      Tcl_StatBuf statBuf;      struct attrlist alist;      fileinfobuf finfo; -    finderinfo *finder = (finderinfo*)(&finfo.data); -    off_t *rsrcForkSize = (off_t*)(&finfo.data); +    finderinfo *finder = (finderinfo *) &finfo.data; +    off_t *rsrcForkSize = (off_t *) &finfo.data;      const char *native;      result = TclpObjStat(fileName, &statBuf);      if (result != 0) { -	Tcl_AppendResult(interp, "could not read \"", -		TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"could not read \"%s\": %s", +		TclGetString(fileName), Tcl_PosixError(interp)));  	return TCL_ERROR;      } @@ -242,8 +256,8 @@ TclMacOSXSetFileAttribute(  	 */  	errno = EISDIR; -	Tcl_AppendResult(interp, "invalid attribute: ", -		Tcl_PosixError(interp), NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"invalid attribute: %s", Tcl_PosixError(interp)));  	return TCL_ERROR;      } @@ -258,8 +272,9 @@ TclMacOSXSetFileAttribute(      result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);      if (result != 0) { -	Tcl_AppendResult(interp, "could not read attributes of \"", -		TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"could not read attributes of \"%s\": %s", +		TclGetString(fileName), Tcl_PosixError(interp)));  	return TCL_ERROR;      } @@ -296,9 +311,9 @@ TclMacOSXSetFileAttribute(  		&finfo.data, sizeof(finfo.data), 0);  	if (result != 0) { -	    Tcl_AppendResult(interp, "could not set attributes of \"", -		    TclGetString(fileName), "\": ", -		    Tcl_PosixError(interp), NULL); +	    Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		    "could not set attributes of \"%s\": %s", +		    TclGetString(fileName), Tcl_PosixError(interp)));  	    return TCL_ERROR;  	}      } else { @@ -317,9 +332,10 @@ TclMacOSXSetFileAttribute(  	     * supported.  	     */ -	    if(newRsrcForkSize != 0) { -		Tcl_AppendResult(interp, -			"setting nonzero rsrclength not supported", NULL); +	    if (newRsrcForkSize != 0) { +		Tcl_SetObjResult(interp, Tcl_NewStringObj( +			"setting nonzero rsrclength not supported", -1)); +		Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);  		return TCL_ERROR;  	    } @@ -334,11 +350,13 @@ TclMacOSXSetFileAttribute(  	    result = truncate(Tcl_DStringValue(&ds), (off_t)0);  	    if (result != 0) {  		/* -		 * truncate() on a valid resource fork path may fail with -		 * a permission error in some OS releases, try truncating -		 * with open() instead: +		 * truncate() on a valid resource fork path may fail with a +		 * permission error in some OS releases, try truncating with +		 * open() instead:  		 */ +  		int fd = open(Tcl_DStringValue(&ds), O_WRONLY | O_TRUNC); +  		if (fd > 0) {  		    result = close(fd);  		} @@ -347,17 +365,18 @@ TclMacOSXSetFileAttribute(  	    Tcl_DStringFree(&ds);  	    if (result != 0) { -		Tcl_AppendResult(interp, -			"could not truncate resource fork of \"", -			TclGetString(fileName), "\": ", -			Tcl_PosixError(interp), NULL); +		Tcl_SetObjResult(interp, Tcl_ObjPrintf( +			"could not truncate resource fork of \"%s\": %s", +			TclGetString(fileName), Tcl_PosixError(interp)));  		return TCL_ERROR;  	    }  	}      }      return TCL_OK;  #else -    Tcl_AppendResult(interp, "Mac OS X file attributes not supported", NULL); +    Tcl_SetObjResult(interp, Tcl_NewStringObj( +	    "Mac OS X file attributes not supported", -1)); +    Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);      return TCL_ERROR;  #endif  } @@ -387,84 +406,79 @@ TclMacOSXCopyFileAttributes(      const Tcl_StatBuf *statBufPtr)  				/* Stat info for source file */  { -#ifdef WEAK_IMPORT_COPYFILE -    if (copyfile != NULL) { -#endif +    if (MayUseCopyFile()) {  #ifdef HAVE_COPYFILE -    if (copyfile(src, dst, NULL, COPYFILE_XATTR | -	    (S_ISLNK(statBufPtr->st_mode) ? COPYFILE_NOFOLLOW_SRC : -		                            COPYFILE_ACL)) < 0) { -	return TCL_ERROR; -    } -    return TCL_OK; +	if (0 == copyfile(src, dst, NULL, (S_ISLNK(statBufPtr->st_mode) +		? COPYFILE_XATTR | COPYFILE_NOFOLLOW_SRC +		: COPYFILE_XATTR | COPYFILE_ACL))) { +	    return TCL_OK; +	}  #endif /* HAVE_COPYFILE */ -#ifdef WEAK_IMPORT_COPYFILE      } else { -#endif -#if !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) -#ifdef HAVE_GETATTRLIST -    struct attrlist alist; -    fileinfobuf finfo; -    off_t *rsrcForkSize = (off_t*)(&finfo.data); +#if (!defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE)) && defined(HAVE_GETATTRLIST) +	struct attrlist alist; +	fileinfobuf finfo; +	off_t *rsrcForkSize = (off_t *) &finfo.data; +	Tcl_DString srcBuf, dstBuf; +	int result; + +	bzero(&alist, sizeof(struct attrlist)); +	alist.bitmapcount = ATTR_BIT_MAP_COUNT; +	alist.commonattr = ATTR_CMN_FNDRINFO; -    bzero(&alist, sizeof(struct attrlist)); -    alist.bitmapcount = ATTR_BIT_MAP_COUNT; -    alist.commonattr = ATTR_CMN_FNDRINFO; +	if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { +	    return TCL_ERROR; +	} +	if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) { +	    return TCL_ERROR; +	} -    if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { -	return TCL_ERROR; -    } +	/* +	 * If we're a directory, we're done as they never have resource forks. +	 */ -    if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) { -	return TCL_ERROR; -    } +	if (S_ISDIR(statBufPtr->st_mode)) { +	    return TCL_OK; +	} -    if (!S_ISDIR(statBufPtr->st_mode)) {  	/* -	 * Only copy non-empty resource fork. +	 * We only copy a non-empty resource fork, so determine if that's the +	 * case first.  	 */  	alist.commonattr = 0;  	alist.fileattr = ATTR_FILE_RSRCLENGTH; -  	if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {  	    return TCL_ERROR; +	} else if (*rsrcForkSize == 0) { +	    return TCL_OK;  	} -	if(*rsrcForkSize > 0) { -	    int result; -	    Tcl_DString ds_src, ds_dst; - -	    /* -	     * Construct paths to resource forks. -	     */ - -	    Tcl_DStringInit(&ds_src); -	    Tcl_DStringAppend(&ds_src, src, -1); -	    Tcl_DStringAppend(&ds_src, _PATH_RSRCFORKSPEC, -1); -	    Tcl_DStringInit(&ds_dst); -	    Tcl_DStringAppend(&ds_dst, dst, -1); -	    Tcl_DStringAppend(&ds_dst, _PATH_RSRCFORKSPEC, -1); +	/* +	 * Construct paths to resource forks. +	 */ -	    result = TclUnixCopyFile(Tcl_DStringValue(&ds_src), -		    Tcl_DStringValue(&ds_dst), statBufPtr, 1); +	Tcl_DStringInit(&srcBuf); +	Tcl_DStringAppend(&srcBuf, src, -1); +	Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, -1); +	Tcl_DStringInit(&dstBuf); +	Tcl_DStringAppend(&dstBuf, dst, -1); +	Tcl_DStringAppend(&dstBuf, _PATH_RSRCFORKSPEC, -1); -	    Tcl_DStringFree(&ds_src); -	    Tcl_DStringFree(&ds_dst); +	/* +	 * Do the copy. +	 */ -	    if (result != 0) { -		return TCL_ERROR; -	    } +	result = TclUnixCopyFile(Tcl_DStringValue(&srcBuf), +		Tcl_DStringValue(&dstBuf), statBufPtr, 1); +	Tcl_DStringFree(&srcBuf); +	Tcl_DStringFree(&dstBuf); +	if (result == 0) { +	    return TCL_OK;  	} +#endif /* (!HAVE_COPYFILE || WEAK_IMPORT_COPYFILE) && HAVE_GETATTRLIST */      } -    return TCL_OK; -#else      return TCL_ERROR; -#endif /* HAVE_GETATTRLIST */ -#endif /* !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) */ -#ifdef WEAK_IMPORT_COPYFILE -    } -#endif  }  /* @@ -472,13 +486,13 @@ TclMacOSXCopyFileAttributes(   *   * TclMacOSXMatchType --   * - *	This routine is used by the globbing code to check if a file - *	matches a given mac type and/or creator code. + *	This routine is used by the globbing code to check if a file matches a + *	given mac type and/or creator code.   *   * Results: - *	The return value is 1, 0 or -1 indicating whether the file - *	matches the given criteria, does not match them, or an error - *	occurred (in wich case an error is left in interp). + *	The return value is 1, 0 or -1 indicating whether the file matches the + *	given criteria, does not match them, or an error occurred (in wich + *	case an error is left in interp).   *   * Side effects:   *	None. @@ -488,16 +502,16 @@ TclMacOSXCopyFileAttributes(  int  TclMacOSXMatchType( -    Tcl_Interp *interp,       /* Interpreter to receive errors. */ -    const char *pathName,     /* Native path to check. */ -    const char *fileName,     /* Native filename to check. */ -    Tcl_StatBuf *statBufPtr,  /* Stat info for file to check */ -    Tcl_GlobTypeData *types)  /* Type description to match against. */ +    Tcl_Interp *interp,		/* Interpreter to receive errors. */ +    const char *pathName,	/* Native path to check. */ +    const char *fileName,	/* Native filename to check. */ +    Tcl_StatBuf *statBufPtr,	/* Stat info for file to check */ +    Tcl_GlobTypeData *types)	/* Type description to match against. */  {  #ifdef HAVE_GETATTRLIST      struct attrlist alist;      fileinfobuf finfo; -    finderinfo *finder = (finderinfo*)(&finfo.data); +    finderinfo *finder = (finderinfo *) &finfo.data;      OSType osType;      bzero(&alist, sizeof(struct attrlist)); @@ -510,8 +524,12 @@ TclMacOSXMatchType(  	    !((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) {  	return 0;      } -    if (S_ISDIR(statBufPtr->st_mode) && (types->macType || types->macCreator)) { -	/* Directories don't support types or creators */ +    if (S_ISDIR(statBufPtr->st_mode) +	    && (types->macType || types->macCreator)) { +	/* +	 * Directories don't support types or creators. +	 */ +  	return 0;      }      if (types->macType) { @@ -560,8 +578,8 @@ GetOSTypeFromObj(      int result = TCL_OK;      if (objPtr->typePtr != &tclOSTypeType) { -	result = tclOSTypeType.setFromAnyProc(interp, objPtr); -    }; +	result = SetOSTypeFromAny(interp, objPtr); +    }      *osTypePtr = (OSType) objPtr->internalRep.longValue;      return result;  } @@ -584,12 +602,13 @@ GetOSTypeFromObj(  static Tcl_Obj *  NewOSTypeObj( -    const OSType osType)    /* OSType used to initialize the new object. */ +    const OSType osType)	/* OSType used to initialize the new +				 * object. */  {      Tcl_Obj *objPtr;      TclNewObj(objPtr); -    Tcl_InvalidateStringRep(objPtr); +    TclInvalidateStringRep(objPtr);      objPtr->internalRep.longValue = (long) osType;      objPtr->typePtr = &tclOSTypeType;      return objPtr; @@ -616,7 +635,7 @@ SetOSTypeFromAny(      Tcl_Interp *interp,		/* Tcl interpreter */      Tcl_Obj *objPtr)		/* Pointer to the object to convert */  { -    char *string; +    const char *string;      int length, result = TCL_OK;      Tcl_DString ds;      Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); @@ -625,18 +644,21 @@ SetOSTypeFromAny(      Tcl_UtfToExternalDString(encoding, string, length, &ds);      if (Tcl_DStringLength(&ds) > 4) { -	Tcl_AppendResult(interp, "expected Macintosh OS type but got \"", -		string, "\": ", NULL); +	if (interp) { +	    Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		    "expected Macintosh OS type but got \"%s\": ", string)); +	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "MAC_OSTYPE", NULL); +	}  	result = TCL_ERROR;      } else {  	OSType osType; -	char string[4] = {'\0','\0','\0','\0'}; -	memcpy(string, Tcl_DStringValue(&ds), -		(size_t) Tcl_DStringLength(&ds)); -	osType = (OSType) string[0] << 24 | -		 (OSType) string[1] << 16 | -		 (OSType) string[2] <<  8 | -		 (OSType) string[3]; +	char bytes[4] = {'\0','\0','\0','\0'}; + +	memcpy(bytes, Tcl_DStringValue(&ds), (size_t)Tcl_DStringLength(&ds)); +	osType = (OSType) bytes[0] << 24 | +		 (OSType) bytes[1] << 16 | +		 (OSType) bytes[2] <<  8 | +		 (OSType) bytes[3];  	TclFreeIntRep(objPtr);  	objPtr->internalRep.longValue = (long) osType;  	objPtr->typePtr = &tclOSTypeType; @@ -667,12 +689,14 @@ SetOSTypeFromAny(  static void  UpdateStringOfOSType( -    register Tcl_Obj *objPtr)	/* OSType object whose string rep to update. */ +    register Tcl_Obj *objPtr)	/* OSType object whose string rep to +				 * update. */  {      char string[5];      OSType osType = (OSType) objPtr->internalRep.longValue;      Tcl_DString ds;      Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); +    unsigned len;      string[0] = (char) (osType >> 24);      string[1] = (char) (osType >> 16); @@ -680,8 +704,9 @@ UpdateStringOfOSType(      string[3] = (char) (osType);      string[4] = '\0';      Tcl_ExternalToUtfDString(encoding, string, -1, &ds); -    objPtr->bytes = ckalloc((unsigned) Tcl_DStringLength(&ds) + 1); -    strcpy(objPtr->bytes, Tcl_DStringValue(&ds)); +    len = (unsigned) Tcl_DStringLength(&ds) + 1; +    objPtr->bytes = ckalloc(len); +    memcpy(objPtr->bytes, Tcl_DStringValue(&ds), len);      objPtr->length = Tcl_DStringLength(&ds);      Tcl_DStringFree(&ds);      Tcl_FreeEncoding(encoding); | 
