diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 4bab260cf..dedb5f8b2 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -1,6 +1,7 @@ /* fdisk.c -- Partition table manipulator for Linux. * * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk) + * Copyright (C) 2012 Davidlohr Bueso * * This program is free software. You can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -50,7 +51,6 @@ #include "gpt.h" -unsigned char *MBRbuffer; int MBRbuffer_changed; #define hex_val(c) ({ \ @@ -231,10 +231,10 @@ void print_menu(enum menutype menu) } static int -get_sysid(int i) { +get_sysid(struct fdisk_context *cxt, int i) { return ( - disklabel == SUN_LABEL ? sun_get_sysid(i) : - disklabel == SGI_LABEL ? sgi_get_sysid(i) : + disklabel == SUN_LABEL ? sun_get_sysid(cxt, i) : + disklabel == SGI_LABEL ? sgi_get_sysid(cxt, i) : ptes[i].part_table->sys_ind); } @@ -439,8 +439,8 @@ void warn_alignment(struct fdisk_context *cxt) } static void -get_partition_table_geometry(void) { - unsigned char *bufp = MBRbuffer; +get_partition_table_geometry(struct fdisk_context *cxt) { + unsigned char *bufp = cxt->mbr; struct partition *p; int i, h, s, hh, ss; int first = 1; @@ -530,7 +530,7 @@ get_geometry(struct fdisk_context *cxt, struct geom *g) pt_heads = pt_sectors = 0; blkdev_get_geometry(cxt->dev_fd, &kern_heads, &kern_sectors); - get_partition_table_geometry(); + get_partition_table_geometry(cxt); heads = user_heads ? user_heads : pt_heads ? pt_heads : @@ -555,27 +555,6 @@ get_geometry(struct fdisk_context *cxt, struct geom *g) } } -/* - * Please, always use allocated buffer if you want to cast the buffer to - * any struct -- cast non-allocated buffer to any struct is against - * strict-aliasing rules. --kzak 16-Oct-2009 - */ -static void init_mbr_buffer(void) -{ - if (MBRbuffer) - return; - - MBRbuffer = xcalloc(1, MAX_SECTOR_SIZE); -} - -void zeroize_mbr_buffer(void) -{ - if (MBRbuffer) - memset(MBRbuffer, 0, MAX_SECTOR_SIZE); -} - - - /* * Read MBR. Returns: * -1: no 0xaa55 flag present (possibly entire disk BSD) @@ -585,25 +564,19 @@ void zeroize_mbr_buffer(void) static int get_boot(struct fdisk_context *cxt, int try_only) { disklabel = ANY_LABEL; - memset(MBRbuffer, 0, 512); - - if (512 != read(cxt->dev_fd, MBRbuffer, 512)) { - if (try_only) - return 1; - fatal(cxt, unable_to_read); - } get_geometry(cxt, NULL); update_units(); if (!check_dos_label(cxt)) - if (check_sun_label() || check_sgi_label() || check_aix_label() || check_mac_label()) + if (check_sun_label(cxt) || check_sgi_label(cxt) || check_aix_label(cxt) + || check_mac_label(cxt)) return 0; if (check_osf_label(cxt)) { /* intialize partitions for BSD as well */ dos_init(cxt); - if (!valid_part_table_flag(MBRbuffer)) { + if (!valid_part_table_flag(cxt->mbr)) { disklabel = OSF_LABEL; return 0; } @@ -879,7 +852,7 @@ get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt) { || (disklabel == SUN_LABEL && (!sunlabel->partitions[i].num_sectors || !sunlabel->part_tags[i].tag)) - || (disklabel == SGI_LABEL && (!sgi_get_num_sectors(i))) + || (disklabel == SGI_LABEL && (!sgi_get_num_sectors(cxt, i))) ) fprintf(stderr, _("Warning: partition %d has empty type\n"), @@ -983,7 +956,7 @@ delete_partition(struct fdisk_context *cxt, int i) if (disklabel == DOS_LABEL) dos_delete_partition(i); else if (disklabel == SUN_LABEL) - sun_delete_partition(i); + sun_delete_partition(cxt, i); else if (disklabel == SGI_LABEL) sgi_delete_partition(cxt, i); @@ -1001,7 +974,7 @@ static void change_sysid(struct fdisk_context *cxt) if (i == -1) return; p = ptes[i].part_table; - origsys = sys = get_sysid(i); + origsys = sys = get_sysid(cxt, i); /* if changing types T to 0 is allowed, then the reverse change must be allowed, too */ @@ -1042,10 +1015,10 @@ static void change_sysid(struct fdisk_context *cxt) if (sys == origsys) break; if (disklabel == SUN_LABEL) { - ptes[i].changed = sun_change_sysid(i, sys); + ptes[i].changed = sun_change_sysid(cxt, i, sys); } else if (disklabel == SGI_LABEL) { - ptes[i].changed = sgi_change_sysid(i, sys); + ptes[i].changed = sgi_change_sysid(cxt, i, sys); } else { p->sys_ind = sys; ptes[i].changed = 1; @@ -1168,7 +1141,7 @@ list_disk_geometry(struct fdisk_context *cxt) { if (cxt->alignment_offset) printf(_("Alignment offset: %lu bytes\n"), cxt->alignment_offset); if (disklabel == DOS_LABEL) - dos_print_mbr_id(); + dos_print_mbr_id(cxt); printf("\n"); } @@ -1471,12 +1444,12 @@ verify(struct fdisk_context *cxt) { return; if (disklabel == SUN_LABEL) { - verify_sun(); + verify_sun(cxt); return; } if (disklabel == SGI_LABEL) { - verify_sgi(1); + verify_sgi(cxt, 1); return; } @@ -1671,7 +1644,7 @@ static void print_raw(struct fdisk_context *cxt) printf(_("Device: %s\n"), cxt->dev_path); if (disklabel == SUN_LABEL || disklabel == SGI_LABEL) - print_buffer(cxt, MBRbuffer); + print_buffer(cxt, cxt->mbr); else for (i = 3; i < partitions; i++) print_buffer(cxt, ptes[i].sectorbuffer); } @@ -1754,7 +1727,7 @@ expert_command_prompt(struct fdisk_context *cxt) read_int(cxt, 1, cylinders, 1048576, 0, _("Number of cylinders")); if (disklabel == SUN_LABEL) - sun_set_ncyl(cylinders); + sun_set_ncyl(cxt, cylinders); break; case 'd': print_raw(cxt); @@ -1784,7 +1757,7 @@ expert_command_prompt(struct fdisk_context *cxt) if (disklabel == SUN_LABEL) sun_set_ilfact(cxt); else if (disklabel == DOS_LABEL) - dos_set_mbr_id(); + dos_set_mbr_id(cxt); break; case 'o': if (disklabel == SUN_LABEL) @@ -1942,17 +1915,17 @@ static void command_prompt(struct fdisk_context *cxt) if (disklabel == DOS_LABEL) toggle_active(get_partition(cxt, 1, partitions)); else if (disklabel == SUN_LABEL) - toggle_sunflags(get_partition(cxt, 1, partitions), + toggle_sunflags(cxt, get_partition(cxt, 1, partitions), SUN_FLAG_UNMNT); else if (disklabel == SGI_LABEL) - sgi_set_bootpartition( + sgi_set_bootpartition(cxt, get_partition(cxt, 1, partitions)); else unknown_command(c); break; case 'b': if (disklabel == SGI_LABEL) - sgi_set_bootfile(); + sgi_set_bootfile(cxt); else if (disklabel == DOS_LABEL) { disklabel = OSF_LABEL; bsd_command_prompt(cxt); @@ -1964,10 +1937,10 @@ static void command_prompt(struct fdisk_context *cxt) if (disklabel == DOS_LABEL) toggle_dos_compatibility_flag(cxt); else if (disklabel == SUN_LABEL) - toggle_sunflags(get_partition(cxt, 1, partitions), + toggle_sunflags(cxt, get_partition(cxt, 1, partitions), SUN_FLAG_RONLY); else if (disklabel == SGI_LABEL) - sgi_set_swappartition( + sgi_set_swappartition(cxt, get_partition(cxt, 1, partitions)); else unknown_command(c); @@ -1977,7 +1950,7 @@ static void command_prompt(struct fdisk_context *cxt) break; case 'i': if (disklabel == SGI_LABEL) - create_sgiinfo(); + create_sgiinfo(cxt); else unknown_command(c); break; @@ -2113,7 +2086,7 @@ int main(int argc, char **argv) printf(_("Warning: the -b (set sector size) option should" " be used with one specified device\n")); - init_mbr_buffer(); + /* init_mbr_buffer(); */ if (optl) { nowarn = 1; diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h index 9d17cdd76..b4f2814f9 100644 --- a/fdisk/fdisk.h +++ b/fdisk/fdisk.h @@ -104,8 +104,9 @@ struct geom { typedef unsigned long long sector_t; struct fdisk_context { - int dev_fd; /* device descriptor */ - char *dev_path; /* device path */ + int dev_fd; /* device descriptor */ + char *dev_path; /* device path */ + unsigned char *mbr; /* buffer with master boot record */ /* topology */ unsigned long io_size; /* I/O size used by fdisk */ @@ -123,6 +124,7 @@ extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, extern int fdisk_dev_has_topology(struct fdisk_context *cxt); extern int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt); extern void fdisk_free_context(struct fdisk_context *cxt); +extern void fdisk_mbr_zeroize(struct fdisk_context *cxt); /* prototypes for fdisk.c */ extern char *disk_device, *line_ptr; @@ -145,7 +147,6 @@ extern unsigned int read_int(struct fdisk_context *cxt, extern void print_menu(enum menutype); extern void print_partition_size(struct fdisk_context *cxt, int num, sector_t start, sector_t stop, int sysid); -extern void zeroize_mbr_buffer(void); extern void fill_bounds(sector_t *first, sector_t *last); extern unsigned int heads, cylinders; extern sector_t sectors; @@ -180,12 +181,6 @@ enum labeltype { }; extern enum labeltype disklabel; - -/* - * Raw disk label. For DOS-type partition tables the MBR, - * with descriptions of the primary partitions. - */ -extern unsigned char *MBRbuffer; extern int MBRbuffer_changed; extern unsigned long grain; diff --git a/fdisk/fdiskaixlabel.c b/fdisk/fdiskaixlabel.c index 9fde61f7a..c15ab749b 100644 --- a/fdisk/fdiskaixlabel.c +++ b/fdisk/fdiskaixlabel.c @@ -14,6 +14,8 @@ #include "fdiskaixlabel.h" #include "nls.h" +#define aixlabel ((aix_partition *)cxt->mbr) + static int other_endian = 0; static short volumes=1; @@ -39,16 +41,15 @@ aix_info( void ) { } void -aix_nolabel( void ) +aix_nolabel(struct fdisk_context *cxt) { aixlabel->magic = 0; partitions = 4; - zeroize_mbr_buffer(); + fdisk_mbr_zeroize(cxt); return; } -int -check_aix_label( void ) +int check_aix_label(struct fdisk_context *cxt) { if (aixlabel->magic != AIX_LABEL_MAGIC && aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) { @@ -61,6 +62,6 @@ check_aix_label( void ) partitions= 1016; volumes = 15; aix_info(); - aix_nolabel(); /* %% */ + aix_nolabel(cxt); /* %% */ return 1; } diff --git a/fdisk/fdiskaixlabel.h b/fdisk/fdiskaixlabel.h index 324b9ae24..bd4cb2781 100644 --- a/fdisk/fdiskaixlabel.h +++ b/fdisk/fdiskaixlabel.h @@ -20,12 +20,8 @@ typedef struct { #define AIX_INFO_MAGIC 0x00072959 #define AIX_INFO_MAGIC_SWAPPED 0x59290700 -/* fdisk.c */ -#define aixlabel ((aix_partition *)MBRbuffer) - /* fdiskaixlabel.c */ extern struct systypes aix_sys_types[]; -extern void aix_nolabel( void ); -extern int check_aix_label( void ); +extern int check_aix_label(struct fdisk_context *cxt); #endif /* FDISK_AIX_LABEL_H */ diff --git a/fdisk/fdiskdoslabel.c b/fdisk/fdiskdoslabel.c index 299cff83c..abf101b32 100644 --- a/fdisk/fdiskdoslabel.c +++ b/fdisk/fdiskdoslabel.c @@ -108,10 +108,10 @@ void dos_init(struct fdisk_context *cxt) for (i = 0; i < 4; i++) { struct pte *pe = &ptes[i]; - pe->part_table = pt_offset(MBRbuffer, i); + pe->part_table = pt_offset(cxt->mbr, i); pe->ext_pointer = NULL; pe->offset = 0; - pe->sectorbuffer = MBRbuffer; + pe->sectorbuffer = cxt->mbr; pe->changed = 0; } @@ -214,9 +214,9 @@ static void read_extended(struct fdisk_context *cxt, int ext) } } -void dos_print_mbr_id(void) +void dos_print_mbr_id(struct fdisk_context *cxt) { - printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer)); + printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(cxt->mbr)); } void create_doslabel(struct fdisk_context *cxt) @@ -229,26 +229,25 @@ void create_doslabel(struct fdisk_context *cxt) fprintf(stderr, _("Building a new DOS disklabel with disk identifier 0x%08x.\n"), id); dos_init(cxt); - zeroize_mbr_buffer(); - + fdisk_mbr_zeroize(cxt); set_all_unchanged(); set_changed(0); /* Generate an MBR ID for this disk */ - dos_write_mbr_id(MBRbuffer, id); + dos_write_mbr_id(cxt->mbr, id); /* Put MBR signature */ - write_part_table_flag(MBRbuffer); + write_part_table_flag(cxt->mbr); } -void dos_set_mbr_id(void) +void dos_set_mbr_id(struct fdisk_context *cxt) { unsigned long new_id; char *ep; char ps[64]; snprintf(ps, sizeof ps, _("New disk identifier (current 0x%08x): "), - dos_read_mbr_id(MBRbuffer)); + dos_read_mbr_id(cxt->mbr)); if (read_chars(ps) == '\n') return; @@ -257,9 +256,9 @@ void dos_set_mbr_id(void) if (*ep != '\n') return; - dos_write_mbr_id(MBRbuffer, new_id); + dos_write_mbr_id(cxt->mbr, new_id); MBRbuffer_changed = 1; - dos_print_mbr_id(); + dos_print_mbr_id(cxt); } void dos_delete_partition(int i) @@ -321,7 +320,7 @@ int check_dos_label(struct fdisk_context *cxt) { int i; - if (!valid_part_table_flag(MBRbuffer)) + if (!valid_part_table_flag(cxt->mbr)) return 0; dos_init(cxt); @@ -668,8 +667,8 @@ void dos_write_table(struct fdisk_context *cxt) MBRbuffer_changed = 1; } if (MBRbuffer_changed) { - write_part_table_flag(MBRbuffer); - write_sector(cxt, 0, MBRbuffer); + write_part_table_flag(cxt->mbr); + write_sector(cxt, 0, cxt->mbr); } /* EBR (logical partitions) */ for (i = 4; i < partitions; i++) { diff --git a/fdisk/fdiskdoslabel.h b/fdisk/fdiskdoslabel.h index 8d62d52e8..f64a4cedd 100644 --- a/fdisk/fdiskdoslabel.h +++ b/fdisk/fdiskdoslabel.h @@ -44,8 +44,8 @@ static inline sector_t get_partition_start(struct pte *pe) } extern void create_doslabel(struct fdisk_context *cxt); -extern void dos_print_mbr_id(void); -extern void dos_set_mbr_id(void); +extern void dos_print_mbr_id(struct fdisk_context *cxt); +extern void dos_set_mbr_id(struct fdisk_context *cxt); extern void dos_delete_partition(int i); extern int check_dos_label(struct fdisk_context *cxt); extern int is_dos_partition(int t); diff --git a/fdisk/fdiskmaclabel.c b/fdisk/fdiskmaclabel.c index e82347d73..1c2e403e7 100644 --- a/fdisk/fdiskmaclabel.c +++ b/fdisk/fdiskmaclabel.c @@ -39,16 +39,16 @@ mac_info( void ) { } void -mac_nolabel( void ) +mac_nolabel(struct fdisk_context *cxt) { maclabel->magic = 0; partitions = 4; - zeroize_mbr_buffer(); + fdisk_mbr_zeroize(cxt); return; } int -check_mac_label( void ) +check_mac_label(struct fdisk_context *cxt) { /* Conversion: only 16 bit should compared @@ -77,7 +77,7 @@ IS_MAC: partitions= 1016; // =? volumes = 15; // =? mac_info(); - mac_nolabel(); /* %% */ + mac_nolabel(cxt); /* %% */ return 1; } diff --git a/fdisk/fdiskmaclabel.h b/fdisk/fdiskmaclabel.h index e664a155a..4873dcdf0 100644 --- a/fdisk/fdiskmaclabel.h +++ b/fdisk/fdiskmaclabel.h @@ -28,12 +28,12 @@ typedef struct { #define MAC_LABEL_MAGIC_3_SWAPPED 0x0000d405 /* fdisk.c */ -#define maclabel ((mac_partition *)MBRbuffer) +#define maclabel ((mac_partition *)cxt->mbr) /* fdiskmaclabel.c */ extern struct systypes mac_sys_types[]; -extern void mac_nolabel( void ); -extern int check_mac_label( void ); +extern void mac_nolabel(struct fdisk_context *cxt); +extern int check_mac_label(struct fdisk_context *cxt); #endif /* FDISK_MAC_LABEL_H */ diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c index 9c425b393..1a10296d0 100644 --- a/fdisk/fdisksgilabel.c +++ b/fdisk/fdisksgilabel.c @@ -11,7 +11,11 @@ * * 2003-03-20 Phillip Kesling * Some fixes + * + * 2012-06-16 Davidlohr Bueso + * Adapt to fdisk context and add heap sort for partitions */ + #include /* stderr */ #include /* exit */ #include /* strstr */ @@ -103,12 +107,12 @@ struct systypes sgi_sys_types[] = { }; static int -sgi_get_nsect(void) { +sgi_get_nsect(struct fdisk_context *cxt) { return SSWAP16(sgilabel->devparam.nsect); } static int -sgi_get_ntrks(void) { +sgi_get_ntrks(struct fdisk_context *cxt) { return SSWAP16(sgilabel->devparam.ntrks); } @@ -130,7 +134,7 @@ sgi_get_pcylcount(void) { #endif void -sgi_nolabel() { +sgi_nolabel(struct fdisk_context *cxt) { sgilabel->magic = 0; partitions = 4; } @@ -147,7 +151,7 @@ two_s_complement_32bit_sum(unsigned int *base, int size /* in bytes */) { } int -check_sgi_label() { +check_sgi_label(struct fdisk_context *cxt) { if (sizeof(sgilabel) > 512) { fprintf(stderr, _("According to MIPS Computer Systems, Inc the " @@ -209,21 +213,21 @@ sgi_list_table(struct fdisk_context *cxt, int xtra) { "Pt# %*s Info Start End Sectors Id System\n"), w + 1, _("Device")); for (i = 0 ; i < partitions; i++) { - if (sgi_get_num_sectors(i) || debug) { - uint32_t start = sgi_get_start_sector(i); - uint32_t len = sgi_get_num_sectors(i); + if (sgi_get_num_sectors(cxt, i) || debug) { + uint32_t start = sgi_get_start_sector(cxt, i); + uint32_t len = sgi_get_num_sectors(cxt, i); kpi++; /* only count nonempty partitions */ printf( "%2d: %s %4s %9ld %9ld %9ld %2x %s\n", /* fdisk part number */ i+1, /* device */ partname(cxt->dev_path, kpi, w+2), -/* flags */ (sgi_get_swappartition() == i) ? "swap" : -/* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ", +/* flags */ (sgi_get_swappartition(cxt) == i) ? "swap" : +/* flags */ (sgi_get_bootpartition(cxt) == i) ? "boot" : " ", /* start */ (long) scround(start), /* end */ (long) scround(start+len)-1, /* no odd flag on end */ (long) len, -/* type id */ sgi_get_sysid(i), -/* type name */ (type = partition_type(sgi_get_sysid(i))) +/* type id */ sgi_get_sysid(cxt, i), +/* type name */ (type = partition_type(sgi_get_sysid(cxt, i))) ? type : _("Unknown")); } } @@ -243,35 +247,35 @@ sgi_list_table(struct fdisk_context *cxt, int xtra) { } unsigned int -sgi_get_start_sector(int i) { +sgi_get_start_sector(struct fdisk_context *cxt, int i) { return SSWAP32(sgilabel->partitions[i].start_sector); } unsigned int -sgi_get_num_sectors(int i) { +sgi_get_num_sectors(struct fdisk_context *cxt, int i) { return SSWAP32(sgilabel->partitions[i].num_sectors); } int -sgi_get_sysid(int i) +sgi_get_sysid(struct fdisk_context *cxt, int i) { return SSWAP32(sgilabel->partitions[i].id); } int -sgi_get_bootpartition(void) +sgi_get_bootpartition(struct fdisk_context *cxt) { return (short) SSWAP16(sgilabel->boot_part); } int -sgi_get_swappartition(void) +sgi_get_swappartition(struct fdisk_context *cxt) { return (short) SSWAP16(sgilabel->swap_part); } void -sgi_set_bootpartition(int i) +sgi_set_bootpartition(struct fdisk_context *cxt, int i) { sgilabel->boot_part = SSWAP16(((short)i)); } @@ -282,12 +286,12 @@ sgi_get_lastblock(void) { } void -sgi_set_swappartition(int i) { +sgi_set_swappartition(struct fdisk_context *cxt, int i) { sgilabel->swap_part = SSWAP16(((short)i)); } static int -sgi_check_bootfile(const char* aFile) { +sgi_check_bootfile(struct fdisk_context *cxt, const char* aFile) { if (strlen(aFile) < 3) /* "/a\n" is minimum */ { printf(_("\nInvalid Bootfile!\n" "\tThe bootfile must be an absolute non-zero pathname,\n" @@ -316,7 +320,7 @@ sgi_check_bootfile(const char* aFile) { } void -sgi_set_bootfile(void) +sgi_set_bootfile(struct fdisk_context *cxt) { printf(_("\nThe current boot file is: %s\n"), sgilabel->boot_file); if (read_chars(_("Please enter the name of the new boot file: ")) == '\n') { @@ -324,7 +328,7 @@ sgi_set_bootfile(void) return; } - if (sgi_check_bootfile(line_ptr)) { + if (sgi_check_bootfile(cxt, line_ptr)) { size_t i = 0; while (i < 16) { if ((line_ptr[i] != '\n') /* in principle caught again by next line */ @@ -340,7 +344,7 @@ sgi_set_bootfile(void) } void -create_sgiinfo(void) { +create_sgiinfo(struct fdisk_context *cxt) { /* I keep SGI's habit to write the sgilabel to the second block */ sgilabel->directory[0].vol_file_start = SSWAP32(2); sgilabel->directory[0].vol_file_size = SSWAP32(sizeof(sgiinfo)); @@ -378,18 +382,18 @@ sgi_write_table(struct fdisk_context *cxt) { } static int -compare_start(int *x, int *y) { +compare_start(struct fdisk_context *cxt, const void *x, const void *y) { /* * sort according to start sectors * and prefers largest partition: * entry zero is entire disk entry */ - unsigned int i = *x; - unsigned int j = *y; - unsigned int a = sgi_get_start_sector(i); - unsigned int b = sgi_get_start_sector(j); - unsigned int c = sgi_get_num_sectors(i); - unsigned int d = sgi_get_num_sectors(j); + unsigned int i = *(int *) x; + unsigned int j = *(int *) y; + unsigned int a = sgi_get_start_sector(cxt, i); + unsigned int b = sgi_get_start_sector(cxt, j); + unsigned int c = sgi_get_num_sectors(cxt, i); + unsigned int d = sgi_get_num_sectors(cxt, j); if (a == b) return (d > c) ? 1 : (d == c) ? 0 : -1; @@ -397,18 +401,67 @@ compare_start(int *x, int *y) { } static int -sgi_gaps(void) { +sgi_gaps(struct fdisk_context *cxt) { /* * returned value is: * = 0 : disk is properly filled to the rim * < 0 : there is an overlap * > 0 : there is still some vacant space */ - return verify_sgi(0); + return verify_sgi(cxt, 0); } +static void generic_swap(void *a, void *b, int size) +{ + char t; + + do { + t = *(char *)a; + *(char *)a++ = *(char *)b; + *(char *)b++ = t; + } while (--size > 0); +} + + +/* heap sort, based on Matt Mackall's linux kernel version */ +static void sort(void *base, size_t num, size_t size, struct fdisk_context *cxt, + int (*cmp_func)(struct fdisk_context *, const void *, const void *)) +{ + /* pre-scale counters for performance */ + int i = (num/2 - 1) * size; + size_t n = num * size, c, r; + + /* heapify */ + for ( ; i >= 0; i -= size) { + for (r = i; r * 2 + size < n; r = c) { + c = r * 2 + size; + if (c < n - size && + cmp_func(cxt, base + c, base + c + size) < 0) + c += size; + if (cmp_func(cxt, base + r, base + c) >= 0) + break; + generic_swap(base + r, base + c, size); + } + } + + /* sort */ + for (i = n - size; i > 0; i -= size) { + generic_swap(base, base + i, size); + for (r = 0; r * 2 + size < (size_t) i; r = c) { + c = r * 2 + size; + if (c < i - size && + cmp_func(cxt, base + c, base + c + size) < 0) + c += size; + if (cmp_func(cxt, base + r, base + c) >= 0) + break; + generic_swap(base + r, base + c, size); + } + } +} + + int -verify_sgi(int verbose) +verify_sgi(struct fdisk_context *cxt, int verbose) { int Index[16]; /* list of valid partitions */ int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */ @@ -419,9 +472,9 @@ verify_sgi(int verbose) clearfreelist(); for (i=0; i<16; i++) { - if (sgi_get_num_sectors(i) != 0) { + if (sgi_get_num_sectors(cxt, i) != 0) { Index[sortcount++]=i; - if (sgi_get_sysid(i) == ENTIRE_DISK) { + if (sgi_get_sysid(cxt, i) == ENTIRE_DISK) { if (entire++ == 1) { if (verbose) printf(_("More than one entire disk entry present.\n")); @@ -434,71 +487,73 @@ verify_sgi(int verbose) printf(_("No partitions defined\n")); return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1; } - qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start); - if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) { + + sort(Index, sortcount, sizeof(Index[0]), cxt, compare_start); + + if (sgi_get_sysid(cxt, Index[0]) == ENTIRE_DISK) { if ((Index[0] != 10) && verbose) printf(_("IRIX likes when Partition 11 covers the entire disk.\n")); - if ((sgi_get_start_sector(Index[0]) != 0) && verbose) + if ((sgi_get_start_sector(cxt, Index[0]) != 0) && verbose) printf(_("The entire disk partition should start " "at block 0,\n" "not at diskblock %d.\n"), - sgi_get_start_sector(Index[0])); + sgi_get_start_sector(cxt, Index[0])); if (debug) /* I do not understand how some disks fulfil it */ - if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose) + if ((sgi_get_num_sectors(cxt, Index[0]) != lastblock) && verbose) printf(_("The entire disk partition is only %d diskblock large,\n" "but the disk is %d diskblocks long.\n"), - sgi_get_num_sectors(Index[0]), lastblock); - lastblock = sgi_get_num_sectors(Index[0]); + sgi_get_num_sectors(cxt, Index[0]), lastblock); + lastblock = sgi_get_num_sectors(cxt, Index[0]); } else { if (verbose) printf(_("Partition 11 should cover the entire disk.\n")); if (debug>2) printf("sysid=%d\tpartition=%d\n", - sgi_get_sysid(Index[0]), Index[0]+1); + sgi_get_sysid(cxt, Index[0]), Index[0]+1); } for (i=1, start=0; i sgi_get_start_sector(Index[i])) { + if (sgi_get_sysid(cxt, Index[i]) == ENTIRE_DISK) continue; + if (start > sgi_get_start_sector(cxt, Index[i])) { if (verbose) printf(_("The Partition %d and %d overlap by %d sectors.\n"), Index[i-1]+1, Index[i]+1, - start - sgi_get_start_sector(Index[i])); + start - sgi_get_start_sector(cxt, Index[i])); if (gap > 0) gap = -gap; if (gap == 0) gap = -1; } - if (start < sgi_get_start_sector(Index[i])) { + if (start < sgi_get_start_sector(cxt, Index[i])) { if (verbose) printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"), - sgi_get_start_sector(Index[i]) - start, - start, sgi_get_start_sector(Index[i])-1); - gap += sgi_get_start_sector(Index[i]) - start; - add2freelist(start, sgi_get_start_sector(Index[i])); + sgi_get_start_sector(cxt, Index[i]) - start, + start, sgi_get_start_sector(cxt, Index[i])-1); + gap += sgi_get_start_sector(cxt, Index[i]) - start; + add2freelist(start, sgi_get_start_sector(cxt, Index[i])); } - start = sgi_get_start_sector(Index[i]) - + sgi_get_num_sectors(Index[i]); + start = sgi_get_start_sector(cxt, Index[i]) + + sgi_get_num_sectors(cxt, Index[i]); /* Align free space on cylinder boundary */ if (start % cylsize) start += cylsize - (start % cylsize); if (debug > 1) { if (verbose) printf("%2d:%12d\t%12d\t%12d\n", Index[i], - sgi_get_start_sector(Index[i]), - sgi_get_num_sectors(Index[i]), - sgi_get_sysid(Index[i])); + sgi_get_start_sector(cxt, Index[i]), + sgi_get_num_sectors(cxt, Index[i]), + sgi_get_sysid(cxt, Index[i])); } } if (start < lastblock) { @@ -513,31 +568,31 @@ verify_sgi(int verbose) * Go for details now */ if (verbose) { - if (sgi_get_bootpartition() < 0 || !sgi_get_num_sectors(sgi_get_bootpartition())) { + if (sgi_get_bootpartition(cxt) < 0 || !sgi_get_num_sectors(cxt, sgi_get_bootpartition(cxt))) { printf(_("\nThe boot partition does not exist.\n")); } - if (sgi_get_swappartition() < 0 || !sgi_get_num_sectors(sgi_get_swappartition())) { + if (sgi_get_swappartition(cxt) < 0 || !sgi_get_num_sectors(cxt, sgi_get_swappartition(cxt))) { printf(_("\nThe swap partition does not exist.\n")); } else { - if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP) - && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP)) + if ((sgi_get_sysid(cxt, sgi_get_swappartition(cxt)) != SGI_SWAP) + && (sgi_get_sysid(cxt, sgi_get_swappartition(cxt)) != LINUX_SWAP)) printf(_("\nThe swap partition has no swap type.\n")); } - if (sgi_check_bootfile("/unix")) + if (sgi_check_bootfile(cxt, "/unix")) printf(_("\tYou have chosen an unusual boot file name.\n")); } return (gap > 0) ? 1 : (gap == 0) ? 0 : -1; } int -sgi_change_sysid(int i, int sys) +sgi_change_sysid(struct fdisk_context *cxt, int i, int sys) { - if (sgi_get_num_sectors(i) == 0) /* caught already before, ... */ { + if (sgi_get_num_sectors(cxt, i) == 0) /* caught already before, ... */ { printf(_("Sorry, only for non-empty partitions you can change the tag.\n")); return 0; } if (((sys != ENTIRE_DISK) && (sys != SGI_VOLHDR)) - && (sgi_get_start_sector(i)<1)) { + && (sgi_get_start_sector(cxt, i)<1)) { read_chars( _("It is highly recommended that the partition at offset 0\n" "is of type \"SGI volhdr\", the IRIX system will rely on it to\n" @@ -553,11 +608,11 @@ sgi_change_sysid(int i, int sys) /* returns partition index of first entry marked as entire disk */ static int -sgi_entire(void) { +sgi_entire(struct fdisk_context *cxt) { int i; for (i=0; i<16; i++) - if (sgi_get_sysid(i) == SGI_VOLUME) + if (sgi_get_sysid(cxt, i) == SGI_VOLUME) return i; return -1; } @@ -569,7 +624,7 @@ sgi_set_partition(struct fdisk_context *cxt, sgilabel->partitions[i].num_sectors = SSWAP32(length); sgilabel->partitions[i].start_sector = SSWAP32(start); set_changed(i); - if (sgi_gaps() < 0) /* rebuild freelist */ + if (sgi_gaps(cxt) < 0) /* rebuild freelist */ printf(_("Partition overlap on the disk.\n")); if (length) print_partition_size(cxt, i + 1, start, start + length, sys); @@ -580,7 +635,7 @@ sgi_set_entire(struct fdisk_context *cxt) { int n; for (n=10; nmbr)) { if (get_part_table(i)->sys_ind) { old[i].sysid = get_part_table(i)->sys_ind; old[i].start = get_start_sect(get_part_table(i)); @@ -748,7 +803,7 @@ create_sgilabel(struct fdisk_context *cxt) break; } - zeroize_mbr_buffer(); + fdisk_mbr_zeroize(cxt); sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC); sgilabel->boot_part = SSWAP16(0); sgilabel->swap_part = SSWAP16(1); diff --git a/fdisk/fdisksgilabel.h b/fdisk/fdisksgilabel.h index 7611d327a..dff32b1ec 100644 --- a/fdisk/fdisksgilabel.h +++ b/fdisk/fdisksgilabel.h @@ -106,33 +106,33 @@ typedef struct { #define SSWAP32(x) (other_endian ? swab32(x) : (uint32_t)(x)) /* fdisk.c */ -#define sgilabel ((sgi_partition *)MBRbuffer) +#define sgilabel ((sgi_partition *)cxt->mbr) #define sgiparam (sgilabel->devparam) /* fdisksgilabel.c */ extern struct systypes sgi_sys_types[]; -extern void sgi_nolabel( void ); -extern int check_sgi_label( void ); +extern void sgi_nolabel(struct fdisk_context *cxt); +extern int check_sgi_label(struct fdisk_context *cxt); extern void sgi_list_table( struct fdisk_context *cxt, int xtra ); -extern int sgi_change_sysid( int i, int sys ); -extern unsigned int sgi_get_start_sector( int i ); -extern unsigned int sgi_get_num_sectors( int i ); -extern int sgi_get_sysid( int i ); +extern int sgi_change_sysid(struct fdisk_context *cxt, int i, int sys); +extern unsigned int sgi_get_start_sector(struct fdisk_context *cxt, int i ); +extern unsigned int sgi_get_num_sectors(struct fdisk_context *cxt, int i ); +extern int sgi_get_sysid(struct fdisk_context *cxt, int i ); extern void sgi_delete_partition( struct fdisk_context *cxt, int i ); 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( void ); -extern int verify_sgi( int verbose ); +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 ); extern void sgi_set_xcyl( void ); extern void sgi_set_ncyl( void ); -extern void sgi_set_bootpartition( int i ); -extern void sgi_set_swappartition( int i ); -extern int sgi_get_bootpartition( void ); -extern int sgi_get_swappartition( void ); -extern void sgi_set_bootfile(void); +extern void sgi_set_bootpartition(struct fdisk_context *cxt, int i ); +extern void sgi_set_swappartition(struct fdisk_context *cxt, int i ); +extern int sgi_get_bootpartition(struct fdisk_context *cxt); +extern int sgi_get_swappartition(struct fdisk_context *cxt); +extern void sgi_set_bootfile(struct fdisk_context *cxt); #endif /* FDISK_SGI_LABEL_H */ diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index ae24e1611..d80b039b0 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -78,13 +78,13 @@ static void init(void) partitions = SUN_NUM_PARTITIONS; } -void sun_nolabel(void) +void sun_nolabel(struct fdisk_context *cxt) { sunlabel->magic = 0; partitions = 4; } -int check_sun_label(void) +int check_sun_label(struct fdisk_context *cxt) { unsigned short *ush; int csum; @@ -166,7 +166,7 @@ void create_sunlabel(struct fdisk_context *cxt) #endif init(); - zeroize_mbr_buffer(); + fdisk_mbr_zeroize(cxt); sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC); sunlabel->sanity = SSWAP32(SUN_LABEL_SANE); @@ -242,7 +242,7 @@ void create_sunlabel(struct fdisk_context *cxt) set_changed(0); } -void toggle_sunflags(int i, uint16_t mask) +void toggle_sunflags(struct fdisk_context *cxt, int i, uint16_t mask) { struct sun_tag_flag *p = &sunlabel->part_tags[i]; @@ -251,7 +251,8 @@ void toggle_sunflags(int i, uint16_t mask) set_changed(i); } -static void fetch_sun(uint32_t *starts, uint32_t *lens, uint32_t *start, uint32_t *stop) +static void fetch_sun(struct fdisk_context *cxt, uint32_t *starts, + uint32_t *lens, uint32_t *start, uint32_t *stop) { int i, continuous = 1; @@ -298,7 +299,7 @@ static int verify_sun_cmp(int *a, int *b) return -1; } -void verify_sun(void) +void verify_sun(struct fdisk_context *cxt) { uint32_t starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS], start, stop; uint32_t i,j,k,starto,endo; @@ -306,7 +307,7 @@ void verify_sun(void) verify_sun_starts = starts; - fetch_sun(starts, lens, &start, &stop); + fetch_sun(cxt, starts, lens, &start, &stop); for (k = 0; k < 7; k++) { for (i = 0; i < SUN_NUM_PARTITIONS; i++) { @@ -347,6 +348,7 @@ void verify_sun(void) } qsort(array,ARRAY_SIZE(array),sizeof(array[0]), (int (*)(const void *,const void *)) verify_sun_cmp); + if (array[0] == -1) { printf(_("No partitions defined\n")); return; @@ -382,7 +384,7 @@ void add_sun_partition(struct fdisk_context *cxt, int n, int sys) return; } - fetch_sun(starts, lens, &start, &stop); + fetch_sun(cxt, starts, lens, &start, &stop); if (stop <= start) { if (n == 2) whole_disk = 1; @@ -484,7 +486,7 @@ and is of type `Whole disk'\n")); set_sun_partition(cxt, n, first, last, sys); } -void sun_delete_partition(int i) +void sun_delete_partition(struct fdisk_context *cxt, int i) { struct sun_partition *part = &sunlabel->partitions[i]; struct sun_tag_flag *tag = &sunlabel->part_tags[i]; @@ -503,7 +505,7 @@ void sun_delete_partition(int i) part->num_sectors = 0; } -int sun_change_sysid(int i, uint16_t sys) +int sun_change_sysid(struct fdisk_context *cxt, int i, uint16_t sys) { struct sun_partition *part = &sunlabel->partitions[i]; struct sun_tag_flag *tag = &sunlabel->part_tags[i]; @@ -594,7 +596,7 @@ void sun_set_alt_cyl(struct fdisk_context *cxt) _("Number of alternate cylinders"))); } -void sun_set_ncyl(int cyl) +void sun_set_ncyl(struct fdisk_context *cxt, int cyl) { sunlabel->ncyl = SSWAP16(cyl); } @@ -641,7 +643,7 @@ void sun_write_table(struct fdisk_context *cxt) fatal(cxt, unable_to_write); } -int sun_get_sysid(int i) +int sun_get_sysid(struct fdisk_context *cxt, int i) { return SSWAP16(sunlabel->part_tags[i].tag); } diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h index 8cb13ec17..d3cd43016 100644 --- a/fdisk/fdisksunlabel.h +++ b/fdisk/fdisksunlabel.h @@ -73,26 +73,26 @@ struct sun_disk_label { #define SUN_LABEL_MAGIC 0xDABE #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA -#define sunlabel ((struct sun_disk_label *)MBRbuffer) +#define sunlabel ((struct sun_disk_label *)cxt->mbr) /* fdisksunlabel.c */ extern struct systypes sun_sys_types[]; -extern int check_sun_label(void); -extern void sun_nolabel(void); +extern int check_sun_label(struct fdisk_context *cxt); +extern void sun_nolabel(struct fdisk_context *cxt); extern void create_sunlabel(struct fdisk_context *cxt); -extern void sun_delete_partition(int i); -extern int sun_change_sysid(int i, uint16_t sys); +extern void sun_delete_partition(struct fdisk_context *cxt, int i); +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(void); +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(int cyl); +extern void sun_set_ncyl(struct fdisk_context *cxt, int cyl); extern void sun_set_xcyl(struct fdisk_context *cxt); extern void sun_set_ilfact(struct fdisk_context *cxt); extern void sun_set_rspeed(struct fdisk_context *cxt); extern void sun_set_pcylcount(struct fdisk_context *cxt); -extern void toggle_sunflags(int i, uint16_t mask); -extern int sun_get_sysid(int i); +extern void toggle_sunflags(struct fdisk_context *cxt, int i, uint16_t mask); +extern int sun_get_sysid(struct fdisk_context *cxt, int i); #endif /* FDISK_SUN_LABEL_H */ diff --git a/fdisk/utils.c b/fdisk/utils.c index d105d8e42..616fcc0dd 100644 --- a/fdisk/utils.c +++ b/fdisk/utils.c @@ -31,6 +31,21 @@ int fdisk_debug_mask; +static int __init_mbr_buffer(struct fdisk_context *cxt) +{ + cxt->mbr = calloc(1, MAX_SECTOR_SIZE); + if (!cxt->mbr) + goto fail; + + /* read MBR */ + if (512 != read(cxt->dev_fd, cxt->mbr, 512)) + goto fail; + + return 0; +fail: + return -1; +} + static unsigned long __get_sector_size(int fd) { int sect_sz; @@ -93,6 +108,18 @@ static int __discover_topology(struct fdisk_context *cxt) return 0; } +/** + * fdisk_mbr_zeroize: + * @cxt: fdisk context + * + * Zero's MBR buffer + */ +void fdisk_mbr_zeroize(struct fdisk_context *cxt) +{ + if (cxt->mbr) + bzero(cxt->mbr, MAX_SECTOR_SIZE); +} + /** * fdisk_dev_sectsz_is_default: * @cxt: fdisk context @@ -181,6 +208,9 @@ struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int rea if (!cxt->dev_path) goto fail; + if (__init_mbr_buffer(cxt) < 0) + goto fail; + __discover_topology(cxt); __discover_geometry(cxt); @@ -210,5 +240,6 @@ void fdisk_free_context(struct fdisk_context *cxt) DBG(CONTEXT, dbgprint("freeing context for %s", cxt->dev_path)); close(cxt->dev_fd); free(cxt->dev_path); + free(cxt->mbr); free(cxt); }