2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
42 * From mount(8) source by Andries Brouwer. Hacked for XFS by mkp.
43 * Recent sync's to mount source:
44 * - util-linux-2.10o ... 06 Sep 00
45 * - util-linux-2.10r ... 06 Dec 00
46 * - util-linux-2.11g ... 02 Jul 01
49 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
51 static inline unsigned short
52 swapped(unsigned short a
) {
53 return (a
>>8) | (a
<<8);
57 assemble4le(unsigned char *p
) {
58 return (p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24));
62 Probes the device and attempts to determine the type of filesystem
65 Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
66 for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
67 Read the superblock only once - aeb
68 Added iso9660, romfs, qnx4, udf, swap - aeb
69 Added a test for high sierra (iso9660) - quinlan@bucknell.edu
70 Corrected the test for xiafs - aeb
71 Added ufs from a patch by jj. But maybe there are several types of ufs?
72 Added ntfs from a patch by Richard Russon.
73 Added a very weak heuristic for vfat - aeb
74 Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
75 Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
76 Added ext3 - Andrew Morton
79 /* udf magic - I find that trying to mount garbage as an udf fs
80 causes a very large kernel delay, almost killing the machine.
81 So, we do not try udf unless there is positive evidence that it
82 might work. Try iso9660 first, it is much more likely.
83 Strings below taken from ECMA 167. */
85 *udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
89 may_be_udf(const char *id
) {
92 for (m
= udf_magic
; m
- udf_magic
< SIZE(udf_magic
); m
++)
93 if (!strncmp(*m
, id
, 5))
99 may_be_swap(const char *s
) {
100 return (strncmp(s
-10, "SWAP-SPACE", 10) == 0 ||
101 strncmp(s
-10, "SWAPSPACE2", 10) == 0);
104 /* rather weak necessary condition */
106 may_be_adfs(const u_char
*s
) {
110 p
= (u_char
*) s
+ 511;
113 sum
= (sum
>> 8) + (sum
& 0xff) + *p
;
115 return (sum
== p
[511]);
118 static int is_reiserfs_magic_string (struct reiserfs_super_block
* rs
)
120 return (!strncmp (rs
->s_magic
, REISERFS_SUPER_MAGIC_STRING
,
121 strlen ( REISERFS_SUPER_MAGIC_STRING
)) ||
122 !strncmp (rs
->s_magic
, REISER2FS_SUPER_MAGIC_STRING
,
123 strlen ( REISER2FS_SUPER_MAGIC_STRING
)));
127 fstype(const char *device
) {
131 struct minix_super_block ms
;
132 struct ext_super_block es
;
133 struct ext2_super_block e2s
;
134 struct reiserfs_super_block rs
;
137 struct xiafs_super_block xiasb
;
139 char qnx4fs_magic
[10]; /* ignore first 4 bytes */
141 struct ntfs_super_block ntfssb
;
142 struct fat_super_block fatsb
;
143 struct xfs_super_block xfsb
;
144 struct cramfs_super_block cramfssb
;
146 struct ufs_super_block ufssb
;
148 struct iso_volume_descriptor iso
;
149 struct hs_volume_descriptor hs
;
151 struct hfs_super_block hfssb
;
152 struct hpfs_super_block hpfssb
;
153 struct adfs_super_block adfssb
;
156 /* opening and reading an arbitrary unknown path can have
157 undesired side effects - first check that `device' refers
159 if (stat (device
, &statbuf
) || !S_ISBLK(statbuf
.st_mode
))
162 fd
= open(device
, O_RDONLY
);
166 if (lseek(fd
, 1024, SEEK_SET
) != 1024
167 || read(fd
, (char *) &sb
, sizeof(sb
)) != sizeof(sb
))
170 /* ext2 has magic in little-endian on disk, so "swapped" is
171 superfluous; however, there have existed strange byteswapped
173 if (ext2magic(sb
.e2s
) == EXT2_SUPER_MAGIC
174 || ext2magic(sb
.e2s
) == EXT2_PRE_02B_MAGIC
175 || ext2magic(sb
.e2s
) == swapped(EXT2_SUPER_MAGIC
)) {
178 /* maybe even ext3? */
179 if ((assemble4le(sb
.e2s
.s_feature_compat
)
180 & EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
181 assemble4le(sb
.e2s
.s_journal_inum
) != 0)
185 else if (minixmagic(sb
.ms
) == MINIX_SUPER_MAGIC
186 || minixmagic(sb
.ms
) == MINIX_SUPER_MAGIC2
187 || minixmagic(sb
.ms
) == swapped(MINIX_SUPER_MAGIC2
))
190 else if (extmagic(sb
.es
) == EXT_SUPER_MAGIC
)
194 if (lseek(fd
, REISERFS_DISK_OFFSET_IN_BYTES
, SEEK_SET
) !=
195 REISERFS_DISK_OFFSET_IN_BYTES
196 || read(fd
, (char *) &sb
, sizeof(sb
)) != sizeof(sb
))
198 if (is_reiserfs_magic_string(&sb
.rs
))
203 if (lseek(fd
, REISERFS_OLD_DISK_OFFSET_IN_BYTES
, SEEK_SET
) !=
204 REISERFS_OLD_DISK_OFFSET_IN_BYTES
205 || read(fd
, (char *) &sb
, sizeof(sb
)) != sizeof(sb
))
207 if (is_reiserfs_magic_string(&sb
.rs
))
212 if (lseek(fd
, 0, SEEK_SET
) != 0
213 || read(fd
, (char *) &xsb
, sizeof(xsb
)) != sizeof(xsb
))
216 if (xiafsmagic(xsb
.xiasb
) == _XIAFS_SUPER_MAGIC
)
218 else if(!strncmp(xsb
.romfs_magic
, "-rom1fs-", 8))
220 else if(!strncmp(xsb
.xfsb
.s_magic
, XFS_SUPER_MAGIC
, 4))
222 else if(!strncmp(xsb
.qnx4fs_magic
+4, "QNX4FS", 6))
224 else if(xsb
.bfs_magic
== 0x1badface)
226 else if(!strncmp(xsb
.ntfssb
.s_magic
, NTFS_SUPER_MAGIC
,
227 sizeof(xsb
.ntfssb
.s_magic
)))
229 else if(cramfsmagic(xsb
.cramfssb
) == CRAMFS_SUPER_MAGIC
)
231 else if ((!strncmp(xsb
.fatsb
.s_os
, "MSDOS", 5) ||
232 !strncmp(xsb
.fatsb
.s_os
, "MSWIN", 5) ||
233 !strncmp(xsb
.fatsb
.s_os
, "MTOOL", 5) ||
234 !strncmp(xsb
.fatsb
.s_os
, "mkdosfs", 7) ||
235 !strncmp(xsb
.fatsb
.s_os
, "kmkdosfs", 8) ||
236 /* Michal Svec: created by fdformat, old msdos utility for
237 formatting large (1.7) floppy disks. */
238 !strncmp(xsb
.fatsb
.s_os
, "CH-FOR18", 8))
239 && (!strncmp(xsb
.fatsb
.s_fs
, "FAT12 ", 8) ||
240 !strncmp(xsb
.fatsb
.s_fs
, "FAT16 ", 8) ||
241 !strncmp(xsb
.fatsb
.s_fs2
, "FAT32 ", 8)))
242 type
= "vfat"; /* only guessing - might as well be fat or umsdos */
246 if (lseek(fd
, 8192, SEEK_SET
) != 8192
247 || read(fd
, (char *) &ufssb
, sizeof(ufssb
)) != sizeof(ufssb
))
250 if (ufsmagic(ufssb
) == UFS_SUPER_MAGIC
) /* also test swapped version? */
255 if (lseek(fd
, 0x8000, SEEK_SET
) != 0x8000
256 || read(fd
, (char *) &isosb
, sizeof(isosb
)) != sizeof(isosb
))
259 if(strncmp(isosb
.iso
.id
, ISO_STANDARD_ID
, sizeof(isosb
.iso
.id
)) == 0
260 || strncmp(isosb
.hs
.id
, HS_STANDARD_ID
, sizeof(isosb
.hs
.id
)) == 0)
262 else if (may_be_udf(isosb
.iso
.id
))
267 if (lseek(fd
, 0x400, SEEK_SET
) != 0x400
268 || read(fd
, (char *) &hfssb
, sizeof(hfssb
)) != sizeof(hfssb
))
271 /* also check if block size is equal to 512 bytes,
272 since the hfs driver currently only has support
273 for block sizes of 512 bytes long, and to be
274 more accurate (sb magic is only a short int) */
275 if ((hfsmagic(hfssb
) == HFS_SUPER_MAGIC
&&
276 hfsblksize(hfssb
) == 0x20000) ||
277 (swapped(hfsmagic(hfssb
)) == HFS_SUPER_MAGIC
&&
278 hfsblksize(hfssb
) == 0x200))
283 if (lseek(fd
, 0x2000, SEEK_SET
) != 0x2000
284 || read(fd
, (char *) &hpfssb
, sizeof(hpfssb
)) != sizeof(hpfssb
))
287 if (hpfsmagic(hpfssb
) == HPFS_SUPER_MAGIC
)
292 if (lseek(fd
, 0xc00, SEEK_SET
) != 0xc00
293 || read(fd
, (char *) &adfssb
, sizeof(adfssb
)) != sizeof(adfssb
))
296 /* only a weak test */
297 if (may_be_adfs((u_char
*) &adfssb
)
298 && (adfsblksize(adfssb
) >= 8 &&
299 adfsblksize(adfssb
) <= 10))
304 /* perhaps the user tries to mount the swap space
305 on a new disk; warn her before she does mkfs on it */
306 int pagesize
= getpagesize();
313 if (rd
> sizeof(buf
))
315 if (lseek(fd
, 0, SEEK_SET
) != 0
316 || read(fd
, buf
, rd
) != rd
)
318 if (may_be_swap(buf
+pagesize
) ||
319 may_be_swap(buf
+4096) || may_be_swap(buf
+8192))