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