From 2ae45f0c5f01821a3152c1621ed75a36ab83083c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 8 Dec 2004 03:44:30 +0000 Subject: [PATCH] Brought "addattr" command into shape, and got rid off a lot of weird stuff - and libbe.so; it now uses the attribute functions as exported by libroot.so :) Improved handling of boolean values, improved error messages a lot. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10374 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/bin/addattr/Jamfile | 7 +- src/apps/bin/addattr/addAttr.cpp | 285 +++++++++++++----------------- src/apps/bin/addattr/addAttr.h | 34 ++-- src/apps/bin/addattr/main.cpp | 254 ++++++++++++++------------ src/apps/bin/addattr/messages.cpp | 34 ---- src/apps/bin/addattr/messages.h | 18 -- 6 files changed, 275 insertions(+), 357 deletions(-) delete mode 100644 src/apps/bin/addattr/messages.cpp delete mode 100644 src/apps/bin/addattr/messages.h diff --git a/src/apps/bin/addattr/Jamfile b/src/apps/bin/addattr/Jamfile index 0d0d32119e..aa2ee60824 100644 --- a/src/apps/bin/addattr/Jamfile +++ b/src/apps/bin/addattr/Jamfile @@ -1,9 +1,6 @@ SubDir OBOS_TOP src apps bin addattr ; BinCommand addattr : - addAttr.cpp main.cpp - messages.cpp - : be -; - + addAttr.cpp + ; diff --git a/src/apps/bin/addattr/addAttr.cpp b/src/apps/bin/addattr/addAttr.cpp index fa514bfe12..0338fa18c7 100644 --- a/src/apps/bin/addattr/addAttr.cpp +++ b/src/apps/bin/addattr/addAttr.cpp @@ -1,188 +1,145 @@ -// Author: Sebastian Nozzi -// Created: 3 may 2002 +/* + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Sebastian Nozzi. + * + * Distributed under the terms of the MIT license. + */ -// Modifications: -// (please include author, date, and description) - -// mmu_man@sf.net: note the original one doesn't link to libbe - - -#include -#include -#include -#include -#include - -#include #include "addAttr.h" -#include "messages.h" -// Adds a certain attribute to many files, specified in an array -// of strings -// -// On success it will return B_OK -// On failure it returns an error code (negative number) -status_t addAttrToFiles( type_code attrType, - const char *attrName, - const char *attrValue, - char **files, - unsigned fileCount ) { +#include +#include - status_t returnCode; - status_t result; - unsigned fileIdx; +#include - returnCode = B_OK; +#include +#include +#include +#include - // Iterate through all the files and add the attribute - // to each of them - for( fileIdx = 0; fileIdx < fileCount; fileIdx++ ) { - result = addAttr( attrType, attrName, attrValue, files[fileIdx] ); - // Try to keep the first error code, if any - if( returnCode == B_OK && result != B_OK ) - returnCode = result; - } - - return returnCode; +template +ssize_t +writeAttrValue(int fd, const char *name, type_code type, Type value) +{ + ssize_t bytes = fs_write_attr(fd, name, type, 0, &value, sizeof(Type)); + if (bytes < 0) + return errno; + + return bytes; } -// Adds an attribute to a file for the given type, name and value -// Locks and unlocks the corresponding node to avoid data inconsistence -// Converts the value accordingly in case of numeric or boolean types -// -// On success it will return the amount of bytes writen -// On failure it returns an error code (negative number) -status_t addAttr( type_code attrType, - const char *attrName, - const char *attrValue, - const char *file ) { - status_t returnCode; +/** Writes an attribute to a node, taking the type into account and + * convertig the value accordingly + * + * On success it will return the amount of bytes writen + * On failure it returns an error code (negative number) + */ - BNode node; - // Traverse links - BEntry entry(file, true); - - node.SetTo(&entry); - // Release file descriptor - entry.Unset(); - -#ifdef DEBUG - printf("%lu | %s | %s | %s\n", attrType, attrName, attrValue, file ); -#endif +static ssize_t +writeAttr(int fd, type_code type, const char *name, const char *value) +{ + uint64 uint64value = 0; + int64 int64value = 0; + double floatValue = 0.0; - returnCode = node.InitCheck(); - - if( returnCode == B_OK ) { + // parse number input at once - returnCode = node.Lock(); // to avoid data inconsistency - - if( returnCode == B_OK ) { - // Only add the attribute if not already there - if( hasAttribute( &node, attrName ) == false ) { - - ssize_t bytesWrittenCode; - - // Write the attribute now - bytesWrittenCode = writeAttr( &node, attrType, attrName, attrValue ); - - // If negative, then it's an error code - if( bytesWrittenCode < 0 ) { - problemsWithFileMsg( file ); - returnCode = bytesWrittenCode; - } - } - node.Sync(); - node.Unlock(); - } else { // Node could not be locked - problemsWithFileMsg( file ); - } - } else { - // File could not be initialized - // (maybe it doesn't exist) - problemsWithFileMsg( file ); - } - - return returnCode; -} - -// Writes an attribute to a node, taking the type into account and -// convertig the value accordingly -// -// On success it will return the amount of bytes writen -// On failure it returns an error code (negative number) -ssize_t writeAttr( BNode *node, type_code attrType, - const char *attrName, const char *attrValue ) { - - int32 int32buffer = 0; - int64 int64buffer = 0; - int boolBuffer = 0; - float floatBuffer = 0.0; - double doubleBuffer = 0.0; - - ssize_t bytesWrittenOrErrorCode; - - switch( attrType ) { - case B_INT32_TYPE: - sscanf( attrValue, "%ld", &int32buffer ); - bytesWrittenOrErrorCode = - node->WriteAttr( attrName, attrType, 0, &int32buffer, sizeof(int32) ); - break; - case B_INT64_TYPE: - sscanf( attrValue, "%lld", &int64buffer ); - bytesWrittenOrErrorCode = - node->WriteAttr( attrName, attrType, 0, &int64buffer, sizeof(int64) ); - break; - case B_FLOAT_TYPE: - sscanf( attrValue, "%f", &floatBuffer ); - bytesWrittenOrErrorCode = - node->WriteAttr( attrName, attrType, 0, &floatBuffer, sizeof(float) ); - break; - case B_DOUBLE_TYPE: - sscanf( attrValue, "%lf", &doubleBuffer ); - bytesWrittenOrErrorCode = - node->WriteAttr( attrName, attrType, 0, &doubleBuffer, sizeof(double) ); - break; + switch (type) { case B_BOOL_TYPE: - // NOTE: the conversion from "int" to "signed char" might seem strange - // but this is the only way I could think to replicate Be's addattr behaviour - sscanf( attrValue, "%d", &boolBuffer ); - boolBuffer = (signed char) boolBuffer; - bytesWrittenOrErrorCode = - node->WriteAttr( attrName, attrType, 0, &boolBuffer, sizeof(signed char) ); + case B_INT8_TYPE: + case B_INT16_TYPE: + case B_INT32_TYPE: + case B_INT64_TYPE: + int64value = strtoll(value, NULL, 0); break; + + case B_UINT8_TYPE: + case B_UINT16_TYPE: + case B_UINT32_TYPE: + case B_UINT64_TYPE: + uint64value = strtoull(value, NULL, 0); + break; + + case B_FLOAT_TYPE: + case B_DOUBLE_TYPE: + floatValue = strtod(value, NULL); + break; + } + + switch (type) { + case B_INT8_TYPE: + return writeAttrValue(fd, name, type, (int8)int64value); + case B_INT16_TYPE: + return writeAttrValue(fd, name, type, (int16)int64value); + case B_INT32_TYPE: + return writeAttrValue(fd, name, type, (int32)int64value); + case B_INT64_TYPE: + return writeAttrValue(fd, name, type, int64value); + + case B_UINT8_TYPE: + return writeAttrValue(fd, name, type, (uint8)uint64value); + case B_UINT16_TYPE: + return writeAttrValue(fd, name, type, (uint16)uint64value); + case B_UINT32_TYPE: + return writeAttrValue(fd, name, type, (uint32)uint64value); + case B_UINT64_TYPE: + return writeAttrValue(fd, name, type, uint64value); + + case B_FLOAT_TYPE: + return writeAttrValue(fd, name, type, (float)floatValue); + case B_DOUBLE_TYPE: + return writeAttrValue(fd, name, type, (double)floatValue); + + case B_BOOL_TYPE: + { + uint8 boolValue = 0; + + if (!strcasecmp(value, "true") || !strcasecmp(value, "t") + || !strcasecmp(value, "on") || !strcasecmp(value, "enabled") + || (isdigit(value[0]) && int64value == 1)) + boolValue = 1; + else if (!strcasecmp(value, "false") || !strcasecmp(value, "f") + || !strcasecmp(value, "off") || !strcasecmp(value, "disabled") + || (isdigit(value[0]) && int64value == 0)) + boolValue = 0; + else + return B_BAD_VALUE; + + return writeAttrValue(fd, name, B_BOOL_TYPE, boolValue); + } + case B_STRING_TYPE: case B_MIME_STRING_TYPE: default: // For string, mime-strings and any other type we just write the value // NOTE that the trailing NULL -IS- added - bytesWrittenOrErrorCode = - node->WriteAttr( attrName, attrType, 0, attrValue, strlen(attrValue)+1 ); - break; - }; - - return bytesWrittenOrErrorCode; -} - -// Checks wether a node has an attribute under the given name or not -// -// The user is responsible for locking and unlocking the node, and -// for assuring that we are retrieving all attributes from the beginning -// by calling RewindAttrs() on the node, if necesary -bool hasAttribute( BNode *node, const char *attrName ) { - - char retrievedName[B_ATTR_NAME_LENGTH]; - bool found; - - found = false; - - while( (!found) && (node->GetNextAttrName( retrievedName )==B_OK) ) { - if( strcmp( retrievedName, attrName ) == 0 ) - found = true; + ssize_t bytes = fs_write_attr(fd, name, type, 0, value, strlen(value) + 1); + if (bytes < 0) + return errno; + return bytes; } - - return found; +} + + +/** Adds an attribute to a file for the given type, name and value + * Converts the value accordingly in case of numeric or boolean types + * + * On success, it returns B_OK, or else an appropriate error code. + */ + +status_t +addAttr(const char *file, type_code type, const char *name, const char *value) +{ + int fd = open(file, O_WRONLY); + if (fd < 0) + return errno; + + fs_remove_attr(fd, name); + ssize_t bytes = writeAttr(fd, type, name, value); + + return bytes >= 0 ? B_OK : bytes; } diff --git a/src/apps/bin/addattr/addAttr.h b/src/apps/bin/addattr/addAttr.h index 55e27ed16b..a999b95b5a 100644 --- a/src/apps/bin/addattr/addAttr.h +++ b/src/apps/bin/addattr/addAttr.h @@ -1,30 +1,16 @@ -// Author: Sebastian Nozzi -// Created: 3 may 2002 - -// Modifications: -// (please include author, date, and description) - -// mmu_man@sf.net: note the original one doesn't link to libbe - +/* + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Sebastian Nozzi. + * + * Distributed under the terms of the MIT license. + */ #ifndef _ADD_ATTR_H #define _ADD_ATTR_H -#include -status_t addAttrToFiles( type_code attrType, - const char *attrName, - const char *attrValue, - char **files, - unsigned fileCount ); +#include -status_t addAttr( type_code attrType, - const char *attrName, - const char *attrValue, - const char *file ); - -bool hasAttribute( BNode *node, const char *attrName ); -ssize_t writeAttr( BNode *node, type_code attrType, - const char *attrName, const char *attrValue ); - -#endif +status_t addAttr(const char *file, type_code attrType, const char *attrName, const char *attrValue); + +#endif /* _ADD_ATTR_H */ diff --git a/src/apps/bin/addattr/main.cpp b/src/apps/bin/addattr/main.cpp index 4835f8942d..30c4cebc26 100644 --- a/src/apps/bin/addattr/main.cpp +++ b/src/apps/bin/addattr/main.cpp @@ -1,9 +1,10 @@ +/* + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Sebastian Nozzi. + * + * Distributed under the terms of the MIT license. + */ -// Author: Sebastian Nozzi -// Created: 1st may 2002 - -// Modifications: -// (please include author, date, and description) #include #include @@ -15,122 +16,151 @@ #include "addAttr.h" #include "messages.h" -status_t typeForString( const char *attrSting, type_code *result ); -int main( int argc, char*argv[] ) +// supported types (if you add any, make sure that writeAttr() handles them properly) + +const struct { + type_code type; + const char *name; +} kSupportedTypes[] = { + {B_STRING_TYPE, "string"}, + {B_MIME_STRING_TYPE, "mime"}, + + {B_INT32_TYPE, "int32"}, + {B_INT32_TYPE, "int"}, + {B_UINT32_TYPE, "uint32"}, + {B_UINT32_TYPE, "uint"}, + + {B_INT64_TYPE, "int64"}, + {B_INT64_TYPE, "llong"}, + {B_UINT64_TYPE, "uint64"}, + {B_UINT64_TYPE, "ullong"}, + + {B_FLOAT_TYPE, "float"}, + {B_DOUBLE_TYPE, "double"}, + + {B_BOOL_TYPE, "bool"}, +}; +const uint32 kNumSupportedTypes = sizeof(kSupportedTypes) / sizeof(kSupportedTypes[0]); + +char *gProgramName; + + +/** For the given string that the user specifies as attribute type + * in the command line, this function tries to figure out the + * corresponding Be API value. + * + * On success, "result" will contain that value + * On failure, B_BAD_VALUE is returned and "result" is not modified + */ + +static status_t +typeForString(const char *string, type_code *_result) { - int returnCode; - - completeToolName = argv[0]; - returnCode = 0; + for (uint32 i = 0; i < kNumSupportedTypes; i++) { + if (!strcmp(string, kSupportedTypes[i].name)) { + *_result = kSupportedTypes[i].type; + return B_OK; + } + } - if( argc > 1 ) { - type_code attrType; - unsigned minArguments; - bool usingDefaultAttr; - bool validAttrType; - - usingDefaultAttr = true; - validAttrType = true; - minArguments = 3; - + // type didn't show up - in this case, we parse the string + // as number and use it directly as type code + + if (sscanf(string, "%lu", _result) == 1) + return B_OK; + + return B_BAD_VALUE; +} + + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-t type] attr value file1 [file2...]\n", gProgramName); + fprintf(stderr, "\tType is one of:\n"); + fprintf(stderr, "\t\tstring, mime, int, llong, float, double, bool,\n"); + fprintf(stderr, "\t\tor a numeric value (ie. 0x1234, 42, ...)\n"); + fprintf(stderr, "\tThe default is `string\'\n"); + + exit(1); +} + + +void +invalidAttrType(const char *attrTypeName) +{ + fprintf(stderr, "%s: attribute type \"%s\" is not valid\n", gProgramName, attrTypeName); + fprintf(stderr, "\tTry one of: string, mime, int, llong, float, double,\n"); + fprintf(stderr, "\t\tbool, or a numeric value (ie. 0x1234, 42, ...)\n"); + + exit(1); +} + + +void +invalidBoolValue(const char *value) +{ + fprintf(stderr, "%s: attribute value \"%s\" is not valid\n", gProgramName, value); + fprintf(stderr, "\tBool accepts: 0, f, false, disabled, off,\n"); + fprintf(stderr, "\t\t1, t, true, enabled, on\n"); + + exit(1); +} + + +int +main(int argc, char *argv[]) +{ + gProgramName = strrchr(argv[0], '/'); + if (gProgramName == NULL) + gProgramName = argv[0]; + else + gProgramName++; + + if (argc < 3 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) + usage(); + + type_code attrType = B_STRING_TYPE; + + int32 i = 2; + + if (!strcmp(argv[1], "-t")) { // Get the attribute type - if( strcmp( argv[1], "-t" ) == 0 ) { - if( argc == 2 ) { - invalidAttrMsg( "(null)" ); - validAttrType = false; - returnCode = 1; - } else if( typeForString( argv[2], &attrType ) == B_BAD_VALUE ) { - invalidAttrMsg( argv[2] ); - validAttrType = false; - returnCode = 1; - } else { - usingDefaultAttr = false; - minArguments = 5; - } - } else { - // The user didn't specify a type - // The default is 'string' - attrType = B_STRING_TYPE; - } - - if( validAttrType ) { - if( (unsigned)argc > minArguments ) { - char **files; - char *attrName; - char *attrValue; - - // The location of the rest of the argument - // varies depending on wether there was a - // "-t" switch or not - if( usingDefaultAttr ) { - attrName = argv[1]; - attrValue = argv[2]; - files = &(argv[3]); - } else { - attrName = argv[3]; - attrValue = argv[4]; - files = &(argv[5]); - } - - // Now that we gathered all the information proceed - // to add the attribute to the file(s) - addAttrToFiles( attrType, attrName, attrValue, - files, argc-minArguments ); - - } else { // some arguments are missing - usageMsg(); - returnCode = 1; - } - } - - } else { // called with no arguments - usageMsg(); - returnCode = 1; + if (typeForString(argv[2], &attrType) != B_OK) + invalidAttrType(argv[2]); + + i++; } - return returnCode; -} + const char *attrName = argv[i++]; + const char *attrValue = argv[i++]; -// For the given string that the user specifies as attribute type -// in the command line, this function tries to figure out the -// corresponding Be API value -// -// On success, "result" will contain that value -// On failure, B_BAD_VALUE is returned and "result" is not modified -status_t typeForString( const char *attrString, type_code *result ) -{ - status_t returnCode; - - returnCode = B_OK; - - if( strcmp( attrString, "string" ) == 0 ){ - *result = B_STRING_TYPE; - } else if( strcmp( attrString, "mime" ) == 0 ){ - *result = B_MIME_STRING_TYPE; - } else if( strcmp( attrString, "int" ) == 0 ) { - *result = B_INT32_TYPE; - } else if( strcmp( attrString, "llong" ) == 0 ) { - *result = B_INT64_TYPE; - } else if( strcmp( attrString, "float" ) == 0 ) { - *result = B_FLOAT_TYPE; - } else if( strcmp( attrString, "double" ) == 0 ) { - *result = B_DOUBLE_TYPE; - } else if( strcmp( attrString, "bool" ) == 0 ) { - *result = B_BOOL_TYPE; - } else { - int convertedFields; - type_code tempCode; - - convertedFields = sscanf( attrString, "%lu", &tempCode ); - - if( convertedFields > 0 ) { - *result = tempCode; - } else { - returnCode = B_BAD_VALUE; + // no files specified + if (argv[i] == NULL) + usage(); + + // Now that we gathered all the information proceed + // to add the attribute to the file(s) + + int result = 0; + + for (; i < argc; i++) { + status_t status = addAttr(argv[i], attrType, attrName, attrValue); + + // special case for bool types + if (status == B_BAD_VALUE && attrType == B_BOOL_TYPE) + invalidBoolValue(attrValue); + + if (status != B_OK) { + fprintf(stderr, "%s: can\'t add attribute to file %s: %s\n", + gProgramName, argv[i], strerror(status)); + + // proceed files, but return an error at the end + result = 1; } } - return returnCode; + return result; } diff --git a/src/apps/bin/addattr/messages.cpp b/src/apps/bin/addattr/messages.cpp deleted file mode 100644 index 22143e700f..0000000000 --- a/src/apps/bin/addattr/messages.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Author: Sebastian Nozzi -// Created: 3 may 2002 - -// Modifications: -// (please include author, date, and description) - -// mmu_man@sf.net: note the original one doesn't link to libbe - -#include - -// Keeps the complete name of this binary at run-time -// To be set at the beginning of the programm -char *completeToolName; - -// Predefined command line messages for the user - -void usageMsg() { - fprintf( stderr, "usage: %s [-t type] attr value file1 [file2...]\n", completeToolName); - fprintf( stderr, "\tType is one of:\n"); - fprintf( stderr, "\t\tstring, mime, int, llong, float, double, bool,\n"); - fprintf( stderr, "\t\tor a numeric value\n"); - fprintf( stderr, "\tThe default is `string\'\n"); -} - -void invalidAttrMsg( const char *attrTypeName ) { - fprintf( stderr, "%s: attribute type %s is not valid\n",completeToolName, attrTypeName); - fprintf( stderr, "\tTry one of: string, mime, int, llong, float, double,\n"); - fprintf( stderr, "\t\tbool, or a \n"); -} - -void problemsWithFileMsg( const char *file ) -{ - fprintf( stderr, "%s: can\'t open file %s to add attribute\n", completeToolName, file ); -} diff --git a/src/apps/bin/addattr/messages.h b/src/apps/bin/addattr/messages.h deleted file mode 100644 index 4ac4bf0767..0000000000 --- a/src/apps/bin/addattr/messages.h +++ /dev/null @@ -1,18 +0,0 @@ -// Author: Sebastian Nozzi -// Created: 3 may 2002 - -// Modifications: -// (please include author, date, and description) - -// mmu_man@sf.net: note the original one doesn't link to libbe - -#ifndef _ADDATTR_MSG_H -#define _ADDATTR_MSG_H - -extern char *completeToolName; - -void usageMsg(); -void invalidAttrMsg( const char *attrTypeName ); -void problemsWithFileMsg( const char *file ); - -#endif