static int test_mknod(void) { int err = 0; int res; start_test("mknod"); unlink(testfile); res = mknod(testfile, 0644, 0); if (res == -1) { PERROR("mknod"); return -1; } res = check_type(testfile, S_IFREG); if (res == -1) return -1; err += check_mode(testfile, 0644); err += check_nlink(testfile, 1); err += check_size(testfile, 0); res = unlink(testfile); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile); if (res == -1) return -1; if (err) return -1; success(); return 0; }
int celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value) { if (check_mode(mode) != CELT_OK) return CELT_INVALID_MODE; switch (request) { case CELT_GET_FRAME_SIZE: *value = mode->mdctSize; break; case CELT_GET_LOOKAHEAD: *value = mode->overlap; break; case CELT_GET_NB_CHANNELS: *value = mode->nbChannels; break; case CELT_GET_BITSTREAM_VERSION: *value = CELT_BITSTREAM_VERSION; break; case CELT_GET_SAMPLE_RATE: *value = mode->Fs; break; default: return CELT_UNIMPLEMENTED; } return CELT_OK; }
static int create_dir(const char *path, const char **dir_files) { int res; int i; rmdir(path); res = mkdir(path, 0755); if (res == -1) { PERROR("mkdir"); return -1; } res = check_type(path, S_IFDIR); if (res == -1) return -1; res = check_mode(path, 0755); if (res == -1) return -1; for (i = 0; dir_files[i]; i++) { char fpath[1024]; sprintf(fpath, "%s/%s", path, dir_files[i]); res = create_file(fpath, "", 0); if (res == -1) { cleanup_dir(path, dir_files, 1); return -1; } } res = check_dir_contents(path, dir_files); if (res == -1) { cleanup_dir(path, dir_files, 1); return -1; } return 0; }
static int test_mkdir(void) { int res; int err = 0; const char *dir_contents[] = {NULL}; start_test("mkdir"); rmdir(testdir); res = mkdir(testdir, 0755); if (res == -1) { PERROR("mkdir"); return -1; } res = check_type(testdir, S_IFDIR); if (res == -1) return -1; err += check_mode(testdir, 0755); err += check_nlink(testdir, 2); err += check_dir_contents(testdir, dir_contents); res = rmdir(testdir); if (res == -1) { PERROR("rmdir"); return -1; } res = check_nonexist(testdir); if (res == -1) return -1; if (err) return -1; success(); return 0; }
static int test_link2(void) { const char *data = testdata; int datalen = testdatalen; int err = 0; int res; start_test("link-unlink-link"); res = create_file(testfile, data, datalen); if (res == -1) return -1; unlink(testfile2); res = link(testfile, testfile2); if (res == -1) { PERROR("link"); return -1; } res = unlink(testfile); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile); if (res == -1) return -1; res = link(testfile2, testfile); if (res == -1) { PERROR("link"); } res = check_type(testfile, S_IFREG); if (res == -1) return -1; err += check_mode(testfile, 0644); err += check_nlink(testfile, 2); err += check_size(testfile, datalen); err += check_data(testfile, data, 0, datalen); res = unlink(testfile2); if (res == -1) { PERROR("unlink"); return -1; } err += check_nlink(testfile, 1); res = unlink(testfile); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile); if (res == -1) return -1; if (err) return -1; success(); return 0; }
CELTEncoder *celt_encoder_create(const CELTMode *mode) { int N, C; CELTEncoder *st; if (check_mode(mode) != CELT_OK) return NULL; N = mode->mdctSize; C = mode->nbChannels; st = celt_alloc(sizeof(CELTEncoder)); if (st==NULL) return NULL; st->marker = ENCODERPARTIAL; st->mode = mode; st->frame_size = N; st->block_size = N; st->overlap = mode->overlap; st->VBR_rate = 0; st->pitch_enabled = 1; st->pitch_permitted = 1; st->pitch_available = 1; st->force_intra = 0; st->delayedIntra = 1; st->tonal_average = QCONST16(1.,8); st->fold_decision = 1; st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t)); st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t)); st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); st->preemph_memE = (celt_word16_t*)celt_alloc(C*sizeof(celt_word16_t)); st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t)); #ifdef EXP_PSY st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16_t)); psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs); #endif if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) #ifdef EXP_PSY && (st->psy_mem!=NULL) #endif && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL)) { st->marker = ENCODERVALID; return st; } /* If the setup fails for some reason deallocate it. */ celt_encoder_destroy(st); return NULL; }
static int test_symlink(void) { char buf[1024]; const char *data = testdata; int datalen = testdatalen; int linklen = strlen(testfile); int err = 0; int res; start_test("symlink"); res = create_file(testfile, data, datalen); if (res == -1) return -1; unlink(testfile2); res = symlink(testfile, testfile2); if (res == -1) { PERROR("symlink"); return -1; } res = check_type(testfile2, S_IFLNK); if (res == -1) return -1; err += check_mode(testfile2, 0777); err += check_nlink(testfile2, 1); res = readlink(testfile2, buf, sizeof(buf)); if (res == -1) { PERROR("readlink"); err--; } if (res != linklen) { ERROR("short readlink: %u instead of %u", res, linklen); err--; } if (memcmp(buf, testfile, linklen) != 0) { ERROR("link mismatch"); err--; } err += check_size(testfile2, datalen); err += check_data(testfile2, data, 0, datalen); res = unlink(testfile2); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile2); if (res == -1) return -1; if (err) return -1; success(); return 0; }
static int test_create(void) { const char *data = testdata; int datalen = testdatalen; int err = 0; int res; int fd; start_test("create"); unlink(testfile); fd = creat(testfile, 0644); if (fd == -1) { PERROR("creat"); return -1; } res = write(fd, data, datalen); if (res == -1) { PERROR("write"); close(fd); return -1; } if (res != datalen) { ERROR("write is short: %u instead of %u", res, datalen); close(fd); return -1; } res = close(fd); if (res == -1) { PERROR("close"); return -1; } res = check_type(testfile, S_IFREG); if (res == -1) return -1; err += check_mode(testfile, 0644); err += check_nlink(testfile, 1); err += check_size(testfile, datalen); err += check_data(testfile, data, 0, datalen); res = unlink(testfile); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile); if (res == -1) return -1; if (err) return -1; success(); return 0; }
static int create_file(const char *path, const char *data, int len) { int res; int fd; unlink(path); fd = creat(path, 0644); if (fd == -1) { PERROR("creat"); return -1; } if (len) { res = write(fd, data, len); if (res == -1) { PERROR("write"); close(fd); return -1; } if (res != len) { ERROR("write is short: %u instead of %u", res, len); close(fd); return -1; } } res = close(fd); if (res == -1) { PERROR("close"); return -1; } res = check_type(path, S_IFREG); if (res == -1) return -1; res = check_mode(path, 0644); if (res == -1) return -1; res = check_nlink(path, 1); if (res == -1) return -1; res = check_size(path, len); if (res == -1) return -1; if (len) { res = check_data(path, data, 0, len); if (res == -1) return -1; } return 0; }
static int test_rename_dir(void) { int err = 0; int res; start_test("rename dir"); res = create_dir(testdir, testdir_files); if (res == -1) return -1; rmdir(testdir2); res = rename(testdir, testdir2); if (res == -1) { PERROR("rename"); cleanup_dir(testdir, testdir_files, 1); return -1; } res = check_nonexist(testdir); if (res == -1) { cleanup_dir(testdir, testdir_files, 1); return -1; } res = check_type(testdir2, S_IFDIR); if (res == -1) { cleanup_dir(testdir2, testdir_files, 1); return -1; } err += check_mode(testdir2, 0755); err += check_dir_contents(testdir2, testdir_files); err += cleanup_dir(testdir2, testdir_files, 0); res = rmdir(testdir2); if (res == -1) { PERROR("rmdir"); return -1; } res = check_nonexist(testdir2); if (res == -1) return -1; if (err) return -1; success(); return 0; }
static int do_test_open_acc(int flags, const char *flags_str, int mode, int err) { const char *data = testdata; int datalen = testdatalen; int res; int fd; start_test("open_acc(%s) mode: 0%03o error: '%s'", flags_str, mode, strerror(err)); unlink(testfile); res = create_file(testfile, data, datalen); if (res == -1) return -1; res = chmod(testfile, mode); if (res == -1) { PERROR("chmod"); return -1; } res = check_mode(testfile, mode); if (res == -1) return -1; fd = open(testfile, flags); if (fd == -1) { if (err != errno) { PERROR("open"); return -1; } } else { if (err) { ERROR("open should have failed"); close(fd); return -1; } close(fd); } success(); return 0; }
void celt_encoder_destroy(CELTEncoder *st) { if (st == NULL) { celt_warning("NULL passed to celt_encoder_destroy"); return; } if (st->marker == ENCODERFREED) { celt_warning("Freeing an encoder which has already been freed"); return; } if (st->marker != ENCODERVALID && st->marker != ENCODERPARTIAL) { celt_warning("This is not a valid CELT encoder structure"); return; } /*Check_mode is non-fatal here because we can still free the encoder memory even if the mode is bad, although calling the free functions in this order is a violation of the API.*/ check_mode(st->mode); celt_free(st->in_mem); celt_free(st->out_mem); celt_free(st->oldBandE); celt_free(st->preemph_memE); celt_free(st->preemph_memD); #ifdef EXP_PSY celt_free (st->psy_mem); psydecay_clear(&st->psy); #endif st->marker = ENCODERFREED; celt_free(st); }
void SID_info(char *fmt, int mode, ...){ int flag_write_time; int i_level; FILE *fp_info; va_list vargs; va_start(vargs,mode); fp_info=stderr; #if USE_MPI if(!SID.flag_results_on && check_mode(mode,SID_INFO_RESULT)){ fprintf(fp_info,"\n"); fprintf(fp_info,"-------------\n"); fprintf(fp_info," Results \n"); fprintf(fp_info,"-------------\n"); fprintf(fp_info,"\n"); SID.flag_infos_started=TRUE; } #else if(SID.flag_continue){ fprintf(fp_info,"\n"); SID.level++; SID.flag_continue=FALSE; } // Write indenting text if(SID.indent){ for(i_level=0;i_level<SID.level;i_level++) fprintf(fp_info,"%s",SID_LOG_INDENT_STRING); } #endif // Write text vfprintf(fp_info,fmt,vargs); fprintf(fp_info,"\n"); fflush(fp_info); va_end(vargs); }
void list_dir(const char *name, char* mode_pattern) { DIR *dir; dirent_t *ent; char *entry_path, access_time[20]; stat_t entry_stat; dir = opendir(name); if(dir == NULL) { printf("Invalid directory name\n"); return; } while(ent = readdir(dir)) { if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; entry_path = malloc(strlen(name) + strlen(ent->d_name) + 2); sprintf(entry_path, "%s/%s", name, ent->d_name); stat(entry_path, &entry_stat); if(S_ISREG(entry_stat.st_mode) && check_mode(&entry_stat, mode_pattern)) { strftime(access_time, 20, "%Y-%m-%d %H:%M:%S", localtime(&entry_stat.st_atime)); printf("File name: \t%s\n", entry_path); printf("File size: \t%d bytes\n", (int)entry_stat.st_size); printf("Last access: \t%s\n", access_time); printf("------------------------\n"); } if(S_ISDIR(entry_stat.st_mode)) { list_dir(entry_path, mode_pattern); } free(entry_path); } closedir(dir); }
_WCRTLINK int _open_osfhandle( long osfhandle, int flags ) { int posix_handle; #if defined(__NT__) // Under Win32, we get an OS handle argument posix_handle = __allocPOSIXHandle( (HANDLE)osfhandle ); if( posix_handle == -1 ) return( -1 ); #else // Under everything else, we get a POSIX handle argument posix_handle = osfhandle; #endif #if !defined(__NETWARE__) if( check_mode( posix_handle, flags ) ) { return( -1 ); } #if !defined(__UNIX__) { int rwmode; unsigned io_mode; rwmode = flags & ( O_RDONLY | O_WRONLY | O_RDWR ); io_mode = __GetIOMode( posix_handle ); io_mode &= ~(_READ|_WRITE|_APPEND|_BINARY); if( rwmode == O_RDWR ) io_mode |= _READ | _WRITE; if( rwmode == O_RDONLY) io_mode |= _READ; if( rwmode == O_WRONLY) io_mode |= _WRITE; if( flags & O_APPEND ) io_mode |= _APPEND; if( flags & O_BINARY ) { io_mode |= _BINARY; } __SetIOMode( posix_handle, io_mode ); } #endif #endif return( posix_handle ); }
int main(int argc, char* argv[]) { int opt = 0; int optindex = 0; char* ipsw = NULL; char* uuid = NULL; int tss_enabled = 0; int shsh_only = 0; char* shsh_dir = NULL; use_apple_server=1; // create an instance of our context struct idevicerestore_client_t* client = (struct idevicerestore_client_t*) malloc(sizeof(struct idevicerestore_client_t)); if (client == NULL) { error("ERROR: Out of memory\n"); return -1; } memset(client, '\0', sizeof(struct idevicerestore_client_t)); while ((opt = getopt_long(argc, argv, "dhcesxtpi:u:", longopts, &optindex)) > 0) { switch (opt) { case 'h': usage(argc, argv); return 0; case 'd': client->flags |= FLAG_DEBUG; idevicerestore_debug = 1; break; case 'e': client->flags |= FLAG_ERASE; break; case 'c': client->flags |= FLAG_CUSTOM; break; case 's': use_apple_server=0; break; case 'x': client->flags |= FLAG_EXCLUDE; break; case 'i': if (optarg) { char* tail = NULL; client->ecid = strtoull(optarg, &tail, 16); if (tail && (tail[0] != '\0')) { client->ecid = 0; } if (client->ecid == 0) { error("ERROR: Could not parse ECID from '%s'\n", optarg); return -1; } } break; case 'u': uuid = optarg; break; case 't': shsh_only = 1; break; case 'p': client->flags |= FLAG_PWN; break; default: usage(argc, argv); return -1; } } if (((argc-optind) == 1) || (client->flags & FLAG_PWN)) { argc -= optind; argv += optind; ipsw = argv[0]; } else { usage(argc, argv); return -1; } if (client->flags & FLAG_DEBUG) { idevice_set_debug_level(1); irecv_set_debug_level(1); } client->uuid = uuid; client->ipsw = ipsw; // update version data (from cache, or apple if too old) load_version_data(client); // check which mode the device is currently in so we know where to start if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) { error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n"); return -1; } info("Found device in %s mode\n", client->mode->string); if (client->mode->index == MODE_WTF) { int cpid = 0; if (dfu_client_new(client) != 0) { error("ERROR: Could not open device in WTF mode\n"); return -1; } if ((dfu_get_cpid(client, &cpid) < 0) || (cpid == 0)) { error("ERROR: Could not get CPID for WTF mode device\n"); dfu_client_free(client); return -1; } char* s_wtfurl = NULL; plist_t wtfurl = plist_access_path(client->version_data, 7, "MobileDeviceSoftwareVersionsByVersion", "5", "RecoverySoftwareVersions", "WTF", "304218112", "5", "FirmwareURL"); if (wtfurl && (plist_get_node_type(wtfurl) == PLIST_STRING)) { plist_get_string_val(wtfurl, &s_wtfurl); } if (!s_wtfurl) { info("Using hardcoded x12220000_5_Recovery.ipsw URL\n"); s_wtfurl = strdup("http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPhone/061-6618.20090617.Xse7Y/x12220000_5_Recovery.ipsw"); } // make a local file name char* fnpart = strrchr(s_wtfurl, '/'); if (!fnpart) { fnpart = "x12220000_5_Recovery.ipsw"; } else { fnpart++; } struct stat fst; char wtfipsw[256]; sprintf(wtfipsw, "cache/%s", fnpart); if (stat(wtfipsw, &fst) != 0) { __mkdir("cache", 0755); download_to_file(s_wtfurl, wtfipsw); } char wtfname[256]; sprintf(wtfname, "Firmware/dfu/WTF.s5l%04xxall.RELEASE.dfu", cpid); char* wtftmp = NULL; uint32_t wtfsize = 0; ipsw_extract_to_memory(wtfipsw, wtfname, &wtftmp, &wtfsize); if (!wtftmp) { error("ERROR: Could not extract WTF\n"); } else { if (dfu_send_buffer(client, wtftmp, wtfsize) != 0) { error("ERROR: Could not send WTF...\n"); } } dfu_client_free(client); sleep(1); free(wtftmp); client->mode = &idevicerestore_modes[MODE_DFU]; } // discover the device type if (check_device(client) < 0 || client->device->index == DEVICE_UNKNOWN) { error("ERROR: Unable to discover device type\n"); return -1; } info("Identified device as %s\n", client->device->product); if ((client->flags & FLAG_PWN) && (client->mode->index != MODE_DFU)) { error("ERROR: you need to put your device into DFU mode to pwn it.\n"); return -1; } if (client->flags & FLAG_PWN) { recovery_client_free(client); info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { return -1; } info("exploiting with limera1n...\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); return -1; } dfu_client_free(client); info("Device should be in pwned DFU state now.\n"); return 0; } if (client->mode->index == MODE_RESTORE) { if (restore_reboot(client) < 0) { error("ERROR: Unable to exit restore mode\n"); return -1; } } // extract buildmanifest plist_t buildmanifest = NULL; if (client->flags & FLAG_CUSTOM) { info("Extracting Restore.plist from IPSW\n"); if (ipsw_extract_restore_plist(ipsw, &buildmanifest) < 0) { error("ERROR: Unable to extract Restore.plist from %s\n", ipsw); return -1; } } else { info("Extracting BuildManifest from IPSW\n"); if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) { error("ERROR: Unable to extract BuildManifest from %s\n", ipsw); return -1; } } /* check if device type is supported by the given build manifest */ if (build_manifest_check_compatibility(buildmanifest, client->device->product) < 0) { error("ERROR: could not make sure this firmware is suitable for the current device. refusing to continue.\n"); return -1; } /* print iOS information from the manifest */ build_manifest_get_version_information(buildmanifest, &client->version, &client->build); info("Product Version: %s\n", client->version); info("Product Build: %s\n", client->build); if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; info("Custom firmware requested. Disabled TSS request.\n"); } // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; if (client->flags & FLAG_CUSTOM) { build_identity = plist_new_dict(); { plist_t node; plist_t comp; plist_t info; plist_t manifest; info = plist_new_dict(); plist_dict_insert_item(info, "RestoreBehavior", plist_new_string((client->flags & FLAG_ERASE) ? "Erase" : "Update")); plist_dict_insert_item(info, "Variant", plist_new_string((client->flags & FLAG_ERASE) ? "Customer Erase Install (IPSW)" : "Customer Upgrade Install (IPSW)")); plist_dict_insert_item(build_identity, "Info", info); manifest = plist_new_dict(); char tmpstr[256]; char p_all_flash[128]; char lcmodel[8]; strcpy(lcmodel, client->device->model); int x = 0; while (lcmodel[x]) { lcmodel[x] = tolower(lcmodel[x]); x++; } sprintf(p_all_flash, "Firmware/all_flash/all_flash.%s.%s", lcmodel, "production"); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/manifest"); // get all_flash file manifest char *files[16]; char *fmanifest = NULL; uint32_t msize = 0; if (ipsw_extract_to_memory(ipsw, tmpstr, &fmanifest, &msize) < 0) { error("ERROR: could not extract %s from IPSW\n", tmpstr); return -1; } char *tok = strtok(fmanifest, "\r\n"); int fc = 0; while (tok) { files[fc++] = strdup(tok); if (fc >= 16) { break; } tok = strtok(NULL, "\r\n"); } free(fmanifest); for (x = 0; x < fc; x++) { info = plist_new_dict(); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/"); strcat(tmpstr, files[x]); plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); const char* compname = get_component_name(files[x]); if (compname) { plist_dict_insert_item(manifest, compname, comp); if (!strncmp(files[x], "DeviceTree", 10)) { plist_dict_insert_item(manifest, "RestoreDeviceTree", plist_copy(comp)); } } else { error("WARNING: unhandled component %s\n", files[x]); plist_free(comp); } free(files[x]); files[x] = NULL; } // add iBSS sprintf(tmpstr, "Firmware/dfu/iBSS.%s.%s.dfu", lcmodel, "RELEASE"); info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "iBSS", comp); // add iBEC sprintf(tmpstr, "Firmware/dfu/iBEC.%s.%s.dfu", lcmodel, "RELEASE"); info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "iBEC", comp); // add kernel cache node = plist_dict_get_item(buildmanifest, "KernelCachesByTarget"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { char tt[4]; strncpy(tt, lcmodel, 3); tt[3] = 0; plist_t kdict = plist_dict_get_item(node, tt); if (kdict && (plist_get_node_type(kdict) == PLIST_DICT)) { plist_t kc = plist_dict_get_item(kdict, "Release"); if (kc && (plist_get_node_type(kc) == PLIST_STRING)) { info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_copy(kc)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "KernelCache", comp); plist_dict_insert_item(manifest, "RestoreKernelCache", plist_copy(comp)); } } } // add ramdisk node = plist_dict_get_item(buildmanifest, "RestoreRamDisks"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { plist_t rd = plist_dict_get_item(node, (client->flags & FLAG_ERASE) ? "User" : "Update"); if (rd && (plist_get_node_type(rd) == PLIST_STRING)) { info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_copy(rd)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "RestoreRamDisk", comp); } } // add OS filesystem node = plist_dict_get_item(buildmanifest, "SystemRestoreImages"); if (!node) { error("ERROR: missing SystemRestoreImages in Restore.plist\n"); } plist_t os = plist_dict_get_item(node, "User"); if (!os) { error("ERROR: missing filesystem in Restore.plist\n"); } else { info = plist_new_dict(); plist_dict_insert_item(info, "Path", plist_copy(os)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", info); plist_dict_insert_item(manifest, "OS", comp); } // finally add manifest plist_dict_insert_item(build_identity, "Manifest", manifest); } } else if (client->flags & FLAG_ERASE) { build_identity = build_manifest_get_build_identity(buildmanifest, 0); if (build_identity == NULL) { error("ERROR: Unable to find any build identities\n"); plist_free(buildmanifest); return -1; } } else { // loop through all build identities in the build manifest // and list the valid ones int i = 0; int valid_builds = 0; int build_count = build_manifest_get_identity_count(buildmanifest); for (i = 0; i < build_count; i++) { build_identity = build_manifest_get_build_identity(buildmanifest, i); valid_builds++; } } /* print information about current build identity */ build_identity_print_information(build_identity); /* retrieve shsh blobs if required */ if (tss_enabled) { debug("Getting device's ECID for TSS request\n"); /* fetch the device's ECID for the TSS request */ if (get_ecid(client, &client->ecid) < 0) { error("ERROR: Unable to find device ECID\n"); return -1; } info("Found ECID " FMT_qu "\n", (long long unsigned int)client->ecid); if (get_shsh_blobs(client, client->ecid, NULL, 0, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } } if (shsh_only) { if (!tss_enabled) { info("This device does not require a TSS record"); return 0; } if (!client->tss) { error("ERROR: could not fetch TSS record"); plist_free(buildmanifest); return -1; } else { char *bin = NULL; uint32_t blen = 0; plist_to_bin(client->tss, &bin, &blen); if (bin) { char zfn[512]; sprintf(zfn, "shsh/" FMT_qu "-%s-%s.shsh", (long long int)client->ecid, client->device->product, client->version); __mkdir("shsh", 0755); struct stat fst; if (stat(zfn, &fst) != 0) { gzFile zf = gzopen(zfn, "wb"); gzwrite(zf, bin, blen); gzclose(zf); info("SHSH saved to '%s'\n", zfn); } else { info("SHSH '%s' already present.\n", zfn); } free(bin); } else { error("ERROR: could not get TSS record data\n"); } plist_free(client->tss); plist_free(buildmanifest); return 0; } } /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } if ((tss_enabled) && client->tss) { /* fix empty dicts */ fixup_tss(client->tss); } // Extract filesystem from IPSW and return its name char* filesystem = NULL; if (ipsw_extract_filesystem(client->ipsw, build_identity, &filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } // if the device is in normal mode, place device into recovery mode if (client->mode->index == MODE_NORMAL) { info("Entering recovery mode...\n"); if (normal_enter_recovery(client) < 0) { error("ERROR: Unable to place device into recovery mode\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } } // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { recovery_client_free(client); if (client->flags & FLAG_CUSTOM) { info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { return -1; } info("exploiting with limera1n\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); return -1; } dfu_client_free(client); info("exploited\n"); } if (dfu_enter_recovery(client, build_identity) < 0) { error("ERROR: Unable to place device into recovery mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } if (client->mode->index == MODE_DFU) { client->mode = &idevicerestore_modes[MODE_RECOVERY]; } else { /* now we load the iBEC */ if (recovery_send_ibec(client, build_identity) < 0) { error("ERROR: Unable to send iBEC\n"); return -1; } recovery_client_free(client); /* this must be long enough to allow the device to run the iBEC */ /* FIXME: Probably better to detect if the device is back then */ sleep(7); } if (client->build[0] > '8') { // we need another tss request with nonce. unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (get_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get nonce from device!\n"); recovery_send_reset(client); return -1; } if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) { nonce_changed = 1; if (client->nonce) { free(client->nonce); } client->nonce = nonce; client->nonce_size = nonce_size; } else { free(nonce); } info("Nonce: "); int i; for (i = 0; i < client->nonce_size; i++) { info("%02x ", client->nonce[i]); } info("\n"); if (nonce_changed && !(client->flags & FLAG_CUSTOM)) { // Welcome iOS5. We have to re-request the TSS with our nonce. plist_free(client->tss); if (get_shsh_blobs(client, client->ecid, client->nonce, client->nonce_size, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } if (!client->tss) { error("ERROR: can't continue without TSS\n"); return -1; } fixup_tss(client->tss); } } // now finally do the magic to put the device into restore mode if (client->mode->index == MODE_RECOVERY) { if (client->srnm == NULL) { error("ERROR: could not retrieve device serial number. Can't continue.\n"); return -1; } if (recovery_enter_restore(client, build_identity) < 0) { error("ERROR: Unable to place device into restore mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } // device is finally in restore mode, let's do this if (client->mode->index == MODE_RESTORE) { info("About to restore device... \n"); if (restore_device(client, build_identity, filesystem) < 0) { error("ERROR: Unable to restore device\n"); return -1; } } info("Cleaning up...\n"); if (filesystem) unlink(filesystem); info("DONE\n"); return 0; }
int main(void) { robockey_init(); while(1) { comm(command); mode = check_mode(); if(wii_flag && command == PLAY) { location_flag = localization(blobs, calibration, location); wii_flag = 0; } switch(mode) { case 0: // normal mode(GOAL A), need command PLAY TO START if(switch_flag) { goal[0] = -125; goal[1] = 0; goal[2] = 0; if(command == HALFTIME) { goal[0] = 125; switch_flag = 0; } } if(command == PLAY) { //if(!found) //{ //found = find(adc1, adc2, &count); //set(TIMSK0,OCIE0A); // Enable timer0 interrupt //} if(find(adc1, adc2, &count)) { m_green(TOGGLE); m_red(OFF); move(location, goal); } } break; case 1: // normal mode(GOAL B), need command PLAY TO START if(switch_flag) { goal[0] = 125; goal[1] = 0; goal[2] = 0; if(command == HALFTIME) { goal[0] = -125; switch_flag = 0; } } if(command == PLAY) { if(find(adc1, adc2, &count)) { m_green(TOGGLE); m_red(OFF); move(location, goal); } } break; case 2: // calibrate the center of the rink m_green(ON); m_red(ON); if(wii_flag) { float calibrationDefault[2] = {0, 0}; float calibrationResult[3] = {0, 0, 0}; if(localization(blobs, calibrationDefault, calibrationResult)) { //m_green(ON); //m_red(ON); calibration[0] = calibrationResult[0]; calibration[1] = calibrationResult[1]; } } break; case 3: // test mode(GOAL A), always play while the power is on. m_green(TOGGLE); m_red(OFF); if(find(adc1, adc2, &count)) { if(wii_flag) { //if(!found) //{ //found = find(adc1, adc2, &count); //set(TIMSK0,OCIE0A); // Enable interrupt //} if(localization(blobs, calibration, location)) { float goal[3] = {-115, 0, 0}; move(location, goal); } } } break; case 4: // test mode(GOAL B), always play while the power is on. m_red(TOGGLE); m_green(OFF); if(find(adc1, adc2, &count)) { if(wii_flag) { if(localization(blobs, calibration, location)) { float goal[3] = {115, 0, 0}; move(location, goal); } } } break; case 5: m_green(ON); m_red(ON); OCR1B = OCR1A; OCR1C = 0.98*OCR1A; break; case 6: qualify_test(&command, blobs, location, &orientation_flag, &west_flag, &east_flag, calibration); break; case 7: OCR1B = OCR1A; OCR1C = 0; m_wait(3200); OCR1B = OCR1A/2; OCR1C = OCR1A/2; m_wait(32000); break; default: OCR1B = 0.5*OCR1A; OCR1C = 0.5*OCR1A; m_green(OFF); m_red(OFF); } m_usb_tx_int((int)(location[0])); m_usb_tx_char('\t'); m_usb_tx_int((int)(location[1])); m_usb_tx_char('\t'); m_usb_tx_int((int)(adc1[0])); m_usb_tx_char('\t'); m_usb_tx_int((int)(adc2[0])); m_usb_tx_char('\t'); m_usb_tx_int((int)(check(PIND, 7))); m_usb_tx_char('\t'); m_usb_tx_char('\r'); if(!check(ADCSRA, ADIF)) set(ADCSRA,ADSC); } }
static int test_ftruncate(int len, int mode) { const char *data = testdata; int datalen = testdatalen; int res; int fd; start_test("ftruncate(%u) mode: 0%03o", len, mode); res = create_file(testfile, data, datalen); if (res == -1) return -1; fd = open(testfile, O_WRONLY); if (fd == -1) { PERROR("open"); return -1; } res = fchmod(fd, mode); if (res == -1) { PERROR("fchmod"); close(fd); return -1; } res = check_mode(testfile, mode); if (res == -1) { close(fd); return -1; } res = ftruncate(fd, len); if (res == -1) { PERROR("ftruncate"); close(fd); return -1; } close(fd); res = check_size(testfile, len); if (res == -1) return -1; if (len > 0) { if (len <= datalen) { res = check_data(testfile, data, 0, len); if (res == -1) return -1; } else { res = check_data(testfile, data, 0, datalen); if (res == -1) return -1; res = check_data(testfile, zerodata, datalen, len - datalen); if (res == -1) return -1; } } res = unlink(testfile); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile); if (res == -1) return -1; success(); return 0; }
static int do_test_open(int exist, int flags, const char *flags_str, int mode) { char buf[4096]; const char *data = testdata; int datalen = testdatalen; unsigned currlen = 0; int err = 0; int res; int fd; loff_t off; start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode); unlink(testfile); if (exist) { res = create_file(testfile, testdata2, testdata2len); if (res == -1) return -1; currlen = testdata2len; } fd = open(testfile, flags, mode); if ((flags & O_CREAT) && (flags & O_EXCL) && exist) { if (fd != -1) { ERROR("open should have failed"); close(fd); return -1; } else if (errno == EEXIST) goto succ; } if (!(flags & O_CREAT) && !exist) { if (fd != -1) { ERROR("open should have failed"); close(fd); return -1; } else if (errno == ENOENT) goto succ; } if (fd == -1) { PERROR("open"); return -1; } if (flags & O_TRUNC) currlen = 0; err += check_type(testfile, S_IFREG); if (exist) err += check_mode(testfile, 0644); else err += check_mode(testfile, mode); err += check_nlink(testfile, 1); err += check_size(testfile, currlen); if (exist && !(flags & O_TRUNC) && (mode & 0400)) err += check_data(testfile, testdata2, 0, testdata2len); res = write(fd, data, datalen); if ((flags & O_ACCMODE) != O_RDONLY) { if (res == -1) { PERROR("write"); err --; } else if (res != datalen) { ERROR("write is short: %u instead of %u", res, datalen); err --; } else { if (datalen > (int) currlen) currlen = datalen; err += check_size(testfile, currlen); if (mode & 0400) { err += check_data(testfile, data, 0, datalen); if (exist && !(flags & O_TRUNC) && testdata2len > datalen) err += check_data(testfile, testdata2 + datalen, datalen, testdata2len - datalen); } } } else { if (res != -1) { ERROR("write should have failed"); err --; } else if (errno != EBADF) { PERROR("write"); err --; } } off = lseek(fd, SEEK_SET, 0); if (off == (loff_t) -1) { PERROR("lseek"); err--; } else if (off != 0) { ERROR("offset should have returned 0"); err --; } res = read(fd, buf, sizeof(buf)); if ((flags & O_ACCMODE) != O_WRONLY) { if (res == -1) { PERROR("read"); err--; } else { int readsize = currlen < sizeof(buf) ? currlen : sizeof(buf); if (res != readsize) { ERROR("read is short: %i instead of %u", res, readsize); err--; } else { if ((flags & O_ACCMODE) != O_RDONLY) { err += check_buffer(buf, data, datalen); if (exist && !(flags & O_TRUNC) && testdata2len > datalen) err += check_buffer(buf + datalen, testdata2 + datalen, testdata2len - datalen); } else if (exist) err += check_buffer(buf, testdata2, testdata2len); } } } else { if (res != -1) { ERROR("read should have failed"); err --; } else if (errno != EBADF) { PERROR("read"); err --; } } res = close(fd); if (res == -1) { PERROR("close"); return -1; } res = unlink(testfile); if (res == -1) { PERROR("unlink"); return -1; } res = check_nonexist(testfile); if (res == -1) return -1; if (err) return -1; succ: success(); return 0; }
void test_core_mkdir__chmods(void) { struct stat st; mode_t *old = git__malloc(sizeof(mode_t)); *old = p_umask(022); cl_set_cleanup(cleanup_chmod_root, old); cl_git_pass(git_futils_mkdir("r", NULL, 0777, 0)); cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH)); cl_git_pass(git_path_lstat("r/mode", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_path_lstat("r/mode/is", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_path_lstat("r/mode/is/important", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_futils_mkdir("mode2/is2/important2", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD)); cl_git_pass(git_path_lstat("r/mode2", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_path_lstat("r/mode2/is2", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_path_lstat("r/mode2/is2/important2", &st)); check_mode(0777, st.st_mode); cl_git_pass(git_futils_mkdir("mode3/is3/important3", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH)); cl_git_pass(git_path_lstat("r/mode3", &st)); check_mode(0777, st.st_mode); cl_git_pass(git_path_lstat("r/mode3/is3", &st)); check_mode(0777, st.st_mode); cl_git_pass(git_path_lstat("r/mode3/is3/important3", &st)); check_mode(0777, st.st_mode); /* test that we chmod existing dir */ cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD)); cl_git_pass(git_path_lstat("r/mode", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_path_lstat("r/mode/is", &st)); check_mode(0755, st.st_mode); cl_git_pass(git_path_lstat("r/mode/is/important", &st)); check_mode(0777, st.st_mode); /* test that we chmod even existing dirs if CHMOD_PATH is set */ cl_git_pass(git_futils_mkdir("mode2/is2/important2.1", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH)); cl_git_pass(git_path_lstat("r/mode2", &st)); check_mode(0777, st.st_mode); cl_git_pass(git_path_lstat("r/mode2/is2", &st)); check_mode(0777, st.st_mode); cl_git_pass(git_path_lstat("r/mode2/is2/important2.1", &st)); check_mode(0777, st.st_mode); }
CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error) { int N, C; CELTEncoder *st; if (check_mode(mode) != CELT_OK) { if (error) *error = CELT_INVALID_MODE; return NULL; } #ifdef DISABLE_STEREO if (channels > 1) { celt_warning("Stereo support was disable from this build"); if (error) *error = CELT_BAD_ARG; return NULL; } #endif if (channels < 0 || channels > 2) { celt_warning("Only mono and stereo supported"); if (error) *error = CELT_BAD_ARG; return NULL; } N = mode->mdctSize; C = channels; st = celt_alloc(sizeof(CELTEncoder)); if (st==NULL) { if (error) *error = CELT_ALLOC_FAIL; return NULL; } st->marker = ENCODERPARTIAL; st->mode = mode; st->frame_size = N; st->block_size = N; st->overlap = mode->overlap; st->channels = channels; st->vbr_rate = 0; st->pitch_enabled = 1; st->pitch_permitted = 1; st->pitch_available = 1; st->force_intra = 0; st->delayedIntra = 1; st->tonal_average = QCONST16(1.,8); st->fold_decision = 1; st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig)); st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig)); st->pitch_buf = celt_alloc(((MAX_PERIOD>>1)+2)*sizeof(celt_word16)); st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16)); st->preemph_memE = (celt_word16*)celt_alloc(C*sizeof(celt_word16)); st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig)); if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL)) { if (error) *error = CELT_OK; st->marker = ENCODERVALID; return st; } /* If the setup fails for some reason deallocate it. */ celt_encoder_destroy(st); if (error) *error = CELT_ALLOC_FAIL; return NULL; }
int main(int argc, char* argv[]) { int opt = 0; int optindex = 0; char* ipsw = NULL; char* uuid = NULL; int tss_enabled = 0; // create an instance of our context struct idevicerestore_client_t* client = (struct idevicerestore_client_t*) malloc(sizeof(struct idevicerestore_client_t)); if (client == NULL) { error("ERROR: Out of memory\n"); return -1; } memset(client, '\0', sizeof(struct idevicerestore_client_t)); while ((opt = getopt_long(argc, argv, "dhcexu:", longopts, &optindex)) > 0) { switch (opt) { case 'h': usage(argc, argv); return 0; case 'd': client->flags |= FLAG_DEBUG; idevicerestore_debug = 1; break; case 'e': client->flags |= FLAG_ERASE; break; case 'c': client->flags |= FLAG_CUSTOM; break; case 'x': client->flags |= FLAG_EXCLUDE; break; case 'u': uuid = optarg; break; default: usage(argc, argv); return -1; } } if ((argc-optind) == 1) { argc -= optind; argv += optind; ipsw = argv[0]; } else { usage(argc, argv); return -1; } if (client->flags & FLAG_DEBUG) { idevice_set_debug_level(1); irecv_set_debug_level(1); } client->uuid = uuid; client->ipsw = ipsw; // check which mode the device is currently in so we know where to start if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) { error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n"); return -1; } info("Found device in %s mode\n", client->mode->string); // discover the device type if (check_device(client) < 0 || client->device->index == DEVICE_UNKNOWN) { error("ERROR: Unable to discover device type\n"); return -1; } info("Identified device as %s\n", client->device->product); if (client->mode->index == MODE_RESTORE) { if (restore_reboot(client) < 0) { error("ERROR: Unable to exit restore mode\n"); return -1; } } // extract buildmanifest plist_t buildmanifest = NULL; info("Extracting BuildManifest from IPSW\n"); if (ipsw_extract_build_manifest(ipsw, &buildmanifest, &tss_enabled) < 0) { error("ERROR: Unable to extract BuildManifest from %s\n", ipsw); return -1; } /* print iOS information from the manifest */ build_manifest_print_information(buildmanifest); if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; info("Custom firmware requested. Disabled TSS request.\n"); } // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; if (client->flags & FLAG_ERASE) { build_identity = build_manifest_get_build_identity(buildmanifest, 0); if (build_identity == NULL) { error("ERROR: Unable to find any build identities\n"); plist_free(buildmanifest); return -1; } } else { // loop through all build identities in the build manifest // and list the valid ones int i = 0; int valid_builds = 0; int build_count = build_manifest_get_identity_count(buildmanifest); for (i = 0; i < build_count; i++) { build_identity = build_manifest_get_build_identity(buildmanifest, i); valid_builds++; } } /* print information about current build identity */ build_identity_print_information(build_identity); /* retrieve shsh blobs if required */ if (tss_enabled) { debug("Getting device's ECID for TSS request\n"); /* fetch the device's ECID for the TSS request */ if (get_ecid(client, &client->ecid) < 0) { error("ERROR: Unable to find device ECID\n"); return -1; } info("Found ECID %llu\n", client->ecid); if (get_shsh_blobs(client, client->ecid, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } } /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } // Extract filesystem from IPSW and return its name char* filesystem = NULL; if (ipsw_extract_filesystem(client->ipsw, build_identity, &filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } // if the device is in normal mode, place device into recovery mode if (client->mode->index == MODE_NORMAL) { info("Entering recovery mode...\n"); if (normal_enter_recovery(client) < 0) { error("ERROR: Unable to place device into recovery mode\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } } // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { if (dfu_enter_recovery(client, build_identity) < 0) { error("ERROR: Unable to place device into recovery mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } // if the device is in recovery mode, place device into restore mode if (client->mode->index == MODE_RECOVERY) { if (recovery_enter_restore(client, build_identity) < 0) { error("ERROR: Unable to place device into restore mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); return -1; } } // device is finally in restore mode, let's do this if (client->mode->index == MODE_RESTORE) { info("Restoring device... \n"); if (restore_device(client, build_identity, filesystem) < 0) { error("ERROR: Unable to restore device\n"); return -1; } } info("Cleaning up...\n"); if (filesystem) unlink(filesystem); info("DONE\n"); return 0; }
ATF_TC_BODY(dup_mode, tc) { check_mode(true, false, false); }
ATF_TC_BODY(dup3_mode, tc) { check_mode(false, false, true); }
int idevicerestore_start(struct idevicerestore_client_t* client) { int tss_enabled = 0; int result = 0; if (!client) { return -1; } if ((client->flags & FLAG_LATEST) && (client->flags & FLAG_CUSTOM)) { error("ERROR: FLAG_LATEST cannot be used with FLAG_CUSTOM.\n"); return -1; } if (!client->ipsw && !(client->flags & FLAG_PWN) && !(client->flags & FLAG_LATEST)) { error("ERROR: no ipsw file given\n"); return -1; } if (client->flags & FLAG_DEBUG) { idevice_set_debug_level(1); irecv_set_debug_level(1); idevicerestore_debug = 1; } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.0); // update version data (from cache, or apple if too old) load_version_data(client); // check which mode the device is currently in so we know where to start if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) { error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n"); return -1; } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.1); info("Found device in %s mode\n", client->mode->string); if (client->mode->index == MODE_WTF) { unsigned int cpid = 0; if (dfu_client_new(client) != 0) { error("ERROR: Could not open device in WTF mode\n"); return -1; } if ((dfu_get_cpid(client, &cpid) < 0) || (cpid == 0)) { error("ERROR: Could not get CPID for WTF mode device\n"); dfu_client_free(client); return -1; } char wtfname[256]; sprintf(wtfname, "Firmware/dfu/WTF.s5l%04xxall.RELEASE.dfu", cpid); unsigned char* wtftmp = NULL; unsigned int wtfsize = 0; // Prefer to get WTF file from the restore IPSW ipsw_extract_to_memory(client->ipsw, wtfname, &wtftmp, &wtfsize); if (!wtftmp) { // Download WTF IPSW char* s_wtfurl = NULL; plist_t wtfurl = plist_access_path(client->version_data, 7, "MobileDeviceSoftwareVersionsByVersion", "5", "RecoverySoftwareVersions", "WTF", "304218112", "5", "FirmwareURL"); if (wtfurl && (plist_get_node_type(wtfurl) == PLIST_STRING)) { plist_get_string_val(wtfurl, &s_wtfurl); } if (!s_wtfurl) { info("Using hardcoded x12220000_5_Recovery.ipsw URL\n"); s_wtfurl = strdup("http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPhone/061-6618.20090617.Xse7Y/x12220000_5_Recovery.ipsw"); } // make a local file name char* fnpart = strrchr(s_wtfurl, '/'); if (!fnpart) { fnpart = "x12220000_5_Recovery.ipsw"; } else { fnpart++; } struct stat fst; char wtfipsw[1024]; if (client->cache_dir) { if (stat(client->cache_dir, &fst) < 0) { mkdir_with_parents(client->cache_dir, 0755); } strcpy(wtfipsw, client->cache_dir); strcat(wtfipsw, "/"); strcat(wtfipsw, fnpart); } else { strcpy(wtfipsw, fnpart); } if (stat(wtfipsw, &fst) != 0) { download_to_file(s_wtfurl, wtfipsw, 0); } ipsw_extract_to_memory(wtfipsw, wtfname, &wtftmp, &wtfsize); if (!wtftmp) { error("ERROR: Could not extract WTF\n"); } } if (wtftmp) { if (dfu_send_buffer(client, wtftmp, wtfsize) != 0) { error("ERROR: Could not send WTF...\n"); } } dfu_client_free(client); sleep(1); free(wtftmp); client->mode = &idevicerestore_modes[MODE_DFU]; } // discover the device type if (check_product_type(client) == NULL || client->device == NULL) { error("ERROR: Unable to discover device type\n"); return -1; } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.2); info("Identified device as %s\n", client->device->product_type); if ((client->flags & FLAG_PWN) && (client->mode->index != MODE_DFU)) { error("ERROR: you need to put your device into DFU mode to pwn it.\n"); return -1; } if (client->flags & FLAG_PWN) { recovery_client_free(client); info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { return -1; } info("exploiting with limera1n...\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, &client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); return -1; } dfu_client_free(client); info("Device should be in pwned DFU state now.\n"); return 0; } if (client->flags & FLAG_LATEST) { char* ipsw = NULL; int res = ipsw_download_latest_fw(client->version_data, client->device->product_type, "cache", &ipsw); if (res != 0) { if (ipsw) { free(ipsw); } return res; } else { client->ipsw = ipsw; } } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.6); if (client->flags & FLAG_NOACTION) { return 0; } if (client->mode->index == MODE_RESTORE) { if (restore_reboot(client) < 0) { error("ERROR: Unable to exit restore mode\n"); return -2; } // we need to refresh the current mode again check_mode(client); info("Found device in %s mode\n", client->mode->string); } // verify if ipsw file exists if (access(client->ipsw, F_OK) < 0) { error("ERROR: Firmware file %s does not exist.\n", client->ipsw); return -1; } // extract buildmanifest plist_t buildmanifest = NULL; if (client->flags & FLAG_CUSTOM) { info("Extracting Restore.plist from IPSW\n"); if (ipsw_extract_restore_plist(client->ipsw, &buildmanifest) < 0) { error("ERROR: Unable to extract Restore.plist from %s. Firmware file might be corrupt.\n", client->ipsw); return -1; } } else { info("Extracting BuildManifest from IPSW\n"); if (ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &tss_enabled) < 0) { error("ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw); return -1; } } idevicerestore_progress(client, RESTORE_STEP_DETECT, 0.8); /* check if device type is supported by the given build manifest */ if (build_manifest_check_compatibility(buildmanifest, client->device->product_type) < 0) { error("ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n"); return -1; } /* print iOS information from the manifest */ build_manifest_get_version_information(buildmanifest, client); info("Product Version: %s\n", client->version); info("Product Build: %s Major: %d\n", client->build, client->build_major); if (client->flags & FLAG_CUSTOM) { /* prevent signing custom firmware */ tss_enabled = 0; info("Custom firmware requested. Disabled TSS request.\n"); } // choose whether this is an upgrade or a restore (default to upgrade) client->tss = NULL; plist_t build_identity = NULL; if (client->flags & FLAG_CUSTOM) { build_identity = plist_new_dict(); { plist_t node; plist_t comp; plist_t inf; plist_t manifest; char tmpstr[256]; char p_all_flash[128]; char lcmodel[8]; strcpy(lcmodel, client->device->hardware_model); int x = 0; while (lcmodel[x]) { lcmodel[x] = tolower(lcmodel[x]); x++; } sprintf(p_all_flash, "Firmware/all_flash/all_flash.%s.%s", lcmodel, "production"); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/manifest"); // get all_flash file manifest char *files[16]; char *fmanifest = NULL; uint32_t msize = 0; if (ipsw_extract_to_memory(client->ipsw, tmpstr, (unsigned char**)&fmanifest, &msize) < 0) { error("ERROR: could not extract %s from IPSW\n", tmpstr); return -1; } char *tok = strtok(fmanifest, "\r\n"); int fc = 0; while (tok) { files[fc++] = strdup(tok); if (fc >= 16) { break; } tok = strtok(NULL, "\r\n"); } free(fmanifest); manifest = plist_new_dict(); for (x = 0; x < fc; x++) { inf = plist_new_dict(); strcpy(tmpstr, p_all_flash); strcat(tmpstr, "/"); strcat(tmpstr, files[x]); plist_dict_insert_item(inf, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); const char* compname = get_component_name(files[x]); if (compname) { plist_dict_insert_item(manifest, compname, comp); if (!strncmp(files[x], "DeviceTree", 10)) { plist_dict_insert_item(manifest, "RestoreDeviceTree", plist_copy(comp)); } } else { error("WARNING: unhandled component %s\n", files[x]); plist_free(comp); } free(files[x]); files[x] = NULL; } // add iBSS sprintf(tmpstr, "Firmware/dfu/iBSS.%s.%s.dfu", lcmodel, "RELEASE"); inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "iBSS", comp); // add iBEC sprintf(tmpstr, "Firmware/dfu/iBEC.%s.%s.dfu", lcmodel, "RELEASE"); inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_new_string(tmpstr)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "iBEC", comp); // add kernel cache plist_t kdict = NULL; node = plist_dict_get_item(buildmanifest, "KernelCachesByTarget"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { char tt[4]; strncpy(tt, lcmodel, 3); tt[3] = 0; kdict = plist_dict_get_item(node, tt); } else { // Populated in older iOS IPSWs kdict = plist_dict_get_item(buildmanifest, "RestoreKernelCaches"); } if (kdict && (plist_get_node_type(kdict) == PLIST_DICT)) { plist_t kc = plist_dict_get_item(kdict, "Release"); if (kc && (plist_get_node_type(kc) == PLIST_STRING)) { inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_copy(kc)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "KernelCache", comp); plist_dict_insert_item(manifest, "RestoreKernelCache", plist_copy(comp)); } } // add ramdisk node = plist_dict_get_item(buildmanifest, "RestoreRamDisks"); if (node && (plist_get_node_type(node) == PLIST_DICT)) { plist_t rd = plist_dict_get_item(node, (client->flags & FLAG_ERASE) ? "User" : "Update"); // if no "Update" ram disk entry is found try "User" ram disk instead if (!rd && !(client->flags & FLAG_ERASE)) { rd = plist_dict_get_item(node, "User"); // also, set the ERASE flag since we actually change the restore variant client->flags |= FLAG_ERASE; } if (rd && (plist_get_node_type(rd) == PLIST_STRING)) { inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_copy(rd)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "RestoreRamDisk", comp); } } // add OS filesystem node = plist_dict_get_item(buildmanifest, "SystemRestoreImages"); if (!node) { error("ERROR: missing SystemRestoreImages in Restore.plist\n"); } plist_t os = plist_dict_get_item(node, "User"); if (!os) { error("ERROR: missing filesystem in Restore.plist\n"); } else { inf = plist_new_dict(); plist_dict_insert_item(inf, "Path", plist_copy(os)); comp = plist_new_dict(); plist_dict_insert_item(comp, "Info", inf); plist_dict_insert_item(manifest, "OS", comp); } // add info inf = plist_new_dict(); plist_dict_insert_item(inf, "RestoreBehavior", plist_new_string((client->flags & FLAG_ERASE) ? "Erase" : "Update")); plist_dict_insert_item(inf, "Variant", plist_new_string((client->flags & FLAG_ERASE) ? "Customer Erase Install (IPSW)" : "Customer Upgrade Install (IPSW)")); plist_dict_insert_item(build_identity, "Info", inf); // finally add manifest plist_dict_insert_item(build_identity, "Manifest", manifest); } } else if (client->flags & FLAG_ERASE) { build_identity = build_manifest_get_build_identity(buildmanifest, 0); if (build_identity == NULL) { error("ERROR: Unable to find any build identities\n"); plist_free(buildmanifest); return -1; } } else { // loop through all build identities in the build manifest // and list the valid ones int i = 0; int valid_builds = 0; int build_count = build_manifest_get_identity_count(buildmanifest); for (i = 0; i < build_count; i++) { build_identity = build_manifest_get_build_identity(buildmanifest, i); valid_builds++; } } /* print information about current build identity */ build_identity_print_information(build_identity); idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.0); /* retrieve shsh blobs if required */ if (tss_enabled) { debug("Getting device's ECID for TSS request\n"); /* fetch the device's ECID for the TSS request */ if (get_ecid(client, &client->ecid) < 0) { error("ERROR: Unable to find device ECID\n"); return -1; } info("Found ECID " FMT_qu "\n", (long long unsigned int)client->ecid); if (client->build_major > 8) { unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (get_nonce(client, &nonce, &nonce_size) < 0) { /* the first nonce request with older firmware releases can fail and it's OK */ info("NOTE: Unable to get nonce from device\n"); } if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) { nonce_changed = 1; if (client->nonce) { free(client->nonce); } client->nonce = nonce; client->nonce_size = nonce_size; } else { free(nonce); } } if (get_shsh_blobs(client, client->ecid, client->nonce, client->nonce_size, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); return -1; } } if (client->flags & FLAG_SHSHONLY) { if (!tss_enabled) { info("This device does not require a TSS record"); return 0; } if (!client->tss) { error("ERROR: could not fetch TSS record"); plist_free(buildmanifest); return -1; } else { char *bin = NULL; uint32_t blen = 0; plist_to_bin(client->tss, &bin, &blen); if (bin) { char zfn[1024]; if (client->cache_dir) { strcpy(zfn, client->cache_dir); strcat(zfn, "/shsh"); } else { strcpy(zfn, "shsh"); } mkdir_with_parents(zfn, 0755); sprintf(zfn+strlen(zfn), "/" FMT_qu "-%s-%s.shsh", (long long int)client->ecid, client->device->product_type, client->version); struct stat fst; if (stat(zfn, &fst) != 0) { gzFile zf = gzopen(zfn, "wb"); gzwrite(zf, bin, blen); gzclose(zf); info("SHSH saved to '%s'\n", zfn); } else { info("SHSH '%s' already present.\n", zfn); } free(bin); } else { error("ERROR: could not get TSS record data\n"); } plist_free(client->tss); plist_free(buildmanifest); return 0; } } /* verify if we have tss records if required */ if ((tss_enabled) && (client->tss == NULL)) { error("ERROR: Unable to proceed without a TSS record.\n"); plist_free(buildmanifest); return -1; } if ((tss_enabled) && client->tss) { /* fix empty dicts */ fixup_tss(client->tss); } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.1); // if the device is in normal mode, place device into recovery mode if (client->mode->index == MODE_NORMAL) { info("Entering recovery mode...\n"); if (normal_enter_recovery(client) < 0) { error("ERROR: Unable to place device into recovery mode from %s mode\n", client->mode->string); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -5; } } // Get filesystem name from build identity char* fsname = NULL; if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) { error("ERROR: Unable get path for filesystem component\n"); return -1; } // check if we already have an extracted filesystem int delete_fs = 0; char* filesystem = NULL; struct stat st; memset(&st, '\0', sizeof(struct stat)); char tmpf[1024]; if (client->cache_dir) { if (stat(client->cache_dir, &st) < 0) { mkdir_with_parents(client->cache_dir, 0755); } strcpy(tmpf, client->cache_dir); strcat(tmpf, "/"); char *ipswtmp = strdup(client->ipsw); strcat(tmpf, basename(ipswtmp)); free(ipswtmp); } else { strcpy(tmpf, client->ipsw); } char* p = strrchr((const char*)tmpf, '.'); if (p) { *p = '\0'; } if (stat(tmpf, &st) < 0) { __mkdir(tmpf, 0755); } strcat(tmpf, "/"); strcat(tmpf, fsname); memset(&st, '\0', sizeof(struct stat)); if (stat(tmpf, &st) == 0) { off_t fssize = 0; ipsw_get_file_size(client->ipsw, fsname, &fssize); if ((fssize > 0) && (st.st_size == fssize)) { info("Using cached filesystem from '%s'\n", tmpf); filesystem = strdup(tmpf); } } if (!filesystem) { char extfn[1024]; strcpy(extfn, tmpf); strcat(extfn, ".extract"); char lockfn[1024]; strcpy(lockfn, tmpf); strcat(lockfn, ".lock"); lock_info_t li; lock_file(lockfn, &li); FILE* extf = NULL; if (access(extfn, F_OK) != 0) { extf = fopen(extfn, "w"); } unlock_file(&li); if (!extf) { // use temp filename filesystem = tempnam(NULL, "ipsw_"); if (!filesystem) { error("WARNING: Could not get temporary filename, using '%s' in current directory\n", fsname); filesystem = strdup(fsname); } delete_fs = 1; } else { // use <fsname>.extract as filename filesystem = strdup(extfn); fclose(extf); } remove(lockfn); // Extract filesystem from IPSW info("Extracting filesystem from IPSW\n"); if (ipsw_extract_to_file(client->ipsw, fsname, filesystem) < 0) { error("ERROR: Unable to extract filesystem from IPSW\n"); if (client->tss) plist_free(client->tss); plist_free(buildmanifest); return -1; } if (strstr(filesystem, ".extract")) { // rename <fsname>.extract to <fsname> rename(filesystem, tmpf); free(filesystem); filesystem = strdup(tmpf); } } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.3); // if the device is in DFU mode, place device into recovery mode if (client->mode->index == MODE_DFU) { recovery_client_free(client); if ((client->flags & FLAG_CUSTOM) && limera1n_is_supported(client->device)) { info("connecting to DFU\n"); if (dfu_client_new(client) < 0) { if (delete_fs && filesystem) unlink(filesystem); return -1; } info("exploiting with limera1n\n"); // TODO: check for non-limera1n device and fail if (limera1n_exploit(client->device, &client->dfu->client) != 0) { error("ERROR: limera1n exploit failed\n"); dfu_client_free(client); if (delete_fs && filesystem) unlink(filesystem); return -1; } dfu_client_free(client); info("exploited\n"); } if (dfu_enter_recovery(client, build_identity) < 0) { error("ERROR: Unable to place device into recovery mode from %s mode\n", client->mode->string); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); if (delete_fs && filesystem) unlink(filesystem); return -2; } } if (client->mode->index == MODE_DFU) { client->mode = &idevicerestore_modes[MODE_RECOVERY]; } else { if ((client->build_major > 8) && !(client->flags & FLAG_CUSTOM)) { /* send ApTicket */ if (recovery_send_ticket(client) < 0) { error("WARNING: Unable to send APTicket\n"); } } /* now we load the iBEC */ if (recovery_send_ibec(client, build_identity) < 0) { error("ERROR: Unable to send iBEC\n"); if (delete_fs && filesystem) unlink(filesystem); return -2; } recovery_client_free(client); /* this must be long enough to allow the device to run the iBEC */ /* FIXME: Probably better to detect if the device is back then */ sleep(7); } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.5); if (client->build_major > 8) { // we need another tss request with nonce. unsigned char* nonce = NULL; int nonce_size = 0; int nonce_changed = 0; if (get_nonce(client, &nonce, &nonce_size) < 0) { error("ERROR: Unable to get nonce from device!\n"); recovery_send_reset(client); if (delete_fs && filesystem) unlink(filesystem); return -2; } if (!client->nonce || (nonce_size != client->nonce_size) || (memcmp(nonce, client->nonce, nonce_size) != 0)) { nonce_changed = 1; if (client->nonce) { free(client->nonce); } client->nonce = nonce; client->nonce_size = nonce_size; } else { free(nonce); } if (nonce_changed && !(client->flags & FLAG_CUSTOM)) { // Welcome iOS5. We have to re-request the TSS with our nonce. plist_free(client->tss); if (get_shsh_blobs(client, client->ecid, client->nonce, client->nonce_size, build_identity, &client->tss) < 0) { error("ERROR: Unable to get SHSH blobs for this device\n"); if (delete_fs && filesystem) unlink(filesystem); return -1; } if (!client->tss) { error("ERROR: can't continue without TSS\n"); if (delete_fs && filesystem) unlink(filesystem); return -1; } fixup_tss(client->tss); } } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.7); // now finally do the magic to put the device into restore mode if (client->mode->index == MODE_RECOVERY) { if (client->srnm == NULL) { error("ERROR: could not retrieve device serial number. Can't continue.\n"); if (delete_fs && filesystem) unlink(filesystem); return -1; } if (recovery_enter_restore(client, build_identity) < 0) { error("ERROR: Unable to place device into restore mode\n"); plist_free(buildmanifest); if (client->tss) plist_free(client->tss); if (delete_fs && filesystem) unlink(filesystem); return -2; } recovery_client_free(client); } idevicerestore_progress(client, RESTORE_STEP_PREPARE, 0.9); // device is finally in restore mode, let's do this if (client->mode->index == MODE_RESTORE) { info("About to restore device... \n"); result = restore_device(client, build_identity, filesystem); if (result < 0) { error("ERROR: Unable to restore device\n"); if (delete_fs && filesystem) unlink(filesystem); return result; } } info("Cleaning up...\n"); if (delete_fs && filesystem) unlink(filesystem); /* special handling of AppleTVs */ if (strncmp(client->device->product_type, "AppleTV", 7) == 0) { if (recovery_client_new(client) == 0) { if (recovery_set_autoboot(client, 1) == 0) { recovery_send_reset(client); } else { error("Setting auto-boot failed?!\n"); } } else { error("Could not connect to device in recovery mode.\n"); } } info("DONE\n"); if (result == 0) { idevicerestore_progress(client, RESTORE_NUM_STEPS-1, 1.0); } return result; }
/* Send the page to the printer. */ static int pr201_print_page(gx_device_printer *pdev, FILE *prn_stream) { int line_size; int height; int bits_per_column; int bytes_per_column; int chunk_size; byte *in, *out; int lnum, skip; int head_pins, lr_pitch, x_dpi; switch (check_mode(pdev->dname)){ case PR201: head_pins=24; lr_pitch=18; x_dpi=160; break; case PR1000: head_pins=40; lr_pitch=20; x_dpi=240; break; case PR150: head_pins=48; lr_pitch=18; x_dpi=320; break; case PR1K4: head_pins=60; lr_pitch=18; x_dpi=400; break; } line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev); height = pdev->height; bits_per_column = head_pins; bytes_per_column = bits_per_column / 8; chunk_size = bits_per_column * line_size; in = (byte *) gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), bits_per_column, line_size, "pr201_print_page(in)"); out = (byte *) gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), bits_per_column, line_size, "pr201_print_page(out)"); if(in == 0 || out == 0) return -1; /* Initialize printer */ fputs("\033cl", pdev->file); /* Software Reset */ fputs("\033P", pdev->file); /* Proportional Mode */ if (check_mode(pdev->dname)==PR150){ fprintf(pdev->file, "\034d%d.", x_dpi); /* 320 dpi mode. */ } fprintf(pdev->file, "\033T%d" , lr_pitch); /* 18/120 inch per line */ /* Send Data to printer */ lnum = 0; skip = 0; while(lnum < height) { byte *inp, *outp, *out_beg, *out_end; int x, y, num_lines, size, mod; /* Copy scan lines */ if(gdev_prn_copy_scan_lines(pdev, lnum, in, chunk_size) < 0) break; /* The number of lines to process */ if((num_lines = height - lnum) > bits_per_column) num_lines = bits_per_column; /* Test for all zero */ size = line_size * num_lines; if(in[0] == 0 && !memcmp((char *)in, (char *)in + 1, size - 1)) { lnum += bits_per_column; skip ++; continue; } /* Fill zero */ if(num_lines < bits_per_column) { size = line_size * (bits_per_column - num_lines); memset(in + line_size * num_lines, 0, size); } lnum += bits_per_column; /* Vertical tab to the appropriate position. */ while(skip > 72) { fprintf(pdev->file, "\037%c", 16 + 72); skip -= 72; } if(skip > 0) { fprintf(pdev->file, "\037%c", 16 + skip); } /* Transpose in blocks of 8 scan lines. */ for(y = 0; y < bytes_per_column; y ++) { inp = in + line_size * 8 * y; outp = out + y; for(x = 0; x < line_size; x ++) { pr201_transpose_8x8(inp, line_size, outp, bytes_per_column); inp ++; outp += bits_per_column; } } /* Remove trailing 0s. */ out_end = out + chunk_size - 1; while(out_end >= out) { if(*out_end) break; out_end --; } size = (out_end - out) + 1; if((mod = size % bytes_per_column) != 0) out_end += bytes_per_column - mod; /* Remove leading 0s. */ out_beg = out; while(out_beg <= out_end) { if(*out_beg) break; out_beg ++; } out_beg -= (out_beg - out) % bytes_per_column; /* Dot addressing */ fprintf(pdev->file, "\033F%04d", (out_beg - out) / bytes_per_column); /* Dot graphics */ size = out_end - out_beg + 1; if (check_mode(pdev->dname)==PR201){ fprintf(pdev->file,"\033J%04d", size / bytes_per_column); }else{ fprintf(pdev->file,"\034bP,48,%04d.", size / bytes_per_column); } fwrite(out_beg, size, 1, pdev->file); /* Carriage Return */ fputc('\r', pdev->file); skip = 1; } /* Form Feed */ fputc('\f',pdev->file); fflush(pdev->file); gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)out, bits_per_column, line_size, "pr201_print_page(out)"); gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)in, bits_per_column, line_size, "pr201_print_page(in)"); return 0; }