From fae7b1bcb5eab5c470b15fd8c491f42244210837 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Mon, 23 Jul 2012 18:47:42 +0200 Subject: [PATCH] fdisk: API: add write to label operations [kzak@redhat.com: - rename functions - use errno] Signed-off-by: Karel Zak Signed-off-by: Davidlohr Bueso --- fdisks/fdisk.c | 23 +++++-------------- fdisks/fdisk.h | 10 +++------ fdisks/fdiskaixlabel.c | 1 + fdisks/fdiskbsdlabel.c | 30 +++++++++++++------------ fdisks/fdiskdoslabel.c | 25 +++++++++++++++++---- fdisks/fdiskdoslabel.h | 1 - fdisks/fdiskmaclabel.c | 1 + fdisks/fdisksgilabel.c | 50 ++++++++++++++++++++++++++++-------------- fdisks/fdisksgilabel.h | 1 - fdisks/fdisksunlabel.c | 9 +++++--- fdisks/fdisksunlabel.h | 1 - fdisks/utils.c | 16 ++++++++++++++ 12 files changed, 104 insertions(+), 64 deletions(-) diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c index ec31b14d8..f25f2aec0 100644 --- a/fdisks/fdisk.c +++ b/fdisks/fdisk.c @@ -1420,24 +1420,13 @@ static void new_partition(struct fdisk_context *cxt) dos_new_partition(cxt); } -static void -write_table(struct fdisk_context *cxt) { - int i; +static void write_table(struct fdisk_context *cxt) +{ + int rc; - if (disklabel == DOS_LABEL) - dos_write_table(cxt); - else if (disklabel == SGI_LABEL) - /* no test on change? the printf below might be mistaken */ - sgi_write_table(cxt); - else if (disklabel == SUN_LABEL) { - int needw = 0; - - for (i=0; i<8; i++) - if (ptes[i].changed) - needw = 1; - if (needw) - sun_write_table(cxt); - } + rc = fdisk_write_disklabel(cxt); + if (rc) + err(EXIT_FAILURE, _("cannot write disk label")); printf(_("The partition table has been altered!\n\n")); reread_partition_table(cxt, 1); diff --git a/fdisks/fdisk.h b/fdisks/fdisk.h index 2a04b8372..9ce2c25b0 100644 --- a/fdisks/fdisk.h +++ b/fdisks/fdisk.h @@ -137,6 +137,8 @@ struct fdisk_label { /* probe disk label */ int (*probe)(struct fdisk_context *cxt); + /* write in-memory changes to disk */ + int (*write)(struct fdisk_context *cxt); /* delete partition */ void (*part_delete)(struct fdisk_context *cxt, int partnum); }; @@ -163,6 +165,7 @@ extern int fdisk_context_set_user_geometry(struct fdisk_context *cxt, unsigned int sectors); extern int fdisk_create_default_disklabel(struct fdisk_context *cxt); extern int fdisk_delete_partition(struct fdisk_context *cxt, int partnum); +extern int fdisk_write_disklabel(struct fdisk_context *cxt); /* prototypes for fdisk.c */ extern char *disk_device, *line_ptr; @@ -265,13 +268,6 @@ static inline void read_sector(struct fdisk_context *cxt, sector_t secno, unsign fatal(cxt, unable_to_read); } -static inline void write_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf) -{ - seek_sector(cxt, secno); - if (write(cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size) - fatal(cxt, unable_to_write); -} - static inline sector_t get_start_sect(struct partition *p) { return read4_little_endian(p->start4); diff --git a/fdisks/fdiskaixlabel.c b/fdisks/fdiskaixlabel.c index 658b7e4cf..c8cb660e0 100644 --- a/fdisks/fdiskaixlabel.c +++ b/fdisks/fdiskaixlabel.c @@ -69,5 +69,6 @@ const struct fdisk_label aix_label = { .name = "aix", .probe = aix_probe_label, + .write = NULL, .part_delete = NULL, }; diff --git a/fdisks/fdiskbsdlabel.c b/fdisks/fdiskbsdlabel.c index ae83d2e7f..50bd840d7 100644 --- a/fdisks/fdiskbsdlabel.c +++ b/fdisks/fdiskbsdlabel.c @@ -63,7 +63,6 @@ static void xbsd_delete_part (struct fdisk_context *cxt, int partnum); static void xbsd_new_part (struct fdisk_context *cxt); -static void xbsd_write_disklabel (struct fdisk_context *cxt); static int xbsd_create_disklabel (struct fdisk_context *cxt); static void xbsd_edit_disklabel (void); static void xbsd_write_bootstrap (struct fdisk_context *cxt); @@ -140,6 +139,21 @@ is_bsd_partition_type(int type) { } #endif +static int xbsd_write_disklabel (struct fdisk_context *cxt) +{ +#if defined (__alpha__) + printf (_("Writing disklabel to %s.\n"), cxt->dev_path); + xbsd_writelabel (cxt, NULL, &xbsd_dlabel); +#else + printf (_("Writing disklabel to %s.\n"), + partname(cxt->dev_path, xbsd_part_index+1, 0)); + xbsd_writelabel (cxt, xbsd_part, &xbsd_dlabel); +#endif + reread_partition_table(cxt, 0); /* no exit yet */ + + return 0; +} + void bsd_command_prompt (struct fdisk_context *cxt) { @@ -376,19 +390,6 @@ xbsd_print_disklabel (struct fdisk_context *cxt, int show_all) { } } -static void -xbsd_write_disklabel (struct fdisk_context *cxt) { -#if defined (__alpha__) - printf (_("Writing disklabel to %s.\n"), cxt->dev_path); - xbsd_writelabel (cxt, NULL, &xbsd_dlabel); -#else - printf (_("Writing disklabel to %s.\n"), - partname(cxt->dev_path, xbsd_part_index+1, 0)); - xbsd_writelabel (cxt, xbsd_part, &xbsd_dlabel); -#endif - reread_partition_table(cxt, 0); /* no exit yet */ -} - static int xbsd_create_disklabel (struct fdisk_context *cxt) { char c; @@ -846,5 +847,6 @@ const struct fdisk_label bsd_label = { .name = "bsd", .probe = osf_probe_label, + .write = xbsd_write_disklabel, .part_delete = xbsd_delete_part, }; diff --git a/fdisks/fdiskdoslabel.c b/fdisks/fdiskdoslabel.c index d9369b691..398e5e040 100644 --- a/fdisks/fdiskdoslabel.c +++ b/fdisks/fdiskdoslabel.c @@ -706,9 +706,18 @@ void dos_new_partition(struct fdisk_context *cxt) } } -void dos_write_table(struct fdisk_context *cxt) +static int write_sector(struct fdisk_context *cxt, sector_t secno, + unsigned char *buf) { - int i; + seek_sector(cxt, secno); + if (write(cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size) + return -errno; + return 0; +} + +static int dos_write_disklabel(struct fdisk_context *cxt) +{ + int i, rc = 0; /* MBR (primary partitions) */ if (!MBRbuffer_changed) { @@ -718,7 +727,9 @@ void dos_write_table(struct fdisk_context *cxt) } if (MBRbuffer_changed) { mbr_set_magic(cxt->firstsector); - write_sector(cxt, 0, cxt->firstsector); + rc = write_sector(cxt, 0, cxt->firstsector); + if (rc) + goto done; } /* EBR (logical partitions) */ for (i = 4; i < partitions; i++) { @@ -726,14 +737,20 @@ void dos_write_table(struct fdisk_context *cxt) if (pe->changed) { mbr_set_magic(pe->sectorbuffer); - write_sector(cxt, pe->offset, pe->sectorbuffer); + rc = write_sector(cxt, pe->offset, pe->sectorbuffer); + if (rc) + goto done; } } + +done: + return rc; } const struct fdisk_label dos_label = { .name = "dos", .probe = dos_probe_label, + .write = dos_write_disklabel, .part_delete = dos_delete_partition, }; diff --git a/fdisks/fdiskdoslabel.h b/fdisks/fdiskdoslabel.h index 2d3620019..d7361a806 100644 --- a/fdisks/fdiskdoslabel.h +++ b/fdisks/fdiskdoslabel.h @@ -44,7 +44,6 @@ extern int is_dos_partition(int t); extern void dos_init(struct fdisk_context *cxt); extern void dos_add_partition(struct fdisk_context *cxt, int n, int sys); extern void dos_new_partition(struct fdisk_context *cxt); -extern void dos_write_table(struct fdisk_context *cxt); extern int mbr_is_valid_magic(unsigned char *b); diff --git a/fdisks/fdiskmaclabel.c b/fdisks/fdiskmaclabel.c index c579a58f1..4e80d395b 100644 --- a/fdisks/fdiskmaclabel.c +++ b/fdisks/fdiskmaclabel.c @@ -84,5 +84,6 @@ const struct fdisk_label mac_label = { .name = "mac", .probe = mac_probe_label, + .write = NULL, .part_delete = NULL, }; diff --git a/fdisks/fdisksgilabel.c b/fdisks/fdisksgilabel.c index 0ee3a83af..836b9d4a7 100644 --- a/fdisks/fdisksgilabel.c +++ b/fdisks/fdisksgilabel.c @@ -39,6 +39,8 @@ static int other_endian = 0; static int debug = 0; static short volumes=1; +static sgiinfo *fill_sgiinfo(void); + /* * only dealing with free blocks here */ @@ -328,10 +330,11 @@ create_sgiinfo(struct fdisk_context *cxt) { strncpy((char *) sgilabel->directory[0].vol_file_name, "sgilabel", 8); } -sgiinfo *fill_sgiinfo(void); -void -sgi_write_table(struct fdisk_context *cxt) { +static int sgi_write_disklabel(struct fdisk_context *cxt) +{ + sgiinfo *info = NULL; + sgilabel->csum = 0; sgilabel->csum = SSWAP32(two_s_complement_32bit_sum( (unsigned int*)sgilabel, @@ -339,23 +342,34 @@ sgi_write_table(struct fdisk_context *cxt) { assert(two_s_complement_32bit_sum( (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0); if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0) - fatal(cxt, unable_to_seek); + goto err; if (write(cxt->dev_fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE) - fatal(cxt, unable_to_write); - if (! strncmp((char *) sgilabel->directory[0].vol_file_name, "sgilabel", 8)) { + goto err; + if (!strncmp((char *) sgilabel->directory[0].vol_file_name, "sgilabel", 8)) { /* * keep this habit of first writing the "sgilabel". * I never tested whether it works without (AN 981002). */ - sgiinfo *info = fill_sgiinfo(); - int infostartblock = SSWAP32(sgilabel->directory[0].vol_file_start); - if (lseek(cxt->dev_fd, (off_t) infostartblock* - SECTOR_SIZE, SEEK_SET) < 0) - fatal(cxt, unable_to_seek); + int infostartblock + = SSWAP32(sgilabel->directory[0].vol_file_start); + + if (lseek(cxt->dev_fd, (off_t) infostartblock * + SECTOR_SIZE, SEEK_SET) < 0) + goto err; + + info = fill_sgiinfo(); + if (!info) + goto err; + if (write(cxt->dev_fd, info, SECTOR_SIZE) != SECTOR_SIZE) - fatal(cxt, unable_to_write); - free(info); + goto err; } + + free(info); + return 0; +err: + free(info); + return -errno; } static int @@ -865,10 +879,13 @@ sgi_set_ncyl(void) /* _____________________________________________________________ */ -sgiinfo * -fill_sgiinfo(void) +static sgiinfo *fill_sgiinfo(void) { - sgiinfo *info=xcalloc(1, sizeof(sgiinfo)); + sgiinfo *info = calloc(1, sizeof(sgiinfo)); + + if (!info) + return NULL; + info->magic=SSWAP32(SGI_INFO_MAGIC); info->b1=SSWAP32(-1); info->b2=SSWAP16(-1); @@ -885,5 +902,6 @@ const struct fdisk_label sgi_label = { .name = "sgi", .probe = sgi_probe_label, + .write = sgi_write_disklabel, .part_delete = sgi_delete_partition, }; diff --git a/fdisks/fdisksgilabel.h b/fdisks/fdisksgilabel.h index 96e96548e..412ec7422 100644 --- a/fdisks/fdisksgilabel.h +++ b/fdisks/fdisksgilabel.h @@ -120,7 +120,6 @@ extern void sgi_add_partition( struct fdisk_context *cxt, int n, int sys ); extern void create_sgilabel( struct fdisk_context *cxt ); extern void create_sgiinfo(struct fdisk_context *cxt); extern int verify_sgi(struct fdisk_context *cxt, int verbose ); -extern void sgi_write_table( struct fdisk_context *cxt ); extern void sgi_set_ilfact( void ); extern void sgi_set_rspeed( void ); extern void sgi_set_pcylcount( void ); diff --git a/fdisks/fdisksunlabel.c b/fdisks/fdisksunlabel.c index 7c369f3e6..3b0b757ad 100644 --- a/fdisks/fdisksunlabel.c +++ b/fdisks/fdisksunlabel.c @@ -626,7 +626,7 @@ void sun_set_pcylcount(struct fdisk_context *cxt) _("Number of physical cylinders"))); } -void sun_write_table(struct fdisk_context *cxt) +static int sun_write_disklabel(struct fdisk_context *cxt) { unsigned short *ush = (unsigned short *)sunlabel; unsigned short csum = 0; @@ -635,9 +635,11 @@ void sun_write_table(struct fdisk_context *cxt) csum ^= *ush++; sunlabel->cksum = csum; if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0) - fatal(cxt, unable_to_seek); + return -errno; if (write(cxt->dev_fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE) - fatal(cxt, unable_to_write); + return -errno; + + return 0; } int sun_get_sysid(struct fdisk_context *cxt, int i) @@ -649,5 +651,6 @@ const struct fdisk_label sun_label = { .name = "sun", .probe = sun_probe_label, + .write = sun_write_disklabel, .part_delete = sun_delete_partition, }; diff --git a/fdisks/fdisksunlabel.h b/fdisks/fdisksunlabel.h index d416401ba..d33a5aa6f 100644 --- a/fdisks/fdisksunlabel.h +++ b/fdisks/fdisksunlabel.h @@ -82,7 +82,6 @@ extern int sun_change_sysid(struct fdisk_context *cxt, int i, uint16_t sys); extern void sun_list_table(struct fdisk_context *cxt, int xtra); extern void verify_sun(struct fdisk_context *cxt); extern void add_sun_partition(struct fdisk_context *cxt, int n, int sys); -extern void sun_write_table(struct fdisk_context *cxt); extern void sun_set_alt_cyl(struct fdisk_context *cxt); extern void sun_set_ncyl(struct fdisk_context *cxt, int cyl); extern void sun_set_xcyl(struct fdisk_context *cxt); diff --git a/fdisks/utils.c b/fdisks/utils.c index 932fa16f0..08f0fe6bd 100644 --- a/fdisks/utils.c +++ b/fdisks/utils.c @@ -47,6 +47,22 @@ static const struct fdisk_label *labels[] = &mac_label, }; +/** + * fdisk_write_disklabel + * @cxt: fdisk context + * + * Write in-memory changes to disk + * + * Returns 0 on success, otherwise, a corresponding error. + */ +int fdisk_write_disklabel(struct fdisk_context *cxt) +{ + if (!cxt) + return -EINVAL; + + return cxt->label->write(cxt); +} + /** * fdisk_delete_partition: * @cxt: fdisk context