2
* Copyright (c) 2000 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))