summaryrefslogblamecommitdiffstats
path: root/disk-utils/blockdev.c
blob: 7f1fd7bb8e1dc4651b729e9a00f8b4a7e3681df2 (plain) (tree)



























































































































































































































                                                                                           
/*
 * blockdev.c --- Do various simple block device ioctls from the command line
 * aeb, 991028
 */

#include <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include <linux/fs.h>
#include "nls.h"

const char *progname;

struct bdc {
	char *name;
	char *iocname;
	long ioc;
	int argtype;
#define ARGNONE	0
#define ARGINTA	1
#define	ARGINTP	2
#define ARGINTG	3
#define ARGLINTG 4
	long argval;
	char *argname;
	char *help;
} bdcms[] = {
#ifdef BLKROSET
	{ "--setro", "BLKROSET", BLKROSET, ARGINTP, 1, NULL, N_("set read-only") },
	{ "--setrw", "BLKROSET", BLKROSET, ARGINTP, 0, NULL, N_("set read-write") },
#endif
#ifdef BLKROGET
	{ "--getro", "BLKROGET", BLKROGET, ARGINTG, -1, NULL, N_("get read-only") },
#endif
#ifdef BLKSSZGET
	{ "--getss", "BLKSSZGET", BLKSSZGET, ARGINTG, -1, NULL, N_("get sectorsize") },
#endif
#ifdef BLKGETSIZE
	{ "--getsize", "BLKGETSIZE", BLKGETSIZE, ARGLINTG, -1, NULL, N_("get size") },
#endif
#ifdef BLKRASET
	{ "--setra", "BLKRASET", BLKRASET, ARGINTA, 0, "READAHEAD", N_("set readahead") },
#endif
#ifdef BLKRAGET
	{ "--getra", "BLKRAGET", BLKRAGET, ARGLINTG, -1, NULL, N_("get readahead") },
#endif
#ifdef BLKFLSBUF
	{ "--flushbufs", "BLKFLSBUF", BLKFLSBUF, ARGNONE, 0, NULL, N_("flush buffers") },
#endif
#ifdef BLKRRPART
	{ "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL,
	  N_("reread partition table") },
#endif
};

#define SIZE(a)	(sizeof(a)/sizeof((a)[0]))

static void
usage(void) {
	int i;
	fprintf(stderr, _("Usage: %s [-V] [-v|-q] commands devices\n"), progname);
	fprintf(stderr, _("Available commands:\n"));
	for (i = 0; i < SIZE(bdcms); i++) {
		fprintf(stderr, "\t%s", bdcms[i].name);
		if (bdcms[i].argname)
			fprintf(stderr, " %s", bdcms[i].argname);
		if (bdcms[i].help)
			fprintf(stderr, "\t(%s)", _(bdcms[i].help));
		fprintf(stderr, "\n");
	}
	exit(1);
}

int
find_cmd(char *s) {
	int j;

	for (j = 0; j < SIZE(bdcms); j++)
		if (!strcmp(s, bdcms[j].name))
			return j;
	return -1;
}

void do_commands(int fd, char **argv, int d);

int
main(int argc, char **argv) {
	int fd, d, j, k;
	char *p;

	/* egcs-2.91.66 is buggy and says:
	   blockdev.c:93: warning: `d' might be used uninitialized */
	d = 0;

	progname = argv[0];
	if ((p = strrchr(progname, '/')) != NULL)
		progname = p+1;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	if (argc < 2)
		usage();

	/* -V not together with commands */
	if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
		printf("%s from %s\n", progname, util_linux_version);
		exit(0);
	}

	/* 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].argtype == ARGINTA)
				d++;
			continue;
		}
		if (!strcmp(argv[d], "--")) {
			d++;
			break;
		}
		if (argv[d][0] != '-')
			break;
	}

	if (d >= argc)
		usage();

	for (k = d; k < argc; k++) {
		fd = open(argv[k], O_RDONLY, 0);
		if (fd < 0) {
			perror(argv[k]);
			exit(1);
		}
		do_commands(fd, argv, d);
	}
	return 0;
}

void
do_commands(int fd, char **argv, int d) {
	int res, i, j;
	int iarg;
	long larg;
	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;
		}

		j = find_cmd(argv[i]);
		if (j == -1) {
			fprintf(stderr, _("%s: Unknown command: %s\n"), progname, argv[i]);
			usage();
		}

		switch(bdcms[j].argtype) {
		default:
		case ARGNONE:
			res = ioctl(fd, bdcms[j].ioc, 0);
			break;
		case ARGINTA:
			if (i == d-1) {
				fprintf(stderr, _("%s requires an argument\n"),
					bdcms[j].name);
				usage();
			}
			iarg = atoi(argv[++i]);
			res = ioctl(fd, bdcms[j].ioc, iarg);
			break;
		case ARGINTP:
		case ARGINTG:
			iarg = bdcms[j].argval;
			res = ioctl(fd, bdcms[j].ioc, &iarg);
			break;
		case ARGLINTG:
			larg = bdcms[j].argval;
			res = ioctl(fd, bdcms[j].ioc, &larg);
			break;
		}
		if (res == -1) {
			perror(bdcms[j].iocname);
			if (verbose)
				printf("%s failed.\n", _(bdcms[j].help));
			exit(1);
		}
		switch(bdcms[j].argtype) {
		case ARGINTG:
			if (verbose)
				printf("%s: %d\n", _(bdcms[j].help), iarg);
			else
				printf("%d\n", iarg);
			break;
		case ARGLINTG:
			if (verbose)
				printf("%s: %ld\n", _(bdcms[j].help), larg);
			else
				printf("%ld\n", larg);
			break;
		default:
			if (verbose)
				printf("%s succeeded.\n", _(bdcms[j].help));
			break;
		}
	}
}