mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zipl/src: add basic support for multiple target base disks
. Modify disk_get_info() to process multiple sets of target parameters
provided by the helper script and store it in the array of "targets"
of the structure job_target_data;
. Besides the logical device, maintain an array of physical base disks
in the disk_info structure;
. Use the logical target device only to create bootmap (it is
automatically mirrored by the respective linux driver (dm, or md)
managing the mirrored target). In contrast, install bootstrap blocks
to each physical base disk individually, bypassing that driver;
. Report in verbose mode on which base disks the bootstrap
installation was performed;
. Use the following logic of setting @info->device (which is printed
as "Device...:" in verbose mode):
. source_auto - the target base disk is set;
. source_script - the target (logical) device is set;
. source_user - the device specified by user (via --targetbase
option), or config file is set.
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
committed by
Steffen Eiden
parent
d9a9bd8dcf
commit
d6b702d579
@@ -56,13 +56,14 @@ typedef enum {
|
|||||||
/* targetbase definition */
|
/* targetbase definition */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
defined_as_device,
|
defined_as_device,
|
||||||
defined_as_name
|
defined_as_name,
|
||||||
|
undefined
|
||||||
} definition_t;
|
} definition_t;
|
||||||
|
|
||||||
/* Disk information type */
|
/* Disk information type */
|
||||||
struct disk_info {
|
struct disk_info {
|
||||||
disk_type_t type;
|
disk_type_t type;
|
||||||
dev_t device;
|
dev_t device; /* logical device for bootmap creation */
|
||||||
dev_t partition;
|
dev_t partition;
|
||||||
int devno;
|
int devno;
|
||||||
int partnum;
|
int partnum;
|
||||||
@@ -72,8 +73,11 @@ struct disk_info {
|
|||||||
struct hd_geometry geo;
|
struct hd_geometry geo;
|
||||||
char* name;
|
char* name;
|
||||||
char* drv_name;
|
char* drv_name;
|
||||||
definition_t targetbase;
|
definition_t targetbase_def;
|
||||||
int is_nvme;
|
int is_nvme;
|
||||||
|
dev_t basedisks[MAX_TARGETS]; /* array of physical disks for
|
||||||
|
* bootstrap blocks recording
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file_range {
|
struct file_range {
|
||||||
@@ -113,6 +117,9 @@ blocknum_t disk_write_block_buffer_align(int fd, int fd_is_basedisk,
|
|||||||
struct disk_info *info, int align,
|
struct disk_info *info, int align,
|
||||||
off_t *offset);
|
off_t *offset);
|
||||||
void disk_print_devt(dev_t d);
|
void disk_print_devt(dev_t d);
|
||||||
|
void disk_print_devname(dev_t d);
|
||||||
|
void prepare_footnote_ptr(int source, char *ptr);
|
||||||
|
void print_footnote_ref(int source, const char *prefix);
|
||||||
void disk_print_info(struct disk_info *info, int source);
|
void disk_print_info(struct disk_info *info, int source);
|
||||||
int disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info);
|
int disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info);
|
||||||
blocknum_t disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count,
|
blocknum_t disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count,
|
||||||
@@ -122,7 +129,6 @@ blocknum_t disk_get_blocklist_from_file(const char* filename,
|
|||||||
disk_blockptr_t** blocklist,
|
disk_blockptr_t** blocklist,
|
||||||
struct disk_info* pinfo);
|
struct disk_info* pinfo);
|
||||||
int disk_check_subchannel_set(int devno, dev_t device, char* dev_name);
|
int disk_check_subchannel_set(int devno, dev_t device, char* dev_name);
|
||||||
void disk_print_geo(struct disk_info *data);
|
|
||||||
int fs_map(int fd, uint64_t offset, blocknum_t *mapped, int fs_block_size);
|
int fs_map(int fd, uint64_t offset, blocknum_t *mapped, int fs_block_size);
|
||||||
|
|
||||||
#endif /* not DISK_H */
|
#endif /* not DISK_H */
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ struct install_set {
|
|||||||
struct program_component *components[NR_PROGRAM_COMPONENTS];
|
struct program_component *components[NR_PROGRAM_COMPONENTS];
|
||||||
int nr_menu_entries;
|
int nr_menu_entries;
|
||||||
int fd;
|
int fd;
|
||||||
char *device;
|
char *basetmp[MAX_TARGETS];
|
||||||
char *filename;
|
char *filename;
|
||||||
unsigned int tmp_filename_created:1;
|
unsigned int tmp_filename_created:1;
|
||||||
unsigned int skip_prepare:1;
|
unsigned int skip_prepare:1;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "zipl.h"
|
#include "zipl.h"
|
||||||
|
|
||||||
|
|
||||||
enum job_id {
|
enum job_id {
|
||||||
job_print_usage = 1,
|
job_print_usage = 1,
|
||||||
job_print_version = 2,
|
job_print_version = 2,
|
||||||
@@ -30,6 +29,21 @@ enum job_id {
|
|||||||
job_mvdump = 8,
|
job_mvdump = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set of parameters per physical disk, which are provided
|
||||||
|
* either by user, or by helper script
|
||||||
|
*/
|
||||||
|
struct target {
|
||||||
|
char *targetbase;
|
||||||
|
disk_type_t targettype;
|
||||||
|
int targetcylinders;
|
||||||
|
int targetheads;
|
||||||
|
int targetsectors;
|
||||||
|
int targetblocksize;
|
||||||
|
blocknum_t targetoffset;
|
||||||
|
int check_params;
|
||||||
|
};
|
||||||
|
|
||||||
/* target information source */
|
/* target information source */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
source_unknown = 0,
|
source_unknown = 0,
|
||||||
@@ -39,17 +53,21 @@ typedef enum {
|
|||||||
} source_t;
|
} source_t;
|
||||||
|
|
||||||
struct job_target_data {
|
struct job_target_data {
|
||||||
char* bootmap_dir;
|
char *bootmap_dir;
|
||||||
char* targetbase;
|
int nr_targets;
|
||||||
disk_type_t targettype;
|
struct target targets[MAX_TARGETS];
|
||||||
int targetcylinders;
|
|
||||||
int targetheads;
|
|
||||||
int targetsectors;
|
|
||||||
int targetblocksize;
|
|
||||||
blocknum_t targetoffset;
|
|
||||||
source_t source;
|
source_t source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum target_params {
|
||||||
|
TARGET_BASE,
|
||||||
|
TARGET_TYPE,
|
||||||
|
TARGET_GEOMETRY,
|
||||||
|
TARGET_BLOCKSIZE,
|
||||||
|
TARGET_OFFSET,
|
||||||
|
LAST_TARGET_PARAM
|
||||||
|
};
|
||||||
|
|
||||||
struct job_common_ipl_data {
|
struct job_common_ipl_data {
|
||||||
char* image;
|
char* image;
|
||||||
char* parmline;
|
char* parmline;
|
||||||
@@ -142,12 +160,94 @@ struct job_data {
|
|||||||
int is_ldipl_dump;
|
int is_ldipl_dump;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct target *target_at(struct job_target_data *data,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
return index >= MAX_TARGETS ? NULL : &data->targets[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *get_targetbase(struct job_target_data *data, int index)
|
||||||
|
{
|
||||||
|
return target_at(data, index)->targetbase;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_targetbase(struct job_target_data *data, int index,
|
||||||
|
char *value)
|
||||||
|
{
|
||||||
|
target_at(data, index)->targetbase = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline disk_type_t get_targettype(struct job_target_data *data,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
return target_at(data, index)->targettype;
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_targettype(struct job_target_data *data, int index, char *value);
|
||||||
|
|
||||||
|
static inline char *job_get_targetbase(struct job_data *job)
|
||||||
|
{
|
||||||
|
return get_targetbase(&job->target, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void job_set_targetbase(struct job_data *job, char *value)
|
||||||
|
{
|
||||||
|
set_targetbase(&job->target, 0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int job_get_nr_targets(struct job_data *job)
|
||||||
|
{
|
||||||
|
return job->target.nr_targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void job_set_nr_targets(struct job_data *job, int value)
|
||||||
|
{
|
||||||
|
job->target.nr_targets = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline disk_type_t job_get_targettype(struct job_data *job)
|
||||||
|
{
|
||||||
|
return get_targettype(&job->target, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int job_set_targettype(struct job_data *job, char *value);
|
||||||
|
|
||||||
|
#define define_target_param_ops(_TYPE_, _PARAM_) \
|
||||||
|
static inline _TYPE_ get_target##_PARAM_(struct job_target_data *data, \
|
||||||
|
int index) \
|
||||||
|
{ \
|
||||||
|
return target_at(data, index)->target##_PARAM_; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline void set_target##_PARAM_(struct job_target_data *data, \
|
||||||
|
int index, _TYPE_ value) \
|
||||||
|
{ \
|
||||||
|
target_at(data, index)->target##_PARAM_ = value; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline _TYPE_ job_get_target##_PARAM_(struct job_data *job) \
|
||||||
|
{ \
|
||||||
|
return get_target##_PARAM_(&job->target, 0); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline void job_set_target##_PARAM_(struct job_data *job, \
|
||||||
|
_TYPE_ value) \
|
||||||
|
{ \
|
||||||
|
set_target##_PARAM_(&job->target, 0, value); \
|
||||||
|
}
|
||||||
|
|
||||||
|
define_target_param_ops(int, cylinders)
|
||||||
|
define_target_param_ops(int, heads)
|
||||||
|
define_target_param_ops(int, sectors)
|
||||||
|
define_target_param_ops(int, blocksize)
|
||||||
|
define_target_param_ops(blocknum_t, offset)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true, if target parameters for the base disk are set
|
* Return true, if target parameters are set at least for one target base disk
|
||||||
*/
|
*/
|
||||||
static inline int target_parameters_are_set(struct job_target_data *td)
|
static inline int target_parameters_are_set(struct job_target_data *td)
|
||||||
{
|
{
|
||||||
return td->targetbase != NULL;
|
return get_targetbase(td, 0) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int job_get(int argc, char* argv[], struct job_data** data);
|
int job_get(int argc, char* argv[], struct job_data** data);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#define MENU_DEFAULT_TIMEOUT 0
|
#define MENU_DEFAULT_TIMEOUT 0
|
||||||
|
|
||||||
#define MAX_DUMP_VOLUMES 32
|
#define MAX_DUMP_VOLUMES 32
|
||||||
|
#define MAX_TARGETS 32
|
||||||
|
|
||||||
#define SECURE_BOOT_UNDEFINED -1
|
#define SECURE_BOOT_UNDEFINED -1
|
||||||
#define SECURE_BOOT_DISABLED 0
|
#define SECURE_BOOT_DISABLED 0
|
||||||
|
|||||||
@@ -1489,9 +1489,9 @@ static int prepare_build_program_table_device(struct job_data *job,
|
|||||||
printf("Target device information\n");
|
printf("Target device information\n");
|
||||||
disk_print_info(bis->info, job->target.source);
|
disk_print_info(bis->info, job->target.source);
|
||||||
}
|
}
|
||||||
if (misc_temp_dev(bis->info->device, 1, &bis->device))
|
if (misc_temp_dev(bis->info->device, 1, &bis->basetmp[0]))
|
||||||
return -1;
|
return -1;
|
||||||
if (check_dump_device(job, bis->info, bis->device))
|
if (check_dump_device(job, bis->info, bis->basetmp[0]))
|
||||||
return -1;
|
return -1;
|
||||||
printf("Building bootmap directly on partition '%s'%s\n",
|
printf("Building bootmap directly on partition '%s'%s\n",
|
||||||
bis->filename,
|
bis->filename,
|
||||||
@@ -1555,6 +1555,8 @@ static int prepare_bootloader_device(struct job_data *job,
|
|||||||
static int prepare_build_program_table_file(struct job_data *job,
|
static int prepare_build_program_table_file(struct job_data *job,
|
||||||
struct install_set *bis)
|
struct install_set *bis)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (bis->skip_prepare)
|
if (bis->skip_prepare)
|
||||||
/* skip the preparation work */
|
/* skip the preparation work */
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1588,8 +1590,12 @@ static int prepare_build_program_table_file(struct job_data *job,
|
|||||||
printf("Target device information\n");
|
printf("Target device information\n");
|
||||||
disk_print_info(bis->info, job->target.source);
|
disk_print_info(bis->info, job->target.source);
|
||||||
}
|
}
|
||||||
if (misc_temp_dev(bis->info->device, 1, &bis->device))
|
for (i = 0; i < job_get_nr_targets(job); i++) {
|
||||||
return -1;
|
if (misc_temp_dev(bis->info->basedisks[i],
|
||||||
|
1,
|
||||||
|
&bis->basetmp[i]))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/* Check configuration number limits */
|
/* Check configuration number limits */
|
||||||
if (job->id == job_menu) {
|
if (job->id == job_menu) {
|
||||||
if (check_menu_positions(&job->data.menu, job->name,
|
if (check_menu_positions(&job->data.menu, job->name,
|
||||||
@@ -1704,9 +1710,9 @@ static int prepare_bootloader_ngdump(struct job_data *job,
|
|||||||
/* Retrieve target device information */
|
/* Retrieve target device information */
|
||||||
if (disk_get_info(job->data.dump.device, &job->target, &info))
|
if (disk_get_info(job->data.dump.device, &job->target, &info))
|
||||||
return -1;
|
return -1;
|
||||||
if (misc_temp_dev(info->device, 1, &bis->device))
|
if (misc_temp_dev(info->device, 1, &bis->basetmp[0]))
|
||||||
return -1;
|
return -1;
|
||||||
if (check_dump_device(job, info, bis->device))
|
if (check_dump_device(job, info, bis->basetmp[0]))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
assert(!job->target.bootmap_dir);
|
assert(!job->target.bootmap_dir);
|
||||||
@@ -1856,6 +1862,9 @@ void free_bootloader(struct install_set *bis)
|
|||||||
if (bis->tmp_filename_created)
|
if (bis->tmp_filename_created)
|
||||||
misc_free_temp_file(bis->filename);
|
misc_free_temp_file(bis->filename);
|
||||||
free(bis->filename);
|
free(bis->filename);
|
||||||
misc_free_temp_dev(bis->device);
|
for (i = 0; i < MAX_TARGETS; i++) {
|
||||||
|
if (bis->basetmp[i])
|
||||||
|
misc_free_temp_dev(bis->basetmp[i]);
|
||||||
|
}
|
||||||
disk_free_info(bis->info);
|
disk_free_info(bis->info);
|
||||||
}
|
}
|
||||||
|
|||||||
293
zipl/src/disk.c
293
zipl/src/disk.c
@@ -187,43 +187,134 @@ out_err:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a script output represented by FH and consisting
|
||||||
|
* of pairs 'key=value' (each such pair is on a separate line).
|
||||||
|
* Check its consistency and set the extracted target parameters
|
||||||
|
* to the array of "targets" at TD.
|
||||||
|
*
|
||||||
|
* NOTE: this function defines specifications on valid output of
|
||||||
|
* zipl helper scripts. See zipl-support-for-mirrored-devices.txt
|
||||||
|
* for details. Before modifying this function, make sure that it
|
||||||
|
* won't lead to format change.
|
||||||
|
*/
|
||||||
static int set_target_parameters(FILE *fh, struct job_target_data *td)
|
static int set_target_parameters(FILE *fh, struct job_target_data *td)
|
||||||
{
|
{
|
||||||
int checkparm = 0;
|
int idx[LAST_TARGET_PARAM] = {0};
|
||||||
|
struct target *t;
|
||||||
char buffer[80];
|
char buffer[80];
|
||||||
char value[40];
|
char value[40];
|
||||||
|
char *error;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a stream of 'key=value' pairs and distribute
|
||||||
|
* them into groups.
|
||||||
|
* The i-th occurrence of some "key" in the stream means
|
||||||
|
* that the respective pair belongs to the group #i
|
||||||
|
*/
|
||||||
|
error = "Exceeded the maximum number of base disks";
|
||||||
while (fgets(buffer, 80, fh)) {
|
while (fgets(buffer, 80, fh)) {
|
||||||
if (sscanf(buffer, "targetbase=%s", value) == 1) {
|
if (sscanf(buffer, "targetbase=%s", value) == 1) {
|
||||||
td->targetbase = misc_strdup(value);
|
t = target_at(td, idx[TARGET_BASE]++);
|
||||||
checkparm++;
|
if (!t)
|
||||||
|
goto error;
|
||||||
|
t->targetbase = misc_strdup(value);
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
if (sscanf(buffer, "targettype=%s", value) == 1) {
|
if (sscanf(buffer, "targettype=%s", value) == 1) {
|
||||||
type_from_target(value, &td->targettype);
|
t = target_at(td, idx[TARGET_TYPE]++);
|
||||||
checkparm++;
|
if (!t)
|
||||||
|
goto error;
|
||||||
|
type_from_target(value, &t->targettype);
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
if (sscanf(buffer, "targetgeometry=%s", value) == 1) {
|
if (sscanf(buffer, "targetgeometry=%s", value) == 1) {
|
||||||
td->targetcylinders =
|
t = target_at(td, idx[TARGET_GEOMETRY]++);
|
||||||
atoi(strtok(value, ","));
|
if (!t)
|
||||||
td->targetheads = atoi(strtok(NULL, ","));
|
goto error;
|
||||||
td->targetsectors = atoi(strtok(NULL, ","));
|
t->targetcylinders = atoi(strtok(value, ","));
|
||||||
checkparm++;
|
t->targetheads = atoi(strtok(NULL, ","));
|
||||||
|
t->targetsectors = atoi(strtok(NULL, ","));
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
if (sscanf(buffer, "targetblocksize=%s", value) == 1) {
|
if (sscanf(buffer, "targetblocksize=%s", value) == 1) {
|
||||||
td->targetblocksize = atoi(value);
|
t = target_at(td, idx[TARGET_BLOCKSIZE]++);
|
||||||
checkparm++;
|
if (!t)
|
||||||
|
goto error;
|
||||||
|
t->targetblocksize = atoi(value);
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
if (sscanf(buffer, "targetoffset=%s", value) == 1) {
|
if (sscanf(buffer, "targetoffset=%s", value) == 1) {
|
||||||
td->targetoffset = atol(value);
|
t = target_at(td, idx[TARGET_OFFSET]++);
|
||||||
checkparm++;
|
if (!t)
|
||||||
|
goto error;
|
||||||
|
t->targetoffset = atol(value);
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
found:
|
||||||
|
t->check_params++;
|
||||||
}
|
}
|
||||||
if ((!disk_is_eckd(td->targettype) && checkparm < 4) ||
|
/* Check for consistency */
|
||||||
(disk_is_eckd(td->targettype) && checkparm != 5)) {
|
error = "Inconsistent script output";
|
||||||
error_reason("Target parameters missing from script");
|
/*
|
||||||
return -1;
|
* First, calculate total number of groups
|
||||||
|
*/
|
||||||
|
td->nr_targets = 0;
|
||||||
|
for (i = 0; i < MAX_TARGETS; i++) {
|
||||||
|
t = target_at(td, i);
|
||||||
|
if (t->check_params == 0)
|
||||||
|
break;
|
||||||
|
td->nr_targets++;
|
||||||
|
}
|
||||||
|
if (!td->nr_targets)
|
||||||
|
/* No keywords found in the stream */
|
||||||
|
goto error;
|
||||||
|
/*
|
||||||
|
* Each group has to include targetbase, targettype,
|
||||||
|
* targetblocksize and targetoffset.
|
||||||
|
*/
|
||||||
|
if (td->nr_targets != idx[TARGET_BASE] ||
|
||||||
|
td->nr_targets != idx[TARGET_TYPE] ||
|
||||||
|
td->nr_targets != idx[TARGET_BLOCKSIZE] ||
|
||||||
|
td->nr_targets != idx[TARGET_OFFSET])
|
||||||
|
goto error;
|
||||||
|
/*
|
||||||
|
* In addition, any group of "ECKD" type has to include
|
||||||
|
* targetgeometry
|
||||||
|
*/
|
||||||
|
for (i = 0; i < td->nr_targets; i++) {
|
||||||
|
t = target_at(td, i);
|
||||||
|
assert(t->check_params >= 4);
|
||||||
|
if (disk_is_eckd(t->targettype) && t->check_params != 5)
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
error:
|
||||||
|
error_reason("%s", error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_base_disk_params(struct job_target_data *td, int index)
|
||||||
|
{
|
||||||
|
disk_type_t type = get_targettype(td, index);
|
||||||
|
|
||||||
|
if (!verbose)
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Base disk '%s':\n", get_targetbase(td, index));
|
||||||
|
fprintf(stderr, " layout........: %s\n", disk_get_type_name(type));
|
||||||
|
}
|
||||||
|
if (disk_is_eckd(type)) {
|
||||||
|
fprintf(stderr, " heads.........: %u\n", get_targetheads(td, index));
|
||||||
|
fprintf(stderr, " sectors.......: %u\n", get_targetsectors(td, index));
|
||||||
|
fprintf(stderr, " cylinders.....: %u\n", get_targetcylinders(td, index));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
fprintf(stderr, " start.........: %lu\n", get_targetoffset(td, index));
|
||||||
|
fprintf(stderr, " blksize.......: %u\n", get_targetblocksize(td, index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,31 +326,57 @@ static int disk_set_info_by_hint(struct job_target_data *td,
|
|||||||
{
|
{
|
||||||
int majnum, minnum;
|
int majnum, minnum;
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
|
int i;
|
||||||
|
/*
|
||||||
|
* Currently multiple base disks with different parameters
|
||||||
|
* are not supported
|
||||||
|
*/
|
||||||
data->devno = -1;
|
data->devno = -1;
|
||||||
data->phy_block_size = td->targetblocksize;
|
data->phy_block_size = get_targetblocksize(td, 0);
|
||||||
data->type = td->targettype;
|
data->type = get_targettype(td, 0);
|
||||||
data->partnum = 0;
|
|
||||||
|
|
||||||
if (sscanf(td->targetbase, "%d:%d", &majnum, &minnum) == 2) {
|
assert(td->nr_targets != 0);
|
||||||
data->device = makedev(majnum, minnum);
|
for (i = 1; i < td->nr_targets; i++) {
|
||||||
data->targetbase = defined_as_device;
|
if (data->type != get_targettype(td, i) ||
|
||||||
data->partnum = minor(stats.st_rdev) - minnum;
|
data->phy_block_size != get_targetblocksize(td, i)) {
|
||||||
} else {
|
print_base_disk_params(td, 0);
|
||||||
if (stat(td->targetbase, &stats)) {
|
print_base_disk_params(td, i);
|
||||||
error_reason(strerror(errno));
|
error_reason("Inconsistent base disk geometry in target device");
|
||||||
error_text("Could not get information for "
|
|
||||||
"file '%s'", td->targetbase);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!S_ISBLK(stats.st_mode)) {
|
}
|
||||||
error_reason("Target base device '%s' is not "
|
data->partnum = 0;
|
||||||
"a block device",
|
data->targetbase_def = undefined;
|
||||||
td->targetbase);
|
|
||||||
|
for (i = 0; i < td->nr_targets; i++) {
|
||||||
|
definition_t defined_as;
|
||||||
|
|
||||||
|
if (sscanf(get_targetbase(td, i),
|
||||||
|
"%d:%d", &majnum, &minnum) == 2) {
|
||||||
|
data->basedisks[i] = makedev(majnum, minnum);
|
||||||
|
defined_as = defined_as_device;
|
||||||
|
} else {
|
||||||
|
if (stat(get_targetbase(td, i), &stats)) {
|
||||||
|
error_reason(strerror(errno));
|
||||||
|
error_text("Could not get information for "
|
||||||
|
"file '%s'", get_targetbase(td, i));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!S_ISBLK(stats.st_mode)) {
|
||||||
|
error_reason("Target base device '%s' is not "
|
||||||
|
"a block device",
|
||||||
|
get_targetbase(td, i));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->basedisks[i] = stats.st_rdev;
|
||||||
|
defined_as = defined_as_name;
|
||||||
|
}
|
||||||
|
if (data->targetbase_def != undefined &&
|
||||||
|
data->targetbase_def != defined_as) {
|
||||||
|
error_reason("Target base disks are defined by different ways");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
data->device = stats.st_rdev;
|
data->targetbase_def = defined_as;
|
||||||
data->targetbase = defined_as_name;
|
|
||||||
}
|
}
|
||||||
if (data->type == disk_type_scsi && ioctl(fd, NVME_IOCTL_ID) >= 0)
|
if (data->type == disk_type_scsi && ioctl(fd, NVME_IOCTL_ID) >= 0)
|
||||||
data->is_nvme = 1;
|
data->is_nvme = 1;
|
||||||
@@ -446,11 +563,28 @@ static int run_targetbase_script(struct job_target_data *td,
|
|||||||
static int disk_set_geometry_by_hint(struct job_target_data *td,
|
static int disk_set_geometry_by_hint(struct job_target_data *td,
|
||||||
struct disk_info *data)
|
struct disk_info *data)
|
||||||
{
|
{
|
||||||
data->geo.heads = td->targetheads;
|
int i;
|
||||||
data->geo.sectors = td->targetsectors;
|
/*
|
||||||
data->geo.cylinders = td->targetcylinders;
|
* Currently multiple base disks with different parameters
|
||||||
data->geo.start = td->targetoffset;
|
* are not supported
|
||||||
|
*/
|
||||||
|
data->geo.heads = get_targetheads(td, 0);
|
||||||
|
data->geo.sectors = get_targetsectors(td, 0);
|
||||||
|
data->geo.cylinders = get_targetcylinders(td, 0);
|
||||||
|
data->geo.start = get_targetoffset(td, 0);
|
||||||
|
|
||||||
|
assert(td->nr_targets != 0);
|
||||||
|
for (i = 1; i < td->nr_targets; i++) {
|
||||||
|
if (data->geo.heads != get_targetheads(td, i) ||
|
||||||
|
data->geo.sectors != get_targetsectors(td, i) ||
|
||||||
|
data->geo.cylinders != get_targetcylinders(td, i) ||
|
||||||
|
data->geo.start != get_targetoffset(td, i)) {
|
||||||
|
print_base_disk_params(td, 0);
|
||||||
|
print_base_disk_params(td, i);
|
||||||
|
error_reason("Inconsistent base disk geometry in target device");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,14 +649,16 @@ static int disk_set_info_complete(struct job_target_data *td,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare INFO required to perform IPL installation on the physical
|
* Prepare INFO required to perform IPL installation on physical disks
|
||||||
* disk where the logical DEVICE is located.
|
* participating in the logical DEVICE.
|
||||||
* Preparation is performed in 2 steps:
|
* Preparation is performed in 2 steps:
|
||||||
*
|
*
|
||||||
* 1. Find out a physical "base" disk where the logical DEVICE is
|
* 1. Find out a set of physical "base" disks participating in the
|
||||||
* located. Calculate "target" parameters (type, geometry, physical
|
* logical DEVICE. For each found disk calculate "target" parameters
|
||||||
* block size, data offset, etc);
|
* (type, geometry, physical block size, data offset, etc) and store
|
||||||
* 2. Complete INFO by the found base disk and target parameters.
|
* it in the array of "targets" of TD;
|
||||||
|
* 2. Complete INFO using the found base disks and calculated target
|
||||||
|
* parameters.
|
||||||
*
|
*
|
||||||
* TD: optionally contains target parameters specified by user via
|
* TD: optionally contains target parameters specified by user via
|
||||||
* config file, or special "target options" of zipl tool.
|
* config file, or special "target options" of zipl tool.
|
||||||
@@ -569,6 +705,7 @@ int disk_get_info(const char *device, struct job_target_data *td,
|
|||||||
goto error;
|
goto error;
|
||||||
if (disk_set_info_by_hint(td, data, fd))
|
if (disk_set_info_by_hint(td, data, fd))
|
||||||
goto error;
|
goto error;
|
||||||
|
data->device = stats.st_rdev;
|
||||||
break;
|
break;
|
||||||
case source_user:
|
case source_user:
|
||||||
/*
|
/*
|
||||||
@@ -581,6 +718,12 @@ int disk_get_info(const char *device, struct job_target_data *td,
|
|||||||
goto error;
|
goto error;
|
||||||
if (disk_set_info_by_hint(td, data, fd))
|
if (disk_set_info_by_hint(td, data, fd))
|
||||||
goto error;
|
goto error;
|
||||||
|
/*
|
||||||
|
* multiple base disks are not supported
|
||||||
|
* with this source type
|
||||||
|
*/
|
||||||
|
assert(td->nr_targets == 1);
|
||||||
|
data->device = data->basedisks[0];
|
||||||
break;
|
break;
|
||||||
case source_auto:
|
case source_auto:
|
||||||
/* no ready target parameters are available */
|
/* no ready target parameters are available */
|
||||||
@@ -588,6 +731,12 @@ int disk_get_info(const char *device, struct job_target_data *td,
|
|||||||
goto error;
|
goto error;
|
||||||
if (disk_set_info_auto(data, &stats, fd))
|
if (disk_set_info_auto(data, &stats, fd))
|
||||||
goto error;
|
goto error;
|
||||||
|
/*
|
||||||
|
* multiple base disks are not supported
|
||||||
|
* with this source type
|
||||||
|
*/
|
||||||
|
data->basedisks[0] = data->device;
|
||||||
|
td->nr_targets = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -943,6 +1092,33 @@ disk_print_devt(dev_t d)
|
|||||||
printf("%02x:%02x", major(d), minor(d));
|
printf("%02x:%02x", major(d), minor(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disk_print_devname(dev_t dev)
|
||||||
|
{
|
||||||
|
struct util_proc_part_entry part_entry;
|
||||||
|
|
||||||
|
if (!util_proc_part_get_entry(dev, &part_entry)) {
|
||||||
|
printf("%s", part_entry.name);
|
||||||
|
util_proc_part_free_entry(&part_entry);
|
||||||
|
} else {
|
||||||
|
disk_print_devt(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare_footnote_ptr(int source, char *ptr)
|
||||||
|
{
|
||||||
|
if (source == source_user || source == source_script)
|
||||||
|
strcpy(ptr, " *)");
|
||||||
|
else
|
||||||
|
strcpy(ptr, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_footnote_ref(int source, const char *prefix)
|
||||||
|
{
|
||||||
|
if (source == source_user)
|
||||||
|
printf("%s*) Data provided by user.\n", prefix);
|
||||||
|
else if (source == source_script)
|
||||||
|
printf("%s*) Data provided by script.\n", prefix);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a name for a given disk TYPE. */
|
/* Return a name for a given disk TYPE. */
|
||||||
char *
|
char *
|
||||||
@@ -994,12 +1170,11 @@ disk_is_large_volume(struct disk_info* info)
|
|||||||
void disk_print_info(struct disk_info *info, int source)
|
void disk_print_info(struct disk_info *info, int source)
|
||||||
{
|
{
|
||||||
char footnote[4] = "";
|
char footnote[4] = "";
|
||||||
if (source == source_user || source == source_script)
|
|
||||||
strcpy(footnote, " *)");
|
|
||||||
|
|
||||||
|
prepare_footnote_ptr(source, footnote);
|
||||||
printf(" Device..........................: ");
|
printf(" Device..........................: ");
|
||||||
disk_print_devt(info->device);
|
disk_print_devt(info->device);
|
||||||
if (info->targetbase == defined_as_device)
|
if (info->targetbase_def == defined_as_device)
|
||||||
printf("%s", footnote);
|
printf("%s", footnote);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (info->partnum != 0) {
|
if (info->partnum != 0) {
|
||||||
@@ -1010,7 +1185,7 @@ void disk_print_info(struct disk_info *info, int source)
|
|||||||
if (info->name) {
|
if (info->name) {
|
||||||
printf(" Device name.....................: %s",
|
printf(" Device name.....................: %s",
|
||||||
info->name);
|
info->name);
|
||||||
if (info->targetbase == defined_as_name)
|
if (info->targetbase_def == defined_as_name)
|
||||||
printf("%s", footnote);
|
printf("%s", footnote);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@@ -1053,21 +1228,7 @@ void disk_print_info(struct disk_info *info, int source)
|
|||||||
info->phy_block_size, footnote);
|
info->phy_block_size, footnote);
|
||||||
printf(" Device size in physical blocks..: %ld\n",
|
printf(" Device size in physical blocks..: %ld\n",
|
||||||
(long) info->phy_blocks);
|
(long) info->phy_blocks);
|
||||||
if (source == source_user)
|
print_footnote_ref(source, " ");
|
||||||
printf(" *) Data provided by user.\n");
|
|
||||||
if (source == source_script)
|
|
||||||
printf(" *) Data provided by script.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print textual representation of geo structure. */
|
|
||||||
void
|
|
||||||
disk_print_geo(struct disk_info *data)
|
|
||||||
{
|
|
||||||
printf(" geo.heads.........:%u\n", data->geo.heads);
|
|
||||||
printf(" geo.sectors.......:%u\n", data->geo.sectors);
|
|
||||||
printf(" geo.cylinders.....:%u\n", data->geo.cylinders);
|
|
||||||
printf(" geo.start.........:%lu\n", data->geo.start);
|
|
||||||
printf(" blksize...........:%u\n", data->phy_block_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether a block is a zero block which identifies a hole in a file.
|
/* Check whether a block is a zero block which identifies a hole in a file.
|
||||||
|
|||||||
@@ -434,11 +434,14 @@ int install_bootloader(struct job_data *job, struct install_set *bis)
|
|||||||
{
|
{
|
||||||
disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr;
|
disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr;
|
||||||
struct disk_info *info = bis->info;
|
struct disk_info *info = bis->info;
|
||||||
char *device = bis->device;
|
char footnote[4];
|
||||||
int fd, rc;
|
int rc;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!info)
|
if (!info)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
prepare_footnote_ptr(job->target.source, footnote);
|
||||||
/* Inform user about what we're up to */
|
/* Inform user about what we're up to */
|
||||||
printf("Preparing boot device for %s%s: ",
|
printf("Preparing boot device for %s%s: ",
|
||||||
disk_get_ipl_type(info->type,
|
disk_get_ipl_type(info->type,
|
||||||
@@ -455,40 +458,58 @@ int install_bootloader(struct job_data *job, struct install_set *bis)
|
|||||||
disk_print_devt(info->device);
|
disk_print_devt(info->device);
|
||||||
printf(".\n");
|
printf(".\n");
|
||||||
}
|
}
|
||||||
/* Open device file */
|
/* Install independently on each physical target base */
|
||||||
fd = open(device, O_RDWR);
|
|
||||||
if (fd == -1) {
|
|
||||||
error_reason(strerror(errno));
|
|
||||||
error_text("Could not open temporary device file '%s'",
|
|
||||||
device);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* Ensure that potential cache inconsistencies between disk and
|
|
||||||
* partition are resolved by flushing the corresponding buffers. */
|
|
||||||
if (!dry_run) {
|
|
||||||
if (ioctl(fd, BLKFLSBUF)) {
|
|
||||||
fprintf(stderr, "Warning: Could not flush disk "
|
|
||||||
"caches.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Depending on disk type, install one or two program tables
|
|
||||||
* for CCW-type IPL and (or) for List-Directed IPL (see the
|
|
||||||
* picture in comments above)
|
|
||||||
*/
|
|
||||||
if (job->id == job_dump_partition) {
|
|
||||||
rc = install_bootloader_dump(bis->tables, info,
|
|
||||||
scsi_dump_sb_blockptr,
|
|
||||||
is_ngdump_enabled(job),
|
|
||||||
fd);
|
|
||||||
} else {
|
|
||||||
rc = install_bootloader_ipl(bis->tables, info, fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsync(fd))
|
for (i = 0; i < job_get_nr_targets(job); i++) {
|
||||||
error_text("Could not sync device file '%s'", device);
|
int fd;
|
||||||
if (close(fd))
|
|
||||||
error_text("Could not close device file '%s'", device);
|
if (verbose) {
|
||||||
|
printf("Installing on base disk: ");
|
||||||
|
disk_print_devname(info->basedisks[i]);
|
||||||
|
printf("%s.\n", footnote);
|
||||||
|
}
|
||||||
|
/* Open device file */
|
||||||
|
fd = open(bis->basetmp[i], O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
error_reason(strerror(errno));
|
||||||
|
error_text("Could not open temporary device file '%s'",
|
||||||
|
bis->basetmp[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Ensure that potential cache inconsistencies between disk and
|
||||||
|
* partition are resolved by flushing the corresponding buffers.
|
||||||
|
*/
|
||||||
|
if (!dry_run) {
|
||||||
|
if (ioctl(fd, BLKFLSBUF)) {
|
||||||
|
fprintf(stderr, "Warning: Could not flush disk "
|
||||||
|
"caches.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Depending on disk type, install one or two program tables
|
||||||
|
* for CCW-type IPL and (or) for List-Directed IPL (see the
|
||||||
|
* picture in comments above)
|
||||||
|
*/
|
||||||
|
if (job->id == job_dump_partition) {
|
||||||
|
rc = install_bootloader_dump(bis->tables, info,
|
||||||
|
scsi_dump_sb_blockptr,
|
||||||
|
is_ngdump_enabled(job),
|
||||||
|
fd);
|
||||||
|
} else {
|
||||||
|
rc = install_bootloader_ipl(bis->tables, info,
|
||||||
|
fd);
|
||||||
|
}
|
||||||
|
if (fsync(fd))
|
||||||
|
error_text("Could not sync device file '%s'",
|
||||||
|
bis->basetmp[i]);
|
||||||
|
if (close(fd))
|
||||||
|
error_text("Could not close device file '%s'",
|
||||||
|
bis->basetmp[i]);
|
||||||
|
if (rc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
print_footnote_ref(job->target.source, "");
|
||||||
|
|
||||||
if (!dry_run && rc == 0) {
|
if (!dry_run && rc == 0) {
|
||||||
if (info->devno >= 0)
|
if (info->devno >= 0)
|
||||||
|
|||||||
@@ -369,11 +369,13 @@ get_command_line(int argc, char* argv[], struct command_line* line)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void free_target_data(struct job_target_data *data)
|
void free_target_data(struct job_target_data *data)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
free(data->bootmap_dir);
|
free(data->bootmap_dir);
|
||||||
free(data->targetbase);
|
for (i = 0; i < data->nr_targets; i++)
|
||||||
|
free(get_targetbase(data, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1345,6 +1347,27 @@ type_from_target(char *target, disk_type_t *type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int set_targettype(struct job_target_data *data, int index, char *value)
|
||||||
|
{
|
||||||
|
return type_from_target(value,
|
||||||
|
&target_at(data, index)->targettype);
|
||||||
|
}
|
||||||
|
|
||||||
|
int job_set_targettype(struct job_data *job, char *value)
|
||||||
|
{
|
||||||
|
return set_targettype(&job->target, 0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int job_set_target(struct job_data *job, char *value)
|
||||||
|
{
|
||||||
|
job_set_targetbase(job, value);
|
||||||
|
if (!job_get_targetbase(job))
|
||||||
|
return -1;
|
||||||
|
job_set_nr_targets(job, 1);
|
||||||
|
job->target.source = source_user;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
||||||
{
|
{
|
||||||
@@ -1361,32 +1384,28 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
|||||||
return -1;
|
return -1;
|
||||||
/* Fill in target */
|
/* Fill in target */
|
||||||
if (data[(int) scan_keyword_targetbase] != NULL) {
|
if (data[(int) scan_keyword_targetbase] != NULL) {
|
||||||
job->target.targetbase =
|
if (job_set_target(job, misc_strdup(data[(int)
|
||||||
misc_strdup(data[(int)
|
scan_keyword_targetbase])))
|
||||||
scan_keyword_targetbase]);
|
|
||||||
if (job->target.targetbase == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
job->target.source = source_user;
|
|
||||||
}
|
}
|
||||||
if (data[(int) scan_keyword_targettype] != NULL) {
|
if (data[(int) scan_keyword_targettype] != NULL) {
|
||||||
if (type_from_target(
|
if (job_set_targettype(job,
|
||||||
data[(int) scan_keyword_targettype],
|
data[(int) scan_keyword_targettype]))
|
||||||
&job->target.targettype))
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (data[(int) scan_keyword_targetgeometry] != NULL) {
|
if (data[(int) scan_keyword_targetgeometry] != NULL) {
|
||||||
job->target.targetcylinders =
|
job_set_targetcylinders(job,
|
||||||
atoi(strtok(data[(int)
|
atoi(strtok(data[(int)
|
||||||
scan_keyword_targetgeometry], ","));
|
scan_keyword_targetgeometry], ",")));
|
||||||
job->target.targetheads = atoi(strtok(NULL, ","));
|
job_set_targetheads(job, atoi(strtok(NULL, ",")));
|
||||||
job->target.targetsectors = atoi(strtok(NULL, ","));
|
job_set_targetsectors(job, atoi(strtok(NULL, ",")));
|
||||||
}
|
}
|
||||||
if (data[(int) scan_keyword_targetblocksize] != NULL)
|
if (data[(int) scan_keyword_targetblocksize] != NULL)
|
||||||
job->target.targetblocksize =
|
job_set_targetblocksize(job,
|
||||||
atoi(data[(int) scan_keyword_targetblocksize]);
|
atoi(data[(int) scan_keyword_targetblocksize]));
|
||||||
if (data[(int) scan_keyword_targetoffset] != NULL)
|
if (data[(int) scan_keyword_targetoffset] != NULL)
|
||||||
job->target.targetoffset =
|
job_set_targetoffset(job,
|
||||||
atol(data[(int) scan_keyword_targetoffset]);
|
atol(data[(int) scan_keyword_targetoffset]));
|
||||||
/* Fill in name and address of image file */
|
/* Fill in name and address of image file */
|
||||||
|
|
||||||
job->data.ipl.common.image = misc_strdup(
|
job->data.ipl.common.image = misc_strdup(
|
||||||
@@ -1614,37 +1633,32 @@ get_menu_job(struct scan_token* scan, char* menu, struct job_data* job)
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
case scan_keyword_targetbase:
|
case scan_keyword_targetbase:
|
||||||
job->target.targetbase = misc_strdup(
|
if (job_set_target(job, misc_strdup(
|
||||||
scan[i].content.keyword.value);
|
scan[i].content.keyword.value)))
|
||||||
if (job->target.targetbase == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
job->target.source = source_user;
|
|
||||||
break;
|
break;
|
||||||
case scan_keyword_targettype:
|
case scan_keyword_targettype:
|
||||||
if (type_from_target(
|
if (job_set_targettype(job,
|
||||||
scan[i].content.keyword.value,
|
scan[i].content.keyword.value))
|
||||||
&job->target.targettype))
|
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
case scan_keyword_targetgeometry:
|
case scan_keyword_targetgeometry:
|
||||||
job->target.targetcylinders =
|
job_set_targetcylinders(job,
|
||||||
atoi(strtok(
|
atoi(strtok(
|
||||||
scan[i].content.keyword.value,
|
scan[i].content.keyword.value,
|
||||||
","));
|
",")));
|
||||||
job->target.targetheads =
|
job_set_targetheads(job,
|
||||||
atoi(strtok(NULL, ","));
|
atoi(strtok(NULL, ",")));
|
||||||
job->target.targetsectors =
|
job_set_targetsectors(job,
|
||||||
atoi(strtok(NULL, ","));
|
atoi(strtok(NULL, ",")));
|
||||||
break;
|
break;
|
||||||
case scan_keyword_targetblocksize:
|
case scan_keyword_targetblocksize:
|
||||||
job->target.targetblocksize =
|
job_set_targetblocksize(job, atoi(
|
||||||
atoi(
|
scan[i].content.keyword.value));
|
||||||
scan[i].content.keyword.value);
|
|
||||||
break;
|
break;
|
||||||
case scan_keyword_targetoffset:
|
case scan_keyword_targetoffset:
|
||||||
job->target.targetoffset =
|
job_set_targetoffset(job, atol(
|
||||||
atol(
|
scan[i].content.keyword.value));
|
||||||
scan[i].content.keyword.value);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Should not happen */
|
/* Should not happen */
|
||||||
|
|||||||
Reference in New Issue
Block a user