Example #1
0
File: log.c Project: l8huang/ovs
struct ovsdb_error *
ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
{
    uint8_t expected_sha1[SHA1_DIGEST_SIZE];
    uint8_t actual_sha1[SHA1_DIGEST_SIZE];
    struct ovsdb_error *error;
    off_t data_offset;
    unsigned long data_length;
    struct json *json;
    char header[128];

    *jsonp = json = NULL;

    if (file->read_error) {
        return ovsdb_error_clone(file->read_error);
    } else if (file->mode == OVSDB_LOG_WRITE) {
        return OVSDB_BUG("reading file in write mode");
    }

    if (!fgets(header, sizeof header, file->stream)) {
        if (feof(file->stream)) {
            error = NULL;
        } else {
            error = ovsdb_io_error(errno, "%s: read failed", file->name);
        }
        goto error;
    }

    if (!parse_header(header, &data_length, expected_sha1)) {
        error = ovsdb_syntax_error(NULL, NULL, "%s: parse error at offset "
                                   "%lld in header line \"%.*s\"",
                                   file->name, (long long int) file->offset,
                                   (int) strcspn(header, "\n"), header);
        goto error;
    }

    data_offset = file->offset + strlen(header);
    error = parse_body(file, data_offset, data_length, actual_sha1, &json);
    if (error) {
        goto error;
    }

    if (memcmp(expected_sha1, actual_sha1, SHA1_DIGEST_SIZE)) {
        error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
                                   "offset %lld have SHA-1 hash "SHA1_FMT" "
                                   "but should have hash "SHA1_FMT,
                                   file->name, data_length,
                                   (long long int) data_offset,
                                   SHA1_ARGS(actual_sha1),
                                   SHA1_ARGS(expected_sha1));
        goto error;
    }

    if (json->type == JSON_STRING) {
        error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
                                   "offset %lld are not valid JSON (%s)",
                                   file->name, data_length,
                                   (long long int) data_offset,
                                   json->u.string);
        goto error;
    }

    file->prev_offset = file->offset;
    file->offset = data_offset + data_length;
    *jsonp = json;
    return NULL;

error:
    file->read_error = ovsdb_error_clone(error);
    json_destroy(json);
    return error;
}
struct ovsdb_error *
ovsdb_parser_get_error(const struct ovsdb_parser *parser)
{
    return parser->error ? ovsdb_error_clone(parser->error) : NULL;
}
Example #3
0
struct ovsdb_error *
ovsdb_log_write(struct ovsdb_log *file, struct json *json)
{
    uint8_t sha1[SHA1_DIGEST_SIZE];
    struct ovsdb_error *error;
    char *json_string;
    char header[128];
    size_t length;

    json_string = NULL;

    if (file->write_error) {
        return ovsdb_error_clone(file->write_error);
    } else if (file->mode == OVSDB_LOG_READ) {
        file->mode = OVSDB_LOG_WRITE;
        if (fseeko(file->stream, file->offset, SEEK_SET)) {
            error = ovsdb_io_error(errno, "%s: cannot seek to offset %lld",
                                   file->name, (long long int) file->offset);
            goto error;
        }
        if (ftruncate(fileno(file->stream), file->offset)) {
            error = ovsdb_io_error(errno, "%s: cannot truncate to length %lld",
                                   file->name, (long long int) file->offset);
            goto error;
        }
    }

    if (json->type != JSON_OBJECT && json->type != JSON_ARRAY) {
        error = OVSDB_BUG("bad JSON type");
        goto error;
    }

    /* Compose content.  Add a new-line (replacing the null terminator) to make
     * the file easier to read, even though it has no semantic value.  */
    json_string = json_to_string(json, 0);
    length = strlen(json_string) + 1;
    json_string[length - 1] = '\n';

    /* Compose header. */
    sha1_bytes(json_string, length, sha1);
    snprintf(header, sizeof header, "%s%zu "SHA1_FMT"\n",
             magic, length, SHA1_ARGS(sha1));

    /* Write. */
    if (fwrite(header, strlen(header), 1, file->stream) != 1
        || fwrite(json_string, length, 1, file->stream) != 1
        || fflush(file->stream))
    {
        error = ovsdb_io_error(errno, "%s: write failed", file->name);

        /* Remove any partially written data, ignoring errors since there is
         * nothing further we can do. */
        ignore(ftruncate(fileno(file->stream), file->offset));

        goto error;
    }

    file->offset += strlen(header) + length;
    free(json_string);
    return NULL;

error:
    file->write_error = ovsdb_error_clone(error);
    free(json_string);
    return error;
}