]>
Commit | Line | Data |
---|---|---|
39037602 A |
1 | // |
2 | // main.m | |
3 | // kdd command | |
4 | // | |
5 | // Created by Lawrence D'Anna on 11/9/15. | |
6 | // Copyright © 2015 Apple Inc. All rights reserved. | |
7 | // | |
8 | ||
9 | #import <Foundation/Foundation.h> | |
10 | #include <stdio.h> | |
11 | #include <unistd.h> | |
12 | #include <zlib.h> | |
13 | #import "kdd.h" | |
14 | ||
15 | void usage(char *const* argv) { | |
16 | fprintf(stderr, "usage: %s [-p] FILE\n", argv[0]); | |
17 | exit(1); | |
18 | } | |
19 | ||
20 | int main(int argc, char *const*argv) { | |
21 | ||
22 | int c ; | |
23 | int plist = 0; | |
24 | ||
25 | while ((c = getopt(argc, argv, "p")) != EOF) { | |
26 | switch(c) { | |
27 | case 'p': | |
28 | plist = TRUE; | |
29 | break; | |
30 | case '?': | |
31 | case 'h': | |
32 | default: | |
33 | usage(argv); | |
34 | break; | |
35 | } | |
36 | } | |
37 | ||
38 | if (optind != argc -1) { | |
39 | usage(argv); | |
40 | } | |
41 | ||
42 | NSError *error = nil; | |
43 | NSData *data; | |
44 | ||
45 | if (0 == strcmp(argv[optind], "-")) { | |
46 | data = [[NSFileHandle fileHandleWithStandardInput] readDataToEndOfFile]; | |
47 | } else { | |
48 | data = [NSData dataWithContentsOfFile:[NSString stringWithUTF8String:argv[optind]] | |
49 | options:NSDataReadingMappedIfSafe | |
50 | error:&error]; | |
51 | } | |
52 | ||
53 | if (!data || error) { | |
54 | NSLog(@"couldn't read data: %@", error); | |
55 | return 1; | |
56 | } | |
57 | ||
58 | if (data.length > UINT32_MAX) { | |
59 | NSLog(@"data too big"); | |
60 | return 1; | |
61 | } | |
62 | ||
63 | NSDictionary *dict = parseKCDataBuffer((void*)data.bytes, (uint32_t)data.length, &error); | |
64 | ||
65 | if (error && error.code == KERN_INVALID_VALUE) { | |
66 | uint8_t buffer[100]; | |
67 | z_stream stream; | |
68 | bzero(&stream, sizeof(stream)); | |
69 | stream.next_in = (void*) data.bytes; | |
70 | stream.avail_in = data.length; | |
71 | stream.next_out = buffer; | |
72 | stream.avail_out = sizeof(buffer); | |
73 | inflateInit2(&stream, 16+MAX_WBITS); | |
74 | NSMutableData *inflated = [[NSMutableData alloc] init]; | |
75 | while (1) { | |
76 | int z = inflate(&stream, Z_NO_FLUSH); | |
77 | if (z == Z_OK || z == Z_STREAM_END) { | |
78 | [inflated appendBytes:buffer length:sizeof(buffer) - stream.avail_out]; | |
79 | stream.avail_out = sizeof(buffer); | |
80 | stream.next_out = buffer; | |
81 | if (z == Z_STREAM_END) { | |
82 | break; | |
83 | } | |
84 | } else { | |
85 | inflated = nil; | |
86 | break; | |
87 | } | |
88 | } | |
89 | if (inflated) { | |
90 | error = nil; | |
91 | dict = parseKCDataBuffer((void*)inflated.bytes, (uint32_t)inflated.length, &error); | |
92 | } | |
93 | } | |
94 | ||
95 | if (error && error.code == KERN_INVALID_VALUE) { | |
96 | NSData *decoded = [[NSData alloc] initWithBase64EncodedData:data options:NSDataBase64DecodingIgnoreUnknownCharacters]; | |
97 | if (decoded) { | |
98 | error = nil; | |
99 | dict = parseKCDataBuffer((void*)decoded.bytes, (uint32_t)decoded.length, &error); | |
100 | } | |
101 | } | |
102 | ||
103 | if (!dict || error) { | |
104 | NSLog(@"error parsing kcdata: %@", error); | |
105 | return 1; | |
106 | } | |
107 | ||
108 | if (plist) { | |
109 | NSData *plist = [NSPropertyListSerialization dataWithPropertyList:dict | |
110 | format:NSPropertyListXMLFormat_v1_0 | |
111 | options:0 | |
112 | error:&error]; | |
113 | if (!plist || error) { | |
114 | NSLog(@"couldn't write plist: %@", error); | |
115 | return 1; | |
116 | } | |
117 | ||
118 | fwrite(plist.bytes, plist.length, 1, stdout); | |
119 | ||
120 | } else { | |
121 | puts([[NSString stringWithFormat: @"%@", dict] UTF8String]); | |
122 | } | |
123 | ||
124 | ||
125 | return 0; | |
126 | } |