Adding upstream version 2.41.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
9586bb3c92
commit
c36e531662
3661 changed files with 2164106 additions and 0 deletions
541
disk-utils/blockdev.c
Normal file
541
disk-utils/blockdev.c
Normal file
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* blockdev.c --- Do various simple block device ioctls from the command line
|
||||
* aeb, 991028
|
||||
*
|
||||
* Copyright (C) 2007-2023 Karel Zak <kzak@redhat.com>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_LINUX_BLKZONED_H
|
||||
#include <linux/blkzoned.h>
|
||||
#endif
|
||||
|
||||
#include "c.h"
|
||||
#include "nls.h"
|
||||
#include "blkdev.h"
|
||||
#include "pathnames.h"
|
||||
#include "closestream.h"
|
||||
#include "strutils.h"
|
||||
#include "sysfs.h"
|
||||
|
||||
struct bdc {
|
||||
long ioc; /* ioctl code */
|
||||
const char *iocname; /* ioctl name (e.g. BLKROSET) */
|
||||
long argval; /* default argument */
|
||||
|
||||
const char *name; /* --setfoo */
|
||||
const char *argname; /* argument name or NULL */
|
||||
|
||||
const char *help;
|
||||
|
||||
int argtype;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* command flags */
|
||||
enum {
|
||||
FL_NOPTR = (1 << 1), /* does not assume pointer (ARG_INT only)*/
|
||||
FL_NORESULT = (1 << 2) /* does not return any data */
|
||||
};
|
||||
|
||||
/* ioctl argument types */
|
||||
enum {
|
||||
ARG_NONE,
|
||||
ARG_USHRT,
|
||||
ARG_INT,
|
||||
ARG_UINT,
|
||||
ARG_LONG,
|
||||
ARG_ULONG,
|
||||
ARG_LLONG,
|
||||
ARG_ULLONG
|
||||
};
|
||||
|
||||
#define IOCTL_ENTRY( io ) .ioc = io, .iocname = # io
|
||||
|
||||
static const struct bdc bdcms[] =
|
||||
{
|
||||
{
|
||||
IOCTL_ENTRY(BLKROSET),
|
||||
.name = "--setro",
|
||||
.argtype = ARG_INT,
|
||||
.argval = 1,
|
||||
.flags = FL_NORESULT,
|
||||
.help = N_("set read-only")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKROSET),
|
||||
.name = "--setrw",
|
||||
.argtype = ARG_INT,
|
||||
.argval = 0,
|
||||
.flags = FL_NORESULT,
|
||||
.help = N_("set read-write")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKROGET),
|
||||
.name = "--getro",
|
||||
.argtype = ARG_INT,
|
||||
.argval = -1,
|
||||
.help = N_("get read-only")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKDISCARDZEROES),
|
||||
.name = "--getdiscardzeroes",
|
||||
.argtype = ARG_UINT,
|
||||
.argval = -1,
|
||||
.help = N_("get discard zeroes support status")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKSSZGET),
|
||||
.name = "--getss",
|
||||
.argtype = ARG_INT,
|
||||
.argval = -1,
|
||||
.help = N_("get logical block (sector) size")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKPBSZGET),
|
||||
.name = "--getpbsz",
|
||||
.argtype = ARG_UINT,
|
||||
.argval = -1,
|
||||
.help = N_("get physical block (sector) size")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKIOMIN),
|
||||
.name = "--getiomin",
|
||||
.argtype = ARG_UINT,
|
||||
.argval = -1,
|
||||
.help = N_("get minimum I/O size")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKIOOPT),
|
||||
.name = "--getioopt",
|
||||
.argtype = ARG_UINT,
|
||||
.argval = -1,
|
||||
.help = N_("get optimal I/O size")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKALIGNOFF),
|
||||
.name = "--getalignoff",
|
||||
.argtype = ARG_INT,
|
||||
.argval = -1,
|
||||
.help = N_("get alignment offset in bytes")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKSECTGET),
|
||||
.name = "--getmaxsect",
|
||||
.argtype = ARG_USHRT,
|
||||
.argval = -1,
|
||||
.help = N_("get max sectors per request")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKBSZGET),
|
||||
.name = "--getbsz",
|
||||
.argtype = ARG_INT,
|
||||
.argval = -1,
|
||||
.help = N_("get blocksize")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKBSZSET),
|
||||
.name = "--setbsz",
|
||||
.argname = "<bytes>",
|
||||
.argtype = ARG_INT,
|
||||
.flags = FL_NORESULT,
|
||||
.help = N_("set blocksize on file descriptor opening the block device")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKGETSIZE),
|
||||
.name = "--getsize",
|
||||
.argtype = ARG_ULONG,
|
||||
.argval = -1,
|
||||
.help = N_("get 32-bit sector count (deprecated, use --getsz)")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKGETSIZE64),
|
||||
.name = "--getsize64",
|
||||
.argtype = ARG_ULLONG,
|
||||
.argval = -1,
|
||||
.help = N_("get size in bytes")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKRASET),
|
||||
.name = "--setra",
|
||||
.argname = "<sectors>",
|
||||
.argtype = ARG_INT,
|
||||
.flags = FL_NOPTR | FL_NORESULT,
|
||||
.help = N_("set readahead")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKRAGET),
|
||||
.name = "--getra",
|
||||
.argtype = ARG_LONG,
|
||||
.argval = -1,
|
||||
.help = N_("get readahead")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKFRASET),
|
||||
.name = "--setfra",
|
||||
.argname = "<sectors>",
|
||||
.argtype = ARG_INT,
|
||||
.flags = FL_NOPTR | FL_NORESULT,
|
||||
.help = N_("set filesystem readahead")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKFRAGET),
|
||||
.name = "--getfra",
|
||||
.argtype = ARG_LONG,
|
||||
.argval = -1,
|
||||
.help = N_("get filesystem readahead")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKGETDISKSEQ),
|
||||
.name = "--getdiskseq",
|
||||
.argtype = ARG_ULLONG,
|
||||
.argval = -1,
|
||||
.help = N_("get disk sequence number")
|
||||
},{
|
||||
#ifdef BLKGETZONESZ
|
||||
IOCTL_ENTRY(BLKGETZONESZ),
|
||||
.name = "--getzonesz",
|
||||
.argtype = ARG_UINT,
|
||||
.argval = -1,
|
||||
.help = N_("get zone size")
|
||||
},{
|
||||
#endif
|
||||
IOCTL_ENTRY(BLKFLSBUF),
|
||||
.name = "--flushbufs",
|
||||
.help = N_("flush buffers")
|
||||
},{
|
||||
IOCTL_ENTRY(BLKRRPART),
|
||||
.name = "--rereadpt",
|
||||
.help = N_("reread partition table")
|
||||
}
|
||||
};
|
||||
|
||||
static void __attribute__((__noreturn__)) usage(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
fputs(USAGE_HEADER, stdout);
|
||||
fprintf(stdout, _(
|
||||
" %1$s [-v|-q] commands devices\n"
|
||||
" %1$s --report [devices]\n"
|
||||
" %1$s -h|-V\n"
|
||||
), program_invocation_short_name);
|
||||
|
||||
fputs(USAGE_SEPARATOR, stdout);
|
||||
fputsln( _("Call block device ioctls from the command line."), stdout);
|
||||
|
||||
fputs(USAGE_OPTIONS, stdout);
|
||||
fputsln( _(" -q quiet mode"), stdout);
|
||||
fputsln( _(" -v verbose mode"), stdout);
|
||||
fputsln( _(" --report print report for specified (or all) devices"), stdout);
|
||||
fputs(USAGE_SEPARATOR, stdout);
|
||||
fprintf(stdout, USAGE_HELP_OPTIONS(16));
|
||||
|
||||
fputs(USAGE_SEPARATOR, stdout);
|
||||
fputsln( _("Available commands:"), stdout);
|
||||
fprintf(stdout, _(" %-25s get size in 512-byte sectors\n"), "--getsz");
|
||||
for (i = 0; i < ARRAY_SIZE(bdcms); i++) {
|
||||
if (bdcms[i].argname)
|
||||
fprintf(stdout, " %s %-*s %s\n", bdcms[i].name,
|
||||
(int)(24 - strlen(bdcms[i].name)),
|
||||
bdcms[i].argname, _(bdcms[i].help));
|
||||
else
|
||||
fprintf(stdout, " %-25s %s\n", bdcms[i].name,
|
||||
_(bdcms[i].help));
|
||||
}
|
||||
|
||||
fprintf(stdout, USAGE_MAN_TAIL("blockdev(8)"));
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int find_cmd(char *s)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(bdcms); j++)
|
||||
if (!strcmp(s, bdcms[j].name))
|
||||
return j;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void do_commands(int fd, char **argv, int d);
|
||||
static void report_header(void);
|
||||
static int report_device(char *device, int quiet);
|
||||
static int report_all_devices(void);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, d, j, k;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
close_stdout_atexit();
|
||||
|
||||
if (argc < 2) {
|
||||
warnx(_("not enough arguments"));
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* -V not together with commands */
|
||||
if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))
|
||||
print_version(EXIT_SUCCESS);
|
||||
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
|
||||
usage();
|
||||
|
||||
/* --report not together with other commands */
|
||||
if (!strcmp(argv[1], "--report")) {
|
||||
int rc = 0;
|
||||
report_header();
|
||||
if (argc > 2) {
|
||||
for (d = 2; d < argc; d++)
|
||||
rc += report_device(argv[d], 0);
|
||||
} else {
|
||||
rc = report_all_devices();
|
||||
}
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* do each of the commands on each of the devices */
|
||||
/* devices start after last command */
|
||||
for (d = 1; d < argc; d++) {
|
||||
j = find_cmd(argv[d]);
|
||||
if (j >= 0) {
|
||||
if (bdcms[j].argname)
|
||||
d++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[d], "--getsz"))
|
||||
continue;
|
||||
if (!strcmp(argv[d], "--")) {
|
||||
d++;
|
||||
break;
|
||||
}
|
||||
if (argv[d][0] != '-')
|
||||
break;
|
||||
}
|
||||
|
||||
if (d >= argc) {
|
||||
warnx(_("no device specified"));
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (k = d; k < argc; k++) {
|
||||
fd = open(argv[k], O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
err(EXIT_FAILURE, _("cannot open %s"), argv[k]);
|
||||
do_commands(fd, argv, d);
|
||||
close(fd);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void do_commands(int fd, char **argv, int d)
|
||||
{
|
||||
int res, i, j;
|
||||
int iarg = 0;
|
||||
unsigned int uarg = 0;
|
||||
unsigned short huarg = 0;
|
||||
long larg = 0;
|
||||
long long llarg = 0;
|
||||
unsigned long lu = 0;
|
||||
unsigned long long llu = 0;
|
||||
int verbose = 0;
|
||||
|
||||
for (i = 1; i < d; i++) {
|
||||
if (!strcmp(argv[i], "-v")) {
|
||||
verbose = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-q")) {
|
||||
verbose = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "--getsz")) {
|
||||
res = blkdev_get_sectors(fd, &llu);
|
||||
if (res == 0) {
|
||||
if (verbose)
|
||||
printf(_("get size in 512-byte sectors: "));
|
||||
printf("%lld\n", llu);
|
||||
}
|
||||
else
|
||||
errx(EXIT_FAILURE,
|
||||
_("could not get device size"));
|
||||
continue;
|
||||
}
|
||||
|
||||
j = find_cmd(argv[i]);
|
||||
if (j == -1) {
|
||||
warnx(_("Unknown command: %s"), argv[i]);
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (bdcms[j].argtype) {
|
||||
default:
|
||||
case ARG_NONE:
|
||||
res = ioctl(fd, bdcms[j].ioc, 0);
|
||||
break;
|
||||
case ARG_USHRT:
|
||||
huarg = bdcms[j].argval;
|
||||
res = ioctl(fd, bdcms[j].ioc, &huarg);
|
||||
break;
|
||||
case ARG_INT:
|
||||
if (bdcms[j].argname) {
|
||||
if (i == d - 1) {
|
||||
warnx(_("%s requires an argument"),
|
||||
bdcms[j].name);
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
}
|
||||
iarg = strtos32_or_err(argv[++i], _("failed to parse command argument"));
|
||||
} else
|
||||
iarg = bdcms[j].argval;
|
||||
|
||||
res = bdcms[j].flags & FL_NOPTR ?
|
||||
ioctl(fd, bdcms[j].ioc, iarg) :
|
||||
ioctl(fd, bdcms[j].ioc, &iarg);
|
||||
break;
|
||||
case ARG_UINT:
|
||||
uarg = bdcms[j].argval;
|
||||
res = ioctl(fd, bdcms[j].ioc, &uarg);
|
||||
break;
|
||||
case ARG_LONG:
|
||||
larg = bdcms[j].argval;
|
||||
res = ioctl(fd, bdcms[j].ioc, &larg);
|
||||
break;
|
||||
case ARG_LLONG:
|
||||
llarg = bdcms[j].argval;
|
||||
res = ioctl(fd, bdcms[j].ioc, &llarg);
|
||||
break;
|
||||
case ARG_ULONG:
|
||||
lu = bdcms[j].argval;
|
||||
res = ioctl(fd, bdcms[j].ioc, &lu);
|
||||
break;
|
||||
case ARG_ULLONG:
|
||||
llu = bdcms[j].argval;
|
||||
res = ioctl(fd, bdcms[j].ioc, &llu);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == -1) {
|
||||
warn(_("ioctl error on %s"), bdcms[j].iocname);
|
||||
if (verbose)
|
||||
printf(_("%s failed.\n"), _(bdcms[j].help));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (bdcms[j].argtype == ARG_NONE ||
|
||||
(bdcms[j].flags & FL_NORESULT)) {
|
||||
if (verbose)
|
||||
printf(_("%s succeeded.\n"), _(bdcms[j].help));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("%s: ", _(bdcms[j].help));
|
||||
|
||||
switch (bdcms[j].argtype) {
|
||||
case ARG_USHRT:
|
||||
printf("%hu\n", huarg);
|
||||
break;
|
||||
case ARG_INT:
|
||||
printf("%d\n", iarg);
|
||||
break;
|
||||
case ARG_UINT:
|
||||
printf("%u\n", uarg);
|
||||
break;
|
||||
case ARG_LONG:
|
||||
printf("%ld\n", larg);
|
||||
break;
|
||||
case ARG_LLONG:
|
||||
printf("%lld\n", llarg);
|
||||
break;
|
||||
case ARG_ULONG:
|
||||
printf("%lu\n", lu);
|
||||
break;
|
||||
case ARG_ULLONG:
|
||||
printf("%llu\n", llu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int report_all_devices(void)
|
||||
{
|
||||
FILE *procpt;
|
||||
char line[200];
|
||||
char ptname[200 + 1];
|
||||
char device[210];
|
||||
int ma, mi, sz;
|
||||
int rc = 0;
|
||||
|
||||
procpt = fopen(_PATH_PROC_PARTITIONS, "r");
|
||||
if (!procpt)
|
||||
err(EXIT_FAILURE, _("cannot open %s"), _PATH_PROC_PARTITIONS);
|
||||
|
||||
while (fgets(line, sizeof(line), procpt)) {
|
||||
if (sscanf(line, " %d %d %d %200[^\n ]",
|
||||
&ma, &mi, &sz, ptname) != 4)
|
||||
continue;
|
||||
|
||||
snprintf(device, sizeof(device), "/dev/%s", ptname);
|
||||
rc += report_device(device, 1);
|
||||
}
|
||||
|
||||
fclose(procpt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int report_device(char *device, int quiet)
|
||||
{
|
||||
int fd;
|
||||
int ro, ssz, bsz;
|
||||
int rc = 0;
|
||||
long ra;
|
||||
unsigned long long bytes;
|
||||
uint64_t start = 0;
|
||||
char start_str[16] = { "\0" };
|
||||
struct stat st;
|
||||
|
||||
fd = open(device, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
if (!quiet)
|
||||
warn(_("cannot open %s"), device);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ro = ssz = bsz = 0;
|
||||
ra = 0;
|
||||
if (fstat(fd, &st) == 0) {
|
||||
dev_t disk;
|
||||
struct path_cxt *pc;
|
||||
|
||||
pc = ul_new_sysfs_path(st.st_rdev, NULL, NULL);
|
||||
if (pc &&
|
||||
sysfs_blkdev_get_wholedisk(pc, NULL, 0, &disk) == 0 &&
|
||||
disk != st.st_rdev) {
|
||||
|
||||
if (ul_path_read_u64(pc, &start, "start") != 0)
|
||||
/* TRANSLATORS: Start sector not available. Max. 15 letters. */
|
||||
snprintf(start_str, sizeof(start_str), "%15s", _("N/A"));
|
||||
}
|
||||
ul_unref_path(pc);
|
||||
}
|
||||
if (!*start_str)
|
||||
snprintf(start_str, sizeof(start_str), "%15ju", start);
|
||||
|
||||
if (ioctl(fd, BLKROGET, &ro) == 0 &&
|
||||
ioctl(fd, BLKRAGET, &ra) == 0 &&
|
||||
ioctl(fd, BLKSSZGET, &ssz) == 0 &&
|
||||
ioctl(fd, BLKBSZGET, &bsz) == 0 &&
|
||||
blkdev_get_size(fd, &bytes) == 0) {
|
||||
printf("%s %5ld %5d %5d %s %15lld %s\n",
|
||||
ro ? "ro" : "rw", ra, ssz, bsz, start_str, bytes, device);
|
||||
} else {
|
||||
if (!quiet)
|
||||
warnx(_("ioctl error on %s"), device);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void report_header(void)
|
||||
{
|
||||
printf(_("RO RA SSZ BSZ StartSec Size Device\n"));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue