]>
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 #include <linux/blkpg.h>
42 #define BLKGETSIZE _IO(0x12,96) /* return device size */
46 static void errmerge(int err
, int m
, char *msg1
, char *msg2
);
48 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
53 struct slice slices
[MAXSLICES
];
55 enum action
{ LIST
, ADD
, DELETE
};
64 addpts(char *t
, ptreader f
)
66 if (ptct
>= MAXTYPES
) {
67 fprintf(stderr
, "addpts: too many types\n");
78 addpts("gpt", read_gpt_pt
);
79 addpts("dos", read_dos_pt
);
80 addpts("bsd", read_bsd_pt
);
81 addpts("solaris", read_solaris_pt
);
82 addpts("unixware", read_unixware_pt
);
85 static char short_opts
[] = "ladgvn:t:";
86 static const struct option long_opts
[] = {
87 { "gpt", no_argument
, NULL
, 'g' },
88 { "type", required_argument
, NULL
, 't' },
89 { "nr", required_argument
, NULL
, 'n' },
97 main(int argc
, char **argv
){
98 int fd
, fd2
, c
, i
, j
, k
, n
;
100 struct hd_geometry g
;
102 struct blkpg_ioctl_arg a
;
103 struct blkpg_partition pt
;
105 enum action what
= LIST
;
106 char *p
, *type
, *diskdevice
, *device
;
115 type
= device
= diskdevice
= NULL
;
117 while ((c
= getopt_long (argc
, argv
, short_opts
, long_opts
, NULL
))
124 what
= DELETE
; break;
144 fprintf(stderr
, "unknown option\n");
148 if (optind
== argc
-2) {
149 device
= argv
[optind
];
150 diskdevice
= argv
[optind
+1];
151 } else if (optind
== argc
-1) {
152 diskdevice
= device
= argv
[optind
];
154 fprintf(stderr
, "call: partx -opts [device] wholedisk\n");
158 fd
= open(diskdevice
, O_RDONLY
);
164 /* remove the indicated partitions from the kernel partition tables */
165 if (what
== DELETE
) {
166 if (device
!= diskdevice
) {
168 "call: partx -d [--nr M-N] wholedisk\n");
175 while (upper
== 0 || lower
<= upper
) {
183 a
.op
= BLKPG_DEL_PARTITION
;
185 a
.datalen
= sizeof(pt
);
187 if (ioctl(fd
, BLKPG
, &a
) == -1)
192 "error deleting partition %d: ",
193 "error deleting partitions %d-%d: ");
195 EBUSY: mounted or in use as swap
196 ENXIO: no such nonempty partition
197 EINVAL: not wholedisk, or bad pno
198 EACCES/EPERM: permission denied
200 if (err
&& err
!= EBUSY
&& err
!= ENXIO
) {
204 if (err
== 0 && verbose
)
205 printf("deleted partition %d\n", lower
);
209 "error deleting partition %d: ",
210 "error deleting partitions %d-%d: ");
214 if (device
!= diskdevice
) {
215 fd2
= open(device
, O_RDONLY
);
224 if (ioctl(fd
, HDIO_GETGEO
, &g
)) {
225 perror("HDIO_GETGEO");
229 fprintf(stderr
, "last arg is not the whole disk\n");
230 fprintf(stderr
, "call: partx -opts device wholedisk\n");
234 if (ioctl(fd2
, HDIO_GETGEO
, &g
)) {
235 perror("HDIO_GETGEO");
240 if(ioctl(fd2
, BLKGETSIZE
, &size
)) {
241 perror("BLKGETSIZE");
247 printf("device %s: start %d size %d\n",
248 device
, all
.start
, all
.size
);
251 fprintf(stderr
, "That disk slice has size 0\n");
255 all
.size
= 0; /* probably extended partition */
257 /* add the indicated partitions to the kernel partition tables */
260 for (i
= 0; i
< ptct
; i
++) {
262 if (!type
|| !strcmp(type
, ptp
->type
)) {
263 n
= ptp
->fn(fd
, all
, slices
, SIZE(slices
));
264 if (n
>= 0 && verbose
)
265 printf("%s: %d slices\n", ptp
->type
, n
);
266 if (n
> 0 && (verbose
|| what
== LIST
)) {
268 printf("#%2d: %9d-%9d (%9d sectors, %6d MB)\n",
271 slices
[j
].start
+slices
[j
].size
-1,
273 (int)((512 * (long long) slices
[j
].size
)
276 if (n
> 0 && what
== ADD
) {
277 /* test for overlap, as in the case of an
278 extended partition, and reduce size */
279 for (j
=0; j
<n
; j
++) {
280 for (k
=j
+1; k
<n
; k
++) {
281 if (slices
[k
].start
> slices
[j
].start
&&
282 slices
[k
].start
< slices
[j
].start
+
284 slices
[j
].size
= slices
[k
].start
-
287 printf("reduced size of "
288 "partition #%d to %d\n",
294 for (j
=0; j
<n
; j
++) {
296 pt
.start
= 512 * (long long) slices
[j
].start
;
297 pt
.length
= 512 * (long long) slices
[j
].size
;
300 a
.op
= BLKPG_ADD_PARTITION
;
302 a
.datalen
= sizeof(pt
);
304 if (ioctl(fd
, BLKPG
, &a
) == -1) {
307 "error adding partition %d\n",
310 printf("added partition %d\n", lower
+j
);
320 xmalloc (size_t size
) {
327 fprintf(stderr
, "Out of memory\n");
334 * sseek: seek to specified sector
336 #if !defined (__alpha__) && !defined (__ia64__)
337 #include <linux/unistd.h> /* _syscall */
339 _syscall5(int, _llseek
, uint
, fd
, ulong
, hi
, ulong
, lo
,
340 long long *, res
, uint
, wh
);
344 sseek(int fd
, unsigned int secnr
) {
346 in
= ((long long) secnr
<< 9);
349 #if !defined (__alpha__) && !defined (__ia64__)
350 if (_llseek (fd
, in
>>32, in
& 0xffffffff, &out
, SEEK_SET
) != 0
353 if ((out
= lseek(fd
, in
, SEEK_SET
)) != in
)
356 fprintf(stderr
, "llseek error\n");
370 getblock(int fd
, unsigned int secnr
) {
373 for (bp
= blockhead
; bp
; bp
= bp
->next
)
374 if (bp
->secnr
== secnr
)
376 if (sseek(fd
, secnr
))
378 bp
= xmalloc(sizeof(struct block
));
380 bp
->next
= blockhead
;
382 bp
->block
= (char *) xmalloc(1024);
383 if (read(fd
, bp
->block
, 1024) != 1024) {
384 fprintf(stderr
, "read error, sector %d\n", secnr
);
390 /* call with errno and integer m and error message */
391 /* merge to interval m-n */
393 errmerge(int err
, int m
, char *msg1
, char *msg2
) {
394 static int preverr
, firstm
, prevm
;
396 if (err
!= preverr
) {
399 fprintf(stderr
, msg1
, firstm
);
401 fprintf(stderr
, msg2
, firstm
, prevm
);