VirtualBox

Changeset 49326 in vbox


Ignore:
Timestamp:
Oct 30, 2013 4:33:40 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
90311
Message:

IPRT: exposes RTNetStrToMAC (resolves todo in misc/getopt.cpp).

Location:
trunk
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/mangling.h

    r49182 r49326  
    961961# define RTNetTCPChecksum                               RT_MANGLER(RTNetTCPChecksum)
    962962# define RTNetUDPChecksum                               RT_MANGLER(RTNetUDPChecksum)
     963# define RTNetStrToMacAddr                              RT_MANGLER(RTNetStrToMacAddr)
    963964# define RTNetIsIPv4AddrStr                             RT_MANGLER(RTNetIsIPv4AddrStr)
    964965# define RTNetStrToIPv4Addr                             RT_MANGLER(RTNetStrToIPv4Addr)
  • trunk/include/iprt/net.h

    r45716 r49326  
    3838 * @{
    3939 */
     40
     41/**
     42 * Converts an stringified Ethernet MAC address into the RTMAC representation.
     43 *
     44 * @todo This should be move to some generic part of the runtime.
     45 *
     46 * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on
     47 *          failure.
     48 *
     49 * @param   pszValue        The value to convert.
     50 * @param   pAddr           Where to store the result.
     51 */
     52RTDECL(int) RTNetStrToMacAddr(const char *pszAddr, PRTMAC pMacAddr);
    4053
    4154/**
  • trunk/src/VBox/Runtime/Makefile.kmk

    r49182 r49326  
    364364        common/net/netaddrstr.cpp \
    365365        common/net/netaddrstr2.cpp \
     366        common/net/macstr.cpp \
    366367        common/path/rtPathRootSpecLen.cpp \
    367368        common/path/rtPathVolumeSpecLen.cpp \
     
    16651666        common/math/gcc/umoddi3.c \
    16661667        common/math/gcc/xordi3.c
     1668#
     1669# actually it's for clang
     1670 if $(VBOX_XCODE_VERSION) >= 5
     1671  RuntimeR0_SOURCES.darwin += r0drv/darwin/bzero-r0drv-darwin.cpp
     1672 endif
     1673
     1674
    16671675endif
    16681676
  • trunk/src/VBox/Runtime/common/misc/getopt.cpp

    r46489 r49326  
    111111 * Converts an stringified Ethernet MAC address into the RTMAC representation.
    112112 *
    113  * @todo This should be move to some generic part of the runtime.
    114  *
    115113 * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on
    116114 *          failure.
     
    121119static int rtgetoptConvertMacAddr(const char *pszValue, PRTMAC pAddr)
    122120{
    123     /*
    124      * Not quite sure if I should accept stuff like "08::27:::1" here...
    125      * The code is accepting "::" patterns now, except for for the first
    126      * and last parts.
    127      */
    128 
    129     /* first */
    130     char *pszNext;
    131     int rc = RTStrToUInt8Ex(RTStrStripL(pszValue), &pszNext, 16, &pAddr->au8[0]);
    132     if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS)
    133         return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    134     if (*pszNext++ != ':')
    135         return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    136 
    137     /* middle */
    138     for (unsigned i = 1; i < 5; i++)
    139     {
    140         if (*pszNext == ':')
    141             pAddr->au8[i] = 0;
    142         else
    143         {
    144             rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &pAddr->au8[i]);
    145             if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS)
    146                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    147             if (*pszNext != ':')
    148                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    149         }
    150         pszNext++;
    151     }
    152 
    153     /* last */
    154     rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &pAddr->au8[5]);
    155     if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES)
    156         return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    157     pszNext = RTStrStripL(pszNext);
    158     if (*pszNext)
     121
     122    int rc = RTNetStrToMacAddr(pszValue, pAddr);
     123    if (RT_FAILURE(rc))
    159124        return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    160125
  • trunk/src/VBox/Runtime/common/net/macstr.cpp

    r49247 r49326  
    55
    66/*
    7  * Copyright (C) 2007-2013 Oracle Corporation
     7 * Copyright (C) 2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3030#include <iprt/cidr.h>
    3131#include <iprt/net.h>                   /* must come before getopt.h */
    32 #include <iprt/getopt.h>
    3332#include "internal/iprt.h"
    3433
     
    3837#include <iprt/message.h>
    3938#include <iprt/string.h>
    40 #include <iprt/uuid.h>
    41 
    42 
    43 /*******************************************************************************
    44 *   Global Variables                                                           *
    45 *******************************************************************************/
    46 /**
    47  * Standard options that gets included unless RTGETOPTINIT_FLAGS_NO_STD_OPTS is
    48  * set.
    49  */
    50 static RTGETOPTDEF const g_aStdOptions[] =
    51 {
    52     {  "--help",        'h',    RTGETOPT_REQ_NOTHING },
    53     {  "-help",         'h',    RTGETOPT_REQ_NOTHING },
    54     {  "--version",     'V',    RTGETOPT_REQ_NOTHING },
    55     {  "-version",      'V',    RTGETOPT_REQ_NOTHING },
    56 };
    57 /** The index of --help in g_aStdOptions.  Used for some trickery.  */
    58 #define RTGETOPT_STD_OPTIONS_HELP_IDX   0
    59 
    60 
    61 
    62 RTDECL(int) RTGetOptInit(PRTGETOPTSTATE pState, int argc, char **argv,
    63                          PCRTGETOPTDEF paOptions, size_t cOptions,
    64                          int iFirst, uint32_t fFlags)
    65 {
    66     AssertReturn(!(fFlags & ~(RTGETOPTINIT_FLAGS_OPTS_FIRST | RTGETOPTINIT_FLAGS_NO_STD_OPTS)), VERR_INVALID_PARAMETER);
    67 
    68     pState->argv         = argv;
    69     pState->argc         = argc;
    70     pState->paOptions    = paOptions;
    71     pState->cOptions     = cOptions;
    72     pState->iNext        = iFirst;
    73     pState->pszNextShort = NULL;
    74     pState->pDef         = NULL;
    75     pState->uIndex       = UINT32_MAX;
    76     pState->fFlags       = fFlags;
    77     pState->cNonOptions  = 0;
    78 
    79     /* validate the options. */
    80     for (size_t i = 0; i < cOptions; i++)
    81     {
    82         Assert(!(paOptions[i].fFlags & ~RTGETOPT_VALID_MASK));
    83         Assert(paOptions[i].iShort > 0);
    84         Assert(paOptions[i].iShort != VINF_GETOPT_NOT_OPTION);
    85         Assert(paOptions[i].iShort != '-');
    86     }
    87 
    88     return VINF_SUCCESS;
    89 }
    90 RT_EXPORT_SYMBOL(RTGetOptInit);
    91 
    92 
    93 /**
    94  * Converts an stringified IPv4 address into the RTNETADDRIPV4 representation.
    95  *
    96  * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on
    97  *          failure.
    98  *
    99  * @param   pszValue        The value to convert.
    100  * @param   pAddr           Where to store the result.
    101  */
    102 static int rtgetoptConvertIPv4Addr(const char *pszValue, PRTNETADDRIPV4 pAddr)
    103 {
    104     if (RT_FAILURE(RTNetStrToIPv4Addr(pszValue, pAddr)))
    105         return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    106     return VINF_SUCCESS;
    107 }
    10839
    10940
     
    11142 * Converts an stringified Ethernet MAC address into the RTMAC representation.
    11243 *
    113  * @todo This should be move to some generic part of the runtime.
    114  *
    115  * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on
    116  *          failure.
     44 * @returns VINF_SUCCESS on success.
    11745 *
    11846 * @param   pszValue        The value to convert.
    11947 * @param   pAddr           Where to store the result.
    12048 */
    121 static int rtgetoptConvertMacAddr(const char *pszValue, PRTMAC pAddr)
     49RTDECL(int) RTNetStrToMacAddr(const char *pszValue, PRTMAC pAddr)
    12250{
    12351    /*
     
    14472            rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &pAddr->au8[i]);
    14573            if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS)
    146                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
     74                return rc;
    14775            if (*pszNext != ':')
    148                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
     76                return VERR_INVALID_PARAMETER;
    14977        }
    15078        pszNext++;
     
    15482    rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &pAddr->au8[5]);
    15583    if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES)
    156         return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
     84        return rc;
    15785    pszNext = RTStrStripL(pszNext);
    15886    if (*pszNext)
    159         return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
     87        return VERR_INVALID_PARAMETER;
    16088
    16189    return VINF_SUCCESS;
    16290}
    163 
    164 
    165 /**
    166  * Searches for a long option.
    167  *
    168  * @returns Pointer to a matching option.
    169  * @param   pszOption       The alleged long option.
    170  * @param   paOptions       Option array.
    171  * @param   cOptions        Number of items in the array.
    172  * @param   fFlags          Init flags.
    173  */
    174 static PCRTGETOPTDEF rtGetOptSearchLong(const char *pszOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags)
    175 {
    176     PCRTGETOPTDEF pOpt = paOptions;
    177     while (cOptions-- > 0)
    178     {
    179         if (pOpt->pszLong)
    180         {
    181             if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
    182             {
    183                 /*
    184                  * A value is required with the argument. We're trying to be
    185                  * understanding here and will permit any of the following:
    186                  *      --long12:value,  --long12=value, --long12 value,
    187                  *      --long:value,    --long=value,   --long value,
    188                  *
    189                  * If the option is index, then all trailing chars must be
    190                  * digits.  For error reporting reasons we also match where
    191                  * there is no index.
    192                  */
    193                 size_t cchLong = strlen(pOpt->pszLong);
    194                 if (   !strncmp(pszOption, pOpt->pszLong, cchLong)
    195                     || (   pOpt->fFlags & RTGETOPT_FLAG_ICASE
    196                         && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong)))
    197                 {
    198                     if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
    199                         while (RT_C_IS_DIGIT(pszOption[cchLong]))
    200                             cchLong++;
    201                     if (   pszOption[cchLong] == '\0'
    202                         || pszOption[cchLong] == ':'
    203                         || pszOption[cchLong] == '=')
    204                         return pOpt;
    205                 }
    206             }
    207             else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
    208             {
    209                 /*
    210                  * The option takes an index but no value.
    211                  * As above, we also match where there is no index.
    212                  */
    213                 size_t cchLong = strlen(pOpt->pszLong);
    214                 if (   !strncmp(pszOption, pOpt->pszLong, cchLong)
    215                     || (   pOpt->fFlags & RTGETOPT_FLAG_ICASE
    216                         && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong)))
    217                 {
    218                     while (RT_C_IS_DIGIT(pszOption[cchLong]))
    219                         cchLong++;
    220                     if (pszOption[cchLong] == '\0')
    221                         return pOpt;
    222                 }
    223             }
    224             else if (   !strcmp(pszOption, pOpt->pszLong)
    225                      || (   pOpt->fFlags & RTGETOPT_FLAG_ICASE
    226                          && !RTStrICmp(pszOption, pOpt->pszLong)))
    227                 return pOpt;
    228         }
    229         pOpt++;
    230     }
    231 
    232     if (!(fFlags & RTGETOPTINIT_FLAGS_NO_STD_OPTS))
    233         for (uint32_t i = 0; i < RT_ELEMENTS(g_aStdOptions); i++)
    234             if (   !strcmp(pszOption, g_aStdOptions[i].pszLong)
    235                 || (   g_aStdOptions[i].fFlags & RTGETOPT_FLAG_ICASE
    236                     && !RTStrICmp(pszOption, g_aStdOptions[i].pszLong)))
    237                 return &g_aStdOptions[i];
    238 
    239     return NULL;
    240 }
    241 
    242 
    243 /**
    244  * Searches for a matching short option.
    245  *
    246  * @returns Pointer to a matching option.
    247  * @param   chOption        The option char.
    248  * @param   paOptions       Option array.
    249  * @param   cOptions        Number of items in the array.
    250  * @param   fFlags          Init flags.
    251  */
    252 static PCRTGETOPTDEF rtGetOptSearchShort(int chOption, PCRTGETOPTDEF paOptions, size_t cOptions, uint32_t fFlags)
    253 {
    254     PCRTGETOPTDEF pOpt = paOptions;
    255     while (cOptions-- > 0)
    256     {
    257         if (pOpt->iShort == chOption)
    258             return pOpt;
    259         pOpt++;
    260     }
    261 
    262     if (!(fFlags & RTGETOPTINIT_FLAGS_NO_STD_OPTS))
    263     {
    264         for (uint32_t i = 0; i < RT_ELEMENTS(g_aStdOptions); i++)
    265             if (g_aStdOptions[i].iShort == chOption)
    266                 return &g_aStdOptions[i];
    267         if (chOption == '?')
    268             return &g_aStdOptions[RTGETOPT_STD_OPTIONS_HELP_IDX];
    269     }
    270     return NULL;
    271 }
    272 
    273 
    274 /**
    275  * Value string -> Value union.
    276  *
    277  * @returns IPRT status code.
    278  * @param   fFlags              The value flags.
    279  * @param   pszValue            The value string.
    280  * @param   pValueUnion         Where to return the processed value.
    281  */
    282 static int rtGetOptProcessValue(uint32_t fFlags, const char *pszValue, PRTGETOPTUNION pValueUnion)
    283 {
    284     /*
    285      * Transform into a option value as requested.
    286      * If decimal conversion fails, we'll check for "0x<xdigit>" and
    287      * try a 16 based conversion. We will not interpret any of the
    288      * generic ints as octals.
    289      */
    290     switch (fFlags & (  RTGETOPT_REQ_MASK
    291                       | RTGETOPT_FLAG_HEX
    292                       | RTGETOPT_FLAG_DEC
    293                       | RTGETOPT_FLAG_OCT))
    294     {
    295         case RTGETOPT_REQ_STRING:
    296             pValueUnion->psz = pszValue;
    297             break;
    298 
    299         case RTGETOPT_REQ_BOOL:
    300             if (   !RTStrICmp(pszValue, "true")
    301                 || !RTStrICmp(pszValue, "t")
    302                 || !RTStrICmp(pszValue, "yes")
    303                 || !RTStrICmp(pszValue, "y")
    304                 || !RTStrICmp(pszValue, "enabled")
    305                 || !RTStrICmp(pszValue, "enable")
    306                 || !RTStrICmp(pszValue, "en")
    307                 || !RTStrICmp(pszValue, "e")
    308                 || !RTStrICmp(pszValue, "on")
    309                 || !RTStrCmp(pszValue, "1")
    310                 )
    311                 pValueUnion->f = true;
    312             else if (   !RTStrICmp(pszValue, "false")
    313                      || !RTStrICmp(pszValue, "f")
    314                      || !RTStrICmp(pszValue, "no")
    315                      || !RTStrICmp(pszValue, "n")
    316                      || !RTStrICmp(pszValue, "disabled")
    317                      || !RTStrICmp(pszValue, "disable")
    318                      || !RTStrICmp(pszValue, "dis")
    319                      || !RTStrICmp(pszValue, "d")
    320                      || !RTStrICmp(pszValue, "off")
    321                      || !RTStrCmp(pszValue, "0")
    322                      )
    323                 pValueUnion->f = false;
    324             else
    325             {
    326                 pValueUnion->psz = pszValue;
    327                 return VERR_GETOPT_UNKNOWN_OPTION;
    328             }
    329             break;
    330 
    331         case RTGETOPT_REQ_BOOL_ONOFF:
    332             if (!RTStrICmp(pszValue, "on"))
    333                 pValueUnion->f = true;
    334             else if (!RTStrICmp(pszValue, "off"))
    335                 pValueUnion->f = false;
    336             else
    337             {
    338                 pValueUnion->psz = pszValue;
    339                 return VERR_GETOPT_UNKNOWN_OPTION;
    340             }
    341             break;
    342 
    343 #define MY_INT_CASE(req, type, memb, convfn) \
    344             case req: \
    345             { \
    346                 type Value; \
    347                 if (    convfn(pszValue, 10, &Value) != VINF_SUCCESS \
    348                     &&  (   pszValue[0] != '0' \
    349                          || (pszValue[1] != 'x' && pszValue[1] != 'X') \
    350                          || !RT_C_IS_XDIGIT(pszValue[2]) \
    351                          || convfn(pszValue, 16, &Value) != VINF_SUCCESS ) ) \
    352                     return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; \
    353                 pValueUnion->memb = Value; \
    354                 break; \
    355             }
    356 #define MY_BASE_INT_CASE(req, type, memb, convfn, base) \
    357             case req: \
    358             { \
    359                 type Value; \
    360                 if (convfn(pszValue, base, &Value) != VINF_SUCCESS) \
    361                     return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; \
    362                 pValueUnion->memb = Value; \
    363                 break; \
    364             }
    365 
    366         MY_INT_CASE(RTGETOPT_REQ_INT8,   int8_t,   i8,  RTStrToInt8Full)
    367         MY_INT_CASE(RTGETOPT_REQ_INT16,  int16_t,  i16, RTStrToInt16Full)
    368         MY_INT_CASE(RTGETOPT_REQ_INT32,  int32_t,  i32, RTStrToInt32Full)
    369         MY_INT_CASE(RTGETOPT_REQ_INT64,  int64_t,  i64, RTStrToInt64Full)
    370         MY_INT_CASE(RTGETOPT_REQ_UINT8,  uint8_t,  u8,  RTStrToUInt8Full)
    371         MY_INT_CASE(RTGETOPT_REQ_UINT16, uint16_t, u16, RTStrToUInt16Full)
    372         MY_INT_CASE(RTGETOPT_REQ_UINT32, uint32_t, u32, RTStrToUInt32Full)
    373         MY_INT_CASE(RTGETOPT_REQ_UINT64, uint64_t, u64, RTStrToUInt64Full)
    374 
    375         MY_BASE_INT_CASE(RTGETOPT_REQ_INT8   | RTGETOPT_FLAG_HEX, int8_t,   i8,  RTStrToInt8Full,   16)
    376         MY_BASE_INT_CASE(RTGETOPT_REQ_INT16  | RTGETOPT_FLAG_HEX, int16_t,  i16, RTStrToInt16Full,  16)
    377         MY_BASE_INT_CASE(RTGETOPT_REQ_INT32  | RTGETOPT_FLAG_HEX, int32_t,  i32, RTStrToInt32Full,  16)
    378         MY_BASE_INT_CASE(RTGETOPT_REQ_INT64  | RTGETOPT_FLAG_HEX, int64_t,  i64, RTStrToInt64Full,  16)
    379         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT8  | RTGETOPT_FLAG_HEX, uint8_t,  u8,  RTStrToUInt8Full,  16)
    380         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT16 | RTGETOPT_FLAG_HEX, uint16_t, u16, RTStrToUInt16Full, 16)
    381         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX, uint32_t, u32, RTStrToUInt32Full, 16)
    382         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX, uint64_t, u64, RTStrToUInt64Full, 16)
    383 
    384         MY_BASE_INT_CASE(RTGETOPT_REQ_INT8   | RTGETOPT_FLAG_DEC, int8_t,   i8,  RTStrToInt8Full,   10)
    385         MY_BASE_INT_CASE(RTGETOPT_REQ_INT16  | RTGETOPT_FLAG_DEC, int16_t,  i16, RTStrToInt16Full,  10)
    386         MY_BASE_INT_CASE(RTGETOPT_REQ_INT32  | RTGETOPT_FLAG_DEC, int32_t,  i32, RTStrToInt32Full,  10)
    387         MY_BASE_INT_CASE(RTGETOPT_REQ_INT64  | RTGETOPT_FLAG_DEC, int64_t,  i64, RTStrToInt64Full,  10)
    388         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT8  | RTGETOPT_FLAG_DEC, uint8_t,  u8,  RTStrToUInt8Full,  10)
    389         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT16 | RTGETOPT_FLAG_DEC, uint16_t, u16, RTStrToUInt16Full, 10)
    390         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_DEC, uint32_t, u32, RTStrToUInt32Full, 10)
    391         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_DEC, uint64_t, u64, RTStrToUInt64Full, 10)
    392 
    393         MY_BASE_INT_CASE(RTGETOPT_REQ_INT8   | RTGETOPT_FLAG_OCT, int8_t,   i8,  RTStrToInt8Full,   8)
    394         MY_BASE_INT_CASE(RTGETOPT_REQ_INT16  | RTGETOPT_FLAG_OCT, int16_t,  i16, RTStrToInt16Full,  8)
    395         MY_BASE_INT_CASE(RTGETOPT_REQ_INT32  | RTGETOPT_FLAG_OCT, int32_t,  i32, RTStrToInt32Full,  8)
    396         MY_BASE_INT_CASE(RTGETOPT_REQ_INT64  | RTGETOPT_FLAG_OCT, int64_t,  i64, RTStrToInt64Full,  8)
    397         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT8  | RTGETOPT_FLAG_OCT, uint8_t,  u8,  RTStrToUInt8Full,  8)
    398         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT16 | RTGETOPT_FLAG_OCT, uint16_t, u16, RTStrToUInt16Full, 8)
    399         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT, uint32_t, u32, RTStrToUInt32Full, 8)
    400         MY_BASE_INT_CASE(RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_OCT, uint64_t, u64, RTStrToUInt64Full, 8)
    401 
    402 #undef MY_INT_CASE
    403 #undef MY_BASE_INT_CASE
    404 
    405         case RTGETOPT_REQ_IPV4ADDR:
    406         {
    407             RTNETADDRIPV4 Addr;
    408             if (rtgetoptConvertIPv4Addr(pszValue, &Addr) != VINF_SUCCESS)
    409                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    410             pValueUnion->IPv4Addr = Addr;
    411             break;
    412         }
    413 
    414         case RTGETOPT_REQ_IPV4CIDR:
    415         {
    416             RTNETADDRIPV4 network;
    417             RTNETADDRIPV4 netmask;
    418             if (RT_FAILURE(RTCidrStrToIPv4(pszValue, &network, &netmask)))
    419               return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    420             pValueUnion->CidrIPv4.IPv4Network.u = network.u;
    421             pValueUnion->CidrIPv4.IPv4Netmask.u = netmask.u;
    422             break;
    423         }
    424 
    425         case RTGETOPT_REQ_MACADDR:
    426         {
    427             RTMAC Addr;
    428             if (rtgetoptConvertMacAddr(pszValue, &Addr) != VINF_SUCCESS)
    429                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    430             pValueUnion->MacAddr = Addr;
    431             break;
    432         }
    433 
    434         case RTGETOPT_REQ_UUID:
    435         {
    436             RTUUID Uuid;
    437             if (RTUuidFromStr(&Uuid, pszValue) != VINF_SUCCESS)
    438                 return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    439             pValueUnion->Uuid = Uuid;
    440             break;
    441         }
    442 
    443         default:
    444             AssertMsgFailed(("f=%#x\n", fFlags));
    445             return VERR_INTERNAL_ERROR;
    446     }
    447 
    448     return VINF_SUCCESS;
    449 }
    450 
    451 
    452 /**
    453  * Moves one argv option entries.
    454  *
    455  * @param   papszTo             Destination.
    456  * @param   papszFrom           Source.
    457  */
    458 static void rtGetOptMoveArgvEntries(char **papszTo, char **papszFrom)
    459 {
    460     if (papszTo != papszFrom)
    461     {
    462         Assert((uintptr_t)papszTo < (uintptr_t)papszFrom);
    463         char * const pszMoved = papszFrom[0];
    464         memmove(&papszTo[1], &papszTo[0], (uintptr_t)papszFrom - (uintptr_t)papszTo);
    465         papszTo[0] = pszMoved;
    466     }
    467 }
    468 
    469 
    470 RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion)
    471 {
    472     /*
    473      * Reset the variables kept in state.
    474      */
    475     pState->pDef = NULL;
    476     pState->uIndex = UINT32_MAX;
    477 
    478     /*
    479      * Make sure the union is completely cleared out, whatever happens below.
    480      */
    481     pValueUnion->u64 = 0;
    482     pValueUnion->pDef = NULL;
    483 
    484     /*
    485      * The next option.
    486      */
    487     bool            fShort;
    488     int             iThis;
    489     const char     *pszArgThis;
    490     PCRTGETOPTDEF   pOpt;
    491 
    492     if (pState->pszNextShort)
    493     {
    494         /*
    495          * We've got short options left over from the previous call.
    496          */
    497         pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions, pState->fFlags);
    498         if (!pOpt)
    499         {
    500             pValueUnion->psz = pState->pszNextShort;
    501             return VERR_GETOPT_UNKNOWN_OPTION;
    502         }
    503         pState->pszNextShort++;
    504         pszArgThis = pState->pszNextShort - 2;
    505         iThis = pState->iNext;
    506         fShort = true;
    507     }
    508     else
    509     {
    510         /*
    511          * Pop off the next argument.  Sorting options and dealing with the
    512          * dash-dash makes this a little extra complicated.
    513          */
    514         for (;;)
    515         {
    516             if (pState->iNext >= pState->argc)
    517                 return 0;
    518 
    519             if (pState->cNonOptions)
    520             {
    521                 if (pState->cNonOptions == INT32_MAX)
    522                 {
    523                     pValueUnion->psz = pState->argv[pState->iNext++];
    524                     return VINF_GETOPT_NOT_OPTION;
    525                 }
    526 
    527                 if (pState->iNext + pState->cNonOptions >= pState->argc)
    528                 {
    529                     pState->cNonOptions = INT32_MAX;
    530                     continue;
    531                 }
    532             }
    533 
    534             iThis = pState->iNext++;
    535             pszArgThis = pState->argv[iThis + pState->cNonOptions];
    536 
    537             /*
    538              * Do a long option search first and then a short option one.
    539              * This way we can make sure single dash long options doesn't
    540              * get mixed up with short ones.
    541              */
    542             pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags);
    543             if (    !pOpt
    544                 &&  pszArgThis[0] == '-'
    545                 &&  pszArgThis[1] != '-'
    546                 &&  pszArgThis[1] != '\0')
    547             {
    548                 pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions, pState->fFlags);
    549                 fShort = pOpt != NULL;
    550             }
    551             else
    552                 fShort = false;
    553 
    554             /* Look for dash-dash. */
    555             if (!pOpt && !strcmp(pszArgThis, "--"))
    556             {
    557                 rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
    558                 pState->cNonOptions = INT32_MAX;
    559                 continue;
    560             }
    561 
    562             /* Options first hacks. */
    563             if (pState->fFlags & RTGETOPTINIT_FLAGS_OPTS_FIRST)
    564             {
    565                 if (pOpt)
    566                     rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
    567                 else if (*pszArgThis == '-')
    568                 {
    569                     pValueUnion->psz = pszArgThis;
    570                     return VERR_GETOPT_UNKNOWN_OPTION;
    571                 }
    572                 else
    573                 {
    574                     /* not an option, add it to the non-options and try again. */
    575                     pState->iNext--;
    576                     pState->cNonOptions++;
    577 
    578                     /* Switch to returning non-options if we've reached the end. */
    579                     if (pState->iNext + pState->cNonOptions >= pState->argc)
    580                         pState->cNonOptions = INT32_MAX;
    581                     continue;
    582                 }
    583             }
    584 
    585             /* done */
    586             break;
    587         }
    588     }
    589 
    590     if (pOpt)
    591     {
    592         pValueUnion->pDef = pOpt; /* in case of no value or error. */
    593 
    594         if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
    595         {
    596             /*
    597              * Find the argument value.
    598              *
    599              * A value is required with the argument. We're trying to be
    600              * understanding here and will permit any of the following:
    601              *      -svalue, -s value, -s:value and -s=value
    602              * (Ditto for long options.)
    603              */
    604             const char *pszValue;
    605             if (fShort)
    606             {
    607                 if (pszArgThis[2] == '\0')
    608                 {
    609                     if (iThis + 1 >= pState->argc)
    610                         return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    611                     pszValue = pState->argv[iThis + pState->cNonOptions + 1];
    612                     rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    613                     pState->iNext++;
    614                 }
    615                 else /* same argument. */
    616                     pszValue = &pszArgThis[2  + (pszArgThis[2] == ':' || pszArgThis[2] == '=')];
    617                 if (pState->pszNextShort)
    618                 {
    619                     pState->pszNextShort = NULL;
    620                     pState->iNext++;
    621                 }
    622             }
    623             else
    624             {
    625                 size_t cchLong = strlen(pOpt->pszLong);
    626                 if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
    627                 {
    628 
    629                     if (pszArgThis[cchLong] == '\0')
    630                         return VERR_GETOPT_INDEX_MISSING;
    631 
    632                     uint32_t uIndex;
    633                     char *pszRet = NULL;
    634                     int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex);
    635                     if (rc == VWRN_TRAILING_CHARS)
    636                     {
    637                         if (   pszRet[0] != ':'
    638                             && pszRet[0] != '=')
    639                             return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    640                         pState->uIndex = uIndex;
    641                         pszValue = pszRet + 1;
    642                     }
    643                     else if (rc == VINF_SUCCESS)
    644                     {
    645                         if (iThis + 1 >= pState->argc)
    646                             return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    647                         pState->uIndex = uIndex;
    648                         pszValue = pState->argv[iThis + pState->cNonOptions + 1];
    649                         rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    650                         pState->iNext++;
    651                     }
    652                     else
    653                         AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
    654                 }
    655                 else
    656                 {
    657                     if (pszArgThis[cchLong] == '\0')
    658                     {
    659                         if (iThis + 1 >= pState->argc)
    660                             return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    661                         pszValue = pState->argv[iThis + pState->cNonOptions + 1];
    662                         rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    663                         pState->iNext++;
    664                     }
    665                     else /* same argument. */
    666                         pszValue = &pszArgThis[cchLong + 1];
    667                 }
    668             }
    669 
    670             /*
    671              * Set up the ValueUnion.
    672              */
    673             int rc = rtGetOptProcessValue(pOpt->fFlags, pszValue, pValueUnion);
    674             if (RT_FAILURE(rc))
    675                 return rc;
    676         }
    677         else if (fShort)
    678         {
    679             /*
    680              * Deal with "compressed" short option lists, correcting the next
    681              * state variables for the start and end cases.
    682              */
    683             if (pszArgThis[2])
    684             {
    685                 if (!pState->pszNextShort)
    686                 {
    687                     /* start */
    688                     pState->pszNextShort = &pszArgThis[2];
    689                     pState->iNext--;
    690                 }
    691             }
    692             else if (pState->pszNextShort)
    693             {
    694                 /* end */
    695                 pState->pszNextShort = NULL;
    696                 pState->iNext++;
    697             }
    698         }
    699         else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
    700         {
    701             size_t cchLong = strlen(pOpt->pszLong);
    702             if (pszArgThis[cchLong] == '\0')
    703                 return VERR_GETOPT_INDEX_MISSING;
    704 
    705             uint32_t uIndex;
    706             if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS)
    707                 pState->uIndex = uIndex;
    708             else
    709                 AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
    710         }
    711 
    712         pState->pDef = pOpt;
    713         return pOpt->iShort;
    714     }
    715 
    716     /*
    717      * Not a known option argument. If it starts with a switch char (-) we'll
    718      * fail with unknown option, and if it doesn't we'll return it as a non-option.
    719      */
    720     if (*pszArgThis == '-')
    721     {
    722         pValueUnion->psz = pszArgThis;
    723         return VERR_GETOPT_UNKNOWN_OPTION;
    724     }
    725 
    726     pValueUnion->psz = pszArgThis;
    727     return VINF_GETOPT_NOT_OPTION;
    728 }
    729 RT_EXPORT_SYMBOL(RTGetOpt);
    730 
    731 
    732 RTDECL(int) RTGetOptFetchValue(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion, uint32_t fFlags)
    733 {
    734     /*
    735      * Validate input.
    736      */
    737     PCRTGETOPTDEF pOpt = pState->pDef;
    738     AssertReturn(!(fFlags & ~RTGETOPT_VALID_MASK), VERR_INVALID_PARAMETER);
    739     AssertReturn((fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING, VERR_INVALID_PARAMETER);
    740 
    741     /*
    742      * Make sure the union is completely cleared out, whatever happens below.
    743      */
    744     pValueUnion->u64 = 0;
    745     pValueUnion->pDef = NULL;
    746 
    747     /*
    748      * Pop off the next argument and convert it into a value union.
    749      */
    750     if (pState->iNext >= pState->argc)
    751         return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    752     int         iThis    = pState->iNext++;
    753     const char *pszValue = pState->argv[iThis + (pState->cNonOptions != INT32_MAX ? pState->cNonOptions : 0)];
    754     pValueUnion->pDef    = pOpt; /* in case of no value or error. */
    755 
    756     if (pState->cNonOptions && pState->cNonOptions != INT32_MAX)
    757         rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
    758 
    759     return rtGetOptProcessValue(fFlags, pszValue, pValueUnion);
    760 }
    761 RT_EXPORT_SYMBOL(RTGetOptFetchValue);
    762 
    763 
    764 RTDECL(RTEXITCODE) RTGetOptPrintError(int ch, PCRTGETOPTUNION pValueUnion)
    765 {
    766     if (ch == VINF_GETOPT_NOT_OPTION)
    767         RTMsgError("Invalid parameter: %s", pValueUnion->psz);
    768     else if (ch > 0)
    769     {
    770         if (RT_C_IS_GRAPH(ch))
    771             RTMsgError("Unhandled option: -%c", ch);
    772         else
    773             RTMsgError("Unhandled option: %i (%#x)", ch, ch);
    774     }
    775     else if (ch == VERR_GETOPT_UNKNOWN_OPTION)
    776         RTMsgError("Unknown option: '%s'", pValueUnion->psz);
    777     else if (ch == VERR_GETOPT_INVALID_ARGUMENT_FORMAT)
    778         /** @todo r=klaus not really ideal, as the value isn't available */
    779         RTMsgError("The value given '%s' has an invalid format.", pValueUnion->pDef->pszLong);
    780     else if (pValueUnion->pDef)
    781         RTMsgError("%s: %Rrs\n", pValueUnion->pDef->pszLong, ch);
    782     else
    783         RTMsgError("%Rrs\n", ch);
    784 
    785     return RTEXITCODE_SYNTAX;
    786 }
    787 RT_EXPORT_SYMBOL(RTGetOptPrintError);
    788 
     91RT_EXPORT_SYMBOL(RTNetStrToMacAddr);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette