Пример #1
0
TEST(VolumeMapTestGroup, FindEndOfVolumeMapInString) {
    const char *input1 = "/volume:/map:test";
    const char *ptr = _findEndVolumeMapString(input1);
    CHECK(ptr != NULL && *ptr == 0);
    CHECK(strncmp(input1, input1, ptr-input1) == 0);

    const char *input2 = "/volume:/map;/input:output";
    ptr = _findEndVolumeMapString(input2);
    CHECK(ptr != NULL && *ptr == ';');
    CHECK(strncmp(input2, "/volume:/map", ptr-input2) == 0);

    const char *sptr = input2;
    const char *limit = input2 + strlen(input2);
    int idx = 0;
    for (sptr = input2, ptr = _findEndVolumeMapString(input2); sptr < limit; ptr = _findEndVolumeMapString(sptr)) {
        switch (idx) {
            case 0:     CHECK(strncmp(sptr, "/volume:/map", ptr - sptr) == 0);
                        break;
            case 1:     CHECK(strncmp(sptr, "/input:output", ptr - sptr) == 0);
                        break;
        }
        sptr = ptr + 1;
        idx++;
    }

    const char *input3 = "\"/volume:/map:ro,rec\"";
    ptr = _findEndVolumeMapString(input3);
    CHECK(ptr && (*ptr == 0));
    CHECK(strlen(input3) == ptr - input3);
}
Пример #2
0
int _parseVolumeMap(
        const char *input,
        VolumeMap *volMap,
        int (*_validate_fp)(const char *, const char *, VolumeMapFlag *),
        short requireTo
) {
    if (input == NULL || volMap == NULL) return 1;
    char **rawPtr = volMap->raw + volMap->n;
    char **toPtr = volMap->to + volMap->n;
    char **fromPtr = volMap->from + volMap->n;
    VolumeMapFlag **flagPtr = volMap->flags + volMap->n;

    const char *ptr = input;
    const char *eptr = NULL;
    char *tmp = NULL;
    size_t len = strlen(input);
    int ret = 0;
    char *to = NULL;
    char *from = NULL;
    VolumeMapFlag *flags = NULL;
    size_t flagsCapacity = 0;
    char *raw = NULL;
    char **tokens = NULL;
    char **tk_ptr = NULL;
    size_t tokenIdx = 0;
    size_t rawLen = 0;
    size_t rawCapacity = 0;
    size_t flagIdx = 0;
    size_t flagCnt = 0;

    while (ptr < input + len) {
        size_t ntokens = 0;
        eptr = _findEndVolumeMapString(ptr);
        if (eptr == ptr && eptr != NULL) {
            ptr++;
            continue;
        }
        if (eptr == NULL) {
            break;
        }

        /* make copy for parsing */
        tmp = (char *) malloc(sizeof(char) * (eptr - ptr + 1));
        if (tmp == NULL) {
            fprintf(stderr, "Failed to allocate memory for tmp string\n");
            goto _parseVolumeMap_unclean;
        }
        strncpy(tmp, ptr, eptr - ptr);
        tmp[eptr - ptr] = 0;

        char *volMapStr = tmp;
        if (*volMapStr == '"' && *(volMapStr + (eptr - ptr) - 1) == '"') {
            *(volMapStr + (eptr - ptr) - 1) = 0;
            volMapStr++;
        }

        /* tokenize the the input string */
        tokens = _tokenizeVolumeMapInput(volMapStr);

        /* count how many non-NULL tokens there are */
        for (ntokens = 0; tokens && tokens[ntokens]; ntokens++) {
        }

        if (tokens == NULL || ntokens == 0) {
            fprintf(stderr, "Failed to parse VolumeMap tokens from \"%s\","
                    " aborting!\n", tmp);
            goto _parseVolumeMap_unclean;
        }

        from = userInputPathFilter(tokens[0], 1);
        to = userInputPathFilter(tokens[1], 1);

        for (tokenIdx = 2; tokenIdx < ntokens; tokenIdx++) {
            if (_parseFlag(tokens[tokenIdx], &flags, &flagsCapacity) != 0) {
                fprintf(stderr, "Invalid mount flags specified: %s\n", tokens[tokenIdx]);
                goto _parseVolumeMap_unclean;
            }
        }

        /* if we only got a from and to is not required 
           assume we are binding a path from outside the container
           and to can be set to from */
        if (from && ntokens == 1 && !requireTo) {
            to = strdup(from);
        }

        /* ensure the user is asking for a legal mapping */
        if ((ret = _validate_fp(from, to, flags)) != 0) {
            fprintf(stderr, "Invalid Volume Map: %.*s, aborting! %d\n",
                (int) (eptr - ptr),
                ptr, ret
            );
            goto _parseVolumeMap_unclean;
        }

        if (to == NULL || from == NULL) {
            fprintf(stderr, "INVALID format for volume map %.*s\n", 
                (int) (eptr - ptr),
                ptr
            );
            goto _parseVolumeMap_unclean;
        }

        for (flagCnt = 0; flags && flags[flagCnt].type != 0; flagCnt++) { }
        if (flagCnt > 0) {
            qsort(flags, flagCnt, sizeof(VolumeMapFlag), _cmpFlags);
        }

        /* generate a new "raw" string from the filtered values */
        rawLen = 2 + strlen(from) + strlen(to);
        raw = (char *) malloc(sizeof(char) * rawLen);
        rawCapacity = sizeof(char) * rawLen;
        rawLen = snprintf(raw, rawLen, "%s:%s", from, to);

        for (flagIdx = 0; flagIdx < flagCnt; flagIdx++) {
            if (flags[flagIdx].type == VOLMAP_FLAG_READONLY) {
                raw = alloc_strcatf(raw, &rawLen, &rawCapacity, ":ro");
            } else if (flags[flagIdx].type == VOLMAP_FLAG_RECURSIVE) {
                raw = alloc_strcatf(raw, &rawLen, &rawCapacity, ":rec");
            } else if (flags[flagIdx].type == VOLMAP_FLAG_SLAVE) {
                raw = alloc_strcatf(raw, &rawLen, &rawCapacity, ":slave");
            } else if (flags[flagIdx].type == VOLMAP_FLAG_PRIVATE) {
                raw = alloc_strcatf(raw, &rawLen, &rawCapacity, ":private");
            } else if (flags[flagIdx].type == VOLMAP_FLAG_PERNODECACHE) {
                VolMapPerNodeCacheConfig *cache = (VolMapPerNodeCacheConfig *) flags[flagIdx].value;
                if (cache == NULL) {
                    fprintf(stderr, "FAILED to read perNodeCache config from memory\n");
                    goto _parseVolumeMap_unclean;
                }
                raw = alloc_strcatf(raw, &rawLen, &rawCapacity, ":perNodeCache=size=%lu,bs=%lu,method=%s,fstype=%s", cache->cacheSize, cache->blockSize, cache->method, cache->fstype);
            }
        }

        /* append to raw array */
        ret = strncpy_StringArray(raw, rawLen, &rawPtr, &(volMap->raw),
                &(volMap->rawCapacity), VOLUME_ALLOC_BLOCK);
        if (ret != 0) goto _parseVolumeMap_unclean;

        ret = strncpy_StringArray(to, strlen(to), &toPtr, &(volMap->to),
                &(volMap->toCapacity), VOLUME_ALLOC_BLOCK);
        if (ret != 0) goto _parseVolumeMap_unclean;

        ret = strncpy_StringArray(from, strlen(from), &fromPtr, &(volMap->from),
                &(volMap->fromCapacity), VOLUME_ALLOC_BLOCK);
        if (ret != 0) goto _parseVolumeMap_unclean;

        if (volMap->n >= volMap->flagsCapacity) {
            VolumeMapFlag **tmp = (VolumeMapFlag **) realloc(volMap->flags, sizeof(VolumeMapFlag *) * (volMap->flagsCapacity + VOLUME_ALLOC_BLOCK));
            if (tmp == NULL) {
                fprintf(stderr, "Failed to allocate memory!\n");
                goto _parseVolumeMap_unclean;
            }
            volMap->flags = tmp;
            flagPtr = volMap->flags + volMap->n;
            volMap->flagsCapacity += VOLUME_ALLOC_BLOCK;
            memset(flagPtr, 0, sizeof(VolumeMapFlag *) * (volMap->flagsCapacity - volMap->n));
        }
        
        *flagPtr++ = flags;
        *flagPtr = NULL;

        if (ret != 0) goto _parseVolumeMap_unclean;

        if (from != NULL) free(from);
        if (to != NULL) free(to);
        if (raw != NULL) free(raw);
        from = NULL;
        to = NULL;
        raw = NULL;
        flags = NULL;

        ptr = eptr + 1;
        volMap->n += 1;
        if (tmp != NULL) free(tmp);
        tmp = NULL;

        for (tk_ptr = tokens; tk_ptr && *tk_ptr; tk_ptr++) {
            free(*tk_ptr);
        }
        if (tokens != NULL) free(tokens);
        tokens = NULL;
    }
    return 0;
_parseVolumeMap_unclean:
    {
        char *freeArray[] = {tmp, from, to, raw, NULL};
        char **freePtr = NULL;
        for (freePtr = freeArray; *freePtr != NULL; freePtr++) {
            if (*freePtr != NULL) {
                free(*freePtr);
            }
        }

        for (tk_ptr = tokens; tk_ptr && *tk_ptr; tk_ptr++) {
            free(*tk_ptr);
        }
        if (tokens != NULL) free(tokens);
        tokens = NULL;

        if (flags != NULL) {
            free_VolumeMapFlag(flags, 1);
            flags = NULL;
        }
    }
    return 1;
}