mirror of
https://github.com/ApacheThunder/GodMode9Nrio.git
synced 2025-06-19 03:05:34 -04:00
196 lines
4.5 KiB
C
196 lines
4.5 KiB
C
|
|
#include <stdio.h>
|
|
#include <sys/statvfs.h>
|
|
#include <nds.h>
|
|
#include "my_sha1.h"
|
|
#include "utils.h"
|
|
|
|
swiSHA1context_t sha1ctx;
|
|
|
|
static inline int htoi(char a){
|
|
if(a >= '0' && a <= '9'){
|
|
return a - '0';
|
|
}else if(a >= 'a' && a <= 'f'){
|
|
return a - ('a' - 0xa);
|
|
}else if(a >= 'A' && a <= 'F'){
|
|
return a - ('A' - 0xa);
|
|
}else{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int hex2bytes(uint8_t *out, unsigned byte_len, const char *in){
|
|
if (strlen(in) < byte_len << 1){
|
|
iprintf("%s: invalid input length, expecting %u, got %u.\n",
|
|
__FUNCTION__, (unsigned)byte_len << 1, (unsigned)strlen(in));
|
|
return -1;
|
|
}
|
|
for(unsigned i = 0; i < byte_len; ++i){
|
|
int h = htoi(*in++), l = htoi(*in++);
|
|
if(h == -1 || l == -1){
|
|
iprintf("%s: invalid input \"%c%c\"\n",
|
|
__FUNCTION__, *(in - 2), *(in - 1));
|
|
return -2;
|
|
}
|
|
*out++ = (h << 4) + l;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static char str_buf[0x10];
|
|
|
|
const char *to_mebi(size_t size) {
|
|
if (size % (1024 * 1024)) {
|
|
sprintf(str_buf, "%.2f", (float)(((double)size) / 1024 / 1024));
|
|
} else {
|
|
siprintf(str_buf, "%u", (unsigned)(size >> 20));
|
|
}
|
|
return str_buf;
|
|
}
|
|
|
|
int save_file(const char *filename, const void *buffer, size_t size, int save_sha1) {
|
|
FILE *f = fopen(filename, "wb");
|
|
if (f == 0) {
|
|
//iprintf("failed to open %s to write\n", filename);
|
|
return -1;
|
|
}
|
|
size_t written = fwrite(buffer, 1, size, f);
|
|
fclose(f);
|
|
if (written != size) {
|
|
//iprintf("error writting %s\n", filename);
|
|
return -2;
|
|
} else {
|
|
//iprintf("saved %s\n", filename);
|
|
}
|
|
if (save_sha1) {
|
|
sha1ctx.sha_block = 0;
|
|
my_swiSHA1Init(&sha1ctx);
|
|
my_swiSHA1Update(&sha1ctx, buffer, size);
|
|
save_sha1_file(filename);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int load_file(void **pbuf, size_t *psize, const char *filename, int verify_sha1, int align) {
|
|
FILE *f = fopen(filename, "rb");
|
|
if (f == 0) {
|
|
//iprintf("failed to open %s to read\n", filename);
|
|
return -1;
|
|
}
|
|
int ret;
|
|
fseek(f, 0, SEEK_END);
|
|
*psize = ftell(f);
|
|
if (*psize == 0) {
|
|
*pbuf = 0;
|
|
ret = 1;
|
|
} else {
|
|
if (align) {
|
|
*pbuf = memalign(align, *psize);
|
|
} else {
|
|
*pbuf = malloc(*psize);
|
|
}
|
|
if (*pbuf == 0) {
|
|
//printf("failed to alloc memory\n");
|
|
ret = -1;
|
|
} else {
|
|
fseek(f, 0, SEEK_SET);
|
|
unsigned read = fread(*pbuf, 1, *psize, f);
|
|
if (read != *psize) {
|
|
//iprintf("error reading %s\n", filename);
|
|
free(*pbuf);
|
|
*pbuf = 0;
|
|
ret = -2;
|
|
} else {
|
|
//iprintf("loaded %s(%u)\n", filename, read);
|
|
if (verify_sha1) {
|
|
//TODO:
|
|
//iprintf("%s: not implemented\n", __FUNCTION__);
|
|
}
|
|
ret = 0;
|
|
}
|
|
}
|
|
}
|
|
fclose(f);
|
|
return ret;
|
|
}
|
|
|
|
int load_block_from_file(void *buf, const char *filename, unsigned offset, unsigned size) {
|
|
FILE *f = fopen(filename, "rb");
|
|
if (f == 0) {
|
|
//iprintf("failed to open %s\n", filename);
|
|
return -1;
|
|
}
|
|
unsigned read;
|
|
int ret;
|
|
if (offset != 0 && fseek(f, offset, SEEK_SET) != 0) {
|
|
//printf("seek error\n");
|
|
ret = -1;
|
|
} else if ((read = fread(buf, 1, size, f)) != size) {
|
|
//iprintf("read error, expecting %u, got %u\n", size, read);
|
|
ret = -1;
|
|
} else {
|
|
ret = 0;
|
|
}
|
|
fclose(f);
|
|
return ret;
|
|
}
|
|
|
|
// you should have updated the sha1 context before calling save_sha1_file
|
|
// example: save_file() in this file and backup() in nand.c
|
|
|
|
int save_sha1_file(const char *filename) {
|
|
size_t len_fn = strlen(filename);
|
|
char *sha1_fn = (char *)malloc(len_fn + 6);
|
|
siprintf(sha1_fn, "%s.sha1", filename);
|
|
// 20 bytes each use 2 chars, space, asterisk, filename, new line
|
|
size_t len_buf = 2 * 20 + 1 + 1 + len_fn + 1;
|
|
char *sha1_buf = (char *)malloc(len_buf + 1); // extra for \0
|
|
char *p = sha1_buf;
|
|
char *digest = (char *)malloc(20);
|
|
my_swiSHA1Final(digest, &sha1ctx);
|
|
for (int i = 0; i < 20; ++i) {
|
|
p += siprintf(p, "%02X", digest[i]);
|
|
}
|
|
free(digest);
|
|
siprintf(p, " *%s\n", filename);
|
|
int ret = save_file(sha1_fn, (u8*)sha1_buf, len_buf, false);
|
|
free(sha1_fn);
|
|
free(sha1_buf);
|
|
return ret;
|
|
}
|
|
|
|
void print_bytes(const void *buf, size_t len) {
|
|
const unsigned char *p = (const unsigned char *)buf;
|
|
for(size_t i = 0; i < len; ++i) {
|
|
iprintf("%02x", *p++);
|
|
}
|
|
}
|
|
|
|
// out must be big enough
|
|
// can work in place
|
|
void utf16_to_ascii(uint8_t *out, const uint16_t *in, unsigned len) {
|
|
const uint16_t *end = in + len;
|
|
while (in < end){
|
|
uint16_t c = *in++;
|
|
if (c == 0) {
|
|
*out = 0;
|
|
break;
|
|
} else if (c < 0x80) {
|
|
*out++ = (uint8_t)c;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t df(const char *path, int verbose) {
|
|
// it's amazing libfat even got this to work
|
|
struct statvfs s;
|
|
statvfs(path, &s);
|
|
size_t free = s.f_bsize * s.f_bfree;
|
|
if (verbose) {
|
|
//iprintf("%s", to_mebi(free));
|
|
//iprintf("/%s MB (free/total)\n", to_mebi(s.f_bsize * s.f_blocks));
|
|
}
|
|
return free;
|
|
}
|
|
|