src/fc_erd_argc_argv.c (210 lines of code) (raw):

// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. /*note: "fc_erd_argc_argv" comes from "fabric configuration endpoint resource description" and was shortened because of the build system who is unhappy with such a long filename*/ #include <errno.h> #include <string.h> #include "windows.h" #include "c_logging/logger.h" #include "c_pal/gballoc_hl.h" #include "c_pal/gballoc_hl_redirect.h" #include "c_pal/string_utils.h" #include "sf_c_util/common_argc_argv.h" #include "sf_c_util/fc_erd_argc_argv.h" /* FABRIC_ENDPOINT_RESOURCE_DESCRIPTION => argc/argv is --serviceEndpointResource "string" --Protocol "string" --Type "string" --Port "string" --CertificateName "string"*/ int FABRIC_ENDPOINT_RESOURCE_DESCRIPTION_to_ARGC_ARGV(const FABRIC_ENDPOINT_RESOURCE_DESCRIPTION* fabric_endpoint_resource_description, int* argc, char*** argv) { int result; if ( (fabric_endpoint_resource_description == NULL) || (argc == NULL) || (argv == NULL) ) { LogError("invalid argument const FABRIC_ENDPOINT_RESOURCE_DESCRIPTION* fabric_endpoint_resource_description=%p, int* argc=%p, char*** argv=%p", fabric_endpoint_resource_description, argc, argv); result = MU_FAILURE; } else { *argc = 6; *argv = malloc_2(*argc, sizeof(char*)); if (*argv == NULL) { LogError("failure in malloc2"); result = MU_FAILURE; } else { (* argv)[0] = sprintf_char("%s", SERVICE_ENDPOINT_RESOURCE); if ((*argv)[0] == NULL) { LogError("failure in sprintf_char"); result = MU_FAILURE; } else { (*argv)[1] = sprintf_char("%ls", fabric_endpoint_resource_description->Name); if ((*argv)[1] == NULL) { LogError("failure in sprintf_char"); result = MU_FAILURE; } else { (*argv)[2] = sprintf_char("%ls", fabric_endpoint_resource_description->Protocol); if ((*argv)[2] == NULL) { LogError("failure in sprintf_char"); result = MU_FAILURE; } else { (*argv)[3] = sprintf_char("%ls", fabric_endpoint_resource_description->Type); if ((*argv)[3] == NULL) { LogError("failure in sprintf_char"); result = MU_FAILURE; } else { (*argv)[4] = sprintf_char("%" PRIu16 "", fabric_endpoint_resource_description->Port); if ((*argv)[4] == NULL) { LogError("failure in sprintf_char"); result = MU_FAILURE; } else { if ( (fabric_endpoint_resource_description->CertificateName == NULL) || (fabric_endpoint_resource_description->CertificateName[0] == L'\0') ) { /*if CertificateName is L"" or NULL and that is passed as an argv to a command line - it gets eaten and later FABRIC_ENDPOINT_RESOURCE_DESCRIPTION_from_ARGC_ARGV expects 6 arguments but only gets 5*/ (*argv)[5] = sprintf_char("%ls", L"CERTIFICATE_NAME_WAS_EMPTY_IN_FABRIC_ENDPOINT_RESOURCE_DESCRIPTION"); } else { (*argv)[5] = sprintf_char("%ls", fabric_endpoint_resource_description->CertificateName); } if ((*argv)[5] == NULL) { LogError("failure in sprintf_char"); result = MU_FAILURE; } else { result = 0; goto allok; //free((*argv)[5]); } free((*argv)[4]); } free((*argv)[3]); } free((*argv)[2]); } free((*argv)[1]); } free((*argv)[0]); } free(*argv); } } allok:; return result; } /* argc/argv => FABRIC_CONFIGURATION_PARAMETER_LIST* */ ARGC_ARGV_DATA_RESULT FABRIC_ENDPOINT_RESOURCE_DESCRIPTION_from_ARGC_ARGV(int argc, char** argv, FABRIC_ENDPOINT_RESOURCE_DESCRIPTION* fabric_endpoint_resource_description, int* argc_consumed) { ARGC_ARGV_DATA_RESULT result; if ( (argc < 6) || (argv == NULL) || (fabric_endpoint_resource_description == NULL) || (argc_consumed == NULL) ) { LogError("invalid argument int argc=%d, char** argv=%p, FABRIC_ENDPOINT_RESOURCE_DESCRIPTION* fabric_endpoint_resource_description=%p, int* argc_consumed=%p", argc, argv, fabric_endpoint_resource_description, argc_consumed); result = ARGC_ARGV_DATA_INVALID; } else { if (strcmp(argv[0], SERVICE_ENDPOINT_RESOURCE) != 0) { LogError("cannot parse %s as FABRIC_ENDPOINT_RESOURCE_DESCRIPTION (it was expected to be " SERVICE_ENDPOINT_RESOURCE "", argv[0]); result = ARGC_ARGV_DATA_INVALID; } else { char* stop; errno = 0; uint64_t port = strtoull(argv[4], &stop, 10); if ( (port > UINT16_MAX) || /*note: overflow always returns ULLONG_MAX which is clearly greater than UINT16_MAX*/ (stop[0]!='\0') ) { LogError("scanning of Port=%s failed. Returned value was=%" PRIu64 ", scanning stopped at \"%s\" after %zu characters, errno was=%d (%s)", argv[4], port, stop, stop - argv[4], errno, strerror(errno)); result = ARGC_ARGV_DATA_INVALID; } else { fabric_endpoint_resource_description->Port = (uint16_t)port; /*weird how endpoint description in SF uses "unsigned long" for port... which not even IPV6 changes...*/ fabric_endpoint_resource_description->Name = mbs_to_wcs(argv[1]); if (fabric_endpoint_resource_description->Name == NULL) { LogError("failure in mbs_to_wcs"); result = ARGC_ARGV_DATA_ERROR; } else { fabric_endpoint_resource_description->Protocol = mbs_to_wcs(argv[2]); if (fabric_endpoint_resource_description->Protocol == NULL) { LogError("failure in mbs_to_wcs"); result = ARGC_ARGV_DATA_ERROR; } else { fabric_endpoint_resource_description->Type = mbs_to_wcs(argv[3]); if (fabric_endpoint_resource_description->Type == NULL) { LogError("failure in mbs_to_wcs"); result = ARGC_ARGV_DATA_ERROR; } else { fabric_endpoint_resource_description->CertificateName = mbs_to_wcs(argv[5]); if (fabric_endpoint_resource_description->CertificateName == NULL) { LogError("failure in mbs_to_wcs"); result = ARGC_ARGV_DATA_ERROR; } else { fabric_endpoint_resource_description->Reserved = NULL; *argc_consumed = 6; result = ARGC_ARGV_DATA_OK; goto allok; //free(fabric_endpoint_resource_description->CertificateName); } free((void*)fabric_endpoint_resource_description->Type); } free((void*)fabric_endpoint_resource_description->Protocol); } free((void*)fabric_endpoint_resource_description->Name); } } } } allok:; return result; } /* freeing a previously produced FABRIC_CONFIGURATION_PARAMETER_LIST* */ void FABRIC_ENDPOINT_RESOURCE_DESCRIPTION_free(FABRIC_ENDPOINT_RESOURCE_DESCRIPTION* fabric_endpoint_resource_description) { if (fabric_endpoint_resource_description == NULL) { LogError("invalid argument FABRIC_ENDPOINT_RESOURCE_DESCRIPTION* fabric_endpoint_resource_description=%p", fabric_endpoint_resource_description); } else { free((void*)fabric_endpoint_resource_description->CertificateName); free((void*)fabric_endpoint_resource_description->Name); free((void*)fabric_endpoint_resource_description->Protocol); free((void*)fabric_endpoint_resource_description->Type); } }