diff options
Diffstat (limited to 'util-linux')
-rw-r--r-- | util-linux/dmesg.c | 95 | ||||
-rw-r--r-- | util-linux/fdflush.c | 36 | ||||
-rw-r--r-- | util-linux/mkswap.c | 253 | ||||
-rw-r--r-- | util-linux/more.c | 110 | ||||
-rw-r--r-- | util-linux/mount.c | 430 | ||||
-rw-r--r-- | util-linux/umount.c | 135 |
6 files changed, 1059 insertions, 0 deletions
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c new file mode 100644 index 000000000..a63fa3d39 --- /dev/null +++ b/util-linux/dmesg.c | |||
@@ -0,0 +1,95 @@ | |||
1 | #include "internal.h" | ||
2 | #include <stdlib.h> | ||
3 | #include <unistd.h> | ||
4 | #include <time.h> | ||
5 | |||
6 | /* dmesg.c -- Print out the contents of the kernel ring buffer | ||
7 | * Created: Sat Oct 9 16:19:47 1993 | ||
8 | * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu | ||
9 | * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) | ||
10 | * This program comes with ABSOLUTELY NO WARRANTY. | ||
11 | * Modifications by Rick Sladkey (jrs@world.std.com) | ||
12 | * from util-linux; adapted for busybox | ||
13 | */ | ||
14 | |||
15 | #include <linux/unistd.h> | ||
16 | #include <stdio.h> | ||
17 | #include <getopt.h> | ||
18 | |||
19 | #define __NR_klog __NR_syslog | ||
20 | |||
21 | #if defined(__GLIBC__) | ||
22 | #include <sys/klog.h> | ||
23 | #define klog klogctl | ||
24 | #else | ||
25 | static inline _syscall3(int,klog,int,type,char *,b,int,len) | ||
26 | #endif /* __GLIBC__ */ | ||
27 | |||
28 | const char dmesg_usage[] = "dmesg"; | ||
29 | |||
30 | int | ||
31 | dmesg_main(struct FileInfo * info, int argc, char * * argv) | ||
32 | { | ||
33 | |||
34 | char buf[4096]; | ||
35 | int i; | ||
36 | int n; | ||
37 | int c; | ||
38 | int level = 0; | ||
39 | int lastc; | ||
40 | int cmd = 3; | ||
41 | |||
42 | while ((c = getopt( argc, argv, "cn:" )) != EOF) { | ||
43 | switch (c) { | ||
44 | case 'c': | ||
45 | cmd = 4; | ||
46 | break; | ||
47 | case 'n': | ||
48 | cmd = 8; | ||
49 | level = atoi(optarg); | ||
50 | break; | ||
51 | case '?': | ||
52 | default: | ||
53 | usage(dmesg_usage); | ||
54 | exit(1); | ||
55 | } | ||
56 | } | ||
57 | argc -= optind; | ||
58 | argv += optind; | ||
59 | |||
60 | if (argc > 1) { | ||
61 | usage(dmesg_usage); | ||
62 | exit(1); | ||
63 | } | ||
64 | |||
65 | if (cmd == 8) { | ||
66 | n = klog( cmd, NULL, level ); | ||
67 | if (n < 0) { | ||
68 | perror( "klog" ); | ||
69 | exit( 1 ); | ||
70 | } | ||
71 | exit( 0 ); | ||
72 | } | ||
73 | |||
74 | n = klog( cmd, buf, sizeof( buf ) ); | ||
75 | if (n < 0) { | ||
76 | perror( "klog" ); | ||
77 | exit( 1 ); | ||
78 | } | ||
79 | |||
80 | lastc = '\n'; | ||
81 | for (i = 0; i < n; i++) { | ||
82 | if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { | ||
83 | i++; | ||
84 | while (buf[i] >= '0' && buf[i] <= '9') | ||
85 | i++; | ||
86 | if (buf[i] == '>') | ||
87 | i++; | ||
88 | } | ||
89 | lastc = buf[i]; | ||
90 | putchar( lastc ); | ||
91 | } | ||
92 | if (lastc != '\n') | ||
93 | putchar( '\n' ); | ||
94 | return 0; | ||
95 | } | ||
diff --git a/util-linux/fdflush.c b/util-linux/fdflush.c new file mode 100644 index 000000000..a15e9b3f7 --- /dev/null +++ b/util-linux/fdflush.c | |||
@@ -0,0 +1,36 @@ | |||
1 | #include "internal.h" | ||
2 | #include <sys/ioctl.h> | ||
3 | #include <linux/fd.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/stat.h> | ||
6 | #include <fcntl.h> | ||
7 | |||
8 | const char fdflush_usage[] = "fdflush device"; | ||
9 | |||
10 | int | ||
11 | fdflush(const char *filename) | ||
12 | { | ||
13 | int status; | ||
14 | int fd = open(filename, 0); | ||
15 | |||
16 | if ( fd < 0 ) { | ||
17 | name_and_error(filename); | ||
18 | return 1; | ||
19 | } | ||
20 | |||
21 | status = ioctl(fd, FDFLUSH, 0); | ||
22 | close(fd); | ||
23 | |||
24 | if ( status != 0 ) { | ||
25 | name_and_error(filename); | ||
26 | return 1; | ||
27 | } | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | |||
32 | int | ||
33 | fdflush_fn(const struct FileInfo * i) | ||
34 | { | ||
35 | return fdflush(i->source); | ||
36 | } | ||
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c new file mode 100644 index 000000000..f797d1395 --- /dev/null +++ b/util-linux/mkswap.c | |||
@@ -0,0 +1,253 @@ | |||
1 | #include "internal.h" | ||
2 | /* | ||
3 | * mkswap.c - set up a linux swap device | ||
4 | * | ||
5 | * (C) 1991 Linus Torvalds. This file may be redistributed as per | ||
6 | * the Linux copyright. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * 20.12.91 - time began. Got VM working yesterday by doing this by hand. | ||
11 | * | ||
12 | * Usage: mkswap [-c] device [size-in-blocks] | ||
13 | * | ||
14 | * -c for readablility checking (use it unless you are SURE!) | ||
15 | * | ||
16 | * The device may be a block device or a image of one, but this isn't | ||
17 | * enforced (but it's not much fun on a character device :-). | ||
18 | * | ||
19 | * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the | ||
20 | * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. | ||
21 | */ | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <unistd.h> | ||
25 | #include <string.h> | ||
26 | #include <fcntl.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <sys/stat.h> | ||
29 | #include <sys/ioctl.h> | ||
30 | |||
31 | #include <asm/page.h> | ||
32 | #include <linux/fs.h> | ||
33 | |||
34 | #ifndef __linux__ | ||
35 | # define volatile | ||
36 | #endif | ||
37 | |||
38 | #define TEST_BUFFER_PAGES 8 | ||
39 | |||
40 | const char mkswap_usage[] = "mkswap [-c] partition [block-count]\n" | ||
41 | "\n" | ||
42 | "\tPrepare a disk partition to be used as a swap partition.\n" | ||
43 | "\tThe default block count is the size of the entire partition.\n" | ||
44 | "\n" | ||
45 | "\t-c:\tCheck for read-ability.\n" | ||
46 | "\tblock-count\tUse only this many blocks.\n"; | ||
47 | |||
48 | static const char * program_name = "mkswap"; | ||
49 | static const char * device_name = NULL; | ||
50 | static int DEV = -1; | ||
51 | static long PAGES = 0; | ||
52 | static int do_check = 0; | ||
53 | static int badpages = 0; | ||
54 | |||
55 | |||
56 | static long bit_test_and_set (unsigned int *addr, unsigned int nr) | ||
57 | { | ||
58 | unsigned int r, m; | ||
59 | |||
60 | addr += nr / (8 * sizeof(int)); | ||
61 | r = *addr; | ||
62 | m = 1 << (nr & (8 * sizeof(int) - 1)); | ||
63 | *addr = r | m; | ||
64 | return (r & m) != 0; | ||
65 | } | ||
66 | |||
67 | static int bit_test_and_clear (unsigned int *addr, unsigned int nr) | ||
68 | { | ||
69 | unsigned int r, m; | ||
70 | |||
71 | addr += nr / (8 * sizeof(int)); | ||
72 | r = *addr; | ||
73 | m = 1 << (nr & (8 * sizeof(int) - 1)); | ||
74 | *addr = r & ~m; | ||
75 | return (r & m) != 0; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Volatile to let gcc know that this doesn't return. When trying | ||
80 | * to compile this under minix, volatile gives a warning, as | ||
81 | * exit() isn't defined as volatile under minix. | ||
82 | */ | ||
83 | volatile void fatal_error(const char * fmt_string) | ||
84 | { | ||
85 | fprintf(stderr,fmt_string,program_name,device_name); | ||
86 | exit(1); | ||
87 | } | ||
88 | |||
89 | #define die(str) fatal_error("%s: " str "\n") | ||
90 | |||
91 | static void check_blocks(int * signature_page) | ||
92 | { | ||
93 | unsigned int current_page; | ||
94 | int do_seek = 1; | ||
95 | char buffer[PAGE_SIZE]; | ||
96 | |||
97 | current_page = 0; | ||
98 | while (current_page < PAGES) { | ||
99 | if (!do_check) { | ||
100 | bit_test_and_set(signature_page,current_page++); | ||
101 | continue; | ||
102 | } else { | ||
103 | printf("\r%d", current_page); | ||
104 | } | ||
105 | if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) != | ||
106 | current_page*PAGE_SIZE) | ||
107 | die("seek failed in check_blocks"); | ||
108 | if ( (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) ) { | ||
109 | bit_test_and_clear(signature_page,current_page++); | ||
110 | badpages++; | ||
111 | continue; | ||
112 | } | ||
113 | bit_test_and_set(signature_page,current_page++); | ||
114 | } | ||
115 | if (do_check) | ||
116 | printf("\n"); | ||
117 | if (badpages) | ||
118 | printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); | ||
119 | } | ||
120 | |||
121 | static long valid_offset (int fd, int offset) | ||
122 | { | ||
123 | char ch; | ||
124 | |||
125 | if (lseek (fd, offset, 0) < 0) | ||
126 | return 0; | ||
127 | if (read (fd, &ch, 1) < 1) | ||
128 | return 0; | ||
129 | return 1; | ||
130 | } | ||
131 | |||
132 | static int count_blocks (int fd) | ||
133 | { | ||
134 | int high, low; | ||
135 | |||
136 | low = 0; | ||
137 | for (high = 1; valid_offset (fd, high); high *= 2) | ||
138 | low = high; | ||
139 | while (low < high - 1) | ||
140 | { | ||
141 | const int mid = (low + high) / 2; | ||
142 | |||
143 | if (valid_offset (fd, mid)) | ||
144 | low = mid; | ||
145 | else | ||
146 | high = mid; | ||
147 | } | ||
148 | valid_offset (fd, 0); | ||
149 | return (low + 1); | ||
150 | } | ||
151 | |||
152 | static int get_size(const char *file) | ||
153 | { | ||
154 | int fd; | ||
155 | int size; | ||
156 | |||
157 | fd = open(file, O_RDWR); | ||
158 | if (fd < 0) { | ||
159 | perror(file); | ||
160 | exit(1); | ||
161 | } | ||
162 | if (ioctl(fd, BLKGETSIZE, &size) >= 0) { | ||
163 | close(fd); | ||
164 | return (size * 512); | ||
165 | } | ||
166 | |||
167 | size = count_blocks(fd); | ||
168 | close(fd); | ||
169 | return size; | ||
170 | } | ||
171 | |||
172 | int | ||
173 | mkswap(char *device_name, int pages, int check) | ||
174 | { | ||
175 | struct stat statbuf; | ||
176 | int goodpages; | ||
177 | int signature_page[PAGE_SIZE/sizeof(int)]; | ||
178 | |||
179 | PAGES = pages; | ||
180 | do_check = check; | ||
181 | |||
182 | memset(signature_page,0,PAGE_SIZE); | ||
183 | |||
184 | if (device_name && !PAGES) { | ||
185 | PAGES = get_size(device_name) / PAGE_SIZE; | ||
186 | } | ||
187 | if (!device_name || PAGES<10) { | ||
188 | fprintf(stderr, | ||
189 | "%s: error: swap area needs to be at least %ldkB\n", | ||
190 | program_name, 10 * PAGE_SIZE / 1024); | ||
191 | /* usage(mkswap_usage); */ | ||
192 | exit(1); | ||
193 | } | ||
194 | if (PAGES > 8 * (PAGE_SIZE - 10)) { | ||
195 | PAGES = 8 * (PAGE_SIZE - 10); | ||
196 | fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", | ||
197 | program_name, PAGES * PAGE_SIZE / 1024); | ||
198 | } | ||
199 | DEV = open(device_name,O_RDWR); | ||
200 | if (DEV < 0 || fstat(DEV, &statbuf) < 0) { | ||
201 | perror(device_name); | ||
202 | exit(1); | ||
203 | } | ||
204 | if (!S_ISBLK(statbuf.st_mode)) | ||
205 | do_check=0; | ||
206 | else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) | ||
207 | die("Will not try to make swapdevice on '%s'"); | ||
208 | check_blocks(signature_page); | ||
209 | if (!bit_test_and_clear(signature_page,0)) | ||
210 | die("fatal: first page unreadable"); | ||
211 | goodpages = PAGES - badpages - 1; | ||
212 | if (goodpages <= 0) | ||
213 | die("Unable to set up swap-space: unreadable"); | ||
214 | printf("Setting up swapspace, size = %ld bytes\n",goodpages*PAGE_SIZE); | ||
215 | strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10); | ||
216 | if (lseek(DEV, 0, SEEK_SET)) | ||
217 | die("unable to rewind swap-device"); | ||
218 | if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) | ||
219 | die("unable to write signature page"); | ||
220 | |||
221 | close(DEV); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | int mkswap_main(struct FileInfo * unnecessary, int argc, char ** argv) | ||
226 | { | ||
227 | char * tmp; | ||
228 | long int pages=0; | ||
229 | int check=0; | ||
230 | |||
231 | if (argc && *argv) | ||
232 | program_name = *argv; | ||
233 | while (argc > 1) { | ||
234 | argv++; | ||
235 | argc--; | ||
236 | if (argv[0][0] != '-') | ||
237 | if (device_name) { | ||
238 | pages = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10); | ||
239 | if (*tmp) { | ||
240 | usage(mkswap_usage); | ||
241 | exit(1); | ||
242 | } | ||
243 | } else | ||
244 | device_name = argv[0]; | ||
245 | else while (*++argv[0]) | ||
246 | switch (argv[0][0]) { | ||
247 | case 'c': check=1; break; | ||
248 | default: usage(mkswap_usage); | ||
249 | exit(1); | ||
250 | } | ||
251 | } | ||
252 | return mkswap(device_name, pages, check); | ||
253 | } | ||
diff --git a/util-linux/more.c b/util-linux/more.c new file mode 100644 index 000000000..65409999b --- /dev/null +++ b/util-linux/more.c | |||
@@ -0,0 +1,110 @@ | |||
1 | #include "internal.h" | ||
2 | #include <stdio.h> | ||
3 | #include <sys/types.h> | ||
4 | #include <sys/stat.h> | ||
5 | #include <sys/ioctl.h> | ||
6 | #include <fcntl.h> | ||
7 | |||
8 | #define BB_MORE_TERM | ||
9 | |||
10 | #ifdef BB_MORE_TERM | ||
11 | #include <termios.h> | ||
12 | #include <signal.h> | ||
13 | |||
14 | FILE *cin; | ||
15 | struct termios initial_settings, new_settings; | ||
16 | |||
17 | void gotsig(int sig) { | ||
18 | tcsetattr(fileno(cin), TCSANOW, &initial_settings); | ||
19 | exit(0); | ||
20 | } | ||
21 | #endif | ||
22 | |||
23 | const char more_usage[] = "more [file]\n" | ||
24 | "\n" | ||
25 | "\tDisplays a file, one page at a time.\n" | ||
26 | "\tIf there are no arguments, the standard input is displayed.\n"; | ||
27 | |||
28 | extern int | ||
29 | more_fn(const struct FileInfo * i) | ||
30 | { | ||
31 | FILE * f = stdin; | ||
32 | int c; | ||
33 | int lines = 0, tlines = 0; | ||
34 | int next_page = 0; | ||
35 | int rows = 24, cols = 79; | ||
36 | #ifdef BB_MORE_TERM | ||
37 | long sizeb = 0; | ||
38 | struct stat st; | ||
39 | struct winsize win; | ||
40 | #endif | ||
41 | |||
42 | if ( i ) { | ||
43 | if (! (f = fopen(i->source, "r") )) { | ||
44 | name_and_error(i->source); | ||
45 | return 1; | ||
46 | } | ||
47 | fstat(fileno(f), &st); | ||
48 | sizeb = st.st_size / 100; | ||
49 | } | ||
50 | |||
51 | #ifdef BB_MORE_TERM | ||
52 | cin = fopen("/dev/tty", "r"); | ||
53 | tcgetattr(fileno(cin),&initial_settings); | ||
54 | new_settings = initial_settings; | ||
55 | new_settings.c_lflag &= ~ICANON; | ||
56 | new_settings.c_lflag &= ~ECHO; | ||
57 | tcsetattr(fileno(cin), TCSANOW, &new_settings); | ||
58 | |||
59 | (void) signal(SIGINT, gotsig); | ||
60 | |||
61 | ioctl(STDOUT_FILENO, TIOCGWINSZ, &win); | ||
62 | if (win.ws_row > 4) rows = win.ws_row - 2; | ||
63 | if (win.ws_col > 0) cols = win.ws_col - 1; | ||
64 | |||
65 | |||
66 | #endif | ||
67 | |||
68 | while ( (c = getc(f)) != EOF ) { | ||
69 | if ( next_page ) { | ||
70 | char garbage; | ||
71 | int len; | ||
72 | tlines += lines; | ||
73 | lines = 0; | ||
74 | next_page = 0; //Percentage is based on bytes, not lines. | ||
75 | if ( i && i->source ) //It is not very acurate, but still useful. | ||
76 | len = printf("%s - %%%2ld - line: %d", i->source, (ftell(f) - sizeb - sizeb) / sizeb, tlines); | ||
77 | else | ||
78 | len = printf("line: %d", tlines); | ||
79 | |||
80 | fflush(stdout); | ||
81 | #ifndef BB_MORE_TERM | ||
82 | read(2, &garbage, 1); | ||
83 | #else | ||
84 | do { | ||
85 | fread(&garbage, 1, 1, cin); | ||
86 | } while ((garbage != ' ') && (garbage != '\n')); | ||
87 | |||
88 | if (garbage == '\n') { | ||
89 | lines = rows; | ||
90 | tlines -= rows; | ||
91 | } | ||
92 | garbage = 0; | ||
93 | //clear line, since tabs don't overwrite. | ||
94 | while(len-- > 0) putchar('\b'); | ||
95 | while(len++ < cols) putchar(' '); | ||
96 | while(len-- > 0) putchar('\b'); | ||
97 | fflush(stdout); | ||
98 | #endif | ||
99 | } | ||
100 | putchar(c); | ||
101 | if ( c == '\n' && ++lines == (rows + 1) ) | ||
102 | next_page = 1; | ||
103 | } | ||
104 | if ( f != stdin ) | ||
105 | fclose(f); | ||
106 | #ifdef BB_MORE_TERM | ||
107 | gotsig(0); | ||
108 | #endif | ||
109 | return 0; | ||
110 | } | ||
diff --git a/util-linux/mount.c b/util-linux/mount.c new file mode 100644 index 000000000..010757d1e --- /dev/null +++ b/util-linux/mount.c | |||
@@ -0,0 +1,430 @@ | |||
1 | /* | ||
2 | 3/21/1999 Charles P. Wright <cpwright@cpwright.com> | ||
3 | searches through fstab when -a is passed | ||
4 | will try mounting stuff with all fses when passed -t auto | ||
5 | |||
6 | 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab. | ||
7 | */ | ||
8 | |||
9 | #include "internal.h" | ||
10 | #include <stdlib.h> | ||
11 | #include <unistd.h> | ||
12 | #include <errno.h> | ||
13 | #include <string.h> | ||
14 | #include <stdio.h> | ||
15 | #include <mntent.h> | ||
16 | #include <sys/mount.h> | ||
17 | #include <ctype.h> | ||
18 | |||
19 | const char mount_usage[] = "mount\n" | ||
20 | "\t\tmount [flags] special-device directory\n" | ||
21 | "\n" | ||
22 | "Flags:\n" | ||
23 | "\t-a:\tMount all file systems in fstab.\n" | ||
24 | "\t-f:\t\"Fake\" mount. Add entry to mount table but don't mount it.\n" | ||
25 | "\t-n:\tDon't write a mount table entry.\n" | ||
26 | "\t-o option:\tOne of many filesystem options, listed below.\n" | ||
27 | "\t-r:\tMount the filesystem read-only.\n" | ||
28 | "\t-t filesystem-type:\tSpecify the filesystem type.\n" | ||
29 | "\t-w:\tMount for reading and writing (default).\n" | ||
30 | "\n" | ||
31 | "Options for use with the \"-o\" flag:\n" | ||
32 | "\tasync / sync:\tWrites are asynchronous / synchronous.\n" | ||
33 | "\tdev / nodev:\tAllow use of special device files / disallow them.\n" | ||
34 | "\texec / noexec:\tAllow use of executable files / disallow them.\n" | ||
35 | "\tsuid / nosuid:\tAllow set-user-id-root programs / disallow them.\n" | ||
36 | "\tremount: Re-mount a currently-mounted filesystem, changing its flags.\n" | ||
37 | "\tro / rw: Mount for read-only / read-write.\n" | ||
38 | "\t" | ||
39 | "There are EVEN MORE flags that are specific to each filesystem.\n" | ||
40 | "You'll have to see the written documentation for those.\n"; | ||
41 | |||
42 | struct mount_options { | ||
43 | const char * name; | ||
44 | unsigned long and; | ||
45 | unsigned long or; | ||
46 | }; | ||
47 | |||
48 | static const struct mount_options mount_options[] = { | ||
49 | { "async", ~MS_SYNCHRONOUS,0 }, | ||
50 | { "defaults", ~0, 0 }, | ||
51 | { "dev", ~MS_NODEV, 0 }, | ||
52 | { "exec", ~MS_NOEXEC, 0 }, | ||
53 | { "nodev", ~0, MS_NODEV }, | ||
54 | { "noexec", ~0, MS_NOEXEC }, | ||
55 | { "nosuid", ~0, MS_NOSUID }, | ||
56 | { "remount", ~0, MS_REMOUNT }, | ||
57 | { "ro", ~0, MS_RDONLY }, | ||
58 | { "rw", ~MS_RDONLY, 0 }, | ||
59 | { "suid", ~MS_NOSUID, 0 }, | ||
60 | { "sync", ~0, MS_SYNCHRONOUS }, | ||
61 | { 0, 0, 0 } | ||
62 | }; | ||
63 | |||
64 | static void | ||
65 | show_flags(unsigned long flags, char * buffer) | ||
66 | { | ||
67 | const struct mount_options * f = mount_options; | ||
68 | while ( f->name ) { | ||
69 | if ( flags & f->and ) { | ||
70 | int length = strlen(f->name); | ||
71 | memcpy(buffer, f->name, length); | ||
72 | buffer += length; | ||
73 | *buffer++ = ','; | ||
74 | *buffer = '\0'; | ||
75 | } | ||
76 | f++; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void | ||
81 | one_option( | ||
82 | char * option | ||
83 | ,unsigned long * flags | ||
84 | ,char * data) | ||
85 | { | ||
86 | const struct mount_options * f = mount_options; | ||
87 | |||
88 | while ( f->name != 0 ) { | ||
89 | if ( strcasecmp(f->name, option) == 0 ) { | ||
90 | *flags &= f->and; | ||
91 | *flags |= f->or; | ||
92 | return; | ||
93 | } | ||
94 | f++; | ||
95 | } | ||
96 | if ( *data ) { | ||
97 | data += strlen(data); | ||
98 | *data++ = ','; | ||
99 | } | ||
100 | strcpy(data, option); | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | parse_mount_options( | ||
105 | char * options | ||
106 | ,unsigned long * flags | ||
107 | ,char * data) | ||
108 | { | ||
109 | while ( *options ) { | ||
110 | char * comma = strchr(options, ','); | ||
111 | if ( comma ) | ||
112 | *comma = '\0'; | ||
113 | one_option(options, flags, data); | ||
114 | if ( comma ) { | ||
115 | *comma = ','; | ||
116 | options = ++comma; | ||
117 | } | ||
118 | else | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | int | ||
124 | mount_one( | ||
125 | char * blockDevice | ||
126 | ,char * directory | ||
127 | ,char * filesystemType | ||
128 | ,unsigned long flags | ||
129 | ,char * string_flags | ||
130 | ,int noMtab | ||
131 | ,int fake) | ||
132 | { | ||
133 | int error = 0; | ||
134 | int status = 0; | ||
135 | |||
136 | char buf[255]; | ||
137 | |||
138 | if (!fake) { | ||
139 | if (*filesystemType == 'a') { //Will fail on real FS starting with 'a' | ||
140 | |||
141 | FILE *f = fopen("/proc/filesystems", "r"); | ||
142 | |||
143 | if (f == NULL) return 1; | ||
144 | |||
145 | while (fgets(buf, sizeof(buf), f) != NULL) { | ||
146 | filesystemType = buf; | ||
147 | if (*filesystemType == '\t') { // Not a nodev filesystem | ||
148 | |||
149 | while (*filesystemType && *filesystemType != '\n') filesystemType++; | ||
150 | *filesystemType = '\0'; | ||
151 | |||
152 | filesystemType = buf; | ||
153 | filesystemType++; //hop past tab | ||
154 | |||
155 | status = mount(blockDevice, directory, filesystemType, | ||
156 | flags|MS_MGC_VAL ,string_flags); | ||
157 | error = errno; | ||
158 | |||
159 | if (status == 0) break; | ||
160 | } | ||
161 | } | ||
162 | fclose(f); | ||
163 | } else { | ||
164 | |||
165 | status = mount( blockDevice, directory, filesystemType, | ||
166 | flags|MS_MGC_VAL ,string_flags); | ||
167 | error = errno; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | if ( status == 0 ) { | ||
172 | char * s = &string_flags[strlen(string_flags)]; | ||
173 | FILE * mountTable; | ||
174 | if ( s != string_flags ) { | ||
175 | *s++ = ','; | ||
176 | show_flags(flags, s); | ||
177 | } | ||
178 | if ( !noMtab && (mountTable = setmntent("/etc/mtab", "a+")) ) { | ||
179 | int length = strlen(directory); | ||
180 | struct mntent m; | ||
181 | |||
182 | if ( length > 1 && directory[length - 1] == '/' ) | ||
183 | directory[length - 1] = '\0'; | ||
184 | |||
185 | if ( filesystemType == 0 ) { | ||
186 | struct mntent * p | ||
187 | = findMountPoint(blockDevice, "/proc/mounts"); | ||
188 | |||
189 | if ( p && p->mnt_type ) | ||
190 | filesystemType = p->mnt_type; | ||
191 | } | ||
192 | m.mnt_fsname = blockDevice; | ||
193 | m.mnt_dir = directory; | ||
194 | m.mnt_type = filesystemType ? filesystemType : "default"; | ||
195 | |||
196 | if (*string_flags) { | ||
197 | m.mnt_opts = string_flags; | ||
198 | } else { | ||
199 | if ( (flags | MS_RDONLY) == flags ) | ||
200 | m.mnt_opts = "ro"; | ||
201 | else | ||
202 | m.mnt_opts = "rw"; | ||
203 | } | ||
204 | |||
205 | m.mnt_freq = 0; | ||
206 | m.mnt_passno = 0; | ||
207 | addmntent(mountTable, &m); | ||
208 | endmntent(mountTable); | ||
209 | } | ||
210 | return 0; | ||
211 | } else { | ||
212 | fprintf(stderr, "Mount %s", blockDevice); | ||
213 | if ( filesystemType && *filesystemType ) | ||
214 | fprintf(stderr, " (type %s)", filesystemType); | ||
215 | |||
216 | fprintf( | ||
217 | stderr | ||
218 | ," on %s: " | ||
219 | ,directory); | ||
220 | |||
221 | switch ( error ) { | ||
222 | case EPERM: | ||
223 | if (geteuid() == 0) | ||
224 | fprintf( | ||
225 | stderr | ||
226 | ,"mount point %s is not a directory" | ||
227 | ,blockDevice); | ||
228 | else | ||
229 | fprintf( | ||
230 | stderr | ||
231 | ,"must be superuser to use mount"); | ||
232 | break; | ||
233 | case EBUSY: | ||
234 | fprintf( | ||
235 | stderr | ||
236 | ,"%s already mounted or %s busy" | ||
237 | ,blockDevice | ||
238 | ,directory); | ||
239 | break; | ||
240 | case ENOENT: | ||
241 | { | ||
242 | struct stat statbuf; | ||
243 | if ( stat(directory, &statbuf) != 0 ) | ||
244 | fprintf( | ||
245 | stderr | ||
246 | ,"directory %s does not exist" | ||
247 | ,directory); | ||
248 | else if ( stat(blockDevice, &statbuf) != 0 ) | ||
249 | fprintf( | ||
250 | stderr | ||
251 | ,"block device %s does not exist" | ||
252 | ,blockDevice); | ||
253 | else | ||
254 | fprintf( | ||
255 | stderr | ||
256 | ,"%s is not mounted on %s, but the mount table says it is." | ||
257 | ,blockDevice | ||
258 | ,directory); | ||
259 | break; | ||
260 | } | ||
261 | case ENOTDIR: | ||
262 | fprintf( | ||
263 | stderr | ||
264 | ,"%s is not a directory" | ||
265 | ,directory); | ||
266 | break; | ||
267 | case EINVAL: | ||
268 | fprintf( | ||
269 | stderr | ||
270 | ,"wrong filesystem type, or bad superblock on %s" | ||
271 | ,blockDevice); | ||
272 | break; | ||
273 | case EMFILE: | ||
274 | fprintf(stderr, "mount table full"); | ||
275 | break; | ||
276 | case EIO: | ||
277 | fprintf( | ||
278 | stderr | ||
279 | ,"I/O error reading %s" | ||
280 | ,blockDevice); | ||
281 | break; | ||
282 | case ENODEV: | ||
283 | { | ||
284 | FILE * f = fopen("/proc/filesystems", "r"); | ||
285 | |||
286 | fprintf( | ||
287 | stderr | ||
288 | ,"filesystem type %s not in kernel.\n" | ||
289 | ,filesystemType); | ||
290 | fprintf(stderr, "Do you need to load a module?\n"); | ||
291 | if ( f ) { | ||
292 | char buf[100]; | ||
293 | |||
294 | fprintf( | ||
295 | stderr | ||
296 | ,"Here are the filesystem types the kernel" | ||
297 | " can mount:\n"); | ||
298 | while ( fgets(buf, sizeof(buf), f) != 0 ) | ||
299 | fprintf(stderr, "\t%s", buf); | ||
300 | fclose(f); | ||
301 | } | ||
302 | break; | ||
303 | } | ||
304 | case ENOTBLK: | ||
305 | fprintf( | ||
306 | stderr | ||
307 | ,"%s is not a block device" | ||
308 | ,blockDevice); | ||
309 | break; | ||
310 | case ENXIO: | ||
311 | fprintf( | ||
312 | stderr | ||
313 | ,"%s is not a valid block device" | ||
314 | ,blockDevice); | ||
315 | break; | ||
316 | default: | ||
317 | fputs(strerror(errno), stderr); | ||
318 | } | ||
319 | putc('\n', stderr); | ||
320 | return -1; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | extern int | ||
325 | mount_main(struct FileInfo * i, int argc, char * * argv) | ||
326 | { | ||
327 | char string_flags[1024]; | ||
328 | unsigned long flags = 0; | ||
329 | char * filesystemType = "auto"; | ||
330 | int fake = 0; | ||
331 | int noMtab = 0; | ||
332 | int all = 0; | ||
333 | |||
334 | *string_flags = '\0'; | ||
335 | |||
336 | if ( argc == 1 ) { | ||
337 | FILE * mountTable; | ||
338 | if ( (mountTable = setmntent("/etc/mtab", "r")) ) { | ||
339 | struct mntent * m; | ||
340 | while ( (m = getmntent(mountTable)) != 0 ) { | ||
341 | printf( | ||
342 | "%s on %s type %s (%s)\n" | ||
343 | ,m->mnt_fsname | ||
344 | ,m->mnt_dir | ||
345 | ,m->mnt_type | ||
346 | ,m->mnt_opts); | ||
347 | } | ||
348 | endmntent(mountTable); | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | while ( argc >= 2 && argv[1][0] == '-' ) { | ||
354 | switch ( argv[1][1] ) { | ||
355 | case 'f': | ||
356 | fake = 1; | ||
357 | break; | ||
358 | case 'n': | ||
359 | noMtab = 1; | ||
360 | break; | ||
361 | case 'o': | ||
362 | if ( argc < 3 ) { | ||
363 | usage(mount_usage); | ||
364 | return 1; | ||
365 | } | ||
366 | parse_mount_options(argv[2], &flags, string_flags); | ||
367 | argc--; | ||
368 | argv++; | ||
369 | break; | ||
370 | case 'r': | ||
371 | flags |= MS_RDONLY; | ||
372 | break; | ||
373 | case 't': | ||
374 | if ( argc < 3 ) { | ||
375 | usage(mount_usage); | ||
376 | return 1; | ||
377 | } | ||
378 | filesystemType = argv[2]; | ||
379 | argc--; | ||
380 | argv++; | ||
381 | break; | ||
382 | case 'v': | ||
383 | break; | ||
384 | case 'w': | ||
385 | flags &= ~MS_RDONLY; | ||
386 | break; | ||
387 | case 'a': | ||
388 | all = 1; | ||
389 | break; | ||
390 | default: | ||
391 | usage(mount_usage); | ||
392 | return 1; | ||
393 | } | ||
394 | argc--; | ||
395 | argv++; | ||
396 | } | ||
397 | |||
398 | if (all == 1) { | ||
399 | struct mntent *m; | ||
400 | FILE *f = setmntent("/etc/fstab", "r"); | ||
401 | |||
402 | if (f == NULL) { | ||
403 | return 1; | ||
404 | } | ||
405 | |||
406 | // FIXME: Combine read routine (make new function) with unmount_all to save space. | ||
407 | |||
408 | while ((m = getmntent(f)) != NULL) { | ||
409 | // If the file system isn't noauto, and isn't mounted on /, mount it | ||
410 | if ((!strstr(m->mnt_opts, "noauto")) && (m->mnt_dir[1] != '\0') | ||
411 | && !((m->mnt_type[0] == 's') && (m->mnt_type[1] == 'w')) | ||
412 | && !((m->mnt_type[0] == 'n') && (m->mnt_type[1] == 'f'))) { | ||
413 | mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, flags, m->mnt_opts, noMtab, fake); | ||
414 | } | ||
415 | } | ||
416 | |||
417 | endmntent(f); | ||
418 | } else { | ||
419 | if ( argc >= 3 ) { | ||
420 | if ( mount_one( argv[1], argv[2], filesystemType, flags, string_flags, noMtab, fake) == 0 ) | ||
421 | return 0; | ||
422 | else | ||
423 | return 1; | ||
424 | } else { | ||
425 | usage(mount_usage); | ||
426 | return 1; | ||
427 | } | ||
428 | } | ||
429 | return 0; | ||
430 | } | ||
diff --git a/util-linux/umount.c b/util-linux/umount.c new file mode 100644 index 000000000..4efc9f9d9 --- /dev/null +++ b/util-linux/umount.c | |||
@@ -0,0 +1,135 @@ | |||
1 | #include "internal.h" | ||
2 | #include <stdlib.h> | ||
3 | #include <unistd.h> | ||
4 | #include <errno.h> | ||
5 | #include <string.h> | ||
6 | #include <stdio.h> | ||
7 | #include <mntent.h> | ||
8 | #include <sys/mount.h> | ||
9 | |||
10 | const char umount_usage[] = "umount {filesystem|directory}\n" | ||
11 | "\tumount -a\n" | ||
12 | "\n" | ||
13 | "\tUnmount a filesystem.\n" | ||
14 | "\t-a:\tUnmounts all mounted filesystems.\n"; | ||
15 | |||
16 | static char * | ||
17 | stralloc(const char * string) | ||
18 | { | ||
19 | int length = strlen(string) + 1; | ||
20 | char * n = malloc(length); | ||
21 | memcpy(n, string, length); | ||
22 | return n; | ||
23 | } | ||
24 | |||
25 | extern void | ||
26 | erase_mtab(const char * name) | ||
27 | { | ||
28 | struct mntent entries[100]; | ||
29 | int count = 0; | ||
30 | FILE * mountTable = setmntent("/etc/mtab", "r"); | ||
31 | struct mntent * m; | ||
32 | |||
33 | if ( mountTable == 0 | ||
34 | && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) { | ||
35 | name_and_error("/etc/mtab"); | ||
36 | return; | ||
37 | } | ||
38 | |||
39 | while ( (m = getmntent(mountTable)) != 0 ) { | ||
40 | entries[count].mnt_fsname = stralloc(m->mnt_fsname); | ||
41 | entries[count].mnt_dir = stralloc(m->mnt_dir); | ||
42 | entries[count].mnt_type = stralloc(m->mnt_type); | ||
43 | entries[count].mnt_opts = stralloc(m->mnt_opts); | ||
44 | entries[count].mnt_freq = m->mnt_freq; | ||
45 | entries[count].mnt_passno = m->mnt_passno; | ||
46 | count++; | ||
47 | } | ||
48 | endmntent(mountTable); | ||
49 | if ( (mountTable = setmntent("/etc/mtab", "w")) ) { | ||
50 | int i; | ||
51 | for ( i = 0; i < count; i++ ) { | ||
52 | int result = ( strcmp(entries[i].mnt_fsname, name) == 0 | ||
53 | || strcmp(entries[i].mnt_dir, name) == 0 ); | ||
54 | |||
55 | if ( result ) | ||
56 | continue; | ||
57 | else | ||
58 | addmntent(mountTable, &entries[i]); | ||
59 | } | ||
60 | endmntent(mountTable); | ||
61 | } | ||
62 | else if ( errno != EROFS ) | ||
63 | name_and_error("/etc/mtab"); | ||
64 | } | ||
65 | |||
66 | static int | ||
67 | umount_all(int noMtab) | ||
68 | { | ||
69 | struct mntent entries[100]; | ||
70 | int count = 0; | ||
71 | FILE * mountTable = setmntent("/etc/mtab", "r"); | ||
72 | struct mntent * m; | ||
73 | int status = 0; | ||
74 | |||
75 | if ( mountTable == 0 | ||
76 | && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) { | ||
77 | name_and_error("/etc/mtab"); | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | while ( (m = getmntent(mountTable)) != 0 ) { | ||
82 | entries[count].mnt_fsname = stralloc(m->mnt_fsname); | ||
83 | count++; | ||
84 | } | ||
85 | endmntent(mountTable); | ||
86 | |||
87 | while ( count > 0 ) { | ||
88 | int result = umount(entries[--count].mnt_fsname) == 0; | ||
89 | /* free(entries[count].mnt_fsname); */ | ||
90 | if ( result ) { | ||
91 | if ( !noMtab ) | ||
92 | erase_mtab(entries[count].mnt_fsname); | ||
93 | } | ||
94 | else { | ||
95 | status = 1; | ||
96 | name_and_error(entries[count].mnt_fsname); | ||
97 | } | ||
98 | } | ||
99 | return status; | ||
100 | } | ||
101 | |||
102 | extern int | ||
103 | do_umount(const char * name, int noMtab) | ||
104 | { | ||
105 | if ( umount(name) == 0 ) { | ||
106 | if ( !noMtab ) | ||
107 | erase_mtab(name); | ||
108 | return 0; | ||
109 | } | ||
110 | return 1; | ||
111 | } | ||
112 | |||
113 | extern int | ||
114 | umount_main(struct FileInfo * i, int argc, char * * argv) | ||
115 | { | ||
116 | int noMtab = 0; | ||
117 | |||
118 | if ( argv[1][0] == '-' ) { | ||
119 | switch ( argv[1][1] ) { | ||
120 | case 'a': | ||
121 | return umount_all(noMtab); | ||
122 | case 'n': | ||
123 | noMtab = 1; | ||
124 | break; | ||
125 | default: | ||
126 | usage(umount_usage); | ||
127 | return 1; | ||
128 | } | ||
129 | } | ||
130 | if ( do_umount(argv[1],noMtab) != 0 ) { | ||
131 | fprintf(stderr, "%s: %s.\n", argv[1], strerror(errno)); | ||
132 | return 1; | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||