1433d6423SLionel Sambuc /* fdisk - partition a hard disk Author: Jakob Schripsema */
2433d6423SLionel Sambuc
3433d6423SLionel Sambuc /* Run this with:
4433d6423SLionel Sambuc *
5433d6423SLionel Sambuc * fdisk [-hheads] [-ssectors] [device]
6433d6423SLionel Sambuc *
7433d6423SLionel Sambuc * e.g.,
8433d6423SLionel Sambuc *
9433d6423SLionel Sambuc * fdisk (to get the default)
10433d6423SLionel Sambuc * fdisk -h4 -s17 /dev/hd0 (MINIX default)
11433d6423SLionel Sambuc * fdisk -h4 -s17 c: (DOS default)
12433d6423SLionel Sambuc * fdisk -h6 -s25 /dev/hd5 (second drive, probably RLL)
13433d6423SLionel Sambuc * fdisk junkfile (to experiment safely)
14433d6423SLionel Sambuc *
15433d6423SLionel Sambuc * The device is opened in read-only mode if the file permissions do not
16433d6423SLionel Sambuc * permit read-write mode, so it is convenient to use a login account with
17433d6423SLionel Sambuc * only read permission to look at the partition table safely.
18433d6423SLionel Sambuc *
19433d6423SLionel Sambuc * Compile with:
20433d6423SLionel Sambuc *
21433d6423SLionel Sambuc * cc -i -o fdisk fdisk.c (MINIX)
22433d6423SLionel Sambuc * cl -DDOS fdisk.c (DOS with MS C compiler)
23433d6423SLionel Sambuc *
24433d6423SLionel Sambuc * This was modified extensively by Bruce Evans 28 Dec 89.
25433d6423SLionel Sambuc * The new version has not been tried with DOS. The open modes are suspect
26433d6423SLionel Sambuc * (everyone should convert to use fcntl.h).
27433d6423SLionel Sambuc *
28433d6423SLionel Sambuc * Changed 18 Dec 92 by Kees J. Bot: Bootstrap code and geometry from device.
29433d6423SLionel Sambuc *
30433d6423SLionel Sambuc * modified 01 March 95 by asw: updated list of known partition types. Also
31433d6423SLionel Sambuc * changed display format slightly to allow for partition type names of
32433d6423SLionel Sambuc * up to 9 chars (previous format allowed for 7, but there were already
33433d6423SLionel Sambuc * some 8 char names in the list).
34433d6423SLionel Sambuc */
35433d6423SLionel Sambuc
36433d6423SLionel Sambuc #include <sys/types.h>
37433d6423SLionel Sambuc #include <machine/partition.h>
38433d6423SLionel Sambuc #include <minix/partition.h>
39433d6423SLionel Sambuc #include <sys/ioctl.h>
40433d6423SLionel Sambuc #include <sys/stat.h>
41433d6423SLionel Sambuc #include <fcntl.h>
42433d6423SLionel Sambuc #include <string.h>
43433d6423SLionel Sambuc #include <stdlib.h>
44433d6423SLionel Sambuc #include <unistd.h>
45433d6423SLionel Sambuc #include <stdio.h>
46433d6423SLionel Sambuc #include <errno.h>
47433d6423SLionel Sambuc
48433d6423SLionel Sambuc #ifdef DOS
49433d6423SLionel Sambuc #include <dos.h>
50433d6423SLionel Sambuc #define DEFAULT_DEV "c:"
51433d6423SLionel Sambuc #define LOAD_OPEN_MODE 0x8000
52433d6423SLionel Sambuc #define SAVE_CREAT_MODE 0644
53433d6423SLionel Sambuc #else
54433d6423SLionel Sambuc #define DEFAULT_DEV "/dev/hd0"
55433d6423SLionel Sambuc #define LOAD_OPEN_MODE 0
56433d6423SLionel Sambuc #define SAVE_CREAT_MODE 0644
57433d6423SLionel Sambuc #define UNIX /* for MINIX */
58433d6423SLionel Sambuc #endif
59433d6423SLionel Sambuc
60433d6423SLionel Sambuc /* Constants */
61433d6423SLionel Sambuc
62433d6423SLionel Sambuc #define DEFAULT_NHEAD 4 /* # heads */
63433d6423SLionel Sambuc #define DEFAULT_NSEC 17 /* sectors / track */
64433d6423SLionel Sambuc #define SECSIZE 512 /* sector size */
65433d6423SLionel Sambuc #define OK 0
66433d6423SLionel Sambuc #define ERR 1
67433d6423SLionel Sambuc
68433d6423SLionel Sambuc #define CYL_MASK 0xc0 /* mask to extract cyl bits from sec field */
69433d6423SLionel Sambuc #define CYL_SHIFT 2 /* shift to extract cyl bits from sec field */
70433d6423SLionel Sambuc #define SEC_MASK 0x3f /* mask to extract sec bits from sec field */
71433d6423SLionel Sambuc
72433d6423SLionel Sambuc /* Globals */
73433d6423SLionel Sambuc char rawsecbuf[SECSIZE + sizeof(long)];
74433d6423SLionel Sambuc char *secbuf;
75433d6423SLionel Sambuc int badbases;
76433d6423SLionel Sambuc int badsizes;
77433d6423SLionel Sambuc int badorders;
78433d6423SLionel Sambuc char *dev_name;
79433d6423SLionel Sambuc int nhead;
80433d6423SLionel Sambuc int nsec;
81433d6423SLionel Sambuc int ncyl = 1024;
82433d6423SLionel Sambuc int readonly;
83433d6423SLionel Sambuc int override= 0;
84433d6423SLionel Sambuc
85433d6423SLionel Sambuc int main(int argc, char *argv []);
86433d6423SLionel Sambuc void getgeom(void);
87433d6423SLionel Sambuc void getboot(char *buffer);
88433d6423SLionel Sambuc void putboot(char *buffer);
89433d6423SLionel Sambuc void load_from_file(void);
90433d6423SLionel Sambuc void save_to_file(void);
91433d6423SLionel Sambuc void dpl_partitions(int rawflag);
92433d6423SLionel Sambuc int chk_table(void);
93433d6423SLionel Sambuc void sec_to_hst(long logsec, unsigned char *hd, unsigned char *sec,
94433d6423SLionel Sambuc unsigned char *cyl);
95433d6423SLionel Sambuc void mark_partition(struct part_entry *pe);
96433d6423SLionel Sambuc void change_partition(struct part_entry *entry);
97433d6423SLionel Sambuc char get_a_char(void);
98433d6423SLionel Sambuc void print_menu(void);
99433d6423SLionel Sambuc void adj_base(struct part_entry *pe);
100433d6423SLionel Sambuc void adj_size(struct part_entry *pe);
101433d6423SLionel Sambuc struct part_entry *ask_partition(void);
102433d6423SLionel Sambuc void footnotes(void);
103433d6423SLionel Sambuc int get_an_int(char *prompt, int *intptr);
104433d6423SLionel Sambuc void list_part_types(void);
105433d6423SLionel Sambuc void mark_npartition(struct part_entry *pe);
106433d6423SLionel Sambuc int mygets(char *buf, int length);
107433d6423SLionel Sambuc char *systype(int type);
108433d6423SLionel Sambuc void toggle_active(struct part_entry *pe);
109433d6423SLionel Sambuc void usage(void);
110433d6423SLionel Sambuc
111433d6423SLionel Sambuc /* One featureful master bootstrap. */
112433d6423SLionel Sambuc char bootstrap[] = {
113433d6423SLionel Sambuc 0353,0001,0000,0061,0300,0216,0330,0216,0300,0372,0216,0320,0274,0000,0174,0373,
114433d6423SLionel Sambuc 0275,0276,0007,0211,0346,0126,0277,0000,0006,0271,0000,0001,0374,0363,0245,0352,
115433d6423SLionel Sambuc 0044,0006,0000,0000,0264,0002,0315,0026,0250,0010,0164,0033,0350,0071,0001,0174,
116433d6423SLionel Sambuc 0007,0060,0344,0315,0026,0242,0205,0007,0054,0060,0074,0012,0163,0363,0120,0350,
117433d6423SLionel Sambuc 0046,0001,0205,0007,0130,0353,0012,0240,0002,0006,0204,0300,0165,0003,0351,0147,
118433d6423SLionel Sambuc 0000,0230,0262,0005,0366,0362,0262,0200,0000,0302,0210,0340,0120,0350,0234,0000,
119433d6423SLionel Sambuc 0163,0003,0351,0147,0000,0130,0054,0001,0175,0003,0351,0141,0000,0276,0276,0175,
120433d6423SLionel Sambuc 0211,0357,0271,0040,0000,0363,0245,0200,0301,0004,0211,0356,0215,0174,0020,0070,
121433d6423SLionel Sambuc 0154,0004,0164,0016,0213,0135,0010,0053,0134,0010,0213,0135,0012,0033,0134,0012,
122433d6423SLionel Sambuc 0163,0014,0212,0044,0206,0144,0020,0210,0044,0106,0071,0376,0162,0364,0211,0376,
123433d6423SLionel Sambuc 0201,0376,0356,0007,0162,0326,0342,0322,0211,0356,0264,0020,0366,0344,0001,0306,
124433d6423SLionel Sambuc 0200,0174,0004,0001,0162,0026,0353,0021,0204,0322,0175,0041,0211,0356,0200,0174,
125433d6423SLionel Sambuc 0004,0000,0164,0013,0366,0004,0200,0164,0006,0350,0070,0000,0162,0053,0303,0203,
126433d6423SLionel Sambuc 0306,0020,0201,0376,0376,0007,0162,0346,0350,0215,0000,0211,0007,0376,0302,0204,
127433d6423SLionel Sambuc 0322,0174,0023,0315,0021,0321,0340,0321,0340,0200,0344,0003,0070,0342,0167,0355,
128433d6423SLionel Sambuc 0350,0011,0000,0162,0350,0303,0350,0003,0000,0162,0146,0303,0211,0356,0214,0134,
129433d6423SLionel Sambuc 0010,0214,0134,0012,0277,0003,0000,0122,0006,0127,0264,0010,0315,0023,0137,0007,
130433d6423SLionel Sambuc 0200,0341,0077,0376,0306,0210,0310,0366,0346,0211,0303,0213,0104,0010,0213,0124,
131433d6423SLionel Sambuc 0012,0367,0363,0222,0210,0325,0366,0361,0060,0322,0321,0352,0321,0352,0010,0342,
132433d6423SLionel Sambuc 0210,0321,0376,0301,0132,0210,0306,0273,0000,0174,0270,0001,0002,0315,0023,0163,
133433d6423SLionel Sambuc 0020,0200,0374,0200,0164,0011,0117,0174,0006,0060,0344,0315,0023,0163,0270,0371,
134433d6423SLionel Sambuc 0303,0201,0076,0376,0175,0125,0252,0165,0001,0303,0350,0013,0000,0243,0007,0353,
135433d6423SLionel Sambuc 0005,0350,0004,0000,0227,0007,0353,0376,0136,0255,0126,0211,0306,0254,0204,0300,
136433d6423SLionel Sambuc 0164,0011,0264,0016,0273,0001,0000,0315,0020,0353,0362,0303,0057,0144,0145,0166,
137433d6423SLionel Sambuc 0057,0150,0144,0077,0010,0000,0015,0012,0000,0116,0157,0156,0145,0040,0141,0143,
138433d6423SLionel Sambuc 0164,0151,0166,0145,0015,0012,0000,0122,0145,0141,0144,0040,0145,0162,0162,0157,
139433d6423SLionel Sambuc 0162,0040,0000,0116,0157,0164,0040,0142,0157,0157,0164,0141,0142,0154,0145,0040,
140433d6423SLionel Sambuc 0000,0000,
141433d6423SLionel Sambuc };
142433d6423SLionel Sambuc
main(int argc,char * argv[])143433d6423SLionel Sambuc int main(int argc, char *argv[])
144433d6423SLionel Sambuc {
145433d6423SLionel Sambuc int argn;
146433d6423SLionel Sambuc char *argp;
147433d6423SLionel Sambuc int ch;
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc /* Init */
150433d6423SLionel Sambuc
151433d6423SLionel Sambuc nhead = DEFAULT_NHEAD;
152433d6423SLionel Sambuc nsec = DEFAULT_NSEC;
153433d6423SLionel Sambuc for (argn = 1; argn < argc && (argp = argv[argn])[0] == '-'; ++argn) {
154433d6423SLionel Sambuc if (argp[1] == 'h')
155433d6423SLionel Sambuc nhead = atoi(argp + 2);
156433d6423SLionel Sambuc else
157433d6423SLionel Sambuc if (argp[1] == 's') nsec = atoi(argp + 2);
158433d6423SLionel Sambuc else
159433d6423SLionel Sambuc usage();
160433d6423SLionel Sambuc override= 1;
161433d6423SLionel Sambuc }
162433d6423SLionel Sambuc
163433d6423SLionel Sambuc if (argn == argc)
164433d6423SLionel Sambuc dev_name = DEFAULT_DEV;
165433d6423SLionel Sambuc else if (argn == argc - 1)
166433d6423SLionel Sambuc dev_name = argv[argn];
167433d6423SLionel Sambuc else
168433d6423SLionel Sambuc usage();
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc /* Align the sector buffer in such a way that the partition table is at
171433d6423SLionel Sambuc * a mod 4 offset in memory. Some weird people add alignment checks to
172433d6423SLionel Sambuc * their Minix!
173433d6423SLionel Sambuc */
174433d6423SLionel Sambuc secbuf = rawsecbuf;
175433d6423SLionel Sambuc while ((long)(secbuf + PART_TABLE_OFF) % sizeof(long) != 0) secbuf++;
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc getgeom();
178433d6423SLionel Sambuc getboot(secbuf);
179433d6423SLionel Sambuc chk_table();
180433d6423SLionel Sambuc
181433d6423SLionel Sambuc do {
182433d6423SLionel Sambuc putchar('\n');
183433d6423SLionel Sambuc dpl_partitions(0);
184433d6423SLionel Sambuc printf(
185433d6423SLionel Sambuc "\n(Enter 'h' for help. A null line will abort any operation) ");
186433d6423SLionel Sambuc ch = get_a_char();
187433d6423SLionel Sambuc putchar('\n');
188433d6423SLionel Sambuc switch (ch) {
189433d6423SLionel Sambuc case '+': footnotes(); break;
190433d6423SLionel Sambuc case 'a': toggle_active(ask_partition()); break;
191433d6423SLionel Sambuc case 'B': adj_base(ask_partition()); break;
192433d6423SLionel Sambuc case 'c': change_partition(ask_partition()); break;
193433d6423SLionel Sambuc case 'h': print_menu(); break;
194433d6423SLionel Sambuc case 'l': load_from_file(); break;
195433d6423SLionel Sambuc case 'm': mark_partition(ask_partition()); break;
196433d6423SLionel Sambuc case 'n': mark_npartition(ask_partition()); break;
197433d6423SLionel Sambuc case 'p': dpl_partitions(1); break;
198433d6423SLionel Sambuc case 0:
199433d6423SLionel Sambuc case 'q': exit(0);
200433d6423SLionel Sambuc case 'S': adj_size(ask_partition()); break;
201433d6423SLionel Sambuc case 's': save_to_file(); break;
202433d6423SLionel Sambuc case 't': list_part_types(); break;
203433d6423SLionel Sambuc case 'v':
204433d6423SLionel Sambuc printf("Partition table is %svalid\n",
205433d6423SLionel Sambuc chk_table() == OK ? "" : "in");
206433d6423SLionel Sambuc break;
207433d6423SLionel Sambuc case 'w':
208433d6423SLionel Sambuc if (readonly)
209433d6423SLionel Sambuc printf("Write disabled\n");
210433d6423SLionel Sambuc else if(chk_table() == OK) {
211433d6423SLionel Sambuc putboot(secbuf);
212433d6423SLionel Sambuc printf(
213433d6423SLionel Sambuc "Partition table has been updated and the file system synced.\n");
214433d6423SLionel Sambuc printf("Please reboot now.\n");
215433d6423SLionel Sambuc exit(0);
216433d6423SLionel Sambuc } else
217433d6423SLionel Sambuc printf("Not written\n");
218433d6423SLionel Sambuc break;
219433d6423SLionel Sambuc default: printf(" %c ????\n", ch); break;
220433d6423SLionel Sambuc }
221433d6423SLionel Sambuc }
222433d6423SLionel Sambuc while (1);
223433d6423SLionel Sambuc }
224433d6423SLionel Sambuc
225433d6423SLionel Sambuc
226433d6423SLionel Sambuc #ifdef UNIX
227433d6423SLionel Sambuc
getgeom(void)228433d6423SLionel Sambuc void getgeom(void)
229433d6423SLionel Sambuc {
230433d6423SLionel Sambuc struct part_geom geom;
231433d6423SLionel Sambuc int fd, r;
232433d6423SLionel Sambuc
233433d6423SLionel Sambuc if (override) return;
234433d6423SLionel Sambuc
235433d6423SLionel Sambuc if ((fd= open(dev_name, O_RDONLY)) < 0) return;
236433d6423SLionel Sambuc
237433d6423SLionel Sambuc r = ioctl(fd, DIOCGETP, &geom);
238433d6423SLionel Sambuc close(fd);
239433d6423SLionel Sambuc if (r < 0) return;
240433d6423SLionel Sambuc
241433d6423SLionel Sambuc nhead = geom.heads;
242433d6423SLionel Sambuc nsec = geom.sectors;
243433d6423SLionel Sambuc ncyl = geom.cylinders;
244433d6423SLionel Sambuc
245433d6423SLionel Sambuc printf("Geometry of %s: %dx%dx%d\n", dev_name, ncyl, nhead, nsec);
246433d6423SLionel Sambuc }
247433d6423SLionel Sambuc
248433d6423SLionel Sambuc static int devfd;
249433d6423SLionel Sambuc
getboot(char * buffer)250433d6423SLionel Sambuc void getboot(char *buffer)
251433d6423SLionel Sambuc {
252433d6423SLionel Sambuc devfd = open(dev_name, 2);
253433d6423SLionel Sambuc if (devfd < 0) {
254433d6423SLionel Sambuc printf("No write permission on %s\n", dev_name);
255433d6423SLionel Sambuc readonly = 1;
256433d6423SLionel Sambuc devfd = open(dev_name, 0);
257433d6423SLionel Sambuc }
258433d6423SLionel Sambuc if (devfd < 0) {
259433d6423SLionel Sambuc printf("Cannot open device %s\n", dev_name);
260433d6423SLionel Sambuc exit(1);
261433d6423SLionel Sambuc }
262433d6423SLionel Sambuc if (read(devfd, buffer, SECSIZE) != SECSIZE) {
263433d6423SLionel Sambuc printf("Cannot read boot sector\n");
264433d6423SLionel Sambuc exit(1);
265433d6423SLionel Sambuc }
266433d6423SLionel Sambuc if (* (unsigned short *) &buffer[510] != 0xAA55) {
267433d6423SLionel Sambuc printf("Invalid boot sector on %s.\n", dev_name);
268433d6423SLionel Sambuc printf("Partition table reset and boot code installed.\n");
269433d6423SLionel Sambuc memset(buffer, 0, 512);
270433d6423SLionel Sambuc memcpy(buffer, bootstrap, sizeof(bootstrap));
271433d6423SLionel Sambuc * (unsigned short *) &buffer[510] = 0xAA55;
272433d6423SLionel Sambuc }
273433d6423SLionel Sambuc }
274433d6423SLionel Sambuc
putboot(char * buffer)275433d6423SLionel Sambuc void putboot(char *buffer)
276433d6423SLionel Sambuc {
277433d6423SLionel Sambuc if (lseek(devfd, 0L, 0) < 0) {
278433d6423SLionel Sambuc printf("Seek error during write\n");
279433d6423SLionel Sambuc exit(1);
280433d6423SLionel Sambuc }
281433d6423SLionel Sambuc if (write(devfd, buffer, SECSIZE) != SECSIZE) {
282433d6423SLionel Sambuc printf("Write error\n");
283433d6423SLionel Sambuc exit(1);
284433d6423SLionel Sambuc }
285433d6423SLionel Sambuc sync();
286433d6423SLionel Sambuc }
287433d6423SLionel Sambuc
288433d6423SLionel Sambuc #endif
289433d6423SLionel Sambuc
290433d6423SLionel Sambuc
load_from_file(void)291433d6423SLionel Sambuc void load_from_file(void)
292433d6423SLionel Sambuc {
293433d6423SLionel Sambuc /* Load buffer from file */
294433d6423SLionel Sambuc
295433d6423SLionel Sambuc char file[80];
296433d6423SLionel Sambuc int fd;
297433d6423SLionel Sambuc
298433d6423SLionel Sambuc printf("Enter name of file to load from: ");
299433d6423SLionel Sambuc if (!mygets(file, (int) sizeof file)) return;
300433d6423SLionel Sambuc fd = open(file, LOAD_OPEN_MODE);
301433d6423SLionel Sambuc if (fd < 0) {
302433d6423SLionel Sambuc printf("Cannot open %s\n", file);
303433d6423SLionel Sambuc return;
304433d6423SLionel Sambuc }
305433d6423SLionel Sambuc if (read(fd, secbuf, SECSIZE) != SECSIZE || close(fd) != 0) {
306433d6423SLionel Sambuc printf("Read error\n");
307433d6423SLionel Sambuc exit(1);
308433d6423SLionel Sambuc }
309433d6423SLionel Sambuc printf("Loaded from %s OK\n", file);
310433d6423SLionel Sambuc chk_table();
311433d6423SLionel Sambuc }
312433d6423SLionel Sambuc
313433d6423SLionel Sambuc
save_to_file(void)314433d6423SLionel Sambuc void save_to_file(void)
315433d6423SLionel Sambuc {
316433d6423SLionel Sambuc /* Save to file */
317433d6423SLionel Sambuc
318433d6423SLionel Sambuc char file[80];
319433d6423SLionel Sambuc int fd;
320433d6423SLionel Sambuc
321433d6423SLionel Sambuc printf("Enter name of file to save to: ");
322433d6423SLionel Sambuc if (!mygets(file, (int) sizeof file)) return;
323433d6423SLionel Sambuc if(chk_table() != OK) printf("Saving anyway\n");
324433d6423SLionel Sambuc fd = creat(file, SAVE_CREAT_MODE);
325433d6423SLionel Sambuc #ifdef DOS
326433d6423SLionel Sambuc if (fd < 0) {
327433d6423SLionel Sambuc printf("Cannot creat %s\n", file);
328433d6423SLionel Sambuc return;
329433d6423SLionel Sambuc }
330433d6423SLionel Sambuc close(fd);
331433d6423SLionel Sambuc fd = open(file, 0x8001);
332433d6423SLionel Sambuc #endif
333433d6423SLionel Sambuc if (fd < 0)
334433d6423SLionel Sambuc printf("Cannot open %s\n", file);
335433d6423SLionel Sambuc else if (write(fd, secbuf, SECSIZE) != SECSIZE || close(fd) != 0)
336433d6423SLionel Sambuc printf("Write error\n");
337433d6423SLionel Sambuc else
338433d6423SLionel Sambuc printf("Saved to %s OK\n", file);
339433d6423SLionel Sambuc }
340433d6423SLionel Sambuc
341433d6423SLionel Sambuc
dpl_partitions(int rawflag)342433d6423SLionel Sambuc void dpl_partitions(int rawflag)
343433d6423SLionel Sambuc {
344433d6423SLionel Sambuc /* Display partition table */
345433d6423SLionel Sambuc
346433d6423SLionel Sambuc char active[5];
347433d6423SLionel Sambuc char basefootnote;
348433d6423SLionel Sambuc int cyl_mask;
349433d6423SLionel Sambuc int devnum;
350433d6423SLionel Sambuc char *format;
351433d6423SLionel Sambuc int i;
352433d6423SLionel Sambuc int i1;
353433d6423SLionel Sambuc char orderfootnote;
354433d6423SLionel Sambuc struct part_entry *pe;
355433d6423SLionel Sambuc struct part_entry *pe1;
356433d6423SLionel Sambuc int sec_mask;
357433d6423SLionel Sambuc char sizefootnote;
358433d6423SLionel Sambuc char type[10];
359433d6423SLionel Sambuc
360433d6423SLionel Sambuc badbases = 0;
361433d6423SLionel Sambuc badsizes = 0;
362433d6423SLionel Sambuc badorders = 0;
363433d6423SLionel Sambuc if (rawflag) {
364433d6423SLionel Sambuc cyl_mask = 0; /* no contribution of cyl to sec */
365433d6423SLionel Sambuc sec_mask = 0xff;
366433d6423SLionel Sambuc format =
367433d6423SLionel Sambuc "%2d %3d%c %4s %-9s x%02x %3d x%02x x%02x %3d x%02x %7ld%c%7ld %7ld%c\n";
368433d6423SLionel Sambuc } else {
369433d6423SLionel Sambuc cyl_mask = CYL_MASK;
370433d6423SLionel Sambuc sec_mask = SEC_MASK;
371433d6423SLionel Sambuc format =
372433d6423SLionel Sambuc "%2d %3d%c %4s %-9s %4d %3d %3d %4d %3d %3d %7ld%c%7ld %7ld%c\n";
373433d6423SLionel Sambuc }
374433d6423SLionel Sambuc printf(
375433d6423SLionel Sambuc " ----first---- -----last---- --------sectors-------\n"
376433d6423SLionel Sambuc );
377433d6423SLionel Sambuc printf(
378433d6423SLionel Sambuc "Num Sorted Act Type Cyl Head Sec Cyl Head Sec Base Last Size\n"
379433d6423SLionel Sambuc );
380433d6423SLionel Sambuc pe = (struct part_entry *) &secbuf[PART_TABLE_OFF];
381433d6423SLionel Sambuc for (i = 1; i <= NR_PARTITIONS; i++, pe++) {
382433d6423SLionel Sambuc if (rawflag) {
383433d6423SLionel Sambuc sprintf(active, "0x%02x", pe->bootind);
384433d6423SLionel Sambuc sprintf(type, "0x%02x", pe->sysind);
385433d6423SLionel Sambuc } else {
386433d6423SLionel Sambuc sprintf(active, "%s", pe->bootind == ACTIVE_FLAG ? "A " : "");
387433d6423SLionel Sambuc sprintf(type, "%s", systype(pe->sysind));
388433d6423SLionel Sambuc }
389433d6423SLionel Sambuc
390433d6423SLionel Sambuc /* Prepare warnings about confusing setups from old versions. */
391433d6423SLionel Sambuc basefootnote = orderfootnote = sizefootnote = ' ';
392433d6423SLionel Sambuc if (pe->sysind == MINIX_PART && pe->lowsec & 1) {
393433d6423SLionel Sambuc basefootnote = '+';
394433d6423SLionel Sambuc ++badbases;
395433d6423SLionel Sambuc }
396433d6423SLionel Sambuc if (pe->size & 1) {
397433d6423SLionel Sambuc sizefootnote = '-';
398433d6423SLionel Sambuc ++badsizes;
399433d6423SLionel Sambuc }
400433d6423SLionel Sambuc
401433d6423SLionel Sambuc /* Calculate the "device numbers" resulting from the misguided sorting
402433d6423SLionel Sambuc * in the wini drivers. The drivers use this conditional for
403433d6423SLionel Sambuc * swapping wn[j] > wn[j+1]:
404433d6423SLionel Sambuc *
405433d6423SLionel Sambuc * if ((wn[j].wn_low == 0 && wn[j+1].wn_low != 0) ||
406433d6423SLionel Sambuc * (wn[j].wn_low > wn[j+1].wn_low && wn[j+1].wn_low != 0)) {
407433d6423SLionel Sambuc *
408433d6423SLionel Sambuc * which simplifies to:
409433d6423SLionel Sambuc *
410433d6423SLionel Sambuc * if (wn[j+1].wn_low != 0 &&
411433d6423SLionel Sambuc * (wn[j].wn_low == 0 || wn[j].wn_low > wn[j+1].wn_low)) {
412433d6423SLionel Sambuc */
413433d6423SLionel Sambuc devnum = 1;
414433d6423SLionel Sambuc for (i1 = 1, pe1 = (struct part_entry *) &secbuf[PART_TABLE_OFF];
415433d6423SLionel Sambuc i1 <= NR_PARTITIONS; ++i1, ++pe1)
416433d6423SLionel Sambuc if ((pe1->lowsec == 0 && pe->lowsec == 0 && pe1 < pe) ||
417433d6423SLionel Sambuc (pe1->lowsec != 0 &&
418433d6423SLionel Sambuc (pe->lowsec == 0 || pe->lowsec > pe1->lowsec)))
419433d6423SLionel Sambuc ++devnum; /* pe1 contents < pe contents */
420433d6423SLionel Sambuc if (devnum != i) {
421433d6423SLionel Sambuc orderfootnote = '#';
422433d6423SLionel Sambuc ++badorders;
423433d6423SLionel Sambuc }
424433d6423SLionel Sambuc
425433d6423SLionel Sambuc printf(format,
426433d6423SLionel Sambuc i,
427433d6423SLionel Sambuc devnum,
428433d6423SLionel Sambuc orderfootnote,
429433d6423SLionel Sambuc active,
430433d6423SLionel Sambuc type,
431433d6423SLionel Sambuc pe->start_cyl + ((pe->start_sec & cyl_mask) << CYL_SHIFT),
432433d6423SLionel Sambuc pe->start_head,
433433d6423SLionel Sambuc pe->start_sec & sec_mask,
434433d6423SLionel Sambuc pe->last_cyl + ((pe->last_sec & cyl_mask) << CYL_SHIFT),
435433d6423SLionel Sambuc pe->last_head,
436433d6423SLionel Sambuc pe->last_sec & sec_mask,
437433d6423SLionel Sambuc pe->lowsec,
438433d6423SLionel Sambuc basefootnote,
439433d6423SLionel Sambuc pe->lowsec + (pe->size == 0 ? 0 : pe->size - 1),
440433d6423SLionel Sambuc pe->size,
441433d6423SLionel Sambuc sizefootnote);
442433d6423SLionel Sambuc }
443433d6423SLionel Sambuc }
444433d6423SLionel Sambuc
445433d6423SLionel Sambuc
chk_table(void)446433d6423SLionel Sambuc int chk_table(void)
447433d6423SLionel Sambuc {
448433d6423SLionel Sambuc /* Check partition table */
449433d6423SLionel Sambuc
450433d6423SLionel Sambuc int active;
451433d6423SLionel Sambuc unsigned char cylinder;
452433d6423SLionel Sambuc unsigned char head;
453433d6423SLionel Sambuc int i;
454433d6423SLionel Sambuc int i1;
455433d6423SLionel Sambuc int maxhead;
456433d6423SLionel Sambuc int maxsec;
457433d6423SLionel Sambuc struct part_entry *pe;
458433d6423SLionel Sambuc struct part_entry *pe1;
459433d6423SLionel Sambuc unsigned char sector;
460433d6423SLionel Sambuc int seenpart;
461433d6423SLionel Sambuc int status;
462433d6423SLionel Sambuc
463433d6423SLionel Sambuc active = 0;
464433d6423SLionel Sambuc maxhead = 0;
465433d6423SLionel Sambuc maxsec = 0;
466433d6423SLionel Sambuc pe = (struct part_entry *) &secbuf[PART_TABLE_OFF];
467433d6423SLionel Sambuc seenpart = 0;
468433d6423SLionel Sambuc status = OK;
469433d6423SLionel Sambuc for (i = 1; i <= NR_PARTITIONS; i++, ++pe) {
470433d6423SLionel Sambuc if (pe->bootind == ACTIVE_FLAG) active++;
471433d6423SLionel Sambuc sec_to_hst(pe->lowsec, &head, §or, &cylinder);
472433d6423SLionel Sambuc if (pe->size == 0 && pe->lowsec == 0) sector = 0;
473433d6423SLionel Sambuc if (head != pe->start_head || sector != pe->start_sec ||
474433d6423SLionel Sambuc cylinder != pe->start_cyl) {
475433d6423SLionel Sambuc printf("Inconsistent base in partition %d.\n", i);
476433d6423SLionel Sambuc printf("Suspect head and sector parameters.\n");
477433d6423SLionel Sambuc status = ERR;
478433d6423SLionel Sambuc }
479433d6423SLionel Sambuc if (pe->size != 0 || pe->lowsec != 0)
480433d6423SLionel Sambuc sec_to_hst(pe->lowsec + pe->size - 1, &head, §or, &cylinder);
481433d6423SLionel Sambuc if (head != pe->last_head || sector != pe->last_sec ||
482433d6423SLionel Sambuc cylinder != pe->last_cyl) {
483433d6423SLionel Sambuc printf("Inconsistent size in partition %d.\n", i);
484433d6423SLionel Sambuc printf("Suspect head and sector parameters.\n");
485433d6423SLionel Sambuc status = ERR;
486433d6423SLionel Sambuc }
487433d6423SLionel Sambuc if (pe->size == 0) continue;
488433d6423SLionel Sambuc seenpart = 1;
489433d6423SLionel Sambuc for (i1 = i + 1, pe1 = pe + 1; i1 <= NR_PARTITIONS; ++i1, ++pe1) {
490433d6423SLionel Sambuc if ((pe->lowsec >= pe1->lowsec &&
491433d6423SLionel Sambuc pe->lowsec < pe1->lowsec + pe1->size) ||
492433d6423SLionel Sambuc (pe->lowsec + pe->size - 1 >= pe1->lowsec &&
493433d6423SLionel Sambuc pe->lowsec + pe->size - 1 < pe1->lowsec + pe1->size))
494433d6423SLionel Sambuc {
495433d6423SLionel Sambuc printf("Overlap between partitions %d and %d\n",
496433d6423SLionel Sambuc i, i1);
497433d6423SLionel Sambuc status = ERR;
498433d6423SLionel Sambuc }
499433d6423SLionel Sambuc }
500433d6423SLionel Sambuc if (pe->lowsec + pe->size < pe->lowsec) {
501433d6423SLionel Sambuc printf("Overflow from preposterous size in partition %d.\n",
502433d6423SLionel Sambuc i);
503433d6423SLionel Sambuc status = ERR;
504433d6423SLionel Sambuc }
505433d6423SLionel Sambuc if (maxhead < pe->start_head) maxhead = pe->start_head;
506433d6423SLionel Sambuc if (maxhead < pe->last_head) maxhead = pe->last_head;
507433d6423SLionel Sambuc if (maxsec < (pe->start_sec & SEC_MASK))
508433d6423SLionel Sambuc maxsec = (pe->start_sec & SEC_MASK);
509433d6423SLionel Sambuc if (maxsec < (pe->last_sec & SEC_MASK))
510433d6423SLionel Sambuc maxsec = (pe->last_sec & SEC_MASK);
511433d6423SLionel Sambuc }
512433d6423SLionel Sambuc if (seenpart) {
513433d6423SLionel Sambuc if (maxhead + 1 != nhead || maxsec != nsec) {
514433d6423SLionel Sambuc printf(
515433d6423SLionel Sambuc "Disk appears to have mis-specified number of heads or sectors.\n");
516433d6423SLionel Sambuc printf("Try fdisk -h%d -s%d %s instead of\n",
517433d6423SLionel Sambuc maxhead + 1, maxsec, dev_name);
518433d6423SLionel Sambuc printf(" fdisk -h%d -s%d %s\n", nhead, nsec, dev_name);
519433d6423SLionel Sambuc seenpart = 0;
520433d6423SLionel Sambuc }
521433d6423SLionel Sambuc } else {
522433d6423SLionel Sambuc printf(
523433d6423SLionel Sambuc "Empty table - skipping test on number of heads and sectors.\n");
524433d6423SLionel Sambuc printf("Assuming %d heads and %d sectors.\n", nhead, nsec);
525433d6423SLionel Sambuc }
526433d6423SLionel Sambuc if (!seenpart) printf("Do not write the table if you are not sure!.\n");
527433d6423SLionel Sambuc if (active > 1) {
528433d6423SLionel Sambuc printf("%d active partitions\n", active);
529433d6423SLionel Sambuc status = ERR;
530433d6423SLionel Sambuc }
531433d6423SLionel Sambuc return(status);
532433d6423SLionel Sambuc }
533433d6423SLionel Sambuc
sec_to_hst(long logsec,unsigned char * hd,unsigned char * sec,unsigned char * cyl)534433d6423SLionel Sambuc void sec_to_hst(long logsec, unsigned char *hd, unsigned char *sec,
535433d6423SLionel Sambuc unsigned char *cyl)
536433d6423SLionel Sambuc {
537433d6423SLionel Sambuc /* Convert a logical sector number to head / sector / cylinder */
538433d6423SLionel Sambuc
539433d6423SLionel Sambuc int bigcyl;
540433d6423SLionel Sambuc
541433d6423SLionel Sambuc bigcyl = logsec / (nhead * nsec);
542433d6423SLionel Sambuc *sec = (logsec % nsec) + 1 + ((bigcyl >> CYL_SHIFT) & CYL_MASK);
543433d6423SLionel Sambuc *cyl = bigcyl;
544433d6423SLionel Sambuc *hd = (logsec % (nhead * nsec)) / nsec;
545433d6423SLionel Sambuc }
546433d6423SLionel Sambuc
mark_partition(struct part_entry * pe)547433d6423SLionel Sambuc void mark_partition(struct part_entry *pe)
548433d6423SLionel Sambuc {
549433d6423SLionel Sambuc /* Mark a partition as being of type MINIX. */
550433d6423SLionel Sambuc
551433d6423SLionel Sambuc if (pe != NULL) {
552433d6423SLionel Sambuc pe->sysind = MINIX_PART;
553433d6423SLionel Sambuc printf("Partition type is now MINIX\n");
554433d6423SLionel Sambuc }
555433d6423SLionel Sambuc }
556433d6423SLionel Sambuc
change_partition(struct part_entry * entry)557433d6423SLionel Sambuc void change_partition(struct part_entry *entry)
558433d6423SLionel Sambuc {
559433d6423SLionel Sambuc /* Get partition info : first & last cylinder */
560433d6423SLionel Sambuc
561433d6423SLionel Sambuc int first, last;
562433d6423SLionel Sambuc long low, high;
563433d6423SLionel Sambuc int ch;
564433d6423SLionel Sambuc
565433d6423SLionel Sambuc if (entry == NULL) return;
566433d6423SLionel Sambuc while (1) {
567433d6423SLionel Sambuc if (!get_an_int("\tEnter first cylinder (an integer >= 0): ", &first))
568433d6423SLionel Sambuc return;
569433d6423SLionel Sambuc if (first >= 0) break;
570433d6423SLionel Sambuc printf("\t\tThat looks like %d which is negative\n", first);
571433d6423SLionel Sambuc }
572433d6423SLionel Sambuc while (1) {
573433d6423SLionel Sambuc if (!get_an_int(
574433d6423SLionel Sambuc "\tEnter last cylinder (an integer >= the first cylinder): ", &last))
575433d6423SLionel Sambuc return;
576433d6423SLionel Sambuc if (last >= first) break;
577433d6423SLionel Sambuc printf("\t\tThat looks like %d which is too small\n", last);
578433d6423SLionel Sambuc }
579433d6423SLionel Sambuc if (first == 0 && last == 0) {
580433d6423SLionel Sambuc entry->bootind = 0;
581433d6423SLionel Sambuc entry->start_head = 0;
582433d6423SLionel Sambuc entry->start_sec = 0;
583433d6423SLionel Sambuc entry->start_cyl = 0;
584433d6423SLionel Sambuc entry->sysind = NO_PART;
585433d6423SLionel Sambuc entry->last_head = 0;
586433d6423SLionel Sambuc entry->last_sec = 0;
587433d6423SLionel Sambuc entry->last_cyl = 0;
588433d6423SLionel Sambuc entry->lowsec = 0;
589433d6423SLionel Sambuc entry->size = 0;
590433d6423SLionel Sambuc printf("Partition deleted\n");
591433d6423SLionel Sambuc return;
592433d6423SLionel Sambuc }
593433d6423SLionel Sambuc low = first & 0xffff;
594433d6423SLionel Sambuc low = low * nsec * nhead;
595433d6423SLionel Sambuc if (low == 0) low = 1; /* sec0 is master boot record */
596433d6423SLionel Sambuc high = last & 0xffff;
597433d6423SLionel Sambuc high = (high + 1) * nsec * nhead - 1;
598433d6423SLionel Sambuc entry->lowsec = low;
599433d6423SLionel Sambuc entry->size = high - low + 1;
600433d6423SLionel Sambuc if (entry->size & 1) {
601433d6423SLionel Sambuc /* Adjust size to even since Minix works with blocks of 2 sectors. */
602433d6423SLionel Sambuc --high;
603433d6423SLionel Sambuc --entry->size;
604433d6423SLionel Sambuc printf("Size reduced by 1 to make it even\n");
605433d6423SLionel Sambuc }
606433d6423SLionel Sambuc sec_to_hst(low, &entry->start_head, &entry->start_sec, &entry->start_cyl);
607433d6423SLionel Sambuc sec_to_hst(high, &entry->last_head, &entry->last_sec, &entry->last_cyl);
608*d0055759SDavid van Moolenbroek printf("Base of partition changed to %u, size changed to %u\n",
609433d6423SLionel Sambuc entry->lowsec, entry->size);
610433d6423SLionel Sambuc
611433d6423SLionel Sambuc /* Accept the MINIX partition type. Usually ignore foreign types, so this
612433d6423SLionel Sambuc * fdisk can be used on foreign partitions. Don't allow NO_PART, because
613433d6423SLionel Sambuc * many DOS fdisks crash on it.
614433d6423SLionel Sambuc */
615433d6423SLionel Sambuc if (entry->sysind == NO_PART) {
616433d6423SLionel Sambuc entry->sysind = MINIX_PART;
617433d6423SLionel Sambuc printf("Partition type changed from None to MINIX\n");
618433d6423SLionel Sambuc } else if (entry->sysind == MINIX_PART)
619433d6423SLionel Sambuc printf("Leaving partition type as MINIX\n");
620433d6423SLionel Sambuc else while (1) {
621433d6423SLionel Sambuc printf("\tChange partition type from %s to MINIX? (y/n) ",
622433d6423SLionel Sambuc systype(entry->sysind));
623433d6423SLionel Sambuc ch = get_a_char();
624433d6423SLionel Sambuc if (ch == 0 || ch == 'n') {
625433d6423SLionel Sambuc printf("Leaving partition type as %s\n",
626433d6423SLionel Sambuc systype(entry->sysind));
627433d6423SLionel Sambuc break;
628433d6423SLionel Sambuc } else if (ch == 'y') {
629433d6423SLionel Sambuc entry->sysind = MINIX_PART;
630433d6423SLionel Sambuc printf("Partition type changed from %s to MINIX\n",
631433d6423SLionel Sambuc systype(entry->sysind));
632433d6423SLionel Sambuc break;
633433d6423SLionel Sambuc }
634433d6423SLionel Sambuc }
635433d6423SLionel Sambuc
636433d6423SLionel Sambuc if (entry->bootind == ACTIVE_FLAG)
637433d6423SLionel Sambuc printf("Leaving partition active\n");
638433d6423SLionel Sambuc else while (1) {
639433d6423SLionel Sambuc printf("\tChange partition to active? (y/n) ");
640433d6423SLionel Sambuc ch = get_a_char();
641433d6423SLionel Sambuc if (ch == 0 || ch == 'n') {
642433d6423SLionel Sambuc printf("Leaving partition inactive\n");
643433d6423SLionel Sambuc break;
644433d6423SLionel Sambuc } else if (ch == 'y') {
645433d6423SLionel Sambuc toggle_active(entry);
646433d6423SLionel Sambuc break;
647433d6423SLionel Sambuc }
648433d6423SLionel Sambuc }
649433d6423SLionel Sambuc }
650433d6423SLionel Sambuc
get_a_char(void)651433d6423SLionel Sambuc char get_a_char(void)
652433d6423SLionel Sambuc {
653433d6423SLionel Sambuc /* Read 1 character and discard rest of line */
654433d6423SLionel Sambuc
655433d6423SLionel Sambuc char buf[80];
656433d6423SLionel Sambuc
657433d6423SLionel Sambuc if (!mygets(buf, (int) sizeof buf)) return(0);
658433d6423SLionel Sambuc return(*buf);
659433d6423SLionel Sambuc }
660433d6423SLionel Sambuc
print_menu(void)661433d6423SLionel Sambuc void print_menu(void)
662433d6423SLionel Sambuc {
663433d6423SLionel Sambuc printf("Type a command letter, then a carriage return:\n");
664433d6423SLionel Sambuc printf(" + - explain any footnotes (+, -, #)\n");
665433d6423SLionel Sambuc printf(" a - toggle an active flag\n");
666433d6423SLionel Sambuc printf(" B - adjust a base sector\n");
667433d6423SLionel Sambuc printf(" c - change a partition\n");
668433d6423SLionel Sambuc printf(" l - load boot block (including partition table) from a file\n");
669433d6423SLionel Sambuc printf(" m - mark a partition as a MINIX partition\n");
670433d6423SLionel Sambuc printf(" n - mark a partition as a non-MINIX partition\n");
671433d6423SLionel Sambuc printf(" p - print raw partition table\n");
672433d6423SLionel Sambuc printf(" q - quit without making any changes\n");
673433d6423SLionel Sambuc printf(" S - adjust a size (by changing the last sector)\n");
674433d6423SLionel Sambuc printf(" s - save boot block (including partition table) on a file\n");
675433d6423SLionel Sambuc printf(" t - print known partition types\n");
676433d6423SLionel Sambuc printf(" v - verify partition table\n");
677433d6423SLionel Sambuc if (readonly)
678433d6423SLionel Sambuc printf(" w - write (disabled)\n");
679433d6423SLionel Sambuc else
680433d6423SLionel Sambuc printf(" w - write changed partition table back to disk and exit\n");
681433d6423SLionel Sambuc }
682433d6423SLionel Sambuc
683433d6423SLionel Sambuc
684433d6423SLionel Sambuc /* Here are the DOS routines for reading and writing the boot sector. */
685433d6423SLionel Sambuc
686433d6423SLionel Sambuc #ifdef DOS
687433d6423SLionel Sambuc
688433d6423SLionel Sambuc union REGS regs;
689433d6423SLionel Sambuc struct SREGS sregs;
690433d6423SLionel Sambuc int drivenum;
691433d6423SLionel Sambuc
getboot(char * buffer)692433d6423SLionel Sambuc void getboot(char *buffer)
693433d6423SLionel Sambuc {
694433d6423SLionel Sambuc /* Read boot sector */
695433d6423SLionel Sambuc
696433d6423SLionel Sambuc segread(&sregs); /* get ds */
697433d6423SLionel Sambuc
698433d6423SLionel Sambuc if (dev_name[1] != ':') {
699433d6423SLionel Sambuc printf("Invalid drive %s\n", dev_name);
700433d6423SLionel Sambuc exit(1);
701433d6423SLionel Sambuc }
702433d6423SLionel Sambuc if (*dev_name >= 'a') *dev_name += 'A' - 'a';
703433d6423SLionel Sambuc drivenum = (*dev_name - 'C') & 0xff;
704433d6423SLionel Sambuc if (drivenum < 0 || drivenum > 7) {
705433d6423SLionel Sambuc printf("Funny drive number %d\n", drivenum);
706433d6423SLionel Sambuc exit(1);
707433d6423SLionel Sambuc }
708433d6423SLionel Sambuc regs.x.ax = 0x201; /* read 1 sectors */
709433d6423SLionel Sambuc regs.h.ch = 0; /* cylinder */
710433d6423SLionel Sambuc regs.h.cl = 1; /* first sector = 1 */
711433d6423SLionel Sambuc regs.h.dh = 0; /* head = 0 */
712433d6423SLionel Sambuc regs.h.dl = 0x80 + drivenum; /* drive = 0 */
713433d6423SLionel Sambuc sregs.es = sregs.ds; /* buffer address */
714433d6423SLionel Sambuc regs.x.bx = (int) buffer;
715433d6423SLionel Sambuc
716433d6423SLionel Sambuc int86x(0x13, ®s, ®s, &sregs);
717433d6423SLionel Sambuc if (regs.x.cflag) {
718433d6423SLionel Sambuc printf("Cannot read boot sector\n");
719433d6423SLionel Sambuc exit(1);
720433d6423SLionel Sambuc }
721433d6423SLionel Sambuc }
722433d6423SLionel Sambuc
723433d6423SLionel Sambuc
putboot(char * buffer)724433d6423SLionel Sambuc void putboot(char *buffer)
725433d6423SLionel Sambuc {
726433d6423SLionel Sambuc /* Write boot sector */
727433d6423SLionel Sambuc
728433d6423SLionel Sambuc regs.x.ax = 0x301; /* read 1 sectors */
729433d6423SLionel Sambuc regs.h.ch = 0; /* cylinder */
730433d6423SLionel Sambuc regs.h.cl = 1; /* first sector = 1 */
731433d6423SLionel Sambuc regs.h.dh = 0; /* head = 0 */
732433d6423SLionel Sambuc regs.h.dl = 0x80 + drivenum; /* drive = 0 */
733433d6423SLionel Sambuc sregs.es = sregs.ds; /* buffer address */
734433d6423SLionel Sambuc regs.x.bx = (int) buffer;
735433d6423SLionel Sambuc
736433d6423SLionel Sambuc int86x(0x13, ®s, ®s, &sregs);
737433d6423SLionel Sambuc if (regs.x.cflag) {
738433d6423SLionel Sambuc printf("Cannot write boot sector\n");
739433d6423SLionel Sambuc exit(1);
740433d6423SLionel Sambuc }
741433d6423SLionel Sambuc }
742433d6423SLionel Sambuc
743433d6423SLionel Sambuc #endif
744433d6423SLionel Sambuc
adj_base(struct part_entry * pe)745433d6423SLionel Sambuc void adj_base(struct part_entry *pe)
746433d6423SLionel Sambuc {
747433d6423SLionel Sambuc /* Adjust base sector of partition, usually to make it even. */
748433d6423SLionel Sambuc
749433d6423SLionel Sambuc int adj;
750433d6423SLionel Sambuc
751433d6423SLionel Sambuc if (pe == NULL) return;
752433d6423SLionel Sambuc while (1) {
753433d6423SLionel Sambuc
754433d6423SLionel Sambuc if (!get_an_int("\tEnter adjustment to base (an integer): ", &adj))
755433d6423SLionel Sambuc return;
756433d6423SLionel Sambuc if (pe->lowsec + adj < 1)
757433d6423SLionel Sambuc printf(
758*d0055759SDavid van Moolenbroek "\t\tThat would make the base %u and too small\n", pe->lowsec + adj);
759433d6423SLionel Sambuc else if (pe->size - adj < 1)
760433d6423SLionel Sambuc printf(
761*d0055759SDavid van Moolenbroek "\t\tThat would make the size %u and too small\n", pe->size - adj);
762433d6423SLionel Sambuc else
763433d6423SLionel Sambuc break;
764433d6423SLionel Sambuc }
765433d6423SLionel Sambuc pe->lowsec += adj;
766433d6423SLionel Sambuc pe->size -= adj;
767433d6423SLionel Sambuc sec_to_hst(pe->lowsec, &pe->start_head, &pe->start_sec, &pe->start_cyl);
768*d0055759SDavid van Moolenbroek printf("Base of partition adjusted to %u, size adjusted to %u\n",
769433d6423SLionel Sambuc pe->lowsec, pe->size);
770433d6423SLionel Sambuc }
771433d6423SLionel Sambuc
adj_size(struct part_entry * pe)772433d6423SLionel Sambuc void adj_size(struct part_entry *pe)
773433d6423SLionel Sambuc {
774433d6423SLionel Sambuc /* Adjust size of partition by reducing high sector. */
775433d6423SLionel Sambuc
776433d6423SLionel Sambuc int adj;
777433d6423SLionel Sambuc
778433d6423SLionel Sambuc if (pe == NULL) return;
779433d6423SLionel Sambuc while (1) {
780433d6423SLionel Sambuc if (!get_an_int("\tEnter adjustment to size (an integer): ", &adj))
781433d6423SLionel Sambuc return;
782433d6423SLionel Sambuc if (pe->size + adj >= 1) break;
783*d0055759SDavid van Moolenbroek printf("\t\tThat would make the size %u and too small \n",
784433d6423SLionel Sambuc pe->size + adj);
785433d6423SLionel Sambuc }
786433d6423SLionel Sambuc pe->size += adj;
787433d6423SLionel Sambuc sec_to_hst(pe->lowsec + pe->size - 1,
788433d6423SLionel Sambuc &pe->last_head, &pe->last_sec, &pe->last_cyl);
789*d0055759SDavid van Moolenbroek printf("Size of partition adjusted to %u\n", pe->size);
790433d6423SLionel Sambuc }
791433d6423SLionel Sambuc
ask_partition()792433d6423SLionel Sambuc struct part_entry *ask_partition()
793433d6423SLionel Sambuc {
794433d6423SLionel Sambuc /* Ask for a valid partition number and return its entry. */
795433d6423SLionel Sambuc
796433d6423SLionel Sambuc int num;
797433d6423SLionel Sambuc
798433d6423SLionel Sambuc while (1) {
799433d6423SLionel Sambuc
800433d6423SLionel Sambuc if (!get_an_int("Enter partition number (1 to 4): ", &num))
801433d6423SLionel Sambuc return(NULL);
802433d6423SLionel Sambuc if (num >= 1 && num <= NR_PARTITIONS) break;
803433d6423SLionel Sambuc printf("\tThat does not look like 1 to 4\n");
804433d6423SLionel Sambuc }
805433d6423SLionel Sambuc printf("Partition %d\n", num);
806433d6423SLionel Sambuc return((struct part_entry *) &secbuf[PART_TABLE_OFF] + (num - 1));
807433d6423SLionel Sambuc }
808433d6423SLionel Sambuc
footnotes(void)809433d6423SLionel Sambuc void footnotes(void)
810433d6423SLionel Sambuc {
811433d6423SLionel Sambuc /* Explain the footnotes. */
812433d6423SLionel Sambuc
813433d6423SLionel Sambuc if (badbases != 0) {
814433d6423SLionel Sambuc printf(
815433d6423SLionel Sambuc "+ The old Minix wini drivers (before V1.5) discarded odd base sectors.\n");
816433d6423SLionel Sambuc printf(
817433d6423SLionel Sambuc " This causes some old (Minix) file systems to be offset by 1 sector.\n");
818433d6423SLionel Sambuc printf(
819433d6423SLionel Sambuc " To use these with the new drivers, increase the base by 1 using 'B'.\n");
820433d6423SLionel Sambuc }
821433d6423SLionel Sambuc
822433d6423SLionel Sambuc if (badsizes != 0) {
823433d6423SLionel Sambuc if (badbases != 0) putchar('\n');
824433d6423SLionel Sambuc printf(
825433d6423SLionel Sambuc "- Minix cannot access the last sector on an odd-sized partition. This\n");
826433d6423SLionel Sambuc printf(
827433d6423SLionel Sambuc " causes trouble for programs like dosread. This program will by default\n");
828433d6423SLionel Sambuc printf(
829433d6423SLionel Sambuc " only create partitions with even sizes. If possible, the current odd\n");
830433d6423SLionel Sambuc printf(
831433d6423SLionel Sambuc " sizes should be decreased by 1 using 'S'. This is safe for all Minix\n");
832433d6423SLionel Sambuc printf(
833433d6423SLionel Sambuc " partitions, and may be safe for other partitions which are about to be\n");
834433d6423SLionel Sambuc printf(
835433d6423SLionel Sambuc " reformatted.\n");
836433d6423SLionel Sambuc }
837433d6423SLionel Sambuc
838433d6423SLionel Sambuc if (badorders!= 0 ) {
839433d6423SLionel Sambuc if (badbases != 0 || badsizes != 0) putchar('\n');
840433d6423SLionel Sambuc printf(
841433d6423SLionel Sambuc "# The partitions are in a funny order. This is normal if they were created\n");
842433d6423SLionel Sambuc printf(
843433d6423SLionel Sambuc " by DOS fdisks prior to DOS 3.3. The Minix wini drivers further confuse\n");
844433d6423SLionel Sambuc printf(
845433d6423SLionel Sambuc " the order by sorting the partitions on their base. Be careful if the\n");
846433d6423SLionel Sambuc printf(
847433d6423SLionel Sambuc " device numbers of unchanged partitions have changed.\n");
848433d6423SLionel Sambuc }
849433d6423SLionel Sambuc }
850433d6423SLionel Sambuc
get_an_int(char * prompt,int * intptr)851433d6423SLionel Sambuc int get_an_int(char *prompt, int *intptr)
852433d6423SLionel Sambuc {
853433d6423SLionel Sambuc /* Read an int from the start of line of stdin, discard rest of line. */
854433d6423SLionel Sambuc
855433d6423SLionel Sambuc char buf[80];
856433d6423SLionel Sambuc
857433d6423SLionel Sambuc while (1) {
858433d6423SLionel Sambuc printf("%s", prompt);
859433d6423SLionel Sambuc if (!mygets(buf, (int) sizeof buf)) return(0);
860433d6423SLionel Sambuc if ((sscanf(buf, "%d", intptr)) == 1) return(1);
861433d6423SLionel Sambuc printf("\t\tThat does not look like an integer\n");
862433d6423SLionel Sambuc }
863433d6423SLionel Sambuc }
864433d6423SLionel Sambuc
list_part_types(void)865433d6423SLionel Sambuc void list_part_types(void)
866433d6423SLionel Sambuc {
867433d6423SLionel Sambuc /* Print all known partition types. */
868433d6423SLionel Sambuc
869433d6423SLionel Sambuc int column;
870433d6423SLionel Sambuc int type;
871433d6423SLionel Sambuc
872433d6423SLionel Sambuc for (column = 0, type = 0; type < 0x100; ++type)
873433d6423SLionel Sambuc if (strcmp(systype(type), "Unknown") != 0) {
874433d6423SLionel Sambuc printf("0x%02x: %-9s", type, systype(type));
875433d6423SLionel Sambuc column += 16;
876433d6423SLionel Sambuc if (column < 80)
877433d6423SLionel Sambuc putchar(' ');
878433d6423SLionel Sambuc else {
879433d6423SLionel Sambuc putchar('\n');
880433d6423SLionel Sambuc column = 0;
881433d6423SLionel Sambuc }
882433d6423SLionel Sambuc }
883433d6423SLionel Sambuc if (column != 0) putchar('\n');
884433d6423SLionel Sambuc }
885433d6423SLionel Sambuc
mark_npartition(struct part_entry * pe)886433d6423SLionel Sambuc void mark_npartition(struct part_entry *pe)
887433d6423SLionel Sambuc {
888433d6423SLionel Sambuc /* Mark a partition with arbitrary type. */
889433d6423SLionel Sambuc
890433d6423SLionel Sambuc char buf[80];
891433d6423SLionel Sambuc unsigned type;
892433d6423SLionel Sambuc
893433d6423SLionel Sambuc if (pe == NULL) return;
894433d6423SLionel Sambuc printf("\nKnown partition types are:\n\n");
895433d6423SLionel Sambuc list_part_types();
896433d6423SLionel Sambuc while (1) {
897433d6423SLionel Sambuc printf("\nEnter partition type (in 2-digit hex): ");
898433d6423SLionel Sambuc if (!mygets(buf, (int) sizeof buf)) return;
899433d6423SLionel Sambuc if (sscanf(buf, "%x", &type) != 1)
900433d6423SLionel Sambuc printf("Invalid hex number\n");
901433d6423SLionel Sambuc else if (type >= 0x100)
902433d6423SLionel Sambuc printf("Hex number too large\n");
903433d6423SLionel Sambuc else
904433d6423SLionel Sambuc break;
905433d6423SLionel Sambuc }
906433d6423SLionel Sambuc pe->sysind = type;
907433d6423SLionel Sambuc printf("Partition type changed to 0x%02x (%s)\n", type, systype(type));
908433d6423SLionel Sambuc }
909433d6423SLionel Sambuc
mygets(char * buf,int length)910433d6423SLionel Sambuc int mygets(char *buf, int length)
911433d6423SLionel Sambuc {
912433d6423SLionel Sambuc /* Get a non-empty line of maximum length 'length'. */
913433d6423SLionel Sambuc
914433d6423SLionel Sambuc while (1) {
915433d6423SLionel Sambuc fflush(stdout);
916433d6423SLionel Sambuc if (fgets(buf, length, stdin) == NULL) {
917433d6423SLionel Sambuc putchar('\n');
918433d6423SLionel Sambuc return(0);
919433d6423SLionel Sambuc }
920433d6423SLionel Sambuc if (strrchr(buf, '\n') != NULL) *strrchr(buf, '\n') = 0;
921433d6423SLionel Sambuc if (*buf != 0) return(1);
922433d6423SLionel Sambuc printf("Use the EOF character to create a null line.\n");
923433d6423SLionel Sambuc printf("Otherwise, please type something before the newline: ");
924433d6423SLionel Sambuc }
925433d6423SLionel Sambuc }
926433d6423SLionel Sambuc
systype(int type)927433d6423SLionel Sambuc char *systype(int type)
928433d6423SLionel Sambuc {
929433d6423SLionel Sambuc /* Convert system indicator into system name. */
930433d6423SLionel Sambuc /* asw 01.03.95: added types based on info in kjb's part.c and output
931433d6423SLionel Sambuc * from Linux (1.0.8) fdisk. Note comments here, there are disagreements.
932433d6423SLionel Sambuc */
933433d6423SLionel Sambuc switch(type) {
934433d6423SLionel Sambuc case NO_PART:
935433d6423SLionel Sambuc return("None");
936433d6423SLionel Sambuc case 1: return("DOS-12");
937433d6423SLionel Sambuc case 2: return("XENIX");
938433d6423SLionel Sambuc case 3: return("XENIX usr");
939433d6423SLionel Sambuc case 4: return("DOS-16");
940433d6423SLionel Sambuc case 5: return("DOS-EXT");
941433d6423SLionel Sambuc case 6: return("DOS-BIG");
942433d6423SLionel Sambuc case 7: return("HPFS");
943433d6423SLionel Sambuc case 8: return("AIX");
944433d6423SLionel Sambuc case 9: return("COHERENT"); /* LINUX says AIX bootable */
945433d6423SLionel Sambuc case 0x0a: return("OS/2"); /* LINUX says OPUS */
946433d6423SLionel Sambuc case 0x10: return("OPUS");
947433d6423SLionel Sambuc case 0x40: return("VENIX286");
948433d6423SLionel Sambuc case 0x51: return("NOVELL?");
949433d6423SLionel Sambuc case 0x52: return("MICROPORT");
950433d6423SLionel Sambuc case 0x63: return("386/IX"); /*LINUX calls this GNU HURD */
951433d6423SLionel Sambuc case 0x64: return("NOVELL286");
952433d6423SLionel Sambuc case 0x65: return("NOVELL386");
953433d6423SLionel Sambuc case 0x75: return("PC/IX");
954433d6423SLionel Sambuc case 0x80: return("MINIX old");
955433d6423SLionel Sambuc case 0x81: return("MINIX");
956433d6423SLionel Sambuc case 0x82: return("LINUXswap");
957433d6423SLionel Sambuc case 0x83: return("LINUX");
958433d6423SLionel Sambuc case 0x93: return("AMOEBA");
959433d6423SLionel Sambuc case 0x94: return("AMOEBAbad");
960433d6423SLionel Sambuc case 0xa5: return("386BSD");
961433d6423SLionel Sambuc case 0xb7: return("BSDI");
962433d6423SLionel Sambuc case 0xb8: return("BSDIswap");
963433d6423SLionel Sambuc case 0xc7: return("Syrinx");
964433d6423SLionel Sambuc case 0xDB: return("CP/M");
965433d6423SLionel Sambuc case 0xe1: return("DOS acc");
966433d6423SLionel Sambuc case 0xe3: return("DOS r/o");
967433d6423SLionel Sambuc case 0xf2: return("DOS 2ary");
968433d6423SLionel Sambuc case 0xFF: return("Badblocks");
969433d6423SLionel Sambuc default: return("Unknown");
970433d6423SLionel Sambuc }
971433d6423SLionel Sambuc }
972433d6423SLionel Sambuc
toggle_active(struct part_entry * pe)973433d6423SLionel Sambuc void toggle_active(struct part_entry *pe)
974433d6423SLionel Sambuc {
975433d6423SLionel Sambuc /* Toggle active flag of a partition. */
976433d6423SLionel Sambuc
977433d6423SLionel Sambuc if (pe == NULL) return;
978433d6423SLionel Sambuc pe->bootind = (pe->bootind == ACTIVE_FLAG) ? 0 : ACTIVE_FLAG;
979433d6423SLionel Sambuc printf("Partition changed to %sactive\n", pe->bootind ? "" : "in");
980433d6423SLionel Sambuc }
981433d6423SLionel Sambuc
usage(void)982433d6423SLionel Sambuc void usage(void)
983433d6423SLionel Sambuc {
984433d6423SLionel Sambuc /* Print usage message and exit. */
985433d6423SLionel Sambuc
986433d6423SLionel Sambuc printf("Usage: fdisk [-hheads] [-ssectors] [device]\n");
987433d6423SLionel Sambuc exit(1);
988433d6423SLionel Sambuc }
989433d6423SLionel Sambuc
990