New API object iso_interval_reader. Enabling flag bits for older API calls
iso_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp(), and iso_write_opts_set_partition_img().
This commit is contained in:
parent
a0719328ea
commit
d4b8cbe474
@ -1483,11 +1483,519 @@ static int finish_libjte(Ecma119Image *target)
|
||||
}
|
||||
|
||||
|
||||
/* >>> need opportunity to just mark a partition in the older sessions
|
||||
*/
|
||||
|
||||
|
||||
struct iso_interval_zeroizer {
|
||||
int z_type; /* 0= $zero_start"-"$zero_end ,
|
||||
1= "zero_mbrpt" , 2= "zero_gpt" , 3= "zero_apm"
|
||||
*/
|
||||
off_t zero_start;
|
||||
off_t zero_end;
|
||||
};
|
||||
|
||||
struct iso_interval_reader {
|
||||
|
||||
/* Setup */
|
||||
|
||||
IsoImage *image;
|
||||
|
||||
char *path;
|
||||
|
||||
int flags; /* bit0= imported_iso, else local_fs
|
||||
*/
|
||||
|
||||
off_t start_byte;
|
||||
off_t end_byte;
|
||||
|
||||
struct iso_interval_zeroizer *zeroizers;
|
||||
int num_zeroizers;
|
||||
|
||||
char *source_pt; /* This is a parasite pointer of path. Do not free */
|
||||
|
||||
/* State information */
|
||||
|
||||
int initialized;
|
||||
int is_block_aligned;
|
||||
off_t cur_block;
|
||||
int fd;
|
||||
uint8_t read_buf[BLOCK_SIZE];
|
||||
uint8_t *pending_read_pt;
|
||||
int pending_read_bytes;
|
||||
off_t read_count;
|
||||
int eof;
|
||||
|
||||
int src_is_open;
|
||||
|
||||
uint32_t apm_block_size;
|
||||
|
||||
};
|
||||
|
||||
static
|
||||
int iso_ivr_next_comp(char *read_pt, char **next_pt, int flag)
|
||||
{
|
||||
*next_pt = NULL;
|
||||
if (read_pt == NULL)
|
||||
return 0;
|
||||
*next_pt = strchr(read_pt, ':');
|
||||
if (*next_pt != NULL)
|
||||
(*next_pt)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* @param flag bit1= end number requested, forward to iso_scanf_io_size()
|
||||
*/
|
||||
static
|
||||
int iso_ivr_read_number(char *start_pt, char *end_pt, off_t *result, int flag)
|
||||
{
|
||||
char txt[20];
|
||||
off_t num;
|
||||
|
||||
if (end_pt - start_pt <= 0 || end_pt - start_pt > 16) {
|
||||
iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0,
|
||||
"Number text too short or too long in interval reader description string");
|
||||
return ISO_MALFORMED_READ_INTVL;
|
||||
}
|
||||
if (end_pt - start_pt > 0)
|
||||
strncpy(txt, start_pt, end_pt - start_pt);
|
||||
txt[end_pt - start_pt] = 0;
|
||||
|
||||
num = iso_scanf_io_size(start_pt, 1 | (flag & 2));
|
||||
if (num < 0.0 || num > 0xffffffffffff) {
|
||||
iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0,
|
||||
"Negative or overly large number in interval reader description string");
|
||||
return ISO_MALFORMED_READ_INTVL;
|
||||
}
|
||||
*result = num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_ivr_parse_interval(char *start_pt, char *end_pt, off_t *start_byte,
|
||||
off_t *end_byte, int flag)
|
||||
{
|
||||
int ret;
|
||||
char *m_pt;
|
||||
|
||||
m_pt = strchr(start_pt, '-');
|
||||
if (m_pt == NULL) {
|
||||
iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0,
|
||||
"Malformed byte interval in interval reader description string");
|
||||
return ISO_MALFORMED_READ_INTVL;
|
||||
}
|
||||
ret = iso_ivr_read_number(start_pt, m_pt, start_byte, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_ivr_read_number(m_pt + 1, end_pt - 1, end_byte, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_ivr_parse_zeroizers(struct iso_interval_reader *ivr,
|
||||
char *pathpt, char *end_pt, int flag)
|
||||
{
|
||||
int ret, num_zs = 1, idx, i;
|
||||
char *rpt, *cpt;
|
||||
|
||||
ivr->num_zeroizers = 0;
|
||||
if (pathpt[0] == 0 || pathpt == end_pt)
|
||||
return ISO_SUCCESS;
|
||||
for(cpt = pathpt - 1; cpt != NULL && cpt < end_pt; num_zs++)
|
||||
cpt = strchr(cpt + 1, ',');
|
||||
LIBISO_ALLOC_MEM(ivr->zeroizers, struct iso_interval_zeroizer, num_zs);
|
||||
for (i = 0; i < num_zs; i++)
|
||||
ivr->zeroizers[i].zero_end = -1;
|
||||
idx = 0;
|
||||
for (rpt = pathpt; rpt != NULL && rpt < end_pt; idx++) {
|
||||
cpt = strchr(rpt, ',');
|
||||
if (cpt == NULL || cpt > end_pt)
|
||||
cpt = end_pt;
|
||||
|
||||
if (cpt == rpt) {
|
||||
continue;
|
||||
} else if (strncmp(rpt, "zero_mbrpt", cpt - rpt) == 0) {
|
||||
ivr->zeroizers[idx].z_type = 1;
|
||||
} else if (strncmp(rpt, "zero_gpt", cpt - rpt) == 0) {
|
||||
ivr->zeroizers[idx].z_type = 2;
|
||||
} else if (strncmp(rpt, "zero_apm", cpt - rpt) == 0) {
|
||||
ivr->zeroizers[idx].z_type = 3;
|
||||
} else {
|
||||
ivr->zeroizers[idx].z_type = 0;
|
||||
ret = iso_ivr_parse_interval(rpt, cpt,
|
||||
&(ivr->zeroizers[idx].zero_start),
|
||||
&(ivr->zeroizers[idx].zero_end), 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
rpt = cpt + 1;
|
||||
ivr->num_zeroizers++;
|
||||
}
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_ivr_parse(struct iso_interval_reader *ivr, char *path, int flag)
|
||||
{
|
||||
int ret;
|
||||
char *flags_pt, *interval_pt, *zeroize_pt;
|
||||
|
||||
flags_pt = path;
|
||||
iso_ivr_next_comp(flags_pt, &interval_pt, 0);
|
||||
iso_ivr_next_comp(interval_pt, &zeroize_pt, 0);
|
||||
iso_ivr_next_comp(zeroize_pt, &(ivr->source_pt), 0);
|
||||
if (ivr->source_pt == NULL) {
|
||||
iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0,
|
||||
"Not enough components in interval reader description string");
|
||||
return ISO_MALFORMED_READ_INTVL;
|
||||
}
|
||||
|
||||
ivr->flags = 0;
|
||||
if (strncmp(flags_pt, "imported_iso", 12) == 0) {
|
||||
ivr->flags |= 1;
|
||||
} else if (strncmp(flags_pt, "local_fs", 8) == 0) {
|
||||
;
|
||||
} else {
|
||||
iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0,
|
||||
"Unknown flag name in first component of interval reader description string");
|
||||
return ISO_MALFORMED_READ_INTVL;
|
||||
}
|
||||
ret = iso_ivr_parse_interval(interval_pt, zeroize_pt, &(ivr->start_byte),
|
||||
&(ivr->end_byte), 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_ivr_parse_zeroizers(ivr, zeroize_pt, ivr->source_pt - 1, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_interval_reader_destroy(struct iso_interval_reader **ivr, int flag)
|
||||
{
|
||||
struct iso_interval_reader *o;
|
||||
|
||||
if (*ivr == NULL)
|
||||
return 0;
|
||||
o = *ivr;
|
||||
|
||||
LIBISO_FREE_MEM(o->path);
|
||||
LIBISO_FREE_MEM(o->zeroizers);
|
||||
|
||||
if (o->fd != -1)
|
||||
close(o->fd);
|
||||
if (o->src_is_open)
|
||||
(*o->image->import_src->close)(o->image->import_src);
|
||||
|
||||
LIBISO_FREE_MEM(*ivr);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/* @param flag bit0= tolerate lack of import_src
|
||||
*/
|
||||
int iso_interval_reader_new(IsoImage *img, char *path,
|
||||
struct iso_interval_reader **ivr,
|
||||
off_t *byte_count, int flag)
|
||||
{
|
||||
int ret, no_img = 0;
|
||||
struct iso_interval_reader *o = NULL;
|
||||
|
||||
*ivr = NULL;
|
||||
*byte_count = 0;
|
||||
LIBISO_ALLOC_MEM(o, struct iso_interval_reader, 1);
|
||||
o->image = img;
|
||||
o->path = NULL;
|
||||
o->zeroizers = NULL;
|
||||
o->num_zeroizers = 0;
|
||||
o->source_pt = NULL;
|
||||
o->initialized = 0;
|
||||
o->is_block_aligned = 0;
|
||||
o->fd = -1;
|
||||
o->pending_read_pt = NULL;
|
||||
o->pending_read_bytes = 0;
|
||||
o->eof = 0;
|
||||
o->read_count = 0;
|
||||
o->src_is_open = 0;
|
||||
|
||||
o->apm_block_size = 0;
|
||||
|
||||
LIBISO_ALLOC_MEM(o->path, char, strlen(path) + 1);
|
||||
strcpy(o->path, path);
|
||||
|
||||
ret = iso_ivr_parse(o, path, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
if (o->image == NULL)
|
||||
no_img = 1;
|
||||
else if (o->image->import_src == NULL)
|
||||
no_img = 1;
|
||||
if ((o->flags & 1) && no_img) {
|
||||
iso_msg_submit(-1, ISO_NO_KEPT_DATA_SRC, 0,
|
||||
"Interval reader lacks of data source object of imported ISO");
|
||||
if (!(flag & 1)) {
|
||||
ret = ISO_BAD_PARTITION_FILE;
|
||||
goto ex;
|
||||
}
|
||||
o->eof = 1;
|
||||
}
|
||||
*byte_count = o->end_byte - o->start_byte + 1;
|
||||
*ivr = o;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ret < 0)
|
||||
iso_interval_reader_destroy(&o, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_ivr_zeroize(struct iso_interval_reader *ivr, uint8_t *buf,
|
||||
int buf_fill, int flag)
|
||||
{
|
||||
int i;
|
||||
off_t low, high, part_start, entry_count, apm_offset = -1, map_entries;
|
||||
uint8_t *apm_buf;
|
||||
struct iso_interval_zeroizer *zr;
|
||||
|
||||
for (i = 0; i < ivr->num_zeroizers; i++) {
|
||||
zr = ivr->zeroizers + i;
|
||||
if (zr->z_type == 1) { /* zero_mbrpt */
|
||||
if (ivr->read_count > 0 || buf_fill < 512)
|
||||
continue;
|
||||
if (buf[510] != 0x55 || buf[511] != 0xaa)
|
||||
continue;
|
||||
memset(buf + 446, 0, 64);
|
||||
|
||||
} else if (zr->z_type == 2) { /* zero_gpt */
|
||||
if (zr->zero_start <= zr->zero_end)
|
||||
goto process_interval;
|
||||
|
||||
if (ivr->read_count > 0 || buf_fill < 512 + 92)
|
||||
continue;
|
||||
if (strncmp((char *) buf + 512, "EFI PART", 8) != 0 ||
|
||||
buf[520] != 0 || buf[521] != 0 || buf[522] != 1 ||
|
||||
buf[523] != 0)
|
||||
continue;
|
||||
/* head_size , curr_lba , entry_size */
|
||||
if (iso_read_lsb(buf + 524, 4) != 92 ||
|
||||
iso_read_lsb(buf + 536, 4) != 1 ||
|
||||
iso_read_lsb(buf + 596, 4) != 128)
|
||||
continue;
|
||||
part_start = iso_read_lsb(buf + 584, 4);
|
||||
entry_count = iso_read_lsb(buf + 592, 4);
|
||||
if (part_start < 2 || part_start + (entry_count + 3) / 4 > 64)
|
||||
continue;
|
||||
zr->zero_start = part_start * 512;
|
||||
zr->zero_end = (part_start + (entry_count + 3) / 4) * 512 - 1;
|
||||
memset(buf + 512, 0, 92);
|
||||
|
||||
} else if (zr->z_type == 3) { /* zero_apm */
|
||||
if (zr->zero_start <= zr->zero_end)
|
||||
goto process_interval;
|
||||
|
||||
if (ivr->read_count == 0) {
|
||||
if (buf_fill < 512)
|
||||
continue;
|
||||
if (buf[0] != 'E' || buf[1] != 'R')
|
||||
continue;
|
||||
ivr->apm_block_size = iso_read_msb(buf + 2, 2);
|
||||
if ((ivr->apm_block_size != 512 &&
|
||||
ivr->apm_block_size != 1024 &&
|
||||
ivr->apm_block_size != 2048) ||
|
||||
((uint32_t) buf_fill) < ivr->apm_block_size) {
|
||||
ivr->apm_block_size = 0;
|
||||
continue;
|
||||
}
|
||||
if (ivr->read_count + buf_fill >= 2 * ivr->apm_block_size)
|
||||
apm_offset = ivr->apm_block_size;
|
||||
} else if (ivr->read_count == 2048 &&
|
||||
ivr->apm_block_size == 2048 && buf_fill == 2048) {
|
||||
apm_offset = 0;
|
||||
}
|
||||
if (apm_offset < 0)
|
||||
continue;
|
||||
|
||||
/* Check for first APM entry */
|
||||
apm_buf = buf + apm_offset;
|
||||
if(apm_buf[0] != 'P' || apm_buf[1] != 'M')
|
||||
continue;
|
||||
if (iso_read_msb(apm_buf + 8, 4) != 1)
|
||||
continue;
|
||||
map_entries = iso_read_msb(apm_buf + 4, 4);
|
||||
if ((1 + map_entries) * ivr->apm_block_size > 16 * 2048)
|
||||
continue;
|
||||
zr->zero_start = ivr->apm_block_size;
|
||||
zr->zero_end = (1 + map_entries) * ivr->apm_block_size;
|
||||
}
|
||||
process_interval:;
|
||||
/* If an interval is defined by now: zeroize its intersection with buf
|
||||
*/
|
||||
if (zr->zero_start <= zr->zero_end) {
|
||||
low = ivr->read_count >= zr->zero_start ?
|
||||
ivr->read_count : zr->zero_start;
|
||||
high = ivr->read_count + buf_fill - 1 <= zr->zero_end ?
|
||||
ivr->read_count + buf_fill - 1 : zr->zero_end;
|
||||
if (low <= high)
|
||||
memset(buf + low - ivr->read_count, 0, high - low + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_interval_reader_read(struct iso_interval_reader *ivr, uint8_t *buf,
|
||||
int *buf_fill, int flag)
|
||||
{
|
||||
int ret, read_done, to_copy, initializing = 0;
|
||||
IsoDataSource *src;
|
||||
uint8_t *read_buf;
|
||||
off_t to_read;
|
||||
|
||||
*buf_fill = 0;
|
||||
src = ivr->image->import_src;
|
||||
|
||||
if (ivr->eof) {
|
||||
eof:;
|
||||
memset(buf, 0, BLOCK_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ivr->initialized) {
|
||||
ivr->cur_block++;
|
||||
} else {
|
||||
initializing = 1;
|
||||
ivr->cur_block = ivr->start_byte / BLOCK_SIZE;
|
||||
ivr->is_block_aligned = !(ivr->start_byte % BLOCK_SIZE);
|
||||
if (ivr->flags & 1) {
|
||||
if (src == NULL)
|
||||
goto eof;
|
||||
ret = (*src->open)(src);
|
||||
if (ret < 0) {
|
||||
ivr->eof = 1;
|
||||
return ret;
|
||||
}
|
||||
ivr->src_is_open = 1;
|
||||
} else {
|
||||
ivr->fd = open(ivr->source_pt, O_RDONLY);
|
||||
if (ivr->fd == -1) {
|
||||
iso_msg_submit(-1, ISO_BAD_PARTITION_FILE, 0,
|
||||
"Cannot open local file for interval reading");
|
||||
ivr->eof = 1;
|
||||
return ISO_BAD_PARTITION_FILE;
|
||||
}
|
||||
if (ivr->cur_block != 0) {
|
||||
if (lseek(ivr->fd, ivr->cur_block * BLOCK_SIZE, SEEK_SET) ==
|
||||
-1) {
|
||||
iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0,
|
||||
"Cannot address interval start in local file");
|
||||
ivr->eof = 1;
|
||||
goto eof;
|
||||
}
|
||||
}
|
||||
}
|
||||
ivr->initialized = 1;
|
||||
}
|
||||
if (ivr->is_block_aligned) {
|
||||
read_buf = buf;
|
||||
} else {
|
||||
process_pending:;
|
||||
read_buf = ivr->read_buf;
|
||||
/* Copy pending bytes from previous read */
|
||||
if (ivr->pending_read_bytes > 0) {
|
||||
memcpy(buf, ivr->pending_read_pt, ivr->pending_read_bytes);
|
||||
*buf_fill = ivr->pending_read_bytes;
|
||||
ivr->pending_read_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read next block */
|
||||
read_done = 0;
|
||||
if (ivr->cur_block * BLOCK_SIZE <= ivr->end_byte) {
|
||||
if (ivr->flags & 1) {
|
||||
ret = (*src->read_block)(src, (uint32_t) ivr->cur_block, read_buf);
|
||||
if (ret < 0) {
|
||||
if (iso_error_get_severity(ret) > 0x68000000) /* > FAILURE */
|
||||
return ret;
|
||||
iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0,
|
||||
"Premature EOF while interval reading from imported ISO");
|
||||
ivr->eof = 1;
|
||||
}
|
||||
read_done = BLOCK_SIZE;
|
||||
} else {
|
||||
read_done = 0;
|
||||
to_read = ivr->end_byte - ivr->start_byte + 1 - ivr->read_count;
|
||||
if (to_read > BLOCK_SIZE)
|
||||
to_read = BLOCK_SIZE;
|
||||
while (read_done < to_read) {
|
||||
ret = read(ivr->fd, read_buf, to_read - read_done);
|
||||
if (ret == -1) {
|
||||
iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0,
|
||||
"Read error while interval reading from local file");
|
||||
ivr->eof = 1;
|
||||
break;
|
||||
} else if (ret == 0) {
|
||||
iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0,
|
||||
"Premature EOF while interval reading from local file");
|
||||
ivr->eof = 1;
|
||||
break;
|
||||
} else
|
||||
read_done += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ivr->is_block_aligned) {
|
||||
*buf_fill = read_done;
|
||||
} else if (initializing) {
|
||||
ivr->pending_read_pt = ivr->read_buf +
|
||||
(ivr->start_byte - ivr->cur_block * BLOCK_SIZE);
|
||||
ivr->pending_read_bytes = (((off_t) ivr->cur_block) + 1) * BLOCK_SIZE -
|
||||
ivr->start_byte;
|
||||
initializing = 0;
|
||||
goto process_pending;
|
||||
|
||||
} else if (read_done > 0) {
|
||||
/* Copy bytes from new read */
|
||||
to_copy = read_done > BLOCK_SIZE - *buf_fill ?
|
||||
BLOCK_SIZE - *buf_fill : read_done;
|
||||
memcpy(buf + *buf_fill, ivr->read_buf, to_copy);
|
||||
*buf_fill += to_copy;
|
||||
ivr->pending_read_pt = ivr->read_buf + to_copy;
|
||||
ivr->pending_read_bytes = read_done - to_copy;
|
||||
}
|
||||
if (ivr->start_byte + ivr->read_count + *buf_fill - 1 > ivr->end_byte) {
|
||||
*buf_fill = ivr->end_byte - ivr->start_byte + 1 - ivr->read_count;
|
||||
ivr->eof = 1;
|
||||
}
|
||||
|
||||
if (*buf_fill < BLOCK_SIZE)
|
||||
memset(buf + *buf_fill, 0, BLOCK_SIZE - *buf_fill);
|
||||
|
||||
ret = iso_ivr_zeroize(ivr, buf, *buf_fill, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ivr->read_count += *buf_fill;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_write_partition_file(Ecma119Image *target, char *path,
|
||||
uint32_t prepad, uint32_t blocks, int flag)
|
||||
{
|
||||
|
||||
struct iso_interval_reader *ivr = NULL;
|
||||
int buf_fill;
|
||||
off_t byte_count;
|
||||
FILE *fp = NULL;
|
||||
uint32_t i;
|
||||
|
||||
uint32_t i, intvl_blocks;
|
||||
uint8_t *buf = NULL;
|
||||
int ret;
|
||||
|
||||
@ -1498,10 +2006,21 @@ int iso_write_partition_file(Ecma119Image *target, char *path,
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* >>> need opportunity to read from input ISO image
|
||||
resp. to just mark a partition in the older sessions
|
||||
*/;
|
||||
|
||||
if (flag & 1) {
|
||||
ret = iso_interval_reader_new(target->image, path,
|
||||
&ivr, &byte_count, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
intvl_blocks = (byte_count + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
ret = iso_interval_reader_read(ivr, buf, &buf_fill, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_write(target, buf, BLOCK_SIZE);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
} else {
|
||||
fp = fopen(path, "rb");
|
||||
if (fp == NULL)
|
||||
{ret = ISO_BAD_PARTITION_FILE; goto ex;}
|
||||
@ -1523,8 +2042,10 @@ int iso_write_partition_file(Ecma119Image *target, char *path,
|
||||
}
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
}
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
iso_interval_reader_destroy(&ivr, 0);
|
||||
LIBISO_FREE_MEM(buf);
|
||||
return ret;
|
||||
}
|
||||
@ -1594,7 +2115,8 @@ void *write_function(void *arg)
|
||||
res = iso_write_partition_file(target,
|
||||
target->opts->appended_partitions[i],
|
||||
target->appended_part_prepad[i],
|
||||
target->appended_part_size[i], 0);
|
||||
target->appended_part_size[i],
|
||||
target->opts->appended_part_flags[i] & 1);
|
||||
if (res < 0)
|
||||
goto write_error;
|
||||
}
|
||||
@ -2825,9 +3347,14 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
|
||||
|
||||
wopts->tail_blocks = 0;
|
||||
wopts->prep_partition = NULL;
|
||||
wopts->prep_part_flag = 0;
|
||||
wopts->efi_boot_partition = NULL;
|
||||
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
|
||||
wopts->efi_boot_part_flag = 0;
|
||||
for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
|
||||
wopts->appended_partitions[i] = NULL;
|
||||
wopts->appended_part_types[i] = 0;
|
||||
wopts->appended_part_flags[i] = 0;
|
||||
}
|
||||
wopts->appended_as_gpt = 0;
|
||||
wopts->ascii_disc_label[0] = 0;
|
||||
wopts->will_cancel = 0;
|
||||
@ -3510,6 +4037,7 @@ int iso_write_opts_set_prep_img(IsoWriteOpts *opts, char *image_path, int flag)
|
||||
opts->prep_partition = strdup(image_path);
|
||||
if (opts->prep_partition == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
opts->prep_part_flag = (flag & 1);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
@ -3523,6 +4051,7 @@ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path,
|
||||
opts->efi_boot_partition = strdup(image_path);
|
||||
if (opts->efi_boot_partition == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
opts->efi_boot_part_flag = (flag & 1);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
@ -3539,6 +4068,7 @@ int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
|
||||
if (opts->appended_partitions[partition_number - 1] == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
opts->appended_part_types[partition_number - 1] = partition_type;
|
||||
opts->appended_part_flags[partition_number - 1] = (flag & 1);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -468,17 +468,20 @@ struct iso_write_opts {
|
||||
to HFS+/FAT and IsoFileSrc areas and marked by an MBR partition entry.
|
||||
*/
|
||||
char *prep_partition;
|
||||
int prep_part_flag;
|
||||
|
||||
/* Eventual disk file path of an EFI system partition image which shall
|
||||
be prepended to HFS+/FAT and IsoFileSrc areas and marked by a GPT entry.
|
||||
*/
|
||||
char *efi_boot_partition;
|
||||
int efi_boot_part_flag;
|
||||
|
||||
/* Eventual disk file paths of prepared images which shall be appended
|
||||
after the ISO image and described by partiton table entries in a MBR
|
||||
*/
|
||||
char *appended_partitions[ISO_MAX_PARTITIONS];
|
||||
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
|
||||
int appended_part_flags[ISO_MAX_PARTITIONS];
|
||||
|
||||
/* If 1: With appended partitions: create protective MBR and mark by GPT
|
||||
*/
|
||||
|
@ -124,6 +124,12 @@ struct iso_read_opts
|
||||
* submission by iso_write_opts_set_system_area(data, 0).
|
||||
*/
|
||||
int load_system_area;
|
||||
|
||||
/**
|
||||
* Keep data source of imported ISO filesystem in IsoImage.import_src
|
||||
*/
|
||||
int keep_import_src;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -5620,6 +5626,10 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
data = fs->data;
|
||||
|
||||
|
||||
if (opts->keep_import_src) {
|
||||
iso_data_source_ref(src);
|
||||
image->import_src = src;
|
||||
}
|
||||
if (opts->load_system_area) {
|
||||
if (image->system_area_data != NULL)
|
||||
free(image->system_area_data);
|
||||
@ -6029,6 +6039,7 @@ int iso_read_opts_new(IsoReadOpts **opts, int profile)
|
||||
ropts->noaaip = 1;
|
||||
ropts->nomd5 = 1;
|
||||
ropts->load_system_area = 0;
|
||||
ropts->keep_import_src = 0;
|
||||
|
||||
*opts = ropts;
|
||||
return ISO_SUCCESS;
|
||||
@ -6173,6 +6184,15 @@ int iso_read_opts_load_system_area(IsoReadOpts *opts, int mode)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_read_opts_keep_import_src(IsoReadOpts *opts, int mode)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->keep_import_src = mode & 1;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an IsoReadImageFeatures object obtained with iso_image_import.
|
||||
*/
|
||||
|
@ -185,6 +185,7 @@ int iso_image_new(const char *name, IsoImage **image)
|
||||
img->hppa_kernel_64 = NULL;
|
||||
img->hppa_ramdisk = NULL;
|
||||
img->alpha_boot_image = NULL;
|
||||
img->import_src = NULL;
|
||||
img->builder_ignore_acl = 1;
|
||||
img->builder_ignore_ea = 1;
|
||||
img->inode_counter = 0;
|
||||
@ -245,6 +246,8 @@ void iso_image_unref(IsoImage *image)
|
||||
iso_image_set_hppa_palo(image, NULL, NULL, NULL, NULL, NULL, 1);
|
||||
if (image->alpha_boot_image != NULL)
|
||||
free(image->alpha_boot_image);
|
||||
if (image->import_src != NULL)
|
||||
iso_data_source_unref(image->import_src);
|
||||
free(image->volset_id);
|
||||
free(image->volume_id);
|
||||
free(image->publisher_id);
|
||||
|
@ -64,6 +64,8 @@ struct Iso_Image
|
||||
/* Eventually loaded system area data, or NULL */
|
||||
char *system_area_data;
|
||||
/* Prescribed/detected options, see iso_write_opts_set_system_area() */
|
||||
/* >>> Needs to be coordinated with .imported_sa_info->system_area_options
|
||||
*/
|
||||
int system_area_options;
|
||||
|
||||
/*
|
||||
@ -100,6 +102,11 @@ struct Iso_Image
|
||||
IsoFilesystem *fs;
|
||||
|
||||
/**
|
||||
* Block storage of imported ISO if demanded by IsoReadOpts.
|
||||
*/
|
||||
IsoDataSource *import_src;
|
||||
|
||||
/*
|
||||
* Default builder to use when adding files to the image tree.
|
||||
*/
|
||||
IsoNodeBuilder *builder;
|
||||
|
@ -2409,6 +2409,117 @@ int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle);
|
||||
*/
|
||||
int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks);
|
||||
|
||||
|
||||
/**
|
||||
* The libisofs interval reader is used internally and offered by libisofs API:
|
||||
* @since 1.4.0
|
||||
* The functions iso_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp(),
|
||||
* and iso_write_opts_set_partition_img() accept with their flag bit0 an
|
||||
* interval reader description string instead of a disk path.
|
||||
* The API calls are iso_interval_reader_new(), iso_interval_reader_read(),
|
||||
* and iso_interval_reader_destroy().
|
||||
* The data may be cut out and optionally partly zeroized.
|
||||
*
|
||||
* An interval reader description string has the form:
|
||||
* $flags:$interval:$zeroizers:$source
|
||||
* The component $flags modifies the further interpretation:
|
||||
* "local_fs" ....... demands to read from a file depicted by the path in
|
||||
* $source.
|
||||
* "imported_iso" ... demands to read from the IsoDataSource object that was
|
||||
* used with iso_image_import() when
|
||||
* iso_read_opts_keep_import_src() was enabled.
|
||||
* The text in $source is ignored.
|
||||
* The application has to ensure that reading from the
|
||||
* import source does not disturb production of the new
|
||||
* ISO session. Especially this would be the case if the
|
||||
* import source is the same libburn drive with a
|
||||
* sequential optical medium to which the new session shall
|
||||
* get burned.
|
||||
* The component $interval consists of two byte address numbers separated
|
||||
* by a "-" character. E.g. "0-429" means to read bytes 0 to 429.
|
||||
* The component $zeroizers consists of zero or more comma separated strings.
|
||||
* They define which part of the read data to zeroize. Byte number 0 means
|
||||
* the byte read from the $interval start address.
|
||||
* Each string may be either
|
||||
* "zero_mbrpt" ..... demands to zeroize bytes 446 to 509 of the read data if
|
||||
* bytes 510 and 511 bear the MBR signature 0x55 0xaa.
|
||||
* "zero_gpt" ....... demands to check for a GPT header in bytes 512 to 1023,
|
||||
* to zeroize it and its partition table blocks.
|
||||
* "zero_apm" ....... demands to check for an APM block 0 and to zeroize
|
||||
* its partition table blocks. But not the block 0 itself,
|
||||
* because it could be actually MBR x86 machine code.
|
||||
* $zero_start"-"$zero_end ... demands to zeroize the read-in bytes beginning
|
||||
* with number $zero_start and ending after $zero_end.
|
||||
* The component $source is the file path with "local_fs", and ignored with
|
||||
* "imported_iso".
|
||||
* Byte numbers may be scaled by a suffix out of {k,m,g,t,s,d} meaning
|
||||
* multiplication by {1024, 1024k, 1024m, 1024g, 2048, 512}. A scaled value
|
||||
* as end number depicts the last byte of the scaled range.
|
||||
* E.g. "0d-0d" is "0-511".
|
||||
* Examples:
|
||||
* "local_fs:0-32767:zero_mbrpt,zero_gpt,440-443:/tmp/template.iso"
|
||||
* "imported_iso:45056d-47103d::"
|
||||
*/
|
||||
struct iso_interval_reader;
|
||||
|
||||
/**
|
||||
* Create an interval reader object.
|
||||
*
|
||||
* @param img
|
||||
* The IsoImage object which can provide the "imported_iso" data source.
|
||||
* @param path
|
||||
* The interval reader description string. See above.
|
||||
* @param ivr
|
||||
* Returns in case of success a pointer to the created object.
|
||||
* Dispose it by iso_interval_reader_destroy() when no longer needed.
|
||||
* @param byte_count
|
||||
* Returns in case of success the number of bytes in the interval.
|
||||
* @param flag
|
||||
* bit0= tolerate (src == NULL) with "imported_iso".
|
||||
* (Will immediately cause eof of interval input.)
|
||||
* @return
|
||||
* ISO_SUCCESS or error (which is < 0)
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
int iso_interval_reader_new(IsoImage *img, char *path,
|
||||
struct iso_interval_reader **ivr,
|
||||
off_t *byte_count, int flag);
|
||||
|
||||
/**
|
||||
* Dispose an interval reader object.
|
||||
*
|
||||
* @param ivr
|
||||
* The reader object to be disposed. *ivr will be set to NULL.
|
||||
* @return
|
||||
* ISO_SUCCESS or error (which is < 0)
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
int iso_interval_reader_destroy(struct iso_interval_reader **ivr, int flag);
|
||||
|
||||
/**
|
||||
* Read the next block of 2048 bytes from an interval reader object.
|
||||
* If end-of-input happens, the interval will get filled up with 0 bytes.
|
||||
*
|
||||
* @param ivr
|
||||
* The object to read from.
|
||||
* @param buf
|
||||
* Pointer to memory for filling in at least 2048 bytes.
|
||||
* @param buf_fill
|
||||
* Will in case of success return the number of valid bytes.
|
||||
* If this is smaller than 2048, then end-of-interval has occured.
|
||||
* @param flag
|
||||
* Unused yet. Submit 0.
|
||||
* @return
|
||||
* ISO_SUCCESS if data were read, 0 if not, < 0 if error
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
int iso_interval_reader_read(struct iso_interval_reader *ivr, uint8_t *buf,
|
||||
int *buf_fill, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Copy a data file from the local filesystem into the emerging ISO image.
|
||||
* Mark it by an MBR partition entry as PreP partition and also cause
|
||||
@ -2427,10 +2538,14 @@ int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks);
|
||||
* @param opts
|
||||
* The option set to be manipulated.
|
||||
* @param image_path
|
||||
* File address in the local file system.
|
||||
* File address in the local file system or instructions for interval
|
||||
* reader. See flag bit0.
|
||||
* NULL revokes production of the PreP partition.
|
||||
* @param flag
|
||||
* Reserved for future usage, set to 0.
|
||||
* bit0= The path contains instructions for the interval reader.
|
||||
* See above.
|
||||
* @since 1.4.0
|
||||
* All other bits are reserved for future usage. Set them to 0.
|
||||
* @return
|
||||
* ISO_SUCCESS or error
|
||||
*
|
||||
@ -2457,10 +2572,14 @@ int iso_write_opts_set_prep_img(IsoWriteOpts *opts, char *image_path,
|
||||
* @param opts
|
||||
* The option set to be manipulated.
|
||||
* @param image_path
|
||||
* File address in the local file system.
|
||||
* File address in the local file system or instructions for interval
|
||||
* reader. See flag bit0.
|
||||
* NULL revokes production of the EFI boot partition.
|
||||
* @param flag
|
||||
* Reserved for future usage, set to 0.
|
||||
* bit0= The path contains instructions for the interval reader
|
||||
* See above.
|
||||
* @since 1.4.0
|
||||
* All other bits are reserved for future usage. Set them to 0.
|
||||
* @return
|
||||
* ISO_SUCCESS or error
|
||||
*
|
||||
@ -2488,7 +2607,8 @@ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path,
|
||||
* unclaimable space before partition 1.
|
||||
* Range with SUN Disk Label: 2 to 8.
|
||||
* @param image_path
|
||||
* File address in the local file system.
|
||||
* File address in the local file system or instructions for interval
|
||||
* reader. See flag bit0.
|
||||
* With SUN Disk Label: an empty name causes the partition to become
|
||||
* a copy of the next lower partition.
|
||||
* @param image_type
|
||||
@ -2496,7 +2616,9 @@ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path,
|
||||
* Linux Native Partition = 0x83. See fdisk command L.
|
||||
* This parameter is ignored with SUN Disk Label.
|
||||
* @param flag
|
||||
* bit0= The path may contain instructions for the interval reader
|
||||
* bit0= The path contains instructions for the interval reader
|
||||
* See above.
|
||||
* @since 1.4.0
|
||||
* All other bits are reserved for future usage. Set them to 0.
|
||||
* @return
|
||||
* ISO_SUCCESS or error
|
||||
@ -2816,6 +2938,24 @@ int iso_read_opts_auto_input_charset(IsoReadOpts *opts, int mode);
|
||||
*/
|
||||
int iso_read_opts_load_system_area(IsoReadOpts *opts, int mode);
|
||||
|
||||
/**
|
||||
* Control whether to keep a reference to the IsoDataSource object which
|
||||
* allows access to the blocks of the imported ISO 9660 filesystem.
|
||||
* This is needed if the interval reader shall read from "imported_iso".
|
||||
*
|
||||
* @param opts
|
||||
* The option set to be manipulated
|
||||
* @param mode
|
||||
* Bitfield for control purposes:
|
||||
* bit0= Keep a reference to the IsoDataSource until the IsoImage object
|
||||
* gets disposed by its final iso_image_unref().
|
||||
* Submit any other bits with value 0.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*
|
||||
*/
|
||||
int iso_read_opts_keep_import_src(IsoReadOpts *opts, int mode);
|
||||
|
||||
/**
|
||||
* Import a previous session or image, for growing or modify.
|
||||
*
|
||||
@ -8161,7 +8301,17 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len,
|
||||
#define ISO_INQ_SYSAREA_PROP 0xE830FE6C
|
||||
|
||||
/** DEC Alpha Boot Loader file is not a data file (FAILURE, HIGH, -405) */
|
||||
#define ISO_ALPHA_BOOT_NOTREG 0xE830FE6A
|
||||
#define ISO_ALPHA_BOOT_NOTREG 0xE830FE6B
|
||||
|
||||
/** No data source of imported ISO image available (WARNING, HIGH, -406) */
|
||||
#define ISO_NO_KEPT_DATA_SRC 0xD030FE6A
|
||||
|
||||
/** Malformed description string for interval reader (FAILURE, HIGH, -407) */
|
||||
#define ISO_MALFORMED_READ_INTVL 0xE830FE69
|
||||
|
||||
/** Unreadable file, premature EOF, or failure to seek for interval reader
|
||||
(WARNING, HIGH, -408) */
|
||||
#define ISO_INTVL_READ_PROBLEM 0xD030FE68
|
||||
|
||||
|
||||
/* Internal developer note:
|
||||
|
@ -141,6 +141,9 @@ iso_image_unref;
|
||||
iso_image_update_sizes;
|
||||
iso_init;
|
||||
iso_init_with_flag;
|
||||
iso_interval_reader_destroy;
|
||||
iso_interval_reader_new;
|
||||
iso_interval_reader_read;
|
||||
iso_lib_is_compatible;
|
||||
iso_lib_version;
|
||||
iso_local_attr_support;
|
||||
@ -216,6 +219,7 @@ iso_read_image_features_has_joliet;
|
||||
iso_read_image_features_has_rockridge;
|
||||
iso_read_opts_auto_input_charset;
|
||||
iso_read_opts_free;
|
||||
iso_read_opts_keep_import_src;
|
||||
iso_read_opts_load_system_area;
|
||||
iso_read_opts_new;
|
||||
iso_read_opts_set_default_gid;
|
||||
|
@ -521,6 +521,12 @@ const char *iso_error_to_msg(int errcode)
|
||||
return "Unrecognized inquiry for system area property";
|
||||
case ISO_ALPHA_BOOT_NOTREG:
|
||||
return "DEC Alpha Boot Loader file is not a data file";
|
||||
case ISO_NO_KEPT_DATA_SRC:
|
||||
return "No data source of imported ISO image available";
|
||||
case ISO_MALFORMED_READ_INTVL:
|
||||
return "Malformed description string for interval reader";
|
||||
case ISO_INTVL_READ_PROBLEM:
|
||||
return "Unreadable file, premature EOF, or failure to seek for interval reader";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
@ -107,12 +107,26 @@ void iso_compute_cyl_head_sec(uint64_t img_blocks, int hpc, int sph,
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t compute_partition_size(char *disk_path, uint32_t *size,
|
||||
int flag)
|
||||
/* @param flag bit0= The path contains instructions for the interval reader
|
||||
*/
|
||||
static int compute_partition_size(Ecma119Image *t, char *disk_path,
|
||||
uint32_t *size, int flag)
|
||||
{
|
||||
int ret;
|
||||
off_t num;
|
||||
struct stat stbuf;
|
||||
struct iso_interval_reader *ivr;
|
||||
off_t byte_count;
|
||||
|
||||
if (flag & 1) {
|
||||
ret = iso_interval_reader_new(t->image, disk_path,
|
||||
&ivr, &byte_count, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*size = (byte_count + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||
iso_interval_reader_destroy(&ivr, 0);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
*size = 0;
|
||||
ret = stat(disk_path, &stbuf);
|
||||
@ -150,8 +164,8 @@ int iso_compute_append_partitions(Ecma119Image *t, int flag)
|
||||
continue;
|
||||
if (t->opts->appended_partitions[i][0] == 0)
|
||||
continue;
|
||||
ret = compute_partition_size(t->opts->appended_partitions[i], &size,
|
||||
0);
|
||||
ret = compute_partition_size(t, t->opts->appended_partitions[i], &size,
|
||||
t->opts->appended_part_flags[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
add_pos = 0;
|
||||
@ -255,7 +269,7 @@ static int write_mbr_partition_entry(int partition_number, int partition_type,
|
||||
*/
|
||||
static
|
||||
int make_grub_msdos_label(uint32_t img_blocks, int sph, int hpc,
|
||||
uint8_t *buf, int flag)
|
||||
uint8_t part_type, uint8_t *buf, int flag)
|
||||
{
|
||||
uint8_t *wpt;
|
||||
uint32_t end_lba, end_sec, end_head, end_cyl;
|
||||
@ -286,7 +300,7 @@ int make_grub_msdos_label(uint32_t img_blocks, int sph, int hpc,
|
||||
*(wpt++) = 0;
|
||||
|
||||
/* 0xcd (partition type) */
|
||||
*(wpt++) = 0xcd;
|
||||
*(wpt++) = part_type;
|
||||
|
||||
/* [3 bytes of C/H/S end], */
|
||||
*(wpt++) = end_head;
|
||||
@ -1660,7 +1674,7 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
int first_partition = 1, last_partition = 4, apm_flag, part_type = 0;
|
||||
int gpt_count = 0, gpt_idx[128], apm_count = 0, no_boot_mbr = 0;
|
||||
int offset_flag = 0;
|
||||
uint32_t img_blocks, gpt_blocks, mbrp1_blocks;
|
||||
uint32_t img_blocks, gpt_blocks, mbrp1_blocks, pml_blocks;
|
||||
uint64_t blk;
|
||||
uint8_t *wpt;
|
||||
|
||||
@ -1767,8 +1781,16 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
if (t->mbr_req_count == 0){
|
||||
/* Write GRUB protective msdos label, i.e. a simple partition
|
||||
table */
|
||||
ret = make_grub_msdos_label(img_blocks, t->partition_secs_per_head,
|
||||
t->partition_heads_per_cyl, buf, 0);
|
||||
if (t->gpt_req_count > 0) {
|
||||
part_type = 0xee;
|
||||
pml_blocks = gpt_blocks;
|
||||
} else {
|
||||
part_type = 0xcd;
|
||||
pml_blocks = img_blocks;
|
||||
}
|
||||
ret = make_grub_msdos_label(pml_blocks, t->partition_secs_per_head,
|
||||
t->partition_heads_per_cyl,
|
||||
(uint8_t) part_type, buf, 0);
|
||||
if (ret != ISO_SUCCESS) /* error should never happen */
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
@ -1826,7 +1848,8 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
sa_type == 0 && t->mbr_req_count == 0) {
|
||||
/* Write a simple partition table. */
|
||||
ret = make_grub_msdos_label(img_blocks, t->partition_secs_per_head,
|
||||
t->partition_heads_per_cyl, buf, 2);
|
||||
t->partition_heads_per_cyl,
|
||||
(uint8_t) 0xcd, buf, 2);
|
||||
if (ret != ISO_SUCCESS) /* error should never happen */
|
||||
return ISO_ASSERT_FAILURE;
|
||||
if (t->opts->appended_as_gpt && t->have_appended_partitions) {
|
||||
@ -1961,7 +1984,8 @@ int iso_align_isohybrid(Ecma119Image *t, int flag)
|
||||
|
||||
img_blocks = t->curblock + t->opts->tail_blocks + t->gpt_backup_size;
|
||||
imgsize = ((off_t) img_blocks) * (off_t) 2048;
|
||||
if (((t->system_area_options & 3) || always_align)
|
||||
if ((!(t->opts->appended_as_gpt && t->have_appended_partitions))
|
||||
&& ((t->system_area_options & 3) || always_align)
|
||||
&& (off_t) (t->partition_heads_per_cyl * t->partition_secs_per_head
|
||||
* 1024) * (off_t) 512 < imgsize) {
|
||||
/* Choose small values which can represent the image size */
|
||||
@ -2585,7 +2609,7 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
t->efi_boot_part_size += (src->sections[i].size + 2047) / 2048;
|
||||
}
|
||||
} else {
|
||||
ret = compute_partition_size(t->opts->efi_boot_partition,
|
||||
ret = compute_partition_size(t, t->opts->efi_boot_partition,
|
||||
&(t->efi_boot_part_size), 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -2615,7 +2639,7 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
}
|
||||
|
||||
if (t->opts->prep_partition != NULL) {
|
||||
ret = compute_partition_size(t->opts->prep_partition,
|
||||
ret = compute_partition_size(t, t->opts->prep_partition,
|
||||
&(t->prep_part_size), 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -2672,14 +2696,16 @@ static int partprepend_writer_write_data(IsoImageWriter *writer)
|
||||
NULL, NULL, 0);
|
||||
} else {
|
||||
ret = iso_write_partition_file(t, t->opts->efi_boot_partition,
|
||||
(uint32_t) 0, t->efi_boot_part_size, 0);
|
||||
(uint32_t) 0, t->efi_boot_part_size,
|
||||
t->opts->efi_boot_part_flag & 1);
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (t->opts->prep_partition != NULL && t->prep_part_size) {
|
||||
ret = iso_write_partition_file(t, t->opts->prep_partition,
|
||||
(uint32_t) 0, t->prep_part_size, 0);
|
||||
(uint32_t) 0, t->prep_part_size,
|
||||
t->opts->prep_part_flag & 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@ -2762,7 +2788,8 @@ static int partappend_writer_write_data(IsoImageWriter *writer)
|
||||
res = iso_write_partition_file(target,
|
||||
target->opts->appended_partitions[i],
|
||||
target->appended_part_prepad[i],
|
||||
target->appended_part_size[i], 0);
|
||||
target->appended_part_size[i],
|
||||
target->appended_part_flags[i] & 1);
|
||||
if (res < 0)
|
||||
return res;
|
||||
target->curblock += target->appended_part_size[i];
|
||||
|
@ -2305,3 +2305,41 @@ int iso_clone_mgtd_mem(char *in, char **out, size_t size)
|
||||
return iso_clone_mem(in, out, size);
|
||||
}
|
||||
|
||||
|
||||
/** Convert a text into a number of type double and multiply it by unit code
|
||||
[kmgt] (2^10 to 2^40) or [s] (2048) or [d] (512).
|
||||
(Also accepts capital letters.)
|
||||
@param text Input like "42", "223062s", "3m" or "-1g"
|
||||
@param flag Bitfield for control purposes:
|
||||
bit0= return -1 rathern than 0 on failure
|
||||
bit1= if scaled then compute the last byte of the last unit
|
||||
@return The derived value
|
||||
*/
|
||||
off_t iso_scanf_io_size(char *text, int flag)
|
||||
{
|
||||
int c;
|
||||
off_t ret = 0, fac = 1;
|
||||
char *rpt;
|
||||
|
||||
for (rpt = text; *rpt >= '0' && *rpt <= '9'; rpt++)
|
||||
ret = ret * 10 + (*rpt - '0');
|
||||
if (rpt == text)
|
||||
return (off_t) (flag & 1 ? -1 : 0);
|
||||
c = *rpt;
|
||||
if (c=='k' || c=='K')
|
||||
fac = 1024;
|
||||
else if (c=='m' || c=='M')
|
||||
fac = 1024 * 1024;
|
||||
else if (c=='g' || c=='G')
|
||||
fac = 1024 * 1024 * 1024;
|
||||
else if (c=='t' || c=='T')
|
||||
fac = ((off_t) 1024) * 1024 * 1024 * 1024;
|
||||
else if (c=='s' || c=='S')
|
||||
fac = 2048;
|
||||
else if (c=='d' || c=='D')
|
||||
fac = 512;
|
||||
ret *= fac;
|
||||
if (flag & 2)
|
||||
ret += fac - 1;
|
||||
return ret;
|
||||
}
|
||||
|
@ -21,6 +21,10 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
@ -627,6 +631,16 @@ int iso_clone_mem(char *in, char **out, size_t size);
|
||||
*/
|
||||
int iso_clone_mgtd_mem(char *in, char **out, size_t size);
|
||||
|
||||
/** Convert a text into a number of type double and multiply it by unit code
|
||||
[kmgt] (2^10 to 2^40) or [s] (2048) or [d] (512).
|
||||
(Also accepts capital letters.)
|
||||
@param text Input like "42", "223062s", "3m" or "-1g"
|
||||
@param flag Bitfield for control purposes:
|
||||
bit0= return -1 rathern than 0 on failure
|
||||
bit1= if scaled then compute the last byte of the last unit
|
||||
@return The derived value
|
||||
*/
|
||||
off_t iso_scanf_io_size(char *text, int flag);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user