diff options
Diffstat (limited to 'util-linux')
-rw-r--r-- | util-linux/fdisk.c | 244 |
1 files changed, 118 insertions, 126 deletions
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 980568bc8..cb15bd267 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -21,6 +21,13 @@ #endif #include "libbb.h" +#if BB_LITTLE_ENDIAN +# define inline_if_little_endian ALWAYS_INLINE +#else +# define inline_if_little_endian /* nothing */ +#endif + + /* Looks like someone forgot to add this to config system */ #ifndef ENABLE_FEATURE_FDISK_BLKSIZE # define ENABLE_FEATURE_FDISK_BLKSIZE 0 @@ -181,7 +188,7 @@ struct pte { sector_t offset; /* disk sector number */ char *sectorbuffer; /* disk sector contents */ #if ENABLE_FEATURE_FDISK_WRITABLE - char changed; /* boolean */ + char changed; /* boolean */ #endif }; @@ -445,27 +452,6 @@ close_dev_fd(void) xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd); } -#if ENABLE_FEATURE_FDISK_WRITABLE -/* Read line; return 0 or first printable char */ -static int -read_line(const char *prompt) -{ - int sz; - - sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL); - if (sz <= 0) - exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ - - if (line_buffer[sz-1] == '\n') - line_buffer[--sz] = '\0'; - - line_ptr = line_buffer; - while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ') - line_ptr++; - return *line_ptr; -} -#endif - /* * Return partition name - uses static storage */ @@ -497,30 +483,13 @@ partname(const char *dev, int pno, int lth) if (lth) { snprintf(bufp, bufsiz, "%*.*s%s%-2u", - lth-wp-2, w, dev, p, pno); + lth-wp-2, w, dev, p, pno); } else { snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno); } return bufp; } -#if ENABLE_FEATURE_FDISK_WRITABLE -static void -set_all_unchanged(void) -{ - int i; - - for (i = 0; i < MAXIMUM_PARTS; i++) - ptes[i].changed = 0; -} - -static ALWAYS_INLINE void -set_changed(int i) -{ - ptes[i].changed = 1; -} -#endif /* FEATURE_FDISK_WRITABLE */ - static ALWAYS_INLINE struct partition * get_part_table(int i) { @@ -541,7 +510,67 @@ valid_part_table_flag(const char *mbuffer) return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa); } +static void fdisk_fatal(const char *why) +{ + if (listing) { + close_dev_fd(); + longjmp(listingbuf, 1); + } + bb_error_msg_and_die(why, disk_device); +} + +static void +seek_sector(sector_t secno) +{ +#if ENABLE_FDISK_SUPPORT_LARGE_DISKS + off64_t off = (off64_t)secno * sector_size; + if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1) + fdisk_fatal(unable_to_seek); +#else + uint64_t off = (uint64_t)secno * sector_size; + if (off > MAXINT(off_t) + || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1 + ) { + fdisk_fatal(unable_to_seek); + } +#endif +} + #if ENABLE_FEATURE_FDISK_WRITABLE +/* Read line; return 0 or first printable char */ +static int +read_line(const char *prompt) +{ + int sz; + + sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL); + if (sz <= 0) + exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ + + if (line_buffer[sz-1] == '\n') + line_buffer[--sz] = '\0'; + + line_ptr = line_buffer; + while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ') + line_ptr++; + return *line_ptr; +} + +static void +set_all_unchanged(void) +{ + int i; + + for (i = 0; i < MAXIMUM_PARTS; i++) + ptes[i].changed = 0; +} + +static ALWAYS_INLINE void +set_changed(int i) +{ + ptes[i].changed = 1; +} + static ALWAYS_INLINE void write_part_table_flag(char *b) { @@ -579,48 +608,18 @@ read_hex(const char *const *sys) continue; } v = bb_strtoul(line_ptr, NULL, 16); - if (v > 0xff) - /* Bad input also triggers this */ - continue; - return v; + if (v <= 0xff) + return v; } } -#endif /* FEATURE_FDISK_WRITABLE */ - -static void fdisk_fatal(const char *why) -{ - if (listing) { - close_dev_fd(); - longjmp(listingbuf, 1); - } - bb_error_msg_and_die(why, disk_device); -} static void -seek_sector(sector_t secno) -{ -#if ENABLE_FDISK_SUPPORT_LARGE_DISKS - off64_t off = (off64_t)secno * sector_size; - if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1) - fdisk_fatal(unable_to_seek); -#else - uint64_t off = (uint64_t)secno * sector_size; - if (off > MAXINT(off_t) - || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1 - ) { - fdisk_fatal(unable_to_seek); - } -#endif -} - -#if ENABLE_FEATURE_FDISK_WRITABLE -static void write_sector(sector_t secno, const void *buf) { seek_sector(secno); xwrite(dev_fd, buf, sector_size); } -#endif +#endif /* FEATURE_FDISK_WRITABLE */ #include "fdisk_aix.c" @@ -713,40 +712,42 @@ STATIC_SUN void sun_write_table(void); #include "fdisk_sun.c" -#if ENABLE_FEATURE_FDISK_WRITABLE -/* start_sect and nr_sects are stored little endian on all machines */ -/* moreover, they are not aligned correctly */ -static void -store4_little_endian(unsigned char *cp, unsigned val) +static inline_if_little_endian unsigned +read4_little_endian(const unsigned char *cp) { - cp[0] = val; - cp[1] = val >> 8; - cp[2] = val >> 16; - cp[3] = val >> 24; + uint32_t v; + move_from_unaligned32(v, cp); + return SWAP_LE32(v); } -#endif /* FEATURE_FDISK_WRITABLE */ -static unsigned -read4_little_endian(const unsigned char *cp) +static sector_t +get_start_sect(const struct partition *p) +{ + return read4_little_endian(p->start4); +} + +static sector_t +get_nr_sects(const struct partition *p) { - return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24); + return read4_little_endian(p->size4); } #if ENABLE_FEATURE_FDISK_WRITABLE -static void -set_start_sect(struct partition *p, unsigned start_sect) +/* start_sect and nr_sects are stored little endian on all machines */ +/* moreover, they are not aligned correctly */ +static inline_if_little_endian void +store4_little_endian(unsigned char *cp, unsigned val) { - store4_little_endian(p->start4, start_sect); + uint32_t v = SWAP_LE32(val); + move_to_unaligned32(cp, v); } -#endif -static sector_t -get_start_sect(const struct partition *p) +static void +set_start_sect(struct partition *p, unsigned start_sect) { - return read4_little_endian(p->start4); + store4_little_endian(p->start4, start_sect); } -#if ENABLE_FEATURE_FDISK_WRITABLE static void set_nr_sects(struct partition *p, unsigned nr_sects) { @@ -754,12 +755,6 @@ set_nr_sects(struct partition *p, unsigned nr_sects) } #endif -static sector_t -get_nr_sects(const struct partition *p) -{ - return read4_little_endian(p->size4); -} - /* Allocate a buffer and read a partition table sector */ static void read_pte(struct pte *pe, sector_t offset) @@ -942,7 +937,7 @@ get_sys_types(void) } #else #define get_sys_types() i386_sys_types -#endif /* FEATURE_FDISK_WRITABLE */ +#endif static const char * partition_type(unsigned char type) @@ -957,6 +952,24 @@ partition_type(unsigned char type) return "Unknown"; } +static int +is_cleared_partition(const struct partition *p) +{ + /* We consider partition "cleared" only if it has only zeros */ + const char *cp = (const char *)p; + int cnt = sizeof(*p); + char bits = 0; + while (--cnt >= 0) + bits |= *cp++; + return (bits == 0); +} + +static void +clear_partition(struct partition *p) +{ + if (p) + memset(p, 0, sizeof(*p)); +} #if ENABLE_FEATURE_FDISK_WRITABLE static int @@ -998,26 +1011,8 @@ list_types(const char *const *sys) } while (done < last[0]); bb_putchar('\n'); } -#endif /* FEATURE_FDISK_WRITABLE */ - -static int -is_cleared_partition(const struct partition *p) -{ - return !(!p || p->boot_ind || p->head || p->sector || p->cyl || - p->sys_ind || p->end_head || p->end_sector || p->end_cyl || - get_start_sect(p) || get_nr_sects(p)); -} static void -clear_partition(struct partition *p) -{ - if (!p) - return; - memset(p, 0, sizeof(struct partition)); -} - -#if ENABLE_FEATURE_FDISK_WRITABLE -static void set_partition(int i, int doext, sector_t start, sector_t stop, int sysid) { struct partition *p; @@ -1189,26 +1184,22 @@ read_extended(int ext) static void create_doslabel(void) { - int i; - printf(msg_building_new_label, "DOS disklabel"); current_label_type = LABEL_DOS; - #if ENABLE_FEATURE_OSF_LABEL possibly_osf_label = 0; #endif g_partitions = 4; - for (i = 510-64; i < 510; i++) - MBRbuffer[i] = 0; + memset(&MBRbuffer[510 - 4*16], 0, 4*16); write_part_table_flag(MBRbuffer); extended_offset = 0; set_all_unchanged(); set_changed(0); get_boot(CREATE_EMPTY_DOS); } -#endif /* FEATURE_FDISK_WRITABLE */ +#endif static void get_sectorsize(void) @@ -1721,9 +1712,10 @@ delete_partition(int i) ptes[i] = ptes[i+1]; i++; } - } else + } else { /* the only logical: clear only */ clear_partition(ptes[i].part_table); + } } } |