1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <zircon/compiler.h>
10 
11 __BEGIN_CDECLS
12 
13 typedef struct kvstore kvstore_t;
14 
15 #define KVS_OK                0
16 #define KVS_ERR_INTERNAL     -1
17 #define KVS_ERR_BAD_PARAM    -2
18 #define KVS_ERR_OUT_OF_SPACE -3
19 #define KVS_ERR_NOT_FOUND    -4
20 #define KVS_ERR_PARSE_HDR    -5
21 #define KVS_ERR_PARSE_REC    -6
22 #define KVS_ERR_PARSE_CRC    -7
23 
24 // KVStore API
25 // -----------
26 
27 // Setup a new, empty kvstore, backed by buffer.
28 void kvs_init(kvstore_t* kvs, void* buffer, size_t buflen);
29 
30 // Initialize a kvstore (read from disk, etc), backed by buffer.
31 int kvs_load(kvstore_t* kvs, void* buffer, size_t buflen);
32 
33 // Prepare kvstore for saving (compute checksum & update header).
34 // On success kvs->data and kvs->datalen represents the data
35 // to write to storage.
36 int kvs_save(kvstore_t* kvs);
37 
38 
39 // Adds a new key and value, provided there is space.
40 // Does not check for duplicates.
41 int kvs_addn(kvstore_t* kvs, const void* key, size_t klen,
42              const void* val, size_t vlen);
43 
44 // Adds a new key and value, provided there is space.
45 // Does not check for duplicates.
46 int kvs_add(kvstore_t* kvs, const char* key, const char* value);
47 
48 
49 // Locates key and returns its value and OK, else NOT_FOUND
50 // returned pointer is not guaranteed stable if kvstore is mutated.
51 int kvs_getn(kvstore_t* kvs, const void* key, size_t klen,
52              const void** val, size_t* vlen);
53 
54 // Locates key and returns its value if found, otherwise returns fallback
55 // returned pointer is not guaranteed stable if kvstore is mutated.
56 const char* kvs_get(kvstore_t* kvs, const char* key, const char* fallback);
57 
58 
59 // Calls func() for each key/value pair.
60 // Return KVS_OK at the end, or stops and returns whatever func()
61 // returned. if func returns non-zero.
62 int kvs_foreach(kvstore_t* kvs, void *cookie,
63                 int (*func)(void *cookie, const char* key, const char* val));
64 
65 
66 // KVStore Wire Format and Internals
67 // ---------------------------------
68 
69 // <header> <kventry>* [ <signature> ]
70 //
71 // <header> := <u64:version> <u32:flags> <u32:length> <u32:crc32> <u32:reserved>
72 // <kventry> := <u8:klen> <u8:vlen> <u8[klen]:key> <u8:0> <u8[vlen]:value> <u8:0>
73 // <signature> := TBD
74 
75 // echo -n "kvstore-version-1" | sha256sum (LSB)
76 #define KVSTORE_VERSION 0x540f19caa7bf19dcUL
77 
78 #define KVSTORE_FLAG_SIGNED 1
79 
80 struct kvstore {
81     void* data;
82     size_t datalen;
83     size_t datamax;
84     size_t kvcount;
85 };
86 
87 typedef struct kvshdr {
88     uint64_t version;
89     uint32_t flags;
90     uint32_t length;
91     uint32_t reserved;
92     uint32_t crc;
93 } kvshdr_t;
94 
95 __END_CDECLS
96