2013-06-12 10:28:26 -05:00
|
|
|
/*
|
2006-12-06 17:25:32 -06:00
|
|
|
* 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
|
|
|
*
|
2013-06-12 10:28:26 -05:00
|
|
|
* Copyright (C) 2007-2013 Karel Zak <kzak@redhat.com>
|
|
|
|
*
|
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>
|
2014-08-13 03:10:11 -05:00
|
|
|
#include <libsmartcols.h>
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-06-12 10:28:26 -05:00
|
|
|
#include "c.h"
|
2011-01-23 15:51:21 -06:00
|
|
|
#include "xalloc.h"
|
2013-09-03 10:36:35 -05:00
|
|
|
#include "all-io.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"
|
2010-03-09 02:21:35 -06:00
|
|
|
#include "mbsalign.h"
|
2006-12-06 17:25:33 -06:00
|
|
|
#include "fdisk.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"
|
2014-06-17 05:15:59 -05:00
|
|
|
#include "sysfs.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
|
|
|
|
2006-12-06 17:26:54 -06:00
|
|
|
#ifdef HAVE_LINUX_COMPILER_H
|
2013-06-12 10:28:26 -05:00
|
|
|
# include <linux/compiler.h>
|
2006-12-06 17:26:54 -06:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_LINUX_BLKPG_H
|
2013-06-12 10:28:26 -05:00
|
|
|
# include <linux/blkpg.h>
|
2006-12-06 17:25:39 -06:00
|
|
|
#endif
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-03-10 07:55:43 -05:00
|
|
|
|
|
|
|
|
|
|
|
int get_user_reply(struct fdisk_context *cxt, const char *prompt,
|
|
|
|
char *buf, size_t bufsz)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
size_t sz;
|
|
|
|
|
|
|
|
do {
|
|
|
|
fputs(prompt, stdout);
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
if (!fgets(buf, bufsz, stdin)) {
|
|
|
|
if (fdisk_label_is_changed(cxt->label)) {
|
|
|
|
fprintf(stderr, _("\nDo you really want to quit? "));
|
|
|
|
|
|
|
|
if (fgets(buf, bufsz, stdin) && !rpmatch(buf))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
fdisk_free_context(cxt);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */
|
|
|
|
|
|
|
|
if (p > buf)
|
|
|
|
memmove(buf, p, p - buf); /* remove blank space */
|
|
|
|
sz = strlen(buf);
|
|
|
|
if (sz && *(buf + sz - 1) == '\n')
|
|
|
|
*(buf + sz - 1) = '\0';
|
|
|
|
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf));
|
2014-03-10 07:55:43 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ask_menu(struct fdisk_context *cxt, struct fdisk_ask *ask,
|
|
|
|
char *buf, size_t bufsz)
|
|
|
|
|
|
|
|
{
|
|
|
|
const char *q = fdisk_ask_get_query(ask);
|
|
|
|
int dft = fdisk_ask_menu_get_default(ask);
|
|
|
|
|
|
|
|
if (q) {
|
|
|
|
fputs(q, stdout); /* print header */
|
|
|
|
fputc('\n', stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
char prompt[128];
|
|
|
|
int key, c;
|
|
|
|
const char *name, *desc;
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
/* print menu items */
|
|
|
|
while (fdisk_ask_menu_get_item(ask, i++, &key, &name, &desc) == 0)
|
|
|
|
fprintf(stdout, " %c %s (%s)\n", key, name, desc);
|
|
|
|
|
|
|
|
/* ask for key */
|
|
|
|
snprintf(prompt, sizeof(prompt), _("Select (default %c): "), dft);
|
|
|
|
get_user_reply(cxt, prompt, buf, bufsz);
|
|
|
|
if (!*buf) {
|
|
|
|
fdisk_info(cxt, _("Using default response %c."), dft);
|
|
|
|
c = dft;
|
|
|
|
} else
|
|
|
|
c = tolower(buf[0]);
|
|
|
|
|
|
|
|
/* check result */
|
|
|
|
i = 0;
|
|
|
|
while (fdisk_ask_menu_get_item(ask, i++, &key, NULL, NULL) == 0) {
|
|
|
|
if (c == key) {
|
|
|
|
fdisk_ask_menu_set_result(ask, c);
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fdisk_warnx(cxt, _("Value out of range."));
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define tochar(num) ((int) ('a' + num - 1))
|
|
|
|
static int ask_number(struct fdisk_context *cxt,
|
|
|
|
struct fdisk_ask *ask,
|
|
|
|
char *buf, size_t bufsz)
|
|
|
|
{
|
|
|
|
char prompt[128] = { '\0' };
|
|
|
|
const char *q = fdisk_ask_get_query(ask);
|
|
|
|
const char *range = fdisk_ask_number_get_range(ask);
|
|
|
|
|
|
|
|
uint64_t dflt = fdisk_ask_number_get_default(ask),
|
|
|
|
low = fdisk_ask_number_get_low(ask),
|
|
|
|
high = fdisk_ask_number_get_high(ask);
|
|
|
|
int inchar = fdisk_ask_number_inchars(ask);
|
|
|
|
|
|
|
|
assert(q);
|
|
|
|
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("asking for number "
|
2014-03-10 07:55:43 -05:00
|
|
|
"['%s', <%ju,%ju>, default=%ju, range: %s]",
|
|
|
|
q, low, high, dflt, range));
|
|
|
|
|
|
|
|
if (range && dflt >= low && dflt <= high) {
|
|
|
|
if (inchar)
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "),
|
|
|
|
q, range, tochar(dflt));
|
|
|
|
else
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "),
|
|
|
|
q, range, dflt);
|
|
|
|
|
|
|
|
} else if (dflt >= low && dflt <= high) {
|
|
|
|
if (inchar)
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "),
|
|
|
|
q, tochar(low), tochar(high), tochar(dflt));
|
|
|
|
else
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "),
|
|
|
|
q, low, high, dflt);
|
|
|
|
} else if (inchar)
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "),
|
|
|
|
q, tochar(low), tochar(high));
|
|
|
|
else
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "),
|
|
|
|
q, low, high);
|
|
|
|
|
|
|
|
do {
|
|
|
|
int rc = get_user_reply(cxt, prompt, buf, bufsz);
|
|
|
|
uint64_t num;
|
|
|
|
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
if (!*buf && dflt >= low && dflt <= high)
|
|
|
|
return fdisk_ask_number_set_result(ask, dflt);
|
|
|
|
|
|
|
|
if (isdigit_string(buf)) {
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
num = strtoumax(buf, &end, 10);
|
|
|
|
if (errno || buf == end || (end && *end))
|
|
|
|
continue;
|
|
|
|
} else if (inchar && isalpha(*buf)) {
|
|
|
|
num = tolower(*buf) - 'a' + 1;
|
|
|
|
} else
|
|
|
|
rc = -EINVAL;
|
|
|
|
|
|
|
|
if (rc == 0 && num >= low && num <= high)
|
|
|
|
return fdisk_ask_number_set_result(ask, num);
|
|
|
|
|
|
|
|
fdisk_warnx(cxt, _("Value out of range."));
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ask_offset(struct fdisk_context *cxt,
|
|
|
|
struct fdisk_ask *ask,
|
|
|
|
char *buf, size_t bufsz)
|
|
|
|
{
|
|
|
|
char prompt[128] = { '\0' };
|
|
|
|
const char *q = fdisk_ask_get_query(ask);
|
|
|
|
const char *range = fdisk_ask_number_get_range(ask);
|
|
|
|
|
|
|
|
uint64_t dflt = fdisk_ask_number_get_default(ask),
|
|
|
|
low = fdisk_ask_number_get_low(ask),
|
|
|
|
high = fdisk_ask_number_get_high(ask),
|
|
|
|
base = fdisk_ask_number_get_base(ask);
|
|
|
|
|
|
|
|
assert(q);
|
|
|
|
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("asking for offset ['%s', <%ju,%ju>, base=%ju, default=%ju, range: %s]",
|
2014-03-10 07:55:43 -05:00
|
|
|
q, low, high, base, dflt, range));
|
|
|
|
|
|
|
|
if (range && dflt >= low && dflt <= high)
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt);
|
|
|
|
else if (dflt >= low && dflt <= high)
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt);
|
|
|
|
else
|
|
|
|
snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high);
|
|
|
|
|
|
|
|
do {
|
|
|
|
uint64_t num = 0;
|
|
|
|
char sig = 0, *p;
|
|
|
|
int pwr = 0;
|
|
|
|
|
|
|
|
int rc = get_user_reply(cxt, prompt, buf, bufsz);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
if (!*buf && dflt >= low && dflt <= high)
|
|
|
|
return fdisk_ask_number_set_result(ask, dflt);
|
|
|
|
|
|
|
|
p = buf;
|
|
|
|
if (*p == '+' || *p == '-') {
|
|
|
|
sig = *buf;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = parse_size(p, &num, &pwr);
|
|
|
|
if (rc)
|
|
|
|
continue;
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("parsed size: %ju", num));
|
2014-03-10 07:55:43 -05:00
|
|
|
if (sig && pwr) {
|
|
|
|
/* +{size}{K,M,...} specified, the "num" is in bytes */
|
|
|
|
uint64_t unit = fdisk_ask_number_get_unit(ask);
|
|
|
|
num += unit/2; /* round */
|
|
|
|
num /= unit;
|
|
|
|
}
|
|
|
|
if (sig == '+')
|
|
|
|
num += base;
|
|
|
|
else if (sig == '-')
|
|
|
|
num = base - num;
|
|
|
|
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("final offset: %ju [sig: %c, power: %d, %s]",
|
2014-03-10 07:55:43 -05:00
|
|
|
num, sig, pwr,
|
|
|
|
sig ? "relative" : "absolute"));
|
|
|
|
if (num >= low && num <= high) {
|
|
|
|
if (sig)
|
|
|
|
fdisk_ask_number_set_relative(ask, 1);
|
|
|
|
return fdisk_ask_number_set_result(ask, num);
|
|
|
|
}
|
|
|
|
fdisk_warnx(cxt, _("Value out of range."));
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int info_count;
|
|
|
|
|
2014-04-01 07:39:13 -05:00
|
|
|
static void fputs_info(struct fdisk_ask *ask, FILE *out)
|
2014-03-10 07:55:43 -05:00
|
|
|
{
|
|
|
|
const char *msg;
|
|
|
|
assert(ask);
|
|
|
|
|
|
|
|
msg = fdisk_ask_print_get_mesg(ask);
|
|
|
|
if (!msg)
|
|
|
|
return;
|
|
|
|
if (info_count == 1)
|
|
|
|
fputc('\n', out);
|
2014-04-01 07:39:13 -05:00
|
|
|
|
|
|
|
fputs(msg, out);
|
2014-03-10 07:55:43 -05:00
|
|
|
fputc('\n', out);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
|
|
|
|
void *data __attribute__((__unused__)))
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
|
|
|
|
assert(cxt);
|
|
|
|
assert(ask);
|
|
|
|
|
|
|
|
if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_INFO)
|
|
|
|
info_count = 0;
|
|
|
|
|
|
|
|
switch(fdisk_ask_get_type(ask)) {
|
|
|
|
case FDISK_ASKTYPE_MENU:
|
|
|
|
return ask_menu(cxt, ask, buf, sizeof(buf));
|
|
|
|
case FDISK_ASKTYPE_NUMBER:
|
|
|
|
return ask_number(cxt, ask, buf, sizeof(buf));
|
|
|
|
case FDISK_ASKTYPE_OFFSET:
|
|
|
|
return ask_offset(cxt, ask, buf, sizeof(buf));
|
|
|
|
case FDISK_ASKTYPE_INFO:
|
|
|
|
info_count++;
|
2014-04-01 07:39:13 -05:00
|
|
|
fputs_info(ask, stdout);
|
2014-03-10 07:55:43 -05:00
|
|
|
break;
|
|
|
|
case FDISK_ASKTYPE_WARNX:
|
2014-05-12 03:22:09 -05:00
|
|
|
color_scheme_fenable("warn", UL_COLOR_RED, stderr);
|
2014-03-10 07:55:43 -05:00
|
|
|
fputs(fdisk_ask_print_get_mesg(ask), stderr);
|
|
|
|
color_fdisable(stderr);
|
|
|
|
fputc('\n', stderr);
|
|
|
|
break;
|
|
|
|
case FDISK_ASKTYPE_WARN:
|
2014-05-12 03:22:09 -05:00
|
|
|
color_scheme_fenable("warn", UL_COLOR_RED, stderr);
|
2014-03-10 07:55:43 -05:00
|
|
|
fputs(fdisk_ask_print_get_mesg(ask), stderr);
|
|
|
|
errno = fdisk_ask_print_get_errno(ask);
|
|
|
|
fprintf(stderr, ": %m\n");
|
|
|
|
color_fdisable(stderr);
|
|
|
|
break;
|
|
|
|
case FDISK_ASKTYPE_YESNO:
|
|
|
|
fputc('\n', stdout);
|
|
|
|
fputs(fdisk_ask_get_query(ask), stdout);
|
|
|
|
rc = get_user_reply(cxt, _(" [Y]es/[N]o: "), buf, sizeof(buf));
|
|
|
|
if (rc == 0)
|
|
|
|
fdisk_ask_yesno_set_result(ask, rpmatch(buf));
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("yes-no ask: reply '%s' [rc=%d]", buf, rc));
|
2014-03-10 07:55:43 -05:00
|
|
|
break;
|
|
|
|
case FDISK_ASKTYPE_STRING:
|
|
|
|
{
|
|
|
|
char prmt[BUFSIZ];
|
|
|
|
snprintf(prmt, sizeof(prmt), "%s: ", fdisk_ask_get_query(ask));
|
|
|
|
fputc('\n', stdout);
|
|
|
|
rc = get_user_reply(cxt, prmt, buf, sizeof(buf));
|
|
|
|
if (rc == 0)
|
|
|
|
fdisk_ask_string_set_result(ask, xstrdup(buf));
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(ASK, ul_debug("string ask: reply '%s' [rc=%d]", buf, rc));
|
2014-03-10 07:55:43 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
warnx(_("internal error: unsupported dialog type %d"), fdisk_ask_get_type(ask));
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
const char *q;
|
2014-08-14 06:28:37 -05:00
|
|
|
struct fdisk_label *lb;
|
|
|
|
|
|
|
|
assert(cxt);
|
|
|
|
lb = fdisk_get_label(cxt, NULL);
|
2014-03-10 07:55:43 -05:00
|
|
|
|
2014-08-14 06:28:37 -05:00
|
|
|
if (!lb)
|
2014-03-10 07:55:43 -05:00
|
|
|
return NULL;
|
|
|
|
|
2014-08-14 06:28:37 -05:00
|
|
|
q = fdisk_label_has_code_parttypes(lb) ?
|
2014-03-10 07:55:43 -05:00
|
|
|
_("Partition type (type L to list all types): ") :
|
|
|
|
_("Hex code (type L to list all codes): ");
|
|
|
|
do {
|
|
|
|
char buf[256];
|
|
|
|
int rc = get_user_reply(cxt, q, buf, sizeof(buf));
|
|
|
|
|
|
|
|
if (rc)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (buf[1] == '\0' && toupper(*buf) == 'L')
|
|
|
|
list_partition_types(cxt);
|
|
|
|
else if (*buf)
|
2014-08-14 06:28:37 -05:00
|
|
|
return fdisk_label_parse_parttype(lb, buf);
|
2014-03-10 07:55:43 -05:00
|
|
|
} while (1);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-24 06:24:09 -05:00
|
|
|
void list_partition_types(struct fdisk_context *cxt)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2013-04-18 07:38:49 -05:00
|
|
|
size_t ntypes = 0;
|
2014-08-14 06:28:37 -05:00
|
|
|
struct fdisk_label *lb = fdisk_get_label(cxt, NULL);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-08-14 06:28:37 -05:00
|
|
|
assert(cxt);
|
|
|
|
lb = fdisk_get_label(cxt, NULL);
|
|
|
|
if (!lb)
|
|
|
|
return;
|
|
|
|
ntypes = fdisk_label_get_nparttypes(lb);
|
|
|
|
if (!ntypes)
|
2012-09-24 06:24:09 -05:00
|
|
|
return;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2014-08-14 06:28:37 -05:00
|
|
|
if (fdisk_label_has_code_parttypes(lb)) {
|
2012-09-24 06:24:09 -05:00
|
|
|
/*
|
|
|
|
* 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;
|
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;
|
2014-08-14 06:28:37 -05:00
|
|
|
const struct fdisk_parttype *t = fdisk_label_get_parttype(lb, next);
|
2012-09-24 06:24:09 -05:00
|
|
|
size_t ret;
|
|
|
|
|
2013-04-18 07:38:49 -05:00
|
|
|
if (t->name) {
|
2014-08-14 06:28:37 -05:00
|
|
|
printf("%c%2x ", i ? ' ' : '\n',
|
|
|
|
fdisk_parttype_get_code(t));
|
|
|
|
ret = mbsalign(_(fdisk_parttype_get_name(t)),
|
|
|
|
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))
|
2014-08-14 06:28:37 -05:00
|
|
|
printf("%-15.15s",
|
|
|
|
_(fdisk_parttype_get_name(t)));
|
2013-04-18 07:38:49 -05:00
|
|
|
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>
|
|
|
|
*/
|
2013-04-18 07:38:49 -05:00
|
|
|
size_t i;
|
2012-09-24 06:24:09 -05:00
|
|
|
|
2014-08-14 06:28:37 -05:00
|
|
|
for (i = 0; i < ntypes; i++) {
|
|
|
|
const struct fdisk_parttype *t = fdisk_label_get_parttype(lb, i);
|
|
|
|
printf("%3zu %-30s %s\n", i + 1,
|
|
|
|
fdisk_parttype_get_name(t),
|
|
|
|
fdisk_parttype_get_string(t));
|
2013-04-18 07:38:49 -05:00
|
|
|
}
|
2012-09-24 06:24:09 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
|
2013-06-25 08:55:02 -05:00
|
|
|
void toggle_dos_compatibility_flag(struct fdisk_context *cxt)
|
2012-12-11 08:08:06 -06:00
|
|
|
{
|
2014-08-13 15:26:53 -05:00
|
|
|
struct fdisk_label *lb = fdisk_get_label(cxt, "dos");
|
2012-12-11 08:08:06 -06:00
|
|
|
int flag;
|
|
|
|
|
|
|
|
if (!lb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
flag = !fdisk_dos_is_compatible(lb);
|
2013-09-03 05:18:33 -05:00
|
|
|
fdisk_info(cxt, flag ?
|
|
|
|
_("DOS Compatibility flag is set (DEPRECATED!)") :
|
|
|
|
_("DOS Compatibility flag is not set"));
|
2009-11-03 04:28:55 -06:00
|
|
|
|
2012-12-11 08:08:06 -06:00
|
|
|
fdisk_dos_enable_compatible(lb, flag);
|
|
|
|
|
2014-08-13 16:57:54 -05:00
|
|
|
if (fdisk_is_label(cxt, DOS))
|
2013-09-03 05:18:33 -05:00
|
|
|
fdisk_reset_alignment(cxt); /* reset the current label */
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2013-07-12 04:31:12 -05:00
|
|
|
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;
|
2013-11-28 05:56:12 -06:00
|
|
|
struct fdisk_parttype *t = NULL;
|
|
|
|
struct fdisk_partition *pa = NULL;
|
|
|
|
const char *old = NULL;
|
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
|
|
|
|
2013-11-28 05:56:12 -06:00
|
|
|
if (fdisk_get_partition(cxt, i, &pa)) {
|
|
|
|
fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = (struct fdisk_parttype *) fdisk_partition_get_type(pa);
|
|
|
|
old = t ? t->name : _("Unknown");
|
|
|
|
|
|
|
|
do {
|
|
|
|
t = ask_partition_type(cxt);
|
|
|
|
} while (!t);
|
|
|
|
|
|
|
|
if (fdisk_set_partition_type(cxt, i, t) == 0)
|
|
|
|
fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
|
|
|
|
_("Changed type of partition '%s' to '%s'."),
|
2014-08-14 06:28:37 -05:00
|
|
|
old, t ? fdisk_parttype_get_name(t) : _("Unknown"));
|
2013-11-28 05:56:12 -06:00
|
|
|
else
|
|
|
|
fdisk_info(cxt,
|
|
|
|
_("Type of partition %zu is unchanged: %s."),
|
|
|
|
i + 1, old);
|
|
|
|
|
2013-12-13 12:26:29 -06:00
|
|
|
fdisk_unref_partition(pa);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2013-07-12 03:44:35 -05:00
|
|
|
void list_disk_geometry(struct fdisk_context *cxt)
|
2013-06-25 07:40:34 -05:00
|
|
|
{
|
|
|
|
char *id = NULL;
|
2014-08-13 17:09:48 -05:00
|
|
|
struct fdisk_label *lb = fdisk_get_label(cxt, NULL);
|
2013-08-30 08:47:50 -05:00
|
|
|
uint64_t bytes = cxt->total_sectors * cxt->sector_size;
|
|
|
|
char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE
|
|
|
|
| SIZE_SUFFIX_3LETTER, bytes);
|
|
|
|
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Disk %s: %s, %ju bytes, %ju sectors"),
|
2013-10-15 05:46:35 -05:00
|
|
|
cxt->dev_path, strsz,
|
2013-10-15 06:26:12 -05:00
|
|
|
bytes, (uintmax_t) cxt->total_sectors);
|
2013-08-30 08:47:50 -05:00
|
|
|
free(strsz);
|
2013-05-02 04:49:28 -05:00
|
|
|
|
2014-08-13 17:09:48 -05:00
|
|
|
if (fdisk_label_require_geometry(lb) || fdisk_use_cylinders(cxt))
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Geometry: %d heads, %llu sectors/track, %llu cylinders"),
|
2013-08-30 08:47:50 -05:00
|
|
|
cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);
|
2013-05-02 04:49:28 -05:00
|
|
|
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Units: %s of %d * %ld = %ld bytes"),
|
2014-08-13 15:26:53 -05:00
|
|
|
fdisk_get_unit(cxt, PLURAL),
|
|
|
|
fdisk_get_units_per_sector(cxt),
|
2013-02-11 09:38:20 -06:00
|
|
|
cxt->sector_size,
|
2014-08-13 15:26:53 -05:00
|
|
|
fdisk_get_units_per_sector(cxt) * cxt->sector_size);
|
2009-10-29 05:25:59 -05:00
|
|
|
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"),
|
2012-06-03 13:15:17 -05:00
|
|
|
cxt->sector_size, cxt->phy_sector_size);
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"),
|
2012-06-03 13:15:17 -05:00
|
|
|
cxt->min_io_size, cxt->io_size);
|
|
|
|
if (cxt->alignment_offset)
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Alignment offset: %lu bytes"),
|
2013-08-30 08:47:50 -05:00
|
|
|
cxt->alignment_offset);
|
2014-08-13 16:57:54 -05:00
|
|
|
if (fdisk_has_label(cxt))
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Disklabel type: %s"), cxt->label->name);
|
2013-06-25 07:40:34 -05:00
|
|
|
|
|
|
|
if (fdisk_get_disklabel_id(cxt, &id) == 0 && id)
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("Disk identifier: %s"), id);
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
|
|
|
|
2013-12-18 03:38:43 -06:00
|
|
|
void list_disklabel(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
struct fdisk_table *tb = NULL;
|
2014-08-08 04:33:28 -05:00
|
|
|
struct fdisk_partition *pa = NULL;
|
2014-08-13 03:10:11 -05:00
|
|
|
struct fdisk_iter *itr = NULL;
|
|
|
|
struct libscols_table *out = NULL;
|
|
|
|
const char *bold = NULL;
|
2014-08-13 04:12:27 -05:00
|
|
|
int *ids = NULL; /* IDs of fdisk_fields */
|
|
|
|
size_t nids = 0, i;
|
2013-12-18 03:38:43 -06:00
|
|
|
|
|
|
|
/* print label specific stuff by libfdisk FDISK_ASK_INFO API */
|
|
|
|
fdisk_list_disklabel(cxt);
|
|
|
|
|
2014-08-13 03:10:11 -05:00
|
|
|
/* get partitions and generate output */
|
|
|
|
if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0)
|
|
|
|
goto done;
|
|
|
|
|
2014-08-13 17:27:28 -05:00
|
|
|
if (fdisk_label_get_fields_ids(NULL, cxt, &ids, &nids))
|
2014-08-13 03:10:11 -05:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
itr = fdisk_new_iter(FDISK_ITER_FORWARD);
|
|
|
|
if (!itr) {
|
|
|
|
fdisk_warn(cxt, _("faild to allocate iterator"));
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
out = scols_new_table();
|
|
|
|
if (!out) {
|
|
|
|
fdisk_warn(cxt, _("faild to allocate output table"));
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (colors_wanted()) {
|
|
|
|
scols_table_enable_colors(out, 1);
|
|
|
|
bold = color_scheme_get_sequence("header", UL_COLOR_BOLD);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* define output table columns */
|
2014-08-13 04:12:27 -05:00
|
|
|
for (i = 0; i < nids; i++) {
|
2014-08-13 03:10:11 -05:00
|
|
|
int fl = 0;
|
|
|
|
struct libscols_column *co;
|
2014-08-13 04:12:27 -05:00
|
|
|
const struct fdisk_field *field =
|
|
|
|
fdisk_label_get_field(cxt->label, ids[i]);
|
|
|
|
if (!field)
|
2014-08-13 03:10:11 -05:00
|
|
|
goto done;
|
2014-08-13 04:12:27 -05:00
|
|
|
if (fdisk_field_is_number(field))
|
2014-08-13 03:10:11 -05:00
|
|
|
fl |= SCOLS_FL_RIGHT;
|
2014-08-13 04:12:27 -05:00
|
|
|
if (fdisk_field_get_id(field) == FDISK_FIELD_TYPE)
|
2014-08-13 03:10:11 -05:00
|
|
|
fl |= SCOLS_FL_TRUNC;
|
|
|
|
|
|
|
|
co = scols_table_new_column(out,
|
2014-08-13 04:12:27 -05:00
|
|
|
fdisk_field_get_name(field),
|
|
|
|
fdisk_field_get_width(field), fl);
|
2014-08-13 03:10:11 -05:00
|
|
|
if (!co)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
/* set colum header color */
|
|
|
|
if (bold)
|
|
|
|
scols_cell_set_color(scols_column_get_header(co), bold);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill-in output table */
|
|
|
|
while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
|
|
|
|
struct libscols_line *ln = scols_table_new_line(out, NULL);
|
|
|
|
|
|
|
|
if (!ln) {
|
|
|
|
fdisk_warn(cxt, _("faild to allocate output line"));
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2014-08-13 04:12:27 -05:00
|
|
|
for (i = 0; i < nids; i++) {
|
2014-08-13 03:10:11 -05:00
|
|
|
char *data = NULL;
|
|
|
|
|
2014-08-13 04:12:27 -05:00
|
|
|
if (fdisk_partition_to_string(pa, cxt, ids[i], &data))
|
2014-08-13 03:10:11 -05:00
|
|
|
continue;
|
|
|
|
scols_line_refer_data(ln, i, data);
|
2014-04-03 05:43:36 -05:00
|
|
|
}
|
2013-12-18 03:38:43 -06:00
|
|
|
}
|
2014-04-16 05:51:08 -05:00
|
|
|
|
2014-08-13 03:10:11 -05:00
|
|
|
/* print */
|
|
|
|
if (!scols_table_is_empty(out)) {
|
|
|
|
fputc('\n', stdout);
|
|
|
|
scols_print_table(out);
|
|
|
|
}
|
2014-08-08 04:33:28 -05:00
|
|
|
|
2014-08-08 05:35:20 -05:00
|
|
|
|
2014-08-13 03:10:11 -05:00
|
|
|
fputc('\n', stdout);
|
|
|
|
|
|
|
|
/* print warnings */
|
2014-08-13 16:27:00 -05:00
|
|
|
while (itr && fdisk_table_next_partition(tb, itr, &pa) == 0) {
|
|
|
|
if (!fdisk_lba_is_phy_aligned(cxt, fdisk_partition_get_start(pa)))
|
|
|
|
fdisk_warnx(cxt, _("Partition %zu does not start on physical sector boundary."),
|
2014-08-08 04:33:28 -05:00
|
|
|
fdisk_partition_get_partno(pa) + 1);
|
2014-08-13 16:27:00 -05:00
|
|
|
}
|
2014-08-08 04:33:28 -05:00
|
|
|
|
2014-08-08 05:35:20 -05:00
|
|
|
if (fdisk_table_wrong_order(tb))
|
2014-04-16 05:51:08 -05:00
|
|
|
fdisk_info(cxt, _("Partition table entries are not in disk order."));
|
2014-08-13 03:10:11 -05:00
|
|
|
done:
|
2014-08-13 04:12:27 -05:00
|
|
|
free(ids);
|
2014-08-13 03:10:11 -05:00
|
|
|
scols_unref_table(out);
|
2013-12-18 03:38:43 -06:00
|
|
|
fdisk_unref_table(tb);
|
2014-08-08 04:33:28 -05:00
|
|
|
fdisk_free_iter(itr);
|
2013-12-18 03:38:43 -06:00
|
|
|
}
|
|
|
|
|
2013-09-03 10:36:35 -05:00
|
|
|
static size_t skip_empty(const unsigned char *buf, size_t i, size_t sz)
|
|
|
|
{
|
|
|
|
size_t next;
|
|
|
|
const unsigned char *p0 = buf + i;
|
|
|
|
|
|
|
|
for (next = i + 16; next < sz; next += 16) {
|
|
|
|
if (memcmp(p0, buf + next, 16) != 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return next == i + 16 ? i : next;
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-09-03 10:36:35 -05:00
|
|
|
static void dump_buffer(off_t base, unsigned char *buf, size_t sz, int all)
|
2013-09-03 05:18:33 -05:00
|
|
|
{
|
2013-09-03 10:36:35 -05:00
|
|
|
size_t i, l, next = 0;
|
|
|
|
|
|
|
|
if (!buf)
|
|
|
|
return;
|
|
|
|
for (i = 0, l = 0; i < sz; i++, l++) {
|
|
|
|
if (l == 0) {
|
|
|
|
if (all == 0 && !next)
|
|
|
|
next = skip_empty(buf, i, sz);
|
|
|
|
printf("%08jx ", base + i);
|
|
|
|
}
|
|
|
|
printf(" %02x", buf[i]);
|
|
|
|
if (l == 7) /* words separator */
|
|
|
|
fputs(" ", stdout);
|
|
|
|
else if (l == 15) {
|
|
|
|
fputc('\n', stdout); /* next line */
|
2006-12-06 17:25:32 -06:00
|
|
|
l = -1;
|
2013-09-03 10:36:35 -05:00
|
|
|
if (next > i) {
|
|
|
|
printf("*\n");
|
|
|
|
i = next - 1;
|
|
|
|
}
|
|
|
|
next = 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (l > 0)
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2013-09-03 10:36:35 -05:00
|
|
|
static void dump_blkdev(struct fdisk_context *cxt, const char *name,
|
|
|
|
off_t offset, size_t size, int all)
|
2012-06-03 13:15:17 -05:00
|
|
|
{
|
2014-04-01 07:39:13 -05:00
|
|
|
fdisk_info(cxt, _("\n%s: offset = %ju, size = %zu bytes."),
|
2013-09-03 10:36:35 -05:00
|
|
|
name, offset, size);
|
|
|
|
|
|
|
|
if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
|
|
|
|
fdisk_warn(cxt, _("cannot seek"));
|
2013-09-26 03:58:03 -05:00
|
|
|
else {
|
|
|
|
unsigned char *buf = xmalloc(size);
|
|
|
|
|
|
|
|
if (read_all(cxt->dev_fd, (char *) buf, size) != (ssize_t) size)
|
|
|
|
fdisk_warn(cxt, _("cannot read"));
|
|
|
|
else
|
|
|
|
dump_buffer(offset, buf, size, all);
|
|
|
|
free(buf);
|
|
|
|
}
|
2013-09-03 10:36:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void dump_firstsector(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
int all = !isatty(STDOUT_FILENO);
|
|
|
|
|
2013-01-22 06:46:55 -06:00
|
|
|
assert(cxt);
|
|
|
|
assert(cxt->label);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-09-03 10:36:35 -05:00
|
|
|
dump_blkdev(cxt, _("First sector"), 0, cxt->sector_size, all);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dump_disklabel(struct fdisk_context *cxt)
|
|
|
|
{
|
|
|
|
int all = !isatty(STDOUT_FILENO);
|
|
|
|
int i = 0;
|
|
|
|
const char *name = NULL;
|
|
|
|
off_t offset = 0;
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
assert(cxt);
|
|
|
|
assert(cxt->label);
|
2013-01-22 06:46:55 -06:00
|
|
|
|
2013-09-03 10:36:35 -05:00
|
|
|
while (fdisk_locate_disklabel(cxt, i++, &name, &offset, &size) == 0 && size)
|
|
|
|
dump_blkdev(cxt, name, offset, size, all);
|
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
|
|
|
}
|
|
|
|
|
2014-07-28 04:57:10 -05:00
|
|
|
static void print_device_pt(struct fdisk_context *cxt, char *device, int warnme)
|
2011-12-15 13:02:40 -06:00
|
|
|
{
|
2014-08-13 15:26:53 -05:00
|
|
|
if (fdisk_assign_device(cxt, device, 1) != 0) { /* read-only */
|
2014-07-28 04:57:10 -05:00
|
|
|
if (warnme || errno == EACCES)
|
|
|
|
warn(_("cannot open %s"), device);
|
|
|
|
return;
|
|
|
|
}
|
2012-05-21 15:28:03 -05:00
|
|
|
|
2013-07-11 11:03:54 -05:00
|
|
|
list_disk_geometry(cxt);
|
|
|
|
|
2014-08-13 16:57:54 -05:00
|
|
|
if (fdisk_has_label(cxt))
|
2013-12-18 03:38:43 -06:00
|
|
|
list_disklabel(cxt);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2013-08-30 08:20:01 -05:00
|
|
|
static void print_all_devices_pt(struct fdisk_context *cxt)
|
2011-12-15 13:02:41 -06:00
|
|
|
{
|
2013-08-30 08:20:01 -05:00
|
|
|
FILE *f;
|
|
|
|
char line[128 + 1];
|
|
|
|
|
|
|
|
f = fopen(_PATH_PROC_PARTITIONS, "r");
|
|
|
|
if (!f) {
|
|
|
|
warn(_("cannot open %s"), _PATH_PROC_PARTITIONS);
|
2006-12-06 17:25:41 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-21 06:35:21 -05:00
|
|
|
DBG(FRONTEND, ul_debug("reading "_PATH_PROC_PARTITIONS));
|
2013-09-16 10:04:57 -05:00
|
|
|
|
2013-08-30 08:20:01 -05:00
|
|
|
while (fgets(line, sizeof(line), f)) {
|
2014-06-17 05:15:59 -05:00
|
|
|
char buf[PATH_MAX], *cn;
|
|
|
|
dev_t devno;
|
2013-08-30 08:20:01 -05:00
|
|
|
|
2014-06-17 05:15:59 -05:00
|
|
|
if (sscanf(line, " %*d %*d %*d %128[^\n ]", buf) != 1)
|
2006-12-06 17:25:41 -06:00
|
|
|
continue;
|
2013-08-30 08:20:01 -05:00
|
|
|
|
2014-06-17 05:15:59 -05:00
|
|
|
devno = sysfs_devname_to_devno(buf, NULL);
|
|
|
|
if (devno <= 0)
|
|
|
|
continue;
|
2013-09-16 10:04:57 -05:00
|
|
|
|
2014-06-17 05:15:59 -05:00
|
|
|
if (sysfs_devno_is_lvm_private(devno) ||
|
|
|
|
sysfs_devno_is_wholedisk(devno) <= 0)
|
|
|
|
continue;
|
2013-09-16 10:04:57 -05:00
|
|
|
|
2014-06-17 05:15:59 -05:00
|
|
|
if (!sysfs_devno_to_devpath(devno, buf, sizeof(buf)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cn = canonicalize_path(buf);
|
|
|
|
if (!cn)
|
|
|
|
continue;
|
|
|
|
if (!is_ide_cdrom_or_tape(cn))
|
2014-07-28 04:57:10 -05:00
|
|
|
print_device_pt(cxt, cn, 0);
|
2014-06-17 05:15:59 -05:00
|
|
|
free(cn);
|
2006-12-06 17:25:41 -06:00
|
|
|
}
|
2013-08-30 08:20:01 -05:00
|
|
|
fclose(f);
|
2006-12-06 17:25:41 -06: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
|
|
|
{
|
2014-07-13 11:40:31 -05:00
|
|
|
int fd, ret;
|
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);
|
2014-07-13 11:40:31 -05:00
|
|
|
ret = blkdev_get_sectors(fd, &size);
|
2012-05-21 14:23:27 -05:00
|
|
|
close(fd);
|
2014-07-13 11:40:31 -05:00
|
|
|
if (ret < 0)
|
|
|
|
err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), dev);
|
2012-05-21 14:23:27 -05:00
|
|
|
return size/2;
|
|
|
|
}
|
|
|
|
|
2014-06-25 06:21:35 -05:00
|
|
|
static void __attribute__ ((__noreturn__)) usage(FILE *out)
|
|
|
|
{
|
|
|
|
fputs(USAGE_HEADER, out);
|
|
|
|
|
|
|
|
fprintf(out,
|
|
|
|
_(" %1$s [options] <disk> change partition table\n"
|
|
|
|
" %1$s [options] -l [<disk>] list partition table(s)\n"),
|
|
|
|
program_invocation_short_name);
|
|
|
|
|
|
|
|
fputs(USAGE_OPTIONS, out);
|
|
|
|
fputs(_(" -b, --sector-size <size> physical and logical sector size\n"), out);
|
|
|
|
fputs(_(" -c, --compatibility[=<mode>] mode is 'dos' or 'nondos' (default)\n"), out);
|
|
|
|
fputs(_(" -L, --color[=<when>] colorize output (auto, always or never)\n"), out);
|
|
|
|
fputs(_(" -l, --list display partitions end exit\n"), out);
|
|
|
|
fputs(_(" -t, --type <type> recognize specified partition table type only\n"), out);
|
|
|
|
fputs(_(" -u, --units[=<unit>] display units: 'cylinders' or 'sectors' (default)\n"), out);
|
|
|
|
fputs(_(" -s, --getsz display device size in 512-byte sectors [DEPRECATED]\n"), out);
|
|
|
|
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
2014-06-30 08:10:29 -05:00
|
|
|
fputs(_(" -C, --cylinders <number> specify the number of cylinders\n"), out);
|
|
|
|
fputs(_(" -H, --heads <number> specify the number of heads\n"), out);
|
|
|
|
fputs(_(" -S, --sectors <number> specify the number of sectors per track\n"), out);
|
2014-06-25 06:21:35 -05:00
|
|
|
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
fputs(USAGE_HELP, out);
|
|
|
|
fputs(USAGE_VERSION, out);
|
|
|
|
|
|
|
|
fprintf(out, USAGE_MAN_TAIL("fdisk(8)"));
|
|
|
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
enum {
|
|
|
|
ACT_FDISK = 0, /* default */
|
|
|
|
ACT_LIST,
|
|
|
|
ACT_SHOWSIZE
|
|
|
|
};
|
|
|
|
|
2012-05-20 11:11:26 -05:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2014-03-21 08:04:59 -05:00
|
|
|
int rc, i, c, act = ACT_FDISK;
|
2014-01-23 06:03:45 -06:00
|
|
|
int colormode = UL_COLORMODE_UNDEF;
|
2012-12-11 07:41:57 -06:00
|
|
|
struct fdisk_context *cxt;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2014-06-25 06:21:35 -05:00
|
|
|
static const struct option longopts[] = {
|
|
|
|
{ "color", optional_argument, NULL, 'L' },
|
|
|
|
{ "compatibility", optional_argument, NULL, 'c' },
|
2014-06-30 08:10:29 -05:00
|
|
|
{ "cylinders", required_argument, NULL, 'C' },
|
|
|
|
{ "heads", required_argument, NULL, 'H' },
|
|
|
|
{ "sectors", required_argument, NULL, 'S' },
|
2014-06-25 06:21:35 -05:00
|
|
|
{ "getsz", no_argument, NULL, 's' },
|
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "list", no_argument, NULL, 'l' },
|
|
|
|
{ "sector-size", required_argument, NULL, 'b' },
|
|
|
|
{ "type", required_argument, NULL, 't' },
|
|
|
|
{ "units", optional_argument, NULL, 'u' },
|
|
|
|
{ "version", no_argument, NULL, 'V' },
|
|
|
|
{ NULL, 0, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
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"));
|
|
|
|
|
2014-08-13 15:26:53 -05:00
|
|
|
fdisk_set_ask(cxt, ask_callback, NULL);
|
2013-01-28 09:16:11 -06:00
|
|
|
|
2014-06-25 06:21:35 -05:00
|
|
|
while ((c = getopt_long(argc, argv, "b:c::C:hH:lL::sS:t:u::vV",
|
|
|
|
longopts, NULL)) != -1) {
|
2006-12-06 17:25:35 -06:00
|
|
|
switch (c) {
|
|
|
|
case 'b':
|
2013-08-30 06:06:15 -05:00
|
|
|
{
|
|
|
|
size_t sz = strtou32_or_err(optarg,
|
|
|
|
_("invalid sector size argument"));
|
|
|
|
if (sz != 512 && sz != 1024 && sz != 2048 && sz != 4096)
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2013-08-30 06:06:15 -05:00
|
|
|
fdisk_save_user_sector_size(cxt, sz, sz);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2013-08-30 06:06:15 -05:00
|
|
|
}
|
2006-12-06 17:26:02 -06:00
|
|
|
case 'C':
|
2013-05-24 04:48:58 -05:00
|
|
|
fdisk_save_user_geometry(cxt,
|
|
|
|
strtou32_or_err(optarg,
|
|
|
|
_("invalid cylinders argument")),
|
|
|
|
0, 0);
|
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
|
2014-06-25 06:21:35 -05:00
|
|
|
* actively used label
|
|
|
|
*/
|
|
|
|
char *p = *optarg == '=' ? optarg + 1 : optarg;
|
2014-08-13 15:26:53 -05:00
|
|
|
struct fdisk_label *lb = fdisk_get_label(cxt, "dos");
|
2014-06-25 06:21:35 -05:00
|
|
|
|
2012-12-11 08:08:06 -06:00
|
|
|
if (!lb)
|
|
|
|
err(EXIT_FAILURE, _("not found DOS label driver"));
|
2014-06-25 06:21:35 -05:00
|
|
|
if (strcmp(p, "dos") == 0)
|
2012-12-11 08:08:06 -06:00
|
|
|
fdisk_dos_enable_compatible(lb, TRUE);
|
2014-06-25 06:21:35 -05:00
|
|
|
else if (strcmp(p, "nondos") == 0)
|
2012-12-11 08:08:06 -06:00
|
|
|
fdisk_dos_enable_compatible(lb, FALSE);
|
2014-06-25 06:21:35 -05:00
|
|
|
else {
|
|
|
|
warnx(_("unknown compatibility mode '%s'"), p);
|
2012-12-11 08:08:06 -06:00
|
|
|
usage(stderr);
|
2014-06-25 06:21:35 -05:00
|
|
|
}
|
2012-12-11 08:08:06 -06:00
|
|
|
}
|
|
|
|
/* 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':
|
2013-05-24 04:48:58 -05:00
|
|
|
fdisk_save_user_geometry(cxt, 0,
|
|
|
|
strtou32_or_err(optarg,
|
|
|
|
_("invalid heads argument")),
|
|
|
|
0);
|
2006-12-06 17:26:02 -06:00
|
|
|
break;
|
|
|
|
case 'S':
|
2013-05-24 04:48:58 -05:00
|
|
|
fdisk_save_user_geometry(cxt, 0, 0,
|
|
|
|
strtou32_or_err(optarg,
|
|
|
|
_("invalid sectors argument")));
|
2006-12-06 17:26:02 -06:00
|
|
|
break;
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'l':
|
2013-08-30 06:26:24 -05:00
|
|
|
act = ACT_LIST;
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2013-09-02 03:54:30 -05:00
|
|
|
case 'L':
|
|
|
|
if (optarg)
|
|
|
|
colormode = colormode_or_err(optarg,
|
|
|
|
_("unsupported color mode"));
|
|
|
|
break;
|
2006-12-06 17:25:35 -06:00
|
|
|
case 's':
|
2013-08-30 06:26:24 -05:00
|
|
|
act = ACT_SHOWSIZE;
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2013-10-09 09:02:42 -05:00
|
|
|
case 't':
|
|
|
|
{
|
|
|
|
struct fdisk_label *lb = NULL;
|
|
|
|
|
2014-08-13 15:26:53 -05:00
|
|
|
while (fdisk_next_label(cxt, &lb) == 0)
|
2013-10-09 09:02:42 -05:00
|
|
|
fdisk_label_set_disabled(lb, 1);
|
|
|
|
|
2014-08-13 15:26:53 -05:00
|
|
|
lb = fdisk_get_label(cxt, optarg);
|
2013-10-09 09:02:42 -05:00
|
|
|
if (!lb)
|
|
|
|
errx(EXIT_FAILURE, _("unsupported disklabel: %s"), optarg);
|
|
|
|
fdisk_label_set_disabled(lb, 0);
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'u':
|
2013-02-11 09:38:20 -06:00
|
|
|
if (optarg && *optarg == '=')
|
|
|
|
optarg++;
|
2014-08-13 15:26:53 -05:00
|
|
|
if (fdisk_set_unit(cxt, optarg) != 0)
|
2011-01-23 15:51:20 -06:00
|
|
|
usage(stderr);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2014-06-25 06:21:35 -05:00
|
|
|
case 'V': /* preferred for util-linux */
|
|
|
|
case 'v': /* for backward compatibility only */
|
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
|
|
|
|
2013-08-30 06:06:15 -05:00
|
|
|
if (argc-optind != 1 && fdisk_has_user_device_properties(cxt))
|
|
|
|
warnx(_("The device properties (sector size and geometry) should"
|
|
|
|
" be used with one specified device only."));
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2014-01-23 06:03:45 -06:00
|
|
|
colors_init(colormode, "fdisk");
|
2013-09-17 02:42:53 -05:00
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
switch (act) {
|
|
|
|
case ACT_LIST:
|
2014-08-13 15:26:53 -05:00
|
|
|
fdisk_enable_listonly(cxt, 1);
|
2013-09-17 02:42:53 -05:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (argc > optind) {
|
|
|
|
int k;
|
2006-12-06 17:26:16 -06:00
|
|
|
for (k = optind; k < argc; k++)
|
2014-07-28 04:57:10 -05:00
|
|
|
print_device_pt(cxt, argv[k], 1);
|
2011-12-15 13:02:41 -06:00
|
|
|
} else
|
2013-08-30 08:20:01 -05:00
|
|
|
print_all_devices_pt(cxt);
|
2013-08-30 06:26:24 -05:00
|
|
|
break;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
case ACT_SHOWSIZE:
|
2013-08-30 06:34:16 -05:00
|
|
|
/* deprecated */
|
2013-08-30 06:26:24 -05:00
|
|
|
if (argc - optind <= 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++) {
|
2013-08-30 06:26:24 -05:00
|
|
|
if (argc - optind == 1)
|
2012-05-21 14:23:27 -05:00
|
|
|
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
|
|
|
}
|
2013-08-30 06:26:24 -05:00
|
|
|
break;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
case ACT_FDISK:
|
|
|
|
if (argc-optind != 1)
|
|
|
|
usage(stderr);
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
/* Here starts interactive mode, use fdisk_{warn,info,..} functions */
|
2014-05-12 03:22:09 -05:00
|
|
|
color_scheme_enable("welcome", UL_COLOR_GREEN);
|
2013-09-03 05:18:33 -05:00
|
|
|
fdisk_info(cxt, _("Welcome to fdisk (%s)."), PACKAGE_STRING);
|
2013-09-02 03:54:30 -05:00
|
|
|
color_disable();
|
|
|
|
fdisk_info(cxt, _("Changes will remain in memory only, until you decide to write them.\n"
|
|
|
|
"Be careful before using the write command.\n"));
|
2013-10-18 06:52:10 -05:00
|
|
|
|
2014-08-13 15:26:53 -05:00
|
|
|
rc = fdisk_assign_device(cxt, argv[optind], 0);
|
2014-03-21 08:04:59 -05:00
|
|
|
if (rc == -EACCES) {
|
2014-08-13 15:26:53 -05:00
|
|
|
rc = fdisk_assign_device(cxt, argv[optind], 1);
|
2014-03-21 08:04:59 -05:00
|
|
|
if (rc == 0)
|
|
|
|
fdisk_warnx(cxt, _("Device open in read-only mode."));
|
|
|
|
}
|
|
|
|
if (rc)
|
2013-10-18 06:52:10 -05:00
|
|
|
err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
|
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
fflush(stdout);
|
2011-11-11 04:12:09 -06:00
|
|
|
|
2014-08-13 16:57:54 -05:00
|
|
|
if (!fdisk_has_label(cxt)) {
|
2013-10-18 06:52:10 -05:00
|
|
|
fdisk_info(cxt, _("Device does not contain a recognized partition table."));
|
2013-08-30 06:26:24 -05:00
|
|
|
fdisk_create_disklabel(cxt, NULL);
|
2013-10-23 09:59:45 -05:00
|
|
|
|
2014-08-13 16:57:54 -05:00
|
|
|
} else if (fdisk_is_label(cxt, GPT) && fdisk_gpt_is_hybrid(cxt))
|
2013-10-23 09:59:45 -05:00
|
|
|
fdisk_warnx(cxt, _(
|
2014-07-22 15:56:27 -05:00
|
|
|
"A hybrid GPT was detected. You have to sync "
|
2013-10-23 09:59:45 -05:00
|
|
|
"the hybrid MBR manually (expert command 'M')."));
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2013-08-30 06:26:24 -05:00
|
|
|
while (1)
|
|
|
|
process_fdisk_menu(&cxt);
|
|
|
|
}
|
2011-08-16 17:19:04 -05:00
|
|
|
|
2012-12-11 07:41:57 -06:00
|
|
|
fdisk_free_context(cxt);
|
2013-08-30 06:26:24 -05:00
|
|
|
return EXIT_SUCCESS;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|