Skip to content

Instantly share code, notes, and snippets.

@atr000
Created February 5, 2010 01:58
Show Gist options
  • Save atr000/295406 to your computer and use it in GitHub Desktop.
Save atr000/295406 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#import <CoreServices/CoreServices.h>
#import <unistd.h>
#import <sys/stat.h>
#import <time.h>
#define manager [NSFileManager defaultManager]
char *returnString=NULL;
char *returnSize(long theSize)
{
float mySize=theSize;
if (returnString != NULL) {
free(returnString);
returnString=NULL;
}
returnString=malloc(10);
//KB
mySize=(mySize / (float)1024);
if (mySize > 1024) {
//MB
mySize=(mySize / (float)1024);
if (mySize > 1024) {
//GB
mySize=(mySize / (float)1024);
sprintf(returnString, "%.2f GB", mySize);
} else {
sprintf(returnString, "%.2f MB", mySize);
}
} else {
sprintf(returnString, "%.2f KB", mySize);
}
if (mySize < 1) {
mySize=theSize;
sprintf(returnString, "%.2f Bytes", mySize);
}
return returnString;
}
void xstat(NSString *theFile, BOOL hfs)
{
NSDictionary *attrs;
NSNumber *fileSize, *identifier, *devIdentifier, *permissions, *hfsExtension, *creator, *type, *links, *ownerID, *groupID;
NSString *owner, *group, *fileType, *fileName, *permString, *filePrint;
NSDate *createDate, *modifyDate;
char access[10];
char linkName[256];
char theFileName[PATH_MAX];
long int tfirst,tsecond,tthird,cfirst,csecond,cthird;
struct stat stats;
FSRef theRef;
FSCatalogInfo catInfo;
FSSpec theSpec;
Boolean isDir, isAlias, dirFlag=0;
FInfo *finderInfo=NULL;
long physDataSize, realDataSize, physRsrcSize, realRsrcSize;
OSErr theErr=0;
OSStatus theStatus=0;
int i;
fileName=theFile;
if ([fileName characterAtIndex:0] == '~') {
fileName=[fileName stringByExpandingTildeInPath];
}
strcpy(theFileName,[fileName fileSystemRepresentation]);
i=lstat(theFileName,&stats);
if (i == -1) {
printf("%s: No such file or directory\n",theFileName);
return;
}
attrs=[manager fileAttributesAtPath:fileName traverseLink:NO];
fileSize=[attrs objectForKey:NSFileSize];
owner=[attrs objectForKey:NSFileOwnerAccountName];
ownerID=[attrs objectForKey:NSFileOwnerAccountID];
group=[attrs objectForKey:NSFileGroupOwnerAccountName];
groupID=[attrs objectForKey:NSFileGroupOwnerAccountID];
links=[attrs objectForKey:NSFileReferenceCount];
identifier=[attrs objectForKey:NSFileSystemFileNumber];
devIdentifier=[attrs objectForKey:NSFileSystemNumber];
permissions=[attrs objectForKey:NSFilePosixPermissions];
permString=[NSString stringWithFormat:@"%04o",[permissions intValue]];
fileType=[attrs objectForKey:NSFileType];
hfsExtension=[attrs objectForKey:NSFileExtensionHidden];
creator=[attrs objectForKey:NSFileHFSCreatorCode];
type=[attrs objectForKey:NSFileHFSTypeCode];
createDate=[attrs objectForKey:NSFileCreationDate];
modifyDate=[attrs objectForKey:NSFileModificationDate];
access[10]='\0';
access[9] = (stats.st_mode & S_IXOTH) ? ((stats.st_mode & S_ISVTX) ? 't' : 'x') : ((stats.st_mode & S_ISVTX) ? 'T' : '-');
access[8] = (stats.st_mode & S_IWOTH) ? 'w' : '-';
access[7] = (stats.st_mode & S_IROTH) ? 'r' : '-';
access[6] = (stats.st_mode & S_IXGRP) ? ((stats.st_mode & S_ISGID) ? 's' : 'x') : ((stats.st_mode & S_ISGID) ? 'S' : '-');
access[5] = (stats.st_mode & S_IWGRP) ? 'w' : '-';
access[4] = (stats.st_mode & S_IRGRP) ? 'r' : '-';
access[3] = (stats.st_mode & S_IXUSR) ? ((stats.st_mode & S_ISUID) ? 's' : 'x') : ((stats.st_mode & S_ISUID) ? 'S' : '-');
access[2] = (stats.st_mode & S_IWUSR) ? 'w' : '-';
access[1] = (stats.st_mode & S_IRUSR) ? 'r' : '-';
switch (stats.st_mode & S_IFMT) {
case S_IFDIR:
access[0] = 'd';
filePrint=@"Directory";
break;
case S_IFCHR:
access[0] = 'c';
filePrint=@"Character Device";
break;
case S_IFBLK:
access[0] = 'b';
filePrint=@"Block Device";
break;
case S_IFREG:
access[0] = '-';
filePrint=@"Regular File";
break;
case S_IFLNK:
access[0] = 'l';
filePrint=@"Symbolic Link";
break;
case S_IFSOCK:
access[0] = 's';
filePrint=@"Socket";
break;
case S_IFIFO:
access[0] = 'p';
filePrint=@"FIFO File";
break;
default:
access[0] = '?';
filePrint=@"Unknown Type";
break;
}
theStatus=FSPathMakeRef(theFileName,&theRef,NULL);
if (theStatus != 0) {
goto UnixEnd;
}
theErr=FSGetCatalogInfo(&theRef, kFSCatInfoDataSizes | kFSCatInfoRsrcSizes | kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catInfo, NULL, &theSpec, NULL);
if (theErr != 0) {
goto UnixEnd;
}
isDir=((catInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0);
physDataSize=(catInfo.dataPhysicalSize);
realDataSize=(catInfo.dataLogicalSize);
physRsrcSize=(catInfo.rsrcPhysicalSize);
realRsrcSize=(catInfo.rsrcLogicalSize);
finderInfo=(FInfo *)catInfo.finderInfo;
FSIsAliasFile(&theRef,&isAlias,&dirFlag);
if ((stats.st_mode & S_IFMT) == S_IFLNK) {
int i;
if ((i=readlink(theFileName,linkName, 256)) == -1) {
printf("Error reading file\n");
return;
}
linkName[(i >= 256) ? 255 : i]='\0';
printf("File: \"%s\" -> \"%s\"\n",theFileName,linkName);
} else if (isAlias) {
short refNum=0;
AliasHandle theAlias=NULL;
ResType aliasRes='alis';
Boolean wasChanged;
FSRef targetRef;
char returnedPath[PATH_MAX + 1];
OSErr aliasErr=0;
OSStatus aliasStatus=0;
filePrint=@"Alias";
refNum=FSpOpenResFile(&theSpec, fsRdWrShPerm);
if (refNum <= 0) { goto SafeEnd; }
theAlias = (AliasHandle)Get1Resource(aliasRes,0);
if (theAlias == NULL) { goto SafeEnd; }
aliasErr=FSFollowFinderAlias(&theRef, theAlias, false, &targetRef, &wasChanged);
if (aliasErr != 0) {
printf("File: \"%s\" -> (Error reading alias: %d)\n",theFileName,aliasErr);
CloseResFile(refNum);
goto SafeEnd;
}
aliasStatus=FSRefMakePath(&targetRef, (UInt8 *)&returnedPath, PATH_MAX);
if (aliasStatus != 0) {
printf("File: \"%s\" -> (Could not locate original)\n",theFileName);
CloseResFile(refNum);
goto SafeEnd;
}
printf("File: \"%s\" -> \"%s\"\n",theFileName, returnedPath);
CloseResFile(refNum);
} else {
printf("File: \"%s\"\n",theFileName);
}
SafeEnd:
printf("IO Block : %d Blocks: %u ", (int)stats.st_blksize, (unsigned int)stats.st_blocks);
printf("Device: %d,%d Inode: %d Links: %d\n", major([devIdentifier intValue]), minor([devIdentifier intValue]), [identifier intValue], [links intValue]);
printf("File Type : %s\n", [filePrint UTF8String]);
if (!isDir) {
printf("Disk Size : %s ",returnSize((physDataSize + physRsrcSize)));
if ((physRsrcSize > 0) && (physDataSize > 0)) {
printf("(Rsrc Fork: %s ", returnSize(physRsrcSize));
printf("/ Data Fork: %s)\n", returnSize(physDataSize));
} else if (physRsrcSize > 0) {
printf("(Rsrc Fork)\n");
} else {
printf ("(Data Fork)\n");
}
printf("Real Size : %s ",returnSize((realDataSize + realRsrcSize)));
if ((realRsrcSize > 0) && (realDataSize > 0)) {
printf("(Rsrc Fork: %s ", returnSize(realRsrcSize));
printf("/ Data Fork: %s)\n", returnSize(realDataSize));
} else if (realRsrcSize > 0) {
printf("(Rsrc Fork)\n");
} else {
printf("(Data Fork)\n");
}
free(returnString);
returnString=NULL;
}
printf("Permissions : (%s/%10.10s)\n", [permString UTF8String], access);
printf("Owner : (%i / %s)\nGroup : (%i / %s)\n", [ownerID intValue], [owner UTF8String], [groupID intValue], [group UTF8String]);
printf("Attributes : ");
printf("%s",isAlias ? "A" : "a");
printf("%s",((finderInfo->fdFlags & kIsInvisible) != 0) ? "V" : "v");
printf("%s",(((finderInfo->fdFlags & kHasBundle) != 0) && !isDir) ? "B" : "b");
printf("%s",(((finderInfo->fdFlags & kIsStationery) != 0) && !isDir) ? "T" : "t");
printf("%s",((finderInfo->fdFlags & kHasCustomIcon) != 0) ? "C" : "c");
printf("%s",((finderInfo->fdFlags & kNameLocked) != 0) ? "L" : "l");
printf("%s",((finderInfo->fdFlags & kHasBeenInited) !=0) ? "I" : "i");
printf("%s",((finderInfo->fdFlags & kHasNoINITs) != 0) ? "N" : "n");
printf("%s",((finderInfo->fdFlags & kIsShared) != 0) ? "M" : "m");
printf("%s",[hfsExtension boolValue] ? "E" : "e");
printf("%s",((finderInfo->fdFlags & kIsOnDesk) != 0) ? "D" : "d");
printf("\n");
// printf("Extension Hidden: %s\n",[hfsExtension boolValue] ? "Yes" : "No");
printf("Creation Date : %s\n",[[createDate descriptionWithCalendarFormat:@"%a %b %e %H:%M:%S %Y" timeZone:nil locale:nil]UTF8String]);
printf("Last Modified : %s\n",[[modifyDate descriptionWithCalendarFormat:@"%a %b %e %H:%M:%S %Y" timeZone:nil locale:nil]UTF8String]);
printf("Last accessed : %s\n", [[[NSDate dateWithTimeIntervalSince1970:stats.st_atime] descriptionWithCalendarFormat:@"%a %b %e %H:%M:%S %Y" timeZone:nil locale:nil]UTF8String]);
printf("Last changed : %s\n", [[[NSDate dateWithTimeIntervalSince1970:stats.st_ctime] descriptionWithCalendarFormat:@"%a %b %e %H:%M:%S %Y" timeZone:nil locale:nil]UTF8String]);
if ([creator unsignedLongValue] > 0) {
tthird = [type unsignedLongValue] >> 8;
tsecond = tthird >> 8;
tfirst = tsecond >> 8;
cthird = [creator unsignedLongValue] >> 8;
csecond = cthird >> 8;
cfirst = csecond >> 8;
printf("Type : %c%c%c%c\nCreator : %c%c%c%c\n", (int)tfirst, (int)tsecond, (int)tthird, [type intValue], (int)cfirst, (int)csecond, (int)cthird, [creator intValue]);
}
return;
UnixEnd:
if ((stats.st_mode & S_IFMT) == S_IFLNK) {
int i;
if ((i=readlink(theFileName,linkName, 256)) == -1) {
printf("Error reading file\n");
return;
}
linkName[(i >= 256) ? 255 : i]='\0';
printf("File: \"%s\" -> \"%s\"\n",theFileName,linkName);
} else {
printf("File: \"%s\"\n", theFileName);
}
printf("IO Block : %d Blocks: %u Device: %d,%d Inode: %d Links: %d\n", (unsigned int)stats.st_blocks, (int)stats.st_blksize, major([devIdentifier intValue]), minor([devIdentifier intValue]), [identifier intValue], [links intValue]);
printf("File Type : %s\n", [filePrint UTF8String]);
if (!((stats.st_mode & S_IFMT) == S_IFDIR)) {
printf("Real Size : %s\n", returnSize([fileSize longValue]));
}
printf("Permissions : (%s/%s)\n", [permString UTF8String], access);
printf("Owner : (%i / %s)\n", [ownerID intValue], [owner UTF8String]);
printf("Group : (%i / %s)\n", [groupID intValue], [group UTF8String]);
printf("Ext Hidden : %s\n", [hfsExtension boolValue] ? "Yes" : "No");
printf("Creation Date : %s\n", [[createDate descriptionWithCalendarFormat:@"%a %b %d %H:%M:%S %Y" timeZone:nil locale:nil]UTF8String]);
printf("Last Modified : %s\n", [[modifyDate descriptionWithCalendarFormat:@"%a %b %d %H:%M:%S %Y" timeZone:nil locale:nil]UTF8String]);
printf("Last accessed : %s\n", [[[NSDate dateWithTimeIntervalSince1970:stats.st_atime] descriptionWithCalendarFormat:@"%a %b %d %H:%M:%S %Z %Y" timeZone:nil locale:nil]UTF8String]);
printf("Last changed : %s", ctime(&stats.st_ctime));
if ([creator unsignedLongValue] > 0) {
tthird = [type unsignedLongValue] >> 8;
tsecond = tthird >> 8;
tfirst = tsecond >> 8;
cthird = [creator unsignedLongValue] >> 8;
csecond = cthird >> 8;
cfirst = csecond >> 8;
printf("Type : %c%c%c%c\nCreator : %c%c%c%c\n", (int)tfirst, (int)tsecond, (int)tthird, [type intValue], (int)cfirst, (int)csecond, (int)cthird, [creator intValue]);
}
}
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
NSString *file;
int c,i;
BOOL hfs=NO;
if (argc == 1) {
printf("USAGE: %s [-v] [-h] FILENAME\n\n",argv[0]);
[pool release];
return 1;
}
while ((c=getopt(argc, argv, "vh?")) != EOF) {
switch (c) {
case 'v':
printf("%s version 0.1.2\n\tCopyright 2003 - 2004 Night Productions\n\n",argv[0]);
return 0;
break;
case 'h':
printf("USAGE: %s [-h] [-v] FILENAME\n\n",argv[0]);
printf("\t-h:\tThis help screen.\n");
printf("\t-v:\tPrints out version information about xstat.\n\n");
printf("\t(Attributes:)\n");
printf("\t\ta - alias file\n");
printf("\t\tv - invisible\n");
printf("\t\tb - bundle\n");
printf("\t\tt - stationary\n");
printf("\t\tc - custom icon\n");
printf("\t\tl - locked\n");
printf("\t\ti - inited\n");
printf("\t\tn - has no INITs\n");
printf("\t\tm - shared file\n");
printf("\t\te - extension hidden\n");
printf("\t\td - desktop\n");
printf("\t(lowercase means 'off/no', uppercase means 'on/yes')\n");
printf("\n");
[pool release];
return 0;
break;
default:
printf("USAGE: %s [-h] [-v] FILENAME\n\n",argv[0]);
[pool release];
return 1;
break;
}
}
for (i= optind; i < argc; i++) {
file=[NSString stringWithUTF8String:argv[i]];
xstat(file,hfs);
file=nil;
}
[pool release];
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment