2 * Copyright 2010, Jérôme Duval.
3 * Copyright 2004-2015, Axel Dörfler, axeld@pinc-software.de.
4 * Copyright 2002, Sebastian Nozzi.
6 * Distributed under the terms of the MIT license.
17 #include <TypeConstants.h>
22 #define ERR(msg, args...) fprintf(stderr, "%s: " msg, kProgramName, args)
23 #define ERR_0(msg) fprintf(stderr, "%s: " msg, kProgramName)
26 static struct option
const kLongOptions
[] = {
27 {"help", no_argument
, 0, 'h'},
32 #ifndef HAIKU_HOST_PLATFORM_SUNOS
33 extern const char *__progname
;
35 #ifdef HAIKU_HOST_PLATFORM_SUNOS
36 static const char *kProgramName
= "addattr";
38 static const char *kProgramName
= __progname
;
42 // supported types (if you add any, make sure that writeAttr() handles
48 } kSupportedTypes
[] = {
49 {B_STRING_TYPE
, "string"},
50 {B_MIME_STRING_TYPE
, "mime"},
52 {B_INT32_TYPE
, "int32"},
53 {B_INT32_TYPE
, "int"},
54 {B_UINT32_TYPE
, "uint32"},
55 {B_UINT32_TYPE
, "uint"},
57 {B_INT64_TYPE
, "int64"},
58 {B_INT64_TYPE
, "llong"},
59 {B_UINT64_TYPE
, "uint64"},
60 {B_UINT64_TYPE
, "ullong"},
62 {B_FLOAT_TYPE
, "float"},
63 {B_DOUBLE_TYPE
, "double"},
65 {B_BOOL_TYPE
, "bool"},
67 {B_TIME_TYPE
, "time"},
69 {B_VECTOR_ICON_TYPE
, "icon"},
72 const uint32 kNumSupportedTypes
= sizeof(kSupportedTypes
)
73 / sizeof(kSupportedTypes
[0]);
76 /*! For the given string that the user specifies as attribute type
77 in the command line, this function tries to figure out the
78 corresponding Be API value.
80 On success, "result" will contain that value
81 On failure, B_BAD_VALUE is returned and "result" is not modified
84 typeForString(const char* string
, type_code
* _result
)
86 for (uint32 i
= 0; i
< kNumSupportedTypes
; i
++) {
87 if (!strcmp(string
, kSupportedTypes
[i
].name
)) {
88 *_result
= kSupportedTypes
[i
].type
;
93 // type didn't show up - in this case, we try to parse
94 // the string as number and use it directly as type code
96 if (sscanf(string
, "%" B_SCNi32
, _result
) == 1)
99 // if that didn't work, try the string as a char-type-code
100 // enclosed in single quotes
102 if (sscanf(string
, "'%c%c%c%c'", &type
[0], &type
[1], &type
[2], &type
[3]) == 4) {
103 *_result
= (type
[0] << 24) | (type
[1] << 16) | (type
[2] << 8) | type
[3];
112 usage(int returnValue
)
114 fprintf(stderr
, "usage: %s [-t type|-c code] [ -P ] attr value file1 [file2...]\n"
115 " or: %s [-f value-from-file] [-t type|-c code] [ -P ] attr file1 [file2...]\n\n"
116 "\t-P : Don't resolve links\n"
117 "\tThe '-t' and '-c' options are alternatives; use one or the other.\n"
118 "\ttype is one of:\n"
119 "\t\tstring, mime, int, int32, uint32, llong, int64, uint64,\n"
120 "\t\tfloat, double, bool, icon, time, raw\n"
121 "\t\tor a numeric value (ie. 0x1234, 42, ...),\n"
122 "\t\tor an escape-quoted type code, eg. \\'MICN\\'\n"
123 "\tThe default is \"string\"\n"
124 "\tcode is a four-char type ID (eg. MICN)\n", kProgramName
, kProgramName
);
131 invalidAttrType(const char* attrTypeName
)
133 fprintf(stderr
, "%s: attribute type \"%s\" is not valid\n", kProgramName
,
135 fprintf(stderr
, "\tTry one of: string, mime, int, llong, float, double,\n"
136 "\t\tbool, icon, time, raw, or a numeric value (ie. 0x1234, 42, ...),\n"
137 "\t\tor a quoted type code, eg.: \\'MICN\\'\n"
138 "\t\tOr enter the actual type code with the '-c' option\n");
145 invalidTypeCode(const char* attrTypeName
)
147 fprintf(stderr
, "%s: attribute type code \"%s\" is not valid\n", kProgramName
,
149 fprintf(stderr
, "\tIt must be exactly four characters\n");
156 invalidBoolValue(const char* value
)
158 fprintf(stderr
, "%s: attribute value \"%s\" is not valid\n", kProgramName
,
160 fprintf(stderr
, "\tBool accepts: 0, f, false, disabled, off,\n"
161 "\t\t1, t, true, enabled, on\n");
168 main(int argc
, char* argv
[])
170 type_code attrType
= B_STRING_TYPE
;
171 char* attrValue
= NULL
;
172 size_t valueFileLength
= 0;
173 bool resolveLinks
= true;
176 while ((c
= getopt_long(argc
, argv
, "hf:t:c:P", kLongOptions
, NULL
)) != -1) {
182 // retrieve attribute value from file
185 status_t status
= file
.SetTo(optarg
, B_READ_ONLY
);
187 ERR("can't read attribute value from file %s: %s\n",
188 optarg
, strerror(status
));
192 status
= file
.GetSize(&size
);
193 if (status
== B_OK
) {
195 ERR_0("attribute value is empty: 0 bytes\n");
198 if (size
> 4 * 1024 * 1024) {
199 ERR("attribute value is too large: %" B_PRIdOFF
203 attrValue
= (char*)malloc(size
);
204 if (attrValue
!= NULL
)
205 status
= file
.Read(attrValue
, size
);
207 status
= B_NO_MEMORY
;
211 ERR("can't read attribute value: %s\n", strerror(status
));
215 valueFileLength
= (size_t)size
;
219 // Get the attribute type
220 if (typeForString(optarg
, &attrType
) != B_OK
)
221 invalidAttrType(optarg
);
224 if (strlen(optarg
) == 4) {
225 // Get the type code directly
227 strncpy(code
+ 1, optarg
, 4);
228 if (typeForString(code
, &attrType
) == B_OK
)
231 invalidTypeCode(optarg
);
233 resolveLinks
= false;
244 if (argc
- optind
< 1)
246 const char* attrName
= argv
[optind
++];
248 if (argc
- optind
< 1)
250 if (!valueFileLength
)
251 attrValue
= argv
[optind
++];
253 if (argc
- optind
< 1)
256 // Now that we gathered all the information proceed
257 // to add the attribute to the file(s)
261 for (; optind
< argc
; optind
++) {
262 status_t status
= addAttr(argv
[optind
], attrType
, attrName
, attrValue
,
263 valueFileLength
, resolveLinks
);
265 // special case for bool types
266 if (status
== B_BAD_VALUE
&& attrType
== B_BOOL_TYPE
)
267 invalidBoolValue(attrValue
);
269 if (status
!= B_OK
) {
270 ERR("can't add attribute to file %s: %s\n", argv
[optind
],
273 // proceed files, but return an error at the end