Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 2 | /* |
Eric Andersen | 596e546 | 1999-10-07 08:30:23 +0000 | [diff] [blame] | 3 | * Mini mount implementation for busybox |
| 4 | * |
Eric Andersen | c499601 | 1999-10-20 22:08:37 +0000 | [diff] [blame] | 5 | * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 6 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 7 | * Copyright (C) 2005 by Rob Landley <rob@landley.net> |
Eric Andersen | 596e546 | 1999-10-07 08:30:23 +0000 | [diff] [blame] | 8 | * |
| 9 | * This program is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License as published by |
| 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | * (at your option) any later version. |
| 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | * General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program; if not, write to the Free Software |
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 22 | * |
Erik Andersen | b7cc49d | 2000-01-13 06:38:14 +0000 | [diff] [blame] | 23 | */ |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 24 | |
Matt Kraai | 3425111 | 2001-05-02 21:17:38 +0000 | [diff] [blame] | 25 | #include <limits.h> |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 26 | #include <stdlib.h> |
| 27 | #include <unistd.h> |
| 28 | #include <errno.h> |
| 29 | #include <string.h> |
| 30 | #include <stdio.h> |
| 31 | #include <mntent.h> |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 32 | #include <ctype.h> |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 33 | #include <sys/mount.h> |
| 34 | #include <fcntl.h> // for CONFIG_FEATURE_MOUNT_LOOP |
| 35 | #include <sys/ioctl.h> // for CONFIG_FEATURE_MOUNT_LOOP |
Eric Andersen | cbe31da | 2001-02-20 06:14:08 +0000 | [diff] [blame] | 36 | #include "busybox.h" |
Eric Andersen | bd22ed8 | 2000-07-08 18:55:24 +0000 | [diff] [blame] | 37 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 38 | /* This is just a warning of a common mistake. Possibly this should be a |
| 39 | * uclibc faq entry rather than in busybox... */ |
Rob Landley | 4a7252b | 2005-10-08 18:49:45 +0000 | [diff] [blame] | 40 | #if ENABLE_FEATURE_MOUNT_NFS && defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) |
Eric Andersen | d9fe958 | 2003-07-22 08:25:37 +0000 | [diff] [blame] | 41 | #error "You need to build uClibc with UCLIBC_HAS_RPC for busybox mount with NFS support to compile." |
| 42 | #endif |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 43 | |
| 44 | // These two aren't always defined in old headers |
| 45 | #ifndef MS_BIND |
| 46 | #define MS_BIND 4096 |
| 47 | #endif |
| 48 | #ifndef MS_MOVE |
| 49 | #define MS_MOVE 8192 |
Eric Andersen | d9fe958 | 2003-07-22 08:25:37 +0000 | [diff] [blame] | 50 | #endif |
| 51 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 52 | /* Consume standard mount options (from -o options or --options). |
| 53 | * Set appropriate flags and collect unrecognized ones as a comma separated |
| 54 | * string to pass to kernel */ |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 55 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 56 | struct { |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 57 | const char *name; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 58 | long flags; |
| 59 | } static const mount_options[] = { |
| 60 | {"loop", 0}, |
| 61 | {"defaults", 0}, |
| 62 | {"noauto", 0}, |
| 63 | {"ro", MS_RDONLY}, |
| 64 | {"rw", ~MS_RDONLY}, |
| 65 | {"nosuid", MS_NOSUID}, |
| 66 | {"suid", ~MS_NOSUID}, |
| 67 | {"dev", ~MS_NODEV}, |
| 68 | {"nodev", MS_NODEV}, |
| 69 | {"exec", ~MS_NOEXEC}, |
| 70 | {"noexec", MS_NOEXEC}, |
| 71 | {"sync", MS_SYNCHRONOUS}, |
| 72 | {"async", ~MS_SYNCHRONOUS}, |
| 73 | {"remount", MS_REMOUNT}, |
| 74 | {"atime", MS_NOATIME}, |
| 75 | {"noatime", MS_NOATIME}, |
| 76 | {"diratime", MS_NODIRATIME}, |
| 77 | {"nodiratime", MS_NODIRATIME}, |
| 78 | {"bind", MS_BIND}, |
| 79 | {"move", MS_MOVE} |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 80 | }; |
| 81 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 82 | /* Uses the mount_options list above */ |
Glenn L McGrath | 9fef17d | 2002-08-22 18:41:20 +0000 | [diff] [blame] | 83 | static void parse_mount_options(char *options, int *flags, char **strflags) |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 84 | { |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 85 | // Loop through options |
| 86 | for(;;) { |
| 87 | int i; |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 88 | char *comma = strchr(options, ','); |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 89 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 90 | if(comma) *comma = 0; |
Eric Andersen | 3ae0c78 | 1999-11-04 01:13:21 +0000 | [diff] [blame] | 91 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 92 | // Find this option in mount_options |
| 93 | for(i = 0; i < (sizeof(mount_options) / sizeof(*mount_options)); i++) { |
| 94 | if(!strcasecmp(mount_options[i].name, options)) { |
| 95 | long fl = mount_options[i].flags; |
| 96 | if(fl < 0) *flags &= fl; |
| 97 | else *flags |= fl; |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 98 | break; |
| 99 | } |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 100 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 101 | // Unrecognized mount option? |
Rob Landley | 9a64314 | 2005-08-30 17:07:49 +0000 | [diff] [blame] | 102 | if(i == (sizeof(mount_options) / sizeof(*mount_options))) { |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 103 | // Add it to strflags, to pass on to kernel |
| 104 | i = *strflags ? strlen(*strflags) : 0; |
| 105 | *strflags = xrealloc(*strflags, i+strlen(options)+2); |
| 106 | // Comma separated if it's not the first one |
Rob Landley | 9a64314 | 2005-08-30 17:07:49 +0000 | [diff] [blame] | 107 | if(i) (*strflags)[i++] = ','; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 108 | strcpy((*strflags)+i, options); |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 109 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 110 | // Advance to next option, or finish |
| 111 | if(comma) { |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 112 | *comma = ','; |
| 113 | options = ++comma; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 114 | } else break; |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 115 | } |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 116 | } |
| 117 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 118 | /* This does the work */ |
Matt Kraai | 1240082 | 2001-04-17 04:32:50 +0000 | [diff] [blame] | 119 | |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 120 | extern int mount_main(int argc, char **argv) |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 121 | { |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 122 | char *string_flags = 0, *fsType = 0, *blockDevice = 0, *directory = 0, |
| 123 | *loopFile = 0, *buf = 0, |
| 124 | *files[] = {"/etc/filesystems", "/proc/filesystems", 0}; |
| 125 | int i, opt, all = FALSE, fakeIt = FALSE, allowWrite = FALSE, |
Rob Landley | 6e98521 | 2005-08-14 18:46:34 +0000 | [diff] [blame] | 126 | rc = 1, useMtab = ENABLE_FEATURE_MTAB_SUPPORT; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 127 | int flags=0xc0ed0000; // Needed for linux 2.2, ignored by 2.4 and 2.6. |
| 128 | FILE *file = 0,*f = 0; |
| 129 | char path[PATH_MAX*2]; |
| 130 | struct mntent m; |
Glenn L McGrath | 3aae100 | 2001-05-07 01:38:03 +0000 | [diff] [blame] | 131 | struct stat statbuf; |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 132 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 133 | /* parse long options, like --bind and --move. Note that -o option |
| 134 | * and --option are synonymous. Yes, this means --remount,rw works. */ |
| 135 | |
| 136 | for(i = opt = 0; i < argc; i++) { |
| 137 | if(argv[i][0] == '-' && argv[i][1] == '-') |
| 138 | parse_mount_options(argv[i]+2, &flags, &string_flags); |
| 139 | else argv[opt++] = argv[i]; |
| 140 | } |
| 141 | argc = opt; |
| 142 | |
| 143 | // Parse remaining options |
| 144 | |
| 145 | while((opt = getopt(argc, argv, "o:t:rwafnv")) > 0) { |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 146 | switch (opt) { |
| 147 | case 'o': |
Eric Andersen | 8b1aa4d | 2002-06-22 17:20:50 +0000 | [diff] [blame] | 148 | parse_mount_options(optarg, &flags, &string_flags); |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 149 | break; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 150 | case 't': |
| 151 | fsType = optarg; |
| 152 | break; |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 153 | case 'r': |
| 154 | flags |= MS_RDONLY; |
| 155 | break; |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 156 | case 'w': |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 157 | allowWrite=TRUE; |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 158 | break; |
| 159 | case 'a': |
| 160 | all = TRUE; |
| 161 | break; |
| 162 | case 'f': |
| 163 | fakeIt = TRUE; |
| 164 | break; |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 165 | case 'n': |
| 166 | useMtab = FALSE; |
Eric Andersen | ee4b7d4 | 2004-04-12 15:02:53 +0000 | [diff] [blame] | 167 | break; |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 168 | case 'v': |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 169 | break; // ignore -v |
| 170 | default: |
| 171 | bb_show_usage(); |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 172 | } |
Matt Kraai | a3045df | 2001-04-17 04:48:51 +0000 | [diff] [blame] | 173 | } |
| 174 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 175 | // If we have no arguments, show currently mounted filesystems |
| 176 | |
| 177 | if(!all && (optind == argc)) { |
| 178 | FILE *mountTable = setmntent(bb_path_mtab_file, "r"); |
| 179 | |
| 180 | if(!mountTable) bb_perror_msg_and_die(bb_path_mtab_file); |
| 181 | |
| 182 | while (getmntent_r(mountTable,&m,path,sizeof(path))) { |
| 183 | blockDevice = m.mnt_fsname; |
| 184 | |
| 185 | // Clean up display a little bit regarding root devie |
| 186 | if(!strcmp(blockDevice, "rootfs")) continue; |
| 187 | if(!strcmp(blockDevice, "/dev/root")) |
| 188 | blockDevice = find_block_device("/"); |
| 189 | |
| 190 | if(!fsType || !strcmp(m.mnt_type, fsType)) |
| 191 | printf("%s on %s type %s (%s)\n", blockDevice, m.mnt_dir, |
| 192 | m.mnt_type, m.mnt_opts); |
| 193 | if(ENABLE_FEATURE_CLEAN_UP && blockDevice != m.mnt_fsname) |
| 194 | free(blockDevice); |
| 195 | } |
| 196 | endmntent(mountTable); |
| 197 | return EXIT_SUCCESS; |
Glenn L McGrath | 8042f65 | 2002-08-23 06:17:46 +0000 | [diff] [blame] | 198 | } |
Matt Kraai | 1240082 | 2001-04-17 04:32:50 +0000 | [diff] [blame] | 199 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 200 | /* The next argument is what to mount. if there's an argument after that |
| 201 | * it's where to mount it. If we're not mounting all, and we have both |
| 202 | * of these arguments, jump straight to the actual mount. */ |
Glenn L McGrath | 9fef17d | 2002-08-22 18:41:20 +0000 | [diff] [blame] | 203 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 204 | statbuf.st_mode=0; |
| 205 | if(optind < argc) |
| 206 | blockDevice = !stat(argv[optind], &statbuf) ? |
| 207 | bb_simplify_path(argv[optind]) : |
| 208 | (ENABLE_FEATURE_CLEAN_UP ? strdup(argv[optind]) : argv[optind]); |
| 209 | if(optind+1 < argc) directory = bb_simplify_path(argv[optind+1]); |
| 210 | |
| 211 | // If we don't have to loop through fstab, skip ahead a bit. |
| 212 | |
| 213 | if(!all && optind+1!=argc) goto singlemount; |
| 214 | |
| 215 | // Loop through /etc/fstab entries to look up this entry. |
| 216 | |
| 217 | if(!(file=setmntent("/etc/fstab","r"))) |
| 218 | bb_perror_msg_and_die("\nCannot read /etc/fstab"); |
| 219 | for(;;) { |
| 220 | |
| 221 | // Get next fstab entry |
| 222 | |
| 223 | if(!getmntent_r(file,&m,path,sizeof(path))) { |
| 224 | if(!all) |
| 225 | bb_perror_msg("Can't find %s in /etc/fstab\n", blockDevice); |
| 226 | break; |
| 227 | } |
| 228 | |
| 229 | // If we're mounting all and all doesn't mount this one, skip it. |
| 230 | |
| 231 | if(all) { |
| 232 | if(strstr(m.mnt_opts,"noauto") || strstr(m.mnt_type,"swap")) |
| 233 | continue; |
| 234 | flags=0; |
| 235 | |
| 236 | /* If we're mounting something specific and this isn't it, skip it. |
| 237 | * Note we must match both the exact text in fstab (ala "proc") or |
| 238 | * a full path from root */ |
| 239 | |
| 240 | } else if(strcmp(blockDevice,m.mnt_fsname) && |
| 241 | strcmp(argv[optind],m.mnt_fsname) && |
| 242 | strcmp(blockDevice,m.mnt_dir) && |
| 243 | strcmp(argv[optind],m.mnt_dir)) continue; |
| 244 | |
| 245 | /* Parse flags from /etc/fstab (unless this is a single mount |
| 246 | * overriding fstab -- note the "all" test above zeroed the flags, |
| 247 | * to prevent flags from previous entries affecting this one, so |
| 248 | * the only way we could get here with nonzero flags is a single |
| 249 | * mount). */ |
| 250 | |
| 251 | if(!flags) { |
| 252 | if(ENABLE_FEATURE_CLEAN_UP) free(string_flags); |
| 253 | string_flags=NULL; |
| 254 | parse_mount_options(m.mnt_opts, &flags, &string_flags); |
| 255 | } |
| 256 | |
| 257 | /* Fill out remaining fields with info from mtab */ |
| 258 | |
| 259 | if(ENABLE_FEATURE_CLEAN_UP) { |
| 260 | free(blockDevice); |
| 261 | blockDevice=strdup(m.mnt_fsname); |
| 262 | free(directory); |
| 263 | directory=strdup(m.mnt_type); |
Glenn L McGrath | 3aae100 | 2001-05-07 01:38:03 +0000 | [diff] [blame] | 264 | } else { |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 265 | blockDevice=m.mnt_fsname; |
| 266 | directory=m.mnt_dir; |
Glenn L McGrath | 3aae100 | 2001-05-07 01:38:03 +0000 | [diff] [blame] | 267 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 268 | fsType=m.mnt_type; |
Matt Kraai | 3425111 | 2001-05-02 21:17:38 +0000 | [diff] [blame] | 269 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 270 | /* Ok, we're ready to actually mount a specific source on a specific |
| 271 | * directory now. */ |
Matt Kraai | a7cecbc | 2001-08-10 15:05:27 +0000 | [diff] [blame] | 272 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 273 | singlemount: |
Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 274 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 275 | // If they said -w, override fstab |
Erik Andersen | 246cc6d | 2000-03-07 07:41:42 +0000 | [diff] [blame] | 276 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 277 | if(allowWrite) flags&=~MS_RDONLY; |
| 278 | |
| 279 | // Might this be an NFS filesystem? |
| 280 | |
Rob Landley | 4a7252b | 2005-10-08 18:49:45 +0000 | [diff] [blame] | 281 | if(ENABLE_FEATURE_MOUNT_NFS && (!fsType || !strcmp(fsType,"nfs")) && |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 282 | strchr(blockDevice, ':') != NULL) |
| 283 | { |
| 284 | if(nfsmount(blockDevice, directory, &flags, &string_flags, 1)) |
| 285 | bb_perror_msg("nfsmount failed"); |
| 286 | else { |
Rob Landley | 6e98521 | 2005-08-14 18:46:34 +0000 | [diff] [blame] | 287 | rc = 0; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 288 | fsType="nfs"; |
Rob Landley | 9a64314 | 2005-08-30 17:07:49 +0000 | [diff] [blame] | 289 | // Strangely enough, nfsmount() doesn't actually mount() |
| 290 | goto mount_it_now; |
Eric Andersen | fdd5103 | 2000-08-02 18:48:26 +0000 | [diff] [blame] | 291 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 292 | } else { |
| 293 | |
| 294 | // Do we need to allocate a loopback device? |
Glenn L McGrath | 9fef17d | 2002-08-22 18:41:20 +0000 | [diff] [blame] | 295 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 296 | if(ENABLE_FEATURE_MOUNT_LOOP && !fakeIt && S_ISREG(statbuf.st_mode)) |
Eric Andersen | 5ef4482 | 2003-02-28 06:29:27 +0000 | [diff] [blame] | 297 | { |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 298 | loopFile = blockDevice; |
| 299 | blockDevice = 0; |
| 300 | switch(set_loop(&blockDevice, loopFile, 0)) { |
| 301 | case 0: |
| 302 | case 1: |
| 303 | break; |
| 304 | default: |
| 305 | bb_error_msg_and_die( |
| 306 | errno == EPERM || errno == EACCES ? |
| 307 | bb_msg_perm_denied_are_you_root : |
| 308 | "Couldn't setup loop device"); |
| 309 | break; |
Eric Andersen | fdd5103 | 2000-08-02 18:48:26 +0000 | [diff] [blame] | 310 | } |
Eric Andersen | 252bacc | 2000-09-19 01:21:13 +0000 | [diff] [blame] | 311 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 312 | |
| 313 | /* If we know the fstype (or don't need to), jump straight |
| 314 | * to the actual mount. */ |
| 315 | |
| 316 | if(fsType || (flags & (MS_REMOUNT | MS_BIND | MS_MOVE))) |
| 317 | goto mount_it_now; |
| 318 | } |
| 319 | |
| 320 | // Loop through filesystem types until mount succeeds or we run out |
| 321 | |
| 322 | for(i = 0; files[i] && rc; i++) { |
| 323 | f = fopen(files[i], "r"); |
| 324 | if(!f) continue; |
| 325 | // Get next block device backed filesystem |
| 326 | for(buf = 0; (buf = fsType = bb_get_chomped_line_from_file(f)); |
| 327 | free(buf)) |
| 328 | { |
| 329 | // Skip funky entries in /proc |
| 330 | if(!strncmp(buf,"nodev",5) && isspace(buf[5])) continue; |
| 331 | |
| 332 | while(isspace(*fsType)) fsType++; |
| 333 | if(*buf=='#' || *buf=='*') continue; |
| 334 | if(!*fsType) continue; |
| 335 | mount_it_now: |
| 336 | // Okay, try to mount |
| 337 | |
| 338 | if (!fakeIt) { |
| 339 | for(;;) { |
| 340 | rc = mount(blockDevice, directory, fsType, flags, string_flags); |
| 341 | if(!rc || (flags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS)) |
| 342 | break; |
| 343 | bb_error_msg("%s is write-protected, mounting read-only", blockDevice); |
| 344 | flags|=MS_RDONLY; |
| 345 | } |
| 346 | } |
Rob Landley | de5fd23 | 2005-08-14 19:26:14 +0000 | [diff] [blame] | 347 | if(!rc || !f) break; |
Glenn L McGrath | 8042f65 | 2002-08-23 06:17:46 +0000 | [diff] [blame] | 348 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 349 | if(f) fclose(f); |
| 350 | if(!f || !rc) break; |
| 351 | } |
| 352 | |
| 353 | /* If the mount was sucessful, and we're maintaining an old-style |
| 354 | * mtab file by hand, add new entry to it now. */ |
| 355 | if((!rc || fakeIt) && useMtab) { |
| 356 | FILE *mountTable = setmntent(bb_path_mtab_file, "a+"); |
| 357 | |
| 358 | if(!mountTable) bb_perror_msg(bb_path_mtab_file); |
| 359 | else { |
| 360 | // Remove trailing / (if any) from directory we mounted on |
| 361 | int length=strlen(directory); |
| 362 | if(length>1 && directory[length-1] == '/') |
| 363 | directory[length-1]=0; |
| 364 | |
| 365 | // Fill out structure (should be ok to re-use existing one). |
| 366 | m.mnt_fsname=blockDevice; |
| 367 | m.mnt_dir=directory; |
| 368 | m.mnt_type=fsType ? : "--bind"; |
| 369 | m.mnt_opts=string_flags ? : |
| 370 | ((flags & MS_RDONLY) ? "ro" : "rw"); |
| 371 | m.mnt_freq = 0; |
| 372 | m.mnt_passno = 0; |
| 373 | |
| 374 | // Write and close |
| 375 | addmntent(mountTable, &m); |
| 376 | endmntent(mountTable); |
Glenn L McGrath | 8042f65 | 2002-08-23 06:17:46 +0000 | [diff] [blame] | 377 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 378 | } else { |
| 379 | // Mount failed. Clean up |
| 380 | if(loopFile) { |
| 381 | del_loop(blockDevice); |
| 382 | if(ENABLE_FEATURE_CLEAN_UP) free(loopFile); |
| 383 | } |
| 384 | // Don't whine about already mounted fs when mounting all. |
Rob Landley | 6e98521 | 2005-08-14 18:46:34 +0000 | [diff] [blame] | 385 | if(rc<0 && errno == EBUSY && all) rc = 0; |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 386 | else if (errno == EPERM) |
| 387 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
Eric Andersen | fdd5103 | 2000-08-02 18:48:26 +0000 | [diff] [blame] | 388 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 389 | // We couldn't free this earlier becase fsType could be in buf. |
| 390 | if(ENABLE_FEATURE_CLEAN_UP) { |
| 391 | free(buf); |
| 392 | free(blockDevice); |
| 393 | free(directory); |
Glenn L McGrath | 8042f65 | 2002-08-23 06:17:46 +0000 | [diff] [blame] | 394 | } |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 395 | if(!all) break; |
Eric Andersen | fdd5103 | 2000-08-02 18:48:26 +0000 | [diff] [blame] | 396 | } |
Glenn L McGrath | 9fef17d | 2002-08-22 18:41:20 +0000 | [diff] [blame] | 397 | |
Rob Landley | 6a6798b | 2005-08-10 20:35:54 +0000 | [diff] [blame] | 398 | if(file) endmntent(file); |
| 399 | if(rc) bb_perror_msg("Mounting %s on %s failed", blockDevice, directory); |
| 400 | |
Rob Landley | 6e98521 | 2005-08-14 18:46:34 +0000 | [diff] [blame] | 401 | return rc; |
Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 402 | } |