diff options
author | Karel Zak | 2006-12-07 00:25:41 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:41 +0100 |
commit | eb63b9b8f4cecb34c2478282567862bc48ef256d (patch) | |
tree | 99243f8eecb44c2bb6a559982b99c680fcb649e7 /disk-utils/raw.c | |
parent | Imported from util-linux-2.9v tarball. (diff) | |
download | kernel-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.c | 217 |
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; +} + |