/* * $Id: Info.xs,v 0.70 2005/08/09 15:47:00 dankogai Exp $ */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" static int not_here(char *s) { croak("%s not implemented on this architecture", s); return -1; } #include "common/util.c" #include "common/macdate.c" #include /* #define CATALOGINFONEEDED kFSCatInfoGettableInfo */ #define CATALOGINFONEEDED (kFSCatInfoNodeFlags|kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoFinderInfo) #define NUMMEMBERSINFO 7 static SV * xs_getfinfo(char *path){ FSRef Ref; FSSpec Spec; FSCatalogInfo Catalog; FInfo *finfo = (FInfo *)(&Catalog.finderInfo); SV* sva[NUMMEMBERSINFO]; OSErr err; if (err = FSPathMakeRef(path, &Ref, NULL)){ seterr(err); return &PL_sv_undef; } /* * to make it work with both directory and file, we * use FSGetCatalogInfo() instead of FSGetFInfo() */ if (err = FSGetCatalogInfo(&Ref, CATALOGINFONEEDED, &Catalog, NULL, NULL, NULL)) { seterr(err); return &PL_sv_undef; } sva[0] = sv_2mortal(newSVpv((char *)&Ref, sizeof(Ref))); sva[1] = sv_2mortal(newSViv(Catalog.nodeFlags)); if (kFSNodeIsDirectoryMask & Catalog.nodeFlags){ sva[2] = sv_2mortal(newSVpv("", 0)); sva[3] = sv_2mortal(newSVpv("", 0)); }else{ sva[2] = sv_2mortal(newSVpv(Catalog.finderInfo, 4)); sva[3] = sv_2mortal(newSVpv(Catalog.finderInfo+4, 4)); } sva[4] = sv_2mortal(newSVuv(finfo->fdFlags)); sva[5] = sv_2mortal(newSVnv(UDT2D(&Catalog.createDate))); sva[6] = sv_2mortal(newSVnv(UDT2D(&Catalog.contentModDate))); return newRV_noinc((SV *)av_make(NUMMEMBERSINFO, sva)); } static int xs_setfinfo( SV *svref, unsigned int nodeFlags, unsigned char *type, unsigned char *creator, unsigned int fdFlags, double ctime, double mtime, char *path ) { FSRef Ref, *rp; FSSpec Spec; FSCatalogInfo Catalog; FInfo *finfo = (FInfo *)(&Catalog.finderInfo); OSErr err; if (path != NULL && strlen(path) != 0){ if (err = FSPathMakeRef(path, &Ref, NULL)){ return seterr(err); }else{ rp = &Ref; } }else{ rp = (FSRef *)SvPV_nolen(svref); } /* prefetch destination catalog; may be used for file locks */ if (err = FSGetCatalogInfo(rp, kFSCatInfoSettableInfo|kFSCatInfoNodeFlags, &Catalog, NULL, NULL, NULL)) { return seterr(err); } /* * unlock the file first. * Note FSp(Rst|Set)FLock dies with segfault when applied to * directories! */ FSRef2FSSpec(rp, &Spec); if (!(Catalog.nodeFlags & kFSNodeIsDirectoryMask)){ if (err = FSpRstFLock(&Spec)){ return seterr(err); } } /* now set Catalog */ Catalog.nodeFlags = nodeFlags; finfo->fdType = char2OSType(type); finfo->fdCreator = char2OSType(creator); finfo->fdFlags = fdFlags; D2UDT(ctime, &Catalog.createDate); D2UDT(mtime, &Catalog.contentModDate); if (err = FSSetCatalogInfo(rp, CATALOGINFONEEDED, &Catalog)){ return seterr(err); } /* Lock the File if neccesary */ if (!(Catalog.nodeFlags & kFSNodeIsDirectoryMask)){ if (Catalog.nodeFlags & kFSNodeLockedMask){ err = FSpSetFLock(&Spec); } } return seterr(err); } MODULE = MacOSX::File::Info PACKAGE = MacOSX::File::Info PROTOTYPES: ENABLE SV * xs_getfinfo(path) char *path; CODE: RETVAL = xs_getfinfo(path); OUTPUT: RETVAL int xs_setfinfo(svref, nodeFlags, type, creator, fdFlags, ctime, mtime, path) SV *svref; unsigned int nodeFlags; unsigned char *type; unsigned char *creator; unsigned int fdFlags; double ctime; double mtime; char *path; CODE: RETVAL = xs_setfinfo(svref, nodeFlags, type, creator, fdFlags, ctime, mtime, path); OUTPUT: RETVAL