diff --git a/src/apps/bin/catattr.cpp b/src/apps/bin/catattr.cpp new file mode 100644 index 0000000000..bcd7ce06b6 --- /dev/null +++ b/src/apps/bin/catattr.cpp @@ -0,0 +1,221 @@ + +// Author: Sebastian Nozzi +// Created: 1st may 2002 + +// Modifications: +// (please include author, date, and description) + +// mmu_man@sf.net: note the original one doesn't link to libbe or libstdc++ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +void catAttr( const char *attrName, const char *fileName ); +void dumpRawData( const char *buffer, off_t size ); +void putCharOrDot( uchar c ); + +// Used to hold argv[0] along the program +char *completeToolName; + +int main( int argc, char *argv[] ) +{ + int returnCode; + + completeToolName = argv[0]; + returnCode = 0; + + if( argc > 2 ) { + + int i; + + // Cat the attribute for every file given + for( i = 2; i < argc; i++ ) + catAttr( argv[1], argv[i] ); + + } else { + // Issue usage message + fprintf( stderr, "usage: %s attr_name file1 [file2...]\n", completeToolName ); + // Be's original version -only- returned 1 if the + // amount of parameters was wrong, not if the file + // or attribute couldn't be found (!) + // In all other cases it returned 0 + returnCode = 1; + } + + return returnCode; +} + + +void catAttr( const char *attrName, const char *fileName ) { + + BNode node; + // Traverse links + BEntry entry(fileName, true); + + node.SetTo(&entry); + // Release file descriptor, which are limited + entry.Unset(); + + if( node.InitCheck() == B_OK ){ + // I chose to lock the node just in case + // If you feel this is too protective remove it + if( node.Lock() == B_OK ) { + + attr_info attrInfo; + + if( node.GetAttrInfo( attrName, &attrInfo ) == B_OK ) { + char *rawBuffer; + + rawBuffer = (char*) malloc( attrInfo.size ); + + if( rawBuffer != NULL ) { + node.ReadAttr( attrName, attrInfo.type, 0, + rawBuffer, attrInfo.size ); + switch( attrInfo.type ) { + case B_INT32_TYPE: + printf("%s : int32 : %ld\n", fileName, *((int32*)rawBuffer) ); + break; + case B_INT64_TYPE: + printf("%s : int64 : %lld\n", fileName, *((int64*)rawBuffer) ); + break; + case B_FLOAT_TYPE: + printf("%s : float : %f\n", fileName, *((float*)rawBuffer) ); + break; + case B_DOUBLE_TYPE: + printf("%s : double : %f\n", fileName, *((double*)rawBuffer) ); + break; + case B_BOOL_TYPE: + printf("%s : bool : %d\n", fileName, *((unsigned char*)rawBuffer) ); + break; + case B_STRING_TYPE: + case B_MIME_STRING_TYPE: + printf("%s : string : %s\n", fileName, rawBuffer ); + break; + default: +#ifdef DEBUG +// This is to see the four letters that build up the attribute type +// in case you are ever unsure of what's going on +// After you got it, go and compare it against the types in +// TypeDefinitions.h + if(1){ + char x[4]; + memcpy( (void*)&x[0], (void*) &attrInfo.type, 4 ); + printf("%c%c%c%c\n",x[3],x[2],x[1],x[0]); + } +#endif + // The rest of the attributes types are displayed as raw data + // Surprisingly for me, even types like B_UINT32_TYPE or + // B_CHAR_TYPE... As of now I will implement this tool exactly + // as Be's original behaved, then we can see to change this + printf("%s : raw_data : \n", fileName ); + dumpRawData( rawBuffer, attrInfo.size ); + break; + } /* type-switch */ + free(rawBuffer); + } else { + // This message I thought myself. It doesn't correspond to Be's + // original version + fprintf( stderr, "Not enough memory to complete this operation\n" ); + } + } else { + // Although misleading, this is the message provided by Be's original + // version if the attribute could not be found + fprintf( stderr, "%s: file %s attribute %s: " + "No such file or directory\n", completeToolName, fileName, attrName ); + } + node.Unlock(); + } else { + // This message I also thought myself. It doesn't correspond to Be's + // original version + fprintf( stderr, "%s: unable lock file %s\n", completeToolName, fileName ); + } + } else { + fprintf( stderr, "%s: can\'t open file %s to cat attribute %s\n", + completeToolName, fileName, attrName ); + } +} + +// Dumps the contents of the attribute in the form of +// raw data. This view is used for the type B_RAW_DATA_TYPE, +// for custom types and for any type that is not directly +// supported by the utility "addattr" +void dumpRawData( const char *buffer, off_t size ) { + + off_t chunkEnd; + off_t dumpPosition; + off_t textPosition; + uchar c; + + chunkEnd = 0x10; + dumpPosition= 0; + + while( dumpPosition < size ) { + // Position for this line + printf( "0x%06lx: ", (unsigned long)dumpPosition ); + + textPosition = dumpPosition; + + // Print the bytes in form of hexadecimal numbers + while( dumpPosition < chunkEnd ) { + if( dumpPosition < size ){ + c = buffer[dumpPosition]; + printf( "%02x", c ); + if( dumpPosition+1 < size ) + putchar(','); + else + putchar(' '); + } else { + printf(" "); + } + dumpPosition++; + } + + // Print the bytes in form of printable characters + // (whenever possible) + printf(" \'"); + while( textPosition < chunkEnd ) { + if( textPosition < size ){ + c = buffer[textPosition]; + putCharOrDot( c ); + } else { + putchar(' '); + } + textPosition++; + } + printf("\'\n"); + + chunkEnd += 0x10; + }/* loop */ +} + +// Used to present the characters in the raw data view +void putCharOrDot( uchar c ) { +// By using this: + +// if( ! isgraph(c) ) + +// better results were archieved, the output was leaner +// but it's not the way it wokrs in Be's version. So I +// decided to let the "bug" there and maybe we can +// see what we do about it for R2 + + // Put the dot for non-printable characters + // (including and below space, which code is 32) + if( c <= ' ' ) + putchar('.'); + else + putchar(c); +} + + + +