summaryrefslogtreecommitdiff
path: root/util-linux
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux')
-rw-r--r--util-linux/dmesg.c95
-rw-r--r--util-linux/fdflush.c36
-rw-r--r--util-linux/mkswap.c253
-rw-r--r--util-linux/more.c110
-rw-r--r--util-linux/mount.c430
-rw-r--r--util-linux/umount.c135
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
25static inline _syscall3(int,klog,int,type,char *,b,int,len)
26#endif /* __GLIBC__ */
27
28const char dmesg_usage[] = "dmesg";
29
30int
31dmesg_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
8const char fdflush_usage[] = "fdflush device";
9
10int
11fdflush(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
32int
33fdflush_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
40const 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
48static const char * program_name = "mkswap";
49static const char * device_name = NULL;
50static int DEV = -1;
51static long PAGES = 0;
52static int do_check = 0;
53static int badpages = 0;
54
55
56static 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
67static 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 */
83volatile 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
91static 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
121static 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
132static 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
152static 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
172int
173mkswap(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
225int 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
23const 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
28extern int
29more_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
19const 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
42struct mount_options {
43 const char * name;
44 unsigned long and;
45 unsigned long or;
46};
47
48static 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
64static void
65show_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
80static void
81one_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
103static void
104parse_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
123int
124mount_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
324extern int
325mount_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
10const 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
16static char *
17stralloc(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
25extern void
26erase_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
66static int
67umount_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
102extern int
103do_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
113extern int
114umount_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}