Skip to content

Commit

Permalink
update sig url, allow cancelling download, "press A to continue" afte…
Browse files Browse the repository at this point in the history
…r download
  • Loading branch information
ITotalJustice committed Dec 30, 2023
1 parent 6cf118c commit d43b4df
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ build
*.elf
*.nacp
*.nro
.vscode/*
!.vscode/c_cpp_properties.json
*.zip
out
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
APP_TITLE := sigpatch-updater
APP_AUTHOR := TotalJustice
APP_VERSION := 0.2.0
APP_VERSION := 0.3.0

TARGET := sigpatch-updater
BUILD := build
Expand Down
11 changes: 5 additions & 6 deletions includes/download.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#ifndef _DOWNLOAD_H_
#define _DOWNLOAD_H_

#define AMS_SIG_URL "https://sigmapatches.coomer.party/sigpatches.zip?latest"
#define AMS_SIG_URL "https://sigmapatches.su/sigpatches.zip"
#define APP_URL "https://github.com/ITotalJustice/sigpatch-updater/releases/latest/download/sigpatch-updater.nro"
#define SYS_PATCH_URL "https://github.com/ITotalJustice/sys-patch/releases/latest/download/sys-patch.zip"
#define TEMP_FILE "/switch/sigpatch-updater/temp"

#define ON 1
#define OFF 0


#include <stdbool.h>
#include <switch.h>

typedef bool(*DlProgressCallback)(u32 dltotal, u32 dlnow, u32 ultotal, u32 ulnow);

//
bool downloadFile(const char *url, const char *output, int api);
bool downloadFile(const char *url, const char *output, DlProgressCallback pcall);

#endif
10 changes: 10 additions & 0 deletions includes/util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _UTIL_H_
#define _UTIL_H_

#include <stdbool.h>

void consolePrint(const char* s, ...) __attribute__ ((format (printf, 1, 2)));

bool stillRunning(void);

#endif
69 changes: 43 additions & 26 deletions source/download.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <math.h>
#include <curl/curl.h>
#include <switch.h>

#include "download.h"
#include "util.h"

#define API_AGENT "ITotalJustice"
#define _1MiB 0x100000
Expand All @@ -19,9 +18,9 @@ typedef struct {
} MemoryStruct_t;

typedef struct {
u_int8_t *data;
uint8_t *data;
size_t data_size;
u_int64_t offset;
uint64_t offset;
FILE *out;
} ntwrk_struct_t;

Expand All @@ -40,27 +39,20 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t num_files,
return realsize;
}

static int download_progress(void *p, double dltotal, double dlnow, double ultotal, double ulnow) {
if (dltotal <= 0.0) return 0;

struct timeval tv = {0};
gettimeofday(&tv, NULL);
const int counter = round(tv.tv_usec / 100000);

if (counter == 0 || counter == 2 || counter == 4 || counter == 6 || counter == 8) {
printf("* DOWNLOADING: %.2fMB of %.2fMB *\r", dlnow / _1MiB, dltotal / _1MiB);
consoleUpdate(NULL);
static int download_progress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) {
const DlProgressCallback callback = (DlProgressCallback)clientp;
if (!callback(dltotal, dlnow, ultotal, ulnow)) {
return 1;
}

return 0;
}

bool downloadFile(const char *url, const char *output, int api) {
bool downloadFile(const char *url, const char *output, DlProgressCallback pcall) {
CURL *curl = curl_easy_init();
if (curl) {
FILE *fp = fopen(output, "wb");
if (fp) {
printf("\n");
consolePrint("\nDownload in progress, Press (B) to cancel...\n\n");

ntwrk_struct_t chunk = {0};
chunk.data = malloc(_1MiB);
Expand All @@ -72,38 +64,63 @@ bool downloadFile(const char *url, const char *output, int api) {
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

// write calls
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);

if (api == OFF) {
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, download_progress);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, download_progress);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, pcall);

CURLM *multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, curl);
int still_running = 1;
CURLMcode mc;

while (still_running) {
mc = curl_multi_perform(multi_handle, &still_running);

if (!mc)
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);

if (mc) {
break;
}
}

// execute curl, save result
CURLcode res = curl_easy_perform(curl);
int msgs_left;
CURLMsg *msg;
CURLcode res = 1;

while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
if (msg->msg == CURLMSG_DONE) {
res = msg->data.result;
}
}

// write from mem to file
if (chunk.offset) {
fwrite(chunk.data, 1, chunk.offset, fp);
}

// clean
curl_multi_remove_handle(multi_handle, curl);
curl_easy_cleanup(curl);
curl_multi_cleanup(multi_handle);
free(chunk.data);
fclose(chunk.out);

if (res == CURLE_OK) {
printf("\n\ndownload complete!\n\n");
consoleUpdate(NULL);
consolePrint("\n\ndownload complete!\n\n");
return true;
} else {
consolePrint("\n\ncurl error: %s", curl_easy_strerror(res));
}
}
}

printf("\n\ndownload failed...\n\n");
consoleUpdate(NULL);
consolePrint("\n\ndownload failed...\n\n");
return false;
}
91 changes: 64 additions & 27 deletions source/main.c
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
#include <curl/curl.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h> // chdir
#include <dirent.h> // mkdir
#include <time.h>
#include <math.h>
#include <switch.h>

#include "download.h"
#include "unzip.h"
#include "util.h"


#define ROOT "/"
#define APP_PATH "/switch/sigpatch-updater/"
#define APP_OUTPUT "/switch/sigpatch-updater/sigpatch-updater.nro"
#define OLD_APP_PATH "/switch/sigpatch-updater.nro"

#define APP_VERSION "0.2.0"
#define APP_VERSION "0.3.0"

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

Expand All @@ -25,21 +29,47 @@ struct Entry {
const char* description;
};

static PadState g_pad;

static bool progressCallback(u32 dltotal, u32 dlnow, u32 ultotal, u32 ulnow) {
if (!stillRunning()) {
return false;
}

padUpdate(&g_pad);
const u64 kDown = padGetButtonsDown(&g_pad);
if (kDown & HidNpadButton_B) {
return false;;
}

if (dltotal > 0) {
struct timeval tv = {0};
gettimeofday(&tv, NULL);
const int counter = round(tv.tv_usec / 100000);

if (counter == 0 || counter == 2 || counter == 4 || counter == 6 || counter == 8) {
const double mb = 1024*1024;
consolePrint("* DOWNLOADING: %.2fMB of %.2fMB *\r", (double)dlnow / mb, (double)dltotal / mb);
}
}

return true;
}

static bool update_sigpatches_handler(void) {
if (downloadFile(AMS_SIG_URL, TEMP_FILE, OFF)) {
if (downloadFile(AMS_SIG_URL, TEMP_FILE, progressCallback)) {
if (!unzip(TEMP_FILE)) {
return false;
}
printf("\nfinished!\n\nRemember to reboot for the patches to be loaded!\n");
consoleUpdate(NULL);
consolePrint("\nfinished!\n\nRemember to reboot for the patches to be loaded!\n");
return true;
} else {
return false;
}
}

static bool update_syspatch_handler(void) {
if (downloadFile(SYS_PATCH_URL, TEMP_FILE, OFF)) {
if (downloadFile(SYS_PATCH_URL, TEMP_FILE, progressCallback)) {
if (!unzip(TEMP_FILE)) {
return false;
}
Expand All @@ -51,15 +81,13 @@ static bool update_syspatch_handler(void) {
};

if (R_FAILED(pmshellLaunchProgram(0, &location, &pid))) {
printf(
consolePrint(
"\nFailed to start sys-patch!\n"
"A reboot is needed...\n"
"Report this issue on GitHub please!\n");
consoleUpdate(NULL);
return false;
} else {
printf("\nsys-patch ran successfully, patches should be applied!\n");
consoleUpdate(NULL);
consolePrint("\nsys-patch ran successfully, patches should be applied!\n");
return true;
}
} else {
Expand All @@ -68,12 +96,11 @@ static bool update_syspatch_handler(void) {
}

static bool update_app_handler(void) {
if (downloadFile(APP_URL, TEMP_FILE, OFF)) {
if (downloadFile(APP_URL, TEMP_FILE, progressCallback)) {
remove(APP_OUTPUT);
rename(TEMP_FILE, APP_OUTPUT);
remove(OLD_APP_PATH);
printf("\nApp updated!\nRestart app to take effect");
consoleUpdate(NULL);
consolePrint("\nApp updated!\nRestart app to take effect");
return true;
} else {
return false;
Expand Down Expand Up @@ -135,14 +162,6 @@ static void refreshScreen(int cursor) {
consoleUpdate(NULL);
}

static void printDisplay(const char *text, ...) {
va_list v;
va_start(v, text);
vfprintf(stdout, text, v);
va_end(v);
consoleUpdate(NULL);
}

// update the cursor so that it wraps around
static void update_cursor(int* cur, int new_value, int max) {
if (new_value >= max) {
Expand All @@ -162,23 +181,28 @@ int main(int argc, char **argv) {
// init stuff
mkdir(APP_PATH, 0777);

// move nro to app folder
if (!strstr(argv[0], APP_OUTPUT)) {
remove(APP_OUTPUT);
rename(argv[0], APP_OUTPUT);
}

// change directory to root (defaults to /switch/)
chdir(ROOT);

// set the cursor position to 0
int cursor = 0;

PadState pad = {0};
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
padInitializeDefault(&pad);
padInitializeDefault(&g_pad);

// main menu
refreshScreen(cursor);

// muh loooooop
while (appletMainLoop()) {
padUpdate(&pad);
const u64 kDown = padGetButtonsDown(&pad);
while (stillRunning()) {
padUpdate(&g_pad);
const u64 kDown = padGetButtonsDown(&g_pad);

// move cursor down...
if (kDown & HidNpadButton_AnyDown) {
Expand All @@ -192,15 +216,28 @@ int main(int argc, char **argv) {

else if (kDown & HidNpadButton_A) {
if (get_wifi_state() < WifiState_1) {
printDisplay(
consolePrint(
"\n\n[Error] not connected to the internet!\n\n"
"An internet connection is required to download updates!\n");
}
else {
if (!ENTRIES[cursor].func()) {
printDisplay("Failed to %s\n", ENTRIES[cursor].display_text);
consolePrint("Failed to %s\n", ENTRIES[cursor].display_text);
}
}

consolePrint("\nPress (A) to continue...\n");

while (stillRunning()) {
padUpdate(&g_pad);
const u64 kDown = padGetButtonsDown(&g_pad);
if (kDown & HidNpadButton_A) {
break;
}
svcSleepThread(1e+9 / 60);
}

refreshScreen(cursor);
}

// exit...
Expand Down
Loading

0 comments on commit d43b4df

Please sign in to comment.