source: trunk/minix/commands/ibm/repartition.c@ 21

Last change on this file since 21 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 6.7 KB
RevLine 
[9]1/* repartition 1.18 - Load a partition table Author: Kees J. Bot
2 * 30 Nov 1991
3 */
4#define nil 0
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/ioctl.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <minix/config.h>
12#include <minix/const.h>
13#include <minix/partition.h>
14#include <minix/u64.h>
15#include <ibm/partition.h>
16#include <sys/stat.h>
17#include <string.h>
18#include <errno.h>
19#include <dirent.h>
20#include <limits.h>
21
22#define DEV_FD0 0x200
23
24#define SECTOR_SIZE 512
25
26#define arraysize(a) (sizeof(a)/sizeof((a)[0]))
27#define arraylimit(a) ((a) + arraysize(a))
28
29char *arg0;
30char *dev_file; /* Device to repartition. */
31
32#ifndef S_ISLNK
33/* There were no symlinks in medieval times. */
34#define lstat stat
35#endif
36
37void report(const char *label)
38{
39 fprintf(stderr, "%s: %s: %s\n", arg0, label, strerror(errno));
40}
41
42void fatal(const char *label)
43{
44 report(label);
45 exit(1);
46}
47
48#ifndef makedev
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)))
53#endif
54
55#define MINOR_d0p0s0 128
56
57void partsort(struct part_entry *pe)
58/* DOS has the misguided idea that partition tables must be sorted. */
59{
60 int i,j;
61 struct part_entry tmp;
62
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)) {
67 tmp = pe[j];
68 pe[j] = pe[j+1];
69 pe[j+1] = tmp;
70 }
71}
72
73char *finddev(dev_t device)
74/* Find the device next to dev_file with the given device number. */
75{
76 DIR *dp;
77 struct dirent *de;
78 static char name[PATH_MAX];
79 char *np;
80 size_t nlen;
81 struct stat st;
82
83 if ((np= strrchr(dev_file, '/')) == nil) np= dev_file; else np++;
84 nlen= np - dev_file;
85 if (nlen > PATH_MAX - NAME_MAX - 1) {
86 fprintf(stderr, "%s: %s: Name is way too long\n",
87 arg0, dev_file);
88 exit(1);
89 }
90 memcpy(name, dev_file, nlen);
91
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
98 ) {
99 closedir(dp);
100 return name;
101 }
102 }
103 fprintf(stderr, "%s: Can't find partition devices associated with %s\n",
104 arg0, dev_file);
105 exit(1);
106}
107
108#define DSETP 0
109#define DGETP 1
110
111int diocntl(dev_t device, int request, struct partition *entry)
112/* Get or set the geometry of a device. */
113{
114 char *name;
115 int r, f, err;
116 struct partition geometry;
117
118 name= finddev(device);
119 if ((f= open(name, O_RDONLY)) < 0) return -1;
120 r= ioctl(f, request == DSETP ? DIOCSETP : DIOCGETP, (void *) entry);
121 err= errno;
122 (void) close(f);
123 errno= err;
124 return r;
125}
126
127struct partition geometry; /* Geometry of the device. */
128
129void print_chs(unsigned long sector)
130{
131 unsigned secspcyl = geometry.heads * geometry.sectors;
132 int delta= 0;
133
134 if (sector == -1) { sector= 0; delta= -1; }
135
136 printf(" %5d/%03d/%02d",
137 (int) (sector / secspcyl),
138 (int) (sector % secspcyl) / geometry.sectors,
139 (int) (sector % geometry.sectors) + delta);
140}
141
142void show_part(char *name, unsigned long base, unsigned long size)
143{
144 int i;
145 static int len= 0;
146
147 if (len == 0) {
148 len= strlen(name) + 3;
149 printf("device");
150 for (i = 6; i < len; i++) fputc(' ', stdout);
151 printf(
152 " first last base size kb\n");
153 }
154
155 printf("%s", name);
156 for (i = strlen(name); i < len; i++) fputc(' ', stdout);
157
158 print_chs(base);
159 print_chs(base + size - 1);
160 printf(" %9lu %9lu %9lu\n", base, size, size / (1024/SECTOR_SIZE));
161}
162
163int main(int argc, char **argv)
164{
165 struct stat hdst;
166 struct partition whole, entry;
167 struct part_entry table[4], *pe;
168 int drive, par, device, incr;
169 int partf;
170 char *table_file;
171 int hd_major, hd_minor;
172 int needsort;
173 int shrink; /* True if partitions are shrinked to fit. */
174 unsigned long base, size, limit;
175
176 if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
177
178 if (argc < 2 || argc > 3) {
179 fprintf(stderr,
180 "Usage: %s device [partition-file]\n", arg0);
181 exit(1);
182 }
183 dev_file= argv[1];
184 table_file= argv[argc - 1];
185 shrink= (argc == 2);
186
187 if (stat(dev_file, &hdst) < 0) fatal(dev_file);
188
189 /* Geometry (to print nice numbers.) */
190 if (diocntl(hdst.st_rdev, DGETP, &geometry) < 0) fatal(dev_file);
191
192 if (!S_ISBLK(hdst.st_mode)) {
193 fprintf(stderr, "%s: %s is not a device\n", arg0, dev_file);
194 exit(1);
195 }
196 hd_major= major(hdst.st_rdev);
197 hd_minor= minor(hdst.st_rdev);
198
199 if (hd_minor >= MINOR_d0p0s0) {
200 errno= EINVAL;
201 fatal(dev_file);
202 }
203
204 if (hd_major == major(DEV_FD0)) {
205 /* HD is actually a floppy. */
206 if (hd_minor >= 4) {
207 errno= EINVAL;
208 fatal(dev_file);
209 }
210 device= hd_minor + (28 << 2);
211 incr= 4;
212 needsort= 0;
213 } else
214 if (hd_minor % (1 + NR_PARTITIONS) == 0) {
215 /* Partitioning hd0, hd5, ... */
216 device= hd_minor + 1;
217 incr= 1;
218 needsort= 1;
219 } else {
220 /* Subpartitioning hd[1-4], hd[6-9], ... */
221 drive= hd_minor / (1 + NR_PARTITIONS);
222 par= hd_minor % (1 + NR_PARTITIONS) - 1;
223
224 device= MINOR_d0p0s0
225 + (drive * NR_PARTITIONS + par) * NR_PARTITIONS;
226 if (device + NR_PARTITIONS - 1 > BYTE) {
227 errno= EINVAL;
228 fatal(dev_file);
229 }
230 incr= 1;
231 needsort= 0;
232 }
233 /* Device is now the first of the minor devices to be repartitioned. */
234
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
239 ) fatal(table_file);
240
241 if (par < sizeof(table)) {
242 fprintf(stderr, "%s: %s does not contain a partition table\n",
243 arg0, table_file);
244 exit(1);
245 }
246 if (needsort) partsort(table);
247
248 /* Show the geometry of the affected drive or partition. */
249 if (diocntl(hdst.st_rdev, DGETP, &whole) < 0) fatal(dev_file);
250
251 /* Use sector numbers. */
252 base = div64u(whole.base, SECTOR_SIZE);
253 size = div64u(whole.size, SECTOR_SIZE);
254 limit = base + size;
255
256 show_part(dev_file, base, size);
257
258 /* Send the partition table entries to the device driver. */
259 for (par= 0; par < NR_PARTITIONS; par++, device+= incr) {
260 pe = &table[par];
261 if (shrink && pe->size != 0) {
262 /* Shrink the partition entry to fit within the
263 * enclosing device just like the driver does.
264 */
265 unsigned long part_limit= pe->lowsec + pe->size;
266
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;
272 }
273
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)
277 fatal(dev_file);
278
279 show_part(finddev(makedev(hd_major, device)),
280 pe->lowsec, pe->size);
281 }
282 exit(0);
283}
Note: See TracBrowser for help on using the repository browser.