1 /* repartition 1.18 - Load a partition table Author: Kees J. Bot
11 #include <minix/config.h>
12 #include <minix/const.h>
13 #include <minix/partition.h>
14 #include <minix/u64.h>
15 #include <machine/partition.h>
24 #define SECTOR_SIZE 512
26 #define arraysize(a) (sizeof(a)/sizeof((a)[0]))
27 #define arraylimit(a) ((a) + arraysize(a))
30 char *dev_file
; /* Device to repartition. */
33 /* There were no symlinks in medieval times. */
37 void report(const char *label
)
39 fprintf(stderr
, "%s: %s: %s\n", arg0
, label
, strerror(errno
));
42 void fatal(const char *label
)
49 #define minor(dev) (((dev) >> MINOR) & BYTE)
50 #define major(dev) (((dev) >> MAJOR) & BYTE)
51 #define makedev(major, minor) \
52 ((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
55 #define MINOR_d0p0s0 128
57 void partsort(struct part_entry
*pe
)
58 /* DOS has the misguided idea that partition tables must be sorted. */
61 struct part_entry tmp
;
63 for (i
= 0; i
< NR_PARTITIONS
; i
++)
64 for (j
= 0; j
< NR_PARTITIONS
-1; j
++)
65 if ((pe
[j
].sysind
== NO_PART
&& pe
[j
+1].sysind
!= NO_PART
) ||
66 (pe
[j
].lowsec
> pe
[j
+1].lowsec
&& pe
[j
+1].sysind
!= NO_PART
)) {
73 char *finddev(dev_t device
)
74 /* Find the device next to dev_file with the given device number. */
78 static char name
[PATH_MAX
];
83 if ((np
= strrchr(dev_file
, '/')) == nil
) np
= dev_file
; else np
++;
85 if (nlen
> PATH_MAX
- NAME_MAX
- 1) {
86 fprintf(stderr
, "%s: %s: Name is way too long\n",
90 memcpy(name
, dev_file
, nlen
);
92 if ((dp
= opendir("/dev")) == nil
) fatal("/dev");
93 while ((de
= readdir(dp
)) != nil
) {
94 strcpy(name
+nlen
, de
->d_name
);
95 if (lstat(name
, &st
) == 0
96 && (S_ISBLK(st
.st_mode
) || S_ISCHR(st
.st_mode
))
97 && st
.st_rdev
== device
103 fprintf(stderr
, "%s: Can't find partition devices associated with %s\n",
111 int diocntl(dev_t device
, int request
, struct partition
*entry
)
112 /* Get or set the geometry of a device. */
116 struct partition geometry
;
118 name
= finddev(device
);
119 if ((f
= open(name
, O_RDONLY
)) < 0) return -1;
120 r
= ioctl(f
, request
== DSETP
? DIOCSETP
: DIOCGETP
, (void *) entry
);
127 struct partition geometry
; /* Geometry of the device. */
129 void print_chs(unsigned long sector
)
131 unsigned secspcyl
= geometry
.heads
* geometry
.sectors
;
134 if (sector
== -1) { sector
= 0; delta
= -1; }
136 printf(" %5d/%03d/%02d",
137 (int) (sector
/ secspcyl
),
138 (int) (sector
% secspcyl
) / geometry
.sectors
,
139 (int) (sector
% geometry
.sectors
) + delta
);
142 void show_part(char *name
, unsigned long base
, unsigned long size
)
148 len
= strlen(name
) + 3;
150 for (i
= 6; i
< len
; i
++) fputc(' ', stdout
);
152 " first last base size kb\n");
156 for (i
= strlen(name
); i
< len
; i
++) fputc(' ', stdout
);
159 print_chs(base
+ size
- 1);
160 printf(" %9lu %9lu %9lu\n", base
, size
, size
/ (1024/SECTOR_SIZE
));
163 int main(int argc
, char **argv
)
166 struct partition whole
, entry
;
167 struct part_entry table
[4], *pe
;
168 int drive
, par
, device
, incr
;
171 int hd_major
, hd_minor
;
173 int shrink
; /* True if partitions are shrinked to fit. */
174 unsigned long base
, size
, limit
;
176 if ((arg0
= strrchr(argv
[0], '/')) == nil
) arg0
= argv
[0]; else arg0
++;
178 if (argc
< 2 || argc
> 3) {
180 "Usage: %s device [partition-file]\n", arg0
);
184 table_file
= argv
[argc
- 1];
187 if (stat(dev_file
, &hdst
) < 0) fatal(dev_file
);
189 /* Geometry (to print nice numbers.) */
190 if (diocntl(hdst
.st_rdev
, DGETP
, &geometry
) < 0) fatal(dev_file
);
192 if (!S_ISBLK(hdst
.st_mode
)) {
193 fprintf(stderr
, "%s: %s is not a device\n", arg0
, dev_file
);
196 hd_major
= major(hdst
.st_rdev
);
197 hd_minor
= minor(hdst
.st_rdev
);
199 if (hd_minor
>= MINOR_d0p0s0
) {
204 if (hd_major
== major(DEV_FD0
)) {
205 /* HD is actually a floppy. */
210 device
= hd_minor
+ (28 << 2);
214 if (hd_minor
% (1 + NR_PARTITIONS
) == 0) {
215 /* Partitioning hd0, hd5, ... */
216 device
= hd_minor
+ 1;
220 /* Subpartitioning hd[1-4], hd[6-9], ... */
221 drive
= hd_minor
/ (1 + NR_PARTITIONS
);
222 par
= hd_minor
% (1 + NR_PARTITIONS
) - 1;
225 + (drive
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
226 if (device
+ NR_PARTITIONS
- 1 > BYTE
) {
233 /* Device is now the first of the minor devices to be repartitioned. */
235 /* Read the partition table from the boot block. */
236 if ((partf
= open(table_file
, O_RDONLY
)) < 0
237 || lseek(partf
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
238 || (par
= read(partf
, (char *) table
, (int) sizeof(table
))) < 0
241 if (par
< sizeof(table
)) {
242 fprintf(stderr
, "%s: %s does not contain a partition table\n",
246 if (needsort
) partsort(table
);
248 /* Show the geometry of the affected drive or partition. */
249 if (diocntl(hdst
.st_rdev
, DGETP
, &whole
) < 0) fatal(dev_file
);
251 /* Use sector numbers. */
252 base
= div64u(whole
.base
, SECTOR_SIZE
);
253 size
= div64u(whole
.size
, SECTOR_SIZE
);
256 show_part(dev_file
, base
, size
);
258 /* Send the partition table entries to the device driver. */
259 for (par
= 0; par
< NR_PARTITIONS
; par
++, device
+= incr
) {
261 if (shrink
&& pe
->size
!= 0) {
262 /* Shrink the partition entry to fit within the
263 * enclosing device just like the driver does.
265 unsigned long part_limit
= pe
->lowsec
+ pe
->size
;
267 if (part_limit
< pe
->lowsec
) part_limit
= limit
;
268 if (part_limit
> limit
) part_limit
= limit
;
269 if (pe
->lowsec
< base
) pe
->lowsec
= base
;
270 if (part_limit
< pe
->lowsec
) part_limit
= pe
->lowsec
;
271 pe
->size
= part_limit
- pe
->lowsec
;
274 entry
.base
= mul64u(pe
->lowsec
, SECTOR_SIZE
);
275 entry
.size
= mul64u(pe
->size
, SECTOR_SIZE
);
276 if (diocntl(makedev(hd_major
, device
), DSETP
, &entry
) < 0)
279 show_part(finddev(makedev(hd_major
, device
)),
280 pe
->lowsec
, pe
->size
);