]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - partx/partx.c
2 * Given a block device and a partition table type,
3 * try to parse the partition table, and list the
4 * contents. Optionally add or remove partitions.
6 * [This is not an fdisk - adding and removing partitions
7 * is not a change of the disk, but just telling the kernel
8 * about presence and numbering of on-disk partitions.]
11 * partx [-{l|a|d}] [--type TYPE] [--nr M-N] [partition] wholedisk
12 * where TYPE is {dos|bsd|solaris|unixware|gpt}.
14 * Read wholedisk and add all partitions:
17 * Subdivide a partition into slices (and delete or shrink the partition):
18 * [Not easy: one needs the partition number of partition -
19 * that is the last 4 or 6 bits of the minor; it can also be found
20 * in /proc/partitions; but there is no good direct way.]
21 * partx -a partition wholedisk
23 * Delete all partitions from wholedisk:
26 * Delete partitions M-N from wholedisk:
27 * partx -d --nr M-N wholedisk
29 * aeb, 2000-03-21 -- sah is 42 now
39 #include <sys/ioctl.h>
40 #include <linux/hdreg.h> /* HDIO_GETGEO */
41 #ifdef HAVE_LINUX_COMPILER_H
42 #include <linux/compiler.h>
44 #include <linux/blkpg.h>
45 #define BLKGETSIZE _IO(0x12,96) /* return device size */
49 static void errmerge(int err
, int m
, char *msg1
, char *msg2
);
51 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
56 struct slice slices
[MAXSLICES
];
58 enum action
{ LIST
, ADD
, DELETE
};
67 addpts(char *t
, ptreader f
)
69 if (ptct
>= MAXTYPES
) {
70 fprintf(stderr
, "addpts: too many types\n");
81 addpts("gpt", read_gpt_pt
);
82 addpts("dos", read_dos_pt
);
83 addpts("bsd", read_bsd_pt
);
84 addpts("solaris", read_solaris_pt
);
85 addpts("unixware", read_unixware_pt
);
88 static char short_opts
[] = "ladgvn:t:";
89 static const struct option long_opts
[] = {
90 { "gpt", no_argument
, NULL
, 'g' },
91 { "type", required_argument
, NULL
, 't' },
92 { "nr", required_argument
, NULL
, 'n' },
100 main(int argc
, char **argv
){
101 int fd
, fd2
, c
, i
, j
, k
, n
;
103 struct hd_geometry g
;
105 struct blkpg_ioctl_arg a
;
106 struct blkpg_partition pt
;
108 enum action what
= LIST
;
109 char *p
, *type
, *diskdevice
, *device
;
118 type
= device
= diskdevice
= NULL
;
120 while ((c
= getopt_long (argc
, argv
, short_opts
, long_opts
, NULL
))
127 what
= DELETE
; break;
129 force_gpt
= 1; break;
147 fprintf(stderr
, "unknown option\n");
151 if (optind
== argc
-2) {
152 device
= argv
[optind
];
153 diskdevice
= argv
[optind
+1];
154 } else if (optind
== argc
-1) {
155 diskdevice
= device
= argv
[optind
];
157 fprintf(stderr
, "call: partx -opts [device] wholedisk\n");
161 fd
= open(diskdevice
, O_RDONLY
);
167 /* remove the indicated partitions from the kernel partition tables */
168 if (what
== DELETE
) {
169 if (device
!= diskdevice
) {
171 "call: partx -d [--nr M-N] wholedisk\n");
178 while (upper
== 0 || lower
<= upper
) {
186 a
.op
= BLKPG_DEL_PARTITION
;
188 a
.datalen
= sizeof(pt
);
190 if (ioctl(fd
, BLKPG
, &a
) == -1)
195 "error deleting partition %d: ",
196 "error deleting partitions %d-%d: ");
198 EBUSY: mounted or in use as swap
199 ENXIO: no such nonempty partition
200 EINVAL: not wholedisk, or bad pno
201 EACCES/EPERM: permission denied
203 if (err
&& err
!= EBUSY
&& err
!= ENXIO
) {
207 if (err
== 0 && verbose
)
208 printf("deleted partition %d\n", lower
);
212 "error deleting partition %d: ",
213 "error deleting partitions %d-%d: ");
217 if (device
!= diskdevice
) {
218 fd2
= open(device
, O_RDONLY
);
227 if (ioctl(fd
, HDIO_GETGEO
, &g
)) {
228 perror("HDIO_GETGEO");
232 fprintf(stderr
, "last arg is not the whole disk\n");
233 fprintf(stderr
, "call: partx -opts device wholedisk\n");
237 if (ioctl(fd2
, HDIO_GETGEO
, &g
)) {
238 perror("HDIO_GETGEO");
243 if(ioctl(fd2
, BLKGETSIZE
, &size
)) {
244 perror("BLKGETSIZE");
250 printf("device %s: start %d size %d\n",
251 device
, all
.start
, all
.size
);
254 fprintf(stderr
, "That disk slice has size 0\n");
258 all
.size
= 0; /* probably extended partition */
260 /* add the indicated partitions to the kernel partition tables */
263 for (i
= 0; i
< ptct
; i
++) {
265 if (!type
|| !strcmp(type
, ptp
->type
)) {
266 n
= ptp
->fn(fd
, all
, slices
, SIZE(slices
));
267 if (n
>= 0 && verbose
)
268 printf("%s: %d slices\n", ptp
->type
, n
);
269 if (n
> 0 && (verbose
|| what
== LIST
)) {
271 printf("#%2d: %9d-%9d (%9d sectors, %6d MB)\n",
274 slices
[j
].start
+slices
[j
].size
-1,
276 (int)((512 * (long long) slices
[j
].size
)
279 if (n
> 0 && what
== ADD
) {
280 /* test for overlap, as in the case of an
281 extended partition, and reduce size */
282 for (j
=0; j
<n
; j
++) {
283 for (k
=j
+1; k
<n
; k
++) {
284 if (slices
[k
].start
> slices
[j
].start
&&
285 slices
[k
].start
< slices
[j
].start
+
287 slices
[j
].size
= slices
[k
].start
-
290 printf("reduced size of "
291 "partition #%d to %d\n",
297 for (j
=0; j
<n
; j
++) {
299 pt
.start
= 512 * (long long) slices
[j
].start
;
300 pt
.length
= 512 * (long long) slices
[j
].size
;
303 a
.op
= BLKPG_ADD_PARTITION
;
305 a
.datalen
= sizeof(pt
);
307 if (ioctl(fd
, BLKPG
, &a
) == -1) {
310 "error adding partition %d\n",
313 printf("added partition %d\n", lower
+j
);
323 xmalloc (size_t size
) {
330 fprintf(stderr
, "Out of memory\n");
337 sseek(int fd
, unsigned int secnr
) {
339 in
= ((long long) secnr
<< 9);
342 if ((out
= lseek(fd
, in
, SEEK_SET
)) != in
)
344 fprintf(stderr
, "lseek error\n");
358 getblock(int fd
, unsigned int secnr
) {
361 for (bp
= blockhead
; bp
; bp
= bp
->next
)
362 if (bp
->secnr
== secnr
)
364 if (sseek(fd
, secnr
))
366 bp
= xmalloc(sizeof(struct block
));
368 bp
->next
= blockhead
;
370 bp
->block
= (char *) xmalloc(1024);
371 if (read(fd
, bp
->block
, 1024) != 1024) {
372 fprintf(stderr
, "read error, sector %d\n", secnr
);
378 /* call with errno and integer m and error message */
379 /* merge to interval m-n */
381 errmerge(int err
, int m
, char *msg1
, char *msg2
) {
382 static int preverr
, firstm
, prevm
;
384 if (err
!= preverr
) {
387 fprintf(stderr
, msg1
, firstm
);
389 fprintf(stderr
, msg2
, firstm
, prevm
);