Make UEFI boot-platform build again
[haiku.git] / src / bin / addattr / main.cpp
blob1f03d401933a4a204e0d5054bed276e6c2381aa0
1 /*
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.
7 */
10 #include <getopt.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
15 #include <File.h>
16 #include <Mime.h>
17 #include <TypeConstants.h>
19 #include "addAttr.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'},
28 {NULL}
32 #ifndef HAIKU_HOST_PLATFORM_SUNOS
33 extern const char *__progname;
34 #endif
35 #ifdef HAIKU_HOST_PLATFORM_SUNOS
36 static const char *kProgramName = "addattr";
37 #else
38 static const char *kProgramName = __progname;
39 #endif
42 // supported types (if you add any, make sure that writeAttr() handles
43 // them properly)
45 const struct {
46 type_code type;
47 const char *name;
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"},
70 {B_RAW_TYPE, "raw"},
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
83 static status_t
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;
89 return B_OK;
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)
97 return B_OK;
99 // if that didn't work, try the string as a char-type-code
100 // enclosed in single quotes
101 uchar type[4];
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];
104 return B_OK;
107 return B_BAD_VALUE;
111 void
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);
126 exit(returnValue);
130 void
131 invalidAttrType(const char* attrTypeName)
133 fprintf(stderr, "%s: attribute type \"%s\" is not valid\n", kProgramName,
134 attrTypeName);
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");
140 exit(1);
144 void
145 invalidTypeCode(const char* attrTypeName)
147 fprintf(stderr, "%s: attribute type code \"%s\" is not valid\n", kProgramName,
148 attrTypeName);
149 fprintf(stderr, "\tIt must be exactly four characters\n");
151 exit(1);
155 void
156 invalidBoolValue(const char* value)
158 fprintf(stderr, "%s: attribute value \"%s\" is not valid\n", kProgramName,
159 value);
160 fprintf(stderr, "\tBool accepts: 0, f, false, disabled, off,\n"
161 "\t\t1, t, true, enabled, on\n");
163 exit(1);
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;
175 int c;
176 while ((c = getopt_long(argc, argv, "hf:t:c:P", kLongOptions, NULL)) != -1) {
177 switch (c) {
178 case 0:
179 break;
180 case 'f':
182 // retrieve attribute value from file
183 BFile file;
184 off_t size;
185 status_t status = file.SetTo(optarg, B_READ_ONLY);
186 if (status < B_OK) {
187 ERR("can't read attribute value from file %s: %s\n",
188 optarg, strerror(status));
189 return 1;
192 status = file.GetSize(&size);
193 if (status == B_OK) {
194 if (size == 0) {
195 ERR_0("attribute value is empty: 0 bytes\n");
196 return 1;
198 if (size > 4 * 1024 * 1024) {
199 ERR("attribute value is too large: %" B_PRIdOFF
200 " bytes\n", size);
201 return 1;
203 attrValue = (char*)malloc(size);
204 if (attrValue != NULL)
205 status = file.Read(attrValue, size);
206 else
207 status = B_NO_MEMORY;
210 if (status < B_OK) {
211 ERR("can't read attribute value: %s\n", strerror(status));
212 return 1;
215 valueFileLength = (size_t)size;
216 break;
218 case 't':
219 // Get the attribute type
220 if (typeForString(optarg, &attrType) != B_OK)
221 invalidAttrType(optarg);
222 break;
223 case 'c':
224 if (strlen(optarg) == 4) {
225 // Get the type code directly
226 char code[] = "' '";
227 strncpy(code + 1, optarg, 4);
228 if (typeForString(code, &attrType) == B_OK)
229 break;
231 invalidTypeCode(optarg);
232 case 'P':
233 resolveLinks = false;
234 break;
235 case 'h':
236 usage(0);
237 break;
238 default:
239 usage(1);
240 break;
244 if (argc - optind < 1)
245 usage(1);
246 const char* attrName = argv[optind++];
248 if (argc - optind < 1)
249 usage(1);
250 if (!valueFileLength)
251 attrValue = argv[optind++];
253 if (argc - optind < 1)
254 usage(1);
256 // Now that we gathered all the information proceed
257 // to add the attribute to the file(s)
259 int result = 0;
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],
271 strerror(status));
273 // proceed files, but return an error at the end
274 result = 1;
278 if (valueFileLength)
279 free(attrValue);
281 return result;