123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557 |
- /* fdisk.c - fdisk program to modify partitions on disk.
- *
- * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
- * Copyright 2013 Kyungwan Han <asura321@gmail.com>
- *
- * No Standard.
- USE_FDISK(NEWTOY(fdisk, "C#<0H#<0S#<0b#<512ul", TOYFLAG_SBIN))
- config FDISK
- bool "fdisk"
- default n
- help
- usage: fdisk [-lu] [-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SECTSZ] DISK
- Change partition table
- -u Start and End are in sectors (instead of cylinders)
- -l Show partition table for each DISK, then exit
- -b size sector size (512, 1024, 2048 or 4096)
- -C CYLINDERS Set number of cylinders/heads/sectors
- -H HEADS
- -S SECTORS
- */
- #define FOR_fdisk
- #include "toys.h"
- #include <linux/hdreg.h>
- GLOBALS(
- long sect_sz;
- long sectors;
- long heads;
- long cylinders;
- )
- #define EXTENDED 0x05
- #define WIN98_EXTENDED 0x0f
- #define LINUX_NATIVE 0x83
- #define LINUX_EXTENDED 0x85
- #define SECTOR_SIZE 512
- #define ONE_K 1024
- #define PARTITION_MAX 60 //partition max is modifiable
- #define IS_EXTENDED(i) ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
- #define sector(s) ((s) & 0x3f)
- #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
- typedef unsigned long long sector_t;
- struct partition {
- unsigned char boot_ind, head, sector, cyl, sys_ind, end_head,
- end_sector, end_cyl, start4[4], size4[4];
- };
- struct part_entry {
- struct partition *part;
- char *sec_buffer;
- sector_t start_offset;
- int modified;
- };
- struct part_types {
- int id;
- char type[24];
- } sys_types[] = {
- {0x00, "Empty"}, {0x01, "FAT12"}, {0x04, "FAT16 <32M"}, {0x05, "Extended"},
- {0x06, "FAT16"}, {0x07, "HPFS/NTFS"}, {0x0a, "OS/2 Boot Manager"},
- {0x0b, "Win95 FAT32"}, {0x0c, "Win95 FAT32 (LBA)"}, {0x0e, "Win95 FAT16 (LBA)"},
- {0x0f, "Win95 Ext'd (LBA)"}, {0x11, "Hidden FAT12"}, {0x12, "Compaq diagnostics"},
- {0x14, "Hidden FAT16 <32M"}, {0x16, "Hidden FAT16"}, {0x17, "Hidden HPFS/NTFS"},
- {0x1b, "Hidden Win95 FAT32"}, {0x1c, "Hidden W95 FAT32 (LBA)"}, {0x1e, "Hidden W95 FAT16 (LBA)"},
- {0x3c, "Part.Magic recovery"}, {0x41, "PPC PReP Boot"}, {0x42, "SFS"},
- {0x63, "GNU HURD or SysV"}, {0x80, "Old Minix"}, {0x81, "Minix / old Linux"},
- {0x82, "Linux swap"}, {0x83, "Linux"}, {0x84, "OS/2 hidden C: drive"},
- {0x85, "Linux extended"}, {0x86, "NTFS volume set"}, {0x87, "NTFS volume set"},
- {0x8e, "Linux LVM"}, {0x9f, "BSD/OS"}, {0xa0, "Thinkpad hibernation"},
- {0xa5, "FreeBSD"}, {0xa6, "OpenBSD"}, {0xa8, "Darwin UFS"}, {0xa9, "NetBSD"},
- {0xab, "Darwin boot"}, {0xb7, "BSDI fs"}, {0xb8, "BSDI swap"},
- {0xbe, "Solaris boot"}, {0xeb, "BeOS fs"}, {0xee, "EFI GPT"},
- {0xef, "EFI (FAT-12/16/32)"}, {0xf0, "Linux/PA-RISC boot"},
- {0xf2, "DOS secondary"}, {0xfd, "Linux raid autodetect"},
- };
- static int num_parts, disp_unit_cyl, dos_flag, dev_fd = 3;
- static long g_cylinders, g_heads, g_sectors, g_sect_size;
- static sector_t total_number_sectors, extended_offset;
- static char MBRbuf[2048], *disk_device;
- struct part_entry partitions[PARTITION_MAX];
- static struct partition* part_offset(char *secbuf, int i)
- {
- return (struct partition*)(secbuf + 0x1be + i*(sizeof(struct partition)));
- }
- static void set_levalue(unsigned char *cp, sector_t value )
- {
- uint32_t val = SWAP_LE32(value);
- memcpy(cp, (void*)&val, 4);
- }
- static void set_hsc(struct partition *p, sector_t start, sector_t end)
- {
- if (dos_flag && (start / (g_sectors * g_heads) > 1023))
- start = g_heads * g_sectors * ONE_K - 1;
- p->sector = (start % g_sectors) + 1;
- start /= g_sectors;
- p->head = start % g_heads;
- start /= g_heads;
- p->cyl = start & 0xFF;
- p->sector |= (start >> 2) & 0xc0;
- if (dos_flag && (end / (g_sectors * g_heads) > 1023))
- end = g_heads * g_sectors * ONE_K - 1;
- p->end_sector = (end % g_sectors) + 1;
- end /= g_sectors;
- p->end_head = end % g_heads;
- end /= g_heads;
- p->end_cyl = end & 0xFF;
- p->end_sector |= (end >> 2) & 0xc0;
- }
- static int chs_warn(void)
- {
- if (g_heads && g_sectors && g_cylinders)
- return 0;
- printf("Unknown value(s) for:");
- if (!g_heads) printf(" heads");
- if (!g_sectors) printf(" sectors");
- if (!g_cylinders) printf(" cylinders");
- printf(". can set in the expert menu.\n");
- return 1;
- }
- static void list_types(void)
- {
- int i, adjust = 0, size = ARRAY_LEN(sys_types);
-
- if(size % 2) adjust = 1;
- for (i = 0; i < (size - adjust); i+=2)
- xprintf("%2x %-22s\t\t%2x %-22.22s\n", sys_types[i].id, sys_types[i].type,
- sys_types[i+1].id, sys_types[i+1].type);
- if (adjust) xprintf("%2x %-22s\n",sys_types[size-1].id, sys_types[size-1].type);
- xputc('\n');
- }
- static void read_sec_sz()
- {
- int arg;
- if (ioctl(dev_fd, BLKSSZGET, &arg) == 0) g_sect_size = arg;
- if (FLAG(b)) {
- if (TT.sect_sz != 512 && TT.sect_sz != 1024 && TT.sect_sz != 2048 &&
- TT.sect_sz != 4096)
- {
- help_exit("bad sector size");
- }
- g_sect_size = TT.sect_sz;
- }
- }
- static sector_t read_size()
- {
- uint64_t sec64 = 0;
- unsigned long sectors = 0;
- if (ioctl(dev_fd, BLKGETSIZE64, &sec64) == 0) {
- sec64 = sec64 >> 9; //convert to 512 block size.
- if (sec64 != (uint32_t) sec64) {
- perror_msg("device has more than 2^32 sectors, can't use all of them");
- sec64 = (uint32_t) - 1L;
- }
- return sec64;
- }
- if (ioctl(dev_fd, BLKGETSIZE, §ors) == 0)
- if (sizeof(long) > sizeof(sector_t) && sectors != (sector_t)sectors)
- sectors = (uint32_t) - 1L;
- return sectors;
- }
- static int validate_part_buff(char *buffer)
- {
- if ((buffer[510] != 0x55) || (buffer[511] != 0xAA)) return 0;
- return 1;
- }
- static int is_partition_clear(struct partition* p)
- {
- int i = 0;
- unsigned char res = 0;
- const char *ptr = (const char*)p;
- for (i = 0; i < sizeof(struct partition); i++) res |= (unsigned char)ptr[i];
- return (res == 0x00);
- }
- static uint32_t swap_le32toh(unsigned char *cp)
- {
- uint32_t val;
- memcpy((void*)&val, cp, 4);
- return le32toh(val);
- }
- static int check_order(void)
- {
- sector_t first[num_parts], last_seen_val = 0;
- int i;
- struct part_entry *pe;
- struct partition *px;
- for (i = 0; i < num_parts; i++) {
- if (i == 4) last_seen_val = 0;
- pe = &partitions[i];
- px = pe->part;
- if (px->sys_ind) {
- first[i] = swap_le32toh(px->start4) + pe->start_offset;
- if (last_seen_val > first[i]) return 1;
- last_seen_val = first[i];
- }
- }
- return 0;
- }
- static void read_geometry(struct hd_geometry *disk)
- {
- struct hd_geometry geometry;
- if (ioctl(dev_fd, HDIO_GETGEO, &geometry)) return;
- disk->heads = geometry.heads;
- disk->sectors = geometry.sectors;
- }
- /* Read the extended boot record for the
- * logical partion details.
- */
- static void read_ebr(int idx)
- {
- char *sec_buf = NULL;
- sector_t offset = 0, local_start_off = 0;
- struct partition *p, *q;
- q = p = partitions[idx].part;
- local_start_off = swap_le32toh(p->start4);
- if (!extended_offset) extended_offset = local_start_off;
- do {
- if (num_parts >= 60) {
- xprintf("Warning: deleting partitions after 60\n");
- memset(q, 0, sizeof(struct partition)); //clear_partition
- partitions[num_parts-1].modified = 1;
- break;
- }
- sec_buf = xzalloc(g_sect_size);
- partitions[num_parts].part = part_offset(sec_buf, 0);
- partitions[num_parts].sec_buffer = sec_buf;
- offset = swap_le32toh(q->start4);
- if (num_parts > 4) offset += local_start_off;
- partitions[num_parts].start_offset = offset;
- xlseek(dev_fd, (off_t)(offset * g_sect_size), SEEK_SET);
- if (g_sect_size != readall(dev_fd, sec_buf, g_sect_size)) {
- close(dev_fd);
- error_exit("Couldn't read sector zero\n");
- }
- num_parts++; //extended partions present.
- q = part_offset(sec_buf, 1);
- } while (!is_partition_clear(q) && IS_EXTENDED(q->sys_ind));
- }
- static void physical_HS(int* h, int *s)
- {
- struct partition *p;
- int i, end_h, end_s, e_hh = 0, e_ss = 0, ini = 1, dirty = 0;
- const unsigned char *bufp = (const unsigned char *)MBRbuf;
- if (!(validate_part_buff((char*)bufp))) return;
- for (i = 0; i < 4; i++) {
- p = part_offset((char*)bufp, i);
- if (p->sys_ind) {
- end_h = p->end_head + 1;
- end_s = (p->end_sector & 077);
- if (ini) {
- e_hh = end_h;
- e_ss = end_s;
- ini = 0;
- } else if (e_hh !=end_h || e_ss != end_s)
- dirty = 1;
- }
- }
- if (!dirty && !ini) {
- *h = e_hh;
- *s = e_ss;
- }
- }
- //Reset the primary partition table
- static void reset_boot(int change)
- {
- int i;
- for(i = 0; i < 4; i++) {
- struct part_entry *pe = &partitions[i];
- pe->part = part_offset(MBRbuf, i);
- pe->start_offset = 0;
- pe->sec_buffer = MBRbuf;
- pe->modified = change;
- }
- }
- static inline void write_table_flag(char *buf)
- {
- buf[510] = 0x55;
- buf[511] = 0xaa;
- }
- /* free the buffers used for holding details of
- * extended logical partions
- */
- static void free_bufs(void)
- {
- int i = 4;
- for (; i < num_parts; i++) free(partitions[i].sec_buffer);
- }
- static void create_empty_doslabel(void)
- {
- xprintf("Building a new DOS Disklabel. The changes will\n"
- "remain in memory only, until you write it.\n");
- num_parts = 4;
- extended_offset = 0;
- memset(&MBRbuf[510 - 4*16], 0, 4*16);
- write_table_flag(MBRbuf);
- partitions[0].modified = 1;
- reset_boot(1);
- }
- /* Read the Master Boot sector of the device for the
- * partition table entries/details.
- * If any extended partition is found then read the EBR
- * for logical partition details
- */
- static int read_mbr(char *device, int validate)
- {
- int fd, sector_fac, i, h = 0, s = 0;
- struct hd_geometry disk;
- fd = open(device, O_RDWR);
- if(fd < 0) {
- perror_msg("can't open '%s'",device);
- return 1;
- }
- disk_device = strdup(device);
- if(fd != dev_fd) {
- if(dup2(fd, dev_fd) != dev_fd) perror_exit("Can't dup2");
- close(fd);
- }
- //read partition table - MBR
- if (SECTOR_SIZE != readall(dev_fd, MBRbuf, SECTOR_SIZE)) {
- close(dev_fd);
- perror_exit("Couldn't read sector zero\n");
- }
- if (validate && !validate_part_buff(MBRbuf)) {
- xprintf("Device contains neither a valid DOS "
- "partition table, nor Sun, SGI, OSF or GPT "
- "disklabel\n");
- create_empty_doslabel();
- }
- disk.heads = disk.sectors = 0;
- read_geometry(&disk); //CHS values
- total_number_sectors = read_size(); //Device size
- read_sec_sz();
- sector_fac = g_sect_size/SECTOR_SIZE; //512 is hardware sector size.
- physical_HS(&h, &s); //physical dimensions may be diferent from HDIO_GETGEO
- g_sectors = (FLAG(S) && TT.sectors) ? TT.sectors : s ? s : disk.sectors ? disk.sectors : 63;
- g_heads = (FLAG(H) && TT.heads) ? TT.heads : h ? h : disk.heads ? disk.heads : 255;
- g_cylinders = total_number_sectors/(g_heads * g_sectors * sector_fac);
- if (!g_cylinders) g_cylinders = FLAG(C) ? TT.cylinders : 0;
- if ((g_cylinders > ONE_K) && !(FLAG(l) || FLAG(S)))
- xprintf("\nThe number of cylinders for this disk is set to %lu.\n"
- "There is nothing wrong with that, but this is larger than 1024,\n"
- "and could in certain setups cause problems.\n", g_cylinders);
- for (i = 0; i < num_parts; i++) {
- if (IS_EXTENDED(partitions[i].part->sys_ind)) {
- read_ebr(i);
- break;
- }
- }
- chs_warn();
- return 0;
- }
- static char* get_type(int sys_ind)
- {
- int i, size = ARRAY_LEN(sys_types);
- for (i = 0; i < size; i++)
- if (sys_ind == sys_types[i].id)
- return sys_types[i].type;
- return "Unknown";
- }
- static void consistency_check(const struct partition *p, int partition)
- {
- unsigned physbc, physbh, physbs, physec, physeh, physes;
- unsigned lbc, lbh, lbs, lec, leh, les;
- sector_t start, end;
- if (!g_heads || !g_sectors || (partition >= 4)) return;
- // physical beginning c, h, s
- physbc = cylinder(p->sector,p->cyl);
- physbh = p->head;
- physbs = sector(p->sector);
- // physical ending c, h, s
- physec = cylinder(p->end_sector, p->end_cyl);
- physeh = p->end_head;
- physes = sector(p->end_sector);
- // logical begin and end CHS values
- start = swap_le32toh((unsigned char*)(p->start4));
- end = start + swap_le32toh((unsigned char*)(p->size4)) -1;
- lbc = start/(g_sectors * g_heads);
- lbh = (start/g_sectors) % g_heads;
- lbs = (start % g_sectors) + 1;
- lec = end/(g_sectors * g_heads);
- leh = (end/g_sectors) % g_heads;
- les = (end % g_sectors) + 1;
- //Logical and Physical diff
- if (g_cylinders <= ONE_K && (physbc != lbc || physbh != lbh || physbs != lbs)) {
- xprintf("Partition %u has different physical/logical beginnings (Non-Linux?): \n", partition+1);
- xprintf("phys = (%u %u %u) ",physbc, physbh, physbs);
- xprintf("logical = (%u %u %u)\n", lbc, lbh, lbs);
- }
- if (g_cylinders <= ONE_K && (physec != lec || physeh != leh || physes != les)) {
- xprintf("Partition %u has different physical/logical endings: \n", partition+1);
- xprintf("phys = (%u %u %u) ",physec, physeh, physes);
- xprintf("logical = (%u %u %u)\n", lec, leh, les);
- }
- // Ending on cylinder boundary?
- if (physeh != (g_heads - 1) || physes != g_sectors)
- xprintf("Partition %u does not end on cylinder boundary\n", partition + 1);
- }
- // List the partition details
- static void list_partitions(int validate)
- {
- struct partition *p;
- uint32_t start_cyl, end_cyl, start_sec, end_sec, blocks, secs;
- char boot, lastchar = '\0', *dev = disk_device;
- int i = 0, len = strlen(disk_device), odds = 0;
- if (validate && !validate_part_buff(MBRbuf)) {
- close(dev_fd);
- toys.exitval = 1;
- xprintf("Device %s: doesn't contain a valid partition table\n", disk_device);
- return;
- }
- if (isdigit(dev[len - 1])) lastchar = 'p';
- xprintf("%*s Boot Start End Blocks Id System\n", len+1, "Device");
- for (i = 0; i < num_parts; i++) {
- p = partitions[i].part;
- if (is_partition_clear(p)) continue;
- boot = ((p->boot_ind == 0x80)?'*':(!p->boot_ind)?' ':'?');
- start_sec = swap_le32toh(p->start4) + partitions[i].start_offset;
- secs = swap_le32toh(p->size4);
- if ((start_sec + secs) == 0) end_sec = 0;
- else end_sec = start_sec + secs -1;
- start_cyl = start_sec/(g_heads * g_sectors) + 1;
- end_cyl = end_sec/(g_heads * g_sectors) + 1;
- blocks = secs;
- if (g_sect_size < ONE_K) {
- blocks /= (ONE_K/g_sect_size);
- odds = secs %(ONE_K/g_sect_size);
- } else if (g_sect_size > ONE_K) blocks *= (g_sect_size/ONE_K);
- if (lastchar) xprintf("%s%c%d",dev, lastchar, i+1);
- else xprintf("%s%d",dev, i+1);
- xprintf(" %c %11u %11u %11u%c %2x %s\n",
- boot,
- disp_unit_cyl == 0? start_sec: start_cyl,
- disp_unit_cyl == 0? end_sec: end_cyl,
- blocks,odds?'+':' ', p->sys_ind, get_type(p->sys_ind));
- consistency_check(p, i);
- }
- if (check_order()) xprintf("\nPartition table entries are not in disk order");
- }
- //Print device details
- static void print_mbr(int validate)
- {
- unsigned long long bytes = ((unsigned long long)total_number_sectors << 9);
- long mbytes = bytes/1000000;
- if (mbytes < 10000) xprintf("Disk %s: %lu MB, %llu bytes\n", disk_device, mbytes, bytes);
- else xprintf("Disk %s: %lu.%lu GB, %llu bytes\n", disk_device, mbytes/1000, (mbytes/100)%10, bytes);
- xprintf("%ld heads, %ld sectors/track, %ld cylinders", g_heads, g_sectors, g_cylinders);
- if (!disp_unit_cyl) {
- xprintf(", total %lld sectors\n", total_number_sectors/(g_sect_size/SECTOR_SIZE));
- xprintf("Units = sectors of 1 * %ld = %ld bytes\n",g_sect_size, g_sect_size);
- } else xprintf("\nUnits = cylinders of %ld * %ld = %ld bytes\n\n",
- g_heads * g_sectors, g_sect_size, g_heads * g_sectors * g_sect_size);
- list_partitions(validate);
- xputc('\n');
- }
- static void init_members(void)
- {
- int i = 0;
- num_parts = 4; //max of primaries in a part table
- disp_unit_cyl = dos_flag = 1;
- extended_offset = 0;
- g_sect_size = SECTOR_SIZE;
- for (i = 0; i < num_parts; i++) {
- partitions[i].part = part_offset(MBRbuf, i);
- partitions[i].sec_buffer = MBRbuf;
- partitions[i].modified = 0;
- partitions[i].start_offset = 0;
- }
- }
- static int read_input(char *mesg, char *outp)
- {
- char *p;
- int size = 0;
- do {
- xprintf("%s", mesg);
- p = fgets(toybuf, 80, stdin);
-
- if (!p || !(size = strlen(p))) exit(0);
- if (p[size-1] == '\n') p[--size] = '\0';
- } while (!size);
- while (*p != '\0' && *p <= ' ') p++;
- if (outp) memcpy(outp, p, strlen(p) + 1); //1 for nul
- return *p;
- }
- static int read_hex(char *mesg)
- {
- int val;
- char input[80], *endp;
- while (1) {
- read_input(mesg, input);
- if ((*input | 0x20) == 'l') {
- list_types();
- memset(input, 0, 80);
- continue;
- }
- val = strtoul(input, &endp, 16);
- if (endp && *endp) continue;
- if (val <= 0xff) return val;
- }
- }
- /* Delete an exiting partition,
- * if its primary, then just clear the partition details
- * if extended, then clear the partition details, also for logical
- * if only logical, then move the later partitions backwards 1 step
- */
- void delete_partition(int i)
- {
- int sys_id, looper = 0;
- struct partition *p, *q, *ext_p, *ext_q;
- sector_t new_start;
- struct part_entry *pe = &partitions[i];
-
- if (chs_warn()) return;
- p = pe->part;
- sys_id = p->sys_ind;
- if (!sys_id) xprintf("Partition %u is empty\n", i+1);
- if (i < 4 && !IS_EXTENDED(sys_id)) {
- memset(p, 0, sizeof(struct partition)); //clear_partition
- pe->modified = 1;
- } else if (i < 4 && IS_EXTENDED(sys_id)) {
- memset(p, 0, sizeof(struct partition)); //clear_partition
- pe->modified = 1;
- for (looper = 4; looper < num_parts; looper++) {
- pe = &partitions[looper];
- p = pe->part;
- if (is_partition_clear(p)) break;
- else {
- memset(p, 0, sizeof(struct partition)); //clear_partition
- pe->modified = 1;
- free(pe->sec_buffer);
- }
- }
- extended_offset = 0;
- num_parts = 4;
- } else {
- //only logical is delete, need to move the rest of them backwards
- if (i == 4) { //move partiton# 6 to 5.
- partitions[i].modified = 1;
- if (num_parts > i+1) {
- q = partitions[i + 1].part;
- *p = *q; //copy the part table
- ext_p = part_offset(partitions[i].sec_buffer, 1);
- ext_q = part_offset(partitions[i + 1].sec_buffer, 1);
- *ext_p = *ext_q; //copy the extended info pointer
- // change the start of the 4th partiton.
- new_start = partitions[i + 1].start_offset + swap_le32toh(q->start4) - extended_offset;
- new_start = SWAP_LE32(new_start);
- memcpy(p->start4, (void *)&new_start, 4);
- } else {
- memset(partitions[i].part, 0, sizeof(struct partition));
- return; //only logical
- }
- } else if (i > 4) {
- ext_p = part_offset(partitions[i-1].sec_buffer, 1);
- ext_q = part_offset(partitions[i].sec_buffer, 1);
- memcpy((void*)ext_p, (void *)ext_q, sizeof(struct partition));
- partitions[i-1].modified = 1;
- }
- if (i == 4) looper = i+2;
- else if (i > 4) looper = i+1;
- for (; looper < num_parts; looper++)
- partitions[looper-1] = partitions[looper];
- num_parts--;
- }
- }
- static int ask_partition(int num_parts)
- {
- int val;
- while (1) {
- do {
- xprintf("Partition (%u - %u):", 1, num_parts);
- fgets(toybuf, 80, stdin);
- } while (!isdigit(*toybuf));
- val = atoi(toybuf);
- if (val > 0 && val <= num_parts) return val;
- else xprintf("Invalid number entered\n");
- }
- }
- static void toggle_active_flag(int i)
- {
- struct partition *p = partitions[i].part;
- if (is_partition_clear(p)) xprintf("Partition %u is empty\n", i+1);
-
- if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
- xprintf("WARNING: Partition %u is an extended partition\n", i + 1);
- p->boot_ind = p->boot_ind == 0x80?0 : 0x80;
- partitions[i].modified = 1;
- }
- //Write the partition details from Buffer to Disk.
- void write_table(void)
- {
- int i =0;
- struct part_entry *pe;
- sector_t offset;
- for (i = 0; i < 4; i++)
- if (partitions[i].modified) partitions[3].modified = 1;
- for (i = 3; i < num_parts; i++) {
- pe = &partitions[i];
- write_table_flag(pe->sec_buffer);
- offset = pe->start_offset;
- if (pe->modified == 1) {
- xlseek(dev_fd, offset * g_sect_size, SEEK_SET);
- xwrite(dev_fd, pe->sec_buffer, g_sect_size);
- }
- }
- xprintf("The partition table has been altered.\n");
- xprintf("Calling ioctl() to re-read partition table\n");
- sync();
- for (i = 4; i < num_parts; i++) free(partitions[i].sec_buffer);
- if(ioctl(dev_fd, BLKRRPART, NULL) < 0)
- perror_exit("WARNING: rereading partition table failed, kernel still uses old table");
- }
- /* try to find a partition for deletion, if only
- * one, then select the same, else ask from USER
- */
- static int get_non_free_partition(int max)
- {
- int num = -1, i = 0;
- for (i = 0; i < max; i++) {
- if (!is_partition_clear(partitions[i].part)) {
- if (num >= 0)
- return ask_partition(num_parts)-1;
- num = i;
- }
- }
- (num >= 0) ? xprintf("Selected partition %d\n",num+1):
- xprintf("No partition is defined yet!\n");
- return num;
- }
- /* a try at autodetecting an empty partition table entry,
- * if multiple options then get USER's choce.
- */
- static int get_free_partition(int max)
- {
- int num = -1, i = 0;
- for (i = 0; i < max; i++) {
- if (is_partition_clear(partitions[i].part)) {
- if (num >= 0)
- return ask_partition(4)-1;
- num = i;
- }
- }
- (num >= 0) ? xprintf("Selected partition %d\n",num+1):
- xprintf("All primary partitions have been defined already!\n");
- return num;
- }
- //taking user input for partition start/end sectors/cyinders
- static uint32_t ask_value(char *mesg, sector_t left, sector_t right, sector_t defalt)
- {
- char *str = toybuf;
- uint32_t val;
- int use_default = 1;
- while (1) {
- use_default = 1;
- do {
- xprintf("%s",mesg);
- fgets(str, 80, stdin);
- } while (!isdigit(*str) && (*str != '\n')
- && (*str != '-') && (*str != '+') && (!isblank(*str)));
- while (isblank(*str)) str++; //remove leading white spaces
- if (*str == '+' || *str == '-') {
- int minus = (*str == '-');
- int absolute = 0;
- val = atoi(str + 1);
- while (isdigit(*++str)) use_default = 0;
- switch (*str) {
- case 'c':
- case 'C':
- if (!disp_unit_cyl) val *= g_heads * g_sectors;
- break;
- case 'K':
- absolute = ONE_K;
- break;
- case 'k':
- absolute = 1000;
- break;
- case 'm':
- case 'M':
- absolute = 1000000;
- break;
- case 'g':
- case 'G':
- absolute = 1000000000;
- break;
- default:
- break;
- }
- if (absolute) {
- unsigned long long bytes = (unsigned long long) val * absolute;
- unsigned long unit = (disp_unit_cyl && (g_heads * g_sectors))? g_heads * g_sectors : 1;
- unit = unit * g_sect_size;
- bytes += unit/2; // rounding
- bytes /= unit;
- val = bytes;
- }
- if (minus)
- val = -val;
- val += left;
- } else {
- val = atoi(str);
- while (isdigit(*str)) {
- str++;
- use_default = 0;
- }
- }
- if(use_default) {
- val = defalt;
- xprintf("Using default value %lld\n", defalt);
- }
- if (val >= left && val <= right) return val;
- else xprintf("Value out of range\n");
- }
- }
- //validating if the start given falls in a limit or not
- static int validate(int start_index, sector_t* begin,sector_t* end, sector_t start
- , int asked)
- {
- int i, valid = 0;
- for (i = start_index; i < num_parts; i++) {
- if (start >= begin[i] && start <= end[i]) {
- if (asked) xprintf("Sector %lld is already allocated\n",start);
- valid = 0;
- break;
- } else valid = 1;
- }
- return valid;
- }
- //get the start sector/cylinder of a new partition
- static sector_t ask_start_sector(int idx, sector_t* begin, sector_t* end, int ext_idx)
- {
- sector_t start, limit, temp = 0, start_cyl, limit_cyl, offset = 1;
- char mesg[256];
- int i, asked = 0, valid = 0, start_index = 0;
- if (dos_flag) offset = g_sectors;
- start = offset;
- if (disp_unit_cyl) limit = (sector_t)g_sectors * g_heads * g_cylinders - 1;
- else limit = total_number_sectors - 1;
- if (disp_unit_cyl) //make the begin of every partition to cylnder boundary
- for (i = 0; i < num_parts; i++)
- begin[i] = (begin[i]/(g_heads* g_sectors)) * (g_heads* g_sectors);
- if (idx >= 4) {
- if (!begin[ext_idx] && extended_offset) begin[ext_idx] = extended_offset;
- start = begin[ext_idx] + offset;
- limit = end[ext_idx];
- start_index = 4;
- }
- do {
- if (asked) valid = validate(start_index, begin, end, start, asked);
- if (valid) break;
- do {
- for (i = start_index; i < num_parts; i++)
- if (start >= begin[i] && start <= end[i])
- start = end[i] + 1 + ((idx >= 4)? offset : 0);
- } while (!validate(start_index, begin, end, start, 0));
- start_cyl = start/(g_sectors * g_heads) + 1;
- limit_cyl = limit/(g_sectors * g_heads) + 1;
- if (start > limit) break;
- sprintf(mesg, "First %s (%lld - %lld, default %lld): ", disp_unit_cyl? "cylinder" : "sector",
- (long long int)(disp_unit_cyl? start_cyl : start),
- (long long int)(disp_unit_cyl? limit_cyl : limit),
- (long long int)(disp_unit_cyl? start_cyl : start));
- temp = ask_value(mesg, disp_unit_cyl? start_cyl : start,
- disp_unit_cyl? limit_cyl : limit, disp_unit_cyl? start_cyl : start);
- asked = 1;
- if (disp_unit_cyl) {
- // point to the cylinder start sector
- temp = (temp-1) * g_heads * g_sectors;
- if (temp < start) //the boundary is falling in the already used sectors.
- temp = start;
- }
- start = temp;
- } while (asked && !valid);
- return start;
- }
- //get the end sector/cylinder of a new partition
- static sector_t ask_end_sector(int idx, sector_t* begin, sector_t* end, int ext_idx, sector_t start_sec)
- {
- sector_t limit, temp = 0, start_cyl, limit_cyl, start = start_sec;
- char mesg[256];
- int i;
- if (disp_unit_cyl) limit = (sector_t)g_sectors * g_heads * g_cylinders - 1;
- else limit = total_number_sectors - 1;
- if (disp_unit_cyl) //make the begin of every partition to cylnder boundary
- for (i = 0; i < num_parts; i++)
- begin[i] = (begin[i]/(g_heads* g_sectors)) * (g_heads* g_sectors);
- if (idx >= 4) limit = end[ext_idx];
- for (i = 0; i < num_parts; i++) {
- struct part_entry *pe = &partitions[i];
- if (start < pe->start_offset && limit >= pe->start_offset) limit = pe->start_offset - 1;
- if (start < begin[i] && limit >= begin[i]) limit = begin[i] - 1;
- }
- start_cyl = start/(g_sectors * g_heads) + 1;
- limit_cyl = limit/(g_sectors * g_heads) + 1;
- if (limit < start) { //the boundary is falling in the already used sectors.
- xprintf("No Free sectors available\n");
- return 0;
- }
- sprintf(mesg, "Last %s or +size or +sizeM or +sizeK (%lld - %lld, default %lld): ",
- disp_unit_cyl? "cylinder" : "sector",
- (long long int)(disp_unit_cyl? start_cyl : start),
- (long long int)(disp_unit_cyl? limit_cyl : limit),
- (long long int)(disp_unit_cyl? limit_cyl : limit));
- temp = ask_value(mesg, disp_unit_cyl? start_cyl : start,
- disp_unit_cyl? limit_cyl : limit, disp_unit_cyl? limit_cyl : limit);
- if (disp_unit_cyl) { // point to the cylinder start sector
- temp = temp * g_heads * g_sectors - 1;
- if (temp > limit) temp = limit;
- }
- if (temp < start) { //the boundary is falling in the already used sectors.
- xprintf("No Free sectors available\n");
- return 0;
- }
- return temp;
- }
- // add a new partition to the partition table
- static int add_partition(int idx, int sys_id)
- {
- int i, ext_idx = -1;
- sector_t start, end, begin_sec[num_parts], end_sec[num_parts];
- struct part_entry *pe = &partitions[idx];
- struct partition *p = pe->part;
- if (p && !is_partition_clear(p)) {
- xprintf("Partition %u is already defined, delete it to re-add\n", idx+1);
- return 0;
- }
- for (i = 0; i < num_parts; i++) {
- pe = &partitions[i];
- p = pe->part;
- if (is_partition_clear(p)) {
- begin_sec[i] = 0xffffffff;
- end_sec[i] = 0;
- } else {
- begin_sec[i] = swap_le32toh(p->start4) + pe->start_offset;
- end_sec[i] = begin_sec[i] + swap_le32toh(p->size4) - 1;
- }
- if (IS_EXTENDED(p->sys_ind)) ext_idx = i;
- }
- start = ask_start_sector(idx, begin_sec, end_sec, ext_idx);
- end = ask_end_sector(idx, begin_sec, end_sec, ext_idx, start);
- if (!end) return 0;
- //Populate partition table entry - 16 bytes
- pe = &partitions[idx];
- p = pe->part;
- if (idx > 4) {
- if (dos_flag) pe->start_offset = start - (sector_t)g_sectors;
- else pe->start_offset = start - 1;
- if (pe->start_offset == extended_offset) pe->start_offset++;
- if (!dos_flag) start++;
- }
-
- set_levalue(p->start4, start - pe->start_offset);
- set_levalue(p->size4, end - start + 1);
- set_hsc(p, start, end);
- p->boot_ind = 0;
- p->sys_ind = sys_id;
- pe->modified = 1;
- if (idx > 4) {
- p = partitions[idx-1].part + 1; //extended pointer for logical partitions
- set_levalue(p->start4, pe->start_offset - extended_offset);
- set_levalue(p->size4, end - start + 1 + (dos_flag? g_sectors: 1));
- set_hsc(p, pe->start_offset, end);
- p->boot_ind = 0;
- p->sys_ind = EXTENDED;
- partitions[idx-1].modified = 1;
- }
- if (IS_EXTENDED(sys_id)) {
- pe = &partitions[4];
- pe->modified = 1;
- pe->sec_buffer = xzalloc(g_sect_size);
- pe->part = part_offset(pe->sec_buffer, 0);
- pe->start_offset = extended_offset = start;
- num_parts = 5;
- }
- return 1;
- }
- static void add_logical_partition(void)
- {
- struct part_entry *pe;
- if (num_parts > 5 || !is_partition_clear(partitions[4].part)) {
- pe = &partitions[num_parts];
- pe->modified = 1;
- pe->sec_buffer = xzalloc(g_sect_size);
- pe->part = part_offset(pe->sec_buffer, 0);
- pe->start_offset = 0;
- num_parts++;
- if (!add_partition(num_parts - 1, LINUX_NATIVE)) {
- num_parts--;
- free(pe->sec_buffer);
- }
- }
- else add_partition(num_parts -1, LINUX_NATIVE);
- }
- /* Add a new partiton to the partition table.
- * MAX partitions limit is taken to be 60, can be changed
- */
- static void add_new_partition(void)
- {
- int choice, idx, i, free_part = 0;
- char *msg = NULL;
-
- if (chs_warn()) return;
- for (i = 0; i < 4; i++) if(is_partition_clear(partitions[i].part)) free_part++;
- if (!free_part && num_parts >= 60) {
- xprintf("The maximum number of partitions has been created\n");
- return;
- }
- if (!free_part) {
- if (extended_offset) add_logical_partition();
- else xprintf("You must delete some partition and add "
- "an extended partition first\n");
- return;
- }
- msg = xmprintf(" %s\n p primary partition(1-4)\n",
- extended_offset? "l logical (5 or over)" : "e extended");
- choice = 0x20 | read_input(msg, NULL);
- free(msg);
- if (choice == 'p') {
- idx = get_free_partition(4);
- if (idx >= 0) add_partition(idx, LINUX_NATIVE);
- return;
- }
- if (choice =='l' && extended_offset) {
- add_logical_partition();
- return;
- }
- if (choice == 'e' && !extended_offset) {
- idx = get_free_partition(4);
- if (idx >= 0) add_partition(idx, EXTENDED);
- return;
- }
- }
- static void change_systype(void )
- {
- int i, sys_id;
- struct partition *p;
- struct part_entry *pe;
- i = ask_partition(num_parts);
- pe = &partitions[i-1];
- p = pe->part;
- if (is_partition_clear(p)) {
- xprintf("Partition %d doesn't exist yet!\n", i);
- return;
- }
- sys_id = read_hex("Hex code (L to list codes): ");
- if ((IS_EXTENDED(p->sys_ind) && !IS_EXTENDED(sys_id)) ||
- (!IS_EXTENDED(p->sys_ind) && IS_EXTENDED(sys_id))) {
- xprintf("you can't change a partition to an extended or vice-versa\n");
- return;
- }
- xprintf("Changed system type of partition %u to %0x (%s)\n",i, sys_id, get_type(sys_id));
- p->sys_ind = sys_id;
- pe->modified = 1;
- }
- static void check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
- {
- sector_t total, real_s, real_c;
- real_s = sector(s) - 1;
- real_c = cylinder(s, c);
- total = (real_c * g_sectors + real_s) * g_heads + h;
- if (!total) xprintf("Partition %u contains sector 0\n", n);
- if (h >= g_heads)
- xprintf("Partition %u: head %u greater than maximum %lu\n", n, h + 1, g_heads);
- if (real_s >= g_sectors)
- xprintf("Partition %u: sector %u greater than maximum %lu\n", n, s, g_sectors);
- if (real_c >= g_cylinders)
- xprintf("Partition %u: cylinder %lld greater than maximum %lu\n", n, real_c + 1, g_cylinders);
- if (g_cylinders <= ONE_K && start != total)
- xprintf("Partition %u: previous sectors %lld disagrees with total %lld\n", n, start, total);
- }
- static void verify_table(void)
- {
- int i, j, ext_idx = -1;
- sector_t begin_sec[num_parts], end_sec[num_parts], total = 1;
- struct part_entry *pe;
- struct partition *p;
- for (i = 0; i < num_parts; i++) {
- pe = &partitions[i];
- p = pe->part;
- if (is_partition_clear(p) || IS_EXTENDED(p->sys_ind)) {
- begin_sec[i] = 0xffffffff;
- end_sec[i] = 0;
- } else {
- begin_sec[i] = swap_le32toh(p->start4) + pe->start_offset;
- end_sec[i] = begin_sec[i] + swap_le32toh(p->size4) - 1;
- }
- if (IS_EXTENDED(p->sys_ind)) ext_idx = i;
- }
- for (i = 0; i < num_parts; i++) {
- pe = &partitions[i];
- p = pe->part;
- if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
- consistency_check(p, i);
- if ((swap_le32toh(p->start4) + pe->start_offset) < begin_sec[i])
- xprintf("Warning: bad start-of-data in partition %u\n", i + 1);
- check(i + 1, p->end_head, p->end_sector, p->end_cyl, end_sec[i]);
- total += end_sec[i] + 1 - begin_sec[i];
- for (j = 0; j < i; j++) {
- if ((begin_sec[i] >= begin_sec[j] && begin_sec[i] <= end_sec[j])
- || ((end_sec[i] <= end_sec[j] && end_sec[i] >= begin_sec[j]))) {
- xprintf("Warning: partition %u overlaps partition %u\n", j + 1, i + 1);
- total += begin_sec[i] >= begin_sec[j] ? begin_sec[i] : begin_sec[j];
- total -= end_sec[i] <= end_sec[j] ? end_sec[i] : end_sec[j];
- }
- }
- }
- }
- if (extended_offset) {
- struct part_entry *pex = &partitions[ext_idx];
- sector_t e_last = swap_le32toh(pex->part->start4) +
- swap_le32toh(pex->part->size4) - 1;
- for (i = 4; i < num_parts; i++) {
- total++;
- p = partitions[i].part;
- if (!p->sys_ind) {
- if (i != 4 || i + 1 < num_parts)
- xprintf("Warning: partition %u is empty\n", i + 1);
- } else if (begin_sec[i] < extended_offset || end_sec[i] > e_last)
- xprintf("Logical partition %u not entirely in partition %u\n", i + 1, ext_idx + 1);
- }
- }
- if (total > g_heads * g_sectors * g_cylinders)
- xprintf("Total allocated sectors %lld greater than the maximum "
- "%lu\n", total, g_heads * g_sectors * g_cylinders);
- else {
- total = g_heads * g_sectors * g_cylinders - total;
- if (total) xprintf("%lld unallocated sectors\n", total);
- }
- }
- static void move_begning(int idx)
- {
- sector_t start, num, new_start, end;
- char mesg[256];
- struct part_entry *pe = &partitions[idx];
- struct partition *p = pe->part;
- if (chs_warn()) return;
- start = swap_le32toh(p->start4) + pe->start_offset;
- num = swap_le32toh(p->size4);
- end = start + num -1;
- if (!num || IS_EXTENDED(p->sys_ind)) {
- xprintf("Partition %u doesn't have data area\n", idx+1);
- return;
- }
- sprintf(mesg, "New beginning of data (0 - %lld, default %lld): ",
- (long long int)(end), (long long int)(start));
- new_start = ask_value(mesg, 0, end, start);
- if (new_start != start) {
- set_levalue(p->start4, new_start - pe->start_offset);
- set_levalue(p->size4, end - new_start +1);
- if ((read_input("Recalculate C/H/S (Y/n): ", NULL) | 0x20) == 'y')
- set_hsc(p, new_start, end);
- pe->modified = 1;
- }
- }
- static void print_raw_sectors()
- {
- int i, j;
- struct part_entry *pe;
- xprintf("Device: %s\n", disk_device);
- for (i = 3; i < num_parts; i++) {
- pe = &partitions[i];
- for (j = 0; j < g_sect_size; j++) {
- if (!(j % 16)) xprintf("\n0x%03X: ",j);
- xprintf("%02X ",pe->sec_buffer[j]);
- }
- xputc('\n');
- }
- }
- static void print_partitions_list(int ext)
- {
- int i;
- struct part_entry *pe;
- struct partition *p;
- xprintf("Disk %s: %lu heads, %lu sectors, %lu cylinders\n\n", disk_device, g_heads, g_sectors, g_cylinders);
- xprintf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
- for (i = 0; i < num_parts; i++) {
- pe = &partitions[i];
- p = pe->part;
- if (p) {
- if (ext && (i >= 4)) p = pe->part + 1;
- if(ext && i < 4 && !IS_EXTENDED(p->sys_ind)) continue;
- xprintf("%2u %02x%4u%4u%5u%4u%4u%5u%11u%11u %02x\n",
- i+1, p->boot_ind, p->head,
- sector(p->sector), cylinder(p->sector, p->cyl),
- p->end_head,
- sector(p->end_sector), cylinder(p->end_sector, p->end_cyl),
- swap_le32toh(p->start4),
- swap_le32toh(p->size4),
- p->sys_ind);
- if (p->sys_ind) consistency_check(p, i);
- }
- }
- }
- //fix the partition table order to ascending
- static void fix_order(void)
- {
- sector_t first[num_parts], min;
- int i, j, oj, ojj, sj, sjj;
- struct part_entry *pe;
- struct partition *px, *py, temp, *pj, *pjj, tmp;
- for (i = 0; i < num_parts; i++) {
- pe = &partitions[i];
- px = pe->part;
- if (is_partition_clear(px)) first[i] = 0xffffffff;
- else first[i] = swap_le32toh(px->start4) + pe->start_offset;
- }
-
- if (!check_order()) {
- xprintf("Ordering is already correct\n\n");
- return;
- }
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 3; j++) {
- if (first[j] > first[j+1]) {
- py = partitions[j+1].part;
- px = partitions[j].part;
- memcpy(&temp, py, sizeof(struct partition));
- memcpy(py, px, sizeof(struct partition));
- memcpy(px, &temp, sizeof(struct partition));
- min = first[j+1];
- first[j+1] = first[j];
- first[j] = min;
- partitions[j].modified = 1;
- }
- }
- }
- for (i = 5; i < num_parts; i++) {
- for (j = 5; j < num_parts - 1; j++) {
- oj = partitions[j].start_offset;
- ojj = partitions[j+1].start_offset;
- if (oj > ojj) {
- partitions[j].start_offset = ojj;
- partitions[j+1].start_offset = oj;
- pj = partitions[j].part;
- set_levalue(pj->start4, swap_le32toh(pj->start4)+oj-ojj);
- pjj = partitions[j+1].part;
- set_levalue(pjj->start4, swap_le32toh(pjj->start4)+ojj-oj);
- set_levalue((partitions[j-1].part+1)->start4, ojj-extended_offset);
- set_levalue((partitions[j].part+1)->start4, oj-extended_offset);
- }
- }
- }
- for (i = 4; i < num_parts; i++) {
- for (j = 4; j < num_parts - 1; j++) {
- pj = partitions[j].part;
- pjj = partitions[j+1].part;
- sj = swap_le32toh(pj->start4);
- sjj = swap_le32toh(pjj->start4);
- oj = partitions[j].start_offset;
- ojj = partitions[j+1].start_offset;
- if (oj+sj > ojj+sjj) {
- tmp = *pj;
- *pj = *pjj;
- *pjj = tmp;
- set_levalue(pj->start4, ojj+sjj-oj);
- set_levalue(pjj->start4, oj+sj-ojj);
- }
- }
- }
- // If anything changed
- for (j = 4; j < num_parts; j++) partitions[j].modified = 1;
- xprintf("Done!\n");
- }
- static void print_menu(void)
- {
- xprintf("a\ttoggle a bootable flag\n"
- "b\tedit bsd disklabel\n"
- "c\ttoggle the dos compatibility flag\n"
- "d\tdelete a partition\n"
- "l\tlist known partition types\n"
- "n\tadd a new partition\n"
- "o\tcreate a new empty DOS partition table\n"
- "p\tprint the partition table\n"
- "q\tquit without saving changes\n"
- "s\tcreate a new empty Sun disklabel\n"
- "t\tchange a partition's system id\n"
- "u\tchange display/entry units\n"
- "v\tverify the partition table\n"
- "w\twrite table to disk and exit\n"
- "x\textra functionality (experts only)\n");
- }
- static void print_xmenu(void)
- {
- xprintf("b\tmove beginning of data in a partition\n"
- "c\tchange number of cylinders\n"
- "d\tprint the raw data in the partition table\n"
- "e\tlist extended partitions\n"
- "f\tfix partition order\n"
- "h\tchange number of heads\n"
- "p\tprint the partition table\n"
- "q\tquit without saving changes\n"
- "r\treturn to main menu\n"
- "s\tchange number of sectors/track\n"
- "v\tverify the partition table\n"
- "w\twrite table to disk and exit\n");
- }
- static void expert_menu(void)
- {
- int choice, idx;
- sector_t value;
- char mesg[256];
- while (1) {
- xputc('\n');
- char *msg = "Expert Command ('m' for help): ";
- choice = 0x20 | read_input(msg, NULL);
- switch (choice) {
- case 'b': //move data beginning in partition
- idx = ask_partition(num_parts);
- move_begning(idx - 1);
- break;
- case 'c': //change cylinders
- sprintf(mesg, "Number of cylinders (1 - 1048576, default %lu): ", g_cylinders);
- value = ask_value(mesg, 1, 1048576, g_cylinders);
- g_cylinders = TT.cylinders = value;
- toys.optflags |= FLAG_C;
- if(g_cylinders > ONE_K)
- xprintf("\nThe number of cylinders for this disk is set to %lu.\n"
- "There is nothing wrong with that, but this is larger than 1024,\n"
- "and could in certain setups cause problems.\n", g_cylinders);
- break;
- case 'd': //print raw data in part tables
- print_raw_sectors();
- break;
- case 'e': //list extended partitions
- print_partitions_list(1);
- break;
- case 'f': //fix part order
- fix_order();
- break;
- case 'h': //change number of heads
- sprintf(mesg, "Number of heads (1 - 256, default %lu): ", g_heads);
- value = ask_value(mesg, 1, 256, g_heads);
- g_heads = TT.heads = value;
- toys.optflags |= FLAG_H;
- break;
- case 'p': //print partition table
- print_partitions_list(0);
- break;
- case 'q':
- free_bufs();
- close(dev_fd);
- xputc('\n');
- exit(0);
- break;
- case 'r':
- return;
- break;
- case 's': //change sector/track
- sprintf(mesg, "Number of sectors (1 - 63, default %lu): ", g_sectors);
- value = ask_value(mesg, 1, 63, g_sectors);
- g_sectors = TT.sectors = value;
- toys.optflags |= FLAG_H;
- break;
- case 'v':
- verify_table();
- break;
- case 'w':
- write_table();
- toys.exitval = 0;
- exit(0);
- break;
- case 'm':
- print_xmenu();
- break;
- default:
- xprintf("Unknown command '%c'\n",choice);
- print_xmenu();
- break;
- }
- } //while(1)
- }
- static int disk_proper(const char *device)
- {
- unsigned length;
- int fd = open(device, O_RDONLY);
- if (fd != -1) {
- struct hd_geometry dev_geo;
- dev_geo.heads = 0;
- dev_geo.sectors = 0;
- int err = ioctl(fd, HDIO_GETGEO, &dev_geo);
- close(fd);
- if (!err) return (dev_geo.start == 0);
- }
- length = strlen(device);
- if (length != 0 && isdigit(device[length - 1])) return 0;
- return 1;
- }
- static void reset_entries()
- {
- int i;
- memset(MBRbuf, 0, sizeof(MBRbuf));
- for (i = 4; i < num_parts; i++)
- memset(&partitions[i], 0, sizeof(struct part_entry));
- }
- //this will keep dev_fd = 3 always alive
- static void move_fd()
- {
- int fd = xopen("/dev/null", O_RDONLY);
- if(fd != dev_fd) {
- if(dup2(fd, dev_fd) != dev_fd) perror_exit("Can't dup2");
- close(fd);
- }
- }
- /* Read proc/partitions and then print the details
- * for partitions on each device
- */
- static void read_and_print_parts()
- {
- unsigned int ma, mi, sz;
- char *name = toybuf, *buffer = toybuf + ONE_K, *device = toybuf + 2048;
- FILE* fp = xfopen("/proc/partitions", "r");
- while (fgets(buffer, ONE_K, fp)) {
- reset_entries();
- num_parts = 4;
- memset(name, 0, sizeof(*name));
- if (sscanf(buffer, " %u %u %u %[^\n ]", &ma, &mi, &sz, name) != 4)
- continue;
-
- sprintf(device,"/dev/%s",name);
- if (disk_proper(device)) {
- if (read_mbr(device, 0)) continue;
- print_mbr(1);
- move_fd();
- }
- }
- fclose(fp);
- }
- void fdisk_main(void)
- {
- int choice, p;
- init_members();
- move_fd();
- if (TT.heads >= 256) TT.heads = 0;
- if (TT.sectors >= 64) TT.sectors = 0;
- if (FLAG(u)) disp_unit_cyl = 0;
- if (FLAG(l)) {
- if (!toys.optc) read_and_print_parts();
- else {
- while(*toys.optargs){
- if (read_mbr(*toys.optargs, 0)) {
- toys.optargs++;
- continue;
- }
- print_mbr(1);
- move_fd();
- toys.optargs++;
- }
- }
- toys.exitval = 0;
- return;
- } else {
- if (toys.optc != 1) help_exit(0);
- if (read_mbr(toys.optargs[0], 1)) return;
- while (1) {
- xputc('\n');
- char *msg = "Command ('m' for help): ";
- choice = 0x20 | read_input(msg, NULL);
- switch (choice) {
- case 'a':
- p = ask_partition(num_parts);
- toggle_active_flag(p - 1); //partition table index start from 0.
- break;
- case 'b':
- break;
- case 'c':
- dos_flag = !dos_flag;
- xprintf("Dos compatible flag is %s\n", dos_flag?"Set" : "Not set");
- break;
- case 'd':
- p = get_non_free_partition(num_parts); //4 was here
- if(p >= 0) delete_partition(p);
- break;
- case 'l':
- list_types();
- break;
- case 'n': //add new partition
- add_new_partition();
- break;
- case 'o':
- create_empty_doslabel();
- break;
- case 'p':
- print_mbr(0);
- break;
- case 'q':
- free_bufs();
- close(dev_fd);
- xputc('\n');
- exit(0);
- break;
- case 's':
- break;
- case 't':
- change_systype();
- break;
- case 'u':
- disp_unit_cyl = !disp_unit_cyl;
- xprintf("Changing Display/Entry units to %s\n",disp_unit_cyl?"cylinders" : "sectors");
- break;
- case 'v':
- verify_table();
- break;
- case 'w':
- write_table();
- toys.exitval = 0;
- return;
- break;
- case 'x':
- expert_menu();
- break;
- case 'm':
- print_menu();
- break;
- default:
- xprintf("%c: Unknown command\n",choice);
- break;
- }
- } //while(1)
- }
- }
|