2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 * From mount(8) source by Andries Brouwer. Hacked for XFS by mkp.
29 * Recent sync's to mount source:
30 * - util-linux-2.10o ... 06 Sep 00
31 * - util-linux-2.10r ... 06 Dec 00
32 * - util-linux-2.11g ... 02 Jul 01
33 * - util-linux-2.11u ... 24 Aug 02
34 * - util-linux-2.11z ... 13 May 03
37 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
39 /* Most file system types can be recognized by a `magic' number
40 in the superblock. Note that the order of the tests is
41 significant: by coincidence a filesystem can have the
42 magic numbers for several file system types simultaneously.
43 For example, the romfs magic lives in the 1st sector;
44 xiafs does not touch the 1st sector and has its magic in
45 the 2nd sector; ext2 does not touch the first two sectors. */
47 static inline unsigned short
48 swapped(unsigned short a
) {
49 return (a
>>8) | (a
<<8);
53 Probes the device and attempts to determine the type of filesystem
56 Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
57 for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
58 Corrected the test for xiafs - aeb
59 Read the superblock only once - aeb
60 Added a very weak heuristic for vfat - aeb
61 Added iso9660, minix-v2, romfs, qnx4, udf, vxfs, swap - aeb
62 Added a test for high sierra (iso9660) - quinlan@bucknell.edu
63 Added ufs from a patch by jj. But maybe there are several types of ufs?
64 Added ntfs from a patch by Richard Russon.
65 Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
66 Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
67 Added ext3 - Andrew Morton
68 Added jfs - Christoph Hellwig
69 Added sysv - Tim Launchbury
70 Added udf - Bryce Nesbitt
74 * udf magic - I find that trying to mount garbage as an udf fs
75 * causes a very large kernel delay, almost killing the machine.
76 * So, we do not try udf unless there is positive evidence that it
77 * might work. Strings below taken from ECMA 167.
80 * It seems that before udf 2.00 the volume descriptor was not well
81 * defined. For 2.00 you're supposed to keep scanning records until
82 * you find one NOT in this list. (See ECMA 2/8.3.1).
85 *udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
90 may_be_udf(const char *id
) {
93 for (m
= udf_magic
; m
- udf_magic
< SIZE(udf_magic
); m
++)
94 if (!strncmp(*m
, id
, 5))
99 /* we saw "CD001" - may be iso9660 or udf - Bryce Nesbitt */
101 is_really_udf(int fd
) {
103 struct iso_volume_descriptor isosb
;
105 /* determine the block size by scanning in 2K increments
106 (block sizes larger than 2K will be null padded) */
107 for (bs
= 1; bs
< 16; bs
++) {
108 lseek(fd
, bs
*2048+32768, SEEK_SET
);
109 if (read(fd
, (char *)&isosb
, sizeof(isosb
)) != sizeof(isosb
))
115 /* Scan up to another 64 blocks looking for additional VSD's */
116 for (j
= 1; j
< 64; j
++) {
118 lseek(fd
, j
*bs
*2048+32768, SEEK_SET
);
119 if (read(fd
, (char *)&isosb
, sizeof(isosb
))
123 /* If we find NSR0x then call it udf:
126 NSR03 for UDF 2.00 */
127 if (!strncmp(isosb
.id
, "NSR0", 4))
129 if (!may_be_udf(isosb
.id
))
137 may_be_swap(const char *s
) {
138 return (strncmp(s
-10, "SWAP-SPACE", 10) == 0 ||
139 strncmp(s
-10, "SWAPSPACE2", 10) == 0);
142 /* rather weak necessary condition */
144 may_be_adfs(const u_char
*s
) {
148 p
= (u_char
*) s
+ 511;
151 sum
= (sum
>> 8) + (sum
& 0xff) + *p
;
153 return (sum
== p
[511]);
156 static int is_reiserfs_magic_string (struct reiserfs_super_block
* rs
)
158 return (!strncmp (rs
->s_magic
, REISERFS_SUPER_MAGIC_STRING
,
159 strlen ( REISERFS_SUPER_MAGIC_STRING
)) ||
160 !strncmp (rs
->s_magic
, REISER2FS_SUPER_MAGIC_STRING
,
161 strlen ( REISER2FS_SUPER_MAGIC_STRING
)));
165 fstype(const char *device
) {
169 struct minix_super_block ms
;
170 struct ext_super_block es
;
171 struct ext2_super_block e2s
;
172 struct vxfs_super_block vs
;
173 struct hfs_super_block hs
;
174 } sb
; /* stuff at 1024 */
176 struct xiafs_super_block xiasb
;
178 char qnx4fs_magic
[10]; /* ignore first 4 bytes */
179 unsigned int bfs_magic
;
180 struct ntfs_super_block ntfssb
;
181 struct fat_super_block fatsb
;
182 struct xfs_super_block xfsb
;
183 struct cramfs_super_block cramfssb
;
185 struct ufs_super_block ufssb
;
187 struct iso_volume_descriptor iso
;
188 struct hs_volume_descriptor hs
;
190 struct reiserfs_super_block reiserfssb
; /* block 64 or 8 */
191 struct jfs_super_block jfssb
; /* block 32 */
192 struct hpfs_super_block hpfssb
;
193 struct adfs_super_block adfssb
;
194 struct sysv_super_block svsb
;
197 /* opening and reading an arbitrary unknown path can have
198 undesired side effects - first check that `device' refers
199 to a block device or ordinary file */
200 if (stat (device
, &statbuf
) ||
201 !(S_ISBLK(statbuf
.st_mode
) || S_ISREG(statbuf
.st_mode
)))
204 fd
= open(device
, O_RDONLY
);
208 /* do seeks and reads in disk order, otherwise a very short
209 partition may cause a failure because of read error */
213 if (lseek(fd
, 0, SEEK_SET
) != 0
214 || read(fd
, (char *) &xsb
, sizeof(xsb
)) != sizeof(xsb
))
216 /* Gyorgy Kovesdi: none of my photocds has a readable block 0 */
218 if (xiafsmagic(xsb
.xiasb
) == _XIAFS_SUPER_MAGIC
)
220 else if(!strncmp(xsb
.romfs_magic
, "-rom1fs-", 8))
222 else if(!strncmp(xsb
.xfsb
.s_magic
, XFS_SUPER_MAGIC
, 4))
224 else if(!strncmp(xsb
.qnx4fs_magic
+4, "QNX4FS", 6))
226 else if(xsb
.bfs_magic
== 0x1badface)
228 else if(!strncmp(xsb
.ntfssb
.s_magic
, NTFS_SUPER_MAGIC
,
229 sizeof(xsb
.ntfssb
.s_magic
)))
231 else if(cramfsmagic(xsb
.cramfssb
) == CRAMFS_SUPER_MAGIC
||
232 cramfsmagic(xsb
.cramfssb
) == CRAMFS_SUPER_MAGIC_BE
)
234 else if ((!strncmp(xsb
.fatsb
.s_os
, "MSDOS", 5) ||
235 !strncmp(xsb
.fatsb
.s_os
, "MSWIN", 5) ||
236 !strncmp(xsb
.fatsb
.s_os
, "MTOOL", 5) ||
237 !strncmp(xsb
.fatsb
.s_os
, "mkdosfs", 7) ||
238 !strncmp(xsb
.fatsb
.s_os
, "kmkdosfs", 8) ||
239 /* Michal Svec: created by fdformat, old msdos utility for
240 formatting large (1.7) floppy disks. */
241 !strncmp(xsb
.fatsb
.s_os
, "CH-FOR18", 8))
242 && (!strncmp(xsb
.fatsb
.s_fs
, "FAT12 ", 8) ||
243 !strncmp(xsb
.fatsb
.s_fs
, "FAT16 ", 8) ||
244 !strncmp(xsb
.fatsb
.s_fs2
, "FAT32 ", 8)))
245 type
= "vfat"; /* only guessing - might as well be fat or umsdos */
250 if (lseek(fd
, 512 , SEEK_SET
) != 512
251 || read(fd
, (char *) &svsb
, sizeof(svsb
)) != sizeof(svsb
))
253 if (sysvmagic(svsb
) == SYSV_SUPER_MAGIC
)
259 if (lseek(fd
, 1024, SEEK_SET
) != 1024 ||
260 read(fd
, (char *) &sb
, sizeof(sb
)) != sizeof(sb
))
263 /* ext2 has magic in little-endian on disk, so "swapped" is
264 superfluous; however, there have existed strange byteswapped
266 if (ext2magic(sb
.e2s
) == EXT2_SUPER_MAGIC
||
267 ext2magic(sb
.e2s
) == EXT2_PRE_02B_MAGIC
||
268 ext2magic(sb
.e2s
) == swapped(EXT2_SUPER_MAGIC
)) {
271 /* maybe even ext3? */
272 if ((assemble4le(sb
.e2s
.s_feature_compat
)
273 & EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
274 assemble4le(sb
.e2s
.s_journal_inum
) != 0)
275 type
= "ext3"; /* "ext3,ext2" */
278 else if (minixmagic(sb
.ms
) == MINIX_SUPER_MAGIC
||
279 minixmagic(sb
.ms
) == MINIX_SUPER_MAGIC2
||
280 minixmagic(sb
.ms
) == swapped(MINIX_SUPER_MAGIC2
) ||
281 minixmagic(sb
.ms
) == MINIX2_SUPER_MAGIC
||
282 minixmagic(sb
.ms
) == MINIX2_SUPER_MAGIC2
)
285 else if (extmagic(sb
.es
) == EXT_SUPER_MAGIC
)
288 else if (vxfsmagic(sb
.vs
) == VXFS_SUPER_MAGIC
)
291 else if (hfsmagic(sb
.hs
) == swapped(HFS_SUPER_MAGIC
) ||
292 (hfsmagic(sb
.hs
) == swapped(HFSPLUS_SUPER_MAGIC
) &&
293 hfsversion(sb
.hs
) == swapped(HFSPLUS_SUPER_VERSION
)))
299 if (lseek(fd
, 0xc00, SEEK_SET
) != 0xc00
300 || read(fd
, (char *) &adfssb
, sizeof(adfssb
)) != sizeof(adfssb
))
303 /* only a weak test */
304 if (may_be_adfs((u_char
*) &adfssb
)
305 && (adfsblksize(adfssb
) >= 8 &&
306 adfsblksize(adfssb
) <= 10))
314 if (lseek(fd
, 8192, SEEK_SET
) != 8192
315 || read(fd
, (char *) &ufssb
, sizeof(ufssb
)) != sizeof(ufssb
))
318 mag
= ufsmagic(ufssb
);
319 if (mag
== UFS_SUPER_MAGIC_LE
|| mag
== UFS_SUPER_MAGIC_BE
)
325 if (lseek(fd
, REISERFS_OLD_DISK_OFFSET_IN_BYTES
, SEEK_SET
) !=
326 REISERFS_OLD_DISK_OFFSET_IN_BYTES
327 || read(fd
, (char *) &reiserfssb
, sizeof(reiserfssb
)) !=
330 if (is_reiserfs_magic_string(&reiserfssb
))
336 if (lseek(fd
, 0x2000, SEEK_SET
) != 0x2000
337 || read(fd
, (char *) &hpfssb
, sizeof(hpfssb
)) != sizeof(hpfssb
))
340 if (hpfsmagic(hpfssb
) == HPFS_SUPER_MAGIC
)
346 if (lseek(fd
, JFS_SUPER1_OFF
, SEEK_SET
) != JFS_SUPER1_OFF
347 || read(fd
, (char *) &jfssb
, sizeof(jfssb
)) != sizeof(jfssb
))
349 if (!strncmp(jfssb
.s_magic
, JFS_MAGIC
, 4))
356 if (lseek(fd
, 0x8000, SEEK_SET
) != 0x8000
357 || read(fd
, (char *) &isosb
, sizeof(isosb
)) != sizeof(isosb
))
360 if (strncmp(isosb
.hs
.id
, HS_STANDARD_ID
, sizeof(isosb
.hs
.id
)) == 0) {
363 } else if (strncmp(isosb
.iso
.id
, ISO_STANDARD_ID
,
364 sizeof(isosb
.iso
.id
)) == 0) {
367 if (is_really_udf(fd
))
369 } else if (may_be_udf(isosb
.iso
.id
))
375 if (lseek(fd
, REISERFS_DISK_OFFSET_IN_BYTES
, SEEK_SET
) !=
376 REISERFS_DISK_OFFSET_IN_BYTES
377 || read(fd
, (char *) &reiserfssb
, sizeof(reiserfssb
)) !=
380 if (is_reiserfs_magic_string(&reiserfssb
))
385 /* perhaps the user tries to mount the swap space
386 on a new disk; warn her before she does mke2fs on it */
387 int pagesize
= getpagesize();
394 if (rd
> sizeof(buf
))
396 if (lseek(fd
, 0, SEEK_SET
) != 0
397 || read(fd
, buf
, rd
) != rd
)
399 if (may_be_swap(buf
+pagesize
) ||
400 may_be_swap(buf
+4096) || may_be_swap(buf
+8192))