mirror of
https://github.com/Thesola10/umd-livepatch.git
synced 2025-04-18 21:43: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
|
||||
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
|
||||
all: $(TARGET).prx
|
||||
INCDIR = $(ARKROOT)/common/include $(ARKROOT)/core/systemctrl/include $(LIBRSYNC)/src
|
||||
|
@ -1,5 +1,5 @@
|
||||
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)
|
||||
|
||||
CMAKE := cmake
|
||||
|
@ -6,6 +6,8 @@
|
||||
*
|
||||
* The functions defined here control reading and writing UMDiff files from
|
||||
* in-memory structure @ref umdiff_File.
|
||||
*
|
||||
* @warning This file is reused by umd_livepatch. Do not allocate on the heap!
|
||||
*/
|
||||
|
||||
#include "umdiff.h"
|
||||
@ -28,7 +30,7 @@ _impl_umdiff_Header_rectify(umdiff_Header *hdr)
|
||||
long len_preamble = sizeof(umdiff_Header)
|
||||
+ (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->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
|
||||
|
||||
// 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.
|
||||
@ -101,16 +101,40 @@ typedef enum {
|
||||
* 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 <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.
|
||||
*/
|
||||
typedef struct {
|
||||
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;
|
||||
long data_len;
|
||||
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_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.
|
||||
*
|
||||
@ -141,6 +165,25 @@ umdiff_File_load(umdiff_File *file, int fd, umdiff_FileFlags flags);
|
||||
int
|
||||
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
|
||||
|
||||
// vim: ft=c.doxygen
|
||||
|
Loading…
x
Reference in New Issue
Block a user