2 * Copyright 2010, Alexander Shagarov, alexander.shagarov@gmail.com.
3 * Copyright 2005, Stephan Aßmus, superstippi@yellowbites.com.
4 * Copyright 2004-2010, Axel Dörfler, axeld@pinc-software.de.
5 * Copyright 2002, Sebastian Nozzi.
7 * Distributed under the terms of the MIT license.
22 #include <TypeConstants.h>
25 /*! Used to present the characters in the raw data view */
29 putchar(isgraph(c
) ? c
: '.');
33 /*! Dumps the contents of the attribute in the form of
34 raw data. This view is used for the type B_RAW_DATA_TYPE,
35 for custom types and for any type that is not directly
36 supported by the utility "addattr"
39 dumpRawData(const char *buffer
, size_t size
)
41 const uint32 kChunkSize
= 16;
42 uint32 dumpPosition
= 0;
44 while (dumpPosition
< size
) {
45 // Position for this line
46 printf("0x%06" B_PRIx32
": ", dumpPosition
);
48 // Print the bytes in form of hexadecimal numbers
49 for (uint32 i
= 0; i
< kChunkSize
; i
++) {
50 if (dumpPosition
+ i
< size
) {
51 printf("%02x ", (uint8
)buffer
[dumpPosition
+ i
]);
56 // Print the bytes in form of printable characters
57 // (whenever possible)
59 for (uint32 i
= 0; i
< kChunkSize
; i
++) {
60 if (dumpPosition
< size
)
61 putCharOrDot(buffer
[dumpPosition
]);
73 type_to_string(uint32 type
)
75 static char buffer
[32];
77 int32 missed
= 0, shift
= 24;
79 for (int32 i
= 0; i
< 4; i
++, shift
-= 8) {
80 value
[i
] = uint8(type
>> shift
);
81 if (value
[i
] < ' ' || value
[i
] > 127) {
88 sprintf(buffer
, "'%c%c%c%c'", value
[0], value
[1], value
[2],
91 sprintf(buffer
, "0x%08" B_PRIx32
, type
);
98 type_name(uint32 type
)
131 return type_to_string(type
);
137 catAttr(const char *attribute
, const char *fileName
, bool keepRaw
,
138 bool dataOnly
, bool resolveLinks
)
140 int fd
= open(fileName
, O_RDONLY
| (resolveLinks
? 0 : O_NOTRAVERSE
));
145 if (fs_stat_attr(fd
, attribute
, &info
) < 0) {
150 // limit size of the attribute, only the first 64k will make it on screen
151 off_t size
= info
.size
;
153 if (size
> 64 * 1024) {
158 char* buffer
= (char*)malloc(size
);
160 fprintf(stderr
, "Could not allocate read buffer!\n");
165 ssize_t bytesRead
= fs_read_attr(fd
, attribute
, info
.type
, 0, buffer
, size
);
172 if (bytesRead
!= size
) {
173 fprintf(stderr
, "Could only read %ld bytes from attribute!\n",
183 while (pos
< info
.size
) {
184 // write what we have read so far
185 written
= write(STDOUT_FILENO
, buffer
, bytesRead
);
186 // check for write error
187 if (written
< bytesRead
) {
189 fprintf(stderr
, "Could only write %ld bytes to stream!\n",
193 fprintf(stderr
, "Failed to write to stream: %s\n",
198 // read next chunk of data at pos
200 bytesRead
= fs_read_attr(fd
, attribute
, info
.type
, pos
, buffer
,
202 // check for read error
203 if (bytesRead
< size
&& pos
+ bytesRead
< info
.size
) {
204 if (bytesRead
>= 0) {
205 fprintf(stderr
, "Could only read %ld bytes from "
206 "attribute!\n", bytesRead
);
208 fprintf(stderr
, "Failed to read from attribute: %s\n",
209 strerror(bytesRead
));
223 printf("%s : %s : ", fileName
, type_name(info
.type
).String());
227 printf("%" B_PRId8
"\n", *((int8
*)buffer
));
230 printf("%" B_PRIu8
"\n", *((uint8
*)buffer
));
233 printf("%" B_PRId16
"\n", *((int16
*)buffer
));
236 printf("%" B_PRIu16
"\n", *((uint16
*)buffer
));
239 printf("%" B_PRId32
"\n", *((int32
*)buffer
));
242 printf("%" B_PRIu32
"\n", *((uint32
*)buffer
));
245 printf("%" B_PRId64
"\n", *((int64
*)buffer
));
248 printf("%" B_PRIu64
"\n", *((uint64
*)buffer
));
251 printf("%f\n", *((float*)buffer
));
254 printf("%f\n", *((double*)buffer
));
257 printf("%d\n", *((unsigned char*)buffer
));
260 case B_MIME_STRING_TYPE
:
264 printf("%s\n", buffer
);
270 if (!cut
&& message
.Unflatten(buffer
) == B_OK
) {
271 message
.PrintToStream();
274 // supposed to fall through
278 // The rest of the attributes types are displayed as raw data
279 dumpRawData(buffer
, size
);
290 usage(const char* program
, int returnCode
)
292 // Issue usage message
293 fprintf(returnCode
== EXIT_SUCCESS
? stdout
: stderr
,
294 "usage: %s [-P] [--raw|-r] <attribute-name> <file1> [<file2>...]\n"
295 " -P\t\tDon't resolve links\n"
296 " --raw,-r\tGet the raw data of attributes\n"
297 " --data,-d\tShow the attribute data only\n", program
);
304 main(int argc
, char *argv
[])
306 char *program
= strrchr(argv
[0], '/');
312 const struct option kLongOptions
[] = {
313 {"raw", no_argument
, NULL
, 'r'},
314 {"data", no_argument
, NULL
, 'd'},
315 {"help", no_argument
, NULL
, 'h'},
319 bool keepRaw
= false;
320 bool resolveLinks
= true;
321 bool dataOnly
= false;
324 while ((option
= getopt_long(argc
, argv
, "rdPh", kLongOptions
, NULL
))
331 resolveLinks
= false;
337 return usage(program
, EXIT_SUCCESS
);
340 return usage(program
, EXIT_FAILURE
);
344 if (optind
+ 2 > argc
)
345 return usage(program
, EXIT_FAILURE
);
348 const char* attrName
= argv
[optind
++];
350 while (optind
< argc
) {
351 const char* fileName
= argv
[optind
++];
352 status_t status
= catAttr(attrName
, fileName
, keepRaw
, dataOnly
,
354 if (status
!= B_OK
) {
355 fprintf(stderr
, "%s: \"%s\", attribute \"%s\": %s\n",
356 program
, fileName
, attrName
, strerror(status
));
361 return succeeded
!= 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;