Upload Tizen:Base source
[framework/base/util-linux-ng.git] / sys-utils / rdev.c
1 /*
2
3   rdev.c  -  query/set root device.
4
5 -------------------------------------------------------------------------
6
7 Date: Sun, 27 Dec 1992 15:55:31 +0000
8 Subject: Re: rdev
9 From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
10 To: Rik Faith <faith@cs.unc.edu>
11
12 There are quite a few versions of rdev:
13
14   - the original rootdev that only printed the current root device, by
15     Linus.
16   - rdev that does what rootdev did and that also allows you to change
17     the root (and swap) device, by me.
18   - rdev got renamed to setroot and I think even to rootdev on various
19     distributions.
20   - Peter MacDonald added video mode and RAM disk setting and included
21     this version on SLS, called rdev again. I've attached his rdev.c to
22     this mail.
23     
24 -------------------------------------------------------------------------
25     
26 Date: 11 Mar 92 21:37:37 GMT
27 Subject: rdev - query/set root device
28 From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
29 Organization: Swiss Federal Institute of Technology (ETH), Zurich, CH
30
31 With all that socket, X11, disk driver and FS hacking going on, apparently
32 nobody has found time to address one of the minor nuisances of life: set-
33 ting the root FS device is still somewhat cumbersome. I've written a little
34 utility which can read and set the root device in boot images:
35
36 rdev accepts an optional offset argument, just in case the address should
37 ever move from 508. If called without arguments, rdev outputs an mtab line
38 for the current root FS, just like /etc/rootdev does.
39
40 ramsize sets the size of the ramdisk.  If size is zero, no ramdisk is used.
41
42 vidmode sets the default video mode at bootup time.  -1 uses default video
43 mode, -2 uses menu.
44
45 -------------------------------------------------------------------------
46
47 Sun Dec 27 10:42:16 1992: Minor usage changes, faith@cs.unc.edu.
48 Tue Mar 30 09:31:52 1993: rdev -Rn to set root readonly flag, sct@dcs.ed.ac.uk
49 Wed Jun 22 21:12:29 1994: Applied patches from Dave
50                           (gentzel@nova.enet.dec.com) to prevent dereferencing
51                           the NULL pointer, faith@cs.unc.edu
52 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
53 - added Native Language Support
54
55 -------------------------------------------------------------------------
56
57 */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <ctype.h>
63 #include <errno.h>
64 #include <fcntl.h>
65 #include <dirent.h>
66 #include <unistd.h>
67 #include <sys/types.h>
68 #include <sys/stat.h>
69
70 #include "nls.h"
71
72 /* rdev.c  -  query/set root device. */
73
74 static void
75 usage(void) {
76
77     puts(_("usage: rdev [ -rv ] [ -o OFFSET ] [ IMAGE [ VALUE [ OFFSET ] ] ]"));
78     puts(_("  rdev /dev/fd0  (or rdev /linux, etc.) displays the current ROOT device"));
79     puts(_("  rdev /dev/fd0 /dev/hda2         sets ROOT to /dev/hda2"));
80     puts(_("  rdev -R /dev/fd0 1              set the ROOTFLAGS (readonly status)"));
81     puts(_("  rdev -r /dev/fd0 627            set the RAMDISK size"));
82     puts(_("  rdev -v /dev/fd0 1              set the bootup VIDEOMODE"));
83     puts(_("  rdev -o N ...                   use the byte offset N"));
84     puts(_("  rootflags ...                   same as rdev -R"));
85     puts(_("  ramsize ...                     same as rdev -r"));
86     puts(_("  vidmode ...                     same as rdev -v"));
87     puts(_("Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,..."));
88     puts(_("      use -R 1 to mount root readonly, -R 0 for read/write."));
89     exit(-1);
90 }
91
92
93 #define DEFAULT_OFFSET 508
94
95
96 static void
97 die(char *msg) {
98         perror(msg);
99         exit(1);
100 }
101
102 /* Earlier rdev fails on /dev/ida/c0d0p1 so we allow for
103    recursion in /dev. -- Paul Clements */
104 /* In fact devfs needs deep recursion. */
105
106 static int
107 find_dev_recursive(char *dirnamebuf, int number) {
108         DIR *dp;
109         struct dirent *dir;
110         struct stat s;
111         int dirnamelen = 0;
112
113         if ((dp = opendir(dirnamebuf)) == NULL)
114                 die("opendir");
115         dirnamelen = strlen(dirnamebuf);
116         while ((dir = readdir(dp)) != NULL) {
117                 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
118                         continue;
119                 if (dirnamelen + 1 + strlen(dir->d_name) > PATH_MAX)
120                         continue;
121                 dirnamebuf[dirnamelen] = '/';
122                 strcpy(dirnamebuf+dirnamelen+1, dir->d_name);
123                 if (lstat(dirnamebuf, &s) < 0)
124                         continue;
125                 if ((s.st_mode & S_IFMT) == S_IFBLK && s.st_rdev == number)
126                         return 1;
127                 if ((s.st_mode & S_IFMT) == S_IFDIR &&
128                     find_dev_recursive(dirnamebuf, number))
129                         return 1;
130         }
131         dirnamebuf[dirnamelen] = 0;
132         closedir(dp);
133         return 0;
134 }
135
136 static char *
137 find_dev(int number) {
138         static char name[PATH_MAX+1];
139
140         if (!number)
141                 return "Boot device";
142         strcpy(name, "/dev");
143         if (find_dev_recursive(name, number))
144                 return name;
145         sprintf(name, "0x%04x", number);
146         return name;
147 }
148
149 /* The enum values are significant, things are stored in this order,
150    see bootsect.S */
151 enum { RDEV, VIDMODE, RAMSIZE, __swapdev__, __syssize__, ROOTFLAGS };
152 char *cmdnames[6] = { "rdev", "vidmode",  "ramsize", "", 
153                       "", "rootflags"};
154 char *desc[6] = { "Root device", "Video mode",  "Ramsize",  "",
155                   "", "Root flags"};
156 #define shift(n) argv+=n,argc-=n
157
158 int
159 main(int argc, char **argv) {
160         int image, offset, dev_nr, i, newoffset=-1;
161         char *ptr;
162         unsigned short val, have_val;
163         struct stat s;
164         int cmd;
165
166         setlocale(LC_ALL, "");
167         bindtextdomain(PACKAGE, LOCALEDIR);
168         textdomain(PACKAGE);
169
170         /* use the command name to figure out what we have to do - ugly */
171         cmd = RDEV;
172         if ((ptr = strrchr(argv[0],'/')) != NULL)
173                 ptr++;
174         else
175                 ptr = argv[0];
176         for (i=0; i<=5; i++) {
177                 if (!strcmp(ptr,cmdnames[i])) {
178                         cmd = i;
179                         break;
180                 }
181         }
182
183         while (argc > 1) { 
184                 if (argv[1][0] != '-')
185                         break;
186                 switch (argv[1][1]) {
187                 case 'R':
188                         cmd = ROOTFLAGS;
189                         shift(1);
190                         break;
191                 case 'r': 
192                         cmd = RAMSIZE;
193                         shift(1);
194                         break;
195                 case 'v':
196                         cmd = VIDMODE;
197                         shift(1);
198                         break;
199                 case 'o':
200                         if (argv[1][2]) {
201                                 newoffset = atoi(argv[1]+2);
202                                 shift(1);
203                                 break;
204                         } else if (argc > 2) {
205                                 newoffset = atoi(argv[2]);
206                                 shift(2);
207                                 break;
208                         }
209                         /* Fall through. . . */
210                 default:
211                         usage();
212                 }
213         }
214
215         /* Here the only sensible way of using rdev */
216         if (argc == 1) {
217                 if (cmd == RDEV) {
218                         if (stat("/",&s) < 0) die("/");
219                         printf("%s /\n", find_dev(s.st_dev));
220                         exit(0);
221                 }
222                 usage();
223         }
224
225         if (argc > 4)
226                 usage();
227
228         /* Ancient garbage.. */
229         offset = DEFAULT_OFFSET-cmd*2;
230         if (newoffset >= 0)
231                 offset = newoffset;
232         if (argc == 4)
233                 offset = atoi(argv[3]);
234
235         have_val = 0;
236
237         if (argc >= 3) {
238                 if (cmd == RDEV) {
239                         if (isdigit(*argv[2])) {
240                                 /* earlier: specify offset */
241                                 /* now: specify major,minor */
242                                 char *p;
243                                 unsigned int ma,mi;
244                                 if ((p = strchr(argv[2], ',')) == NULL)
245                                         die(_("missing comma"));
246                                 ma = atoi(argv[2]);
247                                 mi = atoi(p+1);
248                                 val = ((ma<<8) | mi);
249                         } else {
250                                 char *device = argv[2];
251                                 if (stat(device,&s) < 0)
252                                         die(device);
253                                 val = s.st_rdev;
254                         }
255                 } else {
256                         val = atoi(argv[2]);
257                 }
258                 have_val = 1;
259         }
260
261         if (have_val) {
262                 if ((image = open(argv[1],O_WRONLY)) < 0) die(argv[1]);
263                 if (lseek(image,offset,0) < 0) die("lseek");
264                 if (write(image,(char *)&val,2) != 2) die(argv[1]);
265                 if (close(image) < 0) die("close");
266         } else {
267                 if ((image = open(argv[1],O_RDONLY)) < 0) die(argv[1]);
268                 if (lseek(image,offset,0) < 0) die("lseek");
269                 dev_nr = 0;
270                 if (read(image,(char *)&dev_nr,2) != 2) die(argv[1]);
271                 if (close(image) < 0) die("close");
272                 fputs(desc[cmd], stdout);
273                 if (cmd == RDEV)
274                         printf(" %s\n", find_dev(dev_nr));
275                 else
276                         printf(" %d\n", dev_nr);
277         }
278         return 0;
279 }