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
)
40 #define minor(dev) (((dev) >> MINOR) & BYTE)
41 #define major(dev) (((dev) >> MAJOR) & BYTE)
42 #define makedev(major, minor) \
43 ((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
46 int aflag
; /* Add a new partition to the current table. */
47 int mflag
; /* Minix rules, no need for alignment. */
48 int rflag
; /* Report current partitions. */
49 int fflag
; /* Force making a table even if too small. */
50 int nflag
; /* Play-act, don't really do it. */
52 int cylinders
, heads
, sectors
; /* Device's geometry */
53 int pad
; /* Partitions must be padded. */
55 /* Descriptions of the device to divide and the partitions to make, including
56 * gaps between partitions.
59 struct part_entry primary
, table
[2 * NR_PARTITIONS
+ 1];
62 /* Extra flags at construction time. */
63 #define EXPAND_FLAG 0x01 /* Add the remaining sectors to this one */
64 #define EXIST_FLAG 0x02 /* Use existing partition */
66 void find_exist(struct part_entry
*exist
, int sysind
, int nr
)
70 struct part_entry oldtable
[NR_PARTITIONS
];
73 struct part_entry
*cur
;
74 char *nr_s
[] = { "", "second ", "third ", "fourth" };
76 if ((f
= open(device
, O_RDONLY
)) < 0
78 || lseek(f
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
80 || read(f
, oldtable
, sizeof(oldtable
)) < 0
82 || read(f
, &signature
, sizeof(signature
)) < 0
92 for (i
= 0; i
< NR_PARTITIONS
; i
++) {
93 if (signature
== 0xAA55
94 && oldtable
[i
].sysind
!= NO_PART
95 && oldtable
[i
].lowsec
>= minlow
96 && oldtable
[i
].lowsec
< curlow
99 curlow
= oldtable
[i
].lowsec
;
107 if (cur
== nil
|| cur
->sysind
!= sysind
) {
109 "%s: Can't find a %sexisting partition of type 0x%02X\n",
110 arg0
, nr_s
[nr
], sysind
);
116 void write_table(void)
119 u16_t signature
= 0xAA55;
120 struct part_entry newtable
[NR_PARTITIONS
];
124 printf("(Table not written)\n");
128 for (i
= 0; i
< NR_PARTITIONS
; i
++) newtable
[i
]= table
[1 + 2*i
];
130 if ((f
= open(device
, O_WRONLY
)) < 0
132 || lseek(f
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
134 || write(f
, newtable
, sizeof(newtable
)) < 0
136 || write(f
, &signature
, sizeof(signature
)) < 0
142 void sec2dos(unsigned long sec
, unsigned char *dos
)
143 /* Translate a sector number into the three bytes DOS uses. */
145 unsigned secspcyl
= heads
* sectors
;
150 dos
[1]= ((sec
% sectors
) + 1) | ((cyl
>> 2) & 0xC0);
151 dos
[0]= (sec
% secspcyl
) / sectors
;
154 void show_chs(unsigned long pos
)
162 cyl
= pos
/ (heads
* sectors
);
163 head
= (pos
/ sectors
) - (cyl
* heads
);
166 printf(" %4d/%03d/%02d", cyl
, head
, sec
);
169 void show_part(struct part_entry
*p
)
171 static int banner
= 0;
175 if ((n
% 2) == 0) return;
179 "Part First Last Base Size Kb\n");
183 printf("%3d ", (n
-1) / 2);
185 show_chs(p
->lowsec
+ p
->size
- 1);
186 printf(" %8lu %8lu %7lu\n", p
->lowsec
, p
->size
, p
->size
/ 2);
192 "Usage: partition [-mfn] device [type:]length[+*] ...\n");
196 #define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
198 void parse(char *descr
)
200 int seen
= 0, sysind
, flags
, c
;
201 unsigned long lowsec
, size
;
205 if (strchr(descr
, ':') == nil
) {
207 if ((npart
% 2) != 0) {
208 fprintf(stderr
, "%s: Two holes can't be adjacent.\n",
216 if ((npart
% 2) == 0) {
217 /* Need a hole before this partition. */
219 /* First hole contains the partition table. */
227 if (between('0', c
, '9'))
230 if (between('a', c
, 'z'))
233 if (between('A', c
, 'Z'))
237 sysind
= 0x10 * sysind
+ c
;
240 if (c
!= ':') usage();
245 if (strncmp(descr
, "exist", 5) == 0 && (npart
% 2) == 1) {
246 struct part_entry exist
;
248 find_exist(&exist
, sysind
, (npart
- 1) / 2);
249 sysind
= exist
.sysind
;
250 lowsec
= exist
.lowsec
;
258 while (between('0', (c
= *descr
++), '9')) {
259 size
= 10 * size
+ (c
- '0');
268 if (c
== '+' && !(flags
& EXIST_FLAG
))
275 if (seen
!= 3 || c
!= 0) usage();
277 if (npart
== arraysize(table
)) {
278 fprintf(stderr
, "%s: too many partitions, only %d possible.\n",
279 arg0
, NR_PARTITIONS
);
282 table
[npart
].bootind
= flags
;
283 table
[npart
].sysind
= sysind
;
284 table
[npart
].lowsec
= lowsec
;
285 table
[npart
].size
= size
;
290 /* Get the geometry of the drive the device lives on, and the base and size
295 struct partition geometry
;
298 if ((fd
= open(device
, O_RDONLY
)) < 0) fatal(device
);
300 /* Get the geometry of the drive, and the device's base and size. */
301 if (ioctl(fd
, DIOCGETP
, &geometry
) < 0)
303 /* Use the same fake geometry as part. */
304 if (fstat(fd
, &sb
) < 0)
306 geometry
.base
= cvul64(0);
307 geometry
.size
= cvul64(sb
.st_size
);
308 geometry
.sectors
= 32;
310 geometry
.cylinders
= (sb
.st_size
-1)/SECTOR_SIZE
/
311 (geometry
.sectors
*geometry
.heads
) + 1;
314 primary
.lowsec
= div64u(geometry
.base
, SECTOR_SIZE
);
315 primary
.size
= div64u(geometry
.size
, SECTOR_SIZE
);
316 cylinders
= geometry
.cylinders
;
317 heads
= geometry
.heads
;
318 sectors
= geometry
.sectors
;
320 /* Is this a primary partition table? If so then pad partitions. */
321 pad
= (!mflag
&& primary
.lowsec
== 0);
324 void boundary(struct part_entry
*pe
, int exp
)
325 /* Expand or reduce a primary partition to a track or cylinder boundary to
326 * avoid giving the fdisk's of simpler operating systems a fit.
331 n
= !pad
? 1 : pe
== &table
[0] ? sectors
: heads
* sectors
;
332 if (exp
) pe
->size
+= n
- 1;
333 pe
->size
= ((pe
->lowsec
+ pe
->size
) / n
* n
) - pe
->lowsec
;
336 void distribute(void)
337 /* Fit the partitions onto the device. Try to start and end them on a
338 * cylinder boundary if so required. The first partition is to start on
339 * track 1, not on cylinder 1.
342 struct part_entry
*pe
, *exp
;
344 unsigned long base
, size
, oldbase
;
348 base
= primary
.lowsec
;
351 for (pe
= table
; pe
< arraylimit(table
); pe
++) {
353 if (pe
->bootind
& EXIST_FLAG
) {
354 if (base
> pe
->lowsec
) {
356 "%s: fixed partition %d is preceded by too big partitions/holes\n",
357 arg0
, ((pe
- table
) - 1) / 2);
360 exp
= nil
; /* XXX - Extend before? */
364 if (pe
->bootind
& EXPAND_FLAG
) exp
= pe
;
366 base
= pe
->lowsec
+ pe
->size
;
367 count
-= base
- oldbase
;
371 fprintf(stderr
, "%s: %s is %ld sectors too small\n",
372 arg0
, device
, -count
);
376 /* Add leftover space to the partition marked for
381 exp
->bootind
&= ~EXPAND_FLAG
;
383 } while (exp
!= nil
);
385 for (pe
= table
; pe
< arraylimit(table
); pe
++) {
386 if (pe
->sysind
== NO_PART
) {
387 memset(pe
, 0, sizeof(*pe
));
389 sec2dos(pe
->lowsec
, &pe
->start_head
);
390 sec2dos(pe
->lowsec
+ pe
->size
- 1, &pe
->last_head
);
391 pe
->bootind
&= ACTIVE_FLAG
;
397 int main(int argc
, char **argv
)
401 if ((arg0
= strrchr(argv
[0], '/')) == nil
) arg0
= argv
[0]; else arg0
++;
404 while (i
< argc
&& argv
[i
][0] == '-') {
405 char *opt
= argv
[i
++] + 1;
407 if (opt
[0] == '-' && opt
[1] == 0) break;
409 while (*opt
!= 0) switch (*opt
++) {
410 case 'a': aflag
= 1; break;
411 case 'm': mflag
= 1; break;
412 case 'r': rflag
= 1; break;
413 case 'f': fflag
= 1; break;
414 case 'n': nflag
= 1; break;
421 if ((argc
- i
) != 1) usage();
422 fprintf(stderr
, "%s: -r is not yet implemented\n");
425 if ((argc
- i
) < 1) usage();
426 if (aflag
) fprintf(stderr
, "%s: -a is not yet implemented\n");
431 while (i
< argc
) parse(argv
[i
++]);