* Copyright (c) 2000-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
- *
+ *
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifdef KERNEL
#include <libkern/OSKextLibPrivate.h>
#define VERS_MAJOR_DIGITS (4)
-#define VERS_MINOR_DIGITS (2)
-#define VERS_REVISION_DIGITS (2)
+#define VERS_MINOR_DIGITS (4)
+#define VERS_REVISION_DIGITS (4)
#define VERS_STAGE_DIGITS (1)
#define VERS_STAGE_LEVEL_DIGITS (3)
#define VERS_MAJOR_MAX (9999)
#define VERS_STAGE_LEVEL_MAX (255)
-#define VERS_MAJOR_MULT (100000000)
-#define VERS_MINOR_MULT (1000000)
-#define VERS_REVISION_MULT (10000)
-#define VERS_STAGE_MULT (1000)
+#define VERS_MAJOR_MULT (1000000000000)
+#define VERS_MINOR_MULT (100000000)
+#define VERS_REVISION_MULT (10000)
+#define VERS_STAGE_MULT (1000)
typedef enum {
- kOSKextVersionStageInvalid = 0,
- kOSKextVersionStageDevelopment = 1,
- kOSKextVersionStageAlpha = 3,
- kOSKextVersionStageBeta = 5,
- kOSKextVersionStageCandidate = 7,
- kOSKextVersionStageRelease = 9,
+ kOSKextVersionStageInvalid = 0,
+ kOSKextVersionStageDevelopment = 1,
+ kOSKextVersionStageAlpha = 3,
+ kOSKextVersionStageBeta = 5,
+ kOSKextVersionStageCandidate = 7,
+ kOSKextVersionStageRelease = 9,
} OSKextVersionStage;
/*********************************************************************
*********************************************************************/
-static int __vers_isdigit(char c) {
- return (c == '0' ||
- c == '1' || c == '2' || c == '3' ||
- c == '4' || c == '5' || c == '6' ||
- c == '7' || c == '8' || c == '9');
+static int
+__vers_isdigit(char c)
+{
+ return c == '0' ||
+ c == '1' || c == '2' || c == '3' ||
+ c == '4' || c == '5' || c == '6' ||
+ c == '7' || c == '8' || c == '9';
}
/*********************************************************************
*********************************************************************/
-static int __vers_isspace(char c) {
- return (c == ' ' ||
- c == '\t' ||
- c == '\r' ||
- c == '\n');
+static int
+__vers_isspace(char c)
+{
+ return c == ' ' ||
+ c == '\t' ||
+ c == '\r' ||
+ c == '\n';
}
/*********************************************************************
*********************************************************************/
static int
-__vers_digit_for_char(char c) {
+__vers_digit_for_char(char c)
+{
switch (c) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- default: return -1;
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ default: return -1;
}
}
/*********************************************************************
*********************************************************************/
-static int __VERS_isreleasestate(char c) {
- return (c == 'd' || c == 'a' || c == 'b' || c == 'f');
+static int
+__VERS_isreleasestate(char c)
+{
+ return c == 'd' || c == 'a' || c == 'b' || c == 'f';
}
/*********************************************************************
*********************************************************************/
-static OSKextVersionStage __OSKextVersionStageForString(const char ** string_p) {
- const char * string;
-
- if (!string_p || !*string_p) {
- return kOSKextVersionStageInvalid;
- }
-
- string = *string_p;
-
- if (__vers_isspace(string[0]) || string[0] == '\0') {
- return kOSKextVersionStageRelease;
- } else {
- switch (string[0]) {
- case 'd':
- if (__vers_isdigit(string[1])) {
- *string_p = &string[1];
- return kOSKextVersionStageDevelopment;
- }
- break;
- case 'a':
- if (__vers_isdigit(string[1])) {
- *string_p = &string[1];
- return kOSKextVersionStageAlpha;
- }
- break;
- case 'b':
- if (__vers_isdigit(string[1])) {
- *string_p = &string[1];
- return kOSKextVersionStageBeta;
- }
- break;
- case 'f':
- if (__vers_isdigit(string[1])) {
- *string_p = &string[1];
- return kOSKextVersionStageCandidate;
- } else if (string[1] == 'c' && __vers_isdigit(string[2])) {
- *string_p = &string[2];
- return kOSKextVersionStageCandidate;
- } else {
- return kOSKextVersionStageInvalid;
- }
- default:
- return kOSKextVersionStageInvalid;
- }
- }
-
- return kOSKextVersionStageInvalid;
+static OSKextVersionStage
+__OSKextVersionStageForString(const char ** string_p)
+{
+ const char * string;
+
+ if (!string_p || !*string_p) {
+ return kOSKextVersionStageInvalid;
+ }
+
+ string = *string_p;
+
+ if (__vers_isspace(string[0]) || string[0] == '\0') {
+ return kOSKextVersionStageRelease;
+ } else {
+ switch (string[0]) {
+ case 'd':
+ if (__vers_isdigit(string[1])) {
+ *string_p = &string[1];
+ return kOSKextVersionStageDevelopment;
+ }
+ break;
+ case 'a':
+ if (__vers_isdigit(string[1])) {
+ *string_p = &string[1];
+ return kOSKextVersionStageAlpha;
+ }
+ break;
+ case 'b':
+ if (__vers_isdigit(string[1])) {
+ *string_p = &string[1];
+ return kOSKextVersionStageBeta;
+ }
+ break;
+ case 'f':
+ if (__vers_isdigit(string[1])) {
+ *string_p = &string[1];
+ return kOSKextVersionStageCandidate;
+ } else if (string[1] == 'c' && __vers_isdigit(string[2])) {
+ *string_p = &string[2];
+ return kOSKextVersionStageCandidate;
+ } else {
+ return kOSKextVersionStageInvalid;
+ }
+ default:
+ return kOSKextVersionStageInvalid;
+ }
+ }
+
+ return kOSKextVersionStageInvalid;
}
/*********************************************************************
*********************************************************************/
static const char *
-__OSKextVersionStringForStage(OSKextVersionStage stage)
+__OSKextVersionStringForStage(OSKextVersion stage)
{
switch (stage) {
- case kOSKextVersionStageInvalid: return NULL;
- case kOSKextVersionStageDevelopment: return "d";
- case kOSKextVersionStageAlpha: return "a";
- case kOSKextVersionStageBeta: return "b";
- case kOSKextVersionStageCandidate: return "f";
- case kOSKextVersionStageRelease: return "";
+ default:
+ OS_FALLTHROUGH;
+ case kOSKextVersionStageInvalid: return NULL;
+ case kOSKextVersionStageDevelopment: return "d";
+ case kOSKextVersionStageAlpha: return "a";
+ case kOSKextVersionStageBeta: return "b";
+ case kOSKextVersionStageCandidate: return "f";
+ case kOSKextVersionStageRelease: return "";
}
}
/*********************************************************************
*********************************************************************/
-OSKextVersion OSKextParseVersionString(const char * versionString)
+OSKextVersion
+OSKextParseVersionString(const char * versionString)
{
- OSKextVersion result = -1;
- int vers_digit = -1;
- int num_digits_scanned = 0;
- OSKextVersion vers_major = 0;
- OSKextVersion vers_minor = 0;
- OSKextVersion vers_revision = 0;
- OSKextVersion vers_stage = 0;
- OSKextVersion vers_stage_level = 0;
- const char * current_char_p;
-
- if (!versionString || *versionString == '\0') {
- return -1;
- }
-
- current_char_p = (const char *)&versionString[0];
-
- /*****
- * Check for an initial digit of the major release number.
- */
- vers_major = __vers_digit_for_char(*current_char_p);
- if (vers_major < 0) {
- return -1;
- }
-
- current_char_p++;
- num_digits_scanned = 1;
-
- /* Complete scan for major version number. Legal characters are
- * any digit, period, any buildstage letter.
- */
- while (num_digits_scanned < VERS_MAJOR_DIGITS) {
- if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
- vers_stage = kOSKextVersionStageRelease;
- goto finish;
- } else if (__vers_isdigit(*current_char_p)) {
- vers_digit = __vers_digit_for_char(*current_char_p);
- if (vers_digit < 0) {
- return -1;
- }
- vers_major = (vers_major) * 10 + vers_digit;
- current_char_p++;
- num_digits_scanned++;
- } else if (__VERS_isreleasestate(*current_char_p)) {
- goto release_state;
- } else if (*current_char_p == '.') {
- current_char_p++;
- goto minor_version;
- } else {
- return -1;
- }
- }
-
- /* Check for too many digits.
- */
- if (num_digits_scanned == VERS_MAJOR_DIGITS) {
- if (*current_char_p == '.') {
- current_char_p++;
- } else if (__vers_isdigit(*current_char_p)) {
- return -1;
- }
- }
+ OSKextVersion result = -1;
+ int vers_digit = -1;
+ int num_digits_scanned = 0;
+ OSKextVersion vers_major = 0;
+ OSKextVersion vers_minor = 0;
+ OSKextVersion vers_revision = 0;
+ OSKextVersionStage vers_stage = 0;
+ OSKextVersion vers_stage_level = 0;
+ const char * current_char_p;
+
+ if (!versionString || *versionString == '\0') {
+ return -1;
+ }
+
+ current_char_p = (const char *)&versionString[0];
+
+ /*****
+ * Check for an initial digit of the major release number.
+ */
+ vers_major = __vers_digit_for_char(*current_char_p);
+ if (vers_major < 0) {
+ return -1;
+ }
+
+ current_char_p++;
+ num_digits_scanned = 1;
+
+ /* Complete scan for major version number. Legal characters are
+ * any digit, period, any buildstage letter.
+ */
+ while (num_digits_scanned < VERS_MAJOR_DIGITS) {
+ if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
+ vers_stage = kOSKextVersionStageRelease;
+ goto finish;
+ } else if (__vers_isdigit(*current_char_p)) {
+ vers_digit = __vers_digit_for_char(*current_char_p);
+ if (vers_digit < 0) {
+ return -1;
+ }
+ vers_major = (vers_major) * 10 + vers_digit;
+ current_char_p++;
+ num_digits_scanned++;
+ } else if (__VERS_isreleasestate(*current_char_p)) {
+ goto release_state;
+ } else if (*current_char_p == '.') {
+ current_char_p++;
+ goto minor_version;
+ } else {
+ return -1;
+ }
+ }
+
+ /* Check for too many digits.
+ */
+ if (num_digits_scanned == VERS_MAJOR_DIGITS) {
+ if (*current_char_p == '.') {
+ current_char_p++;
+ } else if (__vers_isdigit(*current_char_p)) {
+ return -1;
+ }
+ }
minor_version:
- num_digits_scanned = 0;
-
- /* Scan for minor version number. Legal characters are
- * any digit, period, any buildstage letter.
- */
- while (num_digits_scanned < VERS_MINOR_DIGITS) {
- if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
- vers_stage = kOSKextVersionStageRelease;
- goto finish;
- } else if (__vers_isdigit(*current_char_p)) {
- vers_digit = __vers_digit_for_char(*current_char_p);
- if (vers_digit < 0) {
- return -1;
- }
- vers_minor = (vers_minor) * 10 + vers_digit;
- current_char_p++;
- num_digits_scanned++;
- } else if (__VERS_isreleasestate(*current_char_p)) {
- goto release_state;
- } else if (*current_char_p == '.') {
- current_char_p++;
- goto revision;
- } else {
- return -1;
- }
- }
-
- /* Check for too many digits.
- */
- if (num_digits_scanned == VERS_MINOR_DIGITS) {
- if (*current_char_p == '.') {
- current_char_p++;
- } else if (__vers_isdigit(*current_char_p)) {
- return -1;
- }
- }
+ num_digits_scanned = 0;
+
+ /* Scan for minor version number. Legal characters are
+ * any digit, period, any buildstage letter.
+ */
+ while (num_digits_scanned < VERS_MINOR_DIGITS) {
+ if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
+ vers_stage = kOSKextVersionStageRelease;
+ goto finish;
+ } else if (__vers_isdigit(*current_char_p)) {
+ vers_digit = __vers_digit_for_char(*current_char_p);
+ if (vers_digit < 0) {
+ return -1;
+ }
+ vers_minor = (vers_minor) * 10 + vers_digit;
+ current_char_p++;
+ num_digits_scanned++;
+ } else if (__VERS_isreleasestate(*current_char_p)) {
+ goto release_state;
+ } else if (*current_char_p == '.') {
+ current_char_p++;
+ goto revision;
+ } else {
+ return -1;
+ }
+ }
+
+ /* Check for too many digits.
+ */
+ if (num_digits_scanned == VERS_MINOR_DIGITS) {
+ if (*current_char_p == '.') {
+ current_char_p++;
+ } else if (__vers_isdigit(*current_char_p)) {
+ return -1;
+ }
+ }
revision:
- num_digits_scanned = 0;
-
- /* Scan for revision version number. Legal characters are
- * any digit, any buildstage letter (NOT PERIOD).
- */
- while (num_digits_scanned < VERS_REVISION_DIGITS) {
- if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
- vers_stage = kOSKextVersionStageRelease;
- goto finish;
- } else if (__vers_isdigit(*current_char_p)) {
- vers_digit = __vers_digit_for_char(*current_char_p);
- if (vers_digit < 0) {
- return -1;
- }
- vers_revision = (vers_revision) * 10 + vers_digit;
- current_char_p++;
- num_digits_scanned++;
- } else if (__VERS_isreleasestate(*current_char_p)) {
- goto release_state;
- } else {
- return -1;
- }
- }
-
- /* Check for too many digits.
- */
- if (num_digits_scanned == VERS_REVISION_DIGITS) {
- if (*current_char_p == '.') {
- current_char_p++;
- } else if (__vers_isdigit(*current_char_p)) {
- return -1;
- }
- }
+ num_digits_scanned = 0;
+
+ /* Scan for revision version number. Legal characters are
+ * any digit, any buildstage letter (NOT PERIOD).
+ */
+ while (num_digits_scanned < VERS_REVISION_DIGITS) {
+ if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
+ vers_stage = kOSKextVersionStageRelease;
+ goto finish;
+ } else if (__vers_isdigit(*current_char_p)) {
+ vers_digit = __vers_digit_for_char(*current_char_p);
+ if (vers_digit < 0) {
+ return -1;
+ }
+ vers_revision = (vers_revision) * 10 + vers_digit;
+ current_char_p++;
+ num_digits_scanned++;
+ } else if (__VERS_isreleasestate(*current_char_p)) {
+ goto release_state;
+ } else {
+ return -1;
+ }
+ }
+
+ /* Check for too many digits.
+ */
+ if (num_digits_scanned == VERS_REVISION_DIGITS) {
+ if (*current_char_p == '.') {
+ current_char_p++;
+ } else if (__vers_isdigit(*current_char_p)) {
+ return -1;
+ }
+ }
release_state:
- /*****
- * Check for the release state.
- */
- if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
- vers_stage = kOSKextVersionStageRelease;
- goto finish;
- } else {
- vers_stage = __OSKextVersionStageForString(¤t_char_p);
- if (vers_stage == kOSKextVersionStageInvalid) {
- return -1;
- }
- }
+ /*****
+ * Check for the release state.
+ */
+ if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
+ vers_stage = kOSKextVersionStageRelease;
+ goto finish;
+ } else {
+ vers_stage = __OSKextVersionStageForString(¤t_char_p);
+ if (vers_stage == kOSKextVersionStageInvalid) {
+ return -1;
+ }
+ }
// stage level
- num_digits_scanned = 0;
-
- /* Scan for stage level number. Legal characters are
- * any digit only.
- */
- while (num_digits_scanned < VERS_STAGE_LEVEL_DIGITS) {
- if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
- if (num_digits_scanned) {
- goto finish;
- } else {
- return -1;
- }
- } else if (__vers_isdigit(*current_char_p)) {
- vers_digit = __vers_digit_for_char(*current_char_p);
- if (vers_digit < 0) {
- return -1;
- }
- vers_stage_level = (vers_stage_level) * 10 + vers_digit;
- current_char_p++;
- num_digits_scanned++;
- } else {
- return -1;
- }
- }
-
- /* Check for too many digits.
- */
- if ((num_digits_scanned == VERS_STAGE_LEVEL_DIGITS) &&
- ! (__vers_isspace(*current_char_p) || (*current_char_p == '\0'))) {
-
- return -1;
- }
-
- if (vers_stage_level > VERS_STAGE_LEVEL_MAX) {
- return -1;
- }
+ num_digits_scanned = 0;
+
+ /* Scan for stage level number. Legal characters are
+ * any digit only.
+ */
+ while (num_digits_scanned < VERS_STAGE_LEVEL_DIGITS) {
+ if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
+ if (num_digits_scanned) {
+ goto finish;
+ } else {
+ return -1;
+ }
+ } else if (__vers_isdigit(*current_char_p)) {
+ vers_digit = __vers_digit_for_char(*current_char_p);
+ if (vers_digit < 0) {
+ return -1;
+ }
+ vers_stage_level = (vers_stage_level) * 10 + vers_digit;
+ current_char_p++;
+ num_digits_scanned++;
+ } else {
+ return -1;
+ }
+ }
+
+ /* Check for too many digits.
+ */
+ if ((num_digits_scanned == VERS_STAGE_LEVEL_DIGITS) &&
+ !(__vers_isspace(*current_char_p) || (*current_char_p == '\0'))) {
+ return -1;
+ }
+
+ if (vers_stage_level > VERS_STAGE_LEVEL_MAX) {
+ return -1;
+ }
finish:
- if (vers_stage == kOSKextVersionStageCandidate && vers_stage_level == 0) {
- return -1;
- }
+ if (vers_stage == kOSKextVersionStageCandidate && vers_stage_level == 0) {
+ return -1;
+ }
- result = (vers_major * VERS_MAJOR_MULT) +
- (vers_minor * VERS_MINOR_MULT) +
- (vers_revision * VERS_REVISION_MULT) +
- (vers_stage * VERS_STAGE_MULT) +
- vers_stage_level;
+ result = (vers_major * VERS_MAJOR_MULT) +
+ (vers_minor * VERS_MINOR_MULT) +
+ (vers_revision * VERS_REVISION_MULT) +
+ (vers_stage * VERS_STAGE_MULT) +
+ vers_stage_level;
- return result;
+ return result;
}
/*********************************************************************
* This function must be safe to call in panic context.
*********************************************************************/
-Boolean OSKextVersionGetString(
- OSKextVersion aVersion,
- char * buffer,
- uint32_t bufferLength)
+Boolean
+OSKextVersionGetString(
+ OSKextVersion aVersion,
+ char * buffer,
+ uint32_t bufferLength)
{
- int cpos = 0;
- OSKextVersion vers_major = 0;
- OSKextVersion vers_minor = 0;
- OSKextVersion vers_revision = 0;
- OSKextVersion vers_stage = 0;
- OSKextVersion vers_stage_level = 0;
- const char * stage_string = NULL; // don't free
-
- /* No buffer or length less than longest possible vers string,
- * return 0.
- */
- if (!buffer || bufferLength < kOSKextVersionMaxLength) {
- return FALSE;
- }
-
- bzero(buffer, bufferLength * sizeof(char));
-
- if (aVersion < 0) {
- strlcpy(buffer, "(invalid)", bufferLength);
- return TRUE;
- }
- if (aVersion == 0) {
- strlcpy(buffer, "(missing)", bufferLength);
- return TRUE;
- }
-
- vers_major = aVersion / VERS_MAJOR_MULT;
- if (vers_major > VERS_MAJOR_MAX) {
- strlcpy(buffer, "(invalid)", bufferLength);
- return TRUE;
- }
-
- vers_minor = aVersion - (vers_major * VERS_MAJOR_MULT);
- vers_minor /= VERS_MINOR_MULT;
-
- vers_revision = aVersion -
- ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) );
- vers_revision /= VERS_REVISION_MULT;
-
- vers_stage = aVersion -
- ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
- (vers_revision * VERS_REVISION_MULT));
- vers_stage /= VERS_STAGE_MULT;
-
- vers_stage_level = aVersion -
- ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
- (vers_revision * VERS_REVISION_MULT) + (vers_stage * VERS_STAGE_MULT));
- if (vers_stage_level > VERS_STAGE_LEVEL_MAX) {
- strlcpy(buffer, "(invalid)", bufferLength);
- return TRUE;
- }
-
- cpos = snprintf(buffer, bufferLength, "%u", (uint32_t)vers_major);
-
- /* Always include the minor version; it just looks weird without.
- */
- buffer[cpos] = '.';
- cpos++;
- cpos += snprintf(buffer+cpos, bufferLength - cpos, "%u", (uint32_t)vers_minor);
-
- /* The revision is displayed only if nonzero.
- */
- if (vers_revision) {
- buffer[cpos] = '.';
- cpos++;
- cpos += snprintf(buffer+cpos, bufferLength - cpos, "%u",
- (uint32_t)vers_revision);
- }
-
- stage_string = __OSKextVersionStringForStage(vers_stage);
- if (!stage_string) {
- strlcpy(buffer, "(invalid)", bufferLength);
- return TRUE;
- }
- if (stage_string[0]) {
- strlcat(buffer, stage_string, bufferLength);
- cpos += strlen(stage_string);
- }
-
- if (vers_stage < kOSKextVersionStageRelease) {
- snprintf(buffer+cpos, bufferLength - cpos, "%u", (uint32_t)vers_stage_level);
- }
-
- return TRUE;
+ int cpos = 0;
+ OSKextVersion vers_major = 0;
+ OSKextVersion vers_minor = 0;
+ OSKextVersion vers_revision = 0;
+ OSKextVersion vers_stage = 0;
+ OSKextVersion vers_stage_level = 0;
+ const char * stage_string = NULL;// don't free
+
+ /* No buffer or length less than longest possible vers string,
+ * return 0.
+ */
+ if (!buffer || bufferLength < kOSKextVersionMaxLength) {
+ return FALSE;
+ }
+
+ bzero(buffer, bufferLength * sizeof(char));
+
+ if (aVersion < 0) {
+ strlcpy(buffer, "(invalid)", bufferLength);
+ return TRUE;
+ }
+ if (aVersion == 0) {
+ strlcpy(buffer, "(missing)", bufferLength);
+ return TRUE;
+ }
+
+ vers_major = aVersion / VERS_MAJOR_MULT;
+ if (vers_major > VERS_MAJOR_MAX) {
+ strlcpy(buffer, "(invalid)", bufferLength);
+ return TRUE;
+ }
+
+ vers_minor = aVersion - (vers_major * VERS_MAJOR_MULT);
+ vers_minor /= VERS_MINOR_MULT;
+
+ vers_revision = aVersion -
+ ((vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT));
+ vers_revision /= VERS_REVISION_MULT;
+
+ vers_stage = aVersion -
+ ((vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
+ (vers_revision * VERS_REVISION_MULT));
+ vers_stage /= VERS_STAGE_MULT;
+
+ vers_stage_level = aVersion -
+ ((vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
+ (vers_revision * VERS_REVISION_MULT) + (vers_stage * VERS_STAGE_MULT));
+ if (vers_stage_level > VERS_STAGE_LEVEL_MAX) {
+ strlcpy(buffer, "(invalid)", bufferLength);
+ return TRUE;
+ }
+
+ cpos = scnprintf(buffer, bufferLength, "%u", (uint32_t)vers_major);
+
+ /* Always include the minor version; it just looks weird without.
+ */
+ buffer[cpos] = '.';
+ cpos++;
+ cpos += scnprintf(buffer + cpos, bufferLength - cpos, "%u", (uint32_t)vers_minor);
+
+ /* The revision is displayed only if nonzero.
+ */
+ if (vers_revision) {
+ buffer[cpos] = '.';
+ cpos++;
+ cpos += scnprintf(buffer + cpos, bufferLength - cpos, "%u",
+ (uint32_t)vers_revision);
+ }
+
+ stage_string = __OSKextVersionStringForStage(vers_stage);
+ if (!stage_string) {
+ strlcpy(buffer, "(invalid)", bufferLength);
+ return TRUE;
+ }
+ if (stage_string[0]) {
+ strlcat(buffer, stage_string, bufferLength);
+ cpos += strlen(stage_string);
+ }
+
+ if (vers_stage < kOSKextVersionStageRelease) {
+ snprintf(buffer + cpos, bufferLength - cpos, "%u", (uint32_t)vers_stage_level);
+ }
+
+ return TRUE;
}
/*********************************************************************
*********************************************************************/
#ifndef KERNEL
-OSKextVersion OSKextParseVersionCFString(CFStringRef versionString)
+OSKextVersion
+OSKextParseVersionCFString(CFStringRef versionString)
{
- OSKextVersion result = -1;
- char versBuffer[kOSKextVersionMaxLength];
-
- if (CFStringGetCString(versionString, versBuffer,
- sizeof(versBuffer), kCFStringEncodingASCII)) {
-
- result = OSKextParseVersionString(versBuffer);
- }
- return result;
+ OSKextVersion result = -1;
+ char versBuffer[kOSKextVersionMaxLength];
+
+ if (CFStringGetCString(versionString, versBuffer,
+ sizeof(versBuffer), kCFStringEncodingASCII)) {
+ result = OSKextParseVersionString(versBuffer);
+ }
+ return result;
}
#endif