btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / bin / listattr.cpp
blob00e0a19aad73480287de0c9494bcf7f9b8ed2aae
1 /*
2 * Copyright 2004-2015, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2002, Ryan Fleet.
5 * Distributed under the terms of the MIT license.
6 */
9 #include <String.h>
10 #include <TypeConstants.h>
11 #include <Mime.h>
13 #include <fs_attr.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <stdio.h>
20 /*! Dumps the contents of the attribute in the form of raw data. This view
21 is used for the type B_RAW_TYPE, for custom types and for any type that
22 is not directly supported by the utility "addattr".
24 static void
25 dump_raw_data(const char *buffer, size_t size)
27 const uint32 kChunkSize = 16;
28 uint32 dumpPosition = 0;
30 while (dumpPosition < size) {
31 // Position for this line
32 printf("\t%04" B_PRIx32 ": ", dumpPosition);
34 // Print the bytes in form of hexadecimal numbers
35 for (uint32 i = 0; i < kChunkSize; i++) {
36 if (dumpPosition + i < size) {
37 printf("%02x ", (uint8)buffer[dumpPosition + i]);
38 } else
39 printf(" ");
42 // Print the bytes in form of printable characters
43 // (whenever possible)
44 printf(" ");
45 for (uint32 i = 0; i < kChunkSize; i++) {
46 if (dumpPosition < size) {
47 char c = buffer[dumpPosition];
48 putchar(isgraph(c) ? c : '.');
49 } else
50 putchar(' ');
52 dumpPosition++;
54 printf("\n");
59 static void
60 show_attr_contents(BNode& node, const char* attribute, const attr_info& info)
62 // limit size of the attribute, only the first kLimit byte will make it on
63 // screen
64 int kLimit = 256;
65 bool cut = false;
66 off_t size = info.size;
67 if (size > kLimit) {
68 size = kLimit;
69 cut = true;
72 char buffer[kLimit];
73 ssize_t bytesRead = node.ReadAttr(attribute, info.type, 0, buffer, size);
74 if (bytesRead != size) {
75 fprintf(stderr, "Could only read %" B_PRIdOFF " bytes from attribute!\n",
76 size);
77 return;
80 switch (info.type) {
81 case B_INT8_TYPE:
82 printf("%" B_PRId8 "\n", *((int8 *)buffer));
83 break;
84 case B_UINT8_TYPE:
85 printf("%" B_PRIu8 "\n", *((uint8 *)buffer));
86 break;
87 case B_INT16_TYPE:
88 printf("%" B_PRId16 "\n", *((int16 *)buffer));
89 break;
90 case B_UINT16_TYPE:
91 printf("%" B_PRIu16 "\n", *((uint16 *)buffer));
92 break;
93 case B_INT32_TYPE:
94 printf("%" B_PRId32 "\n", *((int32 *)buffer));
95 break;
96 case B_UINT32_TYPE:
97 printf("%" B_PRIu32 "\n", *((uint32 *)buffer));
98 break;
99 case B_INT64_TYPE:
100 printf("%" B_PRId64 "\n", *((int64 *)buffer));
101 break;
102 case B_UINT64_TYPE:
103 printf("%" B_PRIu64 "\n", *((uint64 *)buffer));
104 break;
105 case B_FLOAT_TYPE:
106 printf("%f\n", *((float *)buffer));
107 break;
108 case B_DOUBLE_TYPE:
109 printf("%f\n", *((double *)buffer));
110 break;
111 case B_BOOL_TYPE:
112 printf("%d\n", *((unsigned char *)buffer));
113 break;
114 case B_TIME_TYPE:
116 char stringBuffer[256];
117 struct tm timeInfo;
118 localtime_r((time_t *)buffer, &timeInfo);
119 strftime(stringBuffer, sizeof(stringBuffer), "%c", &timeInfo);
120 printf("%s\n", stringBuffer);
121 break;
123 case B_STRING_TYPE:
124 case B_MIME_STRING_TYPE:
125 case 'MSIG':
126 case 'MSDC':
127 case 'MPTH':
128 printf("%s\n", buffer);
129 break;
131 case B_MESSAGE_TYPE:
133 BMessage message;
134 if (!cut && message.Unflatten(buffer) == B_OK) {
135 putchar('\n');
136 message.PrintToStream();
137 putchar('\n');
138 break;
140 // supposed to fall through
143 default:
144 // The rest of the attributes types are displayed as raw data
145 putchar('\n');
146 dump_raw_data(buffer, size);
147 putchar('\n');
148 break;
153 static const char *
154 get_type(type_code type)
156 static char buffer[32];
158 switch (type) {
159 case B_MIME_STRING_TYPE:
160 return "MIME String";
161 case B_RAW_TYPE:
162 return "Raw Data";
164 case B_STRING_TYPE:
165 return "Text";
166 case B_INT64_TYPE:
167 return "Int-64";
168 case B_UINT64_TYPE:
169 return "Uint-64";
170 case B_INT32_TYPE:
171 return "Int-32";
172 case B_UINT32_TYPE:
173 return "Uint-32";
174 case B_INT16_TYPE:
175 return "Int-16";
176 case B_UINT16_TYPE:
177 return "Uint-16";
178 case B_INT8_TYPE:
179 return "Int-8";
180 case B_UINT8_TYPE:
181 return "Uint-8";
182 case B_BOOL_TYPE:
183 return "Boolean";
184 case B_FLOAT_TYPE:
185 return "Float";
186 case B_DOUBLE_TYPE:
187 return "Double";
189 case B_MINI_ICON_TYPE:
190 return "Mini Icon";
191 case B_LARGE_ICON_TYPE:
192 return "Icon";
194 default:
196 int32 missed = 0, shift = 24;
197 uint8 value[4];
198 for (int32 i = 0; i < 4; i++, shift -= 8) {
199 value[i] = uint8(type >> shift);
200 if (value[i] < ' ' || value[i] > 127) {
201 value[i] = '.';
202 missed++;
206 if (missed < 2) {
207 sprintf(buffer, "'%c%c%c%c'", value[0], value[1], value[2],
208 value[3]);
209 } else
210 sprintf(buffer, "0x%08" B_PRIx32, type);
212 return buffer;
219 main(int argc, char *argv[])
221 const char *program = strrchr(argv[0], '/');
222 if (program == NULL)
223 program = argv[0];
224 else
225 program++;
227 bool printContents = false;
229 if (argc > 2 && (!strcmp(argv[1], "--long") || !strcmp(argv[1], "-l"))) {
230 printContents = true;
231 argc--;
232 argv++;
235 if (argc < 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
236 printf("usage: %s [-l|--long] 'filename' ['filename' ...]\n"
237 " -l, --long Shows the attribute contents as well.\n", program);
238 return argc == 2 ? 0 : 1;
241 off_t total = 0;
243 for (int i = 1; i < argc; ++i) {
244 BNode node(argv[i]);
246 status_t status = node.InitCheck();
247 if (status < B_OK) {
248 fprintf(stderr, "%s: initialization failed for \"%s\": %s\n",
249 program, argv[i], strerror(status));
250 return 0;
253 printf("File: %s\n", argv[i]);
255 const int kTypeWidth = 12;
256 const int kSizeWidth = 10;
257 const int kNameWidth = 36;
258 const int kContentsWidth = 21;
259 printf("%*s %*s %-*s%s\n", kTypeWidth, "Type", kSizeWidth, "Size",
260 kNameWidth, "Name", printContents ? "Contents" : "");
262 BString separator;
263 separator.SetTo('-', kTypeWidth + kSizeWidth + kNameWidth
264 + (printContents ? kContentsWidth : 0));
265 puts(separator.String());
267 char name[B_ATTR_NAME_LENGTH];
268 while (node.GetNextAttrName(name) == B_OK) {
269 attr_info attrInfo;
271 status = node.GetAttrInfo(name, &attrInfo);
272 if (status >= B_OK) {
273 printf("%*s", kTypeWidth, get_type(attrInfo.type));
274 printf("% *" B_PRId64 " ", kSizeWidth, attrInfo.size);
275 printf("\"%s\"", name);
277 if (printContents) {
278 // padding
279 int length = kNameWidth - 2 - strlen(name);
280 if (length > 0)
281 printf("%*s", length, "");
283 show_attr_contents(node, name, attrInfo);
284 } else
285 putchar('\n');
287 total += attrInfo.size;
288 } else {
289 fprintf(stderr, "%s: stat failed for \"%s\": %s\n",
290 program, name, strerror(status));
295 printf("\n%" B_PRId64 " bytes total in attributes.\n", total);
296 return 0;