FieldPrinter.c
/* |
File: FieldPrinter.c |
Contains: Routines to pretty print structures. |
Written by: DTS |
Copyright: Copyright (c) 2008 Apple Inc. All Rights Reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. |
("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or |
redistribution of this Apple software constitutes acceptance of |
these terms. If you do not agree with these terms, please do |
not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following |
terms, and subject to these terms, Apple grants you a personal, |
non-exclusive license, under Apple's copyrights in this |
original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or |
without modifications, in source and/or binary forms; provided |
that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the |
following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks |
or logos of Apple Inc. may be used to endorse or promote |
products derived from the Apple Software without specific prior |
written permission from Apple. Except as expressly stated in |
this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or |
by other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. |
APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING |
WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING |
THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, |
INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY |
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY |
OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR |
OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF |
SUCH DAMAGE. |
*/ |
///////////////////////////////////////////////////////////////// |
// Our prototypes |
#include "FieldPrinter.h" |
// System interfaces |
#include <assert.h> |
#include <dirent.h> |
#include <grp.h> |
#include <inttypes.h> |
#include <membership.h> |
#include <netdb.h> |
#include <netinet/in.h> |
#include <paths.h> |
#include <pwd.h> |
#include <stdio.h> |
#include <string.h> |
#include <sys/param.h> |
#include <sys/stat.h> |
///////////////////////////////////////////////////////////////// |
#pragma mark ***** Utilities |
extern char * FPPStringToUTFCString(ConstStr255Param pstr, CFStringEncoding pstrEncoding) |
// See comment in header. |
{ |
CFStringRef str; |
CFIndex strBufLen; |
char * strBuf; |
Boolean success; |
assert(pstr != NULL); |
strBuf = NULL; |
str = CFStringCreateWithPascalString(NULL, pstr, pstrEncoding); |
assert(str != NULL); |
if (str != NULL) { |
strBufLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1; // + 1 for null terminator |
strBuf = (char *) malloc(strBufLen); |
assert(strBuf != NULL); |
if (strBuf != NULL) { |
success = CFStringGetCString(str, strBuf, strBufLen, kCFStringEncodingUTF8); |
assert(success); |
if ( ! success ) { |
free(strBuf); |
strBuf = NULL; |
} |
} |
CFRelease(str); |
} |
return strBuf; |
} |
extern void FPPrintFlags(unsigned long long flags, const FPFlagDesc *flagList, size_t nameWidth, uint32_t indent) |
// See comment in header. |
{ |
int flagIndex; |
size_t thisLen; |
assert(flagList != NULL); |
// Calculate the length of the longest flag name (unless the caller |
// specified one). |
if (nameWidth == 0) { |
flagIndex = 0; |
while (flagList[flagIndex].flagName != NULL) { |
thisLen = strlen(flagList[flagIndex].flagName); |
if (thisLen > nameWidth) { |
nameWidth = thisLen; |
} |
flagIndex += 1; |
} |
} |
// Print each matching flag, clearing each flag that we recognise. |
flagIndex = 0; |
while (flagList[flagIndex].flagName != NULL) { |
fprintf(stdout, "%*s%-*s = %s\n", (int) indent, "", (int) nameWidth, flagList[flagIndex].flagName, (flags & flagList[flagIndex].flagMask) ? "YES" : "NO"); |
flags &= ~flagList[flagIndex].flagMask; |
flagIndex += 1; |
} |
// If any flags remain unrecognised, tell the user. |
if (flags != 0) { |
fprintf(stdout, "%*s... and others (0x%llx)\n", (int) indent, "", flags); |
} |
} |
extern size_t FPFindFlagByName(const FPFlagDesc *flagList, const char *flagName) |
// See comment in header. |
{ |
bool found; |
size_t flagIndex; |
found = false; |
flagIndex = 0; |
while ( ! found && (flagList[flagIndex].flagName != NULL) ) { |
found = (strcasecmp(flagName, flagList[flagIndex].flagName) == 0); |
if ( ! found ) { |
flagIndex += 1; |
} |
} |
if ( ! found ) { |
flagIndex = kFPNotFound; |
} |
return flagIndex; |
} |
extern size_t FPFindEnumByValue(const FPEnumDesc enumList[], int enumValue) |
// See comment in header. |
{ |
bool found; |
size_t enumIndex; |
found = false; |
enumIndex = 0; |
while ( ! found && (enumList[enumIndex].enumName != NULL) ) { |
found = (enumList[enumIndex].enumValue == enumValue); |
if ( ! found ) { |
enumIndex += 1; |
} |
} |
if ( ! found ) { |
enumIndex = kFPNotFound; |
} |
return enumIndex; |
} |
extern size_t FPFindEnumByName(const FPEnumDesc enumList[], const char *enumName) |
// See comment in header. |
{ |
bool found; |
size_t enumIndex; |
found = false; |
enumIndex = 0; |
while ( ! found && (enumList[enumIndex].enumName != NULL) ) { |
found = (strcasecmp(enumList[enumIndex].enumName, enumName) == 0); |
if ( ! found ) { |
enumIndex += 1; |
} |
} |
if ( ! found ) { |
enumIndex = kFPNotFound; |
} |
return enumIndex; |
} |
static void FPPrintFieldsCore(const FPFieldDesc fields[], const void *fieldBuf, size_t fieldBufSize, uint32_t indent, uint32_t verbose, FPEndian endian) |
{ |
#pragma unused(fieldBufSize) |
size_t nameWidth; |
size_t nameLen; |
size_t fieldIndex; |
FPPrinter printer; |
const void * info; |
assert(fields != NULL); |
assert(fieldBuf != NULL); |
// Calculate the maximum field of the field names. |
nameWidth = 0; |
fieldIndex = 0; |
while (fields[fieldIndex].fieldName != NULL) { |
nameLen = strlen(fields[fieldIndex].fieldName); |
if (nameLen > nameWidth) { |
nameWidth = nameLen; |
} |
fieldIndex += 1; |
} |
// Print each field. |
fieldIndex = 0; |
while (fields[fieldIndex].fieldName != NULL) { |
// Make sure the field is within the structure. |
assert( fields[fieldIndex].fieldOffset < fieldBufSize ); |
assert( (fields[fieldIndex].fieldOffset + fields[fieldIndex].fieldSize) <= fieldBufSize); |
// Process any endian override requested by the caller. |
printer = fields[fieldIndex].fieldPrinter; |
info = fields[fieldIndex].fieldInfo; |
switch (endian) { |
case kFPValueHostEndian: |
// do nothing |
break; |
case kFPValueBigEndian: |
if ( (printer == FPHex) || (printer == FPSDec) || (printer == FPUDec) || (printer == FPSignature) ) { |
info = (const void *) (uintptr_t) endian; |
} else if (printer == FPFlags) { |
printer = FPFlagsBE; |
} else { |
assert(false); |
} |
break; |
case kFPValueLittleEndian: |
assert(false); |
break; |
default: |
assert(false); |
break; |
} |
// Call the printer routine. |
printer( |
fields[fieldIndex].fieldName, |
fields[fieldIndex].fieldSize, |
(((char *) fieldBuf) + fields[fieldIndex].fieldOffset), |
indent, |
nameWidth, |
verbose, |
info |
); |
fieldIndex += 1; |
} |
} |
extern void FPPrintFields(const FPFieldDesc fields[], const void *fieldBuf, size_t fieldBufSize, uint32_t indent, uint32_t verbose) |
// See comments in header. |
{ |
FPPrintFieldsCore(fields, fieldBuf, fieldBufSize, indent, verbose, kFPValueHostEndian); |
} |
///////////////////////////////////////////////////////////////// |
#pragma mark ***** Field Printer Routines |
extern void FPNull( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints nothing, in about 20 lines )-: |
// |
// See definition of FPPrinter for a parameter description. |
{ |
// Can't use FPStandardPreCondition because fieldSize is allowed to be |
// zero in this case. |
assert( fieldName != NULL ); |
// assert( fieldSize > 0 ); |
assert( fieldPtr != NULL ); |
assert( (nameWidth > 0) && ( ((size_t) nameWidth) >= strlen(fieldName) ) ); |
#pragma unused(fieldName) |
#pragma unused(fieldSize) |
#pragma unused(fieldPtr) |
#pragma unused(indent) |
#pragma unused(nameWidth) |
#pragma unused(verbose) |
#pragma unused(info) |
// do nothing |
} |
extern void FPCString( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a C string field. The field is assumed to be UTF-8. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
fprintf(stdout, "%*s%-*s = '%s'\n", (int) indent, "", (int) nameWidth, fieldName, (const char *) fieldPtr); |
} |
extern void FPCStringPtr( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a C string pointer field. The encoding is assumed to be UTF-8. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
const char * strPtr; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(const char *)); |
strPtr = *((const char **) fieldPtr); |
assert(strPtr != NULL); |
fprintf(stdout, "%*s%-*s = %p ('%s')\n", (int) indent, "", (int) nameWidth, fieldName, strPtr, strPtr); |
} |
extern void FPPString( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a Pascal string field. info supplies the text encoding. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
char * strBuf; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
assert( FPStandardPreCondition() ); |
strBuf = FPPStringToUTFCString(fieldPtr, (CFStringEncoding) (uintptr_t) info); |
assert(strBuf != NULL); |
if (strBuf != NULL) { |
fprintf(stdout, "%*s%-*s = '%s'\n", (int) indent, "", (int) nameWidth, fieldName, strBuf); |
} |
free(strBuf); |
} |
extern void FPCFString( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a CFString field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
CFStringRef str; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(CFStringRef)); |
str = *( (CFStringRef *) fieldPtr ); |
assert(str != NULL); |
assert( CFGetTypeID(str) == CFStringGetTypeID() ); |
FPCFType(fieldName, sizeof(str), &str, indent, (int) nameWidth, verbose, NULL); |
} |
extern void FPCFType( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a CFType field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
CFTypeRef value; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(CFTypeRef)); |
value = *( (CFTypeRef *) fieldPtr ); |
assert(value != NULL); |
// First handle the compound types, CFDictionary and CFArray. |
if ( CFGetTypeID(value) == CFDictionaryGetTypeID() ) { |
FPCFDictionary(fieldName, sizeof(value), &value, indent, nameWidth, verbose, NULL); |
} else if ( CFGetTypeID(value) == CFArrayGetTypeID() ) { |
// FPCFArray(fieldName, sizeof(value), &value, indent, nameWidth, verbose, NULL); |
fprintf(stderr, "*** CFArray skipped\n"); |
} else { |
const char * quoteStr; |
CFStringRef str; |
CFIndex strBufLen; |
char * strBuf; |
Boolean success; |
// Handle everything else, which hopefully can be converted to a string |
// using CFStringCreateWithFormat. |
quoteStr = ""; |
if ( CFGetTypeID(value) == CFStringGetTypeID() ) { |
quoteStr = "'"; |
} |
str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), value); |
assert(str != NULL); |
if (str != NULL) { |
strBufLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1; // + 1 for null terminator |
strBuf = (char *) malloc(strBufLen); |
assert(strBuf != NULL); |
if (strBuf != NULL) { |
success = CFStringGetCString(str, strBuf, strBufLen, kCFStringEncodingUTF8); |
assert(success); |
if (success) { |
fprintf(stdout, "%*s%-*s = %s%s%s\n", (int) indent, "", (int) nameWidth, fieldName, quoteStr, strBuf, quoteStr); |
} |
} |
free(strBuf); |
CFRelease(str); |
} |
} |
} |
static int KeyCompare(const void *left, const void *right) |
// Comparison callback for sorting an array of CFDictionary keys. |
{ |
CFStringRef leftString; |
CFStringRef rightString; |
assert(left != NULL); |
assert(right != NULL); |
leftString = *(CFStringRef *) left; |
rightString = *(CFStringRef *) right; |
assert(leftString != NULL); |
assert(rightString != NULL); |
return (int) CFStringCompare(leftString, rightString, 0); |
} |
extern void FPCFDictionary( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a CFDictionary field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
CFDictionaryRef dict; |
CFIndex dictCount; |
CFIndex dictIndex; |
Boolean success; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(CFDictionaryRef)); |
dict = *( (CFDictionaryRef *) fieldPtr ); |
assert(dict != NULL); |
assert( CFGetTypeID(dict) == CFDictionaryGetTypeID() ); |
fprintf(stdout, "%*s%-*s = {\n", (int) indent, "", (int) nameWidth, fieldName); |
dictCount = CFDictionaryGetCount(dict); |
if (dictCount > 0) { |
CFTypeRef * keys; |
CFIndex keyWidth; |
char * keyBuf; |
CFIndex keyBufSize; |
keys = malloc(dictCount * sizeof(CFTypeRef)); |
assert(keys != NULL); |
CFDictionaryGetKeysAndValues(dict, (const void **) keys, NULL); |
// Sort the keys so that we get consistent results for the benefit of the |
// test script. |
qsort(keys, dictCount, sizeof(*keys), KeyCompare); |
// Calculate the maximum length of the keys. This is somewhat bogus because |
// we're counting in Unicode characters, not UTF-8, but it will work for the |
// common case where the keys are all ASCII. |
keyWidth = 0; |
for (dictIndex = 0; dictIndex < dictCount; dictIndex++) { |
assert( CFGetTypeID(keys[dictIndex]) == CFStringGetTypeID() ); |
if ( CFStringGetLength(keys[dictIndex]) > keyWidth ) { |
keyWidth = CFStringGetLength(keys[dictIndex]); |
} |
} |
// Once we know the maximum key width, we can use it to allocate a buffer that's |
// big enough to hold the UTF-8 representation of that width. |
keyBufSize = CFStringGetMaximumSizeForEncoding(keyWidth, kCFStringEncodingUTF8) + 1; |
keyBuf = malloc(keyBufSize); |
assert(keyBuf != NULL); |
// Now go through and print each field. |
for (dictIndex = 0; dictIndex < dictCount; dictIndex++) { |
CFTypeRef thisValue; |
success = CFStringGetCString(keys[dictIndex], keyBuf, keyBufSize, kCFStringEncodingUTF8); |
assert(success); |
thisValue = CFDictionaryGetValue(dict, keys[dictIndex]); |
FPCFType(keyBuf, sizeof(thisValue), &thisValue, indent + kStdIndent, keyWidth, verbose, NULL); |
} |
free(keyBuf); |
free(keys); |
} |
fprintf(stdout, "%*s}\n", (int) indent, ""); |
} |
extern void HFSUniStr255FieldPrinter( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints an HFSUniStr255 field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
const HFSUniStr255 * hfsStr; |
CFStringRef str; |
#pragma unused(fieldSize) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(HFSUniStr255)); |
hfsStr = (const HFSUniStr255 *) fieldPtr; |
assert(hfsStr != NULL); |
str = CFStringCreateWithCharacters(NULL, hfsStr->unicode, hfsStr->length); |
assert(str != NULL); |
if (str != NULL) { |
FPCFString(fieldName, sizeof(str), &str, indent, nameWidth, verbose, info); |
} |
CFRelease(str); |
} |
extern void FPPtr( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a generic pointer field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
const void * ptr; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(void *)); |
ptr = *((const void **) fieldPtr); |
fprintf(stdout, "%*s%-*s = %p\n", (int) indent, "", (int) nameWidth, fieldName, ptr); |
} |
extern void FPBoolean( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a Boolean field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
Boolean b; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(Boolean)); |
b = *((Boolean *) fieldPtr); |
fprintf(stdout, "%*s%-*s = %s\n", (int) indent, "", (int) nameWidth, fieldName, b ? "YES" : "NO"); |
} |
static bool SwapIt(const void *info) |
{ |
FPEndian endian; |
bool swap; |
endian = (FPEndian) (uintptr_t) info; |
swap = false; |
switch (endian) { |
case kFPValueHostEndian: |
break; |
case kFPValueBigEndian: |
#if TARGET_RT_LITTLE_ENDIAN |
swap = true; |
#endif |
break; |
case kFPValueLittleEndian: |
#if TARGET_RT_BIG_ENDIAN |
swap = true; |
#endif |
break; |
default: |
assert(false); |
break; |
} |
return swap; |
} |
static uint16_t Swap16(const void *fieldPtr, const void *info) |
{ |
uint16_t x; |
x = * (uint16_t *) fieldPtr; |
if ( SwapIt(info) ) { |
x = OSSwapInt16(x); |
} |
return x; |
} |
static uint32_t Swap32(const void *fieldPtr, const void *info) |
{ |
uint32_t x; |
x = * (uint32_t *) fieldPtr; |
if ( SwapIt(info) ) { |
x = OSSwapInt32(x); |
} |
return x; |
} |
static uint64_t Swap64(const void *fieldPtr, const void *info) |
{ |
uint64_t x; |
x = * (uint64_t *) fieldPtr; |
if ( SwapIt(info) ) { |
x = OSSwapInt64(x); |
} |
return x; |
} |
extern void FPHex( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a field in hex. There's special case code for each common size |
// (8 bits, 16 bits, 32 bits, and 64 bits), and generic code for large sizes. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
size_t i; |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
switch (fieldSize) { |
case sizeof(uint8_t): |
fprintf(stdout, "%*s%-*s = 0x%02" PRIx8 "\n", (int) indent, "", (int) nameWidth, fieldName, *((uint8_t *) fieldPtr) ); |
break; |
case sizeof(uint16_t): |
fprintf(stdout, "%*s%-*s = 0x%04" PRIx16 "\n", (int) indent, "", (int) nameWidth, fieldName, Swap16(fieldPtr, info) ); |
break; |
case sizeof(uint32_t): |
fprintf(stdout, "%*s%-*s = 0x%08" PRIx32 "\n", (int) indent, "", (int) nameWidth, fieldName, Swap32(fieldPtr, info) ); |
break; |
case sizeof(uint64_t): |
fprintf(stdout, "%*s%-*s = 0x%016" PRIx64 "\n", (int) indent, "", (int) nameWidth, fieldName, Swap64(fieldPtr, info) ); |
break; |
default: |
if (fieldSize > sizeof(uint64_t)) { |
fprintf(stdout, "%*s%-*s = ", (int) indent, "", (int) nameWidth, fieldName); |
i = 0; |
while (i < fieldSize) { |
do { |
fprintf(stdout, "%02" PRIx8 " ", ((uint8_t *) fieldPtr)[i]); |
i += 1; |
} while ( (i < fieldSize) && ((i % 16) != 0) ); |
fprintf(stdout, "\n"); |
if (i < fieldSize) { |
fprintf(stdout, "%*s%*s ", (int) indent, "", (int) nameWidth, ""); |
} |
} |
} else { |
assert(false); |
} |
break; |
} |
} |
extern void FPSDec( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a field as a signed decimal. There's special case code for each common |
// size (8 bits, 16 bits, 32 bits, and 64 bits), and other sizes are printed as |
// a hex dump. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
assert( FPStandardPreCondition() ); |
switch (fieldSize) { |
case sizeof(int8_t): |
fprintf(stdout, "%*s%-*s = %" PRId8 "\n", (int) indent, "", (int) nameWidth, fieldName, *((int8_t *) fieldPtr) ); |
break; |
case sizeof(int16_t): |
fprintf(stdout, "%*s%-*s = %" PRId16 "\n", (int) indent, "", (int) nameWidth, fieldName, (int16_t) Swap16(fieldPtr, info) ); |
break; |
case sizeof(int32_t): |
fprintf(stdout, "%*s%-*s = %" PRId32 "\n", (int) indent, "", (int) nameWidth, fieldName, (int32_t) Swap32(fieldPtr, info) ); |
break; |
case sizeof(int64_t): |
fprintf(stdout, "%*s%-*s = %" PRId64 "\n", (int) indent, "", (int) nameWidth, fieldName, (int64_t) Swap64(fieldPtr, info) ); |
break; |
default: |
FPHex(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info); |
break; |
} |
} |
extern void FPUDec( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a field as an unsigned decimal. There's special case code for each common |
// size (8 bits, 16 bits, 32 bits, and 64 bits), and other sizes are printed as |
// a hex dump. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
switch (fieldSize) { |
case sizeof(uint8_t): |
fprintf(stdout, "%*s%-*s = %" PRIu8 "\n", (int) indent, "", (int) nameWidth, fieldName, *((uint8_t *) fieldPtr) ); |
break; |
case sizeof(uint16_t): |
fprintf(stdout, "%*s%-*s = %" PRIu16 "\n", (int) indent, "", (int) nameWidth, fieldName, Swap16(fieldPtr, info) ); |
break; |
case sizeof(uint32_t): |
fprintf(stdout, "%*s%-*s = %" PRIu32 "\n", (int) indent, "", (int) nameWidth, fieldName, Swap32(fieldPtr, info) ); |
break; |
case sizeof(uint64_t): |
fprintf(stdout, "%*s%-*s = %" PRIu64 "\n", (int) indent, "", (int) nameWidth, fieldName, Swap64(fieldPtr, info) ); |
break; |
default: |
FPHex(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info); |
break; |
} |
} |
extern void FPSize( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a field in decimal along with an interpretation of the field as |
// bytes, KB, MB, or GB. In addition, if info is not NULL then it describes |
// another field that holds the units of the value. For example, if fieldPtr |
// points to the disk size in blocks, info describes the field that holds the |
// block size, so that this routine can calculate the size in bytes. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
uint64_t fieldValue; |
uint64_t fieldValueInBytes; |
const FPSizeMultiplier * multiplier; |
const void * multiplierPtr; |
uint64_t unitDivisor; |
const char * unitStr; |
#pragma unused(verbose) |
assert( FPStandardPreCondition() ); |
// Get the value of the field itself. Note that we only handle 32 bit |
// and 64 bit fields because that's all that cropped up in this program. |
switch (fieldSize) { |
case sizeof(uint32_t): |
fieldValue = *((uint32_t *) fieldPtr); |
break; |
case sizeof(uint64_t): |
fieldValue = *((uint64_t *) fieldPtr); |
break; |
default: |
assert(false); |
fieldValue = 0; |
break; |
} |
// If there's a multiplier, get its value (again, we only support 32 bit |
// and 64 bit multipliers) and use it to calculate the total size in bytes. |
if (info != NULL) { |
multiplier = (const FPSizeMultiplier *) info; |
multiplierPtr = ((const char *) fieldPtr) + multiplier->multiplierOffset; |
switch (multiplier->multiplierSize) { |
case sizeof(uint32_t): |
fieldValueInBytes = fieldValue * *((uint32_t *) multiplierPtr); |
break; |
case sizeof(uint64_t): |
fieldValueInBytes = fieldValue * *((uint64_t *) multiplierPtr); |
break; |
default: |
assert(false); |
fieldValueInBytes = 0; |
break; |
} |
} else { |
fieldValueInBytes = fieldValue; |
} |
// Work out the units for printing fieldValueInBytes. |
if (fieldValueInBytes > (1024LL * 1024 * 1024)) { |
unitDivisor = 1024LL * 1024 * 1024; |
unitStr = "GB"; |
} else if (fieldValueInBytes > (1024LL * 1024)) { |
unitDivisor = 1024LL * 1024; |
unitStr = "MB"; |
} else if (fieldValueInBytes > 1024LL) { |
unitDivisor = 1024LL; |
unitStr = "KB"; |
} else { |
unitDivisor = 1; |
if (fieldValueInBytes == 1) { |
unitStr = "byte"; |
} else { |
unitStr = "bytes"; |
} |
} |
// Print the raw field value and its pretty value. |
fprintf(stdout, "%*s%-*s = %" PRIu64 " (%" PRIu64 " %s)\n", (int) indent, "", (int) nameWidth, fieldName, fieldValue, fieldValueInBytes / unitDivisor, unitStr); |
} |
extern void FPSignature( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a signature field (that is, a generalised form of OSType, where |
// each byte is interpreted as a character). Made more complicated by the |
// fact that OSType-bytes are generally considered to be in MacRoman. Oh yeah, |
// and byte order. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
uint16_t sig16; |
uint32_t sig32; |
char tmp[5] = { 0 }; |
char strBuf[64]; |
size_t i; |
Boolean success; |
CFStringRef str; |
FPEndian endian; |
bool swap; |
#pragma unused(verbose) |
assert( FPStandardPreCondition() ); |
assert( (fieldSize == 2) || (fieldSize == 4) ); |
// Generate a UTF-8 C string from the data. This is way more complex that |
// you'd think (-: |
// We want the input data for the string to be big endian. So, we swap it |
// around if its little endian, or host endian on a little endian machine. |
endian = (FPEndian) (uintptr_t) info; |
swap = (endian == kFPValueLittleEndian); |
#if TARGET_RT_LITTLE_ENDIAN |
if (endian == kFPValueHostEndian) { |
swap = true; |
} |
#endif |
for (i = 0; i < fieldSize; i++) { |
uint8_t b; |
b = ((const uint8_t *) fieldPtr)[i]; |
if ( (b < ' ') || (b == 0x7f) ) { |
b = '?'; |
} |
if (swap) { |
tmp[fieldSize - 1 - i] = b; |
} else { |
tmp[i] = b; |
} |
} |
str = CFStringCreateWithCString(NULL, tmp, kCFStringEncodingMacRoman); |
assert(str != NULL); |
success = CFStringGetCString(str, strBuf, sizeof(strBuf), kCFStringEncodingUTF8); |
assert(success); |
CFRelease(str); |
switch (fieldSize) { |
case sizeof(uint16_t): |
sig16 = Swap16(fieldPtr, info); |
fprintf(stdout, "%*s%-*s = 0x%04" PRIx16 " ('%s')\n", (int) indent, "", (int) nameWidth, fieldName, sig16, strBuf); |
break; |
case sizeof(uint32_t): |
sig32 = Swap32(fieldPtr, info); |
fprintf(stdout, "%*s%-*s = 0x%08" PRIx32 " ('%s')\n", (int) indent, "", (int) nameWidth, fieldName, sig32, strBuf); |
break; |
default: |
assert(false); |
break; |
} |
} |
static const char * FindDevString(dev_t dev) |
// Searches "/dev" for a device node whose dev_t matches dev. |
// |
// On success, the result is a C string that contains the Posix |
// path to the dev node. The caller is responsible for disposing |
// of this string using "free". On error, the result is NULL. |
{ |
int err; |
int junk; |
const char * result; |
DIR * dir; |
struct dirent * thisDirEnt; |
char thisDirEntPath[MAXPATHLEN]; |
struct stat sb; |
result = NULL; |
dir = opendir(_PATH_DEV); |
if (dir != NULL) { |
do { |
thisDirEnt = readdir(dir); |
if (thisDirEnt != NULL) { |
// Only interested in character or block device drivers. |
if ( (thisDirEnt->d_type == DT_CHR) || (thisDirEnt->d_type == DT_BLK) ) { |
// Construct the full path to the dev node. |
snprintf(thisDirEntPath, sizeof(thisDirEntPath), _PATH_DEV "%.*s", thisDirEnt->d_namlen, thisDirEnt->d_name); |
err = stat(thisDirEntPath, &sb); |
if (err == 0) { |
// fprintf(stdout, "%s %08x\n", thisDirEntPath, sb.st_rdev); |
if (sb.st_rdev == dev) { |
char * tmp; |
// We have a match. Allocate a C string, copy |
// the name into it, and set up to the return it |
// to our caller. We can't use strdup because |
// there's no guarantee that thisDirEnt->d_name is |
// null terminated. |
tmp = (char *) malloc(thisDirEnt->d_namlen + 1); |
assert(tmp != NULL); |
memcpy(tmp, thisDirEnt->d_name, thisDirEnt->d_namlen); |
tmp[thisDirEnt->d_namlen] = 0; |
result = tmp; |
} |
} |
} |
} |
} while ( (result == NULL) && (thisDirEnt != NULL) ); |
junk = closedir(dir); |
assert(junk == 0); |
} |
return result; |
} |
extern void FPDevT( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a dev_t field, looking up the value in "/dev" to see if |
// we can work out what the corresponding device node is called. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
dev_t dev; |
const char * devStr; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(dev_t)); |
dev = *( (dev_t *) fieldPtr ); |
devStr = FindDevString(dev); |
if (devStr == NULL) { |
fprintf(stdout, "%*s%-*s = 0x%08lx (major=%ld, minor=%ld)\n", (int) indent, "", (int) nameWidth, fieldName, (long ) dev, (long) major(dev), (long) minor(dev)); |
} else { |
fprintf(stdout, "%*s%-*s = 0x%08lx (major=%ld, minor=%ld, %s)\n", (int) indent, "", (int) nameWidth, fieldName, (long ) dev, (long) major(dev), (long) minor(dev), devStr); |
} |
free( (char *) devStr); |
} |
extern void FPUID( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a uid_t field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
uid_t uid; |
struct passwd * pw; |
const char * uidStr; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(uid_t)); |
uid = *((uid_t *) fieldPtr); |
pw = getpwuid(uid); |
if (pw == NULL) { |
uidStr = "???"; |
} else { |
uidStr = pw->pw_name; |
} |
fprintf(stdout, "%*s%-*s = %ld (%s)\n", (int) indent, "", (int) nameWidth, fieldName, (long) uid, uidStr); |
} |
extern void FPGID( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a gid_t field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
gid_t gid; |
struct group * gr; |
const char * gidStr; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(gid_t)); |
gid = *((gid_t *) fieldPtr); |
gr = getgrgid(gid); |
if (gr == NULL) { |
gidStr = "???"; |
} else { |
gidStr = gr->gr_name; |
} |
fprintf(stdout, "%*s%-*s = %ld (%s)\n", (int) indent, "", (int) nameWidth, fieldName, (long) gid, gidStr); |
} |
extern void FPGUID( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a GUID field. Prints both the raw hex and the corresponding |
// user/group name. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
int err; |
const guid_t * guidPtr; |
uuid_t uuid; |
int idType; |
uid_t id; |
const char * idTypeStr; |
const char * idStr; |
struct passwd * pw; |
struct group * gr; |
static const guid_t kNullGUID = { { 0 } }; |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(*guidPtr)); |
guidPtr = (const guid_t *) fieldPtr; |
assert( sizeof(uuid) == sizeof(*guidPtr) ); |
memcpy( uuid, guidPtr, sizeof(uuid) ); |
// First test for a null GUID. |
if ( memcmp(guidPtr, &kNullGUID, sizeof(kNullGUID) ) == 0 ) { |
fprintf( |
stdout, |
"%*s%-*s = 00000000-0000-0000-0000-000000000000 (null)\n", |
(int) indent, |
"", |
(int) nameWidth, |
fieldName |
); |
} else { |
// It's not null, we'll want to map it to a user or group |
// Prepare for failure. |
idTypeStr = "???"; |
idStr = "???"; |
// Map the GUID to an id type (user/group) and ID. |
err = mbr_uuid_to_id(uuid, &id, &idType); |
// Convert the results to strings. |
if (err == 0) { |
switch (idType) { |
case ID_TYPE_UID: |
idTypeStr = "user"; |
pw = getpwuid(id); |
if (pw != NULL) { |
idStr = pw->pw_name; |
} |
break; |
case ID_TYPE_GID: |
idTypeStr = "group"; |
gr = getgrgid( (gid_t) id ); |
if (gr != NULL) { |
idStr = gr->gr_name; |
} |
break; |
default: |
assert(false); |
err = -1; |
break; |
} |
} |
// Print the GUID and its mapping. |
fprintf( |
stdout, |
"%*s%-*s = %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X (%s:%s)\n", |
(int) indent, |
"", |
(int) nameWidth, |
fieldName, |
guidPtr->g_guid[0], |
guidPtr->g_guid[1], |
guidPtr->g_guid[2], |
guidPtr->g_guid[3], |
guidPtr->g_guid[4], |
guidPtr->g_guid[5], |
guidPtr->g_guid[6], |
guidPtr->g_guid[7], |
guidPtr->g_guid[8], |
guidPtr->g_guid[9], |
guidPtr->g_guid[10], |
guidPtr->g_guid[11], |
guidPtr->g_guid[12], |
guidPtr->g_guid[13], |
guidPtr->g_guid[14], |
guidPtr->g_guid[15], |
idTypeStr, |
idStr |
); |
} |
} |
extern void FPModeT( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a mode_t field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
mode_t fieldValue; |
unsigned long tmp; |
char modeStr[12]; |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
switch (fieldSize) { |
case sizeof(mode_t): |
fieldValue = *( (mode_t *) fieldPtr ); |
break; |
case sizeof(uint32_t): // getattrlist returns mode_t's as uint32_t |
tmp = *( (uint32_t *) fieldPtr ); |
fieldValue = tmp; |
break; |
default: |
assert(false); |
fieldValue = 0; |
break; |
} |
strmode(fieldValue, modeStr); |
// Remove trailing blank if present. This indicates the absence of an ACL, |
// which is the most common case. The trailing blank looks ugly when we |
// enclose the string in parens. |
if (modeStr[10] == ' ') { |
modeStr[10] = 0; |
} |
fprintf(stdout, "%*s%-*s = 0x%08lx (%s)\n", (int) indent, "", (int) nameWidth, fieldName, (long) fieldValue, modeStr); |
} |
extern void FPEnum( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints an enumeration value field. info points to an array of FPEnumDesc |
// that describes the known values of the enumeration. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
const FPEnumDesc * enumList; |
int fieldValue; |
int enumIndex; |
const char * enumStr; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
assert( FPStandardPreCondition() ); |
assert(info != NULL); |
enumList = (const FPEnumDesc *) info; |
// Get the field value. |
switch (fieldSize) { |
case sizeof(int8_t): |
fieldValue = *( (const int8_t *) fieldPtr ); |
break; |
case sizeof(int16_t): |
fieldValue = *( (const int16_t *) fieldPtr ); |
break; |
case sizeof(int32_t): |
fieldValue = *( (const int32_t *) fieldPtr ); |
break; |
default: |
assert(false); |
fieldValue = -1; |
break; |
} |
// Search enumList for fieldValue. |
enumIndex = 0; |
while ( (enumList[enumIndex].enumName != NULL) && (enumList[enumIndex].enumValue != fieldValue) ) { |
enumIndex += 1; |
} |
enumStr = enumList[enumIndex].enumName; |
if (enumStr == NULL) { |
enumStr = "???"; |
} |
fprintf(stdout, "%*s%-*s = %d (%s)\n", (int) indent, "", (int) nameWidth, fieldName, fieldValue, enumStr); |
} |
static void FPFlagsCore( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info, |
const FPFlagDesc flagList[] |
) |
// *** Prints a flags field. info is a pointer to an array of FPFlagDesc |
// describing the known flags in the field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
unsigned long long flags; |
assert( FPStandardPreCondition() ); |
assert(flagList != NULL); |
// First print the flag word in hex. |
FPHex(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info); |
// Then extract the flags word and print the individual flags, as long |
// as we're in verbose mode. |
if (verbose > 0) { |
switch (fieldSize) { |
case sizeof(uint8_t): |
flags = *((uint8_t *) fieldPtr); |
break; |
case sizeof(uint16_t): |
flags = Swap16(fieldPtr, info); |
break; |
case sizeof(uint32_t): |
flags = Swap32(fieldPtr, info); |
break; |
case sizeof(uint64_t): |
flags = Swap64(fieldPtr, info); |
break; |
default: |
assert(false); |
flags = 0; |
break; |
} |
FPPrintFlags(flags, flagList, 0, indent + kStdIndent); |
} |
} |
extern void FPFlags( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
{ |
assert( FPStandardPreCondition() ); |
assert(info != NULL); |
FPFlagsCore(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, NULL, (const FPFlagDesc *) info); |
} |
extern void FPFlagsBE( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
{ |
assert( FPStandardPreCondition() ); |
assert(info != NULL); |
FPFlagsCore(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, (const void *) (uintptr_t) kFPValueBigEndian, (const FPFlagDesc *) info); |
} |
extern void FPVerboseFlags( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Just like FPFlags except that the full dump of |
// all the flags is only printed if we're in really verbose mode. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
assert( FPStandardPreCondition() ); |
assert(info != NULL); |
if (verbose > 0) { |
verbose -= 1; |
} |
FPFlags(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info); |
} |
extern void FPUTCDateTime( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a UTCDateTime field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
static CFDateFormatterRef sFormatter; |
static CFLocaleRef sLocale; |
const UTCDateTime * dateTime; |
CFStringRef dateTimeStr; |
CFAbsoluteTime absoluteTime; |
Boolean success; |
static char dateTimeBuf[1024]; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(UTCDateTime)); |
dateTime = (const UTCDateTime *) fieldPtr; |
dateTimeStr = NULL; |
success = false; |
// Create the statics if they haven't been initialised yet. |
if (sLocale == NULL) { |
sLocale = CFLocaleCopyCurrent(); |
} |
if ( (sLocale != NULL) && (sFormatter == NULL) ) { |
sFormatter = CFDateFormatterCreate(NULL, sLocale, kCFDateFormatterFullStyle, kCFDateFormatterFullStyle); |
} |
// Convert dateTime to a C string using the formatter, defaulting to "???" if |
// something goes wrong. |
success = (UCConvertUTCDateTimeToCFAbsoluteTime(dateTime, &absoluteTime) == noErr); |
if ( (sFormatter != NULL) && success ) { |
dateTimeStr = CFDateFormatterCreateStringWithAbsoluteTime(NULL, sFormatter, absoluteTime); |
} |
if (dateTimeStr != NULL) { |
success = CFStringGetCString(dateTimeStr, dateTimeBuf, sizeof(dateTimeBuf), kCFStringEncodingUTF8); |
} |
if ( ! success ) { |
strcpy(dateTimeBuf, "???"); |
} |
fprintf(stdout, "%*s%-*s = %" PRIu16 ".%" PRIu32 ".%" PRIu16 " (%s)\n", |
(int) indent, "", |
(int) nameWidth, fieldName, |
dateTime->highSeconds, |
(uint32_t) dateTime->lowSeconds, |
dateTime->fraction, |
dateTimeBuf |
); |
// Clean up. We don't release the statics (sLocale and sFormatter); rather, we |
// cache them for the next time we're called. |
if (dateTimeStr != NULL) { |
CFRelease(dateTimeStr); |
} |
} |
extern void FPTimeSpec( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
// Prints a timespec field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
size_t junkSize; |
const struct timespec * timeSpec; |
char timeBuf[256]; |
#pragma unused(fieldSize) |
#pragma unused(verbose) |
#pragma unused(info) |
assert( FPStandardPreCondition() ); |
assert(fieldSize == sizeof(struct timespec)); |
timeSpec = (const struct timespec *) fieldPtr; |
junkSize = strftime(timeBuf, sizeof(timeBuf), "%c", gmtime(&timeSpec->tv_sec)); |
assert(junkSize > 0); |
fprintf(stdout, "%*s%-*s = %ld.%ld (%s)\n", |
(int) indent, "", (int) nameWidth, |
fieldName, |
timeSpec->tv_sec, |
timeSpec->tv_nsec, |
timeBuf |
); |
} |
static const FPFlagDesc kFinderFlags[] = { |
{kIsOnDesk, "kIsOnDesk"}, |
{kIsShared, "kIsShared"}, |
{kHasNoINITs, "kHasNoINITs"}, |
{kHasBeenInited, "kHasBeenInited"}, |
{kHasCustomIcon, "kHasCustomIcon"}, |
{kIsStationery, "kIsStationery"}, |
{kNameLocked, "kNameLocked"}, |
{kHasBundle, "kHasBundle"}, |
{kIsInvisible, "kIsInvisible"}, |
{kIsShared, "kIsShared"}, |
{kIsAlias, "kIsAlias"}, |
{ 0, NULL } |
}; |
static const FPFlagDesc kExtendedFinderFlags[] = { |
{kExtendedFlagsAreInvalid, "kExtendedFlagsAreInvalid"}, |
{kExtendedFlagHasCustomBadge, "kExtendedFlagHasCustomBadge"}, |
{kExtendedFlagObjectIsBusy, "kExtendedFlagObjectIsBusy"}, |
{kExtendedFlagHasRoutingInfo, "kExtendedFlagHasRoutingInfo"}, |
{ 0, NULL } |
}; |
static const FPFieldDesc kFileInfoFieldDesc[] = { |
{"fileType", offsetof(FileInfo, fileType), sizeof(OSType), FPSignature, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"fileCreator", offsetof(FileInfo, fileCreator), sizeof(OSType), FPSignature, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"finderFlags", offsetof(FileInfo, finderFlags), sizeof(UInt16), FPFlags, kFinderFlags}, |
{"location.v", offsetof(FileInfo, location.v), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"location.h", offsetof(FileInfo, location.h), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"reservedField", offsetof(FileInfo, reservedField), sizeof(UInt16), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{NULL, 0, 0, NULL, NULL} |
}; |
static const FPFieldDesc kExtendedFileInfoFieldDesc[] = { |
{"reserved1[1]", offsetof(ExtendedFileInfo, reserved1[0]), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"reserved1[2]", offsetof(ExtendedFileInfo, reserved1[1]), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"reserved1[3]", offsetof(ExtendedFileInfo, reserved1[2]), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"reserved1[4]", offsetof(ExtendedFileInfo, reserved1[3]), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"extendedFinderFlags", offsetof(ExtendedFileInfo, extendedFinderFlags), sizeof(UInt16), FPFlags, kExtendedFinderFlags}, |
{"reserved2", offsetof(ExtendedFileInfo, reserved2), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"putAwayFolderID", offsetof(ExtendedFileInfo, putAwayFolderID), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{NULL, 0, 0, NULL, NULL} |
}; |
static const FPFieldDesc kFolderInfoFieldDesc[] = { |
{"windowBounds.top", offsetof(FolderInfo, windowBounds.top), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"windowBounds.left", offsetof(FolderInfo, windowBounds.left), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"windowBounds.bottom", offsetof(FolderInfo, windowBounds.bottom), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"windowBounds.right", offsetof(FolderInfo, windowBounds.right), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"finderFlags", offsetof(FolderInfo, finderFlags), sizeof(UInt16), FPFlags, kFinderFlags}, |
{"location.v", offsetof(FolderInfo, location.v), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"location.h", offsetof(FolderInfo, location.h), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"reservedField", offsetof(FolderInfo, reservedField), sizeof(UInt16), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{NULL, 0, 0, NULL, NULL} |
}; |
static const FPFieldDesc kExtendedFolderInfoFieldDesc[] = { |
{"scrollPosition.v", offsetof(ExtendedFolderInfo, scrollPosition.v), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"scrollPosition.h", offsetof(ExtendedFolderInfo, scrollPosition.h), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"reserved1", offsetof(ExtendedFolderInfo, reserved1), sizeof(SInt32), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"extendedFinderFlags", offsetof(ExtendedFolderInfo, extendedFinderFlags), sizeof(UInt16), FPFlags, kExtendedFinderFlags}, |
{"reserved2", offsetof(ExtendedFolderInfo, reserved2), sizeof(SInt16), FPSDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{"putAwayFolderID", offsetof(ExtendedFolderInfo, putAwayFolderID), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, |
{NULL, 0, 0, NULL, NULL} |
}; |
static const FPFieldDesc kVolumeFinderInfoFieldDesc[] = { |
{"finderInfo[0]", 0 * sizeof(UInt32), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, // dirID of active System Folder |
{"finderInfo[1]", 1 * sizeof(UInt32), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, // dirID of startup application, obsolete |
{"finderInfo[2]", 2 * sizeof(UInt32), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, // dirID of first open Finder window, mostly obsolete |
{"finderInfo[3]", 3 * sizeof(UInt32), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, // dirID of traditional Mac OS System Folder |
{"finderInfo[4]", 4 * sizeof(UInt32), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, // reserved |
{"finderInfo[5]", 5 * sizeof(UInt32), sizeof(UInt32), FPUDec, (const void *) (uintptr_t) kFPValueHostEndian}, // dirID of Mac OS X System Folder |
{"finderInfo[6:7]", 6 * sizeof(UInt32), sizeof(UInt64), FPHex, (const void *) (uintptr_t) kFPValueHostEndian}, // GUID |
{NULL, 0, 0, NULL, NULL} |
}; |
static void FPFinderInfoCore( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info, |
FPEndian endian |
) |
// Prints a Finder info field. |
// |
// See definition of FPPrinter for a parameter description. |
{ |
const uint32_t * finderInfo; |
assert( FPStandardPreCondition() ); |
assert( (fieldSize == 32) || (fieldSize == 16) ); |
if (verbose == 0) { |
FPHex(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info); |
} else { |
FinderInfoFlavour flavour; |
fprintf(stdout, "%*s%s:\n", (int) indent, "", fieldName); |
flavour = (FinderInfoFlavour) (uintptr_t) info; |
switch (flavour) { |
case kVolumeInfo: |
assert(fieldSize == 32); |
finderInfo = (const uint32_t *) fieldPtr; |
FPPrintFieldsCore(kVolumeFinderInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
case kFileInfo: |
assert(fieldSize == 16); |
FPPrintFieldsCore(kFileInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
case kFileInfoExtended: |
assert(fieldSize == 16); |
FPPrintFieldsCore(kExtendedFileInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
case kFileInfoCombined: |
assert(fieldSize == 32); |
FPPrintFieldsCore(kFileInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
FPPrintFieldsCore(kExtendedFileInfoFieldDesc, ((const char *) fieldPtr) + 16, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
case kFolderInfo: |
assert(fieldSize == 16); |
FPPrintFieldsCore(kFolderInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
case kFolderInfoExtended: |
assert(fieldSize == 16); |
FPPrintFieldsCore(kExtendedFolderInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
case kFolderInfoCombined: |
assert(fieldSize == 32); |
FPPrintFieldsCore(kFolderInfoFieldDesc, fieldPtr, fieldSize, indent + kStdIndent, verbose - 1, endian); |
FPPrintFieldsCore(kExtendedFolderInfoFieldDesc, ((const char *) fieldPtr) + 16, fieldSize, indent + kStdIndent, verbose - 1, endian); |
break; |
default: |
assert(false); |
break; |
} |
} |
} |
extern void FPFinderInfo( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
{ |
FPFinderInfoCore(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info, kFPValueHostEndian); |
} |
extern void FPFinderInfoBE( |
const char * fieldName, |
size_t fieldSize, |
const void * fieldPtr, |
uint32_t indent, |
size_t nameWidth, |
uint32_t verbose, |
const void * info |
) |
{ |
FPFinderInfoCore(fieldName, fieldSize, fieldPtr, indent, nameWidth, verbose, info, kFPValueBigEndian); |
} |
Copyright © 2008 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2008-02-25