mirror of
https://github.com/Thesola10/umd-livepatch.git
synced 2025-04-19 22:13:22 +00:00
Implemented UMDiff read/write
This commit is contained in:
parent
78e8bcc861
commit
557f11ff93
3
Makefile
3
Makefile
@ -1,5 +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
|
||||||
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
|
||||||
|
33
stdio_glue.c
Normal file
33
stdio_glue.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* @file stdio_glue.c
|
||||||
|
* @author Karim Vergnes <me@thesola.io>
|
||||||
|
* @copyright GPLv2
|
||||||
|
* @brief Glue code between POSIX stdio and PSP kernel
|
||||||
|
*
|
||||||
|
* This module allows me to reuse code from the UMDiff utility, by redirecting
|
||||||
|
* POSIX standard I/O functions to their PSP kernel counterparts.
|
||||||
|
* Probably won't work for more complex programs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pspkernel.h>
|
||||||
|
|
||||||
|
off_t
|
||||||
|
lseek(int fd, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
return sceIoLseek(fd, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
read(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
return sceIoRead(fd, buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
write(int fd, const void *buf, size_t count)
|
||||||
|
{
|
||||||
|
return sceIoWrite(fd, buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ft=c.doxygen
|
85
umdiff/file.c
Normal file
85
umdiff/file.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* @file file.c
|
||||||
|
* @author Karim Vergnes <me@thesola.io>
|
||||||
|
* @copyright GPLv2
|
||||||
|
* @brief Functions to read and write UMDiff files
|
||||||
|
*
|
||||||
|
* The functions defined here control reading and writing UMDiff files from
|
||||||
|
* in-memory structure @ref umdiff_File.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "umdiff.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
char data[sizeof(umdiff_Header)];
|
||||||
|
umdiff_Header hdr;
|
||||||
|
} _impl_umdiff_RawHeader;
|
||||||
|
|
||||||
|
#define _impl_umdiff_alignSector$(x) \
|
||||||
|
( x + ISO_SECTOR_SIZE - (x % ISO_SECTOR_SIZE) )
|
||||||
|
|
||||||
|
void
|
||||||
|
_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);
|
||||||
|
hdr->version = umdiff_File_$VERSION;
|
||||||
|
hdr->data_start = _impl_umdiff_alignSector$(len_preamble);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umdiff_File_load(umdiff_File *file, int fd, umdiff_FileFlags flags)
|
||||||
|
{
|
||||||
|
_impl_umdiff_RawHeader rheader;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!file) return 1;
|
||||||
|
|
||||||
|
ret = read(fd, &rheader.data, sizeof(umdiff_Header));
|
||||||
|
file->hdr = rheader.hdr;
|
||||||
|
|
||||||
|
if (strncmp(file->hdr.magic, umdiff_File_$MAGIC, 7))
|
||||||
|
return 1;
|
||||||
|
if (file->hdr.version != umdiff_File_$VERSION)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (flags >= umdiff_FileFlags_HEADER_AND_COMMANDS) {
|
||||||
|
ret = read(fd, file->commands, sizeof(umdiff_Command) * file->hdr.cmd_count);
|
||||||
|
}
|
||||||
|
if (flags == umdiff_FileFlags_LOAD_FULL) {
|
||||||
|
file->data_len = lseek(fd, 0, SEEK_END) - file->hdr.data_start;
|
||||||
|
ret = lseek(fd, file->hdr.data_start, SEEK_SET);
|
||||||
|
ret = read(fd, file->data, file->data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umdiff_File_write(umdiff_File *file, int outfd)
|
||||||
|
{
|
||||||
|
_impl_umdiff_RawHeader rheader;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!file || file->mode != umdiff_FileFlags_LOAD_FULL
|
||||||
|
|| !file->commands || !file->data
|
||||||
|
|| !file->hdr.cmd_count || !file->hdr.index[0])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
rheader.hdr = file->hdr;
|
||||||
|
|
||||||
|
_impl_umdiff_Header_rectify(&rheader.hdr);
|
||||||
|
|
||||||
|
ret = write(outfd, rheader.data, sizeof(umdiff_Header));
|
||||||
|
ret = write(outfd, file->commands, sizeof(umdiff_Command) * rheader.hdr.cmd_count);
|
||||||
|
ret = lseek(outfd, rheader.hdr.data_start, SEEK_SET);
|
||||||
|
ret = write(outfd, file->data, file->data_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -9,11 +9,25 @@
|
|||||||
* in the umd_livepatch module.
|
* in the umd_livepatch module.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "usage.rl.h"
|
#include "usage.rl.h"
|
||||||
|
#include "rdiff.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
umdiff_delta(char *source, char *target, char *output)
|
umdiff_delta(char *source, char *target, char *output)
|
||||||
{
|
{
|
||||||
|
int source_fd, target_fd, output_fd;
|
||||||
|
umdiff_File *result;
|
||||||
|
|
||||||
|
source_fd = open(source, O_RDONLY);
|
||||||
|
target_fd = open(target, O_RDONLY);
|
||||||
|
|
||||||
|
result = umdiff_File_fromCompare(source_fd, target_fd);
|
||||||
|
|
||||||
|
output_fd = open(output, O_WRONLY|O_CREAT|O_TRUNC);
|
||||||
|
umdiff_File_write(result, output_fd);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
umdiff/patch.c
Normal file
0
umdiff/patch.c
Normal file
@ -8,12 +8,10 @@
|
|||||||
* and convert it in-memory into the UMDiff format.
|
* and convert it in-memory into the UMDiff format.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "umdiff.h"
|
#include "rdiff.h"
|
||||||
|
|
||||||
#include <librsync.h>
|
#include <librsync.h>
|
||||||
|
|
||||||
#define ISO_SECTOR_SIZE 2048
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
int fd;
|
int fd;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
29
umdiff/rdiff.h
Normal file
29
umdiff/rdiff.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef __RDIFF_H
|
||||||
|
#define __RDIFF_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file rdiff.h
|
||||||
|
* @author Karim Vergnes <me@thesola.io>
|
||||||
|
* @copyright GPLv2
|
||||||
|
* @brief rsync-based diff calculator functions
|
||||||
|
*
|
||||||
|
* Generator functions to create a @ref umdiff_File object from computing the
|
||||||
|
* difference between two files, using librsync algorithms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "umdiff.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate a UMDiff file from a source and target file contents.
|
||||||
|
*
|
||||||
|
* This function invokes a signature and delta job from librsync under the hood.
|
||||||
|
* This is the optimum approach, as it includes our optimum parameters,
|
||||||
|
* ensuring computed blocks line up with ISO9660 sectors.
|
||||||
|
*/
|
||||||
|
umdiff_File *
|
||||||
|
umdiff_File_fromCompare(int source_fd, int target_fd);
|
||||||
|
|
||||||
|
#endif //__RDIFF_H
|
||||||
|
|
||||||
|
// vim: ft=c.doxygen
|
@ -10,7 +10,15 @@
|
|||||||
* This file contains all required types to read and parse a UMDiff file.
|
* This file contains all required types to read and parse a UMDiff file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define UMDIFF_VERSION 0x00
|
#ifndef ISO_SECTOR_SIZE
|
||||||
|
# define ISO_SECTOR_SIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define umdiff_File_$MAGIC "\x7fUMDiff"
|
||||||
|
#define umdiff_File_$VERSION 0x00
|
||||||
|
|
||||||
|
// Commands shall start immediately after the full header
|
||||||
|
#define umdiff_File_$COMMANDS_START (sizeof lp_UMDiffHeader)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Index of commands at 1024 sector interval.
|
* @brief Index of commands at 1024 sector interval.
|
||||||
@ -42,7 +50,7 @@ typedef struct
|
|||||||
__attribute__((packed)) {
|
__attribute__((packed)) {
|
||||||
char magic[7]; /* = 0x7f 'UMDiff' */
|
char magic[7]; /* = 0x7f 'UMDiff' */
|
||||||
char version;
|
char version;
|
||||||
long cmd_len;
|
long cmd_count;
|
||||||
long data_start;
|
long data_start;
|
||||||
umdiff_CmdIndex index;
|
umdiff_CmdIndex index;
|
||||||
} umdiff_Header;
|
} umdiff_Header;
|
||||||
@ -58,7 +66,7 @@ __attribute__((packed)) {
|
|||||||
* - <tt>sector_count</tt>: How many sectors on the original disc the patch
|
* - <tt>sector_count</tt>: How many sectors on the original disc the patch
|
||||||
* command spans.
|
* command spans.
|
||||||
* - <tt>patch_start</tt>: Where in the patch source the substitute data is
|
* - <tt>patch_start</tt>: Where in the patch source the substitute data is
|
||||||
* found, in sectors.
|
* found, in sectors (past @ref data_start for in-file patches).
|
||||||
* - <tt>patch_sector_count</tt>: How many sectors on the patch source the
|
* - <tt>patch_sector_count</tt>: How many sectors on the patch source the
|
||||||
* substitute data occupies. If smaller than <tt>sector_count</tt>, then
|
* substitute data occupies. If smaller than <tt>sector_count</tt>, then
|
||||||
* the substitute is a repeating pattern of that length.
|
* the substitute is a repeating pattern of that length.
|
||||||
@ -75,14 +83,64 @@ typedef struct {
|
|||||||
long data_source; /* 0 = patchfile, 1 = source */
|
long data_source; /* 0 = patchfile, 1 = source */
|
||||||
} umdiff_Command;
|
} umdiff_Command;
|
||||||
|
|
||||||
// Commands shall start immediately after the full header
|
/**
|
||||||
#define UMDIFF_COMMANDS_START (sizeof lp_UMDiffHeader)
|
* @brief Flags to control loading a UMDiff file.
|
||||||
|
*
|
||||||
|
* In order to adapt to memory-constrained environments, one can choose to
|
||||||
|
* not load certain parts of a UMDiff file, instead resorting to in-situ reads.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
umdiff_FileFlags_HEADER_ONLY,
|
||||||
|
umdiff_FileFlags_HEADER_AND_COMMANDS,
|
||||||
|
umdiff_FileFlags_LOAD_FULL
|
||||||
|
} umdiff_FileFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief In-memory structure for a UMDiff file.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @see umdiff_FileFlags for the possible cases.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
umdiff_Header *hdr;
|
umdiff_Header hdr;
|
||||||
umdiff_Command *commands;
|
umdiff_Command *commands;
|
||||||
|
long data_len;
|
||||||
|
char *data;
|
||||||
|
umdiff_FileFlags mode;
|
||||||
} umdiff_File;
|
} umdiff_File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load a UMDiff file from an open file descriptor.
|
||||||
|
*
|
||||||
|
* This function takes a pre-allocated @ref umdiff_File structure, and populates
|
||||||
|
* it from an open file descriptor, according to the given mode flags.
|
||||||
|
*
|
||||||
|
* @param file The target @ref umdiff_File to load into.
|
||||||
|
* @param fd The open file descriptor to read from.
|
||||||
|
* @param flags Flags to control how much data to read in memory.
|
||||||
|
*
|
||||||
|
* @return 0 on success, any other value indicates an error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
umdiff_File_load(umdiff_File *file, int fd, umdiff_FileFlags flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a fully-populated UMDiff into a file descriptor.
|
||||||
|
*
|
||||||
|
* This function takes a fully populated @ref umdiff_File structure, and writes
|
||||||
|
* it down into an open file descriptor. The output header will be set with
|
||||||
|
* correct values, only cmd_len and index must both be set.
|
||||||
|
*
|
||||||
|
* @param file The @ref umdiff_File to write from. Must be fully populated.
|
||||||
|
* @param outfd The open file descriptor to write into.
|
||||||
|
*
|
||||||
|
* @return 0 on success, any other value indicates an error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
umdiff_File_write(umdiff_File *file, int outfd);
|
||||||
|
|
||||||
#endif //__UMDIFF_H
|
#endif //__UMDIFF_H
|
||||||
|
|
||||||
// vim: ft=c.doxygen
|
// vim: ft=c.doxygen
|
||||||
|
Loading…
x
Reference in New Issue
Block a user