mirror of
				https://github.com/Thesola10/umd-livepatch.git
				synced 2025-08-09 22:02:02 +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.
 | 
			
		||||
@ -46,7 +46,7 @@ typedef long umdiff_CmdIndex[1024];
 | 
			
		||||
 * we gain a worst-case patch application process in O(1) space and O(log(n))
 | 
			
		||||
 * time on PSP.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct 
 | 
			
		||||
typedef struct
 | 
			
		||||
__attribute__((packed)) {
 | 
			
		||||
    char magic[7]; /* = 0x7f 'UMDiff' */
 | 
			
		||||
    char version;
 | 
			
		||||
@ -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