1 /* partition 1.13 - Make a partition table Author: Kees J. Bot
10 #include <minix/config.h>
11 #include <minix/const.h>
12 #include <minix/partition.h>
13 #include <minix/u64.h>
14 #include <machine/partition.h>
18 #include <sys/ioctl.h>
21 #define SECTOR_SIZE 512
23 #define arraysize(a) (sizeof(a)/sizeof((a)[0]))
24 #define arraylimit(a) ((a) + arraysize(a))
28 void report(const char *label
)
30 fprintf(stderr
, "%s: %s: %s\n", arg0
, label
, strerror(errno
));
33 void fatal(const char *label
)
39 int aflag
; /* Add a new partition to the current table. */
40 int mflag
; /* Minix rules, no need for alignment. */
41 int rflag
; /* Report current partitions. */
42 int fflag
; /* Force making a table even if too small. */
43 int nflag
; /* Play-act, don't really do it. */
45 int cylinders
, heads
, sectors
; /* Device's geometry */
46 int pad
; /* Partitions must be padded. */
48 /* Descriptions of the device to divide and the partitions to make, including
49 * gaps between partitions.
52 struct part_entry primary
, table
[2 * NR_PARTITIONS
+ 1];
55 /* Extra flags at construction time. */
56 #define EXPAND_FLAG 0x01 /* Add the remaining sectors to this one */
57 #define EXIST_FLAG 0x02 /* Use existing partition */
59 void find_exist(struct part_entry
*exist
, int sysind
, int nr
)
63 struct part_entry oldtable
[NR_PARTITIONS
];
66 struct part_entry
*cur
;
67 char *nr_s
[] = { "", "second ", "third ", "fourth" };
69 if ((f
= open(device
, O_RDONLY
)) < 0
71 || lseek(f
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
73 || read(f
, oldtable
, sizeof(oldtable
)) < 0
75 || read(f
, &signature
, sizeof(signature
)) < 0
85 for (i
= 0; i
< NR_PARTITIONS
; i
++) {
86 if (signature
== 0xAA55
87 && oldtable
[i
].sysind
!= NO_PART
88 && oldtable
[i
].lowsec
>= minlow
89 && oldtable
[i
].lowsec
< curlow
92 curlow
= oldtable
[i
].lowsec
;
100 if (cur
== nil
|| cur
->sysind
!= sysind
) {
102 "%s: Can't find a %sexisting partition of type 0x%02X\n",
103 arg0
, nr_s
[nr
], sysind
);
109 void write_table(void)
112 u16_t signature
= 0xAA55;
113 struct part_entry newtable
[NR_PARTITIONS
];
117 printf("(Table not written)\n");
121 for (i
= 0; i
< NR_PARTITIONS
; i
++) newtable
[i
]= table
[1 + 2*i
];
123 if ((f
= open(device
, O_WRONLY
)) < 0
125 || lseek(f
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
127 || write(f
, newtable
, sizeof(newtable
)) < 0
129 || write(f
, &signature
, sizeof(signature
)) < 0
135 void sec2dos(unsigned long sec
, unsigned char *dos
)
136 /* Translate a sector number into the three bytes DOS uses. */
138 unsigned secspcyl
= heads
* sectors
;
143 dos
[1]= ((sec
% sectors
) + 1) | ((cyl
>> 2) & 0xC0);
144 dos
[0]= (sec
% secspcyl
) / sectors
;
147 void show_chs(unsigned long pos
)
155 cyl
= pos
/ (heads
* sectors
);
156 head
= (pos
/ sectors
) - (cyl
* heads
);
159 printf(" %4d/%03d/%02d", cyl
, head
, sec
);
162 void show_part(struct part_entry
*p
)
164 static int banner
= 0;
168 if ((n
% 2) == 0) return;
172 "Part First Last Base Size Kb\n");
176 printf("%3d ", (n
-1) / 2);
178 show_chs(p
->lowsec
+ p
->size
- 1);
179 printf(" %8lu %8lu %7lu\n", p
->lowsec
, p
->size
, p
->size
/ 2);
185 "Usage: partition [-mfn] device [type:]length[+*] ...\n");
189 #define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
191 void parse(char *descr
)
193 int seen
= 0, sysind
, flags
, c
;
194 unsigned long lowsec
, size
;
198 if (strchr(descr
, ':') == nil
) {
200 if ((npart
% 2) != 0) {
201 fprintf(stderr
, "%s: Two holes can't be adjacent.\n",
209 if ((npart
% 2) == 0) {
210 /* Need a hole before this partition. */
212 /* First hole contains the partition table. */
220 if (between('0', c
, '9'))
223 if (between('a', c
, 'z'))
226 if (between('A', c
, 'Z'))
230 sysind
= 0x10 * sysind
+ c
;
233 if (c
!= ':') usage();
238 if (strncmp(descr
, "exist", 5) == 0 && (npart
% 2) == 1) {
239 struct part_entry exist
;
241 find_exist(&exist
, sysind
, (npart
- 1) / 2);
242 sysind
= exist
.sysind
;
243 lowsec
= exist
.lowsec
;
251 while (between('0', (c
= *descr
++), '9')) {
252 size
= 10 * size
+ (c
- '0');
261 if (c
== '+' && !(flags
& EXIST_FLAG
))
268 if (seen
!= 3 || c
!= 0) usage();
270 if (npart
== arraysize(table
)) {
271 fprintf(stderr
, "%s: too many partitions, only %d possible.\n",
272 arg0
, NR_PARTITIONS
);
275 table
[npart
].bootind
= flags
;
276 table
[npart
].sysind
= sysind
;
277 table
[npart
].lowsec
= lowsec
;
278 table
[npart
].size
= size
;
283 /* Get the geometry of the drive the device lives on, and the base and size
288 struct partition geometry
;
291 if ((fd
= open(device
, O_RDONLY
)) < 0) fatal(device
);
293 /* Get the geometry of the drive, and the device's base and size. */
294 if (ioctl(fd
, DIOCGETP
, &geometry
) < 0)
296 /* Use the same fake geometry as part. */
297 if (fstat(fd
, &sb
) < 0)
299 geometry
.base
= cvul64(0);
300 geometry
.size
= cvul64(sb
.st_size
);
301 geometry
.sectors
= 32;
303 geometry
.cylinders
= (sb
.st_size
-1)/SECTOR_SIZE
/
304 (geometry
.sectors
*geometry
.heads
) + 1;
307 primary
.lowsec
= div64u(geometry
.base
, SECTOR_SIZE
);
308 primary
.size
= div64u(geometry
.size
, SECTOR_SIZE
);
309 cylinders
= geometry
.cylinders
;
310 heads
= geometry
.heads
;
311 sectors
= geometry
.sectors
;
313 /* Is this a primary partition table? If so then pad partitions. */
314 pad
= (!mflag
&& primary
.lowsec
== 0);
317 void boundary(struct part_entry
*pe
, int exp
)
318 /* Expand or reduce a primary partition to a track or cylinder boundary to
319 * avoid giving the fdisk's of simpler operating systems a fit.
324 n
= !pad
? 1 : pe
== &table
[0] ? sectors
: heads
* sectors
;
325 if (exp
) pe
->size
+= n
- 1;
326 pe
->size
= ((pe
->lowsec
+ pe
->size
) / n
* n
) - pe
->lowsec
;
329 void distribute(void)
330 /* Fit the partitions onto the device. Try to start and end them on a
331 * cylinder boundary if so required. The first partition is to start on
332 * track 1, not on cylinder 1.
335 struct part_entry
*pe
, *exp
;
337 unsigned long base
, oldbase
;
341 base
= primary
.lowsec
;
344 for (pe
= table
; pe
< arraylimit(table
); pe
++) {
346 if (pe
->bootind
& EXIST_FLAG
) {
347 if (base
> pe
->lowsec
) {
349 "%s: fixed partition %d is preceded by too big partitions/holes\n",
350 arg0
, ((pe
- table
) - 1) / 2);
353 exp
= nil
; /* XXX - Extend before? */
357 if (pe
->bootind
& EXPAND_FLAG
) exp
= pe
;
359 base
= pe
->lowsec
+ pe
->size
;
360 count
-= base
- oldbase
;
364 fprintf(stderr
, "%s: %s is %ld sectors too small\n",
365 arg0
, device
, -count
);
369 /* Add leftover space to the partition marked for
374 exp
->bootind
&= ~EXPAND_FLAG
;
376 } while (exp
!= nil
);
378 for (pe
= table
; pe
< arraylimit(table
); pe
++) {
379 if (pe
->sysind
== NO_PART
) {
380 memset(pe
, 0, sizeof(*pe
));
382 sec2dos(pe
->lowsec
, &pe
->start_head
);
383 sec2dos(pe
->lowsec
+ pe
->size
- 1, &pe
->last_head
);
384 pe
->bootind
&= ACTIVE_FLAG
;
390 int main(int argc
, char **argv
)
394 if ((arg0
= strrchr(argv
[0], '/')) == nil
) arg0
= argv
[0]; else arg0
++;
397 while (i
< argc
&& argv
[i
][0] == '-') {
398 char *opt
= argv
[i
++] + 1;
400 if (opt
[0] == '-' && opt
[1] == 0) break;
402 while (*opt
!= 0) switch (*opt
++) {
403 case 'a': aflag
= 1; break;
404 case 'm': mflag
= 1; break;
405 case 'r': rflag
= 1; break;
406 case 'f': fflag
= 1; break;
407 case 'n': nflag
= 1; break;
414 if ((argc
- i
) != 1) usage();
415 fprintf(stderr
, "%s: -r is not yet implemented\n", __func__
);
418 if ((argc
- i
) < 1) usage();
419 if (aflag
) fprintf(stderr
, "%s: -a is not yet implemented\n", __func__
);
424 while (i
< argc
) parse(argv
[i
++]);