kv_lfs.h
#ifndef KV_LFS_H
#define KV_LFS_H
#include <stddef.h>
#include <stdbool.h>
int kv_init(const char *mount_point);
int kv_set(const char *key, const void *val, size_t len);
int kv_get(const char *key, void *buf, size_t *len);
int kv_del(const char *key);
bool kv_exist(const char *key);
void kv_deinit(void);
#endif
kv_lfs.c
#include "kv_lfs.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "lfs.h"
#define KV_MAX_KEY 31
#define KV_TMP_FILE "_kv.tmp"
static char g_mount[64] = {0};
static int _make_path(char *dst, size_t dst_len, const char *key)
{
if (strchr(key, '/')) return -1;
int n = snprintf(dst, dst_len, "%s/%s", g_mount, key);
return (n < (int)dst_len) ? 0 : -1;
}
int kv_init(const char *mount_point)
{
strncpy(g_mount, mount_point, sizeof(g_mount) - 1);
struct stat st;
if (stat(g_mount, &st) != 0 && mkdir(g_mount, 0777) != 0) return -1;
return 0;
}
int kv_set(const char *key, const void *val, size_t len)
{
char path[128], tmp[128];
if (_make_path(path, sizeof(path), key) < 0) return -1;
if (snprintf(tmp, sizeof(tmp), "%s/%s", g_mount, KV_TMP_FILE) >= (int)sizeof(tmp)) return -1;
FILE *f = fopen(tmp, "wb");
if (!f) return -1;
if (fwrite(val, 1, len, f) != len) { fclose(f); unlink(tmp); return -1; }
if (fflush(f) != 0 || fclose(f) != 0) { unlink(tmp); return -1; }
return rename(tmp, path) == 0 ? 0 : -1;
}
int kv_get(const char *key, void *buf, size_t *len)
{
char path[128];
if (_make_path(path, sizeof(path), key) < 0) return -1;
struct stat st;
if (stat(path, &st) != 0) return -1;
FILE *f = fopen(path, "rb");
if (!f) return -1;
size_t need = *len;
*len = fread(buf, 1, need, f);
fclose(f);
return 0;
}
int kv_del(const char *key)
{
char path[128];
if (_make_path(path, sizeof(path), key) < 0) return -1;
return unlink(path) == 0 ? 0 : -1;
}
bool kv_exist(const char *key)
{
char path[128];
if (_make_path(path, sizeof(path), key) < 0) return false;
return access(path, F_OK) == 0;
}
void kv_deinit(void) { }
test.c
kv_init("/lfs/kv");
uint32_t boot_cnt = 0;
size_t len = sizeof(boot_cnt);
if (kv_get("boot_cnt", &boot_cnt, &len) == 0)
boot_cnt++;
else
boot_cnt = 1;
kv_set("boot_cnt", &boot_cnt, sizeof(boot_cnt));
FILE *fp = fopen("/userdata/fw.bin", "rb");
char buf[4096];
size_t n;
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
kv_set("fw", buf, n);
fclose(fp);