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 <machine/partition.h>
23 #define SECTOR_SIZE 512
25 #define arraysize(a) (sizeof(a)/sizeof((a)[0]))
26 #define arraylimit(a) ((a) + arraysize(a))
29 char *dev_file
; /* Device to repartition. */
32 /* There were no symlinks in medieval times. */
36 void report(const char *label
)
38 fprintf(stderr
, "%s: %s: %s\n", arg0
, label
, strerror(errno
));
41 void fatal(const char *label
)
47 #define MINOR_d0p0s0 128
49 void partsort(struct part_entry
*pe
)
50 /* DOS has the misguided idea that partition tables must be sorted. */
53 struct part_entry tmp
;
55 for (i
= 0; i
< NR_PARTITIONS
; i
++)
56 for (j
= 0; j
< NR_PARTITIONS
-1; j
++)
57 if ((pe
[j
].sysind
== NO_PART
&& pe
[j
+1].sysind
!= NO_PART
) ||
58 (pe
[j
].lowsec
> pe
[j
+1].lowsec
&& pe
[j
+1].sysind
!= NO_PART
)) {
65 char *finddev(dev_t device
)
66 /* Find the device next to dev_file with the given device number. */
70 static char name
[PATH_MAX
];
75 if ((np
= strrchr(dev_file
, '/')) == nil
) np
= dev_file
; else np
++;
77 if (nlen
> PATH_MAX
- NAME_MAX
- 1) {
78 fprintf(stderr
, "%s: %s: Name is way too long\n",
82 memcpy(name
, dev_file
, nlen
);
84 if ((dp
= opendir("/dev")) == nil
) fatal("/dev");
85 while ((de
= readdir(dp
)) != nil
) {
86 strcpy(name
+nlen
, de
->d_name
);
87 if (lstat(name
, &st
) == 0
88 && (S_ISBLK(st
.st_mode
) || S_ISCHR(st
.st_mode
))
89 && st
.st_rdev
== device
95 fprintf(stderr
, "%s: Can't find partition devices associated with %s\n",
103 int diocntl(dev_t device
, int request
, struct part_geom
*entry
)
104 /* Get or set the geometry of a device. */
109 name
= finddev(device
);
110 if ((f
= open(name
, O_RDONLY
)) < 0) return -1;
111 r
= ioctl(f
, request
== DSETP
? DIOCSETP
: DIOCGETP
, (void *) entry
);
118 struct part_geom geometry
; /* Geometry of the device. */
120 void print_chs(unsigned long sector
)
122 unsigned secspcyl
= geometry
.heads
* geometry
.sectors
;
125 if (sector
== -1) { sector
= 0; delta
= -1; }
127 printf(" %5d/%03d/%02d",
128 (int) (sector
/ secspcyl
),
129 (int) (sector
% secspcyl
) / geometry
.sectors
,
130 (int) (sector
% geometry
.sectors
) + delta
);
133 void show_part(char *name
, unsigned long base
, unsigned long size
)
139 len
= strlen(name
) + 3;
141 for (i
= 6; i
< len
; i
++) fputc(' ', stdout
);
143 " first last base size kb\n");
147 for (i
= strlen(name
); i
< len
; i
++) fputc(' ', stdout
);
150 print_chs(base
+ size
- 1);
151 printf(" %9lu %9lu %9lu\n", base
, size
, size
/ (1024/SECTOR_SIZE
));
154 int main(int argc
, char **argv
)
157 struct part_geom whole
, entry
;
158 struct part_entry table
[4], *pe
;
159 int drive
, par
= 0, device
, incr
;
162 int hd_major
, hd_minor
;
164 int shrink
; /* True if partitions are shrinked to fit. */
165 unsigned long base
, size
, limit
;
167 if ((arg0
= strrchr(argv
[0], '/')) == nil
) arg0
= argv
[0]; else arg0
++;
169 if (argc
< 2 || argc
> 3) {
171 "Usage: %s device [partition-file]\n", arg0
);
175 table_file
= argv
[argc
- 1];
178 if (stat(dev_file
, &hdst
) < 0) fatal(dev_file
);
180 /* Geometry (to print nice numbers.) */
181 if (diocntl(hdst
.st_rdev
, DGETP
, &geometry
) < 0) fatal(dev_file
);
183 if (!S_ISBLK(hdst
.st_mode
)) {
184 fprintf(stderr
, "%s: %s is not a device\n", arg0
, dev_file
);
187 hd_major
= major(hdst
.st_rdev
);
188 hd_minor
= minor(hdst
.st_rdev
);
190 if (hd_minor
>= MINOR_d0p0s0
) {
195 if (hd_major
== major(DEV_FD0
)) {
196 /* HD is actually a floppy. */
201 device
= hd_minor
+ (28 << 2);
205 if (hd_minor
% (1 + NR_PARTITIONS
) == 0) {
206 /* Partitioning hd0, hd5, ... */
207 device
= hd_minor
+ 1;
211 /* Subpartitioning hd[1-4], hd[6-9], ... */
212 drive
= hd_minor
/ (1 + NR_PARTITIONS
);
213 par
= hd_minor
% (1 + NR_PARTITIONS
) - 1;
216 + (drive
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
217 if (device
+ NR_PARTITIONS
- 1 > BYTE
) {
224 /* Device is now the first of the minor devices to be repartitioned. */
226 /* Read the partition table from the boot block. */
227 if ((partf
= open(table_file
, O_RDONLY
)) < 0
228 || lseek(partf
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
229 || (par
= read(partf
, (char *) table
, (int) sizeof(table
))) < 0
232 if (par
< sizeof(table
)) {
233 fprintf(stderr
, "%s: %s does not contain a partition table\n",
237 if (needsort
) partsort(table
);
239 /* Show the geometry of the affected drive or partition. */
240 if (diocntl(hdst
.st_rdev
, DGETP
, &whole
) < 0) fatal(dev_file
);
242 /* Use sector numbers. */
243 base
= whole
.base
/ SECTOR_SIZE
;
244 size
= whole
.size
/ SECTOR_SIZE
;
247 show_part(dev_file
, base
, size
);
249 /* Send the partition table entries to the device driver. */
250 for (par
= 0; par
< NR_PARTITIONS
; par
++, device
+= incr
) {
252 if (shrink
&& pe
->size
!= 0) {
253 /* Shrink the partition entry to fit within the
254 * enclosing device just like the driver does.
256 unsigned long part_limit
= pe
->lowsec
+ pe
->size
;
258 if (part_limit
< pe
->lowsec
) part_limit
= limit
;
259 if (part_limit
> limit
) part_limit
= limit
;
260 if (pe
->lowsec
< base
) pe
->lowsec
= base
;
261 if (part_limit
< pe
->lowsec
) part_limit
= pe
->lowsec
;
262 pe
->size
= part_limit
- pe
->lowsec
;
265 entry
.base
= pe
->lowsec
* SECTOR_SIZE
;
266 entry
.size
= pe
->size
* SECTOR_SIZE
;
267 if (diocntl(makedev(hd_major
, device
), DSETP
, &entry
) < 0)
270 show_part(finddev(makedev(hd_major
, device
)),
271 pe
->lowsec
, pe
->size
);