mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #17797 from jue89/feature/pkg-tiny-vcdiff
Add package tiny-vcdiff
This commit is contained in:
commit
cb27a267a9
@ -108,6 +108,7 @@
|
||||
/pkg/openthread/ @Hyungsin @jia200x
|
||||
/pkg/semtech-loramac/ @aabadie @jia200x
|
||||
/pkg/tinydtls/ @rfuentess @leandrolanzieri
|
||||
/pkg/tinyvcdiff/ @jue89
|
||||
/pkg/u8g2/ @basilfx
|
||||
/pkg/ucglib/ @basilfx
|
||||
/pkg/wakaama/ @leandrolanzieri
|
||||
|
@ -67,6 +67,7 @@ rsource "tiny-asn1/Kconfig"
|
||||
rsource "tinycbor/Kconfig"
|
||||
rsource "tinycrypt/Kconfig"
|
||||
rsource "tinydtls/Kconfig"
|
||||
rsource "tinyvcdiff/Kconfig"
|
||||
rsource "tlsf/Kconfig"
|
||||
rsource "tweetnacl/Kconfig"
|
||||
rsource "u8g2/Kconfig"
|
||||
|
46
pkg/tinyvcdiff/Kconfig
Normal file
46
pkg/tinyvcdiff/Kconfig
Normal file
@ -0,0 +1,46 @@
|
||||
# Copyright (c) 2022 Juergen Fitschen
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
menuconfig PACKAGE_TINYVCDIFF
|
||||
bool "Tiny VCDIFF"
|
||||
depends on TEST_KCONFIG
|
||||
|
||||
if PACKAGE_TINYVCDIFF
|
||||
|
||||
config TINYVCDIFF_BUFFER_SIZE
|
||||
int "Buffer size"
|
||||
default 128
|
||||
help
|
||||
For VCDIFF copy and run instruction the library requires a buffer.
|
||||
The best performance is achieved for sizes of typical page sizes of
|
||||
the underlying MTD or VFS backend. But a size of just 1 byte would
|
||||
work, too.
|
||||
|
||||
menuconfig MODULE_TINYVCDIFF_MTD
|
||||
bool "MTD Backend"
|
||||
depends on MODULE_MTD
|
||||
default y
|
||||
help
|
||||
Use a MTD device as VCDIFF target or source.
|
||||
|
||||
if MODULE_TINYVCDIFF_MTD
|
||||
|
||||
config TINYVCDIFF_MTD_WRITE_SIZE
|
||||
int "Write size"
|
||||
default 4
|
||||
help
|
||||
Alignment and minimum size for MTD write access.
|
||||
|
||||
endif # MODULE_TINYVCDIFF_MTD
|
||||
|
||||
config MODULE_TINYVCDIFF_VFS
|
||||
bool "VFS Backend"
|
||||
depends on MODULE_VFS
|
||||
default y
|
||||
help
|
||||
Use a VFS file as VCDIFF target or source.
|
||||
|
||||
endif # PACKAGE_TINYVCDIFF
|
9
pkg/tinyvcdiff/Makefile
Normal file
9
pkg/tinyvcdiff/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
PKG_NAME=tinyvcdiff
|
||||
PKG_URL=https://github.com/jue89/tiny-vcdiff.git
|
||||
PKG_VERSION=e1a679f36d0212f2b84057a70c72f6e9deda45b3
|
||||
PKG_LICENSE=MIT
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
|
||||
all:
|
||||
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/src -f $(CURDIR)/$(PKG_NAME).mk
|
7
pkg/tinyvcdiff/Makefile.dep
Normal file
7
pkg/tinyvcdiff/Makefile.dep
Normal file
@ -0,0 +1,7 @@
|
||||
ifneq (,$(filter mtd,$(USEMODULE)))
|
||||
USEMODULE += tinyvcdiff_mtd
|
||||
endif
|
||||
|
||||
ifneq (,$(filter vfs,$(USEMODULE)))
|
||||
USEMODULE += tinyvcdiff_vfs
|
||||
endif
|
19
pkg/tinyvcdiff/Makefile.include
Normal file
19
pkg/tinyvcdiff/Makefile.include
Normal file
@ -0,0 +1,19 @@
|
||||
# Buffer size for vcdiff
|
||||
CONFIG_TINYVCDIFF_BUFFER_SIZE ?= 128
|
||||
CFLAGS += -DVCDIFF_BUFFER_SIZE=$(CONFIG_TINYVCDIFF_BUFFER_SIZE)
|
||||
|
||||
# Disable debugging if DEVELHELP is turned off
|
||||
ifneq ($(DEVELHELP),1)
|
||||
CFLAGS += -DVCDIFF_NDEBUG
|
||||
endif
|
||||
|
||||
INCLUDES += -I$(PKGDIRBASE)/tinyvcdiff/include
|
||||
INCLUDES += -I$(RIOTPKG)/tinyvcdiff/include
|
||||
|
||||
ifneq (,$(filter tinyvcdiff_mtd,$(USEMODULE)))
|
||||
DIRS += $(RIOTPKG)/tinyvcdiff/contrib/tinyvcdiff_mtd
|
||||
endif
|
||||
|
||||
ifneq (,$(filter tinyvcdiff_vfs,$(USEMODULE)))
|
||||
DIRS += $(RIOTPKG)/tinyvcdiff/contrib/tinyvcdiff_vfs
|
||||
endif
|
3
pkg/tinyvcdiff/contrib/tinyvcdiff_mtd/Makefile
Normal file
3
pkg/tinyvcdiff/contrib/tinyvcdiff_mtd/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = tinyvcdiff_mtd
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
179
pkg/tinyvcdiff/contrib/tinyvcdiff_mtd/mtd.c
Normal file
179
pkg/tinyvcdiff/contrib/tinyvcdiff_mtd/mtd.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include "vcdiff_mtd.h"
|
||||
#include "assert.h"
|
||||
#include <string.h>
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
static int _erase (void *dev, size_t offset, size_t len)
|
||||
{
|
||||
int rc;
|
||||
vcdiff_mtd_t *mtd = dev;
|
||||
size_t addr = offset + len;
|
||||
size_t page = addr / mtd->dev->page_size;
|
||||
size_t sector = page / mtd->dev->pages_per_sector;
|
||||
size_t cnt = sector - mtd->next_erase_sector + 1;
|
||||
|
||||
/* early exit if all sectors are already in the erased state */
|
||||
if (cnt == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* erase sectors */
|
||||
rc = mtd_erase_sector(mtd->dev, mtd->next_erase_sector, cnt);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
mtd->next_erase_sector += cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _read (void *dev, uint8_t *dest, size_t offset, size_t len)
|
||||
{
|
||||
vcdiff_mtd_t *mtd = dev;
|
||||
|
||||
/* mtd_read_page will take care of calculation the right page */
|
||||
int rc = mtd_read_page(mtd->dev, dest, 0, offset, len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _align_write (vcdiff_mtd_t *mtd, uint8_t **src, size_t *len)
|
||||
{
|
||||
size_t alignment_offset;
|
||||
size_t copy_len;
|
||||
|
||||
alignment_offset = mtd->offset % CONFIG_TINYVCDIFF_MTD_WRITE_SIZE;
|
||||
if (alignment_offset == 0) {
|
||||
/* we are already aligned */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check how many bytes have to be copied to be aligned */
|
||||
copy_len = CONFIG_TINYVCDIFF_MTD_WRITE_SIZE - alignment_offset;
|
||||
if (copy_len > *len) {
|
||||
copy_len = *len;
|
||||
}
|
||||
|
||||
/* copy unaligned bytes to the write buffer */
|
||||
memcpy(&mtd->write_buffer[alignment_offset], *src, copy_len);
|
||||
alignment_offset += copy_len;
|
||||
mtd->offset += copy_len;
|
||||
*len -= copy_len;
|
||||
*src += copy_len;
|
||||
DEBUG("_align_write: buffered %zuB for alignment\n", copy_len);
|
||||
|
||||
if (alignment_offset < CONFIG_TINYVCDIFF_MTD_WRITE_SIZE) {
|
||||
/* we haven't collected enough bytes, yet */
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(alignment_offset == CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
|
||||
|
||||
DEBUG("_align_write: write buffered data\n");
|
||||
|
||||
/* write buffer to mtd
|
||||
* mtd_read_page will take care of calculation the right page
|
||||
* it's safe to call mtd_read_page_raw: the erase driver already
|
||||
* prepared the sector for writing */
|
||||
return mtd_write_page_raw(mtd->dev, mtd->write_buffer, 0,
|
||||
mtd->offset - alignment_offset,
|
||||
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
|
||||
}
|
||||
|
||||
static int _write (void *dev, uint8_t *src, size_t offset, size_t len)
|
||||
{
|
||||
int rc;
|
||||
size_t to_copy;
|
||||
vcdiff_mtd_t *mtd = dev;
|
||||
|
||||
assert(offset == mtd->offset);
|
||||
|
||||
DEBUG("_write: 0x%zx + %zuB\n", mtd->offset, len);
|
||||
|
||||
/* align writes */
|
||||
rc = _align_write(dev, &src, &len);
|
||||
if (rc < 0) {
|
||||
/* an error occurred */
|
||||
return rc;
|
||||
} else if (len == 0) {
|
||||
/* no bytes are left */
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert((mtd->offset % CONFIG_TINYVCDIFF_MTD_WRITE_SIZE) == 0);
|
||||
|
||||
/* copy all aligned data */
|
||||
to_copy = (len / CONFIG_TINYVCDIFF_MTD_WRITE_SIZE) * CONFIG_TINYVCDIFF_MTD_WRITE_SIZE;
|
||||
rc = mtd_write_page_raw(mtd->dev, src, 0, mtd->offset, to_copy);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
mtd->offset += to_copy;
|
||||
len -= to_copy;
|
||||
src += to_copy;
|
||||
if (len == 0) {
|
||||
/* no bytes are left */
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(len < CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
|
||||
|
||||
/* copy remaining bytes into write_buffer */
|
||||
memcpy(mtd->write_buffer, src, len);
|
||||
mtd->offset += len;
|
||||
DEBUG("_write: buffered %zuB for alignment\n", len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _flush (void *dev)
|
||||
{
|
||||
vcdiff_mtd_t *mtd = dev;
|
||||
int rc;
|
||||
uint8_t buf[CONFIG_TINYVCDIFF_MTD_WRITE_SIZE];
|
||||
size_t alignment_offset;
|
||||
|
||||
alignment_offset = mtd->offset % CONFIG_TINYVCDIFF_MTD_WRITE_SIZE;
|
||||
if (alignment_offset == 0) {
|
||||
/* we are already aligned -> no bytes are left in the buffer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG("_flush: write last %zuB\n", alignment_offset);
|
||||
|
||||
/* get present bytes from MTD to pad alignment */
|
||||
rc = mtd_read_page(mtd->dev, buf, 0, mtd->offset - alignment_offset,
|
||||
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* pad write buffer */
|
||||
memcpy(&mtd->write_buffer[alignment_offset], &buf[alignment_offset],
|
||||
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE - alignment_offset);
|
||||
|
||||
/* write last buffer */
|
||||
rc = mtd_write_page_raw(mtd->dev, mtd->write_buffer, 0,
|
||||
mtd->offset - alignment_offset,
|
||||
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
const vcdiff_driver_t vcdiff_mtd_driver = {
|
||||
.erase = _erase,
|
||||
.read = _read,
|
||||
.write = _write,
|
||||
.flush = _flush
|
||||
};
|
3
pkg/tinyvcdiff/contrib/tinyvcdiff_vfs/Makefile
Normal file
3
pkg/tinyvcdiff/contrib/tinyvcdiff_vfs/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = tinyvcdiff_vfs
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
69
pkg/tinyvcdiff/contrib/tinyvcdiff_vfs/vfs.c
Normal file
69
pkg/tinyvcdiff/contrib/tinyvcdiff_vfs/vfs.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include "vcdiff_vfs.h"
|
||||
#include <unistd.h>
|
||||
#include "errno.h"
|
||||
|
||||
static int _read (void *dev, uint8_t *dest, size_t offset, size_t len)
|
||||
{
|
||||
int rc;
|
||||
vcdiff_vfs_t *vfs = dev;
|
||||
|
||||
/* seek to the given offset */
|
||||
rc = vfs_lseek(vfs->fd, offset, SEEK_SET);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
} else if ((size_t) rc != offset) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* read from file into the buffer */
|
||||
rc = vfs_read(vfs->fd, dest, len);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
} else if ((size_t) rc != len) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _write (void *dev, uint8_t *src, size_t offset, size_t len)
|
||||
{
|
||||
int rc;
|
||||
vcdiff_vfs_t *vfs = dev;
|
||||
|
||||
/* make sure to stay in the set file size bounds */
|
||||
if (offset + len > vfs->max_size) {
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
/* seek to the given offset */
|
||||
rc = vfs_lseek(vfs->fd, offset, SEEK_SET);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
} else if ((size_t) rc != offset) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* write all bytes to the file */
|
||||
rc = vfs_write(vfs->fd, src, len);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
} else if ((size_t) rc != len) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const vcdiff_driver_t vcdiff_vfs_driver = {
|
||||
.read = _read,
|
||||
.write = _write
|
||||
};
|
58
pkg/tinyvcdiff/doc.txt
Normal file
58
pkg/tinyvcdiff/doc.txt
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @defgroup pkg_tinyvcdiff Tiny VCDIFF
|
||||
* @ingroup pkg
|
||||
* @brief Decoder for interleaved VCDIFF deltas
|
||||
*
|
||||
* # Introduction
|
||||
*
|
||||
* tiny-vcdiff is a decoder for binary delta files that have been generated by
|
||||
* [open-vcdiff](https://github.com/google/open-vcdiff) in the interleaved format.
|
||||
*
|
||||
* # Usage
|
||||
*
|
||||
* Every delta requires a source (the known data) and a target (the reconstructed
|
||||
* data). This implementation provides backends for the @ref drivers_mtd and
|
||||
* @ref sys_vfs storage drivers.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* The example down below uses a @ref drivers_mtd device as known source data and
|
||||
* writes the resulting target data into a @ref sys_vfs file.
|
||||
*
|
||||
* ```c
|
||||
* #include "vcdiff.h"
|
||||
* #include "vcdiff_mtd.h"
|
||||
* #include "vcdiff_vfs.h"
|
||||
*
|
||||
* int apply_delta (const uint8_t *data, size_t data_len,
|
||||
* mtd_dev_t *source_mtd,
|
||||
* int traget_fd)
|
||||
* {
|
||||
* int rc;
|
||||
* vcdiff_t vcdiff;
|
||||
* vcdiff_init(&vcdiff);
|
||||
*
|
||||
* /* make sure source_mtd is already powered on */
|
||||
* vcdiff_mtd_t source = VCDIFF_MTD_INIT(source_mtd);
|
||||
* vcdiff_set_source_driver(&vcdiff, &vcdiff_mtd_driver, &source);
|
||||
*
|
||||
* /* make sure the vfs file is already opened for writing */
|
||||
* vcdiff_vfs_t target = VCDIFF_VFS_INIT(fd_target);
|
||||
* vcdiff_set_target_driver(&vcdiff, &vcdiff_vfs_driver, &target);
|
||||
*
|
||||
* rc = vcdiff_apply_delta(&vcdiff, data, data_len);
|
||||
* if (rc != 0) {
|
||||
* return rc;
|
||||
* }
|
||||
*
|
||||
* rc = vcdiff_finish(&vcdiff);
|
||||
* return rc;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* # License
|
||||
*
|
||||
* Licensed under MIT.
|
||||
*
|
||||
* @see https://github.com/jue89/tiny-vcdiff.git
|
||||
*/
|
75
pkg/tinyvcdiff/include/vcdiff_mtd.h
Normal file
75
pkg/tinyvcdiff/include/vcdiff_mtd.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @ingroup pkg_tinyvcdiff
|
||||
*
|
||||
* @author Juergen Fitschen <me@jue.yt>
|
||||
*/
|
||||
|
||||
#ifndef VCDIFF_MTD_H
|
||||
#define VCDIFF_MTD_H
|
||||
|
||||
#include "vcdiff.h"
|
||||
#include "mtd.h"
|
||||
|
||||
#ifndef CONFIG_TINYVCDIFF_MTD_WRITE_SIZE
|
||||
/**
|
||||
* @brief Alignment and minimum size for MTD write access
|
||||
*/
|
||||
#define CONFIG_TINYVCDIFF_MTD_WRITE_SIZE 4
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver for accessing MTD devices
|
||||
*/
|
||||
extern const vcdiff_driver_t vcdiff_mtd_driver;
|
||||
|
||||
/**
|
||||
* @brief Context for the underlying MTD device
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Instance of the backing MTD device
|
||||
*/
|
||||
mtd_dev_t *dev;
|
||||
|
||||
/**
|
||||
* @brief Number of the next sector that must be erased
|
||||
*/
|
||||
size_t next_erase_sector;
|
||||
|
||||
/**
|
||||
* @brief Buffer for aligned writes
|
||||
*/
|
||||
uint8_t write_buffer[CONFIG_TINYVCDIFF_MTD_WRITE_SIZE];
|
||||
|
||||
/**
|
||||
* @brief Current offset on the MTD device
|
||||
*/
|
||||
size_t offset;
|
||||
} vcdiff_mtd_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes vcdiff_mtd_t
|
||||
*/
|
||||
#define VCDIFF_MTD_INIT(DEV) { .dev = DEV }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VCDIFF_MTD_H */
|
||||
/** @} */
|
56
pkg/tinyvcdiff/include/vcdiff_vfs.h
Normal file
56
pkg/tinyvcdiff/include/vcdiff_vfs.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @ingroup pkg_tinyvcdiff
|
||||
*
|
||||
* @author Juergen Fitschen <me@jue.yt>
|
||||
*/
|
||||
|
||||
#ifndef VCDIFF_VFS_H
|
||||
#define VCDIFF_VFS_H
|
||||
|
||||
#include "vcdiff.h"
|
||||
#include "vfs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver for accessing VFS-based file access
|
||||
*/
|
||||
extern const vcdiff_driver_t vcdiff_vfs_driver;
|
||||
|
||||
/**
|
||||
* @brief Context for the underlying file
|
||||
*/
|
||||
typedef struct {
|
||||
int fd; /**< File descriptor of the VFS file */
|
||||
size_t max_size; /**< Maxmimum file size for vcdiff target files */
|
||||
} vcdiff_vfs_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes vcdiff_vfs_t with maximum allowed file size
|
||||
*/
|
||||
#define VCDIFF_VFS_INIT_MAX_SIZE(FD, SIZE) { .fd = FD, .max_size = SIZE }
|
||||
|
||||
/**
|
||||
* @brief Initializes vcdiff_vfs_t
|
||||
*/
|
||||
#define VCDIFF_VFS_INIT(FD) VCDIFF_VFS_INIT_MAX_SIZE(FD, SIZE_MAX)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VCDIFF_VFS_H */
|
||||
/** @} */
|
3
pkg/tinyvcdiff/tinyvcdiff.mk
Normal file
3
pkg/tinyvcdiff/tinyvcdiff.mk
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = tinyvcdiff
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
19
tests/pkg_tinyvcdiff/Makefile
Normal file
19
tests/pkg_tinyvcdiff/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
BLOBS += source.bin delta.bin target.bin
|
||||
|
||||
# Only run on native ...
|
||||
TEST_ON_CI_WHITELIST += native
|
||||
|
||||
USEMODULE += embunit
|
||||
|
||||
# Library under test
|
||||
USEPKG += tinyvcdiff
|
||||
|
||||
# MTD backend
|
||||
USEMODULE += mtd
|
||||
|
||||
# VFS backend
|
||||
USEPKG += littlefs2
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
25
tests/pkg_tinyvcdiff/Makefile.ci
Normal file
25
tests/pkg_tinyvcdiff/Makefile.ci
Normal file
@ -0,0 +1,25 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
samd10-xmini \
|
||||
slstk3400a \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32g0316-disco \
|
||||
stm32l0538-disco \
|
||||
waspmote-pro \
|
||||
#
|
10
tests/pkg_tinyvcdiff/README.md
Normal file
10
tests/pkg_tinyvcdiff/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
pkg_tinyvcdiff
|
||||
==============
|
||||
|
||||
This test patches the binary file `source.bin` using `delta.bin` and reconstructs `target.bin`.
|
||||
|
||||
`delta.bin` has been created with open-vcdiff:
|
||||
|
||||
```
|
||||
vcdiff delta -interleaved -dictionary source.bin <target.bin >delta.bin
|
||||
```
|
5
tests/pkg_tinyvcdiff/app.config.test
Normal file
5
tests/pkg_tinyvcdiff/app.config.test
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_MODULE_EMBUNIT=y
|
||||
CONFIG_MODULE_MTD=y
|
||||
CONFIG_MODULE_LITTLEFS2_FS=y
|
||||
CONFIG_PACKAGE_TINYVCDIFF=y
|
||||
CONFIG_PACKAGE_LITTLEFS2=y
|
BIN
tests/pkg_tinyvcdiff/delta.bin
Normal file
BIN
tests/pkg_tinyvcdiff/delta.bin
Normal file
Binary file not shown.
104
tests/pkg_tinyvcdiff/fakemtd.c
Normal file
104
tests/pkg_tinyvcdiff/fakemtd.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @ingroup tests
|
||||
* @brief Fake MTD device
|
||||
*
|
||||
* @author Juergen Fitschen <me@jue.yt>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "fakemtd.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
static inline uint32_t sector2offset(fake_mtd_t *ctx, uint32_t sector)
|
||||
{
|
||||
return sector * ctx->mtd.page_size * ctx->mtd.pages_per_sector;
|
||||
}
|
||||
|
||||
static inline uint32_t page2offset(fake_mtd_t *ctx, uint32_t page)
|
||||
{
|
||||
return page * ctx->mtd.page_size;
|
||||
}
|
||||
|
||||
static inline bool within_bounds(fake_mtd_t *ctx, uint32_t offset, uint32_t count)
|
||||
{
|
||||
return (offset + count) <= sizeof(ctx->buffer);
|
||||
}
|
||||
|
||||
static int _init(mtd_dev_t *dev)
|
||||
{
|
||||
(void) dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _read_page(mtd_dev_t *dev, void *buff, uint32_t page, uint32_t offset, uint32_t size)
|
||||
{
|
||||
fake_mtd_t *ctx = container_of(dev, fake_mtd_t, mtd);
|
||||
|
||||
DEBUG("fake_mtd: _read_page(%"PRIu32", %"PRIu32", %"PRIu32")\n", page, offset, size);
|
||||
|
||||
offset += page2offset(ctx, page);
|
||||
if (!within_bounds(ctx, offset, size)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
memcpy(buff, &ctx->buffer[offset], size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int _write_page(mtd_dev_t *dev, const void *buff, uint32_t page, uint32_t offset, uint32_t size)
|
||||
{
|
||||
fake_mtd_t *ctx = container_of(dev, fake_mtd_t, mtd);
|
||||
|
||||
DEBUG("fake_mtd: _write_page(%"PRIu32", %"PRIu32", %"PRIu32")\n", page, offset, size);
|
||||
|
||||
offset += page2offset(ctx, page);
|
||||
if (!within_bounds(ctx, offset, size)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[offset], buff, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int _erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t count)
|
||||
{
|
||||
fake_mtd_t *ctx = container_of(dev, fake_mtd_t, mtd);
|
||||
|
||||
DEBUG("fake_mtd: _erase_sector(%"PRIu32", %"PRIu32")\n", sector, count);
|
||||
|
||||
uint32_t offset = sector2offset(ctx, sector);
|
||||
uint32_t size = sector2offset(ctx, count);
|
||||
if (!within_bounds(ctx, offset, count)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[offset], 0xff, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const mtd_desc_t fake_mtd_driver = {
|
||||
.init = _init,
|
||||
.read_page = _read_page,
|
||||
.write_page = _write_page,
|
||||
.erase_sector = _erase_sector,
|
||||
};
|
||||
|
||||
/** @} */
|
75
tests/pkg_tinyvcdiff/fakemtd.h
Normal file
75
tests/pkg_tinyvcdiff/fakemtd.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @ingroup tests
|
||||
* @brief Fake MTD device
|
||||
*
|
||||
* @author Juergen Fitschen <me@jue.yt>
|
||||
*/
|
||||
#ifndef FAKEMTD_H
|
||||
#define FAKEMTD_H
|
||||
|
||||
#include "mtd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Page size
|
||||
*/
|
||||
#define FAKE_MTD_PAGE_SIZE 128
|
||||
|
||||
/**
|
||||
* @brief Pages per sector
|
||||
*/
|
||||
#define FAKE_MTD_PAGES_PER_SECTOR 4
|
||||
|
||||
/**
|
||||
* @brief Sector count
|
||||
*/
|
||||
#define FAKE_MTD_SECTOR_COUNT 4
|
||||
|
||||
/**
|
||||
* @brief Storage size in byte
|
||||
*/
|
||||
#define MAKE_MTD_MEM_SIZE (FAKE_MTD_PAGE_SIZE * \
|
||||
FAKE_MTD_PAGES_PER_SECTOR * \
|
||||
FAKE_MTD_SECTOR_COUNT)
|
||||
|
||||
/**
|
||||
* @brief Driver for fake MTD
|
||||
*/
|
||||
extern const mtd_desc_t fake_mtd_driver;
|
||||
|
||||
/**
|
||||
* @brief Context for the fake MTD
|
||||
*/
|
||||
typedef struct {
|
||||
mtd_dev_t mtd; /**< MTD instance */
|
||||
uint8_t buffer[MAKE_MTD_MEM_SIZE]; /**< Storage of the MTD */
|
||||
} fake_mtd_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes fake_mtd_t
|
||||
*/
|
||||
#define FAKE_MTD_INIT { .mtd = { .driver = &fake_mtd_driver, \
|
||||
.sector_count = FAKE_MTD_SECTOR_COUNT, \
|
||||
.pages_per_sector = FAKE_MTD_PAGES_PER_SECTOR, \
|
||||
.page_size = FAKE_MTD_PAGE_SIZE } }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FAKEMTD_H */
|
||||
/** @} */
|
139
tests/pkg_tinyvcdiff/main.c
Normal file
139
tests/pkg_tinyvcdiff/main.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Juergen Fitschen
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief tinyvcdiff library backend tests
|
||||
*
|
||||
* @author Juergen Fitschen <me@jue.yt>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "embUnit.h"
|
||||
#include "vcdiff.h"
|
||||
#include "vcdiff_mtd.h"
|
||||
#include "vcdiff_vfs.h"
|
||||
#include "fakemtd.h"
|
||||
#include "fs/littlefs2_fs.h"
|
||||
|
||||
/* Generated using open-vcdiff:
|
||||
* $ echo "Hello world! I hope you are doing well ..." >source.bin
|
||||
* $ echo "Hello universe! I hope you are doing well ..." >target.bin
|
||||
* $ vcdiff delta -interleaved -dictionary source.bin <target.bin >delta.bin */
|
||||
#include "blob/source.bin.h"
|
||||
#include "blob/target.bin.h"
|
||||
#include "blob/delta.bin.h"
|
||||
|
||||
static vcdiff_t vcdiff;
|
||||
static fake_mtd_t storage_a = FAKE_MTD_INIT;
|
||||
static fake_mtd_t storage_b = FAKE_MTD_INIT;
|
||||
|
||||
static void test_tinyvcdiff_mtd(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
mtd_dev_t * source_mtd = &storage_a.mtd;
|
||||
vcdiff_mtd_t source_vcdiff = VCDIFF_MTD_INIT(source_mtd);
|
||||
|
||||
mtd_dev_t * target_mtd = &storage_b.mtd;
|
||||
vcdiff_mtd_t target_vcdiff = VCDIFF_MTD_INIT(target_mtd);
|
||||
|
||||
/* write source data to fake-mtd */
|
||||
mtd_write(source_mtd, source_bin, 0, source_bin_len);
|
||||
|
||||
/* setup vcdiff */
|
||||
vcdiff_init(&vcdiff);
|
||||
vcdiff_set_source_driver(&vcdiff, &vcdiff_mtd_driver, &source_vcdiff);
|
||||
vcdiff_set_target_driver(&vcdiff, &vcdiff_mtd_driver, &target_vcdiff);
|
||||
|
||||
/* apply diff */
|
||||
rc = vcdiff_apply_delta(&vcdiff, delta_bin, delta_bin_len);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = vcdiff_finish(&vcdiff);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
/* check reconsturcted target */
|
||||
uint8_t target_buf[target_bin_len];
|
||||
mtd_read(target_mtd, target_buf, 0, sizeof(target_buf));
|
||||
TEST_ASSERT_EQUAL_INT(0, memcmp(target_bin, target_buf, sizeof(target_buf)));
|
||||
}
|
||||
|
||||
static void test_tinyvcdiff_vfs(void)
|
||||
{
|
||||
int rc;
|
||||
int source_fd, target_fd;
|
||||
|
||||
littlefs2_desc_t fs = { .dev = &storage_a.mtd };
|
||||
vfs_mount_t mnt = {
|
||||
.mount_point = "/mnt",
|
||||
.fs = &littlefs2_file_system,
|
||||
.private_data = &fs,
|
||||
};
|
||||
vfs_format(&mnt);
|
||||
vfs_mount(&mnt);
|
||||
|
||||
/* write source data to fs */
|
||||
source_fd = vfs_open("/mnt/source", O_WRONLY | O_CREAT, 0);
|
||||
vfs_write(source_fd, source_bin, source_bin_len);
|
||||
vfs_close(source_fd);
|
||||
|
||||
/* open source and target file */
|
||||
source_fd = vfs_open("/mnt/source", O_RDONLY, 0);
|
||||
vcdiff_vfs_t source_vcdiff = VCDIFF_VFS_INIT(source_fd);
|
||||
target_fd = vfs_open("/mnt/target", O_WRONLY | O_CREAT, 0);
|
||||
vcdiff_vfs_t target_vcdiff = VCDIFF_VFS_INIT(target_fd);
|
||||
|
||||
/* setup vcdiff */
|
||||
vcdiff_init(&vcdiff);
|
||||
vcdiff_set_source_driver(&vcdiff, &vcdiff_vfs_driver, &source_vcdiff);
|
||||
vcdiff_set_target_driver(&vcdiff, &vcdiff_vfs_driver, &target_vcdiff);
|
||||
|
||||
/* apply diff */
|
||||
rc = vcdiff_apply_delta(&vcdiff, delta_bin, delta_bin_len);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
rc = vcdiff_finish(&vcdiff);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
vfs_close(source_fd);
|
||||
vfs_close(target_fd);
|
||||
|
||||
/* check reconsturcted target */
|
||||
target_fd = vfs_open("/mnt/target", O_RDONLY, 0);
|
||||
uint8_t target_buf[target_bin_len];
|
||||
vfs_read(target_fd, target_buf, sizeof(target_buf));
|
||||
TEST_ASSERT_EQUAL_INT(0, memcmp(target_bin, target_buf, sizeof(target_buf)));
|
||||
vfs_close(target_fd);
|
||||
|
||||
vfs_umount(&mnt);
|
||||
}
|
||||
|
||||
Test *tests_tinyvcdiff(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_tinyvcdiff_mtd),
|
||||
new_TestFixture(test_tinyvcdiff_vfs),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(tinycvdiff_tests, NULL, NULL, fixtures);
|
||||
return (Test*)&tinycvdiff_tests;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TESTS_START();
|
||||
TESTS_RUN(tests_tinyvcdiff());
|
||||
TESTS_END();
|
||||
return 0;
|
||||
}
|
1
tests/pkg_tinyvcdiff/source.bin
Normal file
1
tests/pkg_tinyvcdiff/source.bin
Normal file
@ -0,0 +1 @@
|
||||
Hello world! I hope you are doing well ...
|
1
tests/pkg_tinyvcdiff/target.bin
Normal file
1
tests/pkg_tinyvcdiff/target.bin
Normal file
@ -0,0 +1 @@
|
||||
Hello universe! I hope you are doing well ...
|
18
tests/pkg_tinyvcdiff/tests/01-run.py
Executable file
18
tests/pkg_tinyvcdiff/tests/01-run.py
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2022 Juergen Fitschen
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
import sys
|
||||
from testrunner import run
|
||||
|
||||
|
||||
def testfunc(child):
|
||||
child.expect("OK")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run(testfunc))
|
Loading…
Reference in New Issue
Block a user