diff options
Diffstat (limited to 'macosx/tclMacOSXFCmd.c')
-rw-r--r-- | macosx/tclMacOSXFCmd.c | 120 |
1 files changed, 79 insertions, 41 deletions
diff --git a/macosx/tclMacOSXFCmd.c b/macosx/tclMacOSXFCmd.c index aab5b44..17cccc2 100644 --- a/macosx/tclMacOSXFCmd.c +++ b/macosx/tclMacOSXFCmd.c @@ -5,11 +5,12 @@ * subcommands of the "file" command. * * Copyright (c) 2003 Tcl Core Team. + * Copyright (c) 2003-2005 Daniel A. Steffen <das@users.sourceforge.net> * * 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.5 2005/11/04 00:06:49 dkf Exp $ + * RCS: @(#) $Id: tclMacOSXFCmd.c,v 1.6 2005/11/27 02:33:49 das Exp $ */ #include "tclInt.h" @@ -19,6 +20,20 @@ #include <sys/paths.h> #endif +/* Darwin 8 copyfile API */ +#ifdef HAVE_COPYFILE +#ifdef HAVE_COPYFILE_H +#include <copyfile.h> +#else +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) +#endif +#endif + +#include <libkern/OSByteOrder.h> + /* * Constants for file attributes subcommand. Need to be kept in sync with * tclUnixFCmd.c ! @@ -46,21 +61,23 @@ static int Tcl_GetOSTypeFromObj(Tcl_Interp *interp, static Tcl_Obj * Tcl_NewOSTypeStringObj(CONST OSType newOSType); enum { - kFinfoIsInvisible = 0x4000, + kIsInvisible = 0x4000, }; +#define kFinfoIsInvisible (OSSwapHostToBigConstInt16(kIsInvisible)) + +typedef struct finderinfo { + u_int32_t type; + u_int32_t creator; + u_int16_t fdFlags; + u_int32_t location; + u_int16_t reserved; + u_int32_t extendedFileInfo[4]; +} __attribute__ ((__packed__)) finderinfo; + typedef struct fileinfobuf { u_int32_t info_length; - union { - struct { - u_int32_t type; - u_int32_t creator; - u_int16_t fdFlags; - u_int16_t location; - u_int32_t padding[4]; - } finder; - off_t rsrcForkSize; - } data __attribute__ ((packed)); + u_int32_t data[8]; } fileinfobuf; /* @@ -93,6 +110,8 @@ TclMacOSXGetFileAttribute( Tcl_StatBuf statBuf; struct attrlist alist; fileinfobuf finfo; + finderinfo *finder = (finderinfo*)(&finfo.data); + off_t *rsrcForkSize = (off_t*)(&finfo.data); CONST char *native; result = TclpObjStat(fileName, &statBuf); @@ -114,7 +133,7 @@ TclMacOSXGetFileAttribute( return TCL_ERROR; } - memset(&alist, 0, sizeof(struct attrlist)); + bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) { alist.fileattr = ATTR_FILE_RSRCLENGTH; @@ -132,17 +151,19 @@ TclMacOSXGetFileAttribute( switch (objIndex) { case MACOSX_CREATOR_ATTRIBUTE: - *attributePtrPtr = Tcl_NewOSTypeStringObj(finfo.data.finder.creator); + *attributePtrPtr = Tcl_NewOSTypeStringObj( + OSSwapBigToHostInt32(finder->creator)); break; case MACOSX_TYPE_ATTRIBUTE: - *attributePtrPtr = Tcl_NewOSTypeStringObj(finfo.data.finder.type); + *attributePtrPtr = Tcl_NewOSTypeStringObj( + OSSwapBigToHostInt32(finder->type)); break; case MACOSX_HIDDEN_ATTRIBUTE: *attributePtrPtr = Tcl_NewBooleanObj( - (finfo.data.finder.fdFlags & kFinfoIsInvisible) != 0); + (finder->fdFlags & kFinfoIsInvisible) != 0); break; case MACOSX_RSRCLENGTH_ATTRIBUTE: - *attributePtrPtr = Tcl_NewWideIntObj(finfo.data.rsrcForkSize); + *attributePtrPtr = Tcl_NewWideIntObj(*rsrcForkSize); break; } return TCL_OK; @@ -181,6 +202,8 @@ TclMacOSXSetFileAttribute( Tcl_StatBuf statBuf; struct attrlist alist; fileinfobuf finfo; + finderinfo *finder = (finderinfo*)(&finfo.data); + off_t *rsrcForkSize = (off_t*)(&finfo.data); CONST char *native; result = TclpObjStat(fileName, &statBuf); @@ -202,7 +225,7 @@ TclMacOSXSetFileAttribute( return TCL_ERROR; } - memset(&alist, 0, sizeof(struct attrlist)); + bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) { alist.fileattr = ATTR_FILE_RSRCLENGTH; @@ -219,33 +242,33 @@ TclMacOSXSetFileAttribute( } if (objIndex != MACOSX_RSRCLENGTH_ATTRIBUTE) { + OSType t; + int h; + switch (objIndex) { case MACOSX_CREATOR_ATTRIBUTE: - if (Tcl_GetOSTypeFromObj(interp, attributePtr, - &finfo.data.finder.creator) != TCL_OK) { + if (Tcl_GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) { return TCL_ERROR; } + finder->creator = OSSwapHostToBigInt32(t); break; case MACOSX_TYPE_ATTRIBUTE: - if (Tcl_GetOSTypeFromObj(interp, attributePtr, - &finfo.data.finder.type) != TCL_OK) { + if (Tcl_GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) { return TCL_ERROR; } + finder->type = OSSwapHostToBigInt32(t); break; - case MACOSX_HIDDEN_ATTRIBUTE: { - int hidden; - - if (Tcl_GetBooleanFromObj(interp,attributePtr,&hidden) != TCL_OK) { + case MACOSX_HIDDEN_ATTRIBUTE: + if (Tcl_GetBooleanFromObj(interp, attributePtr, &h) != TCL_OK) { return TCL_ERROR; } - if (hidden) { - finfo.data.finder.fdFlags |= kFinfoIsInvisible; + if (h) { + finder->fdFlags |= kFinfoIsInvisible; } else { - finfo.data.finder.fdFlags &= ~kFinfoIsInvisible; + finder->fdFlags &= ~kFinfoIsInvisible; } break; } - } result = setattrlist(native, &alist, &finfo.data, sizeof(finfo.data), 0); @@ -257,14 +280,14 @@ TclMacOSXSetFileAttribute( return TCL_ERROR; } } else { - off_t newRsrcForkSize; + Tcl_WideInt newRsrcForkSize; if (Tcl_GetWideIntFromObj(interp, attributePtr, &newRsrcForkSize) != TCL_OK) { return TCL_ERROR; } - if (newRsrcForkSize != finfo.data.rsrcForkSize) { + if (newRsrcForkSize != *rsrcForkSize) { Tcl_DString ds; /* @@ -331,11 +354,19 @@ TclMacOSXCopyFileAttributes( CONST Tcl_StatBuf *statBufPtr) /* Stat info for source file */ { -#ifdef HAVE_GETATTRLIST +#if defined(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; +#elif defined(HAVE_GETATTRLIST) struct attrlist alist; fileinfobuf finfo; + off_t *rsrcForkSize = (off_t*)(&finfo.data); - memset(&alist, 0, sizeof(struct attrlist)); + bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; alist.commonattr = ATTR_CMN_FNDRINFO; @@ -359,7 +390,7 @@ TclMacOSXCopyFileAttributes( return TCL_ERROR; } - if(finfo.data.rsrcForkSize > 0) { + if(*rsrcForkSize > 0) { int result; Tcl_DString ds_src, ds_dst; @@ -422,14 +453,18 @@ Tcl_GetOSTypeFromObj( string = Tcl_GetStringFromObj(objPtr, &length); Tcl_UtfToExternalDString(encoding, string, length, &ds); - if (Tcl_DStringLength(&ds) > sizeof(OSType)) { + if (Tcl_DStringLength(&ds) > 4) { Tcl_AppendResult(interp, "expected Macintosh OS type but got \"", string, "\": ", NULL); result = TCL_ERROR; } else { - memset(osTypePtr, 0, sizeof(OSType)); - memcpy(osTypePtr, Tcl_DStringValue(&ds), + char string[4] = {'\0','\0','\0','\0'}; + memcpy(string, Tcl_DStringValue(&ds), (size_t) Tcl_DStringLength(&ds)); + *osTypePtr = (OSType) string[0] << 24 | + (OSType) string[1] << 16 | + (OSType) string[2] << 8 | + (OSType) string[3]; } Tcl_DStringFree(&ds); Tcl_FreeEncoding(encoding); @@ -456,13 +491,16 @@ static Tcl_Obj * Tcl_NewOSTypeStringObj( CONST OSType newOSType) /* OSType used to initialize the new object. */ { - char string[sizeof(OSType)+1]; + char string[5]; Tcl_Obj *resultPtr; Tcl_DString ds; Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); - memcpy(string, &newOSType, sizeof(OSType)); - string[sizeof(OSType)] = '\0'; + string[0] = (char) (newOSType >> 24); + string[1] = (char) (newOSType >> 16); + string[2] = (char) (newOSType >> 8); + string[3] = (char) (newOSType); + string[4] = '\0'; Tcl_ExternalToUtfDString(encoding, string, -1, &ds); resultPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); |