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
)
48 #define minor(dev) (((dev) >> MINOR) & BYTE)
49 #define major(dev) (((dev) >> MAJOR) & BYTE)
50 #define makedev(major, minor) \
51 ((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
54 #define MINOR_d0p0s0 128
56 void partsort(struct part_entry
*pe
)
57 /* DOS has the misguided idea that partition tables must be sorted. */
60 struct part_entry tmp
;
62 for (i
= 0; i
< NR_PARTITIONS
; i
++)
63 for (j
= 0; j
< NR_PARTITIONS
-1; j
++)
64 if ((pe
[j
].sysind
== NO_PART
&& pe
[j
+1].sysind
!= NO_PART
) ||
65 (pe
[j
].lowsec
> pe
[j
+1].lowsec
&& pe
[j
+1].sysind
!= NO_PART
)) {
72 char *finddev(dev_t device
)
73 /* Find the device next to dev_file with the given device number. */
77 static char name
[PATH_MAX
];
82 if ((np
= strrchr(dev_file
, '/')) == nil
) np
= dev_file
; else np
++;
84 if (nlen
> PATH_MAX
- NAME_MAX
- 1) {
85 fprintf(stderr
, "%s: %s: Name is way too long\n",
89 memcpy(name
, dev_file
, nlen
);
91 if ((dp
= opendir("/dev")) == nil
) fatal("/dev");
92 while ((de
= readdir(dp
)) != nil
) {
93 strcpy(name
+nlen
, de
->d_name
);
94 if (lstat(name
, &st
) == 0
95 && (S_ISBLK(st
.st_mode
) || S_ISCHR(st
.st_mode
))
96 && st
.st_rdev
== device
102 fprintf(stderr
, "%s: Can't find partition devices associated with %s\n",
110 int diocntl(dev_t device
, int request
, struct partition
*entry
)
111 /* Get or set the geometry of a device. */
115 struct partition geometry
;
117 name
= finddev(device
);
118 if ((f
= open(name
, O_RDONLY
)) < 0) return -1;
119 r
= ioctl(f
, request
== DSETP
? DIOCSETP
: DIOCGETP
, (void *) entry
);
126 struct partition geometry
; /* Geometry of the device. */
128 void print_chs(unsigned long sector
)
130 unsigned secspcyl
= geometry
.heads
* geometry
.sectors
;
133 if (sector
== -1) { sector
= 0; delta
= -1; }
135 printf(" %5d/%03d/%02d",
136 (int) (sector
/ secspcyl
),
137 (int) (sector
% secspcyl
) / geometry
.sectors
,
138 (int) (sector
% geometry
.sectors
) + delta
);
141 void show_part(char *name
, unsigned long base
, unsigned long size
)
147 len
= strlen(name
) + 3;
149 for (i
= 6; i
< len
; i
++) fputc(' ', stdout
);
151 " first last base size kb\n");
155 for (i
= strlen(name
); i
< len
; i
++) fputc(' ', stdout
);
158 print_chs(base
+ size
- 1);
159 printf(" %9lu %9lu %9lu\n", base
, size
, size
/ (1024/SECTOR_SIZE
));
162 int main(int argc
, char **argv
)
165 struct partition whole
, entry
;
166 struct part_entry table
[4], *pe
;
167 int drive
, par
, device
, incr
;
170 int hd_major
, hd_minor
;
172 int shrink
; /* True if partitions are shrinked to fit. */
173 unsigned long base
, size
, limit
;
175 if ((arg0
= strrchr(argv
[0], '/')) == nil
) arg0
= argv
[0]; else arg0
++;
177 if (argc
< 2 || argc
> 3) {
179 "Usage: %s device [partition-file]\n", arg0
);
183 table_file
= argv
[argc
- 1];
186 if (stat(dev_file
, &hdst
) < 0) fatal(dev_file
);
188 /* Geometry (to print nice numbers.) */
189 if (diocntl(hdst
.st_rdev
, DGETP
, &geometry
) < 0) fatal(dev_file
);
191 if (!S_ISBLK(hdst
.st_mode
)) {
192 fprintf(stderr
, "%s: %s is not a device\n", arg0
, dev_file
);
195 hd_major
= major(hdst
.st_rdev
);
196 hd_minor
= minor(hdst
.st_rdev
);
198 if (hd_minor
>= MINOR_d0p0s0
) {
203 if (hd_major
== major(DEV_FD0
)) {
204 /* HD is actually a floppy. */
209 device
= hd_minor
+ (28 << 2);
213 if (hd_minor
% (1 + NR_PARTITIONS
) == 0) {
214 /* Partitioning hd0, hd5, ... */
215 device
= hd_minor
+ 1;
219 /* Subpartitioning hd[1-4], hd[6-9], ... */
220 drive
= hd_minor
/ (1 + NR_PARTITIONS
);
221 par
= hd_minor
% (1 + NR_PARTITIONS
) - 1;
224 + (drive
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
225 if (device
+ NR_PARTITIONS
- 1 > BYTE
) {
232 /* Device is now the first of the minor devices to be repartitioned. */
234 /* Read the partition table from the boot block. */
235 if ((partf
= open(table_file
, O_RDONLY
)) < 0
236 || lseek(partf
, (off_t
) PART_TABLE_OFF
, SEEK_SET
) == -1
237 || (par
= read(partf
, (char *) table
, (int) sizeof(table
))) < 0
240 if (par
< sizeof(table
)) {
241 fprintf(stderr
, "%s: %s does not contain a partition table\n",
245 if (needsort
) partsort(table
);
247 /* Show the geometry of the affected drive or partition. */
248 if (diocntl(hdst
.st_rdev
, DGETP
, &whole
) < 0) fatal(dev_file
);
250 /* Use sector numbers. */
251 base
= whole
.base
/ SECTOR_SIZE
;
252 size
= whole
.size
/ SECTOR_SIZE
;
255 show_part(dev_file
, base
, size
);
257 /* Send the partition table entries to the device driver. */
258 for (par
= 0; par
< NR_PARTITIONS
; par
++, device
+= incr
) {
260 if (shrink
&& pe
->size
!= 0) {
261 /* Shrink the partition entry to fit within the
262 * enclosing device just like the driver does.
264 unsigned long part_limit
= pe
->lowsec
+ pe
->size
;
266 if (part_limit
< pe
->lowsec
) part_limit
= limit
;
267 if (part_limit
> limit
) part_limit
= limit
;
268 if (pe
->lowsec
< base
) pe
->lowsec
= base
;
269 if (part_limit
< pe
->lowsec
) part_limit
= pe
->lowsec
;
270 pe
->size
= part_limit
- pe
->lowsec
;
273 entry
.base
= pe
->lowsec
* SECTOR_SIZE
;
274 entry
.size
= pe
->size
* SECTOR_SIZE
;
275 if (diocntl(makedev(hd_major
, device
), DSETP
, &entry
) < 0)
278 show_part(finddev(makedev(hd_major
, device
)),
279 pe
->lowsec
, pe
->size
);