xref: /aosp_15_r20/external/toybox/toys/pending/fdisk.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* fdisk.c -  fdisk program to modify partitions on disk.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2012 Ashwini Kumar <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker  *
6*cf5a6c84SAndroid Build Coastguard Worker  * No Standard.
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker USE_FDISK(NEWTOY(fdisk, "C#<0H#<0S#<0b#<512ul", TOYFLAG_SBIN))
9*cf5a6c84SAndroid Build Coastguard Worker 
10*cf5a6c84SAndroid Build Coastguard Worker config FDISK
11*cf5a6c84SAndroid Build Coastguard Worker   bool "fdisk"
12*cf5a6c84SAndroid Build Coastguard Worker   default n
13*cf5a6c84SAndroid Build Coastguard Worker   help
14*cf5a6c84SAndroid Build Coastguard Worker     usage: fdisk [-lu] [-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SECTSZ] DISK
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker     Change partition table
17*cf5a6c84SAndroid Build Coastguard Worker 
18*cf5a6c84SAndroid Build Coastguard Worker     -u            Start and End are in sectors (instead of cylinders)
19*cf5a6c84SAndroid Build Coastguard Worker     -l            Show partition table for each DISK, then exit
20*cf5a6c84SAndroid Build Coastguard Worker     -b size       sector size (512, 1024, 2048 or 4096)
21*cf5a6c84SAndroid Build Coastguard Worker     -C CYLINDERS  Set number of cylinders/heads/sectors
22*cf5a6c84SAndroid Build Coastguard Worker     -H HEADS
23*cf5a6c84SAndroid Build Coastguard Worker     -S SECTORS
24*cf5a6c84SAndroid Build Coastguard Worker */
25*cf5a6c84SAndroid Build Coastguard Worker 
26*cf5a6c84SAndroid Build Coastguard Worker #define FOR_fdisk
27*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
28*cf5a6c84SAndroid Build Coastguard Worker #include <linux/hdreg.h>
29*cf5a6c84SAndroid Build Coastguard Worker 
30*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
31*cf5a6c84SAndroid Build Coastguard Worker   long sect_sz;
32*cf5a6c84SAndroid Build Coastguard Worker   long sectors;
33*cf5a6c84SAndroid Build Coastguard Worker   long heads;
34*cf5a6c84SAndroid Build Coastguard Worker   long cylinders;
35*cf5a6c84SAndroid Build Coastguard Worker )
36*cf5a6c84SAndroid Build Coastguard Worker 
37*cf5a6c84SAndroid Build Coastguard Worker #define EXTENDED        0x05
38*cf5a6c84SAndroid Build Coastguard Worker #define WIN98_EXTENDED  0x0f
39*cf5a6c84SAndroid Build Coastguard Worker #define LINUX_NATIVE    0x83
40*cf5a6c84SAndroid Build Coastguard Worker #define LINUX_EXTENDED  0x85
41*cf5a6c84SAndroid Build Coastguard Worker 
42*cf5a6c84SAndroid Build Coastguard Worker #define SECTOR_SIZE 512
43*cf5a6c84SAndroid Build Coastguard Worker #define ONE_K       1024
44*cf5a6c84SAndroid Build Coastguard Worker #define PARTITION_MAX  60  //partition max is modifiable
45*cf5a6c84SAndroid Build Coastguard Worker #define IS_EXTENDED(i) ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
46*cf5a6c84SAndroid Build Coastguard Worker #define sector(s) ((s) & 0x3f)
47*cf5a6c84SAndroid Build Coastguard Worker #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
48*cf5a6c84SAndroid Build Coastguard Worker 
49*cf5a6c84SAndroid Build Coastguard Worker typedef unsigned long long sector_t;
50*cf5a6c84SAndroid Build Coastguard Worker 
51*cf5a6c84SAndroid Build Coastguard Worker struct partition {
52*cf5a6c84SAndroid Build Coastguard Worker   unsigned char boot_ind, head, sector, cyl, sys_ind, end_head,
53*cf5a6c84SAndroid Build Coastguard Worker                 end_sector, end_cyl, start4[4], size4[4];
54*cf5a6c84SAndroid Build Coastguard Worker };
55*cf5a6c84SAndroid Build Coastguard Worker 
56*cf5a6c84SAndroid Build Coastguard Worker struct part_entry {
57*cf5a6c84SAndroid Build Coastguard Worker   struct partition *part;
58*cf5a6c84SAndroid Build Coastguard Worker   char *sec_buffer;
59*cf5a6c84SAndroid Build Coastguard Worker   sector_t  start_offset;
60*cf5a6c84SAndroid Build Coastguard Worker   int modified;
61*cf5a6c84SAndroid Build Coastguard Worker };
62*cf5a6c84SAndroid Build Coastguard Worker 
63*cf5a6c84SAndroid Build Coastguard Worker struct part_types {
64*cf5a6c84SAndroid Build Coastguard Worker   int id;
65*cf5a6c84SAndroid Build Coastguard Worker   char type[24];
66*cf5a6c84SAndroid Build Coastguard Worker } sys_types[] = {
67*cf5a6c84SAndroid Build Coastguard Worker   {0x00, "Empty"}, {0x01, "FAT12"}, {0x04, "FAT16 <32M"}, {0x05, "Extended"},
68*cf5a6c84SAndroid Build Coastguard Worker   {0x06, "FAT16"}, {0x07, "HPFS/NTFS"}, {0x0a, "OS/2 Boot Manager"},
69*cf5a6c84SAndroid Build Coastguard Worker   {0x0b, "Win95 FAT32"}, {0x0c, "Win95 FAT32 (LBA)"}, {0x0e, "Win95 FAT16 (LBA)"},
70*cf5a6c84SAndroid Build Coastguard Worker   {0x0f, "Win95 Ext'd (LBA)"}, {0x11, "Hidden FAT12"}, {0x12, "Compaq diagnostics"},
71*cf5a6c84SAndroid Build Coastguard Worker   {0x14, "Hidden FAT16 <32M"}, {0x16, "Hidden FAT16"}, {0x17, "Hidden HPFS/NTFS"},
72*cf5a6c84SAndroid Build Coastguard Worker   {0x1b, "Hidden Win95 FAT32"}, {0x1c, "Hidden W95 FAT32 (LBA)"}, {0x1e, "Hidden W95 FAT16 (LBA)"},
73*cf5a6c84SAndroid Build Coastguard Worker   {0x3c, "Part.Magic recovery"}, {0x41, "PPC PReP Boot"}, {0x42, "SFS"},
74*cf5a6c84SAndroid Build Coastguard Worker   {0x63, "GNU HURD or SysV"}, {0x80, "Old Minix"}, {0x81, "Minix / old Linux"},
75*cf5a6c84SAndroid Build Coastguard Worker   {0x82, "Linux swap"}, {0x83, "Linux"}, {0x84, "OS/2 hidden C: drive"},
76*cf5a6c84SAndroid Build Coastguard Worker   {0x85, "Linux extended"}, {0x86, "NTFS volume set"}, {0x87, "NTFS volume set"},
77*cf5a6c84SAndroid Build Coastguard Worker   {0x8e, "Linux LVM"}, {0x9f, "BSD/OS"}, {0xa0, "Thinkpad hibernation"},
78*cf5a6c84SAndroid Build Coastguard Worker   {0xa5, "FreeBSD"}, {0xa6, "OpenBSD"}, {0xa8, "Darwin UFS"}, {0xa9, "NetBSD"},
79*cf5a6c84SAndroid Build Coastguard Worker   {0xab, "Darwin boot"}, {0xb7, "BSDI fs"}, {0xb8, "BSDI swap"},
80*cf5a6c84SAndroid Build Coastguard Worker   {0xbe, "Solaris boot"}, {0xeb, "BeOS fs"}, {0xee, "EFI GPT"},
81*cf5a6c84SAndroid Build Coastguard Worker   {0xef, "EFI (FAT-12/16/32)"}, {0xf0, "Linux/PA-RISC boot"},
82*cf5a6c84SAndroid Build Coastguard Worker   {0xf2, "DOS secondary"}, {0xfd, "Linux raid autodetect"},
83*cf5a6c84SAndroid Build Coastguard Worker };
84*cf5a6c84SAndroid Build Coastguard Worker 
85*cf5a6c84SAndroid Build Coastguard Worker static int num_parts, disp_unit_cyl, dos_flag, dev_fd = 3;
86*cf5a6c84SAndroid Build Coastguard Worker static long g_cylinders, g_heads, g_sectors, g_sect_size;
87*cf5a6c84SAndroid Build Coastguard Worker static sector_t total_number_sectors, extended_offset;
88*cf5a6c84SAndroid Build Coastguard Worker static char MBRbuf[2048], *disk_device;
89*cf5a6c84SAndroid Build Coastguard Worker struct part_entry partitions[PARTITION_MAX];
90*cf5a6c84SAndroid Build Coastguard Worker 
part_offset(char * secbuf,int i)91*cf5a6c84SAndroid Build Coastguard Worker static struct partition* part_offset(char *secbuf, int i)
92*cf5a6c84SAndroid Build Coastguard Worker {
93*cf5a6c84SAndroid Build Coastguard Worker   return (struct partition*)(secbuf + 0x1be + i*(sizeof(struct partition)));
94*cf5a6c84SAndroid Build Coastguard Worker }
95*cf5a6c84SAndroid Build Coastguard Worker 
set_levalue(unsigned char * cp,sector_t value)96*cf5a6c84SAndroid Build Coastguard Worker static void set_levalue(unsigned char *cp, sector_t value )
97*cf5a6c84SAndroid Build Coastguard Worker {
98*cf5a6c84SAndroid Build Coastguard Worker   uint32_t val = SWAP_LE32(value);
99*cf5a6c84SAndroid Build Coastguard Worker   memcpy(cp, (void*)&val, 4);
100*cf5a6c84SAndroid Build Coastguard Worker }
101*cf5a6c84SAndroid Build Coastguard Worker 
set_hsc(struct partition * p,sector_t start,sector_t end)102*cf5a6c84SAndroid Build Coastguard Worker static void set_hsc(struct partition *p, sector_t start, sector_t end)
103*cf5a6c84SAndroid Build Coastguard Worker {
104*cf5a6c84SAndroid Build Coastguard Worker   if (dos_flag && (start / (g_sectors * g_heads) > 1023))
105*cf5a6c84SAndroid Build Coastguard Worker     start = g_heads * g_sectors * ONE_K - 1;
106*cf5a6c84SAndroid Build Coastguard Worker   p->sector = (start % g_sectors) + 1;
107*cf5a6c84SAndroid Build Coastguard Worker   start /= g_sectors;
108*cf5a6c84SAndroid Build Coastguard Worker   p->head = start % g_heads;
109*cf5a6c84SAndroid Build Coastguard Worker   start /= g_heads;
110*cf5a6c84SAndroid Build Coastguard Worker   p->cyl = start & 0xFF;
111*cf5a6c84SAndroid Build Coastguard Worker   p->sector |= (start >> 2) & 0xc0;
112*cf5a6c84SAndroid Build Coastguard Worker 
113*cf5a6c84SAndroid Build Coastguard Worker   if (dos_flag && (end / (g_sectors * g_heads) > 1023))
114*cf5a6c84SAndroid Build Coastguard Worker     end = g_heads * g_sectors * ONE_K - 1;
115*cf5a6c84SAndroid Build Coastguard Worker   p->end_sector = (end % g_sectors) + 1;
116*cf5a6c84SAndroid Build Coastguard Worker   end /= g_sectors;
117*cf5a6c84SAndroid Build Coastguard Worker   p->end_head = end % g_heads;
118*cf5a6c84SAndroid Build Coastguard Worker   end /= g_heads;
119*cf5a6c84SAndroid Build Coastguard Worker   p->end_cyl = end & 0xFF;
120*cf5a6c84SAndroid Build Coastguard Worker   p->end_sector |= (end >> 2) & 0xc0;
121*cf5a6c84SAndroid Build Coastguard Worker }
122*cf5a6c84SAndroid Build Coastguard Worker 
chs_warn(void)123*cf5a6c84SAndroid Build Coastguard Worker static int chs_warn(void)
124*cf5a6c84SAndroid Build Coastguard Worker {
125*cf5a6c84SAndroid Build Coastguard Worker   if (g_heads && g_sectors && g_cylinders)
126*cf5a6c84SAndroid Build Coastguard Worker     return 0;
127*cf5a6c84SAndroid Build Coastguard Worker 
128*cf5a6c84SAndroid Build Coastguard Worker   printf("Unknown value(s) for:");
129*cf5a6c84SAndroid Build Coastguard Worker   if (!g_heads) printf(" heads");
130*cf5a6c84SAndroid Build Coastguard Worker   if (!g_sectors) printf(" sectors");
131*cf5a6c84SAndroid Build Coastguard Worker   if (!g_cylinders) printf(" cylinders");
132*cf5a6c84SAndroid Build Coastguard Worker   printf(". can set in the expert menu.\n");
133*cf5a6c84SAndroid Build Coastguard Worker   return 1;
134*cf5a6c84SAndroid Build Coastguard Worker }
135*cf5a6c84SAndroid Build Coastguard Worker 
list_types(void)136*cf5a6c84SAndroid Build Coastguard Worker static void list_types(void)
137*cf5a6c84SAndroid Build Coastguard Worker {
138*cf5a6c84SAndroid Build Coastguard Worker   int i, adjust = 0, size = ARRAY_LEN(sys_types);
139*cf5a6c84SAndroid Build Coastguard Worker 
140*cf5a6c84SAndroid Build Coastguard Worker   if(size % 2) adjust = 1;
141*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < (size - adjust); i+=2)
142*cf5a6c84SAndroid Build Coastguard Worker     xprintf("%2x %-22s\t\t%2x %-22.22s\n", sys_types[i].id, sys_types[i].type,
143*cf5a6c84SAndroid Build Coastguard Worker         sys_types[i+1].id, sys_types[i+1].type);
144*cf5a6c84SAndroid Build Coastguard Worker   if (adjust) xprintf("%2x %-22s\n",sys_types[size-1].id, sys_types[size-1].type);
145*cf5a6c84SAndroid Build Coastguard Worker   xputc('\n');
146*cf5a6c84SAndroid Build Coastguard Worker }
147*cf5a6c84SAndroid Build Coastguard Worker 
read_sec_sz()148*cf5a6c84SAndroid Build Coastguard Worker static void read_sec_sz()
149*cf5a6c84SAndroid Build Coastguard Worker {
150*cf5a6c84SAndroid Build Coastguard Worker   int arg;
151*cf5a6c84SAndroid Build Coastguard Worker   if (ioctl(dev_fd, BLKSSZGET, &arg) == 0) g_sect_size = arg;
152*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(b)) {
153*cf5a6c84SAndroid Build Coastguard Worker     if (TT.sect_sz !=  512 && TT.sect_sz != 1024 && TT.sect_sz != 2048 &&
154*cf5a6c84SAndroid Build Coastguard Worker         TT.sect_sz != 4096)
155*cf5a6c84SAndroid Build Coastguard Worker     {
156*cf5a6c84SAndroid Build Coastguard Worker       help_exit("bad sector size");
157*cf5a6c84SAndroid Build Coastguard Worker     }
158*cf5a6c84SAndroid Build Coastguard Worker     g_sect_size = TT.sect_sz;
159*cf5a6c84SAndroid Build Coastguard Worker   }
160*cf5a6c84SAndroid Build Coastguard Worker }
161*cf5a6c84SAndroid Build Coastguard Worker 
read_size()162*cf5a6c84SAndroid Build Coastguard Worker static sector_t read_size()
163*cf5a6c84SAndroid Build Coastguard Worker {
164*cf5a6c84SAndroid Build Coastguard Worker   uint64_t sec64 = 0;
165*cf5a6c84SAndroid Build Coastguard Worker   unsigned long sectors = 0;
166*cf5a6c84SAndroid Build Coastguard Worker   if (ioctl(dev_fd, BLKGETSIZE64, &sec64) == 0) {
167*cf5a6c84SAndroid Build Coastguard Worker     sec64 = sec64 >> 9; //convert to 512 block size.
168*cf5a6c84SAndroid Build Coastguard Worker     if (sec64 != (uint32_t) sec64) {
169*cf5a6c84SAndroid Build Coastguard Worker       perror_msg("device has more than 2^32 sectors, can't use all of them");
170*cf5a6c84SAndroid Build Coastguard Worker       sec64 = (uint32_t) - 1L;
171*cf5a6c84SAndroid Build Coastguard Worker     }
172*cf5a6c84SAndroid Build Coastguard Worker     return sec64;
173*cf5a6c84SAndroid Build Coastguard Worker   }
174*cf5a6c84SAndroid Build Coastguard Worker   if (ioctl(dev_fd, BLKGETSIZE, &sectors) == 0)
175*cf5a6c84SAndroid Build Coastguard Worker     if (sizeof(long) > sizeof(sector_t) && sectors != (sector_t)sectors)
176*cf5a6c84SAndroid Build Coastguard Worker       sectors = (uint32_t) - 1L;
177*cf5a6c84SAndroid Build Coastguard Worker   return sectors;
178*cf5a6c84SAndroid Build Coastguard Worker }
179*cf5a6c84SAndroid Build Coastguard Worker 
validate_part_buff(char * buffer)180*cf5a6c84SAndroid Build Coastguard Worker static int validate_part_buff(char *buffer)
181*cf5a6c84SAndroid Build Coastguard Worker {
182*cf5a6c84SAndroid Build Coastguard Worker   if ((buffer[510] != 0x55) || (buffer[511] != 0xAA)) return 0;
183*cf5a6c84SAndroid Build Coastguard Worker   return 1;
184*cf5a6c84SAndroid Build Coastguard Worker }
185*cf5a6c84SAndroid Build Coastguard Worker 
is_partition_clear(struct partition * p)186*cf5a6c84SAndroid Build Coastguard Worker static int is_partition_clear(struct partition* p)
187*cf5a6c84SAndroid Build Coastguard Worker {
188*cf5a6c84SAndroid Build Coastguard Worker   int i = 0;
189*cf5a6c84SAndroid Build Coastguard Worker   unsigned char res = 0;
190*cf5a6c84SAndroid Build Coastguard Worker   const char *ptr = (const char*)p;
191*cf5a6c84SAndroid Build Coastguard Worker 
192*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < sizeof(struct partition); i++) res |= (unsigned char)ptr[i];
193*cf5a6c84SAndroid Build Coastguard Worker   return (res == 0x00);
194*cf5a6c84SAndroid Build Coastguard Worker }
195*cf5a6c84SAndroid Build Coastguard Worker 
swap_le32toh(unsigned char * cp)196*cf5a6c84SAndroid Build Coastguard Worker static uint32_t swap_le32toh(unsigned char *cp)
197*cf5a6c84SAndroid Build Coastguard Worker {
198*cf5a6c84SAndroid Build Coastguard Worker   uint32_t val;
199*cf5a6c84SAndroid Build Coastguard Worker   memcpy((void*)&val, cp, 4);
200*cf5a6c84SAndroid Build Coastguard Worker   return le32toh(val);
201*cf5a6c84SAndroid Build Coastguard Worker }
202*cf5a6c84SAndroid Build Coastguard Worker 
check_order(void)203*cf5a6c84SAndroid Build Coastguard Worker static int check_order(void)
204*cf5a6c84SAndroid Build Coastguard Worker {
205*cf5a6c84SAndroid Build Coastguard Worker   sector_t first[num_parts], last_seen_val = 0;
206*cf5a6c84SAndroid Build Coastguard Worker   int i;
207*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
208*cf5a6c84SAndroid Build Coastguard Worker   struct partition *px;
209*cf5a6c84SAndroid Build Coastguard Worker 
210*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
211*cf5a6c84SAndroid Build Coastguard Worker     if (i == 4) last_seen_val = 0;
212*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
213*cf5a6c84SAndroid Build Coastguard Worker     px = pe->part;
214*cf5a6c84SAndroid Build Coastguard Worker     if (px->sys_ind) {
215*cf5a6c84SAndroid Build Coastguard Worker       first[i] = swap_le32toh(px->start4) + pe->start_offset;
216*cf5a6c84SAndroid Build Coastguard Worker       if (last_seen_val > first[i]) return 1;
217*cf5a6c84SAndroid Build Coastguard Worker       last_seen_val = first[i];
218*cf5a6c84SAndroid Build Coastguard Worker     }
219*cf5a6c84SAndroid Build Coastguard Worker   }
220*cf5a6c84SAndroid Build Coastguard Worker   return 0;
221*cf5a6c84SAndroid Build Coastguard Worker }
222*cf5a6c84SAndroid Build Coastguard Worker 
read_geometry(struct hd_geometry * disk)223*cf5a6c84SAndroid Build Coastguard Worker static void read_geometry(struct hd_geometry *disk)
224*cf5a6c84SAndroid Build Coastguard Worker {
225*cf5a6c84SAndroid Build Coastguard Worker   struct hd_geometry geometry;
226*cf5a6c84SAndroid Build Coastguard Worker 
227*cf5a6c84SAndroid Build Coastguard Worker   if (ioctl(dev_fd, HDIO_GETGEO, &geometry)) return;
228*cf5a6c84SAndroid Build Coastguard Worker   disk->heads = geometry.heads;
229*cf5a6c84SAndroid Build Coastguard Worker   disk->sectors = geometry.sectors;
230*cf5a6c84SAndroid Build Coastguard Worker }
231*cf5a6c84SAndroid Build Coastguard Worker 
232*cf5a6c84SAndroid Build Coastguard Worker /* Read the extended boot record for the
233*cf5a6c84SAndroid Build Coastguard Worker  * logical partion details.
234*cf5a6c84SAndroid Build Coastguard Worker  */
read_ebr(int idx)235*cf5a6c84SAndroid Build Coastguard Worker static void read_ebr(int idx)
236*cf5a6c84SAndroid Build Coastguard Worker {
237*cf5a6c84SAndroid Build Coastguard Worker   char *sec_buf = NULL;
238*cf5a6c84SAndroid Build Coastguard Worker   sector_t offset = 0, local_start_off = 0;
239*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p, *q;
240*cf5a6c84SAndroid Build Coastguard Worker 
241*cf5a6c84SAndroid Build Coastguard Worker   q = p = partitions[idx].part;
242*cf5a6c84SAndroid Build Coastguard Worker   local_start_off = swap_le32toh(p->start4);
243*cf5a6c84SAndroid Build Coastguard Worker 
244*cf5a6c84SAndroid Build Coastguard Worker   if (!extended_offset) extended_offset = local_start_off;
245*cf5a6c84SAndroid Build Coastguard Worker   do {
246*cf5a6c84SAndroid Build Coastguard Worker     if (num_parts >= 60) {
247*cf5a6c84SAndroid Build Coastguard Worker       xprintf("Warning: deleting partitions after 60\n");
248*cf5a6c84SAndroid Build Coastguard Worker       memset(q, 0, sizeof(struct partition)); //clear_partition
249*cf5a6c84SAndroid Build Coastguard Worker       partitions[num_parts-1].modified = 1;
250*cf5a6c84SAndroid Build Coastguard Worker       break;
251*cf5a6c84SAndroid Build Coastguard Worker     }
252*cf5a6c84SAndroid Build Coastguard Worker 
253*cf5a6c84SAndroid Build Coastguard Worker     sec_buf = xzalloc(g_sect_size);
254*cf5a6c84SAndroid Build Coastguard Worker     partitions[num_parts].part = part_offset(sec_buf, 0);
255*cf5a6c84SAndroid Build Coastguard Worker     partitions[num_parts].sec_buffer = sec_buf;
256*cf5a6c84SAndroid Build Coastguard Worker     offset = swap_le32toh(q->start4);
257*cf5a6c84SAndroid Build Coastguard Worker 
258*cf5a6c84SAndroid Build Coastguard Worker     if (num_parts > 4) offset += local_start_off;
259*cf5a6c84SAndroid Build Coastguard Worker     partitions[num_parts].start_offset = offset;
260*cf5a6c84SAndroid Build Coastguard Worker     xlseek(dev_fd, (off_t)(offset * g_sect_size), SEEK_SET);
261*cf5a6c84SAndroid Build Coastguard Worker 
262*cf5a6c84SAndroid Build Coastguard Worker     if (g_sect_size != readall(dev_fd, sec_buf, g_sect_size)) {
263*cf5a6c84SAndroid Build Coastguard Worker       close(dev_fd);
264*cf5a6c84SAndroid Build Coastguard Worker       error_exit("Couldn't read sector zero\n");
265*cf5a6c84SAndroid Build Coastguard Worker     }
266*cf5a6c84SAndroid Build Coastguard Worker     num_parts++; //extended partions present.
267*cf5a6c84SAndroid Build Coastguard Worker     q = part_offset(sec_buf, 1);
268*cf5a6c84SAndroid Build Coastguard Worker   } while (!is_partition_clear(q) && IS_EXTENDED(q->sys_ind));
269*cf5a6c84SAndroid Build Coastguard Worker }
270*cf5a6c84SAndroid Build Coastguard Worker 
physical_HS(int * h,int * s)271*cf5a6c84SAndroid Build Coastguard Worker static void physical_HS(int* h, int *s)
272*cf5a6c84SAndroid Build Coastguard Worker {
273*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p;
274*cf5a6c84SAndroid Build Coastguard Worker   int i, end_h, end_s, e_hh = 0, e_ss = 0, ini = 1, dirty = 0;
275*cf5a6c84SAndroid Build Coastguard Worker   const unsigned char *bufp = (const unsigned char *)MBRbuf;
276*cf5a6c84SAndroid Build Coastguard Worker 
277*cf5a6c84SAndroid Build Coastguard Worker   if (!(validate_part_buff((char*)bufp))) return;
278*cf5a6c84SAndroid Build Coastguard Worker 
279*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < 4; i++) {
280*cf5a6c84SAndroid Build Coastguard Worker     p = part_offset((char*)bufp, i);
281*cf5a6c84SAndroid Build Coastguard Worker     if (p->sys_ind) {
282*cf5a6c84SAndroid Build Coastguard Worker       end_h = p->end_head + 1;
283*cf5a6c84SAndroid Build Coastguard Worker       end_s = (p->end_sector & 077);
284*cf5a6c84SAndroid Build Coastguard Worker       if (ini) {
285*cf5a6c84SAndroid Build Coastguard Worker         e_hh = end_h;
286*cf5a6c84SAndroid Build Coastguard Worker         e_ss = end_s;
287*cf5a6c84SAndroid Build Coastguard Worker         ini = 0;
288*cf5a6c84SAndroid Build Coastguard Worker       } else if (e_hh !=end_h || e_ss != end_s)
289*cf5a6c84SAndroid Build Coastguard Worker         dirty = 1;
290*cf5a6c84SAndroid Build Coastguard Worker     }
291*cf5a6c84SAndroid Build Coastguard Worker   }
292*cf5a6c84SAndroid Build Coastguard Worker   if (!dirty && !ini) {
293*cf5a6c84SAndroid Build Coastguard Worker     *h = e_hh;
294*cf5a6c84SAndroid Build Coastguard Worker     *s = e_ss;
295*cf5a6c84SAndroid Build Coastguard Worker   }
296*cf5a6c84SAndroid Build Coastguard Worker }
297*cf5a6c84SAndroid Build Coastguard Worker 
298*cf5a6c84SAndroid Build Coastguard Worker //Reset the primary partition table
reset_boot(int change)299*cf5a6c84SAndroid Build Coastguard Worker static void reset_boot(int change)
300*cf5a6c84SAndroid Build Coastguard Worker {
301*cf5a6c84SAndroid Build Coastguard Worker   int i;
302*cf5a6c84SAndroid Build Coastguard Worker   for(i = 0; i < 4; i++) {
303*cf5a6c84SAndroid Build Coastguard Worker     struct part_entry *pe = &partitions[i];
304*cf5a6c84SAndroid Build Coastguard Worker     pe->part = part_offset(MBRbuf, i);
305*cf5a6c84SAndroid Build Coastguard Worker     pe->start_offset = 0;
306*cf5a6c84SAndroid Build Coastguard Worker     pe->sec_buffer = MBRbuf;
307*cf5a6c84SAndroid Build Coastguard Worker     pe->modified = change;
308*cf5a6c84SAndroid Build Coastguard Worker   }
309*cf5a6c84SAndroid Build Coastguard Worker }
310*cf5a6c84SAndroid Build Coastguard Worker 
write_table_flag(char * buf)311*cf5a6c84SAndroid Build Coastguard Worker static inline void write_table_flag(char *buf)
312*cf5a6c84SAndroid Build Coastguard Worker {
313*cf5a6c84SAndroid Build Coastguard Worker   buf[510] = 0x55;
314*cf5a6c84SAndroid Build Coastguard Worker   buf[511] = 0xaa;
315*cf5a6c84SAndroid Build Coastguard Worker }
316*cf5a6c84SAndroid Build Coastguard Worker 
317*cf5a6c84SAndroid Build Coastguard Worker /* free the buffers used for holding details of
318*cf5a6c84SAndroid Build Coastguard Worker  * extended logical partions
319*cf5a6c84SAndroid Build Coastguard Worker */
free_bufs(void)320*cf5a6c84SAndroid Build Coastguard Worker static void free_bufs(void)
321*cf5a6c84SAndroid Build Coastguard Worker {
322*cf5a6c84SAndroid Build Coastguard Worker   int i = 4;
323*cf5a6c84SAndroid Build Coastguard Worker   for (; i < num_parts; i++) free(partitions[i].sec_buffer);
324*cf5a6c84SAndroid Build Coastguard Worker }
325*cf5a6c84SAndroid Build Coastguard Worker 
create_empty_doslabel(void)326*cf5a6c84SAndroid Build Coastguard Worker static void create_empty_doslabel(void)
327*cf5a6c84SAndroid Build Coastguard Worker {
328*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Building a new DOS Disklabel. The changes will\n"
329*cf5a6c84SAndroid Build Coastguard Worker       "remain in memory only, until you write it.\n");
330*cf5a6c84SAndroid Build Coastguard Worker 
331*cf5a6c84SAndroid Build Coastguard Worker   num_parts = 4;
332*cf5a6c84SAndroid Build Coastguard Worker   extended_offset = 0;
333*cf5a6c84SAndroid Build Coastguard Worker   memset(&MBRbuf[510 - 4*16], 0, 4*16);
334*cf5a6c84SAndroid Build Coastguard Worker   write_table_flag(MBRbuf);
335*cf5a6c84SAndroid Build Coastguard Worker   partitions[0].modified = 1;
336*cf5a6c84SAndroid Build Coastguard Worker   reset_boot(1);
337*cf5a6c84SAndroid Build Coastguard Worker }
338*cf5a6c84SAndroid Build Coastguard Worker 
339*cf5a6c84SAndroid Build Coastguard Worker /* Read the Master Boot sector of the device for the
340*cf5a6c84SAndroid Build Coastguard Worker  * partition table entries/details.
341*cf5a6c84SAndroid Build Coastguard Worker  * If any extended partition is found then read the EBR
342*cf5a6c84SAndroid Build Coastguard Worker  * for logical partition details
343*cf5a6c84SAndroid Build Coastguard Worker  */
read_mbr(char * device,int validate)344*cf5a6c84SAndroid Build Coastguard Worker static int read_mbr(char *device, int validate)
345*cf5a6c84SAndroid Build Coastguard Worker {
346*cf5a6c84SAndroid Build Coastguard Worker   int fd, sector_fac, i, h = 0, s = 0;
347*cf5a6c84SAndroid Build Coastguard Worker   struct hd_geometry disk;
348*cf5a6c84SAndroid Build Coastguard Worker   fd = open(device, O_RDWR);
349*cf5a6c84SAndroid Build Coastguard Worker   if(fd < 0) {
350*cf5a6c84SAndroid Build Coastguard Worker     perror_msg("can't open '%s'",device);
351*cf5a6c84SAndroid Build Coastguard Worker     return 1;
352*cf5a6c84SAndroid Build Coastguard Worker   }
353*cf5a6c84SAndroid Build Coastguard Worker 
354*cf5a6c84SAndroid Build Coastguard Worker   disk_device = strdup(device);
355*cf5a6c84SAndroid Build Coastguard Worker   if(fd != dev_fd) {
356*cf5a6c84SAndroid Build Coastguard Worker     if(dup2(fd, dev_fd) != dev_fd) perror_exit("Can't dup2");
357*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
358*cf5a6c84SAndroid Build Coastguard Worker   }
359*cf5a6c84SAndroid Build Coastguard Worker 
360*cf5a6c84SAndroid Build Coastguard Worker   //read partition table - MBR
361*cf5a6c84SAndroid Build Coastguard Worker   if (SECTOR_SIZE != readall(dev_fd, MBRbuf, SECTOR_SIZE)) {
362*cf5a6c84SAndroid Build Coastguard Worker     close(dev_fd);
363*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("Couldn't read sector zero\n");
364*cf5a6c84SAndroid Build Coastguard Worker   }
365*cf5a6c84SAndroid Build Coastguard Worker   if (validate && !validate_part_buff(MBRbuf)) {
366*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Device contains neither a valid DOS "
367*cf5a6c84SAndroid Build Coastguard Worker         "partition table, nor Sun, SGI, OSF or GPT "
368*cf5a6c84SAndroid Build Coastguard Worker         "disklabel\n");
369*cf5a6c84SAndroid Build Coastguard Worker     create_empty_doslabel();
370*cf5a6c84SAndroid Build Coastguard Worker   }
371*cf5a6c84SAndroid Build Coastguard Worker 
372*cf5a6c84SAndroid Build Coastguard Worker   disk.heads = disk.sectors = 0;
373*cf5a6c84SAndroid Build Coastguard Worker   read_geometry(&disk); //CHS values
374*cf5a6c84SAndroid Build Coastguard Worker   total_number_sectors = read_size(); //Device size
375*cf5a6c84SAndroid Build Coastguard Worker   read_sec_sz();
376*cf5a6c84SAndroid Build Coastguard Worker   sector_fac = g_sect_size/SECTOR_SIZE; //512 is hardware sector size.
377*cf5a6c84SAndroid Build Coastguard Worker   physical_HS(&h, &s); //physical dimensions may be diferent from HDIO_GETGEO
378*cf5a6c84SAndroid Build Coastguard Worker   g_sectors = (FLAG(S) && TT.sectors) ? TT.sectors : s ? s : disk.sectors ? disk.sectors : 63;
379*cf5a6c84SAndroid Build Coastguard Worker   g_heads = (FLAG(H) && TT.heads) ? TT.heads : h ? h : disk.heads ? disk.heads : 255;
380*cf5a6c84SAndroid Build Coastguard Worker   g_cylinders = total_number_sectors/(g_heads * g_sectors * sector_fac);
381*cf5a6c84SAndroid Build Coastguard Worker 
382*cf5a6c84SAndroid Build Coastguard Worker   if (!g_cylinders) g_cylinders = FLAG(C) ? TT.cylinders : 0;
383*cf5a6c84SAndroid Build Coastguard Worker   if ((g_cylinders > ONE_K) && !(FLAG(l) || FLAG(S)))
384*cf5a6c84SAndroid Build Coastguard Worker     xprintf("\nThe number of cylinders for this disk is set to %lu.\n"
385*cf5a6c84SAndroid Build Coastguard Worker         "There is nothing wrong with that, but this is larger than 1024,\n"
386*cf5a6c84SAndroid Build Coastguard Worker         "and could in certain setups cause problems.\n", g_cylinders);
387*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
388*cf5a6c84SAndroid Build Coastguard Worker     if (IS_EXTENDED(partitions[i].part->sys_ind)) {
389*cf5a6c84SAndroid Build Coastguard Worker       read_ebr(i);
390*cf5a6c84SAndroid Build Coastguard Worker       break;
391*cf5a6c84SAndroid Build Coastguard Worker     }
392*cf5a6c84SAndroid Build Coastguard Worker   }
393*cf5a6c84SAndroid Build Coastguard Worker   chs_warn();
394*cf5a6c84SAndroid Build Coastguard Worker 
395*cf5a6c84SAndroid Build Coastguard Worker   return 0;
396*cf5a6c84SAndroid Build Coastguard Worker }
397*cf5a6c84SAndroid Build Coastguard Worker 
get_type(int sys_ind)398*cf5a6c84SAndroid Build Coastguard Worker static char* get_type(int sys_ind)
399*cf5a6c84SAndroid Build Coastguard Worker {
400*cf5a6c84SAndroid Build Coastguard Worker   int i, size = ARRAY_LEN(sys_types);
401*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < size; i++)
402*cf5a6c84SAndroid Build Coastguard Worker     if (sys_ind == sys_types[i].id)
403*cf5a6c84SAndroid Build Coastguard Worker       return sys_types[i].type;
404*cf5a6c84SAndroid Build Coastguard Worker   return "Unknown";
405*cf5a6c84SAndroid Build Coastguard Worker }
406*cf5a6c84SAndroid Build Coastguard Worker 
consistency_check(const struct partition * p,int partition)407*cf5a6c84SAndroid Build Coastguard Worker static void consistency_check(const struct partition *p, int partition)
408*cf5a6c84SAndroid Build Coastguard Worker {
409*cf5a6c84SAndroid Build Coastguard Worker   unsigned physbc, physbh, physbs, physec, physeh, physes;
410*cf5a6c84SAndroid Build Coastguard Worker   unsigned lbc, lbh, lbs, lec, leh, les;
411*cf5a6c84SAndroid Build Coastguard Worker   sector_t start, end;
412*cf5a6c84SAndroid Build Coastguard Worker 
413*cf5a6c84SAndroid Build Coastguard Worker   if (!g_heads || !g_sectors || (partition >= 4)) return;
414*cf5a6c84SAndroid Build Coastguard Worker   // physical beginning c, h, s
415*cf5a6c84SAndroid Build Coastguard Worker   physbc = cylinder(p->sector,p->cyl);
416*cf5a6c84SAndroid Build Coastguard Worker   physbh = p->head;
417*cf5a6c84SAndroid Build Coastguard Worker   physbs = sector(p->sector);
418*cf5a6c84SAndroid Build Coastguard Worker   // physical ending c, h, s
419*cf5a6c84SAndroid Build Coastguard Worker   physec = cylinder(p->end_sector, p->end_cyl);
420*cf5a6c84SAndroid Build Coastguard Worker   physeh = p->end_head;
421*cf5a6c84SAndroid Build Coastguard Worker   physes = sector(p->end_sector);
422*cf5a6c84SAndroid Build Coastguard Worker   // logical begin and end CHS values
423*cf5a6c84SAndroid Build Coastguard Worker   start = swap_le32toh((unsigned char*)(p->start4));
424*cf5a6c84SAndroid Build Coastguard Worker   end = start + swap_le32toh((unsigned char*)(p->size4)) -1;
425*cf5a6c84SAndroid Build Coastguard Worker 
426*cf5a6c84SAndroid Build Coastguard Worker   lbc = start/(g_sectors * g_heads);
427*cf5a6c84SAndroid Build Coastguard Worker   lbh = (start/g_sectors) % g_heads;
428*cf5a6c84SAndroid Build Coastguard Worker   lbs = (start % g_sectors) + 1;
429*cf5a6c84SAndroid Build Coastguard Worker 
430*cf5a6c84SAndroid Build Coastguard Worker   lec = end/(g_sectors * g_heads);
431*cf5a6c84SAndroid Build Coastguard Worker   leh = (end/g_sectors) % g_heads;
432*cf5a6c84SAndroid Build Coastguard Worker   les = (end % g_sectors) + 1;
433*cf5a6c84SAndroid Build Coastguard Worker 
434*cf5a6c84SAndroid Build Coastguard Worker   //Logical and Physical diff
435*cf5a6c84SAndroid Build Coastguard Worker   if (g_cylinders <= ONE_K && (physbc != lbc || physbh != lbh || physbs != lbs)) {
436*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u has different physical/logical beginnings (Non-Linux?): \n", partition+1);
437*cf5a6c84SAndroid Build Coastguard Worker     xprintf("phys = (%u %u %u) ",physbc, physbh, physbs);
438*cf5a6c84SAndroid Build Coastguard Worker     xprintf("logical = (%u %u %u)\n", lbc, lbh, lbs);
439*cf5a6c84SAndroid Build Coastguard Worker   }
440*cf5a6c84SAndroid Build Coastguard Worker   if (g_cylinders <= ONE_K && (physec != lec || physeh != leh || physes != les)) {
441*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u has different physical/logical endings: \n", partition+1);
442*cf5a6c84SAndroid Build Coastguard Worker     xprintf("phys = (%u %u %u) ",physec, physeh, physes);
443*cf5a6c84SAndroid Build Coastguard Worker     xprintf("logical = (%u %u %u)\n", lec, leh, les);
444*cf5a6c84SAndroid Build Coastguard Worker   }
445*cf5a6c84SAndroid Build Coastguard Worker   // Ending on cylinder boundary?
446*cf5a6c84SAndroid Build Coastguard Worker   if (physeh != (g_heads - 1) || physes != g_sectors)
447*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u does not end on cylinder boundary\n", partition + 1);
448*cf5a6c84SAndroid Build Coastguard Worker }
449*cf5a6c84SAndroid Build Coastguard Worker 
450*cf5a6c84SAndroid Build Coastguard Worker // List the partition details
list_partitions(int validate)451*cf5a6c84SAndroid Build Coastguard Worker static void list_partitions(int validate)
452*cf5a6c84SAndroid Build Coastguard Worker {
453*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p;
454*cf5a6c84SAndroid Build Coastguard Worker   uint32_t start_cyl, end_cyl, start_sec, end_sec, blocks, secs;
455*cf5a6c84SAndroid Build Coastguard Worker   char boot, lastchar = '\0', *dev = disk_device;
456*cf5a6c84SAndroid Build Coastguard Worker   int i = 0, len = strlen(disk_device), odds = 0;
457*cf5a6c84SAndroid Build Coastguard Worker 
458*cf5a6c84SAndroid Build Coastguard Worker   if (validate && !validate_part_buff(MBRbuf)) {
459*cf5a6c84SAndroid Build Coastguard Worker     close(dev_fd);
460*cf5a6c84SAndroid Build Coastguard Worker     toys.exitval = 1;
461*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Device %s: doesn't contain a valid partition table\n", disk_device);
462*cf5a6c84SAndroid Build Coastguard Worker     return;
463*cf5a6c84SAndroid Build Coastguard Worker   }
464*cf5a6c84SAndroid Build Coastguard Worker   if (isdigit(dev[len - 1])) lastchar = 'p';
465*cf5a6c84SAndroid Build Coastguard Worker 
466*cf5a6c84SAndroid Build Coastguard Worker   xprintf("%*s Boot      Start         End      Blocks  Id System\n", len+1, "Device");
467*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
468*cf5a6c84SAndroid Build Coastguard Worker     p = partitions[i].part;
469*cf5a6c84SAndroid Build Coastguard Worker     if (is_partition_clear(p)) continue;
470*cf5a6c84SAndroid Build Coastguard Worker 
471*cf5a6c84SAndroid Build Coastguard Worker     boot = ((p->boot_ind == 0x80)?'*':(!p->boot_ind)?' ':'?');
472*cf5a6c84SAndroid Build Coastguard Worker     start_sec = swap_le32toh(p->start4) + partitions[i].start_offset;
473*cf5a6c84SAndroid Build Coastguard Worker     secs = swap_le32toh(p->size4);
474*cf5a6c84SAndroid Build Coastguard Worker 
475*cf5a6c84SAndroid Build Coastguard Worker     if ((start_sec + secs) == 0) end_sec = 0;
476*cf5a6c84SAndroid Build Coastguard Worker     else end_sec = start_sec + secs -1;
477*cf5a6c84SAndroid Build Coastguard Worker     start_cyl = start_sec/(g_heads * g_sectors) + 1;
478*cf5a6c84SAndroid Build Coastguard Worker     end_cyl = end_sec/(g_heads * g_sectors) + 1;
479*cf5a6c84SAndroid Build Coastguard Worker     blocks = secs;
480*cf5a6c84SAndroid Build Coastguard Worker     if (g_sect_size < ONE_K) {
481*cf5a6c84SAndroid Build Coastguard Worker       blocks /= (ONE_K/g_sect_size);
482*cf5a6c84SAndroid Build Coastguard Worker       odds = secs %(ONE_K/g_sect_size);
483*cf5a6c84SAndroid Build Coastguard Worker     } else if (g_sect_size > ONE_K) blocks *= (g_sect_size/ONE_K);
484*cf5a6c84SAndroid Build Coastguard Worker 
485*cf5a6c84SAndroid Build Coastguard Worker     if (lastchar) xprintf("%s%c%d",dev, lastchar, i+1);
486*cf5a6c84SAndroid Build Coastguard Worker     else xprintf("%s%d",dev, i+1);
487*cf5a6c84SAndroid Build Coastguard Worker 
488*cf5a6c84SAndroid Build Coastguard Worker     xprintf("   %c %11u %11u %11u%c %2x %s\n",
489*cf5a6c84SAndroid Build Coastguard Worker         boot,
490*cf5a6c84SAndroid Build Coastguard Worker         disp_unit_cyl == 0? start_sec: start_cyl,
491*cf5a6c84SAndroid Build Coastguard Worker         disp_unit_cyl == 0? end_sec: end_cyl,
492*cf5a6c84SAndroid Build Coastguard Worker         blocks,odds?'+':' ', p->sys_ind, get_type(p->sys_ind));
493*cf5a6c84SAndroid Build Coastguard Worker 
494*cf5a6c84SAndroid Build Coastguard Worker     consistency_check(p, i);
495*cf5a6c84SAndroid Build Coastguard Worker   }
496*cf5a6c84SAndroid Build Coastguard Worker   if (check_order()) xprintf("\nPartition table entries are not in disk order");
497*cf5a6c84SAndroid Build Coastguard Worker }
498*cf5a6c84SAndroid Build Coastguard Worker 
499*cf5a6c84SAndroid Build Coastguard Worker //Print device details
print_mbr(int validate)500*cf5a6c84SAndroid Build Coastguard Worker static void print_mbr(int validate)
501*cf5a6c84SAndroid Build Coastguard Worker {
502*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long bytes = ((unsigned long long)total_number_sectors << 9);
503*cf5a6c84SAndroid Build Coastguard Worker   long mbytes = bytes/1000000;
504*cf5a6c84SAndroid Build Coastguard Worker 
505*cf5a6c84SAndroid Build Coastguard Worker   if (mbytes < 10000) xprintf("Disk %s: %lu MB, %llu bytes\n", disk_device, mbytes, bytes);
506*cf5a6c84SAndroid Build Coastguard Worker   else xprintf("Disk %s: %lu.%lu GB, %llu bytes\n", disk_device, mbytes/1000, (mbytes/100)%10, bytes);
507*cf5a6c84SAndroid Build Coastguard Worker   xprintf("%ld heads, %ld sectors/track, %ld cylinders", g_heads, g_sectors, g_cylinders);
508*cf5a6c84SAndroid Build Coastguard Worker   if (!disp_unit_cyl) {
509*cf5a6c84SAndroid Build Coastguard Worker     xprintf(", total %lld sectors\n", total_number_sectors/(g_sect_size/SECTOR_SIZE));
510*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Units = sectors of 1 * %ld = %ld bytes\n",g_sect_size, g_sect_size);
511*cf5a6c84SAndroid Build Coastguard Worker   } else xprintf("\nUnits = cylinders of %ld * %ld = %ld bytes\n\n",
512*cf5a6c84SAndroid Build Coastguard Worker       g_heads * g_sectors, g_sect_size, g_heads * g_sectors * g_sect_size);
513*cf5a6c84SAndroid Build Coastguard Worker   list_partitions(validate);
514*cf5a6c84SAndroid Build Coastguard Worker   xputc('\n');
515*cf5a6c84SAndroid Build Coastguard Worker }
516*cf5a6c84SAndroid Build Coastguard Worker 
init_members(void)517*cf5a6c84SAndroid Build Coastguard Worker static void init_members(void)
518*cf5a6c84SAndroid Build Coastguard Worker {
519*cf5a6c84SAndroid Build Coastguard Worker   int i = 0;
520*cf5a6c84SAndroid Build Coastguard Worker   num_parts = 4; //max of primaries in a part table
521*cf5a6c84SAndroid Build Coastguard Worker   disp_unit_cyl = dos_flag = 1;
522*cf5a6c84SAndroid Build Coastguard Worker   extended_offset = 0;
523*cf5a6c84SAndroid Build Coastguard Worker   g_sect_size = SECTOR_SIZE;
524*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
525*cf5a6c84SAndroid Build Coastguard Worker     partitions[i].part = part_offset(MBRbuf, i);
526*cf5a6c84SAndroid Build Coastguard Worker     partitions[i].sec_buffer = MBRbuf;
527*cf5a6c84SAndroid Build Coastguard Worker     partitions[i].modified = 0;
528*cf5a6c84SAndroid Build Coastguard Worker     partitions[i].start_offset = 0;
529*cf5a6c84SAndroid Build Coastguard Worker   }
530*cf5a6c84SAndroid Build Coastguard Worker }
531*cf5a6c84SAndroid Build Coastguard Worker 
read_input(char * mesg,char * outp)532*cf5a6c84SAndroid Build Coastguard Worker static int read_input(char *mesg, char *outp)
533*cf5a6c84SAndroid Build Coastguard Worker {
534*cf5a6c84SAndroid Build Coastguard Worker   char *p;
535*cf5a6c84SAndroid Build Coastguard Worker   int size = 0;
536*cf5a6c84SAndroid Build Coastguard Worker   do {
537*cf5a6c84SAndroid Build Coastguard Worker     xprintf("%s", mesg);
538*cf5a6c84SAndroid Build Coastguard Worker     p = fgets(toybuf, 80, stdin);
539*cf5a6c84SAndroid Build Coastguard Worker 
540*cf5a6c84SAndroid Build Coastguard Worker     if (!p || !(size = strlen(p))) exit(0);
541*cf5a6c84SAndroid Build Coastguard Worker     if (p[size-1] == '\n') p[--size] = '\0';
542*cf5a6c84SAndroid Build Coastguard Worker   } while (!size);
543*cf5a6c84SAndroid Build Coastguard Worker 
544*cf5a6c84SAndroid Build Coastguard Worker   while (*p != '\0' && *p <= ' ') p++;
545*cf5a6c84SAndroid Build Coastguard Worker   if (outp) memcpy(outp, p, strlen(p) + 1); //1 for nul
546*cf5a6c84SAndroid Build Coastguard Worker   return *p;
547*cf5a6c84SAndroid Build Coastguard Worker }
548*cf5a6c84SAndroid Build Coastguard Worker 
read_hex(char * mesg)549*cf5a6c84SAndroid Build Coastguard Worker static int read_hex(char *mesg)
550*cf5a6c84SAndroid Build Coastguard Worker {
551*cf5a6c84SAndroid Build Coastguard Worker   int val;
552*cf5a6c84SAndroid Build Coastguard Worker   char input[80], *endp;
553*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
554*cf5a6c84SAndroid Build Coastguard Worker     read_input(mesg, input);
555*cf5a6c84SAndroid Build Coastguard Worker     if ((*input | 0x20) == 'l') {
556*cf5a6c84SAndroid Build Coastguard Worker       list_types();
557*cf5a6c84SAndroid Build Coastguard Worker       memset(input, 0, 80);
558*cf5a6c84SAndroid Build Coastguard Worker       continue;
559*cf5a6c84SAndroid Build Coastguard Worker     }
560*cf5a6c84SAndroid Build Coastguard Worker     val = strtoul(input, &endp, 16);
561*cf5a6c84SAndroid Build Coastguard Worker     if (endp && *endp) continue;
562*cf5a6c84SAndroid Build Coastguard Worker     if (val <= 0xff) return val;
563*cf5a6c84SAndroid Build Coastguard Worker   }
564*cf5a6c84SAndroid Build Coastguard Worker }
565*cf5a6c84SAndroid Build Coastguard Worker 
566*cf5a6c84SAndroid Build Coastguard Worker /* Delete an exiting partition,
567*cf5a6c84SAndroid Build Coastguard Worker  * if its primary, then just clear the partition details
568*cf5a6c84SAndroid Build Coastguard Worker  * if extended, then clear the partition details, also for logical
569*cf5a6c84SAndroid Build Coastguard Worker  * if only logical, then move the later partitions backwards 1 step
570*cf5a6c84SAndroid Build Coastguard Worker  */
delete_partition(int i)571*cf5a6c84SAndroid Build Coastguard Worker void delete_partition(int i)
572*cf5a6c84SAndroid Build Coastguard Worker {
573*cf5a6c84SAndroid Build Coastguard Worker   int sys_id, looper = 0;
574*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p, *q, *ext_p, *ext_q;
575*cf5a6c84SAndroid Build Coastguard Worker   sector_t new_start;
576*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe = &partitions[i];
577*cf5a6c84SAndroid Build Coastguard Worker 
578*cf5a6c84SAndroid Build Coastguard Worker   if (chs_warn()) return;
579*cf5a6c84SAndroid Build Coastguard Worker   p = pe->part;
580*cf5a6c84SAndroid Build Coastguard Worker   sys_id = p->sys_ind;
581*cf5a6c84SAndroid Build Coastguard Worker   if (!sys_id) xprintf("Partition %u is empty\n", i+1);
582*cf5a6c84SAndroid Build Coastguard Worker 
583*cf5a6c84SAndroid Build Coastguard Worker   if (i < 4 && !IS_EXTENDED(sys_id)) {
584*cf5a6c84SAndroid Build Coastguard Worker     memset(p, 0, sizeof(struct partition)); //clear_partition
585*cf5a6c84SAndroid Build Coastguard Worker     pe->modified = 1;
586*cf5a6c84SAndroid Build Coastguard Worker   } else if (i < 4 && IS_EXTENDED(sys_id)) {
587*cf5a6c84SAndroid Build Coastguard Worker     memset(p, 0, sizeof(struct partition)); //clear_partition
588*cf5a6c84SAndroid Build Coastguard Worker     pe->modified = 1;
589*cf5a6c84SAndroid Build Coastguard Worker     for (looper = 4; looper < num_parts; looper++) {
590*cf5a6c84SAndroid Build Coastguard Worker       pe = &partitions[looper];
591*cf5a6c84SAndroid Build Coastguard Worker       p = pe->part;
592*cf5a6c84SAndroid Build Coastguard Worker       if (is_partition_clear(p)) break;
593*cf5a6c84SAndroid Build Coastguard Worker       else {
594*cf5a6c84SAndroid Build Coastguard Worker         memset(p, 0, sizeof(struct partition)); //clear_partition
595*cf5a6c84SAndroid Build Coastguard Worker         pe->modified = 1;
596*cf5a6c84SAndroid Build Coastguard Worker         free(pe->sec_buffer);
597*cf5a6c84SAndroid Build Coastguard Worker       }
598*cf5a6c84SAndroid Build Coastguard Worker     }
599*cf5a6c84SAndroid Build Coastguard Worker     extended_offset = 0;
600*cf5a6c84SAndroid Build Coastguard Worker     num_parts = 4;
601*cf5a6c84SAndroid Build Coastguard Worker   } else {
602*cf5a6c84SAndroid Build Coastguard Worker     //only logical is delete, need to move the rest of them backwards
603*cf5a6c84SAndroid Build Coastguard Worker     if (i == 4) { //move partiton# 6 to 5.
604*cf5a6c84SAndroid Build Coastguard Worker       partitions[i].modified = 1;
605*cf5a6c84SAndroid Build Coastguard Worker       if (num_parts > i+1) {
606*cf5a6c84SAndroid Build Coastguard Worker         q = partitions[i + 1].part;
607*cf5a6c84SAndroid Build Coastguard Worker         *p = *q; //copy the part table
608*cf5a6c84SAndroid Build Coastguard Worker         ext_p = part_offset(partitions[i].sec_buffer, 1);
609*cf5a6c84SAndroid Build Coastguard Worker         ext_q = part_offset(partitions[i + 1].sec_buffer, 1);
610*cf5a6c84SAndroid Build Coastguard Worker         *ext_p = *ext_q; //copy the extended info pointer
611*cf5a6c84SAndroid Build Coastguard Worker         // change the start of the 4th partiton.
612*cf5a6c84SAndroid Build Coastguard Worker         new_start = partitions[i + 1].start_offset + swap_le32toh(q->start4) - extended_offset;
613*cf5a6c84SAndroid Build Coastguard Worker         new_start = SWAP_LE32(new_start);
614*cf5a6c84SAndroid Build Coastguard Worker         memcpy(p->start4, (void *)&new_start, 4);
615*cf5a6c84SAndroid Build Coastguard Worker       } else {
616*cf5a6c84SAndroid Build Coastguard Worker         memset(partitions[i].part, 0, sizeof(struct partition));
617*cf5a6c84SAndroid Build Coastguard Worker         return; //only logical
618*cf5a6c84SAndroid Build Coastguard Worker       }
619*cf5a6c84SAndroid Build Coastguard Worker     } else if (i > 4) {
620*cf5a6c84SAndroid Build Coastguard Worker       ext_p = part_offset(partitions[i-1].sec_buffer, 1);
621*cf5a6c84SAndroid Build Coastguard Worker       ext_q = part_offset(partitions[i].sec_buffer, 1);
622*cf5a6c84SAndroid Build Coastguard Worker       memcpy((void*)ext_p, (void *)ext_q, sizeof(struct partition));
623*cf5a6c84SAndroid Build Coastguard Worker       partitions[i-1].modified = 1;
624*cf5a6c84SAndroid Build Coastguard Worker     }
625*cf5a6c84SAndroid Build Coastguard Worker     if (i == 4) looper = i+2;
626*cf5a6c84SAndroid Build Coastguard Worker     else if (i > 4) looper = i+1;
627*cf5a6c84SAndroid Build Coastguard Worker     for (; looper < num_parts; looper++)
628*cf5a6c84SAndroid Build Coastguard Worker       partitions[looper-1] = partitions[looper];
629*cf5a6c84SAndroid Build Coastguard Worker     num_parts--;
630*cf5a6c84SAndroid Build Coastguard Worker   }
631*cf5a6c84SAndroid Build Coastguard Worker }
632*cf5a6c84SAndroid Build Coastguard Worker 
ask_partition(int num_parts)633*cf5a6c84SAndroid Build Coastguard Worker static int ask_partition(int num_parts)
634*cf5a6c84SAndroid Build Coastguard Worker {
635*cf5a6c84SAndroid Build Coastguard Worker   int val;
636*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
637*cf5a6c84SAndroid Build Coastguard Worker     do {
638*cf5a6c84SAndroid Build Coastguard Worker       xprintf("Partition (%u - %u):", 1, num_parts);
639*cf5a6c84SAndroid Build Coastguard Worker       fgets(toybuf, 80, stdin);
640*cf5a6c84SAndroid Build Coastguard Worker     } while (!isdigit(*toybuf));
641*cf5a6c84SAndroid Build Coastguard Worker     val = atoi(toybuf);
642*cf5a6c84SAndroid Build Coastguard Worker     if (val > 0 && val <= num_parts) return val;
643*cf5a6c84SAndroid Build Coastguard Worker     else xprintf("Invalid number entered\n");
644*cf5a6c84SAndroid Build Coastguard Worker   }
645*cf5a6c84SAndroid Build Coastguard Worker }
646*cf5a6c84SAndroid Build Coastguard Worker 
toggle_active_flag(int i)647*cf5a6c84SAndroid Build Coastguard Worker static void toggle_active_flag(int i)
648*cf5a6c84SAndroid Build Coastguard Worker {
649*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p = partitions[i].part;
650*cf5a6c84SAndroid Build Coastguard Worker   if (is_partition_clear(p)) xprintf("Partition %u is empty\n", i+1);
651*cf5a6c84SAndroid Build Coastguard Worker 
652*cf5a6c84SAndroid Build Coastguard Worker   if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
653*cf5a6c84SAndroid Build Coastguard Worker     xprintf("WARNING: Partition %u is an extended partition\n", i + 1);
654*cf5a6c84SAndroid Build Coastguard Worker   p->boot_ind = p->boot_ind == 0x80?0 : 0x80;
655*cf5a6c84SAndroid Build Coastguard Worker   partitions[i].modified = 1;
656*cf5a6c84SAndroid Build Coastguard Worker }
657*cf5a6c84SAndroid Build Coastguard Worker 
658*cf5a6c84SAndroid Build Coastguard Worker //Write the partition details from Buffer to Disk.
write_table(void)659*cf5a6c84SAndroid Build Coastguard Worker void write_table(void)
660*cf5a6c84SAndroid Build Coastguard Worker {
661*cf5a6c84SAndroid Build Coastguard Worker   int i =0;
662*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
663*cf5a6c84SAndroid Build Coastguard Worker   sector_t offset;
664*cf5a6c84SAndroid Build Coastguard Worker 
665*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < 4; i++)
666*cf5a6c84SAndroid Build Coastguard Worker     if (partitions[i].modified) partitions[3].modified = 1;
667*cf5a6c84SAndroid Build Coastguard Worker 
668*cf5a6c84SAndroid Build Coastguard Worker   for (i = 3; i < num_parts; i++) {
669*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
670*cf5a6c84SAndroid Build Coastguard Worker     write_table_flag(pe->sec_buffer);
671*cf5a6c84SAndroid Build Coastguard Worker     offset = pe->start_offset;
672*cf5a6c84SAndroid Build Coastguard Worker     if (pe->modified == 1) {
673*cf5a6c84SAndroid Build Coastguard Worker       xlseek(dev_fd, offset * g_sect_size, SEEK_SET);
674*cf5a6c84SAndroid Build Coastguard Worker       xwrite(dev_fd, pe->sec_buffer, g_sect_size);
675*cf5a6c84SAndroid Build Coastguard Worker     }
676*cf5a6c84SAndroid Build Coastguard Worker   }
677*cf5a6c84SAndroid Build Coastguard Worker   xprintf("The partition table has been altered.\n");
678*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Calling ioctl() to re-read partition table\n");
679*cf5a6c84SAndroid Build Coastguard Worker   sync();
680*cf5a6c84SAndroid Build Coastguard Worker   for (i = 4; i < num_parts; i++) free(partitions[i].sec_buffer);
681*cf5a6c84SAndroid Build Coastguard Worker   if(ioctl(dev_fd, BLKRRPART, NULL) < 0)
682*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("WARNING: rereading partition table failed, kernel still uses old table");
683*cf5a6c84SAndroid Build Coastguard Worker 
684*cf5a6c84SAndroid Build Coastguard Worker }
685*cf5a6c84SAndroid Build Coastguard Worker 
686*cf5a6c84SAndroid Build Coastguard Worker /* try to find a partition for deletion, if only
687*cf5a6c84SAndroid Build Coastguard Worker  * one, then select the same, else ask from USER
688*cf5a6c84SAndroid Build Coastguard Worker  */
get_non_free_partition(int max)689*cf5a6c84SAndroid Build Coastguard Worker static int get_non_free_partition(int max)
690*cf5a6c84SAndroid Build Coastguard Worker {
691*cf5a6c84SAndroid Build Coastguard Worker   int num = -1, i = 0;
692*cf5a6c84SAndroid Build Coastguard Worker 
693*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < max; i++) {
694*cf5a6c84SAndroid Build Coastguard Worker     if (!is_partition_clear(partitions[i].part)) {
695*cf5a6c84SAndroid Build Coastguard Worker       if (num >= 0)
696*cf5a6c84SAndroid Build Coastguard Worker         return ask_partition(num_parts)-1;
697*cf5a6c84SAndroid Build Coastguard Worker       num = i;
698*cf5a6c84SAndroid Build Coastguard Worker     }
699*cf5a6c84SAndroid Build Coastguard Worker   }
700*cf5a6c84SAndroid Build Coastguard Worker   (num >= 0) ? xprintf("Selected partition %d\n",num+1):
701*cf5a6c84SAndroid Build Coastguard Worker     xprintf("No partition is defined yet!\n");
702*cf5a6c84SAndroid Build Coastguard Worker   return num;
703*cf5a6c84SAndroid Build Coastguard Worker }
704*cf5a6c84SAndroid Build Coastguard Worker 
705*cf5a6c84SAndroid Build Coastguard Worker /* a try at autodetecting an empty partition table entry,
706*cf5a6c84SAndroid Build Coastguard Worker  * if multiple options then get USER's choce.
707*cf5a6c84SAndroid Build Coastguard Worker  */
get_free_partition(int max)708*cf5a6c84SAndroid Build Coastguard Worker static int get_free_partition(int max)
709*cf5a6c84SAndroid Build Coastguard Worker {
710*cf5a6c84SAndroid Build Coastguard Worker   int num = -1, i = 0;
711*cf5a6c84SAndroid Build Coastguard Worker 
712*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < max; i++) {
713*cf5a6c84SAndroid Build Coastguard Worker     if (is_partition_clear(partitions[i].part)) {
714*cf5a6c84SAndroid Build Coastguard Worker       if (num >= 0)
715*cf5a6c84SAndroid Build Coastguard Worker         return ask_partition(4)-1;
716*cf5a6c84SAndroid Build Coastguard Worker       num = i;
717*cf5a6c84SAndroid Build Coastguard Worker     }
718*cf5a6c84SAndroid Build Coastguard Worker   }
719*cf5a6c84SAndroid Build Coastguard Worker   (num >= 0) ? xprintf("Selected partition %d\n",num+1):
720*cf5a6c84SAndroid Build Coastguard Worker     xprintf("All primary partitions have been defined already!\n");
721*cf5a6c84SAndroid Build Coastguard Worker   return num;
722*cf5a6c84SAndroid Build Coastguard Worker }
723*cf5a6c84SAndroid Build Coastguard Worker 
724*cf5a6c84SAndroid Build Coastguard Worker //taking user input for partition start/end sectors/cyinders
ask_value(char * mesg,sector_t left,sector_t right,sector_t defalt)725*cf5a6c84SAndroid Build Coastguard Worker static uint32_t ask_value(char *mesg, sector_t left, sector_t right, sector_t defalt)
726*cf5a6c84SAndroid Build Coastguard Worker {
727*cf5a6c84SAndroid Build Coastguard Worker   char *str = toybuf;
728*cf5a6c84SAndroid Build Coastguard Worker   uint32_t val;
729*cf5a6c84SAndroid Build Coastguard Worker   int use_default = 1;
730*cf5a6c84SAndroid Build Coastguard Worker 
731*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
732*cf5a6c84SAndroid Build Coastguard Worker     use_default = 1;
733*cf5a6c84SAndroid Build Coastguard Worker     do {
734*cf5a6c84SAndroid Build Coastguard Worker       xprintf("%s",mesg);
735*cf5a6c84SAndroid Build Coastguard Worker       fgets(str, 80, stdin);
736*cf5a6c84SAndroid Build Coastguard Worker     } while (!isdigit(*str) && (*str != '\n')
737*cf5a6c84SAndroid Build Coastguard Worker         && (*str != '-') && (*str != '+') && (!isblank(*str)));
738*cf5a6c84SAndroid Build Coastguard Worker     while (isblank(*str)) str++; //remove leading white spaces
739*cf5a6c84SAndroid Build Coastguard Worker     if (*str == '+' || *str == '-') {
740*cf5a6c84SAndroid Build Coastguard Worker       int minus = (*str == '-');
741*cf5a6c84SAndroid Build Coastguard Worker       int absolute = 0;
742*cf5a6c84SAndroid Build Coastguard Worker 
743*cf5a6c84SAndroid Build Coastguard Worker       val = atoi(str + 1);
744*cf5a6c84SAndroid Build Coastguard Worker       while (isdigit(*++str)) use_default = 0;
745*cf5a6c84SAndroid Build Coastguard Worker 
746*cf5a6c84SAndroid Build Coastguard Worker       switch (*str) {
747*cf5a6c84SAndroid Build Coastguard Worker         case 'c':
748*cf5a6c84SAndroid Build Coastguard Worker         case 'C':
749*cf5a6c84SAndroid Build Coastguard Worker           if (!disp_unit_cyl) val *= g_heads * g_sectors;
750*cf5a6c84SAndroid Build Coastguard Worker           break;
751*cf5a6c84SAndroid Build Coastguard Worker         case 'K':
752*cf5a6c84SAndroid Build Coastguard Worker           absolute = ONE_K;
753*cf5a6c84SAndroid Build Coastguard Worker           break;
754*cf5a6c84SAndroid Build Coastguard Worker         case 'k':
755*cf5a6c84SAndroid Build Coastguard Worker           absolute = 1000;
756*cf5a6c84SAndroid Build Coastguard Worker           break;
757*cf5a6c84SAndroid Build Coastguard Worker         case 'm':
758*cf5a6c84SAndroid Build Coastguard Worker         case 'M':
759*cf5a6c84SAndroid Build Coastguard Worker           absolute = 1000000;
760*cf5a6c84SAndroid Build Coastguard Worker           break;
761*cf5a6c84SAndroid Build Coastguard Worker         case 'g':
762*cf5a6c84SAndroid Build Coastguard Worker         case 'G':
763*cf5a6c84SAndroid Build Coastguard Worker           absolute = 1000000000;
764*cf5a6c84SAndroid Build Coastguard Worker           break;
765*cf5a6c84SAndroid Build Coastguard Worker         default:
766*cf5a6c84SAndroid Build Coastguard Worker           break;
767*cf5a6c84SAndroid Build Coastguard Worker       }
768*cf5a6c84SAndroid Build Coastguard Worker       if (absolute) {
769*cf5a6c84SAndroid Build Coastguard Worker         unsigned long long bytes = (unsigned long long) val * absolute;
770*cf5a6c84SAndroid Build Coastguard Worker         unsigned long unit = (disp_unit_cyl && (g_heads * g_sectors))? g_heads * g_sectors : 1;
771*cf5a6c84SAndroid Build Coastguard Worker 
772*cf5a6c84SAndroid Build Coastguard Worker         unit = unit * g_sect_size;
773*cf5a6c84SAndroid Build Coastguard Worker         bytes += unit/2; // rounding
774*cf5a6c84SAndroid Build Coastguard Worker         bytes /= unit;
775*cf5a6c84SAndroid Build Coastguard Worker         val = bytes;
776*cf5a6c84SAndroid Build Coastguard Worker       }
777*cf5a6c84SAndroid Build Coastguard Worker       if (minus)
778*cf5a6c84SAndroid Build Coastguard Worker         val = -val;
779*cf5a6c84SAndroid Build Coastguard Worker       val += left;
780*cf5a6c84SAndroid Build Coastguard Worker     } else {
781*cf5a6c84SAndroid Build Coastguard Worker       val = atoi(str);
782*cf5a6c84SAndroid Build Coastguard Worker       while (isdigit(*str)) {
783*cf5a6c84SAndroid Build Coastguard Worker         str++;
784*cf5a6c84SAndroid Build Coastguard Worker         use_default = 0;
785*cf5a6c84SAndroid Build Coastguard Worker       }
786*cf5a6c84SAndroid Build Coastguard Worker     }
787*cf5a6c84SAndroid Build Coastguard Worker     if(use_default) {
788*cf5a6c84SAndroid Build Coastguard Worker       val = defalt;
789*cf5a6c84SAndroid Build Coastguard Worker       xprintf("Using default value %lld\n", defalt);
790*cf5a6c84SAndroid Build Coastguard Worker     }
791*cf5a6c84SAndroid Build Coastguard Worker     if (val >= left && val <= right) return val;
792*cf5a6c84SAndroid Build Coastguard Worker     else xprintf("Value out of range\n");
793*cf5a6c84SAndroid Build Coastguard Worker   }
794*cf5a6c84SAndroid Build Coastguard Worker }
795*cf5a6c84SAndroid Build Coastguard Worker 
796*cf5a6c84SAndroid Build Coastguard Worker //validating if the start given falls in a limit or not
validate(int start_index,sector_t * begin,sector_t * end,sector_t start,int asked)797*cf5a6c84SAndroid Build Coastguard Worker static int validate(int start_index, sector_t* begin,sector_t* end, sector_t start
798*cf5a6c84SAndroid Build Coastguard Worker     , int asked)
799*cf5a6c84SAndroid Build Coastguard Worker {
800*cf5a6c84SAndroid Build Coastguard Worker   int i, valid = 0;
801*cf5a6c84SAndroid Build Coastguard Worker   for (i = start_index; i < num_parts; i++) {
802*cf5a6c84SAndroid Build Coastguard Worker     if (start >= begin[i] && start <= end[i]) {
803*cf5a6c84SAndroid Build Coastguard Worker       if (asked) xprintf("Sector %lld is already allocated\n",start);
804*cf5a6c84SAndroid Build Coastguard Worker       valid = 0;
805*cf5a6c84SAndroid Build Coastguard Worker       break;
806*cf5a6c84SAndroid Build Coastguard Worker     } else valid = 1;
807*cf5a6c84SAndroid Build Coastguard Worker   }
808*cf5a6c84SAndroid Build Coastguard Worker   return valid;
809*cf5a6c84SAndroid Build Coastguard Worker }
810*cf5a6c84SAndroid Build Coastguard Worker 
811*cf5a6c84SAndroid Build Coastguard Worker //get the start sector/cylinder of a new partition
ask_start_sector(int idx,sector_t * begin,sector_t * end,int ext_idx)812*cf5a6c84SAndroid Build Coastguard Worker static sector_t ask_start_sector(int idx, sector_t* begin, sector_t* end, int ext_idx)
813*cf5a6c84SAndroid Build Coastguard Worker {
814*cf5a6c84SAndroid Build Coastguard Worker   sector_t start, limit, temp = 0, start_cyl, limit_cyl, offset = 1;
815*cf5a6c84SAndroid Build Coastguard Worker   char mesg[256];
816*cf5a6c84SAndroid Build Coastguard Worker   int i, asked = 0, valid = 0, start_index = 0;
817*cf5a6c84SAndroid Build Coastguard Worker 
818*cf5a6c84SAndroid Build Coastguard Worker   if (dos_flag) offset = g_sectors;
819*cf5a6c84SAndroid Build Coastguard Worker   start = offset;
820*cf5a6c84SAndroid Build Coastguard Worker   if (disp_unit_cyl) limit = (sector_t)g_sectors * g_heads * g_cylinders - 1;
821*cf5a6c84SAndroid Build Coastguard Worker   else limit = total_number_sectors - 1;
822*cf5a6c84SAndroid Build Coastguard Worker 
823*cf5a6c84SAndroid Build Coastguard Worker   if (disp_unit_cyl) //make the begin of every partition to cylnder boundary
824*cf5a6c84SAndroid Build Coastguard Worker     for (i = 0; i < num_parts; i++)
825*cf5a6c84SAndroid Build Coastguard Worker       begin[i] = (begin[i]/(g_heads* g_sectors)) * (g_heads* g_sectors);
826*cf5a6c84SAndroid Build Coastguard Worker 
827*cf5a6c84SAndroid Build Coastguard Worker   if (idx >= 4) {
828*cf5a6c84SAndroid Build Coastguard Worker     if (!begin[ext_idx] && extended_offset) begin[ext_idx] = extended_offset;
829*cf5a6c84SAndroid Build Coastguard Worker     start = begin[ext_idx] + offset;
830*cf5a6c84SAndroid Build Coastguard Worker     limit = end[ext_idx];
831*cf5a6c84SAndroid Build Coastguard Worker     start_index = 4;
832*cf5a6c84SAndroid Build Coastguard Worker   }
833*cf5a6c84SAndroid Build Coastguard Worker   do {
834*cf5a6c84SAndroid Build Coastguard Worker     if (asked) valid = validate(start_index, begin, end, start, asked);
835*cf5a6c84SAndroid Build Coastguard Worker     if (valid) break;
836*cf5a6c84SAndroid Build Coastguard Worker 
837*cf5a6c84SAndroid Build Coastguard Worker     do {
838*cf5a6c84SAndroid Build Coastguard Worker       for (i = start_index; i < num_parts; i++)
839*cf5a6c84SAndroid Build Coastguard Worker         if (start >= begin[i] && start <= end[i])
840*cf5a6c84SAndroid Build Coastguard Worker           start = end[i] + 1 + ((idx >= 4)? offset : 0);
841*cf5a6c84SAndroid Build Coastguard Worker     } while (!validate(start_index, begin, end, start, 0));
842*cf5a6c84SAndroid Build Coastguard Worker 
843*cf5a6c84SAndroid Build Coastguard Worker     start_cyl = start/(g_sectors * g_heads) + 1;
844*cf5a6c84SAndroid Build Coastguard Worker     limit_cyl = limit/(g_sectors * g_heads) + 1;
845*cf5a6c84SAndroid Build Coastguard Worker 
846*cf5a6c84SAndroid Build Coastguard Worker     if (start > limit) break;
847*cf5a6c84SAndroid Build Coastguard Worker     sprintf(mesg, "First %s (%lld - %lld, default %lld): ", disp_unit_cyl? "cylinder" : "sector",
848*cf5a6c84SAndroid Build Coastguard Worker         (long long int)(disp_unit_cyl? start_cyl : start),
849*cf5a6c84SAndroid Build Coastguard Worker         (long long int)(disp_unit_cyl? limit_cyl : limit),
850*cf5a6c84SAndroid Build Coastguard Worker         (long long int)(disp_unit_cyl? start_cyl : start));
851*cf5a6c84SAndroid Build Coastguard Worker     temp = ask_value(mesg, disp_unit_cyl? start_cyl : start,
852*cf5a6c84SAndroid Build Coastguard Worker         disp_unit_cyl? limit_cyl : limit, disp_unit_cyl? start_cyl : start);
853*cf5a6c84SAndroid Build Coastguard Worker     asked = 1;
854*cf5a6c84SAndroid Build Coastguard Worker 
855*cf5a6c84SAndroid Build Coastguard Worker     if (disp_unit_cyl) {
856*cf5a6c84SAndroid Build Coastguard Worker       // point to the cylinder start sector
857*cf5a6c84SAndroid Build Coastguard Worker       temp = (temp-1) * g_heads * g_sectors;
858*cf5a6c84SAndroid Build Coastguard Worker       if (temp < start) //the boundary is falling in the already used sectors.
859*cf5a6c84SAndroid Build Coastguard Worker         temp = start;
860*cf5a6c84SAndroid Build Coastguard Worker     }
861*cf5a6c84SAndroid Build Coastguard Worker     start = temp;
862*cf5a6c84SAndroid Build Coastguard Worker   } while (asked && !valid);
863*cf5a6c84SAndroid Build Coastguard Worker   return start;
864*cf5a6c84SAndroid Build Coastguard Worker }
865*cf5a6c84SAndroid Build Coastguard Worker 
866*cf5a6c84SAndroid Build Coastguard Worker //get the end sector/cylinder of a new partition
ask_end_sector(int idx,sector_t * begin,sector_t * end,int ext_idx,sector_t start_sec)867*cf5a6c84SAndroid Build Coastguard Worker static sector_t ask_end_sector(int idx, sector_t* begin, sector_t* end, int ext_idx, sector_t start_sec)
868*cf5a6c84SAndroid Build Coastguard Worker {
869*cf5a6c84SAndroid Build Coastguard Worker   sector_t limit, temp = 0, start_cyl, limit_cyl, start = start_sec;
870*cf5a6c84SAndroid Build Coastguard Worker   char mesg[256];
871*cf5a6c84SAndroid Build Coastguard Worker   int i;
872*cf5a6c84SAndroid Build Coastguard Worker 
873*cf5a6c84SAndroid Build Coastguard Worker   if (disp_unit_cyl) limit = (sector_t)g_sectors * g_heads * g_cylinders - 1;
874*cf5a6c84SAndroid Build Coastguard Worker   else limit = total_number_sectors - 1;
875*cf5a6c84SAndroid Build Coastguard Worker 
876*cf5a6c84SAndroid Build Coastguard Worker   if (disp_unit_cyl) //make the begin of every partition to cylnder boundary
877*cf5a6c84SAndroid Build Coastguard Worker     for (i = 0; i < num_parts; i++)
878*cf5a6c84SAndroid Build Coastguard Worker       begin[i] = (begin[i]/(g_heads* g_sectors)) * (g_heads* g_sectors);
879*cf5a6c84SAndroid Build Coastguard Worker 
880*cf5a6c84SAndroid Build Coastguard Worker   if (idx >= 4) limit = end[ext_idx];
881*cf5a6c84SAndroid Build Coastguard Worker 
882*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
883*cf5a6c84SAndroid Build Coastguard Worker     struct part_entry *pe = &partitions[i];
884*cf5a6c84SAndroid Build Coastguard Worker     if (start < pe->start_offset && limit >= pe->start_offset) limit = pe->start_offset - 1;
885*cf5a6c84SAndroid Build Coastguard Worker     if (start < begin[i] && limit >= begin[i]) limit = begin[i] - 1;
886*cf5a6c84SAndroid Build Coastguard Worker   }
887*cf5a6c84SAndroid Build Coastguard Worker 
888*cf5a6c84SAndroid Build Coastguard Worker   start_cyl = start/(g_sectors * g_heads) + 1;
889*cf5a6c84SAndroid Build Coastguard Worker   limit_cyl = limit/(g_sectors * g_heads) + 1;
890*cf5a6c84SAndroid Build Coastguard Worker   if (limit < start) { //the boundary is falling in the already used sectors.
891*cf5a6c84SAndroid Build Coastguard Worker     xprintf("No Free sectors available\n");
892*cf5a6c84SAndroid Build Coastguard Worker     return 0;
893*cf5a6c84SAndroid Build Coastguard Worker   }
894*cf5a6c84SAndroid Build Coastguard Worker   sprintf(mesg, "Last %s or +size or +sizeM or +sizeK (%lld - %lld, default %lld): ",
895*cf5a6c84SAndroid Build Coastguard Worker       disp_unit_cyl? "cylinder" : "sector",
896*cf5a6c84SAndroid Build Coastguard Worker       (long long int)(disp_unit_cyl? start_cyl : start),
897*cf5a6c84SAndroid Build Coastguard Worker       (long long int)(disp_unit_cyl? limit_cyl : limit),
898*cf5a6c84SAndroid Build Coastguard Worker       (long long int)(disp_unit_cyl? limit_cyl : limit));
899*cf5a6c84SAndroid Build Coastguard Worker   temp = ask_value(mesg, disp_unit_cyl? start_cyl : start,
900*cf5a6c84SAndroid Build Coastguard Worker       disp_unit_cyl? limit_cyl : limit, disp_unit_cyl? limit_cyl : limit);
901*cf5a6c84SAndroid Build Coastguard Worker 
902*cf5a6c84SAndroid Build Coastguard Worker   if (disp_unit_cyl) { // point to the cylinder start sector
903*cf5a6c84SAndroid Build Coastguard Worker     temp = temp * g_heads * g_sectors - 1;
904*cf5a6c84SAndroid Build Coastguard Worker     if (temp > limit) temp = limit;
905*cf5a6c84SAndroid Build Coastguard Worker   }
906*cf5a6c84SAndroid Build Coastguard Worker   if (temp < start) { //the boundary is falling in the already used sectors.
907*cf5a6c84SAndroid Build Coastguard Worker     xprintf("No Free sectors available\n");
908*cf5a6c84SAndroid Build Coastguard Worker     return 0;
909*cf5a6c84SAndroid Build Coastguard Worker   }
910*cf5a6c84SAndroid Build Coastguard Worker   return temp;
911*cf5a6c84SAndroid Build Coastguard Worker }
912*cf5a6c84SAndroid Build Coastguard Worker 
913*cf5a6c84SAndroid Build Coastguard Worker // add a new partition to the partition table
add_partition(int idx,int sys_id)914*cf5a6c84SAndroid Build Coastguard Worker static int add_partition(int idx, int sys_id)
915*cf5a6c84SAndroid Build Coastguard Worker {
916*cf5a6c84SAndroid Build Coastguard Worker   int i, ext_idx = -1;
917*cf5a6c84SAndroid Build Coastguard Worker   sector_t start, end, begin_sec[num_parts], end_sec[num_parts];
918*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe = &partitions[idx];
919*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p = pe->part;
920*cf5a6c84SAndroid Build Coastguard Worker 
921*cf5a6c84SAndroid Build Coastguard Worker   if (p && !is_partition_clear(p)) {
922*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u is already defined, delete it to re-add\n", idx+1);
923*cf5a6c84SAndroid Build Coastguard Worker     return 0;
924*cf5a6c84SAndroid Build Coastguard Worker   }
925*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
926*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
927*cf5a6c84SAndroid Build Coastguard Worker     p = pe->part;
928*cf5a6c84SAndroid Build Coastguard Worker     if (is_partition_clear(p)) {
929*cf5a6c84SAndroid Build Coastguard Worker       begin_sec[i] = 0xffffffff;
930*cf5a6c84SAndroid Build Coastguard Worker       end_sec[i] = 0;
931*cf5a6c84SAndroid Build Coastguard Worker     } else {
932*cf5a6c84SAndroid Build Coastguard Worker       begin_sec[i] = swap_le32toh(p->start4) + pe->start_offset;
933*cf5a6c84SAndroid Build Coastguard Worker       end_sec[i] = begin_sec[i] + swap_le32toh(p->size4) - 1;
934*cf5a6c84SAndroid Build Coastguard Worker     }
935*cf5a6c84SAndroid Build Coastguard Worker     if (IS_EXTENDED(p->sys_ind)) ext_idx = i;
936*cf5a6c84SAndroid Build Coastguard Worker   }
937*cf5a6c84SAndroid Build Coastguard Worker   start = ask_start_sector(idx, begin_sec, end_sec, ext_idx);
938*cf5a6c84SAndroid Build Coastguard Worker   end = ask_end_sector(idx, begin_sec, end_sec, ext_idx, start);
939*cf5a6c84SAndroid Build Coastguard Worker   if (!end) return 0;
940*cf5a6c84SAndroid Build Coastguard Worker   //Populate partition table entry  - 16 bytes
941*cf5a6c84SAndroid Build Coastguard Worker   pe = &partitions[idx];
942*cf5a6c84SAndroid Build Coastguard Worker   p = pe->part;
943*cf5a6c84SAndroid Build Coastguard Worker 
944*cf5a6c84SAndroid Build Coastguard Worker   if (idx > 4) {
945*cf5a6c84SAndroid Build Coastguard Worker     if (dos_flag) pe->start_offset = start - (sector_t)g_sectors;
946*cf5a6c84SAndroid Build Coastguard Worker     else pe->start_offset = start - 1;
947*cf5a6c84SAndroid Build Coastguard Worker     if (pe->start_offset == extended_offset) pe->start_offset++;
948*cf5a6c84SAndroid Build Coastguard Worker     if (!dos_flag) start++;
949*cf5a6c84SAndroid Build Coastguard Worker   }
950*cf5a6c84SAndroid Build Coastguard Worker 
951*cf5a6c84SAndroid Build Coastguard Worker   set_levalue(p->start4, start - pe->start_offset);
952*cf5a6c84SAndroid Build Coastguard Worker   set_levalue(p->size4, end - start + 1);
953*cf5a6c84SAndroid Build Coastguard Worker   set_hsc(p, start, end);
954*cf5a6c84SAndroid Build Coastguard Worker   p->boot_ind = 0;
955*cf5a6c84SAndroid Build Coastguard Worker   p->sys_ind = sys_id;
956*cf5a6c84SAndroid Build Coastguard Worker   pe->modified = 1;
957*cf5a6c84SAndroid Build Coastguard Worker 
958*cf5a6c84SAndroid Build Coastguard Worker   if (idx > 4) {
959*cf5a6c84SAndroid Build Coastguard Worker     p = partitions[idx-1].part + 1; //extended pointer for logical partitions
960*cf5a6c84SAndroid Build Coastguard Worker     set_levalue(p->start4, pe->start_offset - extended_offset);
961*cf5a6c84SAndroid Build Coastguard Worker     set_levalue(p->size4, end - start + 1 + (dos_flag? g_sectors: 1));
962*cf5a6c84SAndroid Build Coastguard Worker     set_hsc(p, pe->start_offset, end);
963*cf5a6c84SAndroid Build Coastguard Worker     p->boot_ind = 0;
964*cf5a6c84SAndroid Build Coastguard Worker     p->sys_ind = EXTENDED;
965*cf5a6c84SAndroid Build Coastguard Worker     partitions[idx-1].modified = 1;
966*cf5a6c84SAndroid Build Coastguard Worker   }
967*cf5a6c84SAndroid Build Coastguard Worker   if (IS_EXTENDED(sys_id)) {
968*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[4];
969*cf5a6c84SAndroid Build Coastguard Worker     pe->modified = 1;
970*cf5a6c84SAndroid Build Coastguard Worker     pe->sec_buffer = xzalloc(g_sect_size);
971*cf5a6c84SAndroid Build Coastguard Worker     pe->part = part_offset(pe->sec_buffer, 0);
972*cf5a6c84SAndroid Build Coastguard Worker     pe->start_offset = extended_offset = start;
973*cf5a6c84SAndroid Build Coastguard Worker     num_parts = 5;
974*cf5a6c84SAndroid Build Coastguard Worker   }
975*cf5a6c84SAndroid Build Coastguard Worker   return 1;
976*cf5a6c84SAndroid Build Coastguard Worker }
977*cf5a6c84SAndroid Build Coastguard Worker 
add_logical_partition(void)978*cf5a6c84SAndroid Build Coastguard Worker static void add_logical_partition(void)
979*cf5a6c84SAndroid Build Coastguard Worker {
980*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
981*cf5a6c84SAndroid Build Coastguard Worker   if (num_parts > 5 || !is_partition_clear(partitions[4].part)) {
982*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[num_parts];
983*cf5a6c84SAndroid Build Coastguard Worker     pe->modified = 1;
984*cf5a6c84SAndroid Build Coastguard Worker     pe->sec_buffer = xzalloc(g_sect_size);
985*cf5a6c84SAndroid Build Coastguard Worker     pe->part = part_offset(pe->sec_buffer, 0);
986*cf5a6c84SAndroid Build Coastguard Worker     pe->start_offset = 0;
987*cf5a6c84SAndroid Build Coastguard Worker     num_parts++;
988*cf5a6c84SAndroid Build Coastguard Worker     if (!add_partition(num_parts - 1, LINUX_NATIVE)) {
989*cf5a6c84SAndroid Build Coastguard Worker       num_parts--;
990*cf5a6c84SAndroid Build Coastguard Worker       free(pe->sec_buffer);
991*cf5a6c84SAndroid Build Coastguard Worker     }
992*cf5a6c84SAndroid Build Coastguard Worker   }
993*cf5a6c84SAndroid Build Coastguard Worker   else add_partition(num_parts -1, LINUX_NATIVE);
994*cf5a6c84SAndroid Build Coastguard Worker }
995*cf5a6c84SAndroid Build Coastguard Worker 
996*cf5a6c84SAndroid Build Coastguard Worker /* Add a new partiton to the partition table.
997*cf5a6c84SAndroid Build Coastguard Worker  * MAX partitions limit is taken to be 60, can be changed
998*cf5a6c84SAndroid Build Coastguard Worker  */
add_new_partition(void)999*cf5a6c84SAndroid Build Coastguard Worker static void add_new_partition(void)
1000*cf5a6c84SAndroid Build Coastguard Worker {
1001*cf5a6c84SAndroid Build Coastguard Worker   int choice, idx, i, free_part = 0;
1002*cf5a6c84SAndroid Build Coastguard Worker   char *msg = NULL;
1003*cf5a6c84SAndroid Build Coastguard Worker 
1004*cf5a6c84SAndroid Build Coastguard Worker   if (chs_warn()) return;
1005*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < 4; i++) if(is_partition_clear(partitions[i].part)) free_part++;
1006*cf5a6c84SAndroid Build Coastguard Worker 
1007*cf5a6c84SAndroid Build Coastguard Worker   if (!free_part && num_parts >= 60) {
1008*cf5a6c84SAndroid Build Coastguard Worker     xprintf("The maximum number of partitions has been created\n");
1009*cf5a6c84SAndroid Build Coastguard Worker     return;
1010*cf5a6c84SAndroid Build Coastguard Worker   }
1011*cf5a6c84SAndroid Build Coastguard Worker   if (!free_part) {
1012*cf5a6c84SAndroid Build Coastguard Worker     if (extended_offset) add_logical_partition();
1013*cf5a6c84SAndroid Build Coastguard Worker     else xprintf("You must delete some partition and add "
1014*cf5a6c84SAndroid Build Coastguard Worker           "an extended partition first\n");
1015*cf5a6c84SAndroid Build Coastguard Worker     return;
1016*cf5a6c84SAndroid Build Coastguard Worker   }
1017*cf5a6c84SAndroid Build Coastguard Worker 
1018*cf5a6c84SAndroid Build Coastguard Worker   msg = xmprintf("  %s\n  p  primary partition(1-4)\n",
1019*cf5a6c84SAndroid Build Coastguard Worker           extended_offset? "l  logical (5 or over)" : "e  extended");
1020*cf5a6c84SAndroid Build Coastguard Worker 
1021*cf5a6c84SAndroid Build Coastguard Worker   choice = 0x20 | read_input(msg, NULL);
1022*cf5a6c84SAndroid Build Coastguard Worker   free(msg);
1023*cf5a6c84SAndroid Build Coastguard Worker   if (choice == 'p') {
1024*cf5a6c84SAndroid Build Coastguard Worker     idx = get_free_partition(4);
1025*cf5a6c84SAndroid Build Coastguard Worker     if (idx >= 0) add_partition(idx, LINUX_NATIVE);
1026*cf5a6c84SAndroid Build Coastguard Worker     return;
1027*cf5a6c84SAndroid Build Coastguard Worker   }
1028*cf5a6c84SAndroid Build Coastguard Worker   if (choice =='l' && extended_offset) {
1029*cf5a6c84SAndroid Build Coastguard Worker     add_logical_partition();
1030*cf5a6c84SAndroid Build Coastguard Worker     return;
1031*cf5a6c84SAndroid Build Coastguard Worker   }
1032*cf5a6c84SAndroid Build Coastguard Worker   if (choice == 'e' && !extended_offset) {
1033*cf5a6c84SAndroid Build Coastguard Worker     idx = get_free_partition(4);
1034*cf5a6c84SAndroid Build Coastguard Worker     if (idx >= 0) add_partition(idx, EXTENDED);
1035*cf5a6c84SAndroid Build Coastguard Worker     return;
1036*cf5a6c84SAndroid Build Coastguard Worker   }
1037*cf5a6c84SAndroid Build Coastguard Worker }
1038*cf5a6c84SAndroid Build Coastguard Worker 
change_systype(void)1039*cf5a6c84SAndroid Build Coastguard Worker static void change_systype(void )
1040*cf5a6c84SAndroid Build Coastguard Worker {
1041*cf5a6c84SAndroid Build Coastguard Worker   int i, sys_id;
1042*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p;
1043*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
1044*cf5a6c84SAndroid Build Coastguard Worker 
1045*cf5a6c84SAndroid Build Coastguard Worker   i = ask_partition(num_parts);
1046*cf5a6c84SAndroid Build Coastguard Worker   pe = &partitions[i-1];
1047*cf5a6c84SAndroid Build Coastguard Worker   p = pe->part;
1048*cf5a6c84SAndroid Build Coastguard Worker   if (is_partition_clear(p)) {
1049*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %d doesn't exist yet!\n", i);
1050*cf5a6c84SAndroid Build Coastguard Worker     return;
1051*cf5a6c84SAndroid Build Coastguard Worker   }
1052*cf5a6c84SAndroid Build Coastguard Worker   sys_id = read_hex("Hex code (L to list codes): ");
1053*cf5a6c84SAndroid Build Coastguard Worker   if ((IS_EXTENDED(p->sys_ind) && !IS_EXTENDED(sys_id)) ||
1054*cf5a6c84SAndroid Build Coastguard Worker       (!IS_EXTENDED(p->sys_ind) && IS_EXTENDED(sys_id))) {
1055*cf5a6c84SAndroid Build Coastguard Worker     xprintf("you can't change a  partition to an extended or vice-versa\n");
1056*cf5a6c84SAndroid Build Coastguard Worker     return;
1057*cf5a6c84SAndroid Build Coastguard Worker   }
1058*cf5a6c84SAndroid Build Coastguard Worker 
1059*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Changed system type of partition %u to %0x (%s)\n",i, sys_id, get_type(sys_id));
1060*cf5a6c84SAndroid Build Coastguard Worker   p->sys_ind = sys_id;
1061*cf5a6c84SAndroid Build Coastguard Worker   pe->modified = 1;
1062*cf5a6c84SAndroid Build Coastguard Worker }
1063*cf5a6c84SAndroid Build Coastguard Worker 
check(int n,unsigned h,unsigned s,unsigned c,sector_t start)1064*cf5a6c84SAndroid Build Coastguard Worker static void check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
1065*cf5a6c84SAndroid Build Coastguard Worker {
1066*cf5a6c84SAndroid Build Coastguard Worker   sector_t total, real_s, real_c;
1067*cf5a6c84SAndroid Build Coastguard Worker 
1068*cf5a6c84SAndroid Build Coastguard Worker   real_s = sector(s) - 1;
1069*cf5a6c84SAndroid Build Coastguard Worker   real_c = cylinder(s, c);
1070*cf5a6c84SAndroid Build Coastguard Worker   total = (real_c * g_sectors + real_s) * g_heads + h;
1071*cf5a6c84SAndroid Build Coastguard Worker   if (!total) xprintf("Partition %u contains sector 0\n", n);
1072*cf5a6c84SAndroid Build Coastguard Worker   if (h >= g_heads)
1073*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u: head %u greater than maximum %lu\n", n, h + 1, g_heads);
1074*cf5a6c84SAndroid Build Coastguard Worker   if (real_s >= g_sectors)
1075*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u: sector %u greater than maximum %lu\n", n, s, g_sectors);
1076*cf5a6c84SAndroid Build Coastguard Worker   if (real_c >= g_cylinders)
1077*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u: cylinder %lld greater than maximum %lu\n", n, real_c + 1, g_cylinders);
1078*cf5a6c84SAndroid Build Coastguard Worker   if (g_cylinders <= ONE_K && start != total)
1079*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u: previous sectors %lld disagrees with total %lld\n", n, start, total);
1080*cf5a6c84SAndroid Build Coastguard Worker }
1081*cf5a6c84SAndroid Build Coastguard Worker 
verify_table(void)1082*cf5a6c84SAndroid Build Coastguard Worker static void verify_table(void)
1083*cf5a6c84SAndroid Build Coastguard Worker {
1084*cf5a6c84SAndroid Build Coastguard Worker   int i, j, ext_idx = -1;
1085*cf5a6c84SAndroid Build Coastguard Worker   sector_t begin_sec[num_parts], end_sec[num_parts], total = 1;
1086*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
1087*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p;
1088*cf5a6c84SAndroid Build Coastguard Worker 
1089*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
1090*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
1091*cf5a6c84SAndroid Build Coastguard Worker     p = pe->part;
1092*cf5a6c84SAndroid Build Coastguard Worker     if (is_partition_clear(p) || IS_EXTENDED(p->sys_ind)) {
1093*cf5a6c84SAndroid Build Coastguard Worker       begin_sec[i] = 0xffffffff;
1094*cf5a6c84SAndroid Build Coastguard Worker       end_sec[i] = 0;
1095*cf5a6c84SAndroid Build Coastguard Worker     } else {
1096*cf5a6c84SAndroid Build Coastguard Worker       begin_sec[i] = swap_le32toh(p->start4) + pe->start_offset;
1097*cf5a6c84SAndroid Build Coastguard Worker       end_sec[i] = begin_sec[i] + swap_le32toh(p->size4) - 1;
1098*cf5a6c84SAndroid Build Coastguard Worker     }
1099*cf5a6c84SAndroid Build Coastguard Worker     if (IS_EXTENDED(p->sys_ind)) ext_idx = i;
1100*cf5a6c84SAndroid Build Coastguard Worker   }
1101*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
1102*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
1103*cf5a6c84SAndroid Build Coastguard Worker     p = pe->part;
1104*cf5a6c84SAndroid Build Coastguard Worker     if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
1105*cf5a6c84SAndroid Build Coastguard Worker       consistency_check(p, i);
1106*cf5a6c84SAndroid Build Coastguard Worker       if ((swap_le32toh(p->start4) + pe->start_offset) < begin_sec[i])
1107*cf5a6c84SAndroid Build Coastguard Worker         xprintf("Warning: bad start-of-data in partition %u\n", i + 1);
1108*cf5a6c84SAndroid Build Coastguard Worker       check(i + 1, p->end_head, p->end_sector, p->end_cyl, end_sec[i]);
1109*cf5a6c84SAndroid Build Coastguard Worker       total += end_sec[i] + 1 - begin_sec[i];
1110*cf5a6c84SAndroid Build Coastguard Worker       for (j = 0; j < i; j++) {
1111*cf5a6c84SAndroid Build Coastguard Worker         if ((begin_sec[i] >= begin_sec[j] && begin_sec[i] <= end_sec[j])
1112*cf5a6c84SAndroid Build Coastguard Worker             || ((end_sec[i] <= end_sec[j] && end_sec[i] >= begin_sec[j]))) {
1113*cf5a6c84SAndroid Build Coastguard Worker           xprintf("Warning: partition %u overlaps partition %u\n", j + 1, i + 1);
1114*cf5a6c84SAndroid Build Coastguard Worker           total += begin_sec[i] >= begin_sec[j] ? begin_sec[i] : begin_sec[j];
1115*cf5a6c84SAndroid Build Coastguard Worker           total -= end_sec[i] <= end_sec[j] ? end_sec[i] : end_sec[j];
1116*cf5a6c84SAndroid Build Coastguard Worker         }
1117*cf5a6c84SAndroid Build Coastguard Worker       }
1118*cf5a6c84SAndroid Build Coastguard Worker     }
1119*cf5a6c84SAndroid Build Coastguard Worker   }
1120*cf5a6c84SAndroid Build Coastguard Worker   if (extended_offset) {
1121*cf5a6c84SAndroid Build Coastguard Worker     struct part_entry *pex = &partitions[ext_idx];
1122*cf5a6c84SAndroid Build Coastguard Worker     sector_t e_last = swap_le32toh(pex->part->start4) +
1123*cf5a6c84SAndroid Build Coastguard Worker       swap_le32toh(pex->part->size4) - 1;
1124*cf5a6c84SAndroid Build Coastguard Worker 
1125*cf5a6c84SAndroid Build Coastguard Worker     for (i = 4; i < num_parts; i++) {
1126*cf5a6c84SAndroid Build Coastguard Worker       total++;
1127*cf5a6c84SAndroid Build Coastguard Worker       p = partitions[i].part;
1128*cf5a6c84SAndroid Build Coastguard Worker       if (!p->sys_ind) {
1129*cf5a6c84SAndroid Build Coastguard Worker         if (i != 4 || i + 1 < num_parts)
1130*cf5a6c84SAndroid Build Coastguard Worker           xprintf("Warning: partition %u is empty\n", i + 1);
1131*cf5a6c84SAndroid Build Coastguard Worker       } else if (begin_sec[i] < extended_offset || end_sec[i] > e_last)
1132*cf5a6c84SAndroid Build Coastguard Worker         xprintf("Logical partition %u not entirely in partition %u\n", i + 1, ext_idx + 1);
1133*cf5a6c84SAndroid Build Coastguard Worker     }
1134*cf5a6c84SAndroid Build Coastguard Worker   }
1135*cf5a6c84SAndroid Build Coastguard Worker   if (total > g_heads * g_sectors * g_cylinders)
1136*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Total allocated sectors %lld greater than the maximum "
1137*cf5a6c84SAndroid Build Coastguard Worker         "%lu\n", total, g_heads * g_sectors * g_cylinders);
1138*cf5a6c84SAndroid Build Coastguard Worker   else {
1139*cf5a6c84SAndroid Build Coastguard Worker     total = g_heads * g_sectors * g_cylinders - total;
1140*cf5a6c84SAndroid Build Coastguard Worker     if (total) xprintf("%lld unallocated sectors\n", total);
1141*cf5a6c84SAndroid Build Coastguard Worker   }
1142*cf5a6c84SAndroid Build Coastguard Worker }
1143*cf5a6c84SAndroid Build Coastguard Worker 
move_begning(int idx)1144*cf5a6c84SAndroid Build Coastguard Worker static void move_begning(int idx)
1145*cf5a6c84SAndroid Build Coastguard Worker {
1146*cf5a6c84SAndroid Build Coastguard Worker   sector_t start, num, new_start, end;
1147*cf5a6c84SAndroid Build Coastguard Worker   char mesg[256];
1148*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe = &partitions[idx];
1149*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p = pe->part;
1150*cf5a6c84SAndroid Build Coastguard Worker 
1151*cf5a6c84SAndroid Build Coastguard Worker   if (chs_warn()) return;
1152*cf5a6c84SAndroid Build Coastguard Worker   start = swap_le32toh(p->start4) + pe->start_offset;
1153*cf5a6c84SAndroid Build Coastguard Worker   num = swap_le32toh(p->size4);
1154*cf5a6c84SAndroid Build Coastguard Worker   end = start + num -1;
1155*cf5a6c84SAndroid Build Coastguard Worker 
1156*cf5a6c84SAndroid Build Coastguard Worker   if (!num || IS_EXTENDED(p->sys_ind)) {
1157*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Partition %u doesn't have data area\n", idx+1);
1158*cf5a6c84SAndroid Build Coastguard Worker     return;
1159*cf5a6c84SAndroid Build Coastguard Worker   }
1160*cf5a6c84SAndroid Build Coastguard Worker   sprintf(mesg, "New beginning of data (0 - %lld, default %lld): ",
1161*cf5a6c84SAndroid Build Coastguard Worker       (long long int)(end), (long long int)(start));
1162*cf5a6c84SAndroid Build Coastguard Worker   new_start = ask_value(mesg, 0, end, start);
1163*cf5a6c84SAndroid Build Coastguard Worker   if (new_start != start) {
1164*cf5a6c84SAndroid Build Coastguard Worker     set_levalue(p->start4, new_start - pe->start_offset);
1165*cf5a6c84SAndroid Build Coastguard Worker     set_levalue(p->size4, end - new_start +1);
1166*cf5a6c84SAndroid Build Coastguard Worker     if ((read_input("Recalculate C/H/S (Y/n): ", NULL) | 0x20) == 'y')
1167*cf5a6c84SAndroid Build Coastguard Worker       set_hsc(p, new_start, end);
1168*cf5a6c84SAndroid Build Coastguard Worker     pe->modified = 1;
1169*cf5a6c84SAndroid Build Coastguard Worker   }
1170*cf5a6c84SAndroid Build Coastguard Worker }
1171*cf5a6c84SAndroid Build Coastguard Worker 
print_raw_sectors()1172*cf5a6c84SAndroid Build Coastguard Worker static void print_raw_sectors()
1173*cf5a6c84SAndroid Build Coastguard Worker {
1174*cf5a6c84SAndroid Build Coastguard Worker   int i, j;
1175*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
1176*cf5a6c84SAndroid Build Coastguard Worker 
1177*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Device: %s\n", disk_device);
1178*cf5a6c84SAndroid Build Coastguard Worker   for (i = 3; i < num_parts; i++) {
1179*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
1180*cf5a6c84SAndroid Build Coastguard Worker     for (j = 0; j < g_sect_size; j++) {
1181*cf5a6c84SAndroid Build Coastguard Worker       if (!(j % 16)) xprintf("\n0x%03X: ",j);
1182*cf5a6c84SAndroid Build Coastguard Worker       xprintf("%02X ",pe->sec_buffer[j]);
1183*cf5a6c84SAndroid Build Coastguard Worker     }
1184*cf5a6c84SAndroid Build Coastguard Worker     xputc('\n');
1185*cf5a6c84SAndroid Build Coastguard Worker   }
1186*cf5a6c84SAndroid Build Coastguard Worker }
1187*cf5a6c84SAndroid Build Coastguard Worker 
print_partitions_list(int ext)1188*cf5a6c84SAndroid Build Coastguard Worker static void print_partitions_list(int ext)
1189*cf5a6c84SAndroid Build Coastguard Worker {
1190*cf5a6c84SAndroid Build Coastguard Worker   int i;
1191*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
1192*cf5a6c84SAndroid Build Coastguard Worker   struct partition *p;
1193*cf5a6c84SAndroid Build Coastguard Worker 
1194*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Disk %s: %lu heads, %lu sectors, %lu cylinders\n\n", disk_device, g_heads, g_sectors, g_cylinders);
1195*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
1196*cf5a6c84SAndroid Build Coastguard Worker 
1197*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
1198*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
1199*cf5a6c84SAndroid Build Coastguard Worker     p = pe->part;
1200*cf5a6c84SAndroid Build Coastguard Worker     if (p) {
1201*cf5a6c84SAndroid Build Coastguard Worker       if (ext && (i >= 4)) p = pe->part + 1;
1202*cf5a6c84SAndroid Build Coastguard Worker       if(ext && i < 4 && !IS_EXTENDED(p->sys_ind)) continue;
1203*cf5a6c84SAndroid Build Coastguard Worker 
1204*cf5a6c84SAndroid Build Coastguard Worker       xprintf("%2u %02x%4u%4u%5u%4u%4u%5u%11u%11u %02x\n",
1205*cf5a6c84SAndroid Build Coastguard Worker           i+1, p->boot_ind, p->head,
1206*cf5a6c84SAndroid Build Coastguard Worker           sector(p->sector), cylinder(p->sector, p->cyl),
1207*cf5a6c84SAndroid Build Coastguard Worker           p->end_head,
1208*cf5a6c84SAndroid Build Coastguard Worker           sector(p->end_sector), cylinder(p->end_sector, p->end_cyl),
1209*cf5a6c84SAndroid Build Coastguard Worker           swap_le32toh(p->start4),
1210*cf5a6c84SAndroid Build Coastguard Worker           swap_le32toh(p->size4),
1211*cf5a6c84SAndroid Build Coastguard Worker           p->sys_ind);
1212*cf5a6c84SAndroid Build Coastguard Worker       if (p->sys_ind) consistency_check(p, i);
1213*cf5a6c84SAndroid Build Coastguard Worker     }
1214*cf5a6c84SAndroid Build Coastguard Worker   }
1215*cf5a6c84SAndroid Build Coastguard Worker }
1216*cf5a6c84SAndroid Build Coastguard Worker 
1217*cf5a6c84SAndroid Build Coastguard Worker //fix the partition table order to ascending
fix_order(void)1218*cf5a6c84SAndroid Build Coastguard Worker static void fix_order(void)
1219*cf5a6c84SAndroid Build Coastguard Worker {
1220*cf5a6c84SAndroid Build Coastguard Worker   sector_t first[num_parts], min;
1221*cf5a6c84SAndroid Build Coastguard Worker   int i, j, oj, ojj, sj, sjj;
1222*cf5a6c84SAndroid Build Coastguard Worker   struct part_entry *pe;
1223*cf5a6c84SAndroid Build Coastguard Worker   struct partition *px, *py, temp, *pj, *pjj, tmp;
1224*cf5a6c84SAndroid Build Coastguard Worker 
1225*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < num_parts; i++) {
1226*cf5a6c84SAndroid Build Coastguard Worker     pe = &partitions[i];
1227*cf5a6c84SAndroid Build Coastguard Worker     px = pe->part;
1228*cf5a6c84SAndroid Build Coastguard Worker     if (is_partition_clear(px)) first[i] = 0xffffffff;
1229*cf5a6c84SAndroid Build Coastguard Worker     else first[i] = swap_le32toh(px->start4) + pe->start_offset;
1230*cf5a6c84SAndroid Build Coastguard Worker   }
1231*cf5a6c84SAndroid Build Coastguard Worker 
1232*cf5a6c84SAndroid Build Coastguard Worker   if (!check_order()) {
1233*cf5a6c84SAndroid Build Coastguard Worker     xprintf("Ordering is already correct\n\n");
1234*cf5a6c84SAndroid Build Coastguard Worker     return;
1235*cf5a6c84SAndroid Build Coastguard Worker   }
1236*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; i < 4; i++) {
1237*cf5a6c84SAndroid Build Coastguard Worker     for (j = 0; j < 3; j++) {
1238*cf5a6c84SAndroid Build Coastguard Worker       if (first[j] > first[j+1]) {
1239*cf5a6c84SAndroid Build Coastguard Worker         py = partitions[j+1].part;
1240*cf5a6c84SAndroid Build Coastguard Worker         px = partitions[j].part;
1241*cf5a6c84SAndroid Build Coastguard Worker         memcpy(&temp, py, sizeof(struct partition));
1242*cf5a6c84SAndroid Build Coastguard Worker         memcpy(py, px, sizeof(struct partition));
1243*cf5a6c84SAndroid Build Coastguard Worker         memcpy(px, &temp, sizeof(struct partition));
1244*cf5a6c84SAndroid Build Coastguard Worker         min = first[j+1];
1245*cf5a6c84SAndroid Build Coastguard Worker         first[j+1] = first[j];
1246*cf5a6c84SAndroid Build Coastguard Worker         first[j] = min;
1247*cf5a6c84SAndroid Build Coastguard Worker         partitions[j].modified = 1;
1248*cf5a6c84SAndroid Build Coastguard Worker       }
1249*cf5a6c84SAndroid Build Coastguard Worker     }
1250*cf5a6c84SAndroid Build Coastguard Worker   }
1251*cf5a6c84SAndroid Build Coastguard Worker   for (i = 5; i < num_parts; i++) {
1252*cf5a6c84SAndroid Build Coastguard Worker     for (j = 5; j < num_parts - 1; j++) {
1253*cf5a6c84SAndroid Build Coastguard Worker       oj = partitions[j].start_offset;
1254*cf5a6c84SAndroid Build Coastguard Worker       ojj = partitions[j+1].start_offset;
1255*cf5a6c84SAndroid Build Coastguard Worker       if (oj > ojj) {
1256*cf5a6c84SAndroid Build Coastguard Worker         partitions[j].start_offset = ojj;
1257*cf5a6c84SAndroid Build Coastguard Worker         partitions[j+1].start_offset = oj;
1258*cf5a6c84SAndroid Build Coastguard Worker         pj = partitions[j].part;
1259*cf5a6c84SAndroid Build Coastguard Worker         set_levalue(pj->start4, swap_le32toh(pj->start4)+oj-ojj);
1260*cf5a6c84SAndroid Build Coastguard Worker         pjj = partitions[j+1].part;
1261*cf5a6c84SAndroid Build Coastguard Worker         set_levalue(pjj->start4, swap_le32toh(pjj->start4)+ojj-oj);
1262*cf5a6c84SAndroid Build Coastguard Worker         set_levalue((partitions[j-1].part+1)->start4, ojj-extended_offset);
1263*cf5a6c84SAndroid Build Coastguard Worker         set_levalue((partitions[j].part+1)->start4, oj-extended_offset);
1264*cf5a6c84SAndroid Build Coastguard Worker       }
1265*cf5a6c84SAndroid Build Coastguard Worker     }
1266*cf5a6c84SAndroid Build Coastguard Worker   }
1267*cf5a6c84SAndroid Build Coastguard Worker   for (i = 4; i < num_parts; i++) {
1268*cf5a6c84SAndroid Build Coastguard Worker     for (j = 4; j < num_parts - 1; j++) {
1269*cf5a6c84SAndroid Build Coastguard Worker       pj = partitions[j].part;
1270*cf5a6c84SAndroid Build Coastguard Worker       pjj = partitions[j+1].part;
1271*cf5a6c84SAndroid Build Coastguard Worker       sj = swap_le32toh(pj->start4);
1272*cf5a6c84SAndroid Build Coastguard Worker       sjj = swap_le32toh(pjj->start4);
1273*cf5a6c84SAndroid Build Coastguard Worker       oj = partitions[j].start_offset;
1274*cf5a6c84SAndroid Build Coastguard Worker       ojj = partitions[j+1].start_offset;
1275*cf5a6c84SAndroid Build Coastguard Worker       if (oj+sj > ojj+sjj) {
1276*cf5a6c84SAndroid Build Coastguard Worker         tmp = *pj;
1277*cf5a6c84SAndroid Build Coastguard Worker         *pj = *pjj;
1278*cf5a6c84SAndroid Build Coastguard Worker         *pjj = tmp;
1279*cf5a6c84SAndroid Build Coastguard Worker         set_levalue(pj->start4, ojj+sjj-oj);
1280*cf5a6c84SAndroid Build Coastguard Worker         set_levalue(pjj->start4, oj+sj-ojj);
1281*cf5a6c84SAndroid Build Coastguard Worker       }
1282*cf5a6c84SAndroid Build Coastguard Worker     }
1283*cf5a6c84SAndroid Build Coastguard Worker   }
1284*cf5a6c84SAndroid Build Coastguard Worker   // If anything changed
1285*cf5a6c84SAndroid Build Coastguard Worker   for (j = 4; j < num_parts; j++) partitions[j].modified = 1;
1286*cf5a6c84SAndroid Build Coastguard Worker   xprintf("Done!\n");
1287*cf5a6c84SAndroid Build Coastguard Worker }
1288*cf5a6c84SAndroid Build Coastguard Worker 
print_menu(void)1289*cf5a6c84SAndroid Build Coastguard Worker static void print_menu(void)
1290*cf5a6c84SAndroid Build Coastguard Worker {
1291*cf5a6c84SAndroid Build Coastguard Worker   xprintf("a\ttoggle a bootable flag\n"
1292*cf5a6c84SAndroid Build Coastguard Worker   "b\tedit bsd disklabel\n"
1293*cf5a6c84SAndroid Build Coastguard Worker   "c\ttoggle the dos compatibility flag\n"
1294*cf5a6c84SAndroid Build Coastguard Worker   "d\tdelete a partition\n"
1295*cf5a6c84SAndroid Build Coastguard Worker   "l\tlist known partition types\n"
1296*cf5a6c84SAndroid Build Coastguard Worker   "n\tadd a new partition\n"
1297*cf5a6c84SAndroid Build Coastguard Worker   "o\tcreate a new empty DOS partition table\n"
1298*cf5a6c84SAndroid Build Coastguard Worker   "p\tprint the partition table\n"
1299*cf5a6c84SAndroid Build Coastguard Worker   "q\tquit without saving changes\n"
1300*cf5a6c84SAndroid Build Coastguard Worker   "s\tcreate a new empty Sun disklabel\n"
1301*cf5a6c84SAndroid Build Coastguard Worker   "t\tchange a partition's system id\n"
1302*cf5a6c84SAndroid Build Coastguard Worker   "u\tchange display/entry units\n"
1303*cf5a6c84SAndroid Build Coastguard Worker   "v\tverify the partition table\n"
1304*cf5a6c84SAndroid Build Coastguard Worker   "w\twrite table to disk and exit\n"
1305*cf5a6c84SAndroid Build Coastguard Worker   "x\textra functionality (experts only)\n");
1306*cf5a6c84SAndroid Build Coastguard Worker }
1307*cf5a6c84SAndroid Build Coastguard Worker 
print_xmenu(void)1308*cf5a6c84SAndroid Build Coastguard Worker static void print_xmenu(void)
1309*cf5a6c84SAndroid Build Coastguard Worker {
1310*cf5a6c84SAndroid Build Coastguard Worker   xprintf("b\tmove beginning of data in a partition\n"
1311*cf5a6c84SAndroid Build Coastguard Worker   "c\tchange number of cylinders\n"
1312*cf5a6c84SAndroid Build Coastguard Worker   "d\tprint the raw data in the partition table\n"
1313*cf5a6c84SAndroid Build Coastguard Worker   "e\tlist extended partitions\n"
1314*cf5a6c84SAndroid Build Coastguard Worker   "f\tfix partition order\n"
1315*cf5a6c84SAndroid Build Coastguard Worker   "h\tchange number of heads\n"
1316*cf5a6c84SAndroid Build Coastguard Worker   "p\tprint the partition table\n"
1317*cf5a6c84SAndroid Build Coastguard Worker   "q\tquit without saving changes\n"
1318*cf5a6c84SAndroid Build Coastguard Worker   "r\treturn to main menu\n"
1319*cf5a6c84SAndroid Build Coastguard Worker   "s\tchange number of sectors/track\n"
1320*cf5a6c84SAndroid Build Coastguard Worker   "v\tverify the partition table\n"
1321*cf5a6c84SAndroid Build Coastguard Worker   "w\twrite table to disk and exit\n");
1322*cf5a6c84SAndroid Build Coastguard Worker }
1323*cf5a6c84SAndroid Build Coastguard Worker 
expert_menu(void)1324*cf5a6c84SAndroid Build Coastguard Worker static void expert_menu(void)
1325*cf5a6c84SAndroid Build Coastguard Worker {
1326*cf5a6c84SAndroid Build Coastguard Worker   int choice, idx;
1327*cf5a6c84SAndroid Build Coastguard Worker   sector_t value;
1328*cf5a6c84SAndroid Build Coastguard Worker   char mesg[256];
1329*cf5a6c84SAndroid Build Coastguard Worker 
1330*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
1331*cf5a6c84SAndroid Build Coastguard Worker     xputc('\n');
1332*cf5a6c84SAndroid Build Coastguard Worker     char *msg = "Expert Command ('m' for help): ";
1333*cf5a6c84SAndroid Build Coastguard Worker     choice = 0x20 | read_input(msg, NULL);
1334*cf5a6c84SAndroid Build Coastguard Worker     switch (choice) {
1335*cf5a6c84SAndroid Build Coastguard Worker       case 'b': //move data beginning in partition
1336*cf5a6c84SAndroid Build Coastguard Worker         idx = ask_partition(num_parts);
1337*cf5a6c84SAndroid Build Coastguard Worker         move_begning(idx - 1);
1338*cf5a6c84SAndroid Build Coastguard Worker         break;
1339*cf5a6c84SAndroid Build Coastguard Worker       case 'c': //change cylinders
1340*cf5a6c84SAndroid Build Coastguard Worker           sprintf(mesg, "Number of cylinders (1 - 1048576, default %lu): ", g_cylinders);
1341*cf5a6c84SAndroid Build Coastguard Worker           value = ask_value(mesg, 1, 1048576, g_cylinders);
1342*cf5a6c84SAndroid Build Coastguard Worker           g_cylinders = TT.cylinders = value;
1343*cf5a6c84SAndroid Build Coastguard Worker           toys.optflags |= FLAG_C;
1344*cf5a6c84SAndroid Build Coastguard Worker           if(g_cylinders > ONE_K)
1345*cf5a6c84SAndroid Build Coastguard Worker             xprintf("\nThe number of cylinders for this disk is set to %lu.\n"
1346*cf5a6c84SAndroid Build Coastguard Worker                 "There is nothing wrong with that, but this is larger than 1024,\n"
1347*cf5a6c84SAndroid Build Coastguard Worker                 "and could in certain setups cause problems.\n", g_cylinders);
1348*cf5a6c84SAndroid Build Coastguard Worker         break;
1349*cf5a6c84SAndroid Build Coastguard Worker       case 'd': //print raw data in part tables
1350*cf5a6c84SAndroid Build Coastguard Worker         print_raw_sectors();
1351*cf5a6c84SAndroid Build Coastguard Worker         break;
1352*cf5a6c84SAndroid Build Coastguard Worker       case 'e': //list extended partitions
1353*cf5a6c84SAndroid Build Coastguard Worker         print_partitions_list(1);
1354*cf5a6c84SAndroid Build Coastguard Worker         break;
1355*cf5a6c84SAndroid Build Coastguard Worker       case 'f': //fix part order
1356*cf5a6c84SAndroid Build Coastguard Worker         fix_order();
1357*cf5a6c84SAndroid Build Coastguard Worker         break;
1358*cf5a6c84SAndroid Build Coastguard Worker       case 'h': //change number of heads
1359*cf5a6c84SAndroid Build Coastguard Worker           sprintf(mesg, "Number of heads (1 - 256, default %lu): ", g_heads);
1360*cf5a6c84SAndroid Build Coastguard Worker           value = ask_value(mesg, 1, 256, g_heads);
1361*cf5a6c84SAndroid Build Coastguard Worker           g_heads = TT.heads = value;
1362*cf5a6c84SAndroid Build Coastguard Worker           toys.optflags |= FLAG_H;
1363*cf5a6c84SAndroid Build Coastguard Worker         break;
1364*cf5a6c84SAndroid Build Coastguard Worker       case 'p': //print partition table
1365*cf5a6c84SAndroid Build Coastguard Worker         print_partitions_list(0);
1366*cf5a6c84SAndroid Build Coastguard Worker         break;
1367*cf5a6c84SAndroid Build Coastguard Worker       case 'q':
1368*cf5a6c84SAndroid Build Coastguard Worker         free_bufs();
1369*cf5a6c84SAndroid Build Coastguard Worker         close(dev_fd);
1370*cf5a6c84SAndroid Build Coastguard Worker         xputc('\n');
1371*cf5a6c84SAndroid Build Coastguard Worker         exit(0);
1372*cf5a6c84SAndroid Build Coastguard Worker         break;
1373*cf5a6c84SAndroid Build Coastguard Worker       case 'r':
1374*cf5a6c84SAndroid Build Coastguard Worker         return;
1375*cf5a6c84SAndroid Build Coastguard Worker         break;
1376*cf5a6c84SAndroid Build Coastguard Worker       case 's': //change sector/track
1377*cf5a6c84SAndroid Build Coastguard Worker           sprintf(mesg, "Number of sectors (1 - 63, default %lu): ", g_sectors);
1378*cf5a6c84SAndroid Build Coastguard Worker           value = ask_value(mesg, 1, 63, g_sectors);
1379*cf5a6c84SAndroid Build Coastguard Worker           g_sectors = TT.sectors = value;
1380*cf5a6c84SAndroid Build Coastguard Worker           toys.optflags |= FLAG_H;
1381*cf5a6c84SAndroid Build Coastguard Worker         break;
1382*cf5a6c84SAndroid Build Coastguard Worker       case 'v':
1383*cf5a6c84SAndroid Build Coastguard Worker         verify_table();
1384*cf5a6c84SAndroid Build Coastguard Worker         break;
1385*cf5a6c84SAndroid Build Coastguard Worker       case 'w':
1386*cf5a6c84SAndroid Build Coastguard Worker         write_table();
1387*cf5a6c84SAndroid Build Coastguard Worker         toys.exitval = 0;
1388*cf5a6c84SAndroid Build Coastguard Worker         exit(0);
1389*cf5a6c84SAndroid Build Coastguard Worker         break;
1390*cf5a6c84SAndroid Build Coastguard Worker       case 'm':
1391*cf5a6c84SAndroid Build Coastguard Worker         print_xmenu();
1392*cf5a6c84SAndroid Build Coastguard Worker         break;
1393*cf5a6c84SAndroid Build Coastguard Worker       default:
1394*cf5a6c84SAndroid Build Coastguard Worker         xprintf("Unknown command '%c'\n",choice);
1395*cf5a6c84SAndroid Build Coastguard Worker         print_xmenu();
1396*cf5a6c84SAndroid Build Coastguard Worker         break;
1397*cf5a6c84SAndroid Build Coastguard Worker     }
1398*cf5a6c84SAndroid Build Coastguard Worker   } //while(1)
1399*cf5a6c84SAndroid Build Coastguard Worker }
1400*cf5a6c84SAndroid Build Coastguard Worker 
disk_proper(const char * device)1401*cf5a6c84SAndroid Build Coastguard Worker static int disk_proper(const char *device)
1402*cf5a6c84SAndroid Build Coastguard Worker {
1403*cf5a6c84SAndroid Build Coastguard Worker   unsigned length;
1404*cf5a6c84SAndroid Build Coastguard Worker   int fd = open(device, O_RDONLY);
1405*cf5a6c84SAndroid Build Coastguard Worker 
1406*cf5a6c84SAndroid Build Coastguard Worker   if (fd != -1) {
1407*cf5a6c84SAndroid Build Coastguard Worker     struct hd_geometry dev_geo;
1408*cf5a6c84SAndroid Build Coastguard Worker     dev_geo.heads = 0;
1409*cf5a6c84SAndroid Build Coastguard Worker     dev_geo.sectors = 0;
1410*cf5a6c84SAndroid Build Coastguard Worker     int err = ioctl(fd, HDIO_GETGEO, &dev_geo);
1411*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
1412*cf5a6c84SAndroid Build Coastguard Worker     if (!err) return (dev_geo.start == 0);
1413*cf5a6c84SAndroid Build Coastguard Worker   }
1414*cf5a6c84SAndroid Build Coastguard Worker   length = strlen(device);
1415*cf5a6c84SAndroid Build Coastguard Worker   if (length != 0 && isdigit(device[length - 1])) return 0;
1416*cf5a6c84SAndroid Build Coastguard Worker   return 1;
1417*cf5a6c84SAndroid Build Coastguard Worker }
1418*cf5a6c84SAndroid Build Coastguard Worker 
reset_entries()1419*cf5a6c84SAndroid Build Coastguard Worker static void reset_entries()
1420*cf5a6c84SAndroid Build Coastguard Worker {
1421*cf5a6c84SAndroid Build Coastguard Worker   int i;
1422*cf5a6c84SAndroid Build Coastguard Worker 
1423*cf5a6c84SAndroid Build Coastguard Worker   memset(MBRbuf, 0, sizeof(MBRbuf));
1424*cf5a6c84SAndroid Build Coastguard Worker   for (i = 4; i < num_parts; i++)
1425*cf5a6c84SAndroid Build Coastguard Worker     memset(&partitions[i], 0, sizeof(struct part_entry));
1426*cf5a6c84SAndroid Build Coastguard Worker }
1427*cf5a6c84SAndroid Build Coastguard Worker 
1428*cf5a6c84SAndroid Build Coastguard Worker //this will keep dev_fd = 3 always alive
move_fd()1429*cf5a6c84SAndroid Build Coastguard Worker static void move_fd()
1430*cf5a6c84SAndroid Build Coastguard Worker {
1431*cf5a6c84SAndroid Build Coastguard Worker   int fd = xopen("/dev/null", O_RDONLY);
1432*cf5a6c84SAndroid Build Coastguard Worker   if(fd != dev_fd) {
1433*cf5a6c84SAndroid Build Coastguard Worker     if(dup2(fd, dev_fd) != dev_fd) perror_exit("Can't dup2");
1434*cf5a6c84SAndroid Build Coastguard Worker     close(fd);
1435*cf5a6c84SAndroid Build Coastguard Worker   }
1436*cf5a6c84SAndroid Build Coastguard Worker }
1437*cf5a6c84SAndroid Build Coastguard Worker 
1438*cf5a6c84SAndroid Build Coastguard Worker /* Read proc/partitions and then print the details
1439*cf5a6c84SAndroid Build Coastguard Worker  * for partitions on each device
1440*cf5a6c84SAndroid Build Coastguard Worker  */
read_and_print_parts()1441*cf5a6c84SAndroid Build Coastguard Worker static void read_and_print_parts()
1442*cf5a6c84SAndroid Build Coastguard Worker {
1443*cf5a6c84SAndroid Build Coastguard Worker   unsigned int ma, mi, sz;
1444*cf5a6c84SAndroid Build Coastguard Worker   char *name = toybuf, *buffer = toybuf + ONE_K, *device = toybuf + 2048;
1445*cf5a6c84SAndroid Build Coastguard Worker   FILE* fp = xfopen("/proc/partitions", "r");
1446*cf5a6c84SAndroid Build Coastguard Worker 
1447*cf5a6c84SAndroid Build Coastguard Worker   while (fgets(buffer, ONE_K, fp)) {
1448*cf5a6c84SAndroid Build Coastguard Worker     reset_entries();
1449*cf5a6c84SAndroid Build Coastguard Worker     num_parts = 4;
1450*cf5a6c84SAndroid Build Coastguard Worker     memset(name, 0, sizeof(*name));
1451*cf5a6c84SAndroid Build Coastguard Worker     if (sscanf(buffer, " %u %u %u %[^\n ]", &ma, &mi, &sz, name) != 4)
1452*cf5a6c84SAndroid Build Coastguard Worker       continue;
1453*cf5a6c84SAndroid Build Coastguard Worker 
1454*cf5a6c84SAndroid Build Coastguard Worker     sprintf(device,"/dev/%s",name);
1455*cf5a6c84SAndroid Build Coastguard Worker     if (disk_proper(device)) {
1456*cf5a6c84SAndroid Build Coastguard Worker       if (read_mbr(device, 0)) continue;
1457*cf5a6c84SAndroid Build Coastguard Worker       print_mbr(1);
1458*cf5a6c84SAndroid Build Coastguard Worker       move_fd();
1459*cf5a6c84SAndroid Build Coastguard Worker     }
1460*cf5a6c84SAndroid Build Coastguard Worker   }
1461*cf5a6c84SAndroid Build Coastguard Worker   fclose(fp);
1462*cf5a6c84SAndroid Build Coastguard Worker }
1463*cf5a6c84SAndroid Build Coastguard Worker 
fdisk_main(void)1464*cf5a6c84SAndroid Build Coastguard Worker void fdisk_main(void)
1465*cf5a6c84SAndroid Build Coastguard Worker {
1466*cf5a6c84SAndroid Build Coastguard Worker   int choice, p;
1467*cf5a6c84SAndroid Build Coastguard Worker 
1468*cf5a6c84SAndroid Build Coastguard Worker   init_members();
1469*cf5a6c84SAndroid Build Coastguard Worker   move_fd();
1470*cf5a6c84SAndroid Build Coastguard Worker   if (TT.heads >= 256) TT.heads = 0;
1471*cf5a6c84SAndroid Build Coastguard Worker   if (TT.sectors >= 64) TT.sectors = 0;
1472*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(u)) disp_unit_cyl = 0;
1473*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(l)) {
1474*cf5a6c84SAndroid Build Coastguard Worker     if (!toys.optc) read_and_print_parts();
1475*cf5a6c84SAndroid Build Coastguard Worker     else {
1476*cf5a6c84SAndroid Build Coastguard Worker       while(*toys.optargs){
1477*cf5a6c84SAndroid Build Coastguard Worker         if (read_mbr(*toys.optargs, 0)) {
1478*cf5a6c84SAndroid Build Coastguard Worker           toys.optargs++;
1479*cf5a6c84SAndroid Build Coastguard Worker           continue;
1480*cf5a6c84SAndroid Build Coastguard Worker         }
1481*cf5a6c84SAndroid Build Coastguard Worker         print_mbr(1);
1482*cf5a6c84SAndroid Build Coastguard Worker         move_fd();
1483*cf5a6c84SAndroid Build Coastguard Worker         toys.optargs++;
1484*cf5a6c84SAndroid Build Coastguard Worker       }
1485*cf5a6c84SAndroid Build Coastguard Worker     }
1486*cf5a6c84SAndroid Build Coastguard Worker     toys.exitval = 0;
1487*cf5a6c84SAndroid Build Coastguard Worker     return;
1488*cf5a6c84SAndroid Build Coastguard Worker   } else {
1489*cf5a6c84SAndroid Build Coastguard Worker     if (toys.optc != 1) help_exit(0);
1490*cf5a6c84SAndroid Build Coastguard Worker     if (read_mbr(toys.optargs[0], 1)) return;
1491*cf5a6c84SAndroid Build Coastguard Worker     while (1) {
1492*cf5a6c84SAndroid Build Coastguard Worker       xputc('\n');
1493*cf5a6c84SAndroid Build Coastguard Worker       char *msg = "Command ('m' for help): ";
1494*cf5a6c84SAndroid Build Coastguard Worker       choice = 0x20 | read_input(msg, NULL);
1495*cf5a6c84SAndroid Build Coastguard Worker       switch (choice) {
1496*cf5a6c84SAndroid Build Coastguard Worker         case 'a':
1497*cf5a6c84SAndroid Build Coastguard Worker           p = ask_partition(num_parts);
1498*cf5a6c84SAndroid Build Coastguard Worker           toggle_active_flag(p - 1); //partition table index start from 0.
1499*cf5a6c84SAndroid Build Coastguard Worker           break;
1500*cf5a6c84SAndroid Build Coastguard Worker         case 'b':
1501*cf5a6c84SAndroid Build Coastguard Worker           break;
1502*cf5a6c84SAndroid Build Coastguard Worker         case 'c':
1503*cf5a6c84SAndroid Build Coastguard Worker           dos_flag = !dos_flag;
1504*cf5a6c84SAndroid Build Coastguard Worker           xprintf("Dos compatible flag is %s\n", dos_flag?"Set" : "Not set");
1505*cf5a6c84SAndroid Build Coastguard Worker           break;
1506*cf5a6c84SAndroid Build Coastguard Worker         case 'd':
1507*cf5a6c84SAndroid Build Coastguard Worker           p = get_non_free_partition(num_parts); //4 was here
1508*cf5a6c84SAndroid Build Coastguard Worker           if(p >= 0) delete_partition(p);
1509*cf5a6c84SAndroid Build Coastguard Worker           break;
1510*cf5a6c84SAndroid Build Coastguard Worker         case 'l':
1511*cf5a6c84SAndroid Build Coastguard Worker           list_types();
1512*cf5a6c84SAndroid Build Coastguard Worker           break;
1513*cf5a6c84SAndroid Build Coastguard Worker         case 'n': //add new partition
1514*cf5a6c84SAndroid Build Coastguard Worker           add_new_partition();
1515*cf5a6c84SAndroid Build Coastguard Worker           break;
1516*cf5a6c84SAndroid Build Coastguard Worker         case 'o':
1517*cf5a6c84SAndroid Build Coastguard Worker           create_empty_doslabel();
1518*cf5a6c84SAndroid Build Coastguard Worker           break;
1519*cf5a6c84SAndroid Build Coastguard Worker         case 'p':
1520*cf5a6c84SAndroid Build Coastguard Worker           print_mbr(0);
1521*cf5a6c84SAndroid Build Coastguard Worker           break;
1522*cf5a6c84SAndroid Build Coastguard Worker         case 'q':
1523*cf5a6c84SAndroid Build Coastguard Worker           free_bufs();
1524*cf5a6c84SAndroid Build Coastguard Worker           close(dev_fd);
1525*cf5a6c84SAndroid Build Coastguard Worker           xputc('\n');
1526*cf5a6c84SAndroid Build Coastguard Worker           exit(0);
1527*cf5a6c84SAndroid Build Coastguard Worker           break;
1528*cf5a6c84SAndroid Build Coastguard Worker         case 's':
1529*cf5a6c84SAndroid Build Coastguard Worker           break;
1530*cf5a6c84SAndroid Build Coastguard Worker         case 't':
1531*cf5a6c84SAndroid Build Coastguard Worker           change_systype();
1532*cf5a6c84SAndroid Build Coastguard Worker           break;
1533*cf5a6c84SAndroid Build Coastguard Worker         case 'u':
1534*cf5a6c84SAndroid Build Coastguard Worker           disp_unit_cyl = !disp_unit_cyl;
1535*cf5a6c84SAndroid Build Coastguard Worker           xprintf("Changing Display/Entry units to %s\n",disp_unit_cyl?"cylinders" : "sectors");
1536*cf5a6c84SAndroid Build Coastguard Worker           break;
1537*cf5a6c84SAndroid Build Coastguard Worker         case 'v':
1538*cf5a6c84SAndroid Build Coastguard Worker           verify_table();
1539*cf5a6c84SAndroid Build Coastguard Worker           break;
1540*cf5a6c84SAndroid Build Coastguard Worker         case 'w':
1541*cf5a6c84SAndroid Build Coastguard Worker           write_table();
1542*cf5a6c84SAndroid Build Coastguard Worker           toys.exitval = 0;
1543*cf5a6c84SAndroid Build Coastguard Worker           return;
1544*cf5a6c84SAndroid Build Coastguard Worker           break;
1545*cf5a6c84SAndroid Build Coastguard Worker         case 'x':
1546*cf5a6c84SAndroid Build Coastguard Worker           expert_menu();
1547*cf5a6c84SAndroid Build Coastguard Worker           break;
1548*cf5a6c84SAndroid Build Coastguard Worker         case 'm':
1549*cf5a6c84SAndroid Build Coastguard Worker           print_menu();
1550*cf5a6c84SAndroid Build Coastguard Worker           break;
1551*cf5a6c84SAndroid Build Coastguard Worker         default:
1552*cf5a6c84SAndroid Build Coastguard Worker           xprintf("%c: Unknown command\n",choice);
1553*cf5a6c84SAndroid Build Coastguard Worker           break;
1554*cf5a6c84SAndroid Build Coastguard Worker       }
1555*cf5a6c84SAndroid Build Coastguard Worker     } //while(1)
1556*cf5a6c84SAndroid Build Coastguard Worker   }
1557*cf5a6c84SAndroid Build Coastguard Worker }
1558