int config_find(struct volume *v, struct file_header *conf, struct file_header *sentinel) { uint32_t seq; int i, next = snapshot_next_free(v, &seq); conf->magic = sentinel->magic = 0; if (!volume_read(v, conf, next, sizeof(*conf))) be32_to_hdr(conf); for (i = (v->size / v->block_size) - 1; i > 0; i--) { if (volume_read(v, sentinel, i * v->block_size, sizeof(*sentinel))) { ULOG_ERR("failed to read header\n"); return -1; } be32_to_hdr(sentinel); if (sentinel->magic == OWRT && sentinel->type == CONF && !valid_file_size(sentinel->length)) { if (next == i) return -1; return i; } } return -1; }
int snapshot_read_file(struct volume *v, int block, char *file, uint32_t type) { struct file_header hdr; char buffer[256]; int out, offset = 0; if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) { ULOG_ERR("failed to read header\n"); return -1; } be32_to_hdr(&hdr); if (hdr.magic != OWRT) return -1; if (hdr.type != type) return -1; if (valid_file_size(hdr.length)) return -1; out = open(file, O_WRONLY | O_CREAT, 0700); if (!out) { ULOG_ERR("failed to open %s\n", file); return -1; } offset = block * v->block_size + sizeof(hdr); while (hdr.length > 0) { int len = sizeof(buffer); if (hdr.length < len) len = hdr.length; if (volume_read(v, buffer, offset, len)) return -1; if (write(out, buffer, len) != len) return -1; offset += len; hdr.length -= len; } close(out); if (verify_file_hash(file, hdr.md5)) { ULOG_ERR("md5 verification failed\n"); unlink(file); return 0; } block += pad_file_size(v, hdr.length) / v->block_size; return block; }
int snapshot_next_free(struct volume *v, uint32_t *seq) { struct file_header hdr = { 0 }; int block = 0; *seq = rand(); do { if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) { ULOG_ERR("scanning for next free block failed\n"); return 0; } be32_to_hdr(&hdr); if (hdr.magic != OWRT) break; if (hdr.type == DATA && !valid_file_size(hdr.length)) { if (*seq + 1 != hdr.seq && block) return block; *seq = hdr.seq; block += pad_file_size(v, hdr.length) / v->block_size; } } while (hdr.type == DATA); return block; }
static void preferences_set_page(void) { int i, j; int lim = volume_get_max(); volume_read(&i, &j); widgets_preferences[0].d.thumbbar.value = i * VOLUME_SCALE / lim; widgets_preferences[1].d.thumbbar.value = j * VOLUME_SCALE / lim; for (i = j = 0; interpolation_modes[i]; i++) { if (i == audio_settings.interpolation_mode) { widgets_preferences[i + 2].d.togglebutton.state=1; j = 1; } else { widgets_preferences[i + 2].d.togglebutton.state=0; } } if (!j) { audio_settings.interpolation_mode = 0; widgets_preferences[2].d.togglebutton.state=1; } for (j = 0; j < 4; j++) { widgets_preferences[i+2+(j*2)].d.thumbbar.value = audio_settings.eq_freq[j]; widgets_preferences[i+3+(j*2)].d.thumbbar.value = audio_settings.eq_gain[j]; } widgets_preferences[i+10].d.togglebutton.state = audio_settings.no_ramping?0:1; widgets_preferences[i+11].d.togglebutton.state = audio_settings.no_ramping?1:0; }
/* Find out wether the volume is wrapped and unwrap it eventually */ static int volume_read_wrapper(volume * vol, hfsp_vh* vh) { UInt16 signature; char buf[vol->blksize]; char *p = buf; if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here return -1; signature = bswabU16_inc(p); if( signature == HFS_VOLHEAD_SIG) { /* Wrapper */ UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */ UInt32 sect_per_block; /* how may block build an hfs sector */ UInt16 drAlBlSt; /* first allocation block in volume */ UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */ p += 0x12; /* skip unneded HFS vol fields */ drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */ p += 0x4; /* skip unneded HFS vol fields */ drAlBlSt = bswabU16_inc(p); /* offset 0x1C */ p += 0x5E; /* skip unneded HFS vol fields */ signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */ if( signature != HFSP_VOLHEAD_SIG) HFSP_ERROR(-1, "This looks like a normal HFS volume"); embeds = bswabU16_inc(p); embedl = bswabU16_inc(p); sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ); // end is absolute (not relative to HFS+ start) vol->maxblocks = embedl * sect_per_block; vol->startblock = drAlBlSt + embeds * sect_per_block; /* Now we can try to read the embedded HFS+ volume header */ return volume_read(vol,vh,2); } else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */ p = buf; // Restore to begin of block return volume_readbuf(vh, p); } else HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found"); fail: return -1; }
/* Open the device, read and verify the volume header (and its backup) */ int volume_open( volume* vol, int os_fd ) { hfsp_vh backup; /* backup volume found at second to last block */ long sect_per_block; int shift; vol->blksize_bits = HFSP_BLOCKSZ_BITS; vol->blksize = HFSP_BLOCKSZ; vol->startblock = 0; vol->maxblocks = 3; /* this should be enough until we find the volume descriptor */ vol->extents = NULL; /* Thanks to Jeremias Sauceda */ btree_reset(&vol->catalog); vol->os_fd = os_fd; // vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS); // This wont work for /dev/... but we do not really need it if( volume_read_wrapper(vol, &vol->vol)) return -1; if( volume_read(vol, &backup, vol->maxblocks - 2)) return -1; /* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header and adjust depend values accordingly, after that a block always means a HFS+ allocation size */ /* Usually 4096 / 512 == 8 */ sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ; shift = 0; if( sect_per_block > 1) { shift = 1; while( sect_per_block > 2) { sect_per_block >>=1; shift++; } /* shift = 3 */ }