mirror of
https://github.com/Thesola10/umd-livepatch.git
synced 2025-04-19 22:13:22 +00:00
Implementing patch algorithm
This commit is contained in:
parent
d4fa58acfe
commit
8f3dd9c61b
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
TARGET = umd_livepatch
|
TARGET = umd_livepatch
|
||||||
C_OBJS = patch.o io_funcs.o main.o \
|
C_OBJS = patch.o io_funcs.o main.o \
|
||||||
stdio_glue.o umdiff/file.o
|
stdio_glue.o umdiff/file.o umdiff/patch.o
|
||||||
OBJS = $(C_OBJS) imports.o
|
OBJS = $(C_OBJS) imports.o
|
||||||
all: $(TARGET).prx
|
all: $(TARGET).prx
|
||||||
INCDIR = $(ARKROOT)/common/include $(ARKROOT)/core/systemctrl/include $(LIBRSYNC)/src
|
INCDIR = $(ARKROOT)/common/include $(ARKROOT)/core/systemctrl/include $(LIBRSYNC)/src
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
TARGET = umdiff
|
TARGET = umdiff
|
||||||
C_OBJS = main.c.o compare.c.o file.c.o patch.c.o
|
C_OBJS = main.c.o rdiff.c.o compare.c.o file.c.o patch.c.o
|
||||||
OBJS = $(C_OBJS)
|
OBJS = $(C_OBJS)
|
||||||
|
|
||||||
CMAKE := cmake
|
CMAKE := cmake
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
*
|
*
|
||||||
* The functions defined here control reading and writing UMDiff files from
|
* The functions defined here control reading and writing UMDiff files from
|
||||||
* in-memory structure @ref umdiff_File.
|
* in-memory structure @ref umdiff_File.
|
||||||
|
*
|
||||||
|
* @warning This file is reused by umd_livepatch. Do not allocate on the heap!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "umdiff.h"
|
#include "umdiff.h"
|
||||||
@ -28,7 +30,7 @@ _impl_umdiff_Header_rectify(umdiff_Header *hdr)
|
|||||||
long len_preamble = sizeof(umdiff_Header)
|
long len_preamble = sizeof(umdiff_Header)
|
||||||
+ (sizeof(umdiff_Command) * hdr->cmd_count);
|
+ (sizeof(umdiff_Command) * hdr->cmd_count);
|
||||||
|
|
||||||
strncpy(hdr->magic, umdiff_File_$MAGIC, 7);
|
memcpy(hdr->magic, umdiff_File_$MAGIC, 7);
|
||||||
hdr->version = umdiff_File_$VERSION;
|
hdr->version = umdiff_File_$VERSION;
|
||||||
hdr->data_start = _impl_umdiff_alignSector$(len_preamble);
|
hdr->data_start = _impl_umdiff_alignSector$(len_preamble);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* @file patch.c
|
||||||
|
* @author Karim Vergnes <me@thesola.io>
|
||||||
|
* @copyright GPLv2
|
||||||
|
* @brief UMDiff patch algorithms
|
||||||
|
*
|
||||||
|
* Functions to redirect read requests and reconstruct the result file given
|
||||||
|
* a set of UMDiff commands.
|
||||||
|
*
|
||||||
|
* @warning This file is reused by umd_livepatch. Do not allocate on the heap!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "umdiff.h"
|
||||||
|
|
||||||
|
static long
|
||||||
|
_impl_umdiff_Command_read(umdiff_Command cmd, void *dest, long count, long offset,
|
||||||
|
umdiff_ReadCallback read_source,
|
||||||
|
umdiff_ReadCallback read_patchFile)
|
||||||
|
{
|
||||||
|
long rel_offset = offset - (cmd.sector_start * ISO_SECTOR_SIZE);
|
||||||
|
|
||||||
|
//TODO: implement read system
|
||||||
|
// 1. perform first truncated read
|
||||||
|
// 2. if repeat-length remains, perform second full read
|
||||||
|
// 3. if repeat-length still remains, memcpy second read range onwards
|
||||||
|
// -> saved a bunch of i/o calls at the guest ptr's expense!
|
||||||
|
}
|
||||||
|
|
||||||
|
static umdiff_Command *
|
||||||
|
_impl_umdiff_File_readIndexCmds(umdiff_File *file, long offset_sector,
|
||||||
|
umdiff_ReadCallback read_patchFile)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int index = offset_sector / 1024;
|
||||||
|
|
||||||
|
// stateful optimization: don't re-read the same commands
|
||||||
|
if (index == file->last_index)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (file->mode == umdiff_FileFlags_HEADER_ONLY) {
|
||||||
|
res = read_patchFile(file->commands, sizeof(umdiff_Command) * 1024,
|
||||||
|
file->hdr.index[index]);
|
||||||
|
return file->commands;
|
||||||
|
} else {
|
||||||
|
return file->commands + file->hdr.index[index] - umdiff_File_$COMMANDS_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->last_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umdiff_File_readPatched(umdiff_File *file, void *dest, long count, long offset,
|
||||||
|
umdiff_ReadCallback read_source,
|
||||||
|
umdiff_ReadCallback read_patchFile)
|
||||||
|
{
|
||||||
|
long res;
|
||||||
|
umdiff_Command *commands;
|
||||||
|
umdiff_Command *curCommand;
|
||||||
|
|
||||||
|
#define $offset_sectors (offset / ISO_SECTOR_SIZE)
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
commands = _impl_umdiff_File_readIndexCmds(file, $offset_sectors,
|
||||||
|
read_patchFile);
|
||||||
|
curCommand = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1024; i++) {
|
||||||
|
if (commands[i].sector_start <= $offset_sectors) {
|
||||||
|
curCommand = &commands[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = _impl_umdiff_Command_read(*curCommand, dest, count, offset,
|
||||||
|
read_source, read_patchFile);
|
||||||
|
dest += res;
|
||||||
|
count -= res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ft=c.doxygen
|
15
umdiff/rdiff.c
Normal file
15
umdiff/rdiff.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @file rdiff.c
|
||||||
|
* @author Karim Vergnes <me@thesola.io>
|
||||||
|
* @copyright GPLv2
|
||||||
|
* @brief rsync diff parser
|
||||||
|
*
|
||||||
|
* This file parses and converts rdiff commands into equivalent UMDiff commands
|
||||||
|
* and manages the corresponding data bucket.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <prototab.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// vim: ft=c.doxygen
|
@ -18,7 +18,7 @@
|
|||||||
#define umdiff_File_$VERSION 0x00
|
#define umdiff_File_$VERSION 0x00
|
||||||
|
|
||||||
// Commands shall start immediately after the full header
|
// Commands shall start immediately after the full header
|
||||||
#define umdiff_File_$COMMANDS_START (sizeof lp_UMDiffHeader)
|
#define umdiff_File_$COMMANDS_START (sizeof(umdiff_Header))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Index of commands at 1024 sector interval.
|
* @brief Index of commands at 1024 sector interval.
|
||||||
@ -101,16 +101,40 @@ typedef enum {
|
|||||||
* This struct represents the contents of a UMDiff file, loaded in memory.
|
* This struct represents the contents of a UMDiff file, loaded in memory.
|
||||||
* If read from a file, only the header is guaranteed to be populated.
|
* If read from a file, only the header is guaranteed to be populated.
|
||||||
*
|
*
|
||||||
|
* If <tt>commands</tt> is set to point to a 1024-command buffer, and <tt>mode</tt>
|
||||||
|
* is set to @ref umdiff_FileFlags_HEADER_ONLY, it will be used as a holding
|
||||||
|
* buffer when reading commands from file.
|
||||||
|
*
|
||||||
* @see umdiff_FileFlags for the possible cases.
|
* @see umdiff_FileFlags for the possible cases.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
umdiff_Header hdr;
|
umdiff_Header hdr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief List of loaded commands from file
|
||||||
|
*
|
||||||
|
* If <tt>mode</tt> is set to @ref umdiff_FileFlags_HEADER_ONLY, this is
|
||||||
|
* expected to be a pre-allocated buffer holding 1024 commands.
|
||||||
|
* Otherwise, it contains all commands in the file.
|
||||||
|
*/
|
||||||
umdiff_Command *commands;
|
umdiff_Command *commands;
|
||||||
long data_len;
|
|
||||||
char *data;
|
char *data;
|
||||||
|
long data_len;
|
||||||
|
|
||||||
|
/** Keeps track of the last command batch pulled from index. */
|
||||||
|
int last_index;
|
||||||
|
/** Which loading mode was used when this file was opened. */
|
||||||
umdiff_FileFlags mode;
|
umdiff_FileFlags mode;
|
||||||
} umdiff_File;
|
} umdiff_File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function to read from a source.
|
||||||
|
*
|
||||||
|
* This is used by @ref umdiff_File_readPatched to perform an actual read from
|
||||||
|
* a data source, be it the patch file or original media.
|
||||||
|
*/
|
||||||
|
typedef int (*umdiff_ReadCallback)(void *dest, long count, long offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load a UMDiff file from an open file descriptor.
|
* @brief Load a UMDiff file from an open file descriptor.
|
||||||
*
|
*
|
||||||
@ -141,6 +165,25 @@ umdiff_File_load(umdiff_File *file, int fd, umdiff_FileFlags flags);
|
|||||||
int
|
int
|
||||||
umdiff_File_write(umdiff_File *file, int outfd);
|
umdiff_File_write(umdiff_File *file, int outfd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform a read at a given offset and size with patches applied.
|
||||||
|
*
|
||||||
|
* This function maps a given read request into the patched data, using the
|
||||||
|
* provided callback functions to carry out the actual read commands needed.
|
||||||
|
*
|
||||||
|
* @param file The @ref umdiff_File to perform the patch with.
|
||||||
|
* @param dest Like pread(2), the buffer to write the data into.
|
||||||
|
* @param count Like pread(2), the amount of data to read.
|
||||||
|
* @param offset Like pread(2), the offset at which to start reading.
|
||||||
|
*
|
||||||
|
* @param read_source The function to read the source media.
|
||||||
|
* @param read_patchFile The function to read the patch file from storage.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
umdiff_File_readPatched(umdiff_File *file, void *dest, long count, long offset,
|
||||||
|
umdiff_ReadCallback read_source,
|
||||||
|
umdiff_ReadCallback read_patchFile);
|
||||||
|
|
||||||
#endif //__UMDIFF_H
|
#endif //__UMDIFF_H
|
||||||
|
|
||||||
// vim: ft=c.doxygen
|
// vim: ft=c.doxygen
|
||||||
|
Loading…
x
Reference in New Issue
Block a user