]> git.ipfire.org Git - thirdparty/util-linux.git/blame - disk-utils/raw.c
mkfs.cramfs: several strings without gettext calls
[thirdparty/util-linux.git] / disk-utils / raw.c
CommitLineData
eb63b9b8
KZ
1/*
2 * raw.c: User mode tool to bind and query raw character devices.
3 *
22853e4a 4 * Stephen Tweedie, 1999, 2000
eb63b9b8
KZ
5 *
6 * This file may be redistributed under the terms of the GNU General
7 * Public License, version 2.
8 *
22853e4a 9 * Copyright Red Hat Software, 1999, 2000
eb63b9b8
KZ
10 *
11 */
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <errno.h>
17#include <string.h>
d5c28ebc 18#include <fcntl.h>
eb63b9b8
KZ
19#include <sys/stat.h>
20#include <sys/ioctl.h>
21#include <sys/sysmacros.h>
22853e4a
KZ
22#include <linux/raw.h>
23#include <linux/major.h>
eb63b9b8 24
22853e4a
KZ
25#ifdef OLD_RAW_DEVS
26#define RAWCTLDEV "/dev/raw"
27#define RAWDEVDIR "/dev/"
28#else
29#define RAWCTLDEV "/dev/rawctl"
30#define RAWDEVDIR "/dev/raw/"
31#endif
ffc43748 32#define DEVFS_RAWCTLDEV "/dev/raw/rawctl"
eb63b9b8 33
34ab1590 34#define RAW_NR_MINORS 8192
eb63b9b8
KZ
35
36char * progname;
37int do_query = 0;
38int do_query_all = 0;
39
40int master_fd;
41int raw_minor;
42
43void open_raw_ctl(void);
44int query(int minor, int quiet);
45int bind (int minor, int block_major, int block_minor);
46
47
48static void usage(int err)
49{
50 fprintf(stderr,
51 "Usage:\n"
22853e4a
KZ
52 " %s " RAWDEVDIR "rawN <major> <minor>\n"
53 " %s " RAWDEVDIR "rawN /dev/<blockdev>\n"
54 " %s -q " RAWDEVDIR "rawN\n"
eb63b9b8
KZ
55 " %s -qa\n",
56 progname, progname, progname, progname);
57 exit(err);
58}
59
60
61int main(int argc, char *argv[])
62{
364cda48 63 int c;
eb63b9b8
KZ
64 char * raw_name;
65 char * block_name;
66 int err;
67 int block_major, block_minor;
34ab1590 68 int i, rc;
eb63b9b8
KZ
69
70 struct stat statbuf;
71
72 progname = argv[0];
73
ffc43748 74 while ((c = getopt(argc, argv, "ahq")) != -1) {
eb63b9b8
KZ
75 switch (c) {
76 case 'a':
77 do_query_all = 1;
78 break;
79 case 'h':
80 usage(0);
81 case 'q':
82 do_query = 1;
83 break;
84 default:
85 usage(1);
86 }
87 }
88
89 /*
90 * Check for, and open, the master raw device, /dev/raw
91 */
92
93 open_raw_ctl();
94
95 if (do_query_all) {
96 if (optind < argc)
97 usage(1);
34ab1590 98 for (i = 1; i < RAW_NR_MINORS; i++)
eb63b9b8
KZ
99 query(i, 1);
100 exit(0);
101 }
102
103 /*
104 * It's a bind or a single query. Either way we need a raw device.
105 */
106
107 if (optind >= argc)
108 usage(1);
109 raw_name = argv[optind++];
110
34ab1590
KZ
111 /*
112 * try to check the device name before stat(), because on systems with
113 * udev the raw0 causes a create udev event for char 162/0, which
114 * causes udev to *remove* /dev/rawctl
115 */
116 rc = sscanf(raw_name, RAWDEVDIR "raw%d", &raw_minor);
117 if (rc == 1 && raw_minor == 0) {
118 fprintf (stderr,
119 "Device '%s' is control raw dev "
120 "(use raw<N> where <N> is greater than zero)\n",
121 raw_name);
122 exit(2);
123 }
124
eb63b9b8
KZ
125 err = stat(raw_name, &statbuf);
126 if (err) {
127 fprintf (stderr, "Cannot locate raw device '%s' (%s)\n",
128 raw_name, strerror(errno));
129 exit(2);
130 }
131
132 if (!S_ISCHR(statbuf.st_mode)) {
34ab1590 133 fprintf (stderr, "Raw device '%s' is not a character dev\n",
eb63b9b8
KZ
134 raw_name);
135 exit(2);
136 }
137 if (major(statbuf.st_rdev) != RAW_MAJOR) {
138 fprintf (stderr, "Device '%s' is not a raw dev\n",
139 raw_name);
140 exit(2);
141 }
142
143 raw_minor = minor(statbuf.st_rdev);
144
145 if (do_query)
146 return query(raw_minor, 0);
34ab1590 147
eb63b9b8
KZ
148 /*
149 * It's not a query, so we still have some parsing to do. Have
150 * we been given a block device filename or a major/minor pair?
151 */
152
153 switch (argc - optind) {
154 case 1:
155 block_name = argv[optind];
156 err = stat(block_name, &statbuf);
157 if (err) {
158 fprintf (stderr,
159 "Cannot locate block device '%s' (%s)\n",
160 block_name, strerror(errno));
161 exit(2);
162 }
163
164 if (!S_ISBLK(statbuf.st_mode)) {
165 fprintf (stderr, "Device '%s' is not a block dev\n",
166 block_name);
167 exit(2);
168 }
169
170 block_major = major(statbuf.st_rdev);
171 block_minor = minor(statbuf.st_rdev);
172 break;
173
174 case 2:
175 block_major = strtol(argv[optind], 0, 0);
176 block_minor = strtol(argv[optind+1], 0, 0);
177 break;
178
179 default:
66ee8158 180 block_major = block_minor = 0; /* just to keep gcc happy */
eb63b9b8
KZ
181 usage(1);
182 }
183
184 return bind(raw_minor, block_major, block_minor);
185 return 0;
186
187}
188
189
190void open_raw_ctl(void)
191{
ffc43748
KZ
192 int errsv;
193
22853e4a 194 master_fd = open(RAWCTLDEV, O_RDWR, 0);
eb63b9b8 195 if (master_fd < 0) {
ffc43748
KZ
196 errsv = errno;
197 master_fd = open(DEVFS_RAWCTLDEV, O_RDWR, 0);
198 if (master_fd < 0) {
199 fprintf (stderr,
200 "Cannot open master raw device '"
201 RAWCTLDEV
202 "' (%s)\n", strerror(errsv));
203 exit(2);
204 }
eb63b9b8
KZ
205 }
206}
207
208int query(int minor, int quiet)
209{
210 struct raw_config_request rq;
34ab1590 211 static int has_worked = 0;
eb63b9b8 212 int err;
34ab1590 213
eb63b9b8
KZ
214 rq.raw_minor = minor;
215 err = ioctl(master_fd, RAW_GETBIND, &rq);
216 if (err < 0) {
217 if (quiet && errno == ENODEV)
218 return 3;
34ab1590
KZ
219 if (has_worked && errno == EINVAL)
220 return 0;
221 fprintf (stderr,
eb63b9b8
KZ
222 "Error querying raw device (%s)\n",
223 strerror(errno));
224 exit(3);
225 }
34ab1590
KZ
226 /* If one query has worked, mark that fact so that we don't
227 * report spurious fatal errors if raw(8) has been built to
228 * support more raw minor numbers than the kernel has. */
229 has_worked = 1;
eb63b9b8
KZ
230 if (quiet && !rq.block_major && !rq.block_minor)
231 return 0;
22853e4a 232 printf (RAWDEVDIR "raw%d: bound to major %d, minor %d\n",
eb63b9b8
KZ
233 minor, (int) rq.block_major, (int) rq.block_minor);
234 return 0;
235}
236
237int bind(int minor, int block_major, int block_minor)
238{
239 struct raw_config_request rq;
240 int err;
241
242 rq.raw_minor = minor;
243 rq.block_major = block_major;
244 rq.block_minor = block_minor;
245 err = ioctl(master_fd, RAW_SETBIND, &rq);
246 if (err < 0) {
247 fprintf (stderr,
248 "Error setting raw device (%s)\n",
249 strerror(errno));
250 exit(3);
251 }
22853e4a 252 printf (RAWDEVDIR "raw%d: bound to major %d, minor %d\n",
eb63b9b8
KZ
253 raw_minor, (int) rq.block_major, (int) rq.block_minor);
254 return 0;
255}
256