cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

json.c (4026B)


      1/* Parse JSON files using the JSMN parser. */
      2
      3/*
      4 * Copyright (c) 2014, Intel Corporation
      5 * All rights reserved.
      6 *
      7 * Redistribution and use in source and binary forms, with or without
      8 * modification, are permitted provided that the following conditions are met:
      9 *
     10 * 1. Redistributions of source code must retain the above copyright notice,
     11 * this list of conditions and the following disclaimer.
     12 *
     13 * 2. Redistributions in binary form must reproduce the above copyright
     14 * notice, this list of conditions and the following disclaimer in the
     15 * documentation and/or other materials provided with the distribution.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     28 * OF THE POSSIBILITY OF SUCH DAMAGE.
     29*/
     30
     31#include <stdlib.h>
     32#include <string.h>
     33#include <sys/mman.h>
     34#include <sys/stat.h>
     35#include <fcntl.h>
     36#include <stdio.h>
     37#include <errno.h>
     38#include <unistd.h>
     39#include "jsmn.h"
     40#include "json.h"
     41#include <linux/kernel.h>
     42
     43
     44static char *mapfile(const char *fn, size_t *size)
     45{
     46	unsigned ps = sysconf(_SC_PAGESIZE);
     47	struct stat st;
     48	char *map = NULL;
     49	int err;
     50	int fd = open(fn, O_RDONLY);
     51
     52	if (fd < 0 && verbose > 0 && fn) {
     53		pr_err("Error opening events file '%s': %s\n", fn,
     54				strerror(errno));
     55	}
     56
     57	if (fd < 0)
     58		return NULL;
     59	err = fstat(fd, &st);
     60	if (err < 0)
     61		goto out;
     62	*size = st.st_size;
     63	map = mmap(NULL,
     64		   (st.st_size + ps - 1) & ~(ps - 1),
     65		   PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
     66	if (map == MAP_FAILED)
     67		map = NULL;
     68out:
     69	close(fd);
     70	return map;
     71}
     72
     73static void unmapfile(char *map, size_t size)
     74{
     75	unsigned ps = sysconf(_SC_PAGESIZE);
     76	munmap(map, roundup(size, ps));
     77}
     78
     79/*
     80 * Parse json file using jsmn. Return array of tokens,
     81 * and mapped file. Caller needs to free array.
     82 */
     83jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len)
     84{
     85	jsmn_parser parser;
     86	jsmntok_t *tokens;
     87	jsmnerr_t res;
     88	unsigned sz;
     89
     90	*map = mapfile(fn, size);
     91	if (!*map)
     92		return NULL;
     93	/* Heuristic */
     94	sz = *size * 16;
     95	tokens = malloc(sz);
     96	if (!tokens)
     97		goto error;
     98	jsmn_init(&parser);
     99	res = jsmn_parse(&parser, *map, *size, tokens,
    100			 sz / sizeof(jsmntok_t));
    101	if (res != JSMN_SUCCESS) {
    102		pr_err("%s: json error %s\n", fn, jsmn_strerror(res));
    103		goto error_free;
    104	}
    105	if (len)
    106		*len = parser.toknext;
    107	return tokens;
    108error_free:
    109	free(tokens);
    110error:
    111	unmapfile(*map, *size);
    112	return NULL;
    113}
    114
    115void free_json(char *map, size_t size, jsmntok_t *tokens)
    116{
    117	free(tokens);
    118	unmapfile(map, size);
    119}
    120
    121static int countchar(char *map, char c, int end)
    122{
    123	int i;
    124	int count = 0;
    125	for (i = 0; i < end; i++)
    126		if (map[i] == c)
    127			count++;
    128	return count;
    129}
    130
    131/* Return line number of a jsmn token */
    132int json_line(char *map, jsmntok_t *t)
    133{
    134	return countchar(map, '\n', t->start) + 1;
    135}
    136
    137static const char * const jsmn_types[] = {
    138	[JSMN_PRIMITIVE] = "primitive",
    139	[JSMN_ARRAY] = "array",
    140	[JSMN_OBJECT] = "object",
    141	[JSMN_STRING] = "string"
    142};
    143
    144#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?")
    145
    146/* Return type name of a jsmn token */
    147const char *json_name(jsmntok_t *t)
    148{
    149	return LOOKUP(jsmn_types, t->type);
    150}
    151
    152int json_len(jsmntok_t *t)
    153{
    154	return t->end - t->start;
    155}
    156
    157/* Is string t equal to s? */
    158int json_streq(char *map, jsmntok_t *t, const char *s)
    159{
    160	unsigned len = json_len(t);
    161	return len == strlen(s) && !strncasecmp(map + t->start, s, len);
    162}