xref: /xnu-11417.140.69/libkern/kxld/tests/kextcopyright.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 2009 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <stdio.h>
30 
31 #include <CoreFoundation/CoreFoundation.h>
32 
33 #include <kxld.h>
34 
35 #define kCFBundleGetInfoStringKey CFSTR("CFBundleGetInfoString")
36 #define kNSHumanReadableCopyrightKey CFSTR("NSHumanReadableCopyright")
37 
38 const char *gProgname = NULL;
39 
40 static void usage(void);
41 static void printFormat(void);
42 static char *convert_cfstring(CFStringRef the_string);
43 
44 /******************************************************************************
45 ******************************************************************************/
46 static void
usage(void)47 usage(void)
48 {
49 	printf("usage: %s [path to kext]\n\n"
50 	    "This program validates the copyright string in a kext's info "
51 	    "dictionary.\n\n", gProgname);
52 
53 	printFormat();
54 }
55 
56 /******************************************************************************
57 ******************************************************************************/
58 static void
printFormat(void)59 printFormat(void)
60 {
61 	fprintf(stderr,
62 	    "The copyright string should be contained in the NSHumanReadableCopyright key.\n"
63 	    "It should be of the format:\n"
64 	    "\tCopyright © [year(s) of publication] Apple Inc. All rights reserved.\n\n"
65 	    "where [year(s) of publication] is a comma-separated list of years and/or\n"
66 	    "year ranges, e.g., 2004, 2006-2008.  Years must be four digits.  Year ranges\n"
67 	    "may not contain spaces and must use four digits for both years.\n\n"
68 	    "The following are examples of valid copyright strings:\n"
69 	    "\tCopyright © 2008 Apple Inc. All rights reserved.\n"
70 	    "\tCopyright © 2004-2008 Apple Inc. All rights reserved.\n"
71 	    "\tCopyright © 1998,2000-2002,2004,2006-2008 Apple Inc. All rights reserved.\n");
72 }
73 
74 /******************************************************************************
75 ******************************************************************************/
76 char *
convert_cfstring(CFStringRef the_string)77 convert_cfstring(CFStringRef the_string)
78 {
79 	char *result = NULL;
80 	CFDataRef the_data = NULL;
81 	const UInt8 *data_bytes = NULL;
82 	char *converted_string = NULL;
83 	u_long converted_len = 0;
84 	u_long bytes_copied = 0;
85 
86 	the_data = CFStringCreateExternalRepresentation(kCFAllocatorDefault,
87 	    the_string, kCFStringEncodingUTF8, 0);
88 	if (!the_data) {
89 		fprintf(stderr, "Failed to convert string\n");
90 		goto finish;
91 	}
92 
93 	data_bytes = CFDataGetBytePtr(the_data);
94 	if (!data_bytes) {
95 		fprintf(stderr, "Failed to get converted string bytes\n");
96 		goto finish;
97 	}
98 
99 	converted_len = strlen((const char *)data_bytes) + 1; // +1 for nul
100 	converted_string = malloc(converted_len);
101 	if (!converted_string) {
102 		fprintf(stderr, "Failed to allocate memory\n");
103 		goto finish;
104 	}
105 
106 	bytes_copied = strlcpy(converted_string, (const char *) data_bytes,
107 	    converted_len) + 1; // +1 for nul
108 	if (bytes_copied != converted_len) {
109 		fprintf(stderr, "Failed to copy converted string\n");
110 		goto finish;
111 	}
112 
113 	result = converted_string;
114 finish:
115 	if (the_data) {
116 		CFRelease(the_data);
117 	}
118 	return result;
119 }
120 
121 /******************************************************************************
122 ******************************************************************************/
123 int
main(int argc,const char * argv[])124 main(int argc, const char *argv[])
125 {
126 	int result = 1;
127 	boolean_t infoCopyrightIsValid = false;
128 	boolean_t readableCopyrightIsValid = false;
129 	CFURLRef anURL = NULL;                  // must release
130 	CFBundleRef aBundle = NULL;             // must release
131 	CFDictionaryRef aDict = NULL;           // do not release
132 	CFStringRef infoCopyrightString = NULL; // do not release
133 	CFStringRef readableCopyrightString = NULL; // do not release
134 	char *infoStr = NULL;                   // must free
135 	char *readableStr = NULL;               // must free
136 
137 	gProgname = argv[0];
138 
139 	if (argc != 2) {
140 		usage();
141 		goto finish;
142 	}
143 
144 	anURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
145 	    (const UInt8 *) argv[1], strlen(argv[1]), /* isDirectory */ FALSE);
146 	if (!anURL) {
147 		fprintf(stderr, "Can't create path from %s\n", argv[1]);
148 		goto finish;
149 	}
150 
151 	aBundle = CFBundleCreate(kCFAllocatorDefault, anURL);
152 	if (!aBundle) {
153 		fprintf(stderr, "Can't create bundle at path %s\n", argv[1]);
154 		goto finish;
155 	}
156 
157 	aDict = CFBundleGetInfoDictionary(aBundle);
158 	if (!aDict) {
159 		fprintf(stderr, "Can't get info dictionary from bundle\n");
160 		goto finish;
161 	}
162 
163 	infoCopyrightString = CFDictionaryGetValue(aDict, kCFBundleGetInfoStringKey);
164 	readableCopyrightString = CFDictionaryGetValue(aDict, kNSHumanReadableCopyrightKey);
165 
166 	if (!infoCopyrightString && !readableCopyrightString) {
167 		fprintf(stderr, "This kext does not have a value for NSHumanReadableCopyright");
168 		goto finish;
169 	}
170 
171 	if (infoCopyrightString) {
172 		fprintf(stderr, "Warning: This kext has a value for CFBundleGetInfoString.\n"
173 		    "This key is obsolete, and may be removed from the kext's Info.plist.\n"
174 		    "It has been replaced by CFBundleVersion and NSHumanReadableCopyright.\n\n");
175 
176 		infoStr = convert_cfstring(infoCopyrightString);
177 		if (!infoStr) {
178 			goto finish;
179 		}
180 
181 		infoCopyrightIsValid = kxld_validate_copyright_string(infoStr);
182 	}
183 
184 	if (readableCopyrightString) {
185 		readableStr = convert_cfstring(readableCopyrightString);
186 		if (!readableStr) {
187 			goto finish;
188 		}
189 
190 		readableCopyrightIsValid = kxld_validate_copyright_string(readableStr);
191 	}
192 
193 	if (!readableCopyrightIsValid) {
194 		if (infoCopyrightIsValid) {
195 			fprintf(stderr, "Warning: The copyright string in NSHumanReadableCopyright is invalid,\n"
196 			    "but the string in CFBundleGetInfoString is valid.  CFBundleGetInfoString is\n"
197 			    "obsolete.  Please migrate your copyright string to NSHumanReadableCopyright.\n\n");
198 		} else {
199 			fprintf(stderr, "Error: There is no valid copyright string for this kext.\n\n");
200 			printFormat();
201 			goto finish;
202 		}
203 	}
204 
205 	result = 0;
206 finish:
207 	if (anURL) {
208 		CFRelease(anURL);
209 	}
210 	if (aBundle) {
211 		CFRelease(aBundle);
212 	}
213 	if (infoStr) {
214 		free(infoStr);
215 	}
216 	if (readableStr) {
217 		free(readableStr);
218 	}
219 
220 	return result;
221 }
222