The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libsa/vers_rsrc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2006 Apple Computer, 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 #ifndef KERNEL
   29 #include <libc.h>
   30 #include "vers_rsrc.h"
   31 #else
   32 #include <sys/systm.h>
   33 #include <libsa/vers_rsrc.h>
   34 #endif /* not KERNEL */
   35 
   36 #ifndef KERNEL
   37 #define PRIV_EXT
   38 #else
   39 #define PRIV_EXT  __private_extern__
   40 #endif /* not KERNEL */
   41 
   42 #define VERS_MAJOR_DIGITS        (4)
   43 #define VERS_MINOR_DIGITS        (2)
   44 #define VERS_REVISION_DIGITS     (2)
   45 #define VERS_STAGE_DIGITS        (1)
   46 #define VERS_STAGE_LEVEL_DIGITS  (3)
   47 
   48 #define VERS_MAJOR_MULT    (100000000)
   49 #define VERS_MINOR_MULT      (1000000)
   50 #define VERS_REVISION_MULT     (10000)
   51 #define VERS_STAGE_MULT         (1000)
   52 
   53 typedef enum {
   54     VERS_invalid     = 0,
   55     VERS_development = 1,
   56     VERS_alpha       = 3,
   57     VERS_beta        = 5,
   58     VERS_candidate   = 7,
   59     VERS_release     = 9,
   60 } VERS_stage;
   61 
   62 
   63 static int __vers_isdigit(char c) {
   64     return (c == '' ||
   65         c == '1' || c == '2' || c == '3' ||
   66         c == '4' || c == '5' || c == '6' ||
   67         c == '7' || c == '8' || c == '9');
   68 }
   69 
   70 static int __vers_isspace(char c) {
   71     return (c == ' ' ||
   72         c == '\t' ||
   73         c == '\r' ||
   74         c == '\n');
   75 }
   76 
   77 static int __vers_digit_for_char(char c) {
   78     switch (c) {
   79       case '': return 0; break;
   80       case '1': return 1; break;
   81       case '2': return 2; break;
   82       case '3': return 3; break;
   83       case '4': return 4; break;
   84       case '5': return 5; break;
   85       case '6': return 6; break;
   86       case '7': return 7; break;
   87       case '8': return 8; break;
   88       case '9': return 9; break;
   89       default:  return -1; break;
   90     }
   91 
   92     return -1;
   93 }
   94 
   95 static int __VERS_isreleasestate(char c) {
   96     return (c == 'd' || c == 'a' || c == 'b' || c == 'f');
   97 }
   98 
   99 
  100 static VERS_stage __VERS_stage_for_string(const char ** string_p) {
  101     const char * string;
  102 
  103     if (!string_p || !*string_p) {
  104         return VERS_invalid;
  105     }
  106 
  107     string = *string_p;
  108 
  109     if (__vers_isspace(string[0]) || string[0] == '\0') {
  110         return VERS_release;
  111     } else {
  112         switch (string[0]) {
  113           case 'd':
  114               if (__vers_isdigit(string[1])) {
  115                   *string_p = &string[1];
  116                   return VERS_development;
  117               }
  118               break;
  119           case 'a':
  120               if (__vers_isdigit(string[1])) {
  121                   *string_p = &string[1];
  122                   return VERS_alpha;
  123               }
  124               break;
  125           case 'b':
  126               if (__vers_isdigit(string[1])) {
  127                   *string_p = &string[1];
  128                   return VERS_beta;
  129               }
  130               break;
  131           case 'f':
  132               if (__vers_isdigit(string[1])) {
  133                   *string_p = &string[1];
  134                   return VERS_candidate;
  135               } else if (string[1] == 'c' && __vers_isdigit(string[2])) {
  136                   *string_p = &string[2];
  137                   return VERS_candidate;
  138               } else {
  139                   return VERS_invalid;
  140               }
  141               break;
  142           default:
  143               return VERS_invalid;
  144               break;
  145         }
  146     }
  147 
  148     return VERS_invalid;
  149 }
  150 
  151 static const char * __VERS_string_for_stage(VERS_stage stage) {
  152     switch (stage) {
  153       case VERS_invalid:     return "?"; break;
  154       case VERS_development: return "d"; break;
  155       case VERS_alpha:       return "a"; break;
  156       case VERS_beta:        return "b"; break;
  157       case VERS_candidate:   return "f"; break;
  158       case VERS_release:     return ""; break;
  159     }
  160 
  161     return "?";
  162 }
  163 
  164 PRIV_EXT
  165 VERS_version VERS_parse_string(const char * vers_string) {
  166     VERS_version result = -1;
  167     int vers_digit = -1;
  168     int num_digits_scanned = 0;
  169     VERS_version vers_major = 0;
  170     VERS_version vers_minor = 0;
  171     VERS_version vers_revision = 0;
  172     VERS_version vers_stage = 0;
  173     VERS_version vers_stage_level = 0;
  174     const char * current_char_p;
  175 
  176     if (!vers_string || *vers_string == '\0') {
  177         return -1;
  178     }
  179 
  180     current_char_p = (const char *)&vers_string[0];
  181 
  182    /*****
  183     * Check for an initial digit of the major release number.
  184     */
  185     vers_major = __vers_digit_for_char(*current_char_p);
  186     if (vers_major < 0) {
  187         return -1;
  188     }
  189 
  190     current_char_p++;
  191     num_digits_scanned = 1;
  192 
  193    /* Complete scan for major version number. Legal characters are
  194     * any digit, period, any buildstage letter.
  195     */
  196     while (num_digits_scanned < VERS_MAJOR_DIGITS) {
  197         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  198             vers_stage = VERS_release;
  199             goto finish;
  200         } else if (__vers_isdigit(*current_char_p)) {
  201             vers_digit = __vers_digit_for_char(*current_char_p);
  202             if (vers_digit < 0) {
  203                 return -1;
  204             }
  205             vers_major = (vers_major) * 10 + vers_digit;
  206             current_char_p++;
  207             num_digits_scanned++;
  208         } else if (__VERS_isreleasestate(*current_char_p)) {
  209             goto release_state;
  210         } else if (*current_char_p == '.') {
  211             current_char_p++;
  212             goto minor_version;
  213         } else {
  214             return -1;
  215         }
  216     }
  217 
  218    /* Check for too many digits.
  219     */
  220     if (num_digits_scanned == VERS_MAJOR_DIGITS) {
  221          if (*current_char_p == '.') {
  222             current_char_p++;
  223         } else if (__vers_isdigit(*current_char_p)) {
  224             return -1;
  225         }
  226     }
  227 
  228 minor_version:
  229 
  230     num_digits_scanned = 0;
  231 
  232    /* Scan for minor version number. Legal characters are
  233     * any digit, period, any buildstage letter.
  234     */
  235     while (num_digits_scanned < VERS_MINOR_DIGITS) {
  236         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  237             vers_stage = VERS_release;
  238             goto finish;
  239         } else if (__vers_isdigit(*current_char_p)) {
  240             vers_digit = __vers_digit_for_char(*current_char_p);
  241             if (vers_digit < 0) {
  242                 return -1;
  243             }
  244             vers_minor = (vers_minor) * 10 + vers_digit;
  245             current_char_p++;
  246             num_digits_scanned++;
  247         } else if (__VERS_isreleasestate(*current_char_p)) {
  248             goto release_state;
  249         } else if (*current_char_p == '.') {
  250             current_char_p++;
  251             goto revision;
  252         } else {
  253             return -1;
  254         }
  255     }
  256 
  257    /* Check for too many digits.
  258     */
  259     if (num_digits_scanned == VERS_MINOR_DIGITS) {
  260          if (*current_char_p == '.') {
  261             current_char_p++;
  262         } else if (__vers_isdigit(*current_char_p)) {
  263             return -1;
  264         }
  265     }
  266 
  267 revision:
  268 
  269     num_digits_scanned = 0;
  270 
  271    /* Scan for revision version number. Legal characters are
  272     * any digit, any buildstage letter (NOT PERIOD).
  273     */
  274     while (num_digits_scanned < VERS_REVISION_DIGITS) {
  275         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  276             vers_stage = VERS_release;
  277             goto finish;
  278         } else if (__vers_isdigit(*current_char_p)) {
  279             vers_digit = __vers_digit_for_char(*current_char_p);
  280             if (vers_digit < 0) {
  281                 return -1;
  282             }
  283             vers_revision = (vers_revision) * 10 + vers_digit;
  284             current_char_p++;
  285             num_digits_scanned++;
  286         } else if (__VERS_isreleasestate(*current_char_p)) {
  287             goto release_state;
  288         } else {
  289             return -1;
  290         }
  291     }
  292 
  293    /* Check for too many digits.
  294     */
  295     if (num_digits_scanned == VERS_REVISION_DIGITS) {
  296          if (*current_char_p == '.') {
  297             current_char_p++;
  298         } else if (__vers_isdigit(*current_char_p)) {
  299             return -1;
  300         }
  301     }
  302 
  303 release_state:
  304 
  305    /*****
  306     * Check for the release state.
  307     */
  308     if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  309         vers_stage = VERS_release;
  310         goto finish;
  311     } else {
  312         vers_stage = __VERS_stage_for_string(&current_char_p);
  313         if (vers_stage == VERS_invalid) {
  314             return -1;
  315         }
  316     }
  317 
  318 
  319 // stage level
  320 
  321     num_digits_scanned = 0;
  322 
  323    /* Scan for stage level number. Legal characters are
  324     * any digit only.
  325     */
  326     while (num_digits_scanned < VERS_STAGE_LEVEL_DIGITS) {
  327         if (__vers_isspace(*current_char_p) || *current_char_p == '\0') {
  328             if (num_digits_scanned) {
  329                 goto finish;
  330             } else {
  331                 return -1;
  332             }
  333         } else if (__vers_isdigit(*current_char_p)) {
  334             vers_digit = __vers_digit_for_char(*current_char_p);
  335             if (vers_digit < 0) {
  336                 return -1;
  337             }
  338             vers_stage_level = (vers_stage_level) * 10 + vers_digit;
  339             current_char_p++;
  340             num_digits_scanned++;
  341         } else {
  342             return -1;
  343         }
  344     }
  345 
  346    /* Check for too many digits.
  347     */
  348     if ((num_digits_scanned == VERS_STAGE_LEVEL_DIGITS) &&
  349         ! (__vers_isspace(*current_char_p) || (*current_char_p == '\0'))) {
  350 
  351         return -1;
  352     }
  353 
  354     if (vers_stage_level > 255) {
  355         return -1;
  356     }
  357 
  358 finish:
  359 
  360     if (vers_stage == VERS_candidate && vers_stage_level == 0) {
  361         return -1;
  362     }
  363 
  364     result = (vers_major * VERS_MAJOR_MULT) +
  365              (vers_minor * VERS_MINOR_MULT) +
  366              (vers_revision * VERS_REVISION_MULT) +
  367              (vers_stage * VERS_STAGE_MULT) +
  368              vers_stage_level; 
  369 
  370     return result;
  371 }
  372 
  373 #define VERS_STRING_MAX_LEN  (16)
  374 
  375 PRIV_EXT
  376 int VERS_string(char * buffer, UInt32 length, VERS_version vers) {
  377     int cpos = 0;
  378     VERS_version vers_major = 0;
  379     VERS_version vers_minor = 0;
  380     VERS_version vers_revision = 0;
  381     VERS_version vers_stage = 0;
  382     VERS_version vers_stage_level = 0;
  383     const char * stage_string = NULL;  // don't free
  384 
  385    /* No buffer or length less than longest possible vers string,
  386     * return 0.
  387     */
  388     if (!buffer || length < VERS_STRING_MAX_LEN) {
  389         return 0;
  390     }
  391 
  392     bzero(buffer, length * sizeof(char));
  393 
  394     if (vers < 0) {
  395         strlcpy(buffer, "(invalid)", length);
  396         return 1;
  397     }
  398 
  399     vers_major = vers / VERS_MAJOR_MULT;
  400 
  401     vers_minor = vers - (vers_major * VERS_MAJOR_MULT);
  402     vers_minor /= VERS_MINOR_MULT;
  403 
  404     vers_revision = vers -
  405         ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) );
  406     vers_revision /= VERS_REVISION_MULT;
  407 
  408     vers_stage = vers -
  409         ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
  410           (vers_revision * VERS_REVISION_MULT));
  411     vers_stage /= VERS_STAGE_MULT;
  412 
  413     vers_stage_level = vers -
  414         ( (vers_major * VERS_MAJOR_MULT) + (vers_minor * VERS_MINOR_MULT) +
  415           (vers_revision * VERS_REVISION_MULT) + (vers_stage * VERS_STAGE_MULT));
  416 
  417     cpos = snprintf(buffer, length, "%lu", (UInt32)vers_major);
  418 
  419    /* Always include the minor version; it just looks weird without.
  420     */
  421     buffer[cpos] = '.';
  422     cpos++;
  423     cpos += snprintf(buffer+cpos, length - cpos, "%lu", (UInt32)vers_minor);
  424 
  425    /* The revision is displayed only if nonzero.
  426     */
  427     if (vers_revision) {
  428         buffer[cpos] = '.';
  429         cpos++;
  430         cpos += snprintf(buffer+cpos, length - cpos, "%lu",
  431                         (UInt32)vers_revision);
  432     }
  433 
  434     stage_string = __VERS_string_for_stage(vers_stage);
  435     if (stage_string && stage_string[0]) {
  436         strlcat(buffer, stage_string, length);
  437         cpos += strlen(stage_string);
  438     }
  439 
  440     if (vers_stage < VERS_release) {
  441         snprintf(buffer+cpos, length - cpos, "%lu", (UInt32)vers_stage_level);
  442     }
  443 
  444     return 1;
  445 }

Cache object: ab9006bbe2c5634b8eb18810ad61db61


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.