int create_temp_folder(char *addon, char *temp_folder, size_t bufsize) { /* * Create a temp folder for the given addon in the proper place * depending on the operating system. Returns -1 on failure and 0 * on success. */ char temp[2048] = TEMPPATH; char addon_sanitized[2048]; int i; #ifdef _WIN32 temp[0] = 0; GetTempPath(sizeof(temp), temp); strcat(temp, "armake\\"); #endif temp[strlen(temp) - 1] = 0; for (i = 0; i < strlen(addon); i++) { if (addon[i] == '\\' || addon[i] == '/') addon_sanitized[i] = '_'; else addon_sanitized[i] = addon[i]; } // find a free one for (i = 0; i < 1024; i++) { snprintf(temp_folder, bufsize, "%s_%s_%i%c", temp, addon_sanitized, i, PATHSEP); if (access(temp_folder, F_OK) == -1) break; } if (i == 1024) return -1; return create_folders(temp_folder); }
int cmd_unpack() { extern DocoptArgs args; extern int current_operation; extern char current_target[2048]; FILE *f_source; FILE *f_target; int num_files; long i; long j; long fp_tmp; char prefix[2048] = { 0 }; char full_path[2048]; char buffer[2048]; struct header *headers; headers = (struct header *)malloc(sizeof(struct header) * MAXFILES); current_operation = OP_UNPACK; strcpy(current_target, args.source); // remove trailing slash in target if (args.target[strlen(args.target) - 1] == PATHSEP) args.target[strlen(args.target) - 1] = 0; // open file f_source = fopen(args.source, "rb"); if (!f_source) { errorf("Failed to open %s.\n", args.source); return 1; } // create folder if (create_folders(args.target)) { errorf("Failed to create output folder %s.\n", args.target); return 2; } // read header extensions and prefix fseek(f_source, 1, SEEK_SET); fgets(buffer, 5, f_source); if (strncmp(buffer, "sreV", 4) != 0) { errorf("Unrecognized file format.\n"); return 3; } fseek(f_source, 21, SEEK_SET); while (true) { fp_tmp = ftell(f_source); if (strcmp(buffer, "prefix") == 0) { fgets(prefix, sizeof(prefix), f_source); fseek(f_source, fp_tmp + strlen(prefix) + 1, SEEK_SET); strcpy(buffer, prefix); } else { fgets(buffer, sizeof(buffer), f_source); fseek(f_source, fp_tmp + strlen(buffer) + 1, SEEK_SET); } if (strlen(buffer) == 0) break; } // read headers for (num_files = 0; num_files <= MAXFILES; num_files++) { fp_tmp = ftell(f_source); fgets(buffer, sizeof(buffer), f_source); fseek(f_source, fp_tmp + strlen(buffer) + 1, SEEK_SET); if (strlen(buffer) == 0) { fseek(f_source, sizeof(uint32_t) * 5, SEEK_CUR); break; } strcpy(headers[num_files].name, buffer); fread(&headers[num_files].packing_method, sizeof(uint32_t), 1, f_source); fread(&headers[num_files].original_size, sizeof(uint32_t), 1, f_source); fseek(f_source, sizeof(uint32_t) * 2, SEEK_CUR); fread(&headers[num_files].data_size, sizeof(uint32_t), 1, f_source); } if (num_files > MAXFILES) { errorf("Maximum number of files (%i) exceeded.\n", MAXFILES); return 4; } // read files for (i = 0; i < num_files; i++) { // check for garbage if (is_garbage(&headers[i])) { fseek(f_source, headers[i].data_size, SEEK_CUR); continue; } // replace pathseps on linux #ifndef _WIN32 for (j = 0; j < strlen(headers[i].name); j++) { if (headers[i].name[j] == '\\') headers[i].name[j] = PATHSEP; } #endif // get full path strcpy(full_path, args.target); strcat(full_path, PATHSEP_STR); strcat(full_path, headers[i].name); // create containing folder strcpy(buffer, full_path); if (strrchr(buffer, PATHSEP) != NULL) { *strrchr(buffer, PATHSEP) = 0; if (create_folders(buffer)) { errorf("Failed to create folder %s.\n", buffer); return 5; } } // open target file if (access(full_path, F_OK) != -1 && !args.force) { errorf("File %s already exists and --force was not set.\n", full_path); return 6; } f_target = fopen(full_path, "wb"); if (!f_target) { errorf("Failed to open file %s.\n", full_path); return 7; } // write to file for (j = 0; headers[i].data_size - j >= sizeof(buffer); j += sizeof(buffer)) { fread(buffer, sizeof(buffer), 1, f_source); fwrite(buffer, sizeof(buffer), 1, f_target); } fread(buffer, headers[i].data_size - j, 1, f_source); fwrite(buffer, headers[i].data_size - j, 1, f_target); // clean up fclose(f_target); } // clean up fclose(f_source); free(headers); // if prefix file wasn't included but there is a prefix, create one strcpy(full_path, args.target); strcat(full_path, PATHSEP_STR); strcat(full_path, "$PBOPREFIX$"); if (access(full_path, F_OK) == -1 && strlen(prefix) > 0) { f_target = fopen(full_path, "wb"); if (!f_target) { errorf("Failed to open file %s.\n", full_path); return 8; } fputs(prefix, f_target); fputc('\n', f_target); fclose(f_target); } return 0; }
int copy_file(char *source, char *target) { /* * Copy the file from the source to the target. Overwrites if the target * already exists. * Returns a negative integer on failure and 0 on success. */ // Create the containing folder char containing[strlen(target) + 1]; int lastsep = 0; int i; for (i = 0; i < strlen(target); i++) { if (target[i] == PATHSEP) lastsep = i; } strcpy(containing, target); containing[lastsep] = 0; if (create_folders(containing)) return -1; #ifdef _WIN32 if (!CopyFile(source, target, 0)) return -2; #else int f_target, f_source; char buf[4096]; ssize_t nread; f_source = open(source, O_RDONLY); if (f_source < 0) return -2; f_target = open(target, O_WRONLY | O_CREAT, 0666); if (f_target < 0) { close(f_source); if (f_target >= 0) close(f_target); return -3; } while (nread = read(f_source, buf, sizeof buf), nread > 0) { char *out_ptr = buf; ssize_t nwritten; do { nwritten = write(f_target, out_ptr, nread); if (nwritten >= 0) { nread -= nwritten; out_ptr += nwritten; } else if (errno != EINTR) { close(f_source); if (f_target >= 0) close(f_target); return -4; } } while (nread > 0); } close(f_source); if (close(f_target) < 0) return -5; #endif return 0; }