#include "partx.h"
#include "sysfs.h"
#include "loopdev.h"
-#include "at.h"
#include "closestream.h"
#include "optutils.h"
};
/* columns descriptions */
-struct colinfo infos[] = {
+static struct colinfo infos[] = {
[COL_PARTNO] = { "NR", 0.25, SCOLS_FL_RIGHT, N_("partition number") },
[COL_START] = { "START", 0.30, SCOLS_FL_RIGHT, N_("start of the partition in sectors") },
[COL_END] = { "END", 0.30, SCOLS_FL_RIGHT, N_("end of the partition in sectors") },
#define NCOLS ARRAY_SIZE(infos)
/* array with IDs of enabled columns */
-static int columns[NCOLS], ncolumns;
+static int columns[NCOLS];
+static size_t ncolumns;
static int verbose;
static int partx_flags;
static inline int get_column_id(int num)
{
assert(ARRAY_SIZE(columns) == NCOLS);
- assert(num < ncolumns);
+ assert((size_t)num < ncolumns);
assert(columns[num] < (int) NCOLS);
return columns[num];
}
assert(partition);
if (devno) {
- struct sysfs_cxt cxt;
+ struct path_cxt *pc;
int rc;
- if (sysfs_init(&cxt, devno, NULL))
+ pc = ul_new_sysfs_path(devno, NULL, NULL);
+ if (!pc)
goto err;
- rc = sysfs_read_int(&cxt, "partition", &partno);
- sysfs_deinit(&cxt);
+ rc = ul_path_read_s32(pc, &partno, "partition");
+ ul_unref_path(pc);
if (rc == 0)
return partno;
sz = strlen(partition);
p = partition + sz - 1;
- if (!isdigit((unsigned int) *p))
+ if (!isdigit((unsigned char) *p))
goto err;
- while (isdigit((unsigned int) *(p - 1))) p--;
+ while (isdigit((unsigned char) *(p - 1))) p--;
errno = 0;
partno = strtol(p, &end, 10);
continue;
snprintf(path, sizeof(path), "%s/partition", d->d_name);
- fd = open_at(dirfd(dir), dirname, path, O_RDONLY);
+ fd = openat(dirfd(dir), path, O_RDONLY);
if (fd) {
int x = 0;
FILE *f = fdopen(fd, "r");
return SLICES_MAX;
}
+static int recount_range_by_pt(blkid_partlist ls, int *lower, int *upper)
+{
+ int n = 0, i, nparts = blkid_partlist_numof_partitions(ls);
+
+ for (i = 0; i < nparts; i++) {
+ blkid_partition par = blkid_partlist_get_partition(ls, i);
+ int partno = blkid_partition_get_partno(par);
+ n = max(partno, n);
+ }
+
+ if (*lower < 0)
+ *lower = n + *lower + 1;
+ if (*upper < 0)
+ *upper = n + *upper + 1;
+
+ if (*lower > *upper && *upper != 0) {
+ warnx(_("specified range <%d:%d> does not make sense"), *lower, *upper);
+ return -EINVAL;
+ }
+ if (verbose)
+ printf(_("range recount: max partno=%d, lower=%d, upper=%d\n"), n, *lower, *upper);
+ return 0;
+}
+
static void del_parts_warnx(const char *device, int first, int last)
{
if (first == last)
assert(fd >= 0);
assert(device);
+ /* recount range by information in /sys */
if (!lower)
lower = 1;
if (!upper || lower < 0 || upper < 0) {
continue;
} else if (errno == ENXIO) {
if (verbose)
- printf(_("%s: partition #%d already doesn't exist\n"), device, i);
+ printf(_("%s: partition #%d doesn't exist\n"), device, i);
continue;
}
rc = -1;
static int add_parts(int fd, const char *device,
blkid_partlist ls, int lower, int upper)
{
- int i, nparts, rc = 0, errfirst = 0, errlast = 0;
+ int i, nparts, rc, errfirst = 0, errlast = 0;
assert(fd >= 0);
assert(device);
assert(ls);
+ rc = recount_range_by_pt(ls, &lower, &upper);
+ if (rc)
+ return rc;
+
nparts = blkid_partlist_numof_partitions(ls);
for (i = 0; i < nparts; i++) {
assert(device);
assert(ls);
+ /* recount range by information in /sys, if on disk number of
+ * partitions is greater than in /sys the use on-disk limit */
nparts = blkid_partlist_numof_partitions(ls);
if (!lower)
lower = 1;
static int list_parts(blkid_partlist ls, int lower, int upper)
{
- int i, nparts;
+ int i, nparts, rc;
assert(ls);
+ rc = recount_range_by_pt(ls, &lower, &upper);
+ if (rc)
+ return rc;
+
nparts = blkid_partlist_numof_partitions(ls);
for (i = 0; i < nparts; i++) {
line = scols_table_new_line(table, NULL);
if (!line) {
- warn(_("failed to add line to output"));
+ warn(_("failed to allocate output line"));
return -ENOMEM;
}
- for (i = 0; i < ncolumns; i++) {
+ for (i = 0; (size_t)i < ncolumns; i++) {
char *str = NULL; /* allocated string */
const char *cstr = NULL; /* foreign string */
else if (str)
rc = scols_line_refer_data(line, i, str);
if (rc) {
- warn(_("failed to add data to output table"));
+ warn(_("failed to add output data"));
break;
}
}
if (!nparts)
return 0;
- table = scols_new_table(NULL);
+ scols_init_debug(0);
+ table = scols_new_table();
if (!table) {
- warn(_("failed to initialize output table"));
+ warn(_("failed to allocate output table"));
return -1;
}
- scols_table_set_raw(table, !!(scols_flags & PARTX_RAW));
- scols_table_set_export(table, !!(scols_flags & PARTX_EXPORT));
- scols_table_set_no_headings(table, !!(scols_flags & PARTX_NOHEADINGS));
+ scols_table_enable_raw(table, !!(scols_flags & PARTX_RAW));
+ scols_table_enable_export(table, !!(scols_flags & PARTX_EXPORT));
+ scols_table_enable_noheadings(table, !!(scols_flags & PARTX_NOHEADINGS));
- for (i = 0; i < ncolumns; i++) {
+ for (i = 0; (size_t)i < ncolumns; i++) {
struct colinfo *col = get_column_info(i);
if (!scols_table_new_column(table, col->name, col->whint, col->flags)) {
- warnx(_("failed to initialize output column"));
+ warnx(_("failed to allocate output column"));
goto done;
}
}
+ rc = recount_range_by_pt(ls, &lower, &upper);
+ if (rc)
+ goto done;
+
for (i = 0; i < nparts; i++) {
blkid_partition par = blkid_partlist_get_partition(ls, i);
int n = blkid_partition_get_partno(par);
return ls;
}
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static void __attribute__((__noreturn__)) usage(void)
{
+ FILE *out = stdout;
size_t i;
fputs(USAGE_HEADER, out);
_(" %s [-a|-d|-s|-u] [--nr <n:m> | <partition>] <disk>\n"),
program_invocation_short_name);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Tell the kernel about the presence and numbering of partitions.\n"), out);
+
fputs(USAGE_OPTIONS, out);
fputs(_(" -a, --add add specified partitions or all of them\n"), out);
fputs(_(" -d, --delete delete specified partitions or all of them\n"), out);
fputs(_(" -g, --noheadings don't print headings for --show\n"), out);
fputs(_(" -n, --nr <n:m> specify the range of partitions (e.g. --nr 2:4)\n"), out);
fputs(_(" -o, --output <list> define which output columns to use\n"), out);
+ fputs(_(" --output-all output all columns\n"), out);
fputs(_(" -P, --pairs use key=\"value\" output format\n"), out);
fputs(_(" -r, --raw use raw output format\n"), out);
- fputs(_(" -t, --type <type> specify the partition type (dos, bsd, solaris, etc.)\n"), out);
+ fputs(_(" -S, --sector-size <num> overwrite sector size\n"), out);
+ fputs(_(" -t, --type <type> specify the partition type\n"), out);
+ fputs(_(" --list-types list supported partition types and exit\n"), out);
fputs(_(" -v, --verbose verbose mode\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
-
- fputs(_("\nAvailable columns (for --show, --raw or --pairs):\n"), out);
+ printf(USAGE_HELP_OPTIONS(22));
+ fputs(USAGE_COLUMNS, out);
for (i = 0; i < NCOLS; i++)
fprintf(out, " %10s %s\n", infos[i].name, _(infos[i].help));
- fprintf(out, USAGE_MAN_TAIL("partx(8)"));
+ printf(USAGE_MAN_TAIL("partx(8)"));
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
int main(int argc, char **argv)
char *wholedisk = NULL; /* allocated, ie: /dev/sda */
char *outarg = NULL;
dev_t disk_devno = 0, part_devno = 0;
+ unsigned int sector_size = 0;
+ enum {
+ OPT_LIST_TYPES = CHAR_MAX + 1,
+ OPT_OUTPUT_ALL
+ };
static const struct option long_opts[] = {
{ "bytes", no_argument, NULL, 'b' },
{ "noheadings", no_argument, NULL, 'g' },
{ "delete", no_argument, NULL, 'd' },
{ "update", no_argument, NULL, 'u' },
{ "type", required_argument, NULL, 't' },
+ { "list-types", no_argument, NULL, OPT_LIST_TYPES },
{ "nr", required_argument, NULL, 'n' },
{ "output", required_argument, NULL, 'o' },
+ { "output-all", no_argument, NULL, OPT_OUTPUT_ALL },
{ "pairs", no_argument, NULL, 'P' },
+ { "sector-size",required_argument, NULL, 'S' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
- static const ul_excl_t excl[] = { /* rows and cols in in ASCII order */
- { 'P','a','d','l','r','s' },
+ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
+ { 'P','a','d','l','r','s','u' },
{ 0 }
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
while ((c = getopt_long(argc, argv,
- "abdglrsuvn:t:o:PhV", long_opts, NULL)) != -1) {
+ "abdglrsuvn:t:o:PS:hV", long_opts, NULL)) != -1) {
err_exclusive_options(c, long_opts, excl, excl_st);
case 'o':
outarg = optarg;
break;
+ case OPT_OUTPUT_ALL:
+ for (ncolumns = 0; ncolumns < ARRAY_SIZE(infos); ncolumns++)
+ columns[ncolumns] = ncolumns;
+ break;
case 'P':
scols_flags |= PARTX_EXPORT;
what = ACT_SHOW;
case 's':
what = ACT_SHOW;
break;
+ case 'S':
+ sector_size = strtou32_or_err(optarg, _("invalid sector size argument"));
+ break;
case 't':
type = optarg;
break;
case 'v':
verbose = 1;
break;
+ case OPT_LIST_TYPES:
+ {
+ size_t idx = 0;
+ const char *name = NULL;
+
+ while (blkid_partitions_get_name(idx++, &name) == 0)
+ puts(name);
+ return EXIT_SUCCESS;
+ }
case 'h':
- usage(stdout);
+ usage();
case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
- case '?':
+ print_version(EXIT_SUCCESS);
default:
- usage(stderr);
+ errtryhelp(EXIT_FAILURE);
}
}
} else {
device = argv[optind];
wholedisk = xstrdup(argv[optind + 1]);
+
+ if (device && wholedisk && !startswith(device, wholedisk))
+ errx(EXIT_FAILURE, _("partition and disk name do not match"));
}
} else if (optind == argc - 1) {
/* passed only one arg (ie: /dev/sda3 or /dev/sda) */
device = argv[optind];
if (stat(device, &sb))
- err(EXIT_FAILURE, _("stat failed %s"), device);
+ err(EXIT_FAILURE, _("stat of %s failed"), device);
part_devno = sb.st_rdev;
device = NULL;
part_devno = 0;
}
- } else
- usage(stderr);
-
+ } else {
+ warnx(_("bad usage"));
+ errtryhelp(EXIT_FAILURE);
+ }
if (device && (upper || lower))
errx(EXIT_FAILURE, _("--nr and <partition> are mutually exclusive"));
if (!pr || blkid_probe_set_device(pr, fd, 0, 0))
warnx(_("%s: failed to initialize blkid prober"),
wholedisk);
- else
+ else {
+ if (sector_size)
+ blkid_probe_set_sectorsize(pr, sector_size);
+
ls = get_partlist(pr, wholedisk, type);
+ }
if (ls) {
- int n = blkid_partlist_numof_partitions(ls);
-
- if (lower < 0)
- lower = n + lower + 1;
- if (upper < 0)
- upper = n + upper + 1;
- if (lower > upper) {
- warnx(_("specified range <%d:%d> "
- "does not make sense"), lower, upper);
- rc = -1, what = ACT_NONE;
- }
-
switch (what) {
case ACT_SHOW:
rc = show_parts(ls, scols_flags, lower, upper);
break;
case ACT_UPD:
rc = upd_parts(fd, wholedisk, disk_devno, ls, lower, upper);
+ break;
case ACT_NONE:
break;
default:
abort();
}
- }
+ } else
+ rc = 1;
+
blkid_free_probe(pr);
}