diff --git a/src/bin/addattr/Jamfile b/src/bin/addattr/Jamfile index 7f5a6d1f8b..3ff4840ee3 100644 --- a/src/bin/addattr/Jamfile +++ b/src/bin/addattr/Jamfile @@ -1,6 +1,9 @@ SubDir HAIKU_TOP src bin addattr ; +SetSubDirSupportedPlatformsBeOSCompatible ; + BinCommand addattr : main.cpp addAttr.cpp + : be ; diff --git a/src/bin/addattr/addAttr.cpp b/src/bin/addattr/addAttr.cpp index 0338fa18c7..d46f451408 100644 --- a/src/bin/addattr/addAttr.cpp +++ b/src/bin/addattr/addAttr.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. * Copyright 2002, Sebastian Nozzi. * * Distributed under the terms of the MIT license. @@ -39,7 +39,7 @@ writeAttrValue(int fd, const char *name, type_code type, Type value) */ static ssize_t -writeAttr(int fd, type_code type, const char *name, const char *value) +writeAttr(int fd, type_code type, const char *name, const char *value, size_t length) { uint64 uint64value = 0; int64 int64value = 0; @@ -115,10 +115,13 @@ writeAttr(int fd, type_code type, const char *name, const char *value) 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 - ssize_t bytes = fs_write_attr(fd, name, type, 0, value, strlen(value) + 1); + // Note that the trailing NULL is added. If a length was given, we write + // the value directly, though. + ssize_t bytes = fs_write_attr(fd, name, type, 0, value, + length ? length : strlen(value) + 1); if (bytes < 0) return errno; + return bytes; } } @@ -131,14 +134,15 @@ writeAttr(int fd, type_code type, const char *name, const char *value) */ status_t -addAttr(const char *file, type_code type, const char *name, const char *value) +addAttr(const char *file, type_code type, const char *name, + const char *value, size_t length) { int fd = open(file, O_WRONLY); if (fd < 0) return errno; fs_remove_attr(fd, name); - ssize_t bytes = writeAttr(fd, type, name, value); + ssize_t bytes = writeAttr(fd, type, name, value, length); return bytes >= 0 ? B_OK : bytes; } diff --git a/src/bin/addattr/addAttr.h b/src/bin/addattr/addAttr.h index a999b95b5a..e1403ada50 100644 --- a/src/bin/addattr/addAttr.h +++ b/src/bin/addattr/addAttr.h @@ -1,5 +1,5 @@ /* - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. * Copyright 2002, Sebastian Nozzi. * * Distributed under the terms of the MIT license. @@ -11,6 +11,7 @@ #include -status_t addAttr(const char *file, type_code attrType, const char *attrName, const char *attrValue); +status_t addAttr(const char *file, type_code attrType, const char *attrName, + const char *attrValue, size_t length); #endif /* _ADD_ATTR_H */ diff --git a/src/bin/addattr/main.cpp b/src/bin/addattr/main.cpp index a8d2addb92..9ff13b09b3 100644 --- a/src/bin/addattr/main.cpp +++ b/src/bin/addattr/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. * Copyright 2002, Sebastian Nozzi. * * Distributed under the terms of the MIT license. @@ -8,8 +8,9 @@ #include "addAttr.h" -#include +#include #include +#include #include #include @@ -69,20 +70,35 @@ typeForString(const char *string, type_code *_result) if (sscanf(string, "%lu", _result) == 1) return B_OK; + uchar type[4]; + if (sscanf(string, "'%c%c%c%c'", &type[0], &type[1], &type[2], &type[3]) == 4) { + *_result = (type[0] << 24) | (type[1] << 16) | (type[2] << 8) | type[3]; + return B_OK; + } + return B_BAD_VALUE; } void -usage(void) +usage(int returnValue) { - 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"); + fprintf(stderr, "usage: %s [-t type] attr value file1 [file2...]\n" + " or: %s [-f value-from-file] [-t type] attr file1 [file2...]\n\n" + "\tType is one of:\n" + "\t\tstring, mime, int, llong, float, double, bool,\n" + "\t\tor a numeric value (ie. 0x1234, 42, 'ABCD', ...)\n" + "\tThe default is \"string\"\n", gProgramName, gProgramName); - exit(1); + exit(returnValue); +} + + +void +assertArgument(int i, int argc) +{ + if (i >= argc) + usage(1); } @@ -91,7 +107,7 @@ 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"); + fprintf(stderr, "\t\tbool, or a numeric value (ie. 0x1234, 42, 'ABCD', ...)\n"); exit(1); } @@ -117,27 +133,74 @@ main(int argc, char *argv[]) else gProgramName++; - if (argc < 3 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) - usage(); + assertArgument(1, argc); + if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) + usage(0); type_code attrType = B_STRING_TYPE; + char *attrValue = NULL; + size_t valueFileLength = 0; int32 i = 1; - if (!strcmp(argv[1], "-t")) { + if (!strcmp(argv[i], "-f")) { + // retrieve attribute value from file + BFile file; + off_t size; + assertArgument(i, argc); + status_t status = file.SetTo(argv[i + 1], B_READ_ONLY); + if (status < B_OK) { + fprintf(stderr, "%s: can't read attribute value from file %s: %s\n", + gProgramName, argv[i], strerror(status)); + + return 1; + } + + status = file.GetSize(&size); + if (status == B_OK) { + if (size > 4 * 1024 * 1024) { + fprintf(stderr, "%s: attribute value is too large: %Ld bytes\n", + gProgramName, size); + + return 1; + } + attrValue = (char *)malloc(size); + if (attrValue != NULL) + status = file.Read(attrValue, size); + else + status = B_NO_MEMORY; + } + + if (status < B_OK) { + fprintf(stderr, "%s: can't read attribute value: %s\n", + gProgramName, strerror(status)); + + return 1; + } + + valueFileLength = (size_t)size; + i += 2; + } + + assertArgument(i, argc); + if (!strcmp(argv[i], "-t")) { // Get the attribute type - if (typeForString(argv[2], &attrType) != B_OK) - invalidAttrType(argv[2]); + assertArgument(i, argc); + if (typeForString(argv[i + 1], &attrType) != B_OK) + invalidAttrType(argv[i + 1]); i += 2; } + assertArgument(i, argc); const char *attrName = argv[i++]; - const char *attrValue = argv[i++]; - // no files specified - if (argv[i] == NULL) - usage(); + assertArgument(i, argc); + if (!valueFileLength) + attrValue = argv[i++]; + + // no files specified? + assertArgument(i, argc); // Now that we gathered all the information proceed // to add the attribute to the file(s) @@ -145,14 +208,15 @@ main(int argc, char *argv[]) int result = 0; for (; i < argc; i++) { - status_t status = addAttr(argv[i], attrType, attrName, attrValue); + status_t status = addAttr(argv[i], attrType, attrName, attrValue, + valueFileLength); // 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", + 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 @@ -160,6 +224,9 @@ main(int argc, char *argv[]) } } + if (valueFileLength) + free(attrValue); + return result; }