2006-12-06 17:25:32 -06:00
|
|
|
/* fdisk.c -- Partition table manipulator for Linux.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
|
2012-06-17 11:10:07 -05:00
|
|
|
* Copyright (C) 2012 Davidlohr Bueso <dave@gnu.org>
|
2006-12-06 17:25:32 -06:00
|
|
|
*
|
|
|
|
* This program is free software. You can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation: either version 1 or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
2006-12-06 17:25:35 -06:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <sys/stat.h>
|
2008-01-16 12:53:56 -06:00
|
|
|
#include <sys/time.h>
|
2007-07-06 20:32:31 -05:00
|
|
|
#include <time.h>
|
2008-08-19 06:53:28 -05:00
|
|
|
#include <limits.h>
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2011-01-23 15:51:21 -06:00
|
|
|
#include "xalloc.h"
|
2006-12-06 17:25:43 -06:00
|
|
|
#include "nls.h"
|
2011-01-02 15:58:13 -06:00
|
|
|
#include "rpmatch.h"
|
2007-11-07 12:05:31 -06:00
|
|
|
#include "blkdev.h"
|
2006-12-06 17:25:39 -06:00
|
|
|
#include "common.h"
|
2010-03-09 02:21:35 -06:00
|
|
|
#include "mbsalign.h"
|
2006-12-06 17:25:33 -06:00
|
|
|
#include "fdisk.h"
|
2009-03-11 08:00:21 -05:00
|
|
|
#include "wholedisk.h"
|
2010-12-16 18:28:59 -06:00
|
|
|
#include "pathnames.h"
|
|
|
|
#include "canonicalize.h"
|
2011-08-17 06:21:12 -05:00
|
|
|
#include "strutils.h"
|
2012-04-04 13:02:04 -05:00
|
|
|
#include "closestream.h"
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2013-05-02 08:40:36 -05:00
|
|
|
#include "pt-sun.h" /* to toggle flags */
|
2006-12-06 17:25:37 -06:00
|
|
|
#include "fdisksgilabel.h"
|
2007-06-27 16:49:56 -05:00
|
|
|
#include "fdiskmaclabel.h"
|
2012-04-28 17:02:45 -05:00
|
|
|
#include "fdiskdoslabel.h"
|
2012-05-20 11:11:33 -05:00
|
|
|
#include "fdiskbsdlabel.h"
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:26:54 -06:00
|
|
|
#ifdef HAVE_LINUX_COMPILER_H
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_LINUX_BLKPG_H
|
2006-12-06 17:25:39 -06:00
|
|
|
#include <linux/blkpg.h>
|
|
|
|
#endif
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-09-24 04:30:26 -05:00
|
|
|
|
2012-05-27 14:44:13 -05:00
|
|
|
sector_t get_nr_sects(struct partition *p) {
|
2006-12-06 17:25:35 -06:00
|
|
|
return read4_little_endian(p->size4);
|
|
|
|
}
|
|
|
|
|
2012-05-21 15:28:03 -05:00
|
|
|
char *line_ptr, /* interactive input */
|
2006-12-06 17:25:43 -06:00
|
|
|
line_buffer[LINE_LENGTH];
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-01-22 06:46:55 -06:00
|
|
|
int nowarn = 0; /* no warnings for fdisk -l/-s */
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int user_cylinders, user_heads, user_sectors;
|
2011-07-03 05:01:21 -05:00
|
|
|
|
2013-02-11 09:38:20 -06:00
|
|
|
void toggle_units(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
fdisk_context_set_unit(cxt,
|
|
|
|
fdisk_context_use_cylinders(cxt) ? "sectors" :
|
|
|
|
"cylinders");
|
|
|
|
if (fdisk_context_use_cylinders(cxt))
|
|
|
|
fdisk_info(cxt, _("Changing display/entry units to cylinders (DEPRECATED!)."));
|
|
|
|
else
|
|
|
|
fdisk_info(cxt, _("Changing display/entry units to sectors."));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-23 15:51:20 -06:00
|
|
|
static void __attribute__ ((__noreturn__)) usage(FILE *out)
|
|
|
|
{
|
|
|
|
fprintf(out, _("Usage:\n"
|
|
|
|
" %1$s [options] <disk> change partition table\n"
|
|
|
|
" %1$s [options] -l <disk> list partition table(s)\n"
|
|
|
|
" %1$s -s <partition> give partition size(s) in blocks\n"
|
|
|
|
"\nOptions:\n"
|
|
|
|
" -b <size> sector size (512, 1024, 2048 or 4096)\n"
|
|
|
|
" -c[=<mode>] compatible mode: 'dos' or 'nondos' (default)\n"
|
|
|
|
" -h print this help text\n"
|
|
|
|
" -u[=<unit>] display units: 'cylinders' or 'sectors' (default)\n"
|
|
|
|
" -v print program version\n"
|
|
|
|
" -C <number> specify the number of cylinders\n"
|
|
|
|
" -H <number> specify the number of heads\n"
|
|
|
|
" -S <number> specify the number of sectors per track\n"
|
|
|
|
"\n"), program_invocation_short_name);
|
|
|
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2012-07-25 14:15:35 -05:00
|
|
|
void __attribute__((__noreturn__))
|
|
|
|
fatal(struct fdisk_context *cxt, enum failure why)
|
2012-04-27 06:23:42 -05:00
|
|
|
{
|
2012-05-21 15:28:03 -05:00
|
|
|
close(cxt->dev_fd);
|
2006-12-06 17:25:32 -06:00
|
|
|
switch (why) {
|
|
|
|
case unable_to_read:
|
2012-05-21 15:28:03 -05:00
|
|
|
err(EXIT_FAILURE, _("unable to read %s"), cxt->dev_path);
|
2011-01-23 15:58:14 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
case unable_to_seek:
|
2012-05-21 15:28:03 -05:00
|
|
|
err(EXIT_FAILURE, _("unable to seek on %s"), cxt->dev_path);
|
2011-01-23 15:58:14 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
case unable_to_write:
|
2012-05-21 15:28:03 -05:00
|
|
|
err(EXIT_FAILURE, _("unable to write %s"), cxt->dev_path);
|
2011-01-23 15:58:14 -06:00
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
case ioctl_error:
|
2012-05-21 15:28:03 -05:00
|
|
|
err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), cxt->dev_path);
|
2011-01-23 15:58:14 -06:00
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
default:
|
2011-01-23 15:58:14 -06:00
|
|
|
err(EXIT_FAILURE, _("fatal error"));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
struct partition *
|
|
|
|
get_part_table(int i) {
|
|
|
|
return ptes[i].part_table;
|
|
|
|
}
|
|
|
|
|
2012-09-24 06:24:09 -05:00
|
|
|
void list_partition_types(struct fdisk_context *cxt)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2012-09-24 06:24:09 -05:00
|
|
|
struct fdisk_parttype *types;
|
2013-04-18 07:38:49 -05:00
|
|
|
size_t ntypes = 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-09-24 06:24:09 -05:00
|
|
|
if (!cxt || !cxt->label || !cxt->label->parttypes)
|
|
|
|
return;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-09-24 06:24:09 -05:00
|
|
|
types = cxt->label->parttypes;
|
2013-04-18 07:38:49 -05:00
|
|
|
ntypes = cxt->label->nparttypes;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-09-24 06:24:09 -05:00
|
|
|
if (types[0].typestr == NULL) {
|
|
|
|
/*
|
|
|
|
* Prints in 4 columns in format <hex> <name>
|
|
|
|
*/
|
2013-04-18 07:38:49 -05:00
|
|
|
size_t last[4], done = 0, next = 0, size;
|
|
|
|
int i;
|
2010-03-09 02:21:35 -06:00
|
|
|
|
2013-04-18 07:38:49 -05:00
|
|
|
size = ntypes;
|
|
|
|
if (types[ntypes - 1].name == NULL)
|
|
|
|
size--;
|
2012-09-24 06:24:09 -05:00
|
|
|
|
|
|
|
for (i = 3; i >= 0; i--)
|
|
|
|
last[3 - i] = done += (size + i - done) / (i + 1);
|
|
|
|
i = done = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
#define NAME_WIDTH 15
|
|
|
|
char name[NAME_WIDTH * MB_LEN_MAX];
|
|
|
|
size_t width = NAME_WIDTH;
|
|
|
|
struct fdisk_parttype *t = &types[next];
|
|
|
|
size_t ret;
|
|
|
|
|
2013-04-18 07:38:49 -05:00
|
|
|
if (t->name) {
|
|
|
|
printf("%c%2x ", i ? ' ' : '\n', t->type);
|
|
|
|
ret = mbsalign(_(t->name), name, sizeof(name),
|
|
|
|
&width, MBS_ALIGN_LEFT, 0);
|
2012-09-24 06:24:09 -05:00
|
|
|
|
2013-04-18 07:38:49 -05:00
|
|
|
if (ret == (size_t)-1 || ret >= sizeof(name))
|
|
|
|
printf("%-15.15s", _(t->name));
|
|
|
|
else
|
|
|
|
fputs(name, stdout);
|
|
|
|
}
|
2012-09-24 06:24:09 -05:00
|
|
|
|
|
|
|
next = last[i++] + done;
|
|
|
|
if (i > 3 || next >= last[i]) {
|
|
|
|
i = 0;
|
|
|
|
next = ++done;
|
|
|
|
}
|
|
|
|
} while (done < last[0]);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Prints 1 column in format <idx> <name> <typestr>
|
|
|
|
*/
|
|
|
|
struct fdisk_parttype *t;
|
2013-04-18 07:38:49 -05:00
|
|
|
size_t i;
|
2012-09-24 06:24:09 -05:00
|
|
|
|
2013-04-18 07:38:49 -05:00
|
|
|
for (i = 0, t = types; t && i < ntypes; t++, i++) {
|
|
|
|
if (t->name)
|
|
|
|
printf("%3zu %-30s %s\n", i + 1,
|
|
|
|
t->name, t->typestr);
|
|
|
|
}
|
2012-09-24 06:24:09 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static int
|
|
|
|
test_c(char **m, char *mesg) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int val = 0;
|
|
|
|
if (!*m)
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("You must set"));
|
2006-12-06 17:25:32 -06:00
|
|
|
else {
|
|
|
|
fprintf(stderr, " %s", *m);
|
|
|
|
val = 1;
|
|
|
|
}
|
|
|
|
*m = mesg;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2012-06-17 11:10:33 -05:00
|
|
|
int warn_geometry(struct fdisk_context *cxt)
|
2012-04-28 17:02:45 -05:00
|
|
|
{
|
2006-12-06 17:25:32 -06:00
|
|
|
char *m = NULL;
|
|
|
|
int prev = 0;
|
2006-12-06 17:26:30 -06:00
|
|
|
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SGI)) /* cannot set cylinders etc anyway */
|
2006-12-06 17:26:30 -06:00
|
|
|
return 0;
|
2012-06-17 11:10:33 -05:00
|
|
|
if (!cxt->geom.heads)
|
2006-12-06 17:25:39 -06:00
|
|
|
prev = test_c(&m, _("heads"));
|
2012-06-17 11:10:33 -05:00
|
|
|
if (!cxt->geom.sectors)
|
2006-12-06 17:25:39 -06:00
|
|
|
prev = test_c(&m, _("sectors"));
|
2012-06-17 11:10:33 -05:00
|
|
|
if (!cxt->geom.cylinders)
|
2006-12-06 17:25:39 -06:00
|
|
|
prev = test_c(&m, _("cylinders"));
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!m)
|
|
|
|
return 0;
|
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("%s%s.\nYou can do this from the extra functions menu.\n"),
|
|
|
|
prev ? _(" and ") : " ", m);
|
2006-12-06 17:25:32 -06:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
void warn_limits(struct fdisk_context *cxt)
|
2012-04-28 17:02:45 -05:00
|
|
|
{
|
2012-06-03 13:15:20 -05:00
|
|
|
if (cxt->total_sectors > UINT_MAX && !nowarn) {
|
|
|
|
unsigned long long bytes = cxt->total_sectors * cxt->sector_size;
|
2010-08-23 05:11:26 -05:00
|
|
|
int giga = bytes / 1000000000;
|
2008-08-20 16:27:50 -05:00
|
|
|
int hectogiga = (giga + 50) / 100;
|
|
|
|
|
2008-08-19 06:53:28 -05:00
|
|
|
fprintf(stderr, _("\n"
|
|
|
|
"WARNING: The size of this disk is %d.%d TB (%llu bytes).\n"
|
2008-08-20 16:27:50 -05:00
|
|
|
"DOS partition table format can not be used on drives for volumes\n"
|
2012-06-03 13:15:17 -05:00
|
|
|
"larger than (%llu bytes) for %ld-byte sectors. Use parted(1) and GUID \n"
|
2008-08-19 06:53:28 -05:00
|
|
|
"partition table format (GPT).\n\n"),
|
2008-08-20 16:27:50 -05:00
|
|
|
hectogiga / 10, hectogiga % 10,
|
2010-08-23 05:11:26 -05:00
|
|
|
bytes,
|
2012-06-03 13:15:17 -05:00
|
|
|
(sector_t ) UINT_MAX * cxt->sector_size,
|
|
|
|
cxt->sector_size);
|
2008-08-19 06:53:28 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2013-01-18 09:11:40 -06:00
|
|
|
static void maybe_exit(struct fdisk_context *cxt, int rc, int *asked)
|
2011-01-02 15:58:12 -06:00
|
|
|
{
|
|
|
|
char line[LINE_LENGTH];
|
|
|
|
|
2013-01-18 09:11:40 -06:00
|
|
|
assert(cxt);
|
|
|
|
assert(cxt->label);
|
|
|
|
|
2011-01-02 15:58:12 -06:00
|
|
|
putchar('\n');
|
2011-01-05 09:50:47 -06:00
|
|
|
if (asked)
|
|
|
|
*asked = 0;
|
2011-01-02 15:58:12 -06:00
|
|
|
|
2013-01-18 09:11:40 -06:00
|
|
|
if (fdisk_label_is_changed(cxt->label)) {
|
2011-01-02 15:58:12 -06:00
|
|
|
fprintf(stderr, _("Do you really want to quit? "));
|
|
|
|
|
|
|
|
if (!fgets(line, LINE_LENGTH, stdin) || rpmatch(line) == 1)
|
2013-01-18 09:11:40 -06:00
|
|
|
goto leave;
|
2011-01-05 09:50:47 -06:00
|
|
|
if (asked)
|
|
|
|
*asked = 1;
|
2013-01-18 09:11:40 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
leave:
|
|
|
|
fdisk_free_context(cxt);
|
|
|
|
exit(rc);
|
2011-01-02 15:58:12 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
/* read line; return 0 or first char */
|
2013-01-18 09:11:40 -06:00
|
|
|
int read_line(struct fdisk_context *cxt, int *asked)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2006-12-06 17:25:37 -06:00
|
|
|
line_ptr = line_buffer;
|
2006-12-06 17:25:39 -06:00
|
|
|
if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
|
2013-01-18 09:11:40 -06:00
|
|
|
maybe_exit(cxt, 1, asked);
|
2006-12-06 17:25:32 -06:00
|
|
|
return 0;
|
2006-12-06 17:25:39 -06:00
|
|
|
}
|
2011-01-05 09:50:47 -06:00
|
|
|
if (asked)
|
|
|
|
*asked = 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
while (*line_ptr && !isgraph(*line_ptr))
|
|
|
|
line_ptr++;
|
|
|
|
return *line_ptr;
|
|
|
|
}
|
|
|
|
|
2013-01-18 09:11:40 -06:00
|
|
|
char read_char(struct fdisk_context *cxt, char *mesg)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2006-12-06 17:25:35 -06:00
|
|
|
do {
|
2006-12-06 17:25:32 -06:00
|
|
|
fputs(mesg, stdout);
|
2006-12-06 17:25:44 -06:00
|
|
|
fflush (stdout); /* requested by niles@scyld.com */
|
2013-01-18 09:11:40 -06:00
|
|
|
|
|
|
|
} while (!read_line(cxt, NULL));
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
return *line_ptr;
|
|
|
|
}
|
|
|
|
|
2013-01-18 09:11:40 -06:00
|
|
|
char read_chars(struct fdisk_context *cxt, char *mesg)
|
2006-12-06 17:25:35 -06:00
|
|
|
{
|
2011-01-05 09:50:47 -06:00
|
|
|
int rc, asked = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
fputs(mesg, stdout);
|
|
|
|
fflush (stdout); /* niles@scyld.com */
|
2013-01-18 09:11:40 -06:00
|
|
|
rc = read_line(cxt, &asked);
|
2011-01-05 09:50:47 -06:00
|
|
|
} while (asked);
|
|
|
|
|
|
|
|
if (!rc) {
|
2006-12-06 17:25:35 -06:00
|
|
|
*line_ptr = '\n';
|
2006-12-06 17:25:37 -06:00
|
|
|
line_ptr[1] = 0;
|
|
|
|
}
|
|
|
|
return *line_ptr;
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2012-09-25 03:23:36 -05:00
|
|
|
struct fdisk_parttype *read_partition_type(struct fdisk_context *cxt)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2012-09-25 03:23:36 -05:00
|
|
|
if (!cxt || !cxt->label || !cxt->label->nparttypes)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
do {
|
|
|
|
size_t sz;
|
|
|
|
|
|
|
|
if (cxt->label->parttypes[0].typestr)
|
2013-01-18 09:11:40 -06:00
|
|
|
read_chars(cxt, _("Partition type (type L to list all types): "));
|
2012-09-25 03:23:36 -05:00
|
|
|
else
|
2013-01-18 09:11:40 -06:00
|
|
|
read_chars(cxt, _("Hex code (type L to list all codes): "));
|
2012-09-25 03:23:36 -05:00
|
|
|
|
|
|
|
sz = strlen(line_ptr);
|
|
|
|
if (!sz || line_ptr[sz - 1] != '\n' || sz == 1)
|
|
|
|
continue;
|
|
|
|
line_ptr[sz - 1] = '\0';
|
|
|
|
|
|
|
|
if (tolower(*line_ptr) == 'l')
|
|
|
|
list_partition_types(cxt);
|
|
|
|
else
|
|
|
|
return fdisk_parse_parttype(cxt, line_ptr);
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
return NULL;
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
|
|
|
|
2012-09-25 03:23:36 -05:00
|
|
|
|
2012-05-06 07:10:18 -05:00
|
|
|
unsigned int
|
2012-06-03 13:15:17 -05:00
|
|
|
read_int_with_suffix(struct fdisk_context *cxt,
|
|
|
|
unsigned int low, unsigned int dflt, unsigned int high,
|
2012-01-15 23:36:12 -06:00
|
|
|
unsigned int base, char *mesg, int *is_suffix_used)
|
2006-12-06 17:25:33 -06:00
|
|
|
{
|
2012-01-15 23:36:12 -06:00
|
|
|
unsigned int res;
|
2006-12-06 17:25:37 -06:00
|
|
|
int default_ok = 1;
|
2012-01-15 23:36:13 -06:00
|
|
|
int absolute = 0;
|
2006-12-06 17:25:37 -06:00
|
|
|
static char *ms = NULL;
|
2011-08-01 08:19:53 -05:00
|
|
|
static size_t mslen = 0;
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
if (!ms || strlen(mesg)+100 > mslen) {
|
|
|
|
mslen = strlen(mesg)+200;
|
2011-01-23 15:51:21 -06:00
|
|
|
ms = xrealloc(ms,mslen);
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (dflt < low || dflt > high)
|
|
|
|
default_ok = 0;
|
|
|
|
|
|
|
|
if (default_ok)
|
2006-12-06 17:26:12 -06:00
|
|
|
snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
|
2006-12-06 17:25:46 -06:00
|
|
|
mesg, low, high, dflt);
|
2006-12-06 17:25:37 -06:00
|
|
|
else
|
2006-12-06 17:26:12 -06:00
|
|
|
snprintf(ms, mslen, "%s (%u-%u): ",
|
2006-12-06 17:25:46 -06:00
|
|
|
mesg, low, high);
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
while (1) {
|
2006-12-06 17:25:37 -06:00
|
|
|
int use_default = default_ok;
|
|
|
|
|
|
|
|
/* ask question and read answer */
|
2013-01-18 09:11:40 -06:00
|
|
|
while (read_chars(cxt, ms) != '\n' && !isdigit(*line_ptr)
|
2006-12-06 17:25:37 -06:00
|
|
|
&& *line_ptr != '-' && *line_ptr != '+')
|
|
|
|
continue;
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
if (*line_ptr == '+' || *line_ptr == '-') {
|
2006-12-06 17:26:08 -06:00
|
|
|
int minus = (*line_ptr == '-');
|
2007-12-12 18:06:44 -06:00
|
|
|
int suflen;
|
2006-12-06 17:26:08 -06:00
|
|
|
|
2012-01-15 23:36:13 -06:00
|
|
|
absolute = 0;
|
2012-01-15 23:36:12 -06:00
|
|
|
res = atoi(line_ptr + 1);
|
2006-12-06 17:26:08 -06:00
|
|
|
|
2007-12-12 18:06:44 -06:00
|
|
|
while (isdigit(*++line_ptr))
|
2006-12-06 17:25:33 -06:00
|
|
|
use_default = 0;
|
2006-12-06 17:26:08 -06:00
|
|
|
|
2011-05-09 09:00:36 -05:00
|
|
|
while (isspace(*line_ptr))
|
|
|
|
line_ptr++;
|
|
|
|
|
2007-12-12 18:06:44 -06:00
|
|
|
suflen = strlen(line_ptr) - 1;
|
|
|
|
|
|
|
|
while(isspace(*(line_ptr + suflen)))
|
|
|
|
*(line_ptr + suflen--) = '\0';
|
|
|
|
|
|
|
|
if ((*line_ptr == 'C' || *line_ptr == 'c') &&
|
|
|
|
*(line_ptr + 1) == '\0') {
|
|
|
|
/*
|
|
|
|
* Cylinders
|
|
|
|
*/
|
2013-02-11 09:38:20 -06:00
|
|
|
if (fdisk_context_use_cylinders(cxt))
|
2012-06-17 11:10:33 -05:00
|
|
|
res *= cxt->geom.heads * cxt->geom.sectors;
|
2008-11-13 16:08:34 -06:00
|
|
|
} else if (*line_ptr &&
|
|
|
|
*(line_ptr + 1) == 'B' &&
|
2007-12-12 18:06:44 -06:00
|
|
|
*(line_ptr + 2) == '\0') {
|
|
|
|
/*
|
|
|
|
* 10^N
|
|
|
|
*/
|
|
|
|
if (*line_ptr == 'K')
|
2006-12-06 17:26:08 -06:00
|
|
|
absolute = 1000;
|
2007-12-12 18:06:44 -06:00
|
|
|
else if (*line_ptr == 'M')
|
2006-12-06 17:26:08 -06:00
|
|
|
absolute = 1000000;
|
2007-12-12 18:06:44 -06:00
|
|
|
else if (*line_ptr == 'G')
|
2006-12-06 17:26:08 -06:00
|
|
|
absolute = 1000000000;
|
2007-12-12 18:06:44 -06:00
|
|
|
else
|
|
|
|
absolute = -1;
|
2008-11-13 16:08:34 -06:00
|
|
|
} else if (*line_ptr &&
|
|
|
|
*(line_ptr + 1) == '\0') {
|
2007-12-12 18:06:44 -06:00
|
|
|
/*
|
|
|
|
* 2^N
|
|
|
|
*/
|
|
|
|
if (*line_ptr == 'K')
|
|
|
|
absolute = 1 << 10;
|
|
|
|
else if (*line_ptr == 'M')
|
|
|
|
absolute = 1 << 20;
|
|
|
|
else if (*line_ptr == 'G')
|
|
|
|
absolute = 1 << 30;
|
|
|
|
else
|
|
|
|
absolute = -1;
|
|
|
|
} else if (*line_ptr != '\0')
|
|
|
|
absolute = -1;
|
|
|
|
|
|
|
|
if (absolute == -1) {
|
|
|
|
printf(_("Unsupported suffix: '%s'.\n"), line_ptr);
|
|
|
|
printf(_("Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte)\n"
|
|
|
|
" 2^N: K (KibiByte), M (MebiByte), G (GibiByte)\n"));
|
|
|
|
continue;
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
2007-12-12 18:06:44 -06:00
|
|
|
|
2012-01-15 23:36:12 -06:00
|
|
|
if (absolute && res) {
|
2006-12-06 17:26:08 -06:00
|
|
|
unsigned long long bytes;
|
|
|
|
unsigned long unit;
|
|
|
|
|
2012-01-15 23:36:12 -06:00
|
|
|
bytes = (unsigned long long) res * absolute;
|
2013-02-11 09:38:20 -06:00
|
|
|
unit = cxt->sector_size * fdisk_context_get_units_per_sector(cxt);
|
2006-12-06 17:26:08 -06:00
|
|
|
bytes += unit/2; /* round */
|
|
|
|
bytes /= unit;
|
2012-01-15 23:36:12 -06:00
|
|
|
res = bytes;
|
2006-12-06 17:26:08 -06:00
|
|
|
}
|
|
|
|
if (minus)
|
2012-01-15 23:36:12 -06:00
|
|
|
res = -res;
|
|
|
|
res += base;
|
2006-12-06 17:25:37 -06:00
|
|
|
} else {
|
2012-01-15 23:36:12 -06:00
|
|
|
res = atoi(line_ptr);
|
2006-12-06 17:25:37 -06:00
|
|
|
while (isdigit(*line_ptr)) {
|
2006-12-06 17:25:33 -06:00
|
|
|
line_ptr++;
|
|
|
|
use_default = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-01-15 23:36:13 -06:00
|
|
|
if (use_default) {
|
|
|
|
printf(_("Using default value %u\n"), dflt);
|
|
|
|
return dflt;
|
|
|
|
}
|
2012-01-15 23:36:12 -06:00
|
|
|
if (res >= low && res <= high)
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
2006-12-06 17:25:33 -06:00
|
|
|
else
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Value out of range.\n"));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2012-01-15 23:36:13 -06:00
|
|
|
if (is_suffix_used)
|
|
|
|
*is_suffix_used = absolute > 0;
|
2012-01-15 23:36:12 -06:00
|
|
|
return res;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2009-11-04 07:30:31 -06:00
|
|
|
/*
|
|
|
|
* Print the message MESG, then read an integer in LOW..HIGH.
|
|
|
|
* If the user hits Enter, DFLT is returned, provided that is in LOW..HIGH.
|
|
|
|
* Answers like +10 are interpreted as offsets from BASE.
|
|
|
|
*
|
|
|
|
* There is no default if DFLT is not between LOW and HIGH.
|
|
|
|
*/
|
|
|
|
unsigned int
|
2012-06-03 13:15:17 -05:00
|
|
|
read_int(struct fdisk_context *cxt,
|
|
|
|
unsigned int low, unsigned int dflt, unsigned int high,
|
2009-11-04 07:30:31 -06:00
|
|
|
unsigned int base, char *mesg)
|
|
|
|
{
|
2012-06-03 13:15:17 -05:00
|
|
|
return read_int_with_suffix(cxt, low, dflt, high, base, mesg, NULL);
|
2009-11-04 07:30:31 -06:00
|
|
|
}
|
|
|
|
|
2012-12-11 08:08:06 -06:00
|
|
|
static void toggle_dos_compatibility_flag(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
struct fdisk_label *lb = fdisk_context_get_label(cxt, "dos");
|
|
|
|
int flag;
|
|
|
|
|
|
|
|
if (!lb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
flag = !fdisk_dos_is_compatible(lb);
|
|
|
|
|
|
|
|
if (flag)
|
2010-06-16 03:52:20 -05:00
|
|
|
printf(_("DOS Compatibility flag is set (DEPRECATED!)\n"));
|
2009-11-03 04:28:55 -06:00
|
|
|
else
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("DOS Compatibility flag is not set\n"));
|
2009-11-03 04:28:55 -06:00
|
|
|
|
2012-12-11 08:08:06 -06:00
|
|
|
fdisk_dos_enable_compatible(lb, flag);
|
|
|
|
|
|
|
|
if (fdisk_is_disklabel(cxt, DOS))
|
|
|
|
fdisk_reset_alignment(cxt);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-07-23 11:15:57 -05:00
|
|
|
static void delete_partition(struct fdisk_context *cxt, int partnum)
|
2011-11-14 07:47:19 -06:00
|
|
|
{
|
2012-07-23 11:15:57 -05:00
|
|
|
if (partnum < 0 || warn_geometry(cxt))
|
2011-12-15 13:02:46 -06:00
|
|
|
return;
|
|
|
|
|
2012-10-07 09:33:37 -05:00
|
|
|
if (fdisk_delete_partition(cxt, partnum) != 0)
|
|
|
|
printf(_("Could not delete partition %d\n"), partnum + 1);
|
|
|
|
else
|
|
|
|
printf(_("Partition %d is deleted\n"), partnum + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-09-26 06:30:44 -05:00
|
|
|
static void change_partition_type(struct fdisk_context *cxt)
|
2012-06-03 13:15:17 -05:00
|
|
|
{
|
2013-03-05 08:39:12 -06:00
|
|
|
size_t i;
|
2012-09-25 03:23:36 -05:00
|
|
|
struct fdisk_parttype *t, *org_t;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-01-22 06:46:55 -06:00
|
|
|
assert(cxt);
|
|
|
|
assert(cxt->label);
|
|
|
|
|
2013-03-05 08:39:12 -06:00
|
|
|
if (fdisk_ask_partnum(cxt, &i, FALSE))
|
2006-12-06 17:26:03 -06:00
|
|
|
return;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-09-25 05:12:28 -05:00
|
|
|
org_t = t = fdisk_get_partition_type(cxt, i);
|
|
|
|
if (!t)
|
2013-03-05 08:39:12 -06:00
|
|
|
printf(_("Partition %zu does not exist yet!\n"), i + 1);
|
2012-09-25 05:12:28 -05:00
|
|
|
|
2012-09-26 06:30:44 -05:00
|
|
|
else do {
|
2012-09-25 03:23:36 -05:00
|
|
|
t = read_partition_type(cxt);
|
|
|
|
if (!t)
|
|
|
|
continue;
|
|
|
|
|
2012-09-26 06:30:44 -05:00
|
|
|
if (fdisk_set_partition_type(cxt, i, t) == 0) {
|
|
|
|
printf (_("Changed type of partition '%s' to '%s'\n"),
|
|
|
|
org_t ? org_t->name : _("Unknown"),
|
|
|
|
t ? t->name : _("Unknown"));
|
|
|
|
} else {
|
2013-03-05 08:39:12 -06:00
|
|
|
printf (_("Type of partition %zu is unchanged: %s\n"),
|
2012-09-26 06:30:44 -05:00
|
|
|
i + 1,
|
|
|
|
org_t ? org_t->name : _("Unknown"));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2012-09-26 06:30:44 -05:00
|
|
|
break;
|
|
|
|
} while (1);
|
2012-09-25 03:23:36 -05:00
|
|
|
|
|
|
|
fdisk_free_parttype(t);
|
|
|
|
fdisk_free_parttype(org_t);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2012-05-27 14:44:04 -05:00
|
|
|
list_disk_geometry(struct fdisk_context *cxt) {
|
2012-06-03 13:15:20 -05:00
|
|
|
unsigned long long bytes = cxt->total_sectors * cxt->sector_size;
|
2006-12-06 17:26:03 -06:00
|
|
|
long megabytes = bytes/1000000;
|
|
|
|
|
|
|
|
if (megabytes < 10000)
|
2012-07-26 09:04:26 -05:00
|
|
|
printf(_("\nDisk %s: %ld MB, %lld bytes"),
|
2012-05-21 15:28:03 -05:00
|
|
|
cxt->dev_path, megabytes, bytes);
|
2008-08-20 16:27:50 -05:00
|
|
|
else {
|
|
|
|
long hectomega = (megabytes + 50) / 100;
|
2012-07-26 09:04:26 -05:00
|
|
|
printf(_("\nDisk %s: %ld.%ld GB, %llu bytes"),
|
2012-05-21 15:28:03 -05:00
|
|
|
cxt->dev_path, hectomega / 10, hectomega % 10, bytes);
|
2008-08-20 16:27:50 -05:00
|
|
|
}
|
2012-07-26 09:04:26 -05:00
|
|
|
printf(_(", %llu sectors\n"), cxt->total_sectors);
|
2013-05-02 04:49:28 -05:00
|
|
|
|
|
|
|
if (is_dos_compatible(cxt) || fdisk_is_disklabel(cxt, SUN))
|
|
|
|
printf(_("Geometry: %d heads, %llu sectors/track, %llu cylinders\n"),
|
2012-07-26 09:04:27 -05:00
|
|
|
cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);
|
2013-05-02 04:49:28 -05:00
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
printf(_("Units = %s of %d * %ld = %ld bytes\n"),
|
2013-02-11 09:38:20 -06:00
|
|
|
fdisk_context_get_unit(cxt, PLURAL),
|
|
|
|
fdisk_context_get_units_per_sector(cxt),
|
|
|
|
cxt->sector_size,
|
|
|
|
fdisk_context_get_units_per_sector(cxt) * cxt->sector_size);
|
2009-10-29 05:25:59 -05:00
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
printf(_("Sector size (logical/physical): %lu bytes / %lu bytes\n"),
|
|
|
|
cxt->sector_size, cxt->phy_sector_size);
|
2010-02-04 08:02:16 -06:00
|
|
|
printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"),
|
2012-06-03 13:15:17 -05:00
|
|
|
cxt->min_io_size, cxt->io_size);
|
|
|
|
if (cxt->alignment_offset)
|
|
|
|
printf(_("Alignment offset: %lu bytes\n"), cxt->alignment_offset);
|
2012-12-04 07:58:55 -06:00
|
|
|
if (fdisk_dev_has_disklabel(cxt))
|
|
|
|
printf(_("Disk label type: %s\n"), cxt->label->name);
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, DOS))
|
2012-06-17 11:10:07 -05:00
|
|
|
dos_print_mbr_id(cxt);
|
2007-07-06 20:32:31 -05:00
|
|
|
printf("\n");
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
|
|
|
|
fdisk: add GPT support
This patch allows fdisk to handle GUID partition tables, based on the latest UEFI specifications
version 2.3.1, from June 27th, 2012. The following operations are supported:
- Probing (detects both protective and hybrid MBRs)
- Writing to disk
- Listing used partitions
- Adding partitions
- Deleting partitions
- Data integrity verifications (for both headers and partitions).
A few considerations:
- Currently we do not fix invalid primary headers -- we just abort!
- Header checksums are updated upon every change (ie: add/delete partitions), this allows us
to mathematically verify the changes on-the-fly, and not only when writing to disk, like
most other related tools do.
- We are extremly picky when writing to disk, any error aborts the opeartion.
- When creating a new partition, the following GUIDs are available:
http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
For test cases, the gpt.img from libblkid tests, scsi_debug and my own hard drive (/dev/sda) were used.
For the image, all operations were tested successfully, and for /dev/sda all except write, which
was not tested - hey, I'm not suicidal!
[kzak@redhat.com: - add get/set partition type functions
- use unified on strings based table for partition types
- add partition type to table list function]
Tested-and-reviewed-by: Petr Uzel <petr.uzel@suse.cz>
Signed-off-by: Davidlohr Bueso <dave@gnu.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
2012-09-27 02:50:27 -05:00
|
|
|
static void list_table(struct fdisk_context *cxt, int xtra)
|
|
|
|
{
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SGI)) {
|
2012-05-27 14:44:04 -05:00
|
|
|
sgi_list_table(cxt, xtra);
|
2006-12-06 17:25:37 -06:00
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-05-27 14:44:04 -05:00
|
|
|
list_disk_geometry(cxt);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2013-04-30 04:57:30 -05:00
|
|
|
if (fdisk_is_disklabel(cxt, OSF))
|
2012-05-27 14:44:04 -05:00
|
|
|
xbsd_print_disklabel(cxt, xtra);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2013-04-30 04:57:30 -05:00
|
|
|
else if (fdisk_is_disklabel(cxt, DOS))
|
2013-01-21 05:01:44 -06:00
|
|
|
dos_list_table(cxt, xtra);
|
2013-04-30 04:57:30 -05:00
|
|
|
else
|
|
|
|
fdisk_list_disklabel(cxt);
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-07-24 02:54:52 -05:00
|
|
|
static void verify(struct fdisk_context *cxt)
|
|
|
|
{
|
2012-06-17 11:10:33 -05:00
|
|
|
if (warn_geometry(cxt))
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
|
2012-07-24 02:54:52 -05:00
|
|
|
fdisk_verify_disklabel(cxt);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
static void new_partition(struct fdisk_context *cxt)
|
2012-05-06 07:10:18 -05:00
|
|
|
{
|
2013-01-18 04:43:56 -06:00
|
|
|
assert(cxt);
|
|
|
|
assert(cxt->label);
|
|
|
|
|
2012-07-24 02:34:22 -05:00
|
|
|
if (warn_geometry(cxt))
|
2006-12-06 17:25:49 -06:00
|
|
|
return;
|
|
|
|
|
2013-01-28 09:16:11 -06:00
|
|
|
fdisk_add_partition(cxt, NULL);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-07-23 11:47:42 -05:00
|
|
|
static void write_table(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
int rc;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-07-23 11:47:42 -05:00
|
|
|
rc = fdisk_write_disklabel(cxt);
|
|
|
|
if (rc)
|
|
|
|
err(EXIT_FAILURE, _("cannot write disk label"));
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("The partition table has been altered!\n\n"));
|
2012-05-27 14:44:04 -05:00
|
|
|
reread_partition_table(cxt, 1);
|
2006-12-06 17:25:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-05-27 14:44:04 -05:00
|
|
|
reread_partition_table(struct fdisk_context *cxt, int leave) {
|
2006-12-06 17:25:41 -06:00
|
|
|
int i;
|
2007-09-03 17:10:16 -05:00
|
|
|
struct stat statbuf;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-05-21 15:28:03 -05:00
|
|
|
i = fstat(cxt->dev_fd, &statbuf);
|
2007-09-03 17:10:16 -05:00
|
|
|
if (i == 0 && S_ISBLK(statbuf.st_mode)) {
|
|
|
|
sync();
|
2008-07-23 17:46:05 -05:00
|
|
|
#ifdef BLKRRPART
|
|
|
|
printf(_("Calling ioctl() to re-read partition table.\n"));
|
2012-05-21 15:28:03 -05:00
|
|
|
i = ioctl(cxt->dev_fd, BLKRRPART);
|
2008-07-23 17:46:05 -05:00
|
|
|
#else
|
|
|
|
errno = ENOSYS;
|
|
|
|
i = 1;
|
|
|
|
#endif
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (i) {
|
2011-09-22 05:12:37 -05:00
|
|
|
printf(_("\nWARNING: Re-reading the partition table failed with error %d: %m.\n"
|
2008-09-16 06:08:12 -05:00
|
|
|
"The kernel still uses the old table. The new table will be used at\n"
|
|
|
|
"the next reboot or after you run partprobe(8) or kpartx(8)\n"),
|
2011-09-22 05:12:37 -05:00
|
|
|
errno);
|
2006-12-06 17:25:49 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:41 -06:00
|
|
|
if (leave) {
|
2012-05-21 15:28:03 -05:00
|
|
|
if (fsync(cxt->dev_fd) || close(cxt->dev_fd)) {
|
2006-12-06 17:26:30 -06:00
|
|
|
fprintf(stderr, _("\nError closing file\n"));
|
|
|
|
exit(1);
|
|
|
|
}
|
2006-12-06 17:25:41 -06:00
|
|
|
|
|
|
|
printf(_("Syncing disks.\n"));
|
|
|
|
sync();
|
|
|
|
exit(!!i);
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_PER_LINE 16
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2012-06-03 13:15:17 -05:00
|
|
|
print_buffer(struct fdisk_context *cxt, unsigned char pbuffer[]) {
|
2011-08-01 08:19:53 -05:00
|
|
|
unsigned int i, l;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
for (i = 0, l = 0; i < cxt->sector_size; i++, l++) {
|
2006-12-06 17:25:32 -06:00
|
|
|
if (l == 0)
|
|
|
|
printf("0x%03X:", i);
|
2007-05-30 10:10:43 -05:00
|
|
|
printf(" %02X", pbuffer[i]);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (l == MAX_PER_LINE - 1) {
|
|
|
|
printf("\n");
|
|
|
|
l = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (l > 0)
|
|
|
|
printf("\n");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
static void print_raw(struct fdisk_context *cxt)
|
|
|
|
{
|
2013-01-22 06:46:55 -06:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
assert(cxt);
|
|
|
|
assert(cxt->label);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-06-03 13:15:17 -05:00
|
|
|
printf(_("Device: %s\n"), cxt->dev_path);
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SUN) ||
|
|
|
|
fdisk_is_disklabel(cxt, SGI) ||
|
|
|
|
fdisk_is_disklabel(cxt, GPT))
|
2012-07-23 07:24:25 -05:00
|
|
|
print_buffer(cxt, cxt->firstsector);
|
2013-01-22 06:46:55 -06:00
|
|
|
|
2013-06-12 10:32:03 -05:00
|
|
|
else if (fdisk_is_disklabel(cxt, DOS)) {
|
|
|
|
for (i = 3; i < cxt->label->nparts_max; i++)
|
2012-06-03 13:15:17 -05:00
|
|
|
print_buffer(cxt, ptes[i].sectorbuffer);
|
2013-06-12 10:32:03 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-05-21 15:28:03 -05:00
|
|
|
static void __attribute__ ((__noreturn__)) handle_quit(struct fdisk_context *cxt)
|
2012-05-20 11:11:21 -05:00
|
|
|
{
|
2012-05-21 15:28:03 -05:00
|
|
|
fdisk_free_context(cxt);
|
2012-05-20 11:11:21 -05:00
|
|
|
printf("\n");
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2012-05-27 14:44:04 -05:00
|
|
|
expert_command_prompt(struct fdisk_context *cxt)
|
2011-11-11 04:12:08 -06:00
|
|
|
{
|
2006-12-06 17:25:43 -06:00
|
|
|
char c;
|
2013-03-05 08:39:12 -06:00
|
|
|
size_t n;
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2013-01-22 06:46:55 -06:00
|
|
|
assert(cxt);
|
|
|
|
|
2013-05-02 04:23:25 -05:00
|
|
|
fdisk_context_enable_details(cxt, 1);
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
while(1) {
|
2013-01-22 06:46:55 -06:00
|
|
|
assert(cxt->label);
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
putchar('\n');
|
2013-01-18 09:11:40 -06:00
|
|
|
c = tolower(read_char(cxt, _("Expert command (m for help): ")));
|
2006-12-06 17:25:43 -06:00
|
|
|
switch (c) {
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'a':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SUN))
|
2013-02-22 08:34:04 -06:00
|
|
|
fdisk_sun_set_alt_cyl(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'b':
|
2013-03-05 08:39:12 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, DOS) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
dos_move_begin(cxt, n);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'c':
|
2012-12-03 08:32:16 -06:00
|
|
|
user_cylinders = read_int(cxt, 1, cxt->geom.cylinders, 1048576, 0,
|
2006-12-06 17:25:43 -06:00
|
|
|
_("Number of cylinders"));
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_geometry(cxt, user_cylinders, user_heads, user_sectors);
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SUN))
|
2013-02-22 08:34:04 -06:00
|
|
|
fdisk_sun_set_ncyl(cxt, cxt->geom.cylinders);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'd':
|
2012-06-03 13:15:17 -05:00
|
|
|
print_raw(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'e':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SGI))
|
2006-12-06 17:25:37 -06:00
|
|
|
sgi_set_xcyl();
|
2012-11-25 22:25:49 -06:00
|
|
|
else if (fdisk_is_disklabel(cxt, SUN))
|
2013-02-22 08:34:04 -06:00
|
|
|
fdisk_sun_set_xcyl(cxt);
|
2006-12-06 17:25:56 -06:00
|
|
|
else
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, DOS))
|
2013-01-21 05:25:30 -06:00
|
|
|
dos_list_table_expert(cxt, 1);
|
2006-12-06 17:25:37 -06:00
|
|
|
break;
|
2006-12-06 17:25:43 -06:00
|
|
|
case 'f':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, DOS))
|
2013-01-22 06:46:55 -06:00
|
|
|
dos_fix_partition_table_order(cxt);
|
2006-12-06 17:25:43 -06:00
|
|
|
break;
|
2006-12-06 17:25:37 -06:00
|
|
|
case 'g':
|
2012-07-24 07:15:08 -05:00
|
|
|
fdisk_create_disklabel(cxt, "sgi");
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'h':
|
2012-12-03 08:32:16 -06:00
|
|
|
user_heads = read_int(cxt, 1, cxt->geom.heads, 256, 0,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Number of heads"));
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_geometry(cxt, user_cylinders, user_heads, user_sectors);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'i':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SUN))
|
2013-02-22 08:34:04 -06:00
|
|
|
fdisk_sun_set_ilfact(cxt);
|
2012-11-25 22:25:49 -06:00
|
|
|
else if (fdisk_is_disklabel(cxt, DOS))
|
2012-06-17 11:10:07 -05:00
|
|
|
dos_set_mbr_id(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'o':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SUN))
|
2013-02-22 08:34:04 -06:00
|
|
|
fdisk_sun_set_rspeed(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'p':
|
2013-05-15 07:07:14 -05:00
|
|
|
list_table(cxt, 1);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'q':
|
2012-05-21 15:28:03 -05:00
|
|
|
handle_quit(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'r':
|
2013-05-02 04:23:25 -05:00
|
|
|
fdisk_context_enable_details(cxt, 0);
|
2006-12-06 17:25:35 -06:00
|
|
|
return;
|
|
|
|
case 's':
|
2012-12-03 08:32:16 -06:00
|
|
|
user_sectors = read_int(cxt, 1, cxt->geom.sectors, 63, 0,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Number of sectors"));
|
2012-12-11 08:08:06 -06:00
|
|
|
if (is_dos_compatible(cxt))
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("Warning: setting "
|
2006-12-06 17:25:35 -06:00
|
|
|
"sector offset for DOS "
|
2012-07-26 09:04:25 -05:00
|
|
|
"compatibility\n"));
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_geometry(cxt, user_cylinders, user_heads, user_sectors);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2013-05-15 06:33:24 -05:00
|
|
|
case 'u':
|
|
|
|
if (fdisk_is_disklabel(cxt, GPT) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
fdisk_gpt_partition_set_uuid(cxt, n);
|
|
|
|
break;
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'v':
|
2012-06-03 13:15:17 -05:00
|
|
|
verify(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'w':
|
2012-05-27 14:44:07 -05:00
|
|
|
write_table(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'y':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SUN))
|
2013-02-22 08:34:04 -06:00
|
|
|
fdisk_sun_set_pcylcount(cxt);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
default:
|
2013-05-17 08:11:11 -05:00
|
|
|
print_fdisk_menu(cxt);
|
|
|
|
break;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-20 07:42:10 -06:00
|
|
|
static int is_ide_cdrom_or_tape(char *device)
|
|
|
|
{
|
|
|
|
int fd, ret;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-02-01 06:42:08 -06:00
|
|
|
if ((fd = open(device, O_RDONLY)) < 0)
|
2006-12-06 17:25:49 -06:00
|
|
|
return 0;
|
2011-12-20 07:42:10 -06:00
|
|
|
ret = blkdev_is_cdrom(fd);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2011-12-20 07:42:10 -06:00
|
|
|
close(fd);
|
|
|
|
return ret;
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2011-12-15 13:02:41 -06:00
|
|
|
/* Print disk geometry and partition table of a specified device (-l option) */
|
2012-12-11 07:41:57 -06:00
|
|
|
static void print_partition_table_from_option(struct fdisk_context *cxt,
|
|
|
|
char *device, unsigned long sector_size)
|
2011-12-15 13:02:40 -06:00
|
|
|
{
|
2012-12-11 07:41:57 -06:00
|
|
|
if (fdisk_context_assign_device(cxt, device, 1) != 0) /* read-only */
|
2012-07-15 03:39:57 -05:00
|
|
|
err(EXIT_FAILURE, _("cannot open %s"), device);
|
2012-05-21 15:28:03 -05:00
|
|
|
|
2012-07-23 03:11:08 -05:00
|
|
|
if (sector_size) /* passed -b option, override autodiscovery */
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_sector_size(cxt, sector_size);
|
2012-07-23 03:11:08 -05:00
|
|
|
|
2012-07-23 06:57:58 -05:00
|
|
|
if (user_cylinders || user_heads || user_sectors)
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_geometry(cxt, user_cylinders,
|
2012-07-23 03:11:08 -05:00
|
|
|
user_heads, user_sectors);
|
2012-07-23 04:08:26 -05:00
|
|
|
|
2013-03-11 09:51:22 -05:00
|
|
|
if (fdisk_dev_has_disklabel(cxt))
|
2012-05-27 14:44:04 -05:00
|
|
|
list_table(cxt, 0);
|
2013-03-11 09:51:22 -05:00
|
|
|
else
|
|
|
|
list_disk_geometry(cxt);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:16 -06:00
|
|
|
/*
|
|
|
|
* for fdisk -l:
|
|
|
|
* try all things in /proc/partitions that look like a full disk
|
|
|
|
*/
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2012-12-11 07:41:57 -06:00
|
|
|
print_all_partition_table_from_option(struct fdisk_context *cxt,
|
|
|
|
unsigned long sector_size)
|
2011-12-15 13:02:41 -06:00
|
|
|
{
|
2006-12-06 17:25:41 -06:00
|
|
|
FILE *procpt;
|
2012-07-09 15:26:27 -05:00
|
|
|
char line[128 + 1], ptname[128 + 1], devname[256];
|
2008-11-13 08:37:22 -06:00
|
|
|
int ma, mi;
|
|
|
|
unsigned long long sz;
|
2006-12-06 17:25:41 -06:00
|
|
|
|
2010-12-16 18:28:59 -06:00
|
|
|
procpt = fopen(_PATH_PROC_PARTITIONS, "r");
|
2006-12-06 17:25:41 -06:00
|
|
|
if (procpt == NULL) {
|
2010-12-16 18:28:59 -06:00
|
|
|
fprintf(stderr, _("cannot open %s\n"), _PATH_PROC_PARTITIONS);
|
2006-12-06 17:25:41 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (fgets(line, sizeof(line), procpt)) {
|
2009-04-29 07:24:45 -05:00
|
|
|
if (sscanf (line, " %d %d %llu %128[^\n ]",
|
2006-12-06 17:25:41 -06:00
|
|
|
&ma, &mi, &sz, ptname) != 4)
|
|
|
|
continue;
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(devname, sizeof(devname), "/dev/%s", ptname);
|
2010-12-16 18:28:59 -06:00
|
|
|
if (is_whole_disk(devname)) {
|
|
|
|
char *cn = canonicalize_path(devname);
|
|
|
|
if (cn) {
|
2011-12-22 08:53:25 -06:00
|
|
|
if (!is_ide_cdrom_or_tape(cn))
|
2012-12-11 07:41:57 -06:00
|
|
|
print_partition_table_from_option(cxt, cn, sector_size);
|
2010-12-16 18:28:59 -06:00
|
|
|
free(cn);
|
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:41 -06:00
|
|
|
}
|
2006-12-06 17:25:49 -06:00
|
|
|
fclose(procpt);
|
2006-12-06 17:25:41 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
unknown_command(int c) {
|
|
|
|
printf(_("%c: unknown command\n"), c);
|
2006-12-06 17:25:39 -06:00
|
|
|
}
|
|
|
|
|
2012-05-27 14:43:56 -05:00
|
|
|
static void print_welcome(void)
|
|
|
|
{
|
|
|
|
printf(_("Welcome to fdisk (%s).\n\n"
|
|
|
|
"Changes will remain in memory only, until you decide to write them.\n"
|
|
|
|
"Be careful before using the write command.\n\n"), PACKAGE_STRING);
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2012-05-27 14:44:04 -05:00
|
|
|
static void command_prompt(struct fdisk_context *cxt)
|
2011-11-11 04:12:09 -06:00
|
|
|
{
|
2011-12-15 13:02:46 -06:00
|
|
|
int c;
|
2013-03-05 08:39:12 -06:00
|
|
|
size_t n;
|
2007-05-31 07:31:51 -05:00
|
|
|
|
2013-01-22 06:46:55 -06:00
|
|
|
assert(cxt);
|
|
|
|
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, OSF)) {
|
2011-11-11 04:12:09 -06:00
|
|
|
putchar('\n');
|
|
|
|
/* OSF label, and no DOS label */
|
|
|
|
printf(_("Detected an OSF/1 disklabel on %s, entering "
|
|
|
|
"disklabel mode.\n"),
|
2012-05-21 15:28:03 -05:00
|
|
|
cxt->dev_path);
|
2012-05-27 14:44:04 -05:00
|
|
|
bsd_command_prompt(cxt);
|
2012-12-11 11:30:03 -06:00
|
|
|
|
2011-11-11 04:12:09 -06:00
|
|
|
/* If we return we may want to make an empty DOS label? */
|
2012-12-11 11:30:03 -06:00
|
|
|
fdisk_context_switch_label(cxt, "dos");
|
2011-11-11 04:12:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
2013-01-22 06:46:55 -06:00
|
|
|
|
|
|
|
assert(cxt->label);
|
|
|
|
|
2011-11-11 04:12:09 -06:00
|
|
|
putchar('\n');
|
2013-01-18 09:11:40 -06:00
|
|
|
c = tolower(read_char(cxt, _("Command (m for help): ")));
|
2011-11-11 04:12:09 -06:00
|
|
|
switch (c) {
|
|
|
|
case 'a':
|
2013-03-05 08:39:12 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, DOS) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
fdisk_partition_toggle_flag(cxt, n, DOS_FLAG_ACTIVE);
|
|
|
|
|
|
|
|
else if (fdisk_is_disklabel(cxt, SUN) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
fdisk_partition_toggle_flag(cxt, n, SUN_FLAG_UNMNT);
|
|
|
|
|
|
|
|
else if (fdisk_is_disklabel(cxt, SGI) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
fdisk_partition_toggle_flag(cxt, n, SGI_FLAG_BOOT);
|
2011-11-11 04:12:09 -06:00
|
|
|
else
|
|
|
|
unknown_command(c);
|
|
|
|
break;
|
|
|
|
case 'b':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SGI))
|
2012-06-17 11:10:07 -05:00
|
|
|
sgi_set_bootfile(cxt);
|
2012-11-25 22:25:49 -06:00
|
|
|
else if (fdisk_is_disklabel(cxt, DOS)) {
|
2013-03-05 08:14:04 -06:00
|
|
|
|
|
|
|
struct fdisk_context *bsd;
|
|
|
|
|
|
|
|
bsd = fdisk_new_nested_context(cxt, "bsd");
|
|
|
|
if (bsd)
|
|
|
|
bsd_command_prompt(bsd);
|
|
|
|
fdisk_free_context(bsd);
|
2011-11-09 12:04:12 -06:00
|
|
|
} else
|
|
|
|
unknown_command(c);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'c':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, DOS))
|
2012-06-03 13:15:17 -05:00
|
|
|
toggle_dos_compatibility_flag(cxt);
|
2013-03-05 08:39:12 -06:00
|
|
|
else if (fdisk_is_disklabel(cxt, SUN) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
fdisk_partition_toggle_flag(cxt, n, SUN_FLAG_RONLY);
|
|
|
|
|
|
|
|
else if (fdisk_is_disklabel(cxt, SGI) &&
|
|
|
|
fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
fdisk_partition_toggle_flag(cxt, n, SGI_FLAG_SWAP);
|
2011-11-11 04:12:09 -06:00
|
|
|
else
|
|
|
|
unknown_command(c);
|
|
|
|
break;
|
|
|
|
case 'd':
|
2013-03-05 08:39:12 -06:00
|
|
|
if (fdisk_ask_partnum(cxt, &n, FALSE) == 0)
|
|
|
|
delete_partition(cxt, n);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
2012-10-27 12:23:47 -05:00
|
|
|
case 'g':
|
|
|
|
fdisk_create_disklabel(cxt, "gpt");
|
|
|
|
break;
|
2011-11-11 04:12:09 -06:00
|
|
|
case 'i':
|
2012-11-25 22:25:49 -06:00
|
|
|
if (fdisk_is_disklabel(cxt, SGI))
|
2012-06-17 11:10:07 -05:00
|
|
|
create_sgiinfo(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
else
|
|
|
|
unknown_command(c);
|
2012-01-31 14:06:42 -06:00
|
|
|
break;
|
2011-11-11 04:12:09 -06:00
|
|
|
case 'l':
|
2012-09-24 06:24:09 -05:00
|
|
|
list_partition_types(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'm':
|
2013-05-17 08:11:11 -05:00
|
|
|
print_fdisk_menu(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'n':
|
2012-06-03 13:15:17 -05:00
|
|
|
new_partition(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'o':
|
2012-07-24 07:15:08 -05:00
|
|
|
fdisk_create_disklabel(cxt, "dos");
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'p':
|
2012-05-27 14:44:04 -05:00
|
|
|
list_table(cxt, 0);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'q':
|
2012-05-21 15:28:03 -05:00
|
|
|
handle_quit(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
case 's':
|
2012-07-24 07:15:08 -05:00
|
|
|
fdisk_create_disklabel(cxt, "sun");
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 't':
|
2012-09-26 06:30:44 -05:00
|
|
|
change_partition_type(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'u':
|
2013-02-11 09:38:20 -06:00
|
|
|
toggle_units(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'v':
|
2012-06-03 13:15:17 -05:00
|
|
|
verify(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'w':
|
2012-05-27 14:44:07 -05:00
|
|
|
write_table(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
case 'x':
|
2012-05-27 14:44:04 -05:00
|
|
|
expert_command_prompt(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
unknown_command(c);
|
2013-05-17 08:11:11 -05:00
|
|
|
print_fdisk_menu(cxt);
|
2011-11-11 04:12:09 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-31 07:31:51 -05:00
|
|
|
|
2012-05-27 14:44:13 -05:00
|
|
|
static sector_t get_dev_blocks(char *dev)
|
2012-05-21 14:23:27 -05:00
|
|
|
{
|
|
|
|
int fd;
|
2012-05-27 14:44:13 -05:00
|
|
|
sector_t size;
|
2012-05-21 14:23:27 -05:00
|
|
|
|
|
|
|
if ((fd = open(dev, O_RDONLY)) < 0)
|
2012-07-15 03:39:57 -05:00
|
|
|
err(EXIT_FAILURE, _("cannot open %s"), dev);
|
2012-05-27 14:44:04 -05:00
|
|
|
if (blkdev_get_sectors(fd, &size) == -1) {
|
|
|
|
close(fd);
|
|
|
|
err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), dev);
|
|
|
|
}
|
2012-05-21 14:23:27 -05:00
|
|
|
close(fd);
|
|
|
|
return size/2;
|
|
|
|
}
|
|
|
|
|
2012-05-20 11:11:26 -05:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2012-05-21 14:23:27 -05:00
|
|
|
int c, optl = 0, opts = 0;
|
2012-06-03 13:15:17 -05:00
|
|
|
unsigned long sector_size = 0;
|
2012-12-11 07:41:57 -06:00
|
|
|
struct fdisk_context *cxt;
|
2012-12-11 08:08:06 -06:00
|
|
|
struct fdisk_label *lb;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
textdomain(PACKAGE);
|
2012-04-04 13:02:04 -05:00
|
|
|
atexit(close_stdout);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-12-11 07:41:57 -06:00
|
|
|
fdisk_init_debug(0);
|
|
|
|
cxt = fdisk_new_context();
|
|
|
|
if (!cxt)
|
|
|
|
err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
|
|
|
|
|
2013-01-28 09:16:11 -06:00
|
|
|
fdisk_context_set_ask(cxt, ask_callback, NULL);
|
|
|
|
|
2010-06-16 03:52:20 -05:00
|
|
|
while ((c = getopt(argc, argv, "b:c::C:hH:lsS:u::vV")) != -1) {
|
2006-12-06 17:25:35 -06:00
|
|
|
switch (c) {
|
|
|
|
case 'b':
|
2006-12-06 17:26:02 -06:00
|
|
|
/* Ugly: this sector size is really per device,
|
|
|
|
so cannot be combined with multiple disks,
|
|
|
|
and te same goes for the C/H/S options.
|
|
|
|
*/
|
2012-05-15 10:43:49 -05:00
|
|
|
sector_size = strtou32_or_err(optarg, _("invalid sector size argument"));
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sector_size != 512 && sector_size != 1024 &&
|
2009-03-09 03:52:08 -05:00
|
|
|
sector_size != 2048 && sector_size != 4096)
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:26:02 -06:00
|
|
|
case 'C':
|
2012-05-15 10:43:49 -05:00
|
|
|
user_cylinders = strtou32_or_err(optarg, _("invalid cylinders argument"));
|
2006-12-06 17:26:02 -06:00
|
|
|
break;
|
2010-02-15 07:39:30 -06:00
|
|
|
case 'c':
|
2012-12-11 08:08:06 -06:00
|
|
|
if (optarg) {
|
2013-02-22 08:34:04 -06:00
|
|
|
/* this setting is independent on the current
|
|
|
|
* actively used label */
|
2012-12-11 08:08:06 -06:00
|
|
|
lb = fdisk_context_get_label(cxt, "dos");
|
|
|
|
if (!lb)
|
|
|
|
err(EXIT_FAILURE, _("not found DOS label driver"));
|
|
|
|
if (strcmp(optarg, "=dos") == 0)
|
|
|
|
fdisk_dos_enable_compatible(lb, TRUE);
|
|
|
|
else if (strcmp(optarg, "=nondos") == 0)
|
|
|
|
fdisk_dos_enable_compatible(lb, FALSE);
|
|
|
|
else
|
|
|
|
usage(stderr);
|
|
|
|
}
|
|
|
|
/* use default if no optarg specified */
|
2010-02-15 07:39:30 -06:00
|
|
|
break;
|
2006-12-06 17:26:02 -06:00
|
|
|
case 'H':
|
2012-05-15 10:43:49 -05:00
|
|
|
user_heads = strtou32_or_err(optarg, _("invalid heads argument"));
|
|
|
|
if (user_heads > 256)
|
2006-12-06 17:26:02 -06:00
|
|
|
user_heads = 0;
|
|
|
|
break;
|
|
|
|
case 'S':
|
2012-05-15 10:43:49 -05:00
|
|
|
user_sectors = strtou32_or_err(optarg, _("invalid sectors argument"));
|
|
|
|
if (user_sectors >= 64)
|
2006-12-06 17:26:02 -06:00
|
|
|
user_sectors = 0;
|
|
|
|
break;
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'l':
|
|
|
|
optl = 1;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
opts = 1;
|
|
|
|
break;
|
|
|
|
case 'u':
|
2013-02-11 09:38:20 -06:00
|
|
|
if (optarg && *optarg == '=')
|
|
|
|
optarg++;
|
|
|
|
if (fdisk_context_set_unit(cxt, optarg) != 0)
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:25:43 -06:00
|
|
|
case 'V':
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'v':
|
2012-04-23 05:15:15 -05:00
|
|
|
printf(UTIL_LINUX_VERSION);
|
|
|
|
return EXIT_SUCCESS;
|
2012-05-20 11:11:26 -05:00
|
|
|
case 'h':
|
|
|
|
usage(stdout);
|
2006-12-06 17:25:35 -06:00
|
|
|
default:
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-05-21 15:32:25 -05:00
|
|
|
|
2012-06-03 12:47:44 -05:00
|
|
|
if (sector_size && argc-optind != 1)
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Warning: the -b (set sector size) option should"
|
|
|
|
" be used with one specified device\n"));
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (optl) {
|
|
|
|
nowarn = 1;
|
|
|
|
if (argc > optind) {
|
|
|
|
int k;
|
2006-12-06 17:26:16 -06:00
|
|
|
for (k = optind; k < argc; k++)
|
2012-12-11 07:41:57 -06:00
|
|
|
print_partition_table_from_option(cxt, argv[k], sector_size);
|
2011-12-15 13:02:41 -06:00
|
|
|
} else
|
2012-12-11 07:41:57 -06:00
|
|
|
print_all_partition_table_from_option(cxt, sector_size);
|
2012-06-03 13:15:30 -05:00
|
|
|
exit(EXIT_SUCCESS);
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (opts) {
|
2012-05-21 14:23:27 -05:00
|
|
|
/* print partition size for one or more devices */
|
|
|
|
int i, ndevs = argc - optind;
|
|
|
|
if (ndevs <= 0)
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2012-05-21 14:23:27 -05:00
|
|
|
for (i = optind; i < argc; i++) {
|
|
|
|
if (ndevs == 1)
|
|
|
|
printf("%llu\n", get_dev_blocks(argv[i]));
|
2006-12-06 17:25:35 -06:00
|
|
|
else
|
2012-05-21 14:23:27 -05:00
|
|
|
printf("%s: %llu\n", argv[i], get_dev_blocks(argv[i]));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2012-05-21 14:23:27 -05:00
|
|
|
exit(EXIT_SUCCESS);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2012-07-15 01:58:51 -05:00
|
|
|
if (argc-optind != 1)
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2012-12-11 07:41:57 -06:00
|
|
|
if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0)
|
2012-07-15 03:39:57 -05:00
|
|
|
err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
|
2012-07-23 03:11:08 -05:00
|
|
|
|
2012-07-15 01:58:51 -05:00
|
|
|
if (sector_size) /* passed -b option, override autodiscovery */
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_sector_size(cxt, sector_size);
|
2012-07-23 03:11:08 -05:00
|
|
|
|
2012-07-23 06:57:58 -05:00
|
|
|
if (user_cylinders || user_heads || user_sectors)
|
2012-12-06 05:12:41 -06:00
|
|
|
fdisk_override_geometry(cxt, user_cylinders,
|
2012-07-23 06:57:58 -05:00
|
|
|
user_heads, user_sectors);
|
2012-07-15 01:58:51 -05:00
|
|
|
|
2012-05-27 14:43:56 -05:00
|
|
|
print_welcome();
|
2011-11-11 04:12:09 -06:00
|
|
|
|
2012-07-23 03:56:06 -05:00
|
|
|
if (!fdisk_dev_has_disklabel(cxt)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Device does not contain a recognized partition table\n"));
|
2012-07-24 03:31:32 -05:00
|
|
|
fdisk_create_disklabel(cxt, NULL);
|
2012-07-23 03:56:06 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2012-05-27 14:44:04 -05:00
|
|
|
command_prompt(cxt);
|
2011-08-16 17:19:04 -05:00
|
|
|
|
2012-12-11 07:41:57 -06:00
|
|
|
fdisk_free_context(cxt);
|
2006-12-06 17:25:37 -06:00
|
|
|
return 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|