1142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* fdisk.c -  fdisk program to modify partitions on disk.
2142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma *
3142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
41c8b0090a6529ce35f877973778e7814387c1e3fRob Landley * Copyright 2013 Kyungwan Han <asura321@gmail.com>
5142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma *
6142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * No Standard.
7142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
8142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini SharmaUSE_FDISK(NEWTOY(fdisk, "C#<0H#<0S#<0b#<512ul", TOYFLAG_SBIN))
9142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
10142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmaconfig FDISK
11142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  bool "fdisk"
12142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  default n
13142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  help
14142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    usage: fdisk [-lu] [-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SECTSZ] DISK
15142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
16142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    Change partition table
17142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
18142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    -u            Start and End are in sectors (instead of cylinders)
19142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    -l            Show partition table for each DISK, then exit
20142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    -b size       sector size (512, 1024, 2048 or 4096)
21142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    -C CYLINDERS  Set number of cylinders/heads/sectors
22142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    -H HEADS
23142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    -S SECTORS
24142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma*/
25142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
26142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define FOR_fdisk
27142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#include "toys.h"
28142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#include <linux/hdreg.h>
29142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
30142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini SharmaGLOBALS(
31142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  long sect_sz;
32142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  long sectors;
33142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  long heads;
34142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  long cylinders;
35142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma)
36142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
37142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define EXTENDED        0x05
38142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define WIN98_EXTENDED  0x0f
39142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define LINUX_NATIVE    0x83
40142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define LINUX_EXTENDED  0x85
41142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
42142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define SECTOR_SIZE 512
43142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define ONE_K       1024
44142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define PARTITION_MAX  60  //partition max is modifiable
45142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define IS_EXTENDED(i) ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
46142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define sector(s) ((s) & 0x3f)
47142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
48142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
49142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmatypedef off_t sector_t;
50142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
51142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastruct partition {
52142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned char boot_ind, head, sector, cyl, sys_ind, end_head,
53142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma                end_sector, end_cyl, start4[4], size4[4];
54142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma};
55142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
56142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastruct part_entry {
57142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *part;
58142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char *sec_buffer;
59142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t  start_offset;
60142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int modified;
61142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma};
62142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
63142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastruct part_types {
64142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int id;
659d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  char type[24];
66142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma} sys_types[] = {
67142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x00, "Empty"}, {0x01, "FAT12"}, {0x04, "FAT16 <32M"}, {0x05, "Extended"},
68142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x06, "FAT16"}, {0x07, "HPFS/NTFS"}, {0x0a, "OS/2 Boot Manager"},
69142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x0b, "Win95 FAT32"}, {0x0c, "Win95 FAT32 (LBA)"}, {0x0e, "Win95 FAT16 (LBA)"},
70142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x0f, "Win95 Ext'd (LBA)"}, {0x11, "Hidden FAT12"}, {0x12, "Compaq diagnostics"},
71142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x14, "Hidden FAT16 <32M"}, {0x16, "Hidden FAT16"}, {0x17, "Hidden HPFS/NTFS"},
72142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x1b, "Hidden Win95 FAT32"}, {0x1c, "Hidden W95 FAT32 (LBA)"}, {0x1e, "Hidden W95 FAT16 (LBA)"},
73142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x3c, "Part.Magic recovery"}, {0x41, "PPC PReP Boot"}, {0x42, "SFS"},
74142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x63, "GNU HURD or SysV"}, {0x80, "Old Minix"}, {0x81, "Minix / old Linux"},
75142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x82, "Linux swap"}, {0x83, "Linux"}, {0x84, "OS/2 hidden C: drive"},
76142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x85, "Linux extended"}, {0x86, "NTFS volume set"}, {0x87, "NTFS volume set"},
77142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0x8e, "Linux LVM"}, {0x9f, "BSD/OS"}, {0xa0, "Thinkpad hibernation"},
78142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0xa5, "FreeBSD"}, {0xa6, "OpenBSD"}, {0xa8, "Darwin UFS"}, {0xa9, "NetBSD"},
79142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0xab, "Darwin boot"}, {0xb7, "BSDI fs"}, {0xb8, "BSDI swap"},
80142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0xbe, "Solaris boot"}, {0xeb, "BeOS fs"}, {0xee, "EFI GPT"},
81142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0xef, "EFI (FAT-12/16/32)"}, {0xf0, "Linux/PA-RISC boot"},
82142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  {0xf2, "DOS secondary"}, {0xfd, "Linux raid autodetect"},
83142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma};
84142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
85142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int num_parts, disp_unit_cyl, dos_flag, dev_fd = 3;
86142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic long g_cylinders, g_heads, g_sectors, g_sect_size;
87142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic sector_t total_number_sectors, extended_offset;
88142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic char MBRbuf[2048], *disk_device;
89142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastruct part_entry partitions[PARTITION_MAX];
90142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
91142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic struct partition* part_offset(char *secbuf, int i)
92142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
93142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return (struct partition*)(secbuf + 0x1be + i*(sizeof(struct partition)));
94142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
95142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
96142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void set_levalue(unsigned char *cp, sector_t value )
97142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
98142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  uint32_t val = SWAP_LE32(value);
99142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  memcpy(cp, (void*)&val, 4);
100142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
101142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
102142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void set_hsc(struct partition *p, sector_t start, sector_t end)
103142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
104142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (dos_flag && (start / (g_sectors * g_heads) > 1023))
105142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start = g_heads * g_sectors * ONE_K - 1;
106142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->sector = (start % g_sectors) + 1;
107142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start /= g_sectors;
108142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->head = start % g_heads;
109142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start /= g_heads;
110142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->cyl = start & 0xFF;
111142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->sector |= (start >> 2) & 0xc0;
112142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
113142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (dos_flag && (end / (g_sectors * g_heads) > 1023))
114142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    end = g_heads * g_sectors * ONE_K - 1;
115142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->end_sector = (end % g_sectors) + 1;
116142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  end /= g_sectors;
117142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->end_head = end % g_heads;
118142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  end /= g_heads;
119142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->end_cyl = end & 0xFF;
120142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->end_sector |= (end >> 2) & 0xc0;
121142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
122142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
123142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int chs_warn(void)
124142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
125142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (g_heads && g_sectors && g_cylinders)
126142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return 0;
127142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
128142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  printf("Unknown value(s) for:");
129142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!g_heads) printf(" heads");
130142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!g_sectors) printf(" sectors");
131142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!g_cylinders) printf(" cylinders");
132142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  printf(". can set in the expert menu.\n");
133142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return 1;
134142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
135142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
136142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void list_types(void)
137142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
138142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, adjust = 0, size = ARRAY_LEN(sys_types);
139142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
140142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if(size % 2) adjust = 1;
141142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < (size - adjust); i+=2)
142142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("%2x %-22s\t\t%2x %-22.22s\n", sys_types[i].id, sys_types[i].type,
143142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        sys_types[i+1].id, sys_types[i+1].type);
144142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (adjust) xprintf("%2x %-22s\n",sys_types[size-1].id, sys_types[size-1].type);
145142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xputc('\n');
146142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
147142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
148142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void read_sec_sz()
149142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
150142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int arg;
151142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (ioctl(dev_fd, BLKSSZGET, &arg) == 0) g_sect_size = arg;
1529d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  if (toys.optflags & FLAG_b) {
1539d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    if (TT.sect_sz !=  512 && TT.sect_sz != 1024 && TT.sect_sz != 2048 &&
1549d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham        TT.sect_sz != 4096) {
1559d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham      toys.exithelp++;
1569d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham      error_exit("bad sector size");
1579d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    }
1589d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    g_sect_size = TT.sect_sz;
1599d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  }
160142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
161142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
162142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic sector_t read_size()
163142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
164142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  uint64_t sec64 = 0;
165142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned long sectors = 0;
166142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (ioctl(dev_fd, BLKGETSIZE64, &sec64) == 0) {
167142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    sec64 = sec64 >> 9; //convert to 512 block size.
168142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (sec64 != (uint32_t) sec64) {
169142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      perror_msg("device has more than 2^32 sectors, can't use all of them");
170142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      sec64 = (uint32_t) - 1L;
171142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
172142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return sec64;
173142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
174142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (ioctl(dev_fd, BLKGETSIZE, &sectors) == 0)
175142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (sizeof(long) > sizeof(sector_t) && sectors != (sector_t)sectors)
176142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      sectors = (uint32_t) - 1L;
177142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return sectors;
178142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
179142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
180142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int validate_part_buff(char *buffer)
181142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
182142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if ((buffer[510] != 0x55) || (buffer[511] != 0xAA)) return 0;
183142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return 1;
184142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
185142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
186142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int is_partition_clear(struct partition* p)
187142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
188142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i = 0;
189142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned char res = 0;
190142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  const char *ptr = (const char*)p;
191142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
192142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < sizeof(struct partition); i++) res |= (unsigned char)ptr[i];
193142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return (res == 0x00);
194142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
195142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
196142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic uint32_t swap_le32toh(unsigned char *cp)
197142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
198142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  uint32_t val;
199142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  memcpy((void*)&val, cp, 4);
200142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return le32toh(val);
201142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
202142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
203142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int check_order(void)
204142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
205142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t first[num_parts], last_seen_val = 0;
206142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i;
207142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
208142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *px;
209142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
210142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
211142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (i == 4) last_seen_val = 0;
212142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
213142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    px = pe->part;
214142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (px->sys_ind) {
215142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      first[i] = swap_le32toh(px->start4) + pe->start_offset;
216142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (last_seen_val > first[i]) return 1;
217142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      last_seen_val = first[i];
218142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
219142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
220142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return 0;
221142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
222142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
223142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void read_geometry(struct hd_geometry *disk)
224142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
225142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct hd_geometry geometry;
226142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
227142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (ioctl(dev_fd, HDIO_GETGEO, &geometry)) return;
228142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  disk->heads = geometry.heads;
229142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  disk->sectors = geometry.sectors;
230142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
231142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
232142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* Read the extended boot record for the
233142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * logical partion details.
234142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
235142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void read_ebr(int idx)
236142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
237142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char *sec_buf = NULL;
238142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t offset = 0, local_start_off = 0;
239142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p, *q;
240142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
241142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  q = p = partitions[idx].part;
242142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  local_start_off = swap_le32toh(p->start4);
243142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
244142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!extended_offset) extended_offset = local_start_off;
245142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  do {
24630f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma    if (num_parts >= 60) {
24730f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma      xprintf("Warning: deleting partitions after 60\n");
24830f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma      memset(q, 0, sizeof(struct partition)); //clear_partition
24930f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma      partitions[num_parts-1].modified = 1;
25030f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma      break;
25130f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma    }
25230f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma
253142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    sec_buf = xzalloc(g_sect_size);
254142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[num_parts].part = part_offset(sec_buf, 0);
255142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[num_parts].sec_buffer = sec_buf;
256142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    offset = swap_le32toh(q->start4);
257142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
258142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (num_parts > 4) offset += local_start_off;
259142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[num_parts].start_offset = offset;
260142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xlseek(dev_fd, (off_t)(offset * g_sect_size), SEEK_SET);
261142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
262142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (g_sect_size != readall(dev_fd, sec_buf, g_sect_size)) {
263142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      close(dev_fd);
264142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      error_exit("Couldn't read sector zero\n");
265142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
266142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    num_parts++; //extended partions present.
267142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    q = part_offset(sec_buf, 1);
26830f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma  } while (!is_partition_clear(q) && IS_EXTENDED(q->sys_ind));
269142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
270142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
271142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void physical_HS(int* h, int *s)
272142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
273142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p;
274142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, end_h, end_s, e_hh = 0, e_ss = 0, ini = 1, dirty = 0;
275142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  const unsigned char *bufp = (const unsigned char *)MBRbuf;
276142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
277142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!(validate_part_buff((char*)bufp))) return;
278142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
279142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < 4; i++) {
280142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = part_offset((char*)bufp, i);
281142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (p->sys_ind) {
282142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      end_h = p->end_head + 1;
283142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      end_s = (p->end_sector & 077);
284142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (ini) {
285142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        e_hh = end_h;
286142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        e_ss = end_s;
287142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        ini = 0;
288142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      } else if (e_hh !=end_h || e_ss != end_s)
289142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        dirty = 1;
290142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
291142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
292142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!dirty && !ini) {
293142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    *h = e_hh;
294142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    *s = e_ss;
295142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
296142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
297142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
298142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//Reset the primary partition table
299142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void reset_boot(int change)
300142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
301142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i;
302142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for(i = 0; i < 4; i++) {
303142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    struct part_entry *pe = &partitions[i];
304142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->part = part_offset(MBRbuf, i);
305142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->start_offset = 0;
306142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->sec_buffer = MBRbuf;
307142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->modified = change;
308142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
309142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
310142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
311142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic inline void write_table_flag(char *buf)
312142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
313142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  buf[510] = 0x55;
314142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  buf[511] = 0xaa;
315142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
316142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
317142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* free the buffers used for holding details of
318142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * extended logical partions
319142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma*/
320142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void free_bufs(void)
321142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
322142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i = 4;
323142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (; i < num_parts; i++) free(partitions[i].sec_buffer);
324142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
325142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
326142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void create_empty_doslabel(void)
327142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
328142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Building a new DOS Disklabel. The changes will\n"
329142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      "remain in memory only, until you write it.\n");
330142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
331142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  num_parts = 4;
332142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  extended_offset = 0;
333142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  memset(&MBRbuf[510 - 4*16], 0, 4*16);
334142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  write_table_flag(MBRbuf);
335142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  partitions[0].modified = 1;
336142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  reset_boot(1);
337142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
338142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
339142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* Read the Master Boot sector of the device for the
340142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * partition table entries/details.
341142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * If any extended partition is found then read the EBR
342142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * for logical partition details
343142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
344142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int read_mbr(char *device, int validate)
345142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
346142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int fd, sector_fac, i, h = 0, s = 0;
347142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct hd_geometry disk;
348142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  fd = open(device, O_RDWR);
349142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if(fd < 0) {
350142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    perror_msg("can't open '%s'",device);
351142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return 1;
352142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
353142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
354142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  disk_device = strdup(device);
355142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if(fd != dev_fd) {
356142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if(dup2(fd, dev_fd) != dev_fd) perror_exit("Can't dup2");
357142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    close(fd);
358142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
359142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
360142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  //read partition table - MBR
361142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (SECTOR_SIZE != readall(dev_fd, MBRbuf, SECTOR_SIZE)) {
362142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    close(dev_fd);
363142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    perror_exit("Couldn't read sector zero\n");
364142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
365142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (validate && !validate_part_buff(MBRbuf)) {
366142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Device contains neither a valid DOS "
367142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        "partition table, nor Sun, SGI, OSF or GPT "
368142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        "disklabel\n");
369142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    create_empty_doslabel();
370142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
371142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
372142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  disk.heads = disk.sectors = 0;
373142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  read_geometry(&disk); //CHS values
374142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  total_number_sectors = read_size(); //Device size
375142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  read_sec_sz();
376142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_fac = g_sect_size/SECTOR_SIZE; //512 is hardware sector size.
377142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physical_HS(&h, &s); //physical dimensions may be diferent from HDIO_GETGEO
378142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  g_sectors = (toys.optflags & FLAG_S && TT.sectors)? TT.sectors :  s? s : disk.sectors?disk.sectors : 63;
379142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  g_heads = (toys.optflags & FLAG_H && TT.heads)? TT.heads : h? h : disk.heads? disk.heads : 255;
380142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  g_cylinders = total_number_sectors/(g_heads * g_sectors * sector_fac);
381142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
382142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!g_cylinders) g_cylinders = toys.optflags & FLAG_C? TT.cylinders : 0;
383142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if ((g_cylinders > ONE_K) && !(toys.optflags & (FLAG_l | FLAG_S)))
384142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("\nThe number of cylinders for this disk is set to %lu.\n"
385142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        "There is nothing wrong with that, but this is larger than 1024,\n"
386142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        "and could in certain setups cause problems.\n", g_cylinders);
387142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
388142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (IS_EXTENDED(partitions[i].part->sys_ind)) {
389142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      read_ebr(i);
390142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      break;
391142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
392142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
393142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  chs_warn();
394142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
395142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return 0;
396142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
397142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
398142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic char* get_type(int sys_ind)
399142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
400142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, size = ARRAY_LEN(sys_types);
401142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < size; i++)
402142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (sys_ind == sys_types[i].id)
403142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      return sys_types[i].type;
404142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return "Unknown";
405142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
406142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
407142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void consistency_check(const struct partition *p, int partition)
408142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
409142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned physbc, physbh, physbs, physec, physeh, physes;
410142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned lbc, lbh, lbs, lec, leh, les;
411142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t start, end;
412142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
413142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!g_heads || !g_sectors || (partition >= 4)) return;
414142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  // physical beginning c, h, s
415142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physbc = cylinder(p->sector,p->cyl);
416142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physbh = p->head;
417142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physbs = sector(p->sector);
418142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  // physical ending c, h, s
419142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physec = cylinder(p->end_sector, p->end_cyl);
420142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physeh = p->end_head;
421142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  physes = sector(p->end_sector);
422142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  // logical begin and end CHS values
423142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start = swap_le32toh((unsigned char*)(p->start4));
424142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  end = start + swap_le32toh((unsigned char*)(p->size4)) -1;
425142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
426142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  lbc = start/(g_sectors * g_heads);
427142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  lbh = (start/g_sectors) % g_heads;
428142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  lbs = (start % g_sectors) + 1;
429142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
430142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  lec = end/(g_sectors * g_heads);
431142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  leh = (end/g_sectors) % g_heads;
432142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  les = (end % g_sectors) + 1;
433142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
434142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  //Logical and Physical diff
435142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (g_cylinders <= ONE_K && (physbc != lbc || physbh != lbh || physbs != lbs)) {
436142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u has different physical/logical beginings (Non-Linux?): \n", partition+1);
437142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("phys = (%u %u %u) ",physbc, physbh, physbs);
438142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("logical = (%u %u %u)\n", lbc, lbh, lbs);
439142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
440142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (g_cylinders <= ONE_K && (physec != lec || physeh != leh || physes != les)) {
441142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u has different physical/logical endings: \n", partition+1);
442142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("phys = (%u %u %u) ",physec, physeh, physes);
443142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("logical = (%u %u %u)\n", lec, leh, les);
444142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
445142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  // Ending on cylinder boundary?
446142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (physeh != (g_heads - 1) || physes != g_sectors)
447142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u does not end on cylinder boundary\n", partition + 1);
448142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
449142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
450142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma// List the partition details
451142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void list_partitions(int validate)
452142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
453142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p;
454142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  uint32_t start_cyl, end_cyl, start_sec, end_sec, blocks, secs;
455142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char boot, lastchar = '\0', *dev = disk_device;
456142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i = 0, len = strlen(disk_device), odds = 0;
457142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
458142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (validate && !validate_part_buff(MBRbuf)) {
459142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    close(dev_fd);
460142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    toys.exitval = 1;
461142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Device %s: doesn't contain a valid partition table\n", disk_device);
462142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
463142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
464142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (isdigit(dev[len - 1])) lastchar = 'p';
465142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
466142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("%*s Boot      Start         End      Blocks  Id System\n", len+1, "Device");
467142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
468142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = partitions[i].part;
469142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (is_partition_clear(p)) continue;
470142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
47130f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma    boot = ((p->boot_ind == 0x80)?'*':(!p->boot_ind)?' ':'?');
472142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start_sec = swap_le32toh(p->start4) + partitions[i].start_offset;
473142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    secs = swap_le32toh(p->size4);
474142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
475142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if ((start_sec + secs) == 0) end_sec = 0;
476142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else end_sec = start_sec + secs -1;
477142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start_cyl = start_sec/(g_heads * g_sectors) + 1;
478142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    end_cyl = end_sec/(g_heads * g_sectors) + 1;
479142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    blocks = secs;
480142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (g_sect_size < ONE_K) {
481142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      blocks /= (ONE_K/g_sect_size);
482142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      odds = secs %(ONE_K/g_sect_size);
483142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } else if (g_sect_size > ONE_K) blocks *= (g_sect_size/ONE_K);
484142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
485142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (lastchar) xprintf("%s%c%d",dev, lastchar, i+1);
486142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else xprintf("%s%d",dev, i+1);
487142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
488142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("   %c %11u %11u %11u%c %2x %s\n",
489142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        boot,
490142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        disp_unit_cyl == 0? start_sec: start_cyl,
491142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        disp_unit_cyl == 0? end_sec: end_cyl,
492142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        blocks,odds?'+':' ', p->sys_ind, get_type(p->sys_ind));
493142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
494142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    consistency_check(p, i);
495142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
496142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (check_order()) xprintf("\nPartition table entries are not in disk order");
497142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
498142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
499142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//Print device details
500142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void print_mbr(int validate)
501142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
502142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned long long bytes = ((unsigned long long)total_number_sectors << 9);
503142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  long mbytes = bytes/1000000;
504142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
505142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (mbytes < 10000) xprintf("Disk %s: %lu MB, %llu bytes\n", disk_device, mbytes, bytes);
506142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  else xprintf("Disk %s: %lu.%lu GB, %llu bytes\n", disk_device, mbytes/1000, (mbytes/100)%10, bytes);
507142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("%ld heads, %ld sectors/track, %ld cylinders", g_heads, g_sectors, g_cylinders);
508142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!disp_unit_cyl) {
509142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf(", total %lld sectors\n", total_number_sectors/(g_sect_size/SECTOR_SIZE));
510142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Units = sectors of 1 * %ld = %ld bytes\n",g_sect_size, g_sect_size);
511142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  } else xprintf("\nUnits = cylinders of %ld * %ld = %ld bytes\n\n",
512142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      g_heads * g_sectors, g_sect_size, g_heads * g_sectors * g_sect_size);
513142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  list_partitions(validate);
514142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xputc('\n');
515142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
516142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
517142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void init_members(void)
518142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
519142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i = 0;
520142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  num_parts = 4; //max of primaries in a part table
521142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  disp_unit_cyl = dos_flag = 1;
522142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  extended_offset = 0;
523142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  g_sect_size = SECTOR_SIZE;
524142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
525142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[i].part = part_offset(MBRbuf, i);
526142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[i].sec_buffer = MBRbuf;
527142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[i].modified = 0;
528142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[i].start_offset = 0;
529142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
530142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
531142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
532142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int read_input(char *mesg, char *outp)
533142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
534142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char *p;
535142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int size = 0;
5369d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  do {
5379d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    xprintf("%s", mesg);
5389d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    p = fgets(toybuf, 80, stdin);
539142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
5409d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    if (!p || !(size = strlen(p))) exit(0);
5419d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    if (p[size-1] == '\n') p[--size] = '\0';
5429d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  } while (!size);
543142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
544142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  while (*p != '\0' && *p <= ' ') p++;
545142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (outp) memcpy(outp, p, strlen(p) + 1); //1 for nul
546142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return *p;
547142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
548142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
549142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int read_hex(char *mesg)
550142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
551142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int val;
552142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char input[80], *endp;
553142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  while (1) {
554142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    read_input(mesg, input);
555142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if ((*input | 0x20) == 'l') {
556142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      list_types();
557142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      memset(input, 0, 80);
558142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      continue;
559142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
560142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    val = strtoul(input, &endp, 16);
561142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (endp && *endp) continue;
562142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (val <= 0xff) return val;
563142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
564142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
565142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
566142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* Delete an exiting partition,
567142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * if its primary, then just clear the partition details
568142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * if extended, then clear the partition details, also for logical
569142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * if only logical, then move the later partitions backwards 1 step
570142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
571142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmavoid delete_partition(int i)
572142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
573142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int sys_id, looper = 0;
574142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p, *q, *ext_p, *ext_q;
575142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t new_start;
576142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe = &partitions[i];
577142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
578142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (chs_warn()) return;
579142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p = pe->part;
580142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sys_id = p->sys_ind;
581142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!sys_id) xprintf("Partition %u is empty\n", i+1);
582142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
583142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (i < 4 && !IS_EXTENDED(sys_id)) {
584142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    memset(p, 0, sizeof(struct partition)); //clear_partition
585142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->modified = 1;
586142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  } else if (i < 4 && IS_EXTENDED(sys_id)) {
587142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    memset(p, 0, sizeof(struct partition)); //clear_partition
588142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->modified = 1;
589142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (looper = 4; looper < num_parts; looper++) {
590142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      pe = &partitions[looper];
591142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      p = pe->part;
592142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (is_partition_clear(p)) break;
593142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      else {
594142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        memset(p, 0, sizeof(struct partition)); //clear_partition
595142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        pe->modified = 1;
596142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        free(pe->sec_buffer);
597142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
598142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
599142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    extended_offset = 0;
600142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    num_parts = 4;
601142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  } else {
602142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    //only logical is delete, need to move the rest of them backwards
603142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (i == 4) { //move partiton# 6 to 5.
604142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      partitions[i].modified = 1;
605142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (num_parts > i+1) {
606142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        q = partitions[i + 1].part;
607142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        *p = *q; //copy the part table
608142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        ext_p = part_offset(partitions[i].sec_buffer, 1);
609142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        ext_q = part_offset(partitions[i + 1].sec_buffer, 1);
610142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        *ext_p = *ext_q; //copy the extended info pointer
611142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        // change the start of the 4th partiton.
612142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        new_start = partitions[i + 1].start_offset + swap_le32toh(q->start4) - extended_offset;
613142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        new_start = SWAP_LE32(new_start);
614142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        memcpy(p->start4, (void *)&new_start, 4);
615142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      } else {
616142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        memset(partitions[i].part, 0, sizeof(struct partition));
617142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        return; //only logical
618142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
619142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } else if (i > 4) {
620142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      ext_p = part_offset(partitions[i-1].sec_buffer, 1);
621142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      ext_q = part_offset(partitions[i].sec_buffer, 1);
622142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      memcpy((void*)ext_p, (void *)ext_q, sizeof(struct partition));
623142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      partitions[i-1].modified = 1;
624142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
625142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (i == 4) looper = i+2;
626142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else if (i > 4) looper = i+1;
627142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (; looper < num_parts; looper++)
628142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      partitions[looper-1] = partitions[looper];
629142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    num_parts--;
630142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
631142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
632142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
633142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int ask_partition(int num_parts)
634142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
635142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int val;
636142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  while (1) {
637142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    do {
638142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xprintf("Partition (%u - %u):", 1, num_parts);
639142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      fgets(toybuf, 80, stdin);
640142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } while (!isdigit(*toybuf));
641142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    val = atoi(toybuf);
642142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (val > 0 && val <= num_parts) return val;
643142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else xprintf("Invalid number entered\n");
644142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
645142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
646142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
647142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void toggle_active_flag(int i)
648142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
649142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p = partitions[i].part;
650142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (is_partition_clear(p)) xprintf("Partition %u is empty\n", i+1);
651142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
652142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
653142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("WARNING: Partition %u is an extended partition\n", i + 1);
654142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->boot_ind = p->boot_ind == 0x80?0 : 0x80;
655142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  partitions[i].modified = 1;
656142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
657142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
658142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//Write the partition details from Buffer to Disk.
659142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmavoid write_table(void)
660142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
661142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i =0;
662142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
663142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t offset;
664142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
665142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < 4; i++)
666142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (partitions[i].modified) partitions[3].modified = 1;
667142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
668142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 3; i < num_parts; i++) {
669142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
670142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    write_table_flag(pe->sec_buffer);
671142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    offset = pe->start_offset;
672142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (pe->modified == 1) {
673142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xlseek(dev_fd, offset * g_sect_size, SEEK_SET);
674142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xwrite(dev_fd, pe->sec_buffer, g_sect_size);
675142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
676142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
677142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("The partition table has been altered.\n");
678142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Calling ioctl() to re-read partition table\n");
679142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sync();
680142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 4; i < num_parts; i++) free(partitions[i].sec_buffer);
681142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if(ioctl(dev_fd, BLKRRPART, NULL) < 0)
682142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    perror_exit("WARNING: rereading partition table failed, kernel still uses old table");
683142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
684142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
685142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
686142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* try to find a partition for deletion, if only
687142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * one, then select the same, else ask from USER
688142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
689142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int get_non_free_partition(int max)
690142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
691142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int num = -1, i = 0;
692142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
693142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < max; i++) {
694142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!is_partition_clear(partitions[i].part)) {
6959d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham      if (num >= 0)
6969d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham        return ask_partition(num_parts)-1;
697142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      num = i;
698142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
699142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
700142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  (num >= 0) ? xprintf("Selected partition %d\n",num+1):
701142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("No partition is defined yet!\n");
702142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return num;
703142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
704142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
705142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* a try at autodetecting an empty partition table entry,
706142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * if multiple options then get USER's choce.
707142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
708142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int get_free_partition(int max)
709142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
710142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int num = -1, i = 0;
711142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
712142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < max; i++) {
713142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (is_partition_clear(partitions[i].part)) {
7149d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham      if (num >= 0)
7159d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham        return ask_partition(4)-1;
716142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      num = i;
717142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
718142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
719142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  (num >= 0) ? xprintf("Selected partition %d\n",num+1):
720142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("All primary partitions have been defined already!\n");
721142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return num;
722142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
723142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
724142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//taking user input for partition start/end sectors/cyinders
725142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic uint32_t ask_value(char *mesg, sector_t left, sector_t right, sector_t defalt)
726142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
727142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char *str = toybuf;
728142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  uint32_t val;
729142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int use_default = 1;
730142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
731142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  while (1) {
732142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    use_default = 1;
733142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    do {
734142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xprintf("%s",mesg);
735142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      fgets(str, 80, stdin);
736142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } while (!isdigit(*str) && (*str != '\n')
737142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        && (*str != '-') && (*str != '+') && (!isblank(*str)));
738142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    while (isblank(*str)) str++; //remove leading white spaces
739142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (*str == '+' || *str == '-') {
740142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      int minus = (*str == '-');
741142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      int absolute = 0;
742142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
743142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      val = atoi(str + 1);
744142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      while (isdigit(*++str)) use_default = 0;
745142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
746142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      switch (*str) {
747142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'c':
748142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'C':
749142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          if (!disp_unit_cyl) val *= g_heads * g_sectors;
750142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
751142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'K':
752142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          absolute = ONE_K;
753142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
754142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'k':
755142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          absolute = 1000;
756142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
757142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'm':
758142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'M':
759142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          absolute = 1000000;
760142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
761142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'g':
762142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'G':
763142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          absolute = 1000000000;
764142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
765142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        default:
766142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
767142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
768142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (absolute) {
769142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        unsigned long long bytes = (unsigned long long) val * absolute;
770142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        unsigned long unit = (disp_unit_cyl && (g_heads * g_sectors))? g_heads * g_sectors : 1;
771142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
772142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        unit = unit * g_sect_size;
773142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        bytes += unit/2; // rounding
774142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        bytes /= unit;
775142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        val = bytes;
776142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
777142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (minus)
778142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        val = -val;
779142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      val += left;
780142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } else {
781142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      val = atoi(str);
782142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      while (isdigit(*str)) {
783142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        str++;
784142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        use_default = 0;
785142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
786142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
787142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if(use_default) {
788142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      val = defalt;
789142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xprintf("Using default value %lld\n", defalt);
790142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
791142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (val >= left && val <= right) return val;
792142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else xprintf("Value out of range\n");
793142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
794142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
795142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
796142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//validating if the start given falls in a limit or not
797142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int validate(int start_index, sector_t* begin,sector_t* end, sector_t start
798142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    , int asked)
799142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
800142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, valid = 0;
801142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = start_index; i < num_parts; i++) {
802142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (start >= begin[i] && start <= end[i]) {
803142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (asked) xprintf("Sector %lld is already allocated\n",start);
804142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      valid = 0;
805142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      break;
806142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } else valid = 1;
807142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
808142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return valid;
809142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
810142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
811142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//get the start sector/cylinder of a new partition
812142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic sector_t ask_start_sector(int idx, sector_t* begin, sector_t* end, int ext_idx)
813142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
814142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t start, limit, temp = 0, start_cyl, limit_cyl, offset = 1;
815142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char mesg[256];
816142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, asked = 0, valid = 0, start_index = 0;
817142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
818142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (dos_flag) offset = g_sectors;
819142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start = offset;
820142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (disp_unit_cyl) limit = (sector_t)g_sectors * g_heads * g_cylinders - 1;
821142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  else limit = total_number_sectors - 1;
822142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
823142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (disp_unit_cyl) //make the begin of every partition to cylnder boundary
824142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (i = 0; i < num_parts; i++)
825142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      begin[i] = (begin[i]/(g_heads* g_sectors)) * (g_heads* g_sectors);
826142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
827142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (idx >= 4) {
828142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!begin[ext_idx] && extended_offset) begin[ext_idx] = extended_offset;
829142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start = begin[ext_idx] + offset;
830142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    limit = end[ext_idx];
831142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start_index = 4;
832142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
833142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  do {
834142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (asked) valid = validate(start_index, begin, end, start, asked);
835142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (valid) break;
836142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
8379d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    do {
8389d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham      for (i = start_index; i < num_parts; i++)
8399d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham        if (start >= begin[i] && start <= end[i])
8409d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham          start = end[i] + 1 + ((idx >= 4)? offset : 0);
8419d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham    } while (!validate(start_index, begin, end, start, 0));
842142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
843142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start_cyl = start/(g_sectors * g_heads) + 1;
844142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    limit_cyl = limit/(g_sectors * g_heads) + 1;
845142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
846142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (start > limit) break;
847142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    sprintf(mesg, "First %s (%lld - %lld, default %lld): ", disp_unit_cyl? "cylinder" : "sector",
848142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        (long long int)(disp_unit_cyl? start_cyl : start),
849142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        (long long int)(disp_unit_cyl? limit_cyl : limit),
850142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        (long long int)(disp_unit_cyl? start_cyl : start));
851142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    temp = ask_value(mesg, disp_unit_cyl? start_cyl : start,
852142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        disp_unit_cyl? limit_cyl : limit, disp_unit_cyl? start_cyl : start);
853142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    asked = 1;
854142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
855142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (disp_unit_cyl) {
856142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      // point to the cylinder start sector
857142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      temp = (temp-1) * g_heads * g_sectors;
858142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (temp < start) //the boundary is falling in the already used sectors.
859142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        temp = start;
860142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
861142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    start = temp;
862142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  } while (asked && !valid);
863142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return start;
864142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
865142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
866142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//get the end sector/cylinder of a new partition
867142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic sector_t ask_end_sector(int idx, sector_t* begin, sector_t* end, int ext_idx, sector_t start_sec)
868142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
869142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t limit, temp = 0, start_cyl, limit_cyl, start = start_sec;
870142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char mesg[256];
871142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i;
872142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
873142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (disp_unit_cyl) limit = (sector_t)g_sectors * g_heads * g_cylinders - 1;
874142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  else limit = total_number_sectors - 1;
875142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
876142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (disp_unit_cyl) //make the begin of every partition to cylnder boundary
877142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (i = 0; i < num_parts; i++)
878142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      begin[i] = (begin[i]/(g_heads* g_sectors)) * (g_heads* g_sectors);
879142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
880142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (idx >= 4) limit = end[ext_idx];
881142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
88230f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma  for (i = 0; i < num_parts; i++) {
88330f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma    struct part_entry *pe = &partitions[i];
88430f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma    if (start < pe->start_offset && limit >= pe->start_offset) limit = pe->start_offset - 1;
885142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (start < begin[i] && limit >= begin[i]) limit = begin[i] - 1;
88630f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma  }
887142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
888142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start_cyl = start/(g_sectors * g_heads) + 1;
889142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  limit_cyl = limit/(g_sectors * g_heads) + 1;
890142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (limit < start) { //the boundary is falling in the already used sectors.
891142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("No Free sectors available\n");
892142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return 0;
893142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
894142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sprintf(mesg, "Last %s or +size or +sizeM or +sizeK (%lld - %lld, default %lld): ",
895142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      disp_unit_cyl? "cylinder" : "sector",
896142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      (long long int)(disp_unit_cyl? start_cyl : start),
897142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      (long long int)(disp_unit_cyl? limit_cyl : limit),
898142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      (long long int)(disp_unit_cyl? limit_cyl : limit));
899142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  temp = ask_value(mesg, disp_unit_cyl? start_cyl : start,
900142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      disp_unit_cyl? limit_cyl : limit, disp_unit_cyl? limit_cyl : limit);
901142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
902142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (disp_unit_cyl) { // point to the cylinder start sector
903142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    temp = temp * g_heads * g_sectors - 1;
904142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (temp > limit) temp = limit;
905142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
906142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (temp < start) { //the boundary is falling in the already used sectors.
907142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("No Free sectors available\n");
908142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return 0;
909142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
910142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return temp;
911142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
912142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
913142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma// add a new partition to the partition table
914142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int add_partition(int idx, int sys_id)
915142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
916142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, ext_idx = -1;
917142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t start, end, begin_sec[num_parts], end_sec[num_parts];
918142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe = &partitions[idx];
919142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p = pe->part;
920142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
921142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (p && !is_partition_clear(p)) {
922142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u is already defined, delete it to re-add\n", idx+1);
923142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return 0;
924142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
925142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
926142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
927142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = pe->part;
928142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (is_partition_clear(p)) {
929142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      begin_sec[i] = 0xffffffff;
930142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      end_sec[i] = 0;
931142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } else {
932142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      begin_sec[i] = swap_le32toh(p->start4) + pe->start_offset;
933142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      end_sec[i] = begin_sec[i] + swap_le32toh(p->size4) - 1;
934142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
935142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (IS_EXTENDED(p->sys_ind)) ext_idx = i;
936142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
937142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start = ask_start_sector(idx, begin_sec, end_sec, ext_idx);
938142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  end = ask_end_sector(idx, begin_sec, end_sec, ext_idx, start);
939142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!end) return 0;
940142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  //Populate partition table entry  - 16 bytes
941142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  pe = &partitions[idx];
942142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p = pe->part;
943142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
944142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (idx > 4) {
945142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (dos_flag) pe->start_offset = start - (sector_t)g_sectors;
946142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else pe->start_offset = start - 1;
947142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (pe->start_offset == extended_offset) pe->start_offset++;
948142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!dos_flag) start++;
949142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
950142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
951142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  set_levalue(p->start4, start - pe->start_offset);
952142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  set_levalue(p->size4, end - start + 1);
953142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  set_hsc(p, start, end);
954142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->boot_ind = 0;
955142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->sys_ind = sys_id;
956142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  pe->modified = 1;
957142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
958142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (idx > 4) {
959142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = partitions[idx-1].part + 1; //extended pointer for logical partitions
960142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    set_levalue(p->start4, pe->start_offset - extended_offset);
961142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    set_levalue(p->size4, end - start + 1 + (dos_flag? g_sectors: 1));
96230f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma    set_hsc(p, pe->start_offset, end);
963142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p->boot_ind = 0;
964142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p->sys_ind = EXTENDED;
965142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    partitions[idx-1].modified = 1;
966142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
967142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (IS_EXTENDED(sys_id)) {
968142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[4];
969142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->modified = 1;
970142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->sec_buffer = xzalloc(g_sect_size);
971142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->part = part_offset(pe->sec_buffer, 0);
972142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->start_offset = extended_offset = start;
973142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    num_parts = 5;
974142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
975142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return 1;
976142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
977142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
978142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void add_logical_partition(void)
979142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
980142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
981142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (num_parts > 5 || !is_partition_clear(partitions[4].part)) {
982142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[num_parts];
983142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->modified = 1;
984142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->sec_buffer = xzalloc(g_sect_size);
985142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->part = part_offset(pe->sec_buffer, 0);
986142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->start_offset = 0;
987142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    num_parts++;
988142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!add_partition(num_parts - 1, LINUX_NATIVE)) {
989142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      num_parts--;
990142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      free(pe->sec_buffer);
991142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
992142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
993142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  else add_partition(num_parts -1, LINUX_NATIVE);
994142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
995142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
996142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* Add a new partiton to the partition table.
997142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * MAX partitions limit is taken to be 60, can be changed
998142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
999142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void add_new_partition(void)
1000142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1001142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int choice, idx, i, free_part = 0;
1002142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char *msg = NULL;
1003142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1004142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (chs_warn()) return;
1005142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < 4; i++) if(is_partition_clear(partitions[i].part)) free_part++;
1006142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1007142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!free_part && num_parts >= 60) {
1008142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("The maximum number of partitions has been created\n");
1009142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1010142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1011142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!free_part) {
1012142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (extended_offset) add_logical_partition();
1013142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else xprintf("You must delete some partition and add "
1014142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          "an extended partition first\n");
1015142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1016142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1017142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
101859d85e2bb065a3bdc27868acb7a65f89d872c7faRob Landley  msg = xmprintf("  %s\n  p  primary partition(1-4)\n",
1019142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          extended_offset? "l  logical (5 or over)" : "e  extended");
1020142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1021142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  choice = 0x20 | read_input(msg, NULL);
1022142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  free(msg);
1023142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (choice == 'p') {
1024142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    idx = get_free_partition(4);
1025142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (idx >= 0) add_partition(idx, LINUX_NATIVE);
1026142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1027142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1028142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (choice =='l' && extended_offset) {
1029142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    add_logical_partition();
1030142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1031142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1032142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (choice == 'e' && !extended_offset) {
1033142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    idx = get_free_partition(4);
1034142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (idx >= 0) add_partition(idx, EXTENDED);
1035142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1036142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1037142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1038142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1039142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void change_systype(void )
1040142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1041142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, sys_id;
1042142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p;
1043142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
1044142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1045142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  i = ask_partition(num_parts);
1046142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  pe = &partitions[i-1];
1047142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p = pe->part;
1048142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (is_partition_clear(p)) {
1049142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %d doesn't exist yet!\n", i);
1050142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1051142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1052142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sys_id = read_hex("Hex code (L to list codes): ");
1053142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if ((IS_EXTENDED(p->sys_ind) && !IS_EXTENDED(sys_id)) ||
1054142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      (!IS_EXTENDED(p->sys_ind) && IS_EXTENDED(sys_id))) {
1055142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("you can't change a  partition to an extended or vice-versa\n");
1056142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1057142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1058142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1059142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Changed system type of partition %u to %0x (%s)\n",i, sys_id, get_type(sys_id));
1060142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  p->sys_ind = sys_id;
1061142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  pe->modified = 1;
1062142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1063142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1064142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
1065142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1066142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t total, real_s, real_c;
1067142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1068142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  real_s = sector(s) - 1;
1069142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  real_c = cylinder(s, c);
1070142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  total = (real_c * g_sectors + real_s) * g_heads + h;
1071142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!total) xprintf("Partition %u contains sector 0\n", n);
1072142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (h >= g_heads)
1073142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u: head %u greater than maximum %lu\n", n, h + 1, g_heads);
1074142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (real_s >= g_sectors)
1075142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u: sector %u greater than maximum %lu\n", n, s, g_sectors);
1076142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (real_c >= g_cylinders)
1077142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u: cylinder %lld greater than maximum %lu\n", n, real_c + 1, g_cylinders);
1078142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (g_cylinders <= ONE_K && start != total)
1079142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u: previous sectors %lld disagrees with total %lld\n", n, start, total);
1080142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1081142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1082142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void verify_table(void)
1083142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1084142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, j, ext_idx = -1;
1085142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t begin_sec[num_parts], end_sec[num_parts], total = 1;
1086142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
1087142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p;
1088142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1089142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
1090142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
1091142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = pe->part;
1092142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (is_partition_clear(p) || IS_EXTENDED(p->sys_ind)) {
1093142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      begin_sec[i] = 0xffffffff;
1094142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      end_sec[i] = 0;
1095142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } else {
1096142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      begin_sec[i] = swap_le32toh(p->start4) + pe->start_offset;
1097142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      end_sec[i] = begin_sec[i] + swap_le32toh(p->size4) - 1;
1098142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1099142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (IS_EXTENDED(p->sys_ind)) ext_idx = i;
1100142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1101142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
1102142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
1103142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = pe->part;
1104142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
1105142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      consistency_check(p, i);
1106142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if ((swap_le32toh(p->start4) + pe->start_offset) < begin_sec[i])
1107142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        xprintf("Warning: bad start-of-data in partition %u\n", i + 1);
1108142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      check(i + 1, p->end_head, p->end_sector, p->end_cyl, end_sec[i]);
1109142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      total += end_sec[i] + 1 - begin_sec[i];
1110142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      for (j = 0; j < i; j++) {
1111142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        if ((begin_sec[i] >= begin_sec[j] && begin_sec[i] <= end_sec[j])
1112142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma            || ((end_sec[i] <= end_sec[j] && end_sec[i] >= begin_sec[j]))) {
1113142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          xprintf("Warning: partition %u overlaps partition %u\n", j + 1, i + 1);
1114142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          total += begin_sec[i] >= begin_sec[j] ? begin_sec[i] : begin_sec[j];
1115142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          total -= end_sec[i] <= end_sec[j] ? end_sec[i] : end_sec[j];
1116142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        }
1117142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
1118142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1119142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1120142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (extended_offset) {
1121142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    struct part_entry *pex = &partitions[ext_idx];
1122142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    sector_t e_last = swap_le32toh(pex->part->start4) +
1123142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      swap_le32toh(pex->part->size4) - 1;
1124142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1125142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (i = 4; i < num_parts; i++) {
1126142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      total++;
1127142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      p = partitions[i].part;
1128142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (!p->sys_ind) {
1129142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        if (i != 4 || i + 1 < num_parts)
1130142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          xprintf("Warning: partition %u is empty\n", i + 1);
1131142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      } else if (begin_sec[i] < extended_offset || end_sec[i] > e_last)
1132142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        xprintf("Logical partition %u not entirely in partition %u\n", i + 1, ext_idx + 1);
1133142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1134142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1135142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (total > g_heads * g_sectors * g_cylinders)
1136142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Total allocated sectors %lld greater than the maximum "
1137142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        "%lu\n", total, g_heads * g_sectors * g_cylinders);
1138142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  else {
1139142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    total = g_heads * g_sectors * g_cylinders - total;
1140142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (total) xprintf("%lld unallocated sectors\n", total);
1141142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1142142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1143142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1144142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void move_begning(int idx)
1145142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1146142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t start, num, new_start, end;
1147142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char mesg[256];
1148142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe = &partitions[idx];
1149142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p = pe->part;
1150142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1151142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (chs_warn()) return;
1152142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  start = swap_le32toh(p->start4) + pe->start_offset;
1153142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  num = swap_le32toh(p->size4);
1154142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  end = start + num -1;
1155142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1156142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!num || IS_EXTENDED(p->sys_ind)) {
1157142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Partition %u doesn't have data area\n", idx+1);
1158142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1159142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1160142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sprintf(mesg, "New begining of data (0 - %lld, default %lld): ",
1161142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      (long long int)(end), (long long int)(start));
1162142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  new_start = ask_value(mesg, 0, end, start);
1163142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (new_start != start) {
1164142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    set_levalue(p->start4, new_start - pe->start_offset);
1165142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    set_levalue(p->size4, end - new_start +1);
1166142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if ((read_input("Recalculate C/H/S (Y/n): ", NULL) | 0x20) == 'y')
1167142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      set_hsc(p, new_start, end);
1168142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe->modified = 1;
1169142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1170142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1171142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1172142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void print_raw_sectors()
1173142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1174142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, j;
1175142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
1176142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1177142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Device: %s\n", disk_device);
1178142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 3; i < num_parts; i++) {
1179142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
1180142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (j = 0; j < g_sect_size; j++) {
1181142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (!(j % 16)) xprintf("\n0x%03X: ",j);
1182142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xprintf("%02X ",pe->sec_buffer[j]);
1183142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1184142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xputc('\n');
1185142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1186142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1187142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1188142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void print_partitions_list(int ext)
1189142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1190142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i;
1191142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
1192142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *p;
1193142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1194142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Disk %s: %lu heads, %lu sectors, %lu cylinders\n\n", disk_device, g_heads, g_sectors, g_cylinders);
1195142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
1196142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1197142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
1198142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
1199142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    p = pe->part;
1200142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (p) {
1201142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (ext && (i >= 4)) p = pe->part + 1;
1202142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if(ext && i < 4 && !IS_EXTENDED(p->sys_ind)) continue;
1203142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1204142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xprintf("%2u %02x%4u%4u%5u%4u%4u%5u%11u%11u %02x\n",
1205142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          i+1, p->boot_ind, p->head,
1206142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          sector(p->sector), cylinder(p->sector, p->cyl),
1207142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          p->end_head,
1208142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          sector(p->end_sector), cylinder(p->end_sector, p->end_cyl),
1209142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          swap_le32toh(p->start4),
1210142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          swap_le32toh(p->size4),
1211142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          p->sys_ind);
1212142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (p->sys_ind) consistency_check(p, i);
1213142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1214142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1215142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1216142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1217142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//fix the partition table order to ascending
1218142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void fix_order(void)
1219142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1220142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t first[num_parts], min;
1221142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i, j, oj, ojj, sj, sjj;
1222142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct part_entry *pe;
1223142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  struct partition *px, *py, temp, *pj, *pjj, tmp;
1224142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1225142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < num_parts; i++) {
1226142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    pe = &partitions[i];
1227142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    px = pe->part;
1228142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (is_partition_clear(px)) first[i] = 0xffffffff;
1229142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else first[i] = swap_le32toh(px->start4) + pe->start_offset;
1230142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1231142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1232142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (!check_order()) {
1233142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xprintf("Ordering is already correct\n\n");
1234142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1235142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1236142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 0; i < 4; i++) {
1237142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (j = 0; j < 3; j++) {
1238142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (first[j] > first[j+1]) {
1239142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        py = partitions[j+1].part;
1240142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        px = partitions[j].part;
1241142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        memcpy(&temp, py, sizeof(struct partition));
1242142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        memcpy(py, px, sizeof(struct partition));
1243142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        memcpy(px, &temp, sizeof(struct partition));
1244142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        min = first[j+1];
1245142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        first[j+1] = first[j];
1246142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        first[j] = min;
1247142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        partitions[j].modified = 1;
1248142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
1249142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1250142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1251142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 5; i < num_parts; i++) {
1252142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (j = 5; j < num_parts - 1; j++) {
1253142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      oj = partitions[j].start_offset;
1254142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      ojj = partitions[j+1].start_offset;
1255142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (oj > ojj) {
1256142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        partitions[j].start_offset = ojj;
1257142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        partitions[j+1].start_offset = oj;
1258142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        pj = partitions[j].part;
1259142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        set_levalue(pj->start4, swap_le32toh(pj->start4)+oj-ojj);
1260142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        pjj = partitions[j+1].part;
1261142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        set_levalue(pjj->start4, swap_le32toh(pjj->start4)+ojj-oj);
1262142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        set_levalue((partitions[j-1].part+1)->start4, ojj-extended_offset);
1263142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        set_levalue((partitions[j].part+1)->start4, oj-extended_offset);
1264142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
1265142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1266142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1267142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 4; i < num_parts; i++) {
1268142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    for (j = 4; j < num_parts - 1; j++) {
1269142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      pj = partitions[j].part;
1270142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      pjj = partitions[j+1].part;
1271142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      sj = swap_le32toh(pj->start4);
1272142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      sjj = swap_le32toh(pjj->start4);
1273142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      oj = partitions[j].start_offset;
1274142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      ojj = partitions[j+1].start_offset;
1275142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (oj+sj > ojj+sjj) {
1276142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        tmp = *pj;
1277142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        *pj = *pjj;
1278142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        *pjj = tmp;
1279142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        set_levalue(pj->start4, ojj+sjj-oj);
1280142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        set_levalue(pjj->start4, oj+sj-ojj);
1281142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
1282142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1283142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1284142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  // If anything changed
1285142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (j = 4; j < num_parts; j++) partitions[j].modified = 1;
1286142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  xprintf("Done!\n");
1287142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1288142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1289142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void print_menu(void)
1290142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
12919d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  xprintf("a\ttoggle a bootable flag\n"
12929d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "b\tedit bsd disklabel\n"
12939d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "c\ttoggle the dos compatibility flag\n"
12949d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "d\tdelete a partition\n"
12959d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "l\tlist known partition types\n"
12969d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "n\tadd a new partition\n"
12979d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "o\tcreate a new empty DOS partition table\n"
12989d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "p\tprint the partition table\n"
12999d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "q\tquit without saving changes\n"
13009d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "s\tcreate a new empty Sun disklabel\n"
13019d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "t\tchange a partition's system id\n"
13029d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "u\tchange display/entry units\n"
13039d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "v\tverify the partition table\n"
13049d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "w\twrite table to disk and exit\n"
13059d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "x\textra functionality (experts only)\n");
1306142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1307142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1308142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void print_xmenu(void)
1309142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
13109d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  xprintf("b\tmove beginning of data in a partition\n"
13119d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "c\tchange number of cylinders\n"
13129d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "d\tprint the raw data in the partition table\n"
13139d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "e\tlist extended partitions\n"
13149d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "f\tfix partition order\n"
13159d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "h\tchange number of heads\n"
13169d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "p\tprint the partition table\n"
13179d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "q\tquit without saving changes\n"
13189d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "r\treturn to main menu\n"
13199d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "s\tchange number of sectors/track\n"
13209d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "v\tverify the partition table\n"
13219d44ab3f179e0e914abc1d6edc79a22c265baaa9Isaac Dunham  "w\twrite table to disk and exit\n");
1322142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1323142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1324142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void expert_menu(void)
1325142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1326142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int choice, idx;
1327142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  sector_t value;
1328142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char mesg[256];
1329142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1330142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  while (1) {
1331142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    xputc('\n');
1332142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    char *msg = "Expert Command ('m' for help): ";
1333142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    choice = 0x20 | read_input(msg, NULL);
1334142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    switch (choice) {
1335142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'b': //move data begining in partition
1336142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        idx = ask_partition(num_parts);
1337142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        move_begning(idx - 1);
1338142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1339142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'c': //change cylinders
1340142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          sprintf(mesg, "Number of cylinders (1 - 1048576, default %lu): ", g_cylinders);
1341142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          value = ask_value(mesg, 1, 1048576, g_cylinders);
1342142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          g_cylinders = TT.cylinders = value;
1343142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          toys.optflags |= FLAG_C;
1344142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          if(g_cylinders > ONE_K)
1345142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma            xprintf("\nThe number of cylinders for this disk is set to %lu.\n"
1346142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma                "There is nothing wrong with that, but this is larger than 1024,\n"
1347142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma                "and could in certain setups cause problems.\n", g_cylinders);
1348142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1349142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'd': //print raw data in part tables
1350142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        print_raw_sectors();
1351142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1352142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'e': //list extended partitions
1353142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        print_partitions_list(1);
1354142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1355142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'f': //fix part order
1356142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        fix_order();
1357142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1358142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'h': //change number of heads
1359142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          sprintf(mesg, "Number of heads (1 - 256, default %lu): ", g_heads);
1360142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          value = ask_value(mesg, 1, 256, g_heads);
1361142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          g_heads = TT.heads = value;
1362142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          toys.optflags |= FLAG_H;
1363142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1364142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'p': //print partition table
1365142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        print_partitions_list(0);
1366142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1367142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'q':
1368142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        free_bufs();
1369142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        close(dev_fd);
1370142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        xputc('\n');
1371142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        exit(0);
1372142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1373142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'r':
1374142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        return;
1375142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1376142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 's': //change sector/track
1377142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          sprintf(mesg, "Number of sectors (1 - 63, default %lu): ", g_sectors);
1378142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          value = ask_value(mesg, 1, 63, g_sectors);
1379142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          g_sectors = TT.sectors = value;
1380142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          toys.optflags |= FLAG_H;
1381142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1382142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'v':
1383142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        verify_table();
1384142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1385142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'w':
1386142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        write_table();
1387142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        toys.exitval = 0;
1388142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        exit(0);
1389142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1390142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      case 'm':
1391142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        print_xmenu();
1392142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1393142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      default:
1394142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        xprintf("Unknown command '%c'\n",choice);
1395142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        print_xmenu();
1396142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        break;
1397142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1398142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  } //while(1)
1399142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1400142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1401142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic int disk_proper(const char *device)
1402142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1403142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned length;
1404142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int fd = open(device, O_RDONLY);
1405142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1406142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (fd != -1) {
1407142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    struct hd_geometry dev_geo;
1408142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    dev_geo.heads = 0;
1409142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    dev_geo.sectors = 0;
1410142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    int err = ioctl(fd, HDIO_GETGEO, &dev_geo);
1411142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    close(fd);
1412142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!err) return (dev_geo.start == 0);
1413142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1414142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  length = strlen(device);
1415142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (length != 0 && isdigit(device[length - 1])) return 0;
1416142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  return 1;
1417142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1418142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1419142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void reset_entries()
1420142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1421142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int i;
1422142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1423142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  memset(MBRbuf, 0, sizeof(MBRbuf));
1424142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  for (i = 4; i < num_parts; i++)
1425142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    memset(&partitions[i], 0, sizeof(struct part_entry));
1426142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1427142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1428142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma//this will keep dev_fd = 3 always alive
1429142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void move_fd()
1430142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1431142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int fd = xopen("/dev/null", O_RDONLY);
1432142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if(fd != dev_fd) {
1433142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if(dup2(fd, dev_fd) != dev_fd) perror_exit("Can't dup2");
1434142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    close(fd);
1435142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1436142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1437142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1438142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma/* Read proc/partitions and then print the details
1439142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma * for partitions on each device
1440142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma */
1441142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmastatic void read_and_print_parts()
1442142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1443142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  unsigned int ma, mi, sz;
1444142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  char *name = toybuf, *buffer = toybuf + ONE_K, *device = toybuf + 2048;
1445142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  FILE* fp = xfopen("/proc/partitions", "r");
1446142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1447142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  while (fgets(buffer, ONE_K, fp)) {
1448142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    reset_entries();
1449142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    num_parts = 4;
1450142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    memset(name, 0, sizeof(name));
1451142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (sscanf(buffer, " %u %u %u %[^\n ]", &ma, &mi, &sz, name) != 4)
1452142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      continue;
1453142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1454142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    sprintf(device,"/dev/%s",name);
1455142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (disk_proper(device)) {
1456142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      if (read_mbr(device, 0)) continue;
1457142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      print_mbr(1);
1458142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      move_fd();
1459142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1460142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1461142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  fclose(fp);
1462142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1463142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1464142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharmavoid fdisk_main(void)
1465142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma{
1466142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  int choice, p;
1467142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma
1468142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  init_members();
1469142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  move_fd();
1470142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (TT.heads >= 256) TT.heads = 0;
1471142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (TT.sectors >= 64) TT.sectors = 0;
1472142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (toys.optflags & FLAG_u) disp_unit_cyl = 0;
1473142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  if (toys.optflags & FLAG_l) {
1474142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!toys.optc) read_and_print_parts();
1475142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    else {
1476142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      while(*toys.optargs){
1477142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        if (read_mbr(*toys.optargs, 0)) {
1478142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          toys.optargs++;
1479142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          continue;
1480142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        }
1481142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        print_mbr(1);
1482142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        move_fd();
1483142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        toys.optargs++;
1484142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
1485142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1486142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    toys.exitval = 0;
1487142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    return;
1488142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  } else {
1489142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (!toys.optc || toys.optc > 1 ) {
1490142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      toys.exitval = toys.exithelp = 1;
1491142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      show_help();
1492142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      return;
1493142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    }
1494142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    if (read_mbr(toys.optargs[0], 1)) return;
1495142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    while (1) {
1496142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      xputc('\n');
1497142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      char *msg = "Command ('m' for help): ";
1498142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      choice = 0x20 | read_input(msg, NULL);
1499142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      switch (choice) {
1500142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'a':
1501142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          p = ask_partition(num_parts);
1502142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          toggle_active_flag(p - 1); //partition table index start from 0.
1503142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1504142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'b':
1505142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1506142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'c':
1507142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          dos_flag = !dos_flag;
1508142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          xprintf("Dos compatible flag is %s\n", dos_flag?"Set" : "Not set");
1509142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1510142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'd':
1511142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          p = get_non_free_partition(num_parts); //4 was here
1512142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          if(p >= 0) delete_partition(p);
1513142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1514142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'l':
1515142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          list_types();
1516142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1517142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'n': //add new partition
1518142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          add_new_partition();
1519142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1520142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'o':
1521142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          create_empty_doslabel();
1522142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1523142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'p':
1524142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          print_mbr(0);
1525142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1526142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'q':
1527142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          free_bufs();
1528142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          close(dev_fd);
1529142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          xputc('\n');
1530142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          exit(0);
1531142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1532142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 's':
1533142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1534142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 't':
1535142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          change_systype();
1536142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1537142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'u':
1538142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          disp_unit_cyl = !disp_unit_cyl;
1539142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          xprintf("Changing Display/Entry units to %s\n",disp_unit_cyl?"cylinders" : "sectors");
1540142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1541142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'v':
1542142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          verify_table();
1543142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1544142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'w':
1545142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          write_table();
1546142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          toys.exitval = 0;
1547142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          return;
1548142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1549142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'x':
1550142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          expert_menu();
1551142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1552142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        case 'm':
1553142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          print_menu();
1554142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1555142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma        default:
1556142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          xprintf("%c: Unknown command\n",choice);
1557142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma          break;
1558142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma      }
1559142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma    } //while(1)
1560142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma  }
1561142ebdcfbe01007cd86d699d85dc608bbcaacf82Ashwini Sharma}
1562