summaryrefslogtreecommitdiffstats
path: root/disk-utils/raw.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:41 +0100
committerKarel Zak2006-12-07 00:25:41 +0100
commiteb63b9b8f4cecb34c2478282567862bc48ef256d (patch)
tree99243f8eecb44c2bb6a559982b99c680fcb649e7 /disk-utils/raw.c
parentImported from util-linux-2.9v tarball. (diff)
downloadkernel-qcow2-util-linux-eb63b9b8f4cecb34c2478282567862bc48ef256d.tar.gz
kernel-qcow2-util-linux-eb63b9b8f4cecb34c2478282567862bc48ef256d.tar.xz
kernel-qcow2-util-linux-eb63b9b8f4cecb34c2478282567862bc48ef256d.zip
Imported from util-linux-2.10f tarball.
Diffstat (limited to 'disk-utils/raw.c')
-rw-r--r--disk-utils/raw.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/disk-utils/raw.c b/disk-utils/raw.c
new file mode 100644
index 000000000..5fb95348a
--- /dev/null
+++ b/disk-utils/raw.c
@@ -0,0 +1,217 @@
+/*
+ * raw.c: User mode tool to bind and query raw character devices.
+ *
+ * Stephen Tweedie, 1999
+ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License, version 2.
+ *
+ * Copyright Red Hat Software, 1999
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
+#include <sys/raw.h>
+
+
+
+char * progname;
+int do_query = 0;
+int do_query_all = 0;
+
+int master_fd;
+int raw_minor;
+
+void open_raw_ctl(void);
+int query(int minor, int quiet);
+int bind (int minor, int block_major, int block_minor);
+
+
+static void usage(int err)
+{
+ fprintf(stderr,
+ "Usage:\n"
+ " %s /dev/rawN <major> <minor>\n"
+ " %s /dev/rawN /dev/<blockdev>\n"
+ " %s -q /dev/rawN\n"
+ " %s -qa\n",
+ progname, progname, progname, progname);
+ exit(err);
+}
+
+
+int main(int argc, char *argv[])
+{
+ char c;
+ char * raw_name;
+ char * block_name;
+ int err;
+ int block_major, block_minor;
+ int i;
+
+ struct stat statbuf;
+
+ progname = argv[0];
+
+ while ((c = getopt(argc, argv, "ahq")) != EOF) {
+ switch (c) {
+ case 'a':
+ do_query_all = 1;
+ break;
+ case 'h':
+ usage(0);
+ case 'q':
+ do_query = 1;
+ break;
+ default:
+ usage(1);
+ }
+ }
+
+ /*
+ * Check for, and open, the master raw device, /dev/raw
+ */
+
+ open_raw_ctl();
+
+ if (do_query_all) {
+ if (optind < argc)
+ usage(1);
+ for (i=1; i<255; i++)
+ query(i, 1);
+ exit(0);
+ }
+
+ /*
+ * It's a bind or a single query. Either way we need a raw device.
+ */
+
+ if (optind >= argc)
+ usage(1);
+ raw_name = argv[optind++];
+
+ err = stat(raw_name, &statbuf);
+ if (err) {
+ fprintf (stderr, "Cannot locate raw device '%s' (%s)\n",
+ raw_name, strerror(errno));
+ exit(2);
+ }
+
+ if (!S_ISCHR(statbuf.st_mode)) {
+ fprintf (stderr, "raw device '%s' is not a character dev\n",
+ raw_name);
+ exit(2);
+ }
+ if (major(statbuf.st_rdev) != RAW_MAJOR) {
+ fprintf (stderr, "Device '%s' is not a raw dev\n",
+ raw_name);
+ exit(2);
+ }
+
+ raw_minor = minor(statbuf.st_rdev);
+
+ if (do_query)
+ return query(raw_minor, 0);
+
+ /*
+ * It's not a query, so we still have some parsing to do. Have
+ * we been given a block device filename or a major/minor pair?
+ */
+
+ switch (argc - optind) {
+ case 1:
+ block_name = argv[optind];
+ err = stat(block_name, &statbuf);
+ if (err) {
+ fprintf (stderr,
+ "Cannot locate block device '%s' (%s)\n",
+ block_name, strerror(errno));
+ exit(2);
+ }
+
+ if (!S_ISBLK(statbuf.st_mode)) {
+ fprintf (stderr, "Device '%s' is not a block dev\n",
+ block_name);
+ exit(2);
+ }
+
+ block_major = major(statbuf.st_rdev);
+ block_minor = minor(statbuf.st_rdev);
+ break;
+
+ case 2:
+ block_major = strtol(argv[optind], 0, 0);
+ block_minor = strtol(argv[optind+1], 0, 0);
+ break;
+
+ default:
+ usage(1);
+ }
+
+ return bind(raw_minor, block_major, block_minor);
+ return 0;
+
+}
+
+
+void open_raw_ctl(void)
+{
+ master_fd = open("/dev/raw", O_RDWR, 0);
+ if (master_fd < 0) {
+ fprintf (stderr,
+ "Cannot open master raw device '/dev/raw' (%s)\n",
+ strerror(errno));
+ exit(2);
+ }
+}
+
+int query(int minor, int quiet)
+{
+ struct raw_config_request rq;
+ int err;
+
+ rq.raw_minor = minor;
+ err = ioctl(master_fd, RAW_GETBIND, &rq);
+ if (err < 0) {
+ if (quiet && errno == ENODEV)
+ return 3;
+ fprintf (stderr,
+ "Error querying raw device (%s)\n",
+ strerror(errno));
+ exit(3);
+ }
+ if (quiet && !rq.block_major && !rq.block_minor)
+ return 0;
+ printf ("/dev/raw%d: bound to major %d, minor %d\n",
+ minor, (int) rq.block_major, (int) rq.block_minor);
+ return 0;
+}
+
+int bind(int minor, int block_major, int block_minor)
+{
+ struct raw_config_request rq;
+ int err;
+
+ rq.raw_minor = minor;
+ rq.block_major = block_major;
+ rq.block_minor = block_minor;
+ err = ioctl(master_fd, RAW_SETBIND, &rq);
+ if (err < 0) {
+ fprintf (stderr,
+ "Error setting raw device (%s)\n",
+ strerror(errno));
+ exit(3);
+ }
+ printf ("/dev/raw%d: bound to major %d, minor %d\n",
+ raw_minor, (int) rq.block_major, (int) rq.block_minor);
+ return 0;
+}
+