xref: /xnu-10002.81.5/libkdd/kdd_main.m (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
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
15void usage(char *const* argv) {
16    fprintf(stderr, "usage: %s [-p] FILE\n", argv[0]);
17    exit(1);
18}
19
20int 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}
127