bool manifest_entry_download_replace(struct host *h, const char *basedir, struct manifest_entry *e, void (*delete_hook)(const char *file)) { char buf[LINE_BUF_LEN]; enum host_status ret; bool valid = false; FILE *f; /* Try to open our target file. If we can't open it, it might be * write protected or in-use. In this case, it may be possible to * rename the original file out of the way. Try this trick first. */ f = fopen_unsafe(e->name, "w+b"); if(!f) { snprintf(buf, LINE_BUF_LEN, "%s~", e->name); if(rename(e->name, buf)) { warn("Failed to rename in-use file '%s' to '%s'\n", e->name, buf); goto err_out; } if(delete_hook) delete_hook(buf); f = fopen_unsafe(e->name, "w+b"); if(!f) { warn("Unable to open file '%s' for writing\n", e->name); goto err_out; } } snprintf(buf, LINE_BUF_LEN, "%s/%08x%08x%08x%08x%08x%08x%08x%08x", basedir, e->sha256[0], e->sha256[1], e->sha256[2], e->sha256[3], e->sha256[4], e->sha256[5], e->sha256[6], e->sha256[7]); ret = host_recv_file(h, buf, f, "application/octet-stream"); if(ret != HOST_SUCCESS) { warn("File '%s' could not be downloaded (error %d)\n", e->name, ret); goto err_close; } rewind(f); if(!manifest_entry_check_validity(e, f)) { warn("File '%s' failed validation\n", e->name); goto err_close; } valid = true; err_close: fclose(f); err_out: return valid; }
bool updater_init(char *argv[]) { struct manifest_entry *e; bool ret; FILE *f; process_argv = argv; if(!swivel_current_dir(false)) return false; check_for_updates = __check_for_updates; f = fopen_unsafe(DELETE_TXT, "rb"); if(!f) goto err_swivel_back; delete_list = manifest_list_create(f); fclose(f); for(e = delete_list; e; e = e->next) { f = fopen_unsafe(e->name, "rb"); if(!f) continue; ret = manifest_entry_check_validity(e, f); fclose(f); if(!ret) continue; if(unlink(e->name)) continue; /* Obtain the path for this file. If the file isn't at the top * level, and the directory is empty (rmdir ensures this) * the directory will be pruned. */ check_prune_basedir(e->name); } manifest_list_free(&delete_list); unlink(DELETE_TXT); err_swivel_back: swivel_current_dir_back(false); return true; }
void COutputBuffer::Flush() { FILE* fp; if (_type == OUT_FILE) { Flush(_pfile); } else { ASSERTNR(_type == OUT_FILENAME); if (_filename != NULL) { fp = fopen_unsafe(_filename, "a"); if (fp == NULL) { // We might not be able to open the log or full log output // files because someone is grepping or otherwise looking // through them while rl is active. In that case, we don't // want to just kill rl, so just keep accumulating output // and try again next time. Output a warning to the log so // they know it happened (but they won't see it unless the // output is flushed). We could consider having a maximum, // after which we "turn off" this output buffer, but we're // unlikely to ever have so much output that it causes a // problem. Warning("Cannot open '%s' for appending with error '%s'", _filename, strerror_unsafe(errno)); } else { Flush(fp); fclose(fp); } } } }
int load_mzm(struct world *mzx_world, char *name, int start_x, int start_y, int mode, int savegame) { FILE *input_file; size_t file_size; void *buffer; int success; input_file = fopen_unsafe(name, "rb"); if(input_file) { fseek(input_file, 0, SEEK_END); file_size = ftell(input_file); buffer = cmalloc(file_size); fseek(input_file, 0, SEEK_SET); fread(buffer, file_size, 1, input_file); fclose(input_file); success = load_mzm_common(mzx_world, buffer, (int)file_size, start_x, start_y, mode, savegame, name); free(buffer); return success; } else { error_message(E_MZM_DOES_NOT_EXIST, 0, name); return -1; } }
void save_board_file(struct world *mzx_world, struct board *cur_board, char *name) { FILE *fp = fopen_unsafe(name, "wb"); struct zip_archive *zp; boolean success = false; if(fp) { fputc(0xFF, fp); fputc('M', fp); fputc((MZX_VERSION >> 8) & 0xFF, fp); fputc(MZX_VERSION & 0xFF, fp); zp = zip_open_fp_write(fp); if(zp) { if(!save_board(mzx_world, cur_board, zp, 0, MZX_VERSION, 0)) success = true; zip_close(zp, NULL); } else fclose(fp); } if(!success) error_message(E_WORLD_IO_SAVING, 0, NULL); }
static struct manifest_entry *manifest_get_remote(struct host *h, const char *base) { struct manifest_entry *manifest = NULL; char url[LINE_BUF_LEN]; enum host_status ret; FILE *f; snprintf(url, LINE_BUF_LEN, "%s/" MANIFEST_TXT, base); f = fopen_unsafe(MANIFEST_TXT, "w+b"); if(!f) { warn("Failed to open local " MANIFEST_TXT " for writing\n"); goto err_out; } ret = host_recv_file(h, url, f, "text/plain"); if(ret != HOST_SUCCESS) { warn("Processing " MANIFEST_TXT " failed (error %d)\n", ret); goto err_fclose; } rewind(f); manifest = manifest_list_create(f); err_fclose: fclose(f); err_out: return manifest; }
void help_open(struct world *mzx_world, const char *file_name) { mzx_world->help_file = fopen_unsafe(file_name, "rb"); if(!mzx_world->help_file) return; help = cmalloc(1024 * 64); }
static bool backup_original_manifest(void) { unsigned int len, pos = 0; char block[BLOCK_SIZE]; FILE *input, *output; bool ret = false; struct stat s; // No existing manifest; this is non-fatal if(stat(MANIFEST_TXT, &s)) { ret = true; goto err_out; } input = fopen_unsafe(MANIFEST_TXT, "rb"); if(!input) goto err_out; output = fopen_unsafe(MANIFEST_TXT "~", "wb"); if(!output) goto err_close_input; len = (unsigned int)ftell_and_rewind(input); while(pos < len) { unsigned int block_size = MIN(BLOCK_SIZE, len - pos); if(fread(block, block_size, 1, input) != 1) goto err_close_output; if(fwrite(block, block_size, 1, output) != 1) goto err_close_output; pos += block_size; } ret = true; err_close_output: fclose(output); err_close_input: fclose(input); err_out: return ret; }
void save_mzm(struct world *mzx_world, char *name, int start_x, int start_y, int width, int height, int mode, int savegame) { FILE *output_file = fopen_unsafe(name, "wb"); size_t *buffer; size_t length; if(output_file) { buffer = NULL; save_mzm_common(mzx_world, start_x, start_y, width, height, mode, savegame, mem_allocate, (void **)(&buffer)); length = buffer[0]; fwrite(&buffer[1], length, 1, output_file); free(buffer); fclose(output_file); } }
static struct manifest_entry *manifest_get_local(void) { struct manifest_entry *manifest; FILE *f; f = fopen_unsafe(MANIFEST_TXT, "rb"); if(!f) { warn("Local " MANIFEST_TXT " is missing\n"); return NULL; } manifest = manifest_list_create(f); fclose(f); return manifest; }
BOOL CheckForPass(char * filename, char * optReportBuf, char * cmdbuf, BOOL fDumpOutputFile = TRUE) { FILE * fp; char buf[BUFFER_SIZE]; // Check to see if the exe ran at all. fp = fopen_unsafe(filename, "r"); if (fp == NULL) { LogOut("ERROR: Test failed to run. Unable to open file '%s', error '%s' (%s):", filename, strerror_unsafe(errno), optReportBuf); LogOut(" %s", cmdbuf); return FALSE; } // Parse the output file and verify that all lines must be pass/passed, or empty lines BOOL pass = FALSE; while(fgets(buf, BUFFER_SIZE, fp) != NULL) { if(!_strcmpi(buf, "pass\n") || !_strcmpi(buf, "passed\n")) { // Passing strings were found - pass pass = TRUE; } else if(_strcmpi(buf, "\n") != 0) { // Something else other than a newline was found - this is a failure. pass = FALSE; break; } } fclose(fp); if (!pass) { LogOut("ERROR: Test failed to run correctly: pass not found in output file (%s):", optReportBuf); LogOut(" %s", cmdbuf); if (fDumpOutputFile) { DumpFileToLog(filename); } } return pass; }
FILE * val_fopen(const char *filename) { struct stat stat_result; int stat_op_result = stat(filename, &stat_result); FILE *f; if(stat_op_result) return NULL; if(!S_ISREG(stat_result.st_mode)) return NULL; if(!(f = fopen_unsafe(filename, "rb"))) return NULL; return f; }
static void delete_hook(const char *file) { struct manifest_entry *new_entry; struct SHA256_ctx ctx; bool ret; FILE *f; new_entry = ccalloc(1, sizeof(struct manifest_entry)); if(!new_entry) goto err_out; if(delete_p) { delete_p->next = new_entry; delete_p = delete_p->next; } else delete_list = delete_p = new_entry; delete_p->name = cmalloc(strlen(file) + 1); if(!delete_p->name) goto err_delete_p; strcpy(delete_p->name, file); f = fopen_unsafe(file, "rb"); if(!f) goto err_delete_p_name; delete_p->size = (unsigned long)ftell_and_rewind(f); ret = manifest_compute_sha256(&ctx, f, delete_p->size); fclose(f); if(!ret) goto err_delete_p_name; memcpy(delete_p->sha256, ctx.H, sizeof(Uint32) * 8); return; err_delete_p_name: free(delete_p->name); err_delete_p: free(delete_p); delete_p = NULL; err_out: return; }
struct audio_stream *construct_mikmod_stream(char *filename, Uint32 frequency, Uint32 volume, Uint32 repeat) { FILE *input_file; char *input_buffer; Uint32 file_size; struct audio_stream *ret_val = NULL; input_file = fopen_unsafe(filename, "rb"); if(input_file) { MODULE *open_file; file_size = ftell_and_rewind(input_file); input_buffer = cmalloc(file_size); fread(input_buffer, file_size, 1, input_file); open_file = MikMod_LoadSongRW(SDL_RWFromMem(input_buffer, file_size), 64); if(open_file) { struct mikmod_stream *mm_stream = cmalloc(sizeof(struct mikmod_stream)); mm_stream->module_data = open_file; Player_Start(mm_stream->module_data); initialize_sampled_stream((struct sampled_stream *)mm_stream, mm_set_frequency, mm_get_frequency, frequency, 2, 0); ret_val = (struct audio_stream *)mm_stream; construct_audio_stream((struct audio_stream *)mm_stream, mm_mix_data, mm_set_volume, mm_set_repeat, mm_set_order, mm_set_position, mm_get_order, mm_get_position, mm_destruct, volume, repeat); } fclose(input_file); free(input_buffer); } return ret_val; }
static void manifest_add_list_validate_augment(struct manifest_entry *local, struct manifest_entry **added) { struct manifest_entry *e, *a = *added; // Scan along to penultimate `added' (if we have any) if(a) while(a->next) a = a->next; for(e = local; e; e = e->next) { struct manifest_entry *new_added; FILE *f; f = fopen_unsafe(e->name, "rb"); if(f) { if(manifest_entry_check_validity(e, f)) { fclose(f); continue; } fclose(f); } warn("Local file '%s' failed manifest validation\n", e->name); new_added = manifest_entry_copy(e); if(*added) { a->next = new_added; a = a->next; } else a = *added = new_added; } }
int main(int argc, char *argv[]) { int world, byte; long ext_pos; FILE *fp; if(argc <= 1) { error("Usage: %s [mzx/mzb file]\n", argv[0]); goto exit_out; } ext_pos = strlen(argv[1]) - 4; if(ext_pos < 0) { error("File '%s' of an unknown type.\n", argv[1]); goto exit_out; } if(!strcasecmp(argv[1] + ext_pos, ".mzb")) { world = false; } else if(!strcasecmp(argv[1] + ext_pos, ".mzx")) { world = true; } else { error("Unknown extension '%s'.\n", argv[1] + ext_pos); goto exit_out; } fp = fopen_unsafe(argv[1], "r+b"); if(!fp) { error("Could not open '%s' for read/write.\n", argv[1]); goto exit_out; } /* World files need some crap at the beginning skipped. Also, world files * can theoretically be encrypted, though practically this will not happen * with modern worlds. Just in case, check for it and abort. * * Board files just need the 0xFF byte at the start skipping. */ if(world) { char name[BOARD_NAME_SIZE]; size_t fret; // Last selected board name; junked, we simply don't care fret = fread(name, BOARD_NAME_SIZE, 1, fp); if(fret != 1) goto err_read; // Check protection isn't enabled byte = fgetc(fp); if(byte < 0) goto err_read; else if(byte != 0) { error("Protected worlds are not supported.\n"); goto exit_close; } } else { byte = fgetc(fp); if(byte < 0) goto err_read; else if(byte != 0xff) error("Board file is corrupt or unsupported.\n"); } // Validate version is current byte = fgetc(fp); if(byte < 0) goto err_read; else if(byte != 'M') { error("World file is corrupt or unsupported.\n"); goto exit_close; } byte = fgetc(fp); if(byte < 0) goto err_read; else if(byte != WORLD_VERSION_HI) { error("This tool only supports worlds or boards from %d.%d.\n", WORLD_VERSION_HI, WORLD_VERSION_LO); goto exit_close; } byte = fgetc(fp); if(byte < 0) goto err_read; else if(byte != WORLD_VERSION_LO) { error("This tool only supports worlds or boards from %d.%d.\n", WORLD_VERSION_HI, WORLD_VERSION_LO); goto exit_close; } // Re-write current magic with previous version's magic if(fseek(fp, -2, SEEK_CUR) != 0) goto err_seek; byte = fputc(WORLD_VERSION_PREV_HI, fp); if(byte == EOF) goto err_write; byte = fputc(WORLD_VERSION_PREV_LO, fp); if(byte == EOF) goto err_write; #if WORLD_VERSION == 0x0254 { enum status ret; if(world) ret = convert_284_to_283(fp); else ret = convert_284_to_283_board(fp, NULL); switch(ret) { case SEEK_ERROR: goto err_seek; case READ_ERROR: goto err_read; case WRITE_ERROR: goto err_write; case SUCCESS: break; } } #endif fprintf(stdout, "File '%s' successfully downgraded from %d.%d to %d.%d.\n", argv[1], WORLD_VERSION_HI, WORLD_VERSION_LO, WORLD_VERSION_PREV_HI, WORLD_VERSION_PREV_LO); exit_close: fclose(fp); exit_out: return 0; err_seek: error("Seek error, aborting.\n"); goto exit_close; err_read: error("Read error, aborting.\n"); goto exit_close; err_write: error("Write error, aborting.\n"); goto exit_close; }
void replace_current_board(struct world *mzx_world, char *name) { int current_board_id = mzx_world->current_board_id; struct board *src_board = mzx_world->current_board; FILE *fp = fopen_unsafe(name, "rb"); struct zip_archive *zp; char version_string[4]; int file_version; int success = 0; if(fp) { if(!fread(version_string, 4, 1, fp)) { error_message(E_IO_READ, 0, NULL); fclose(fp); return; } file_version = board_magic(version_string); if(file_version > 0 && file_version <= MZX_LEGACY_FORMAT_VERSION) { // Legacy board. clear_board(src_board); src_board = legacy_load_board_allocate_direct(mzx_world, fp, file_version); success = 1; fclose(fp); } else if(file_version <= MZX_VERSION) { int board_id; // Regular board or maybe not a board at all. zp = zip_open_fp_read(fp); // Make sure it's an actual zip. if(zp) { // Make sure the zip contains a board. board_id = find_first_board(zp); if(board_id >= 0) { clear_board(src_board); src_board = load_board_allocate(mzx_world, zp, 0, file_version, board_id); success = 1; } } if(!success) error_message(E_BOARD_FILE_INVALID, 0, NULL); zip_close(zp, NULL); } else { error_message(E_BOARD_FILE_FUTURE_VERSION, file_version, NULL); fclose(fp); } if(success) { // Set up the newly allocated board. optimize_null_objects(src_board); if(src_board->robot_list) src_board->robot_list[0] = &mzx_world->global_robot; set_update_done_current(mzx_world); set_current_board(mzx_world, src_board); mzx_world->board_list[current_board_id] = src_board; } } }
static void __check_for_updates(struct world *mzx_world, struct config_info *conf) { int cur_host; char *update_host; bool try_next_host = true; bool ret = false; set_context(CTX_UPDATER); if(conf->update_host_count < 1) { error("No updater hosts defined! Aborting.", 1, 8, 0); goto err_out; } if(!swivel_current_dir(true)) goto err_out; for(cur_host = 0; (cur_host < conf->update_host_count) && try_next_host; cur_host++) { char **list_entries, buffer[LINE_BUF_LEN], *url_base, *value; struct manifest_entry *removed, *replaced, *added, *e; int i = 0, entries = 0, buf_len, result; char update_branch[LINE_BUF_LEN]; const char *version = VERSION; int list_entry_width = 0; enum host_status status; struct host *h = NULL; unsigned int retries; FILE *f; // Acid test: Can we write to this directory? f = fopen_unsafe(UPDATES_TXT, "w+b"); if(!f) { error("Failed to create \"" UPDATES_TXT "\". Check permissions.", 1, 8, 0); goto err_chdir; } update_host = conf->update_hosts[cur_host]; if(!reissue_connection(conf, &h, update_host)) goto err_host_destroy; for(retries = 0; retries < MAX_RETRIES; retries++) { // Grab the file containing the names of the current Stable and Unstable status = host_recv_file(h, "/" UPDATES_TXT, f, "text/plain"); rewind(f); if(status == HOST_SUCCESS) break; if(!reissue_connection(conf, &h, update_host)) goto err_host_destroy; } if(retries == MAX_RETRIES) { snprintf(widget_buf, WIDGET_BUF_LEN, "Failed to download \"" UPDATES_TXT "\" (err=%d).\n", status); widget_buf[WIDGET_BUF_LEN - 1] = 0; error(widget_buf, 1, 8, 0); goto err_host_destroy; } snprintf(update_branch, LINE_BUF_LEN, "Current-%s", conf->update_branch_pin); // Walk this list (of two, hopefully) while(true) { char *m = buffer, *key; value = NULL; // Grab a single line from the manifest if(!fgets(buffer, LINE_BUF_LEN, f)) break; key = strsep(&m, ":\n"); if(!key) break; value = strsep(&m, ":\n"); if(!value) break; if(strcmp(key, update_branch) == 0) break; } fclose(f); unlink(UPDATES_TXT); /* There was no "Current-XXX: Version" found; we cannot proceed with the * update because we cannot compute an update URL below. */ if(!value) { error("Failed to identify applicable update version.", 1, 8, 0); goto err_host_destroy; } /* There's likely to be a space prepended to the version number. * Skip it here. */ if(value[0] == ' ') value++; /* We found the latest update version, but we should check to see if that * matches the version we're already using. The user may choose to receive * "stability" updates for their current major version, or upgrade to the * newest one. */ if(strcmp(value, version) != 0) { struct element *elements[6]; struct dialog di; buf_len = snprintf(widget_buf, WIDGET_BUF_LEN, "A new major version is available (%s)", value); widget_buf[WIDGET_BUF_LEN - 1] = 0; elements[0] = construct_label((55 - buf_len) >> 1, 2, widget_buf); elements[1] = construct_label(2, 4, "You can continue to receive updates for the version\n" "installed (if available), or you can upgrade to the\n" "newest major version (recommended)."); elements[2] = construct_label(2, 8, "If you do not upgrade, this question will be asked\n" "again the next time you run the updater.\n"); elements[3] = construct_button(9, 11, "Upgrade", 0); elements[4] = construct_button(21, 11, "Update Old", 1); elements[5] = construct_button(36, 11, "Cancel", 2); construct_dialog(&di, "New Major Version", 11, 6, 55, 14, elements, 6, 3); result = run_dialog(mzx_world, &di); destruct_dialog(&di); // User pressed Escape, abort all updates if(result < 0 || result == 2) { try_next_host = false; goto err_host_destroy; } // User pressed Upgrade, use new major if(result == 0) version = value; } /* We can now compute a unique URL base for the updater. This will * be composed of a user-selected version and a static platform-archicture * name. */ url_base = cmalloc(LINE_BUF_LEN); snprintf(url_base, LINE_BUF_LEN, "/%s/" PLATFORM, version); debug("Update base URL: %s\n", url_base); /* The call to manifest_get_updates() destroys any existing manifest * file in this directory. Since we still allow user to abort after * this call, and downloading the updates may fail, we copy the * old manifest to a backup location and optionally restore it later. */ if(!backup_original_manifest()) { error("Failed to back up manifest. Check permissions.", 1, 8, 0); try_next_host = false; goto err_free_url_base; } for(retries = 0; retries < MAX_RETRIES; retries++) { bool m_ret; m_hide(); draw_window_box(3, 11, 76, 13, DI_MAIN, DI_DARK, DI_CORNER, 1, 1); write_string("Computing manifest deltas (added, replaced, deleted)..", 13, 12, DI_TEXT, 0); update_screen(); m_ret = manifest_get_updates(h, url_base, &removed, &replaced, &added); clear_screen(32, 7); m_show(); update_screen(); if(m_ret) break; if(!reissue_connection(conf, &h, update_host)) goto err_roll_back_manifest; } if(retries == MAX_RETRIES) { error("Failed to compute update manifests", 1, 8, 0); goto err_roll_back_manifest; } // At this point, we have a successful manifest, so we won't need another host try_next_host = false; if(!removed && !replaced && !added) { struct element *elements[3]; struct dialog di; elements[0] = construct_label(2, 2, "This client is already current."); elements[1] = construct_button(7, 4, "OK", 0); elements[2] = construct_button(13, 4, "Try next host", 1); construct_dialog(&di, "No Updates", 22, 9, 35, 6, elements, 3, 1); result = run_dialog(mzx_world, &di); destruct_dialog(&di); if((result == 1) && (cur_host < conf->update_host_count)) try_next_host = true; goto err_free_update_manifests; } for(e = removed; e; e = e->next, entries++) list_entry_width = MAX(list_entry_width, 2 + (int)strlen(e->name)+1+1); for(e = replaced; e; e = e->next, entries++) list_entry_width = MAX(list_entry_width, 2 + (int)strlen(e->name)+1+1); for(e = added; e; e = e->next, entries++) list_entry_width = MAX(list_entry_width, 2 + (int)strlen(e->name)+1+1); // We don't want the listbox to be too wide list_entry_width = MIN(list_entry_width, 60); list_entries = cmalloc(entries * sizeof(char *)); for(e = removed; e; e = e->next, i++) { list_entries[i] = cmalloc(list_entry_width); snprintf(list_entries[i], list_entry_width, "- %s", e->name); list_entries[i][list_entry_width - 1] = 0; } for(e = replaced; e; e = e->next, i++) { list_entries[i] = cmalloc(list_entry_width); snprintf(list_entries[i], list_entry_width, "* %s", e->name); list_entries[i][list_entry_width - 1] = 0; } for(e = added; e; e = e->next, i++) { list_entries[i] = cmalloc(list_entry_width); snprintf(list_entries[i], list_entry_width, "+ %s", e->name); list_entries[i][list_entry_width - 1] = 0; } draw_window_box(19, 1, 59, 4, DI_MAIN, DI_DARK, DI_CORNER, 1, 1); write_string(" Task Summary ", 33, 1, DI_TITLE, 0); write_string("ESC - Cancel [+] Add [-] Delete", 21, 2, DI_TEXT, 0); write_string("ENTER - Proceed [*] Replace ", 21, 3, DI_TEXT, 0); result = list_menu((const char **)list_entries, list_entry_width, NULL, 0, entries, ((80 - (list_entry_width + 9)) >> 1) + 1, 4); for(i = 0; i < entries; i++) free(list_entries[i]); free(list_entries); clear_screen(32, 7); update_screen(); if(result < 0) goto err_free_update_manifests; /* Defer deletions until we restart; any of these files may still be * in use by this (old) process. Reduce the number of entries by the * number of removed items for the progress meter below. */ for(e = removed; e; e = e->next, entries--) delete_hook(e->name); /* Since the operations for adding and replacing a file are identical, * we modify the replaced list and tack on the added list to the end. * * Either list may be NULL; in the case that `replaced' is NULL, simply * re-assign the `added' pointer. `added' being NULL has no effect. * * Later, we need only free the replaced list (see below). */ if(replaced) { for(e = replaced; e->next; e = e->next) ; e->next = added; } else replaced = added; cancel_update = false; host_set_callbacks(h, NULL, recv_cb, cancel_cb); i = 1; for(e = replaced; e; e = e->next, i++) { for(retries = 0; retries < MAX_RETRIES; retries++) { char name[72]; bool m_ret; if(!check_create_basedir(e->name)) goto err_free_delete_list; final_size = (long)e->size; m_hide(); snprintf(name, 72, "%s (%ldb) [%u/%u]", e->name, final_size, i, entries); meter(name, 0, final_size); update_screen(); m_ret = manifest_entry_download_replace(h, url_base, e, delete_hook); clear_screen(32, 7); m_show(); update_screen(); if(m_ret) break; if(cancel_update) { error("Download was cancelled; update aborted.", 1, 8, 0); goto err_free_delete_list; } if(!reissue_connection(conf, &h, update_host)) goto err_free_delete_list; host_set_callbacks(h, NULL, recv_cb, cancel_cb); } if(retries == MAX_RETRIES) { snprintf(widget_buf, WIDGET_BUF_LEN, "Failed to download \"%s\" (after %d attempts).", e->name, retries); widget_buf[WIDGET_BUF_LEN - 1] = 0; error(widget_buf, 1, 8, 0); goto err_free_delete_list; } } if(delete_list) { f = fopen_unsafe(DELETE_TXT, "wb"); if(!f) { error("Failed to create \"" DELETE_TXT "\". Check permissions.", 1, 8, 0); goto err_free_delete_list; } for(e = delete_list; e; e = e->next) { fprintf(f, "%08x%08x%08x%08x%08x%08x%08x%08x %lu %s\n", e->sha256[0], e->sha256[1], e->sha256[2], e->sha256[3], e->sha256[4], e->sha256[5], e->sha256[6], e->sha256[7], e->size, e->name); } fclose(f); } try_next_host = false; ret = true; err_free_delete_list: manifest_list_free(&delete_list); delete_list = delete_p = NULL; err_free_update_manifests: manifest_list_free(&removed); manifest_list_free(&replaced); err_roll_back_manifest: restore_original_manifest(ret); err_free_url_base: free(url_base); err_host_destroy: host_destroy(h); pop_context(); } //end host for loop err_chdir: swivel_current_dir_back(true); err_out: /* At this point we found updates and we successfully updated * to them. Reload the program with the original argv. */ if(ret) { const void *argv = process_argv; struct element *elements[2]; struct dialog di; elements[0] = construct_label(2, 2, "This client will now attempt to restart itself."); elements[1] = construct_button(23, 4, "OK", 0); construct_dialog(&di, "Update Successful", 14, 9, 51, 6, elements, 2, 1); run_dialog(mzx_world, &di); destruct_dialog(&di); execv(process_argv[0], argv); perror("execv"); error("Attempt to invoke self failed!", 1, 8, 0); return; } }
int main (int argc, char **argv) { FILE *fd; unsigned char mzmhead[16] = { 'M', 'Z', 'M', '2', /* Magic */ 0, 0, /* Width */ 0, 0, /* Height */ 0, 0, 0, 0, 0, 1, 0, 0 /* Stuff */ }; char input_file_name[MAX_PATH] = { '\0' }; char output_mzm_name[MAX_PATH] = { '\0' }; char output_chr_name[MAX_PATH] = { '\0' }; char output_pal_name[MAX_PATH] = { '\0' }; char output_base_name[MAX_PATH] = { '\0' }; char ext[5] = { '\0' }; int skip_char = -1; png_uint_32 w, h, i, t; rgba_color *img; mzx_tile *tile; mzx_glyph chr[256]; mzx_color pal[256]; smzx_converter *c; if (argc < 2 || argv[1][0] == '-') { fprintf(stderr, "png2smzx Image Conversion Utility\n\n" "Usage: %s <in.png> [<out> | <out.mzm> " "[<out.chr] [<out.pal>]] [options]\n\n" "Options:\n" "--skip-char=[value 0-255] Skip this " "char in the conversion process.\n" "\n" , argv[0]); return 1; } strncpy(input_file_name, argv[1], MAX_PATH); input_file_name[MAX_PATH - 1] = '\0'; // Read the input files for(i = 2; i < (unsigned int) argc; i++) { strncpy(ext, (argv[i] + strlen(argv[i]) - 4), 5); if(!strcasecmp(ext, ".mzm")) strncpy(output_mzm_name, argv[i], MAX_PATH); if(!strcasecmp(ext, ".chr")) strncpy(output_chr_name, argv[i], MAX_PATH); if(!strcasecmp(ext, ".pal")) strncpy(output_pal_name, argv[i], MAX_PATH); if(!strncasecmp(argv[i], "--skip-char", 11) && (argv[i][11] == '=') && argv[i][12]) { skip_char = strtol(argv[i] + 12, NULL, 10) % 256; fprintf(stderr, "Skipping char %i.", skip_char); } } output_mzm_name[MAX_PATH - 1] = '\0'; output_chr_name[MAX_PATH - 1] = '\0'; output_pal_name[MAX_PATH - 1] = '\0'; // Fill in the missing filenames if(output_mzm_name[0]) { strncpy(output_base_name, output_mzm_name, strlen(output_mzm_name) - 4); output_base_name[strlen(output_mzm_name) - 4] = '\0'; } else { if(argc >= 3 && argv[2] && argv[2][0] != '-') strncpy(output_base_name, argv[2], MAX_PATH - 5); else strncpy(output_base_name, input_file_name, MAX_PATH - 5); output_base_name[MAX_PATH - 6] = '\0'; strcpy(output_mzm_name, output_base_name); strcpy(output_mzm_name + strlen(output_mzm_name), ".mzm"); output_pal_name[0] = '\0'; output_chr_name[0] = '\0'; } if(!output_chr_name[0]) { strcpy(output_chr_name, output_base_name); strcpy(output_chr_name + strlen(output_chr_name), ".chr"); } if(!output_pal_name[0]) { strcpy(output_pal_name, output_base_name); strcpy(output_pal_name + strlen(output_pal_name), ".pal"); } // Do stuff img = (rgba_color *)read_png(input_file_name, &w, &h); if (!img) { fprintf(stderr, "Error reading image.\n"); return 1; } if ((w % 8) || (h % 14)) { fprintf(stderr, "Image not divisible by 8x14; cropping...\n"); if (w % 8) { t = w / 8 * 8; for (i = 1; i < h; i++) memmove(img + i * t, img + i * w, sizeof(rgba_color) * t); } } w /= 8; h /= 14; c = smzx_convert_init(w, h, 0, skip_char, 256, 0, 16); if (!c) { fprintf(stderr, "Error initializing converter.\n"); free(img); return 1; } tile = malloc(sizeof(mzx_tile) * w * h); if (!tile) { fprintf(stderr, "Error allocating tile buffer.\n"); smzx_convert_free(c); free(img); return 1; } smzx_convert(c, img, tile, chr, pal); smzx_convert_free(c); free(img); mzmhead[4] = w & 0xFF; mzmhead[5] = w >> 8; mzmhead[6] = h & 0xFF; mzmhead[7] = h >> 8; fd = fopen_unsafe(output_mzm_name, "wb"); if (!fd) { fprintf(stderr, "Error opening MZM file.\n"); free(tile); return 1; } if (fwrite(mzmhead, sizeof(mzmhead), 1, fd) != 1) { fprintf(stderr, "Error writing MZM header.\n"); fclose(fd); free(tile); return 1; } if (fwrite(tile, sizeof(mzx_tile) * w * h, 1, fd) != 1) { fprintf(stderr, "Error writing MZM data.\n"); fclose(fd); free(tile); return 1; } free(tile); fclose(fd); fd = fopen_unsafe(output_chr_name, "wb"); if (!fd) { fprintf(stderr, "Error opening CHR file.\n"); return 1; } if (fwrite(chr, sizeof(chr), 1, fd) != 1) { fprintf(stderr, "Error writing CHR data.\n"); fclose(fd); return 1; } fclose(fd); fd = fopen_unsafe(output_pal_name, "wb"); if (!fd) { fprintf(stderr, "Error opening PAL file.\n"); return 1; } if (fwrite(pal, sizeof(pal), 1, fd) != 1) { fprintf(stderr, "Error writing PAL data.\n"); fclose(fd); return 1; } fclose(fd); return 0; }
void DumpFileToLog( char* path ) { FILE* fp; char buf[BUFFER_SIZE]; char* p; fp = fopen_unsafe(path, "r"); if (fp == NULL) { LogError("ERROR: DumpFileToLog couldn't open file '%s' with error '%s'", path, strerror_unsafe(errno)); } else { int fd = _fileno(fp); struct _stat64 fileStats; if (fd != -1 && _fstat64(fd, &fileStats) != -1) { char creationTime[256]; char accessTime[256]; char currTime[256]; __time64_t now = _time64(NULL); _ctime64_s(currTime, &now); _ctime64_s(creationTime, &fileStats.st_ctime); _ctime64_s(accessTime, &fileStats.st_atime); auto stripNewline = [](char *buf) { if (char *ptr = strchr(buf, '\n')) *ptr = '\0'; }; stripNewline(creationTime); stripNewline(accessTime); stripNewline(currTime); LogOut("ERROR: name of output file: %s; size: %I64d; creation: %s, last access: %s, now: %s", path, fileStats.st_size, creationTime, accessTime, currTime); } if (!FNoProgramOutput) { bool printlines = !FOnlyAssertOutput; if (printlines) { LogOut("ERROR: bad output file follows ============"); } while (fgets(buf, BUFFER_SIZE, fp) != NULL) { // Strip the newline, since LogOut adds one p = strchr(buf, '\n'); if (p != NULL) { *p = '\0'; } if (!printlines && strlen(buf) > 8 && buf[0] == 'A' && buf[1] == 'S' && buf[2] == 'S' && buf[3] == 'E' && buf[4] == 'R' && buf[5] == 'T') { printlines = true; LogOut("ERROR: bad output file follows ============"); } if (printlines) { LogOut("%s", buf); } } if (printlines) { LogOut("ERROR: end of bad output file ============"); } } fclose(fp); } }
int png_write_screen(Uint8 *pixels, struct rgb_color *pal, int count, const char *name) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep * volatile row_ptrs = NULL; png_colorp volatile pal_ptr = NULL; int volatile ret = false; int type; int i; FILE *f; f = fopen_unsafe(name, "wb"); if(!f) goto exit_out; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) goto exit_close; info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) goto exit_free_close; if(setjmp(png_jmpbuf(png_ptr))) goto exit_free_close; png_init_io(png_ptr, f); // we know we have an 8-bit surface; save a palettized PNG type = PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE; png_set_IHDR(png_ptr, info_ptr, 640, 350, 8, type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); pal_ptr = cmalloc(count * sizeof(png_color)); if(!pal_ptr) goto exit_free_close; for(i = 0; i < count; i++) { pal_ptr[i].red = pal[i].r; pal_ptr[i].green = pal[i].g; pal_ptr[i].blue = pal[i].b; } png_set_PLTE(png_ptr, info_ptr, pal_ptr, count); // do the write of the header png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); row_ptrs = cmalloc(sizeof(png_bytep) * 350); if(!row_ptrs) goto exit_free_close; // and then the surface for(i = 0; i < 350; i++) row_ptrs[i] = (png_bytep)(Uint8 *)pixels + i * 640; png_write_image(png_ptr, row_ptrs); png_write_end(png_ptr, info_ptr); // all done ret = true; exit_free_close: png_destroy_write_struct(&png_ptr, &info_ptr); free(pal_ptr); free(row_ptrs); exit_close: fclose(f); exit_out: return ret; }
void *png_read_file(const char *name, png_uint_32 *_w, png_uint_32 *_h, check_w_h_constraint_t constraint, rgba_surface_allocator_t allocator) { png_uint_32 i, w, h, stride; png_byte header[8]; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep * volatile row_ptrs = NULL; void * volatile s = NULL; void *pixels; int type; int bpp; FILE *f; f = fopen_unsafe(name, "rb"); if(!f) goto exit_out; if(fread(header, 1, 8, f) < 8) goto exit_close; if(png_sig_cmp(header, 0, 8)) goto exit_close; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) goto exit_close; info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) goto exit_free_close; if(setjmp(png_jmpbuf(png_ptr))) goto exit_free_close; png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &bpp, &type, NULL, NULL, NULL); if(!constraint(w, h)) { warn("Requested image '%s' failed dimension checks.\n", name); goto exit_free_close; } if(type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); else if(type == PNG_COLOR_TYPE_GRAY_ALPHA || !(type & PNG_COLOR_MASK_COLOR)) png_set_gray_to_rgb(png_ptr); else if(!(type & PNG_COLOR_MASK_COLOR) && bpp < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if(bpp == 16) png_set_strip_16(png_ptr); else if(bpp < 8) png_set_packing(png_ptr); if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); else if(!(type & PNG_COLOR_MASK_ALPHA)) png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); // FIXME: Are these necessary? png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &bpp, &type, NULL, NULL, NULL); row_ptrs = cmalloc(sizeof(png_bytep) * h); if(!row_ptrs) goto exit_free_close; s = allocator(w, h, &stride, &pixels); if(!s) goto exit_free_close; for(i = 0; i < h; i++) row_ptrs[i] = (png_bytep)(unsigned char *)pixels + i * stride; png_read_image(png_ptr, row_ptrs); if(_w) *_w = w; if(_h) *_h = h; exit_free_close: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(row_ptrs); exit_close: fclose(f); exit_out: return s; }
int png_write_screen_32bpp(Uint32 *pixels, const char *name) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep * volatile row_ptrs = NULL; int volatile ret = false; int type; int i; FILE *f; f = fopen_unsafe(name, "wb"); if(!f) goto exit_out; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) goto exit_close; info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) goto exit_free_close; if(setjmp(png_jmpbuf(png_ptr))) goto exit_free_close; png_init_io(png_ptr, f); // 24-bit png type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, 640, 350, 8, type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // do the write of the header png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); row_ptrs = cmalloc(sizeof(png_bytep) * 350); if(!row_ptrs) goto exit_free_close; // our surface is 32bpp ABGR, so set up filler and order png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); png_set_bgr(png_ptr); // and then the surface for(i = 0; i < 350; i++) row_ptrs[i] = (png_bytep)(pixels + i * 640); png_write_image(png_ptr, row_ptrs); png_write_end(png_ptr, info_ptr); // all done ret = true; exit_free_close: png_destroy_write_struct(&png_ptr, &info_ptr); free(row_ptrs); exit_close: fclose(f); exit_out: return ret; }