2 * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changes from Adam
3 * J. Richter (adam@adam.yggdrasil.com) so that /proc/filesystems is used
4 * if no -t option is given. I modified his patches so that, if
5 * /proc/filesystems is not available, the behavior of mount is the same as
8 * Wed Feb 8 09:23:18 1995: Mike Grupenhoff <kashmir@umiacs.UMD.EDU> added
9 * a probe of the superblock for the type before /proc/filesystems is
12 * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect
14 * Wed Nov 11 11:33:55 1998: K.Garloff@ping.de, try /etc/filesystems before
16 * [This was mainly in order to specify vfat before fat; these days we often
17 * detect *fat and then assume vfat, so perhaps /etc/filesystems isnt
20 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
21 * - added Native Language Support
23 * Fri Dec 1 23:31:00 2000: Sepp Wijnands <mrrazz@garbage-coderz.net>
24 * added probes for cramfs, hfs, hpfs and adfs.
36 #include <sys/types.h>
38 #include "mount_guess_fstype.h"
39 #include "sundries.h" /* for xstrdup */
42 #define ETC_FILESYSTEMS "/etc/filesystems"
43 #define PROC_FILESYSTEMS "/proc/filesystems"
45 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
47 /* Most file system types can be recognized by a `magic' number
48 in the superblock. Note that the order of the tests is
49 significant: by coincidence a filesystem can have the
50 magic numbers for several file system types simultaneously.
51 For example, the romfs magic lives in the 1st sector;
52 xiafs does not touch the 1st sector and has its magic in
53 the 2nd sector; ext2 does not touch the first two sectors. */
55 static inline unsigned short
56 swapped(unsigned short a
) {
57 return (a
>>8) | (a
<<8);
61 char *guess_fstype_from_superblock(const char *device);
63 Probes the device and attempts to determine the type of filesystem
66 Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
67 for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
68 Read the superblock only once - aeb
69 Added iso9660, romfs, qnx4, udf, swap - aeb
70 Added a test for high sierra (iso9660) - quinlan@bucknell.edu
71 Corrected the test for xiafs - aeb
72 Added ufs from a patch by jj. But maybe there are several types of ufs?
73 Added ntfs from a patch by Richard Russon.
74 Added a very weak heuristic for vfat - aeb
75 Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
76 Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
80 "adfs", "bfs", "cramfs", "ext", "ext2",
81 "hfs", "hpfs", "iso9660", "minix", "ntfs",
82 "qnx4", "romfs", "swap", "udf", "ufs",
87 tested(const char *device
) {
90 for (m
= magic_known
; m
- magic_known
< SIZE(magic_known
); m
++)
91 if (!strcmp(*m
, device
))
96 /* udf magic - I find that trying to mount garbage as an udf fs
97 causes a very large kernel delay, almost killing the machine.
98 So, we do not try udf unless there is positive evidence that it
99 might work. Try iso9660 first, it is much more likely.
100 Strings below taken from ECMA 167. */
102 *udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
106 may_be_udf(const char *id
) {
109 for (m
= udf_magic
; m
- udf_magic
< SIZE(udf_magic
); m
++)
110 if (!strncmp(*m
, id
, 5))
116 may_be_swap(const char *s
) {
117 return (strncmp(s
-10, "SWAP-SPACE", 10) == 0 ||
118 strncmp(s
-10, "SWAPSPACE2", 10) == 0);
121 /* rather weak necessary condition */
123 may_be_adfs(const u_char
*s
) {
127 p
= (u_char
*) s
+ 511;
130 sum
= (sum
>> 8) + (sum
& 0xff) + *p
;
132 return (sum
== p
[511]);
136 fstype(const char *device
) {
140 struct minix_super_block ms
;
141 struct ext_super_block es
;
142 struct ext2_super_block e2s
;
145 struct xiafs_super_block xiasb
;
147 char qnx4fs_magic
[10]; /* ignore first 4 bytes */
149 struct ntfs_super_block ntfssb
;
150 struct fat_super_block fatsb
;
151 struct xfs_super_block xfsb
;
152 struct cramfs_super_block cramfssb
;
154 struct ufs_super_block ufssb
;
156 struct iso_volume_descriptor iso
;
157 struct hs_volume_descriptor hs
;
159 struct hfs_super_block hfssb
;
160 struct hpfs_super_block hpfssb
;
161 struct adfs_super_block adfssb
;
164 /* opening and reading an arbitrary unknown path can have
165 undesired side effects - first check that `device' refers
167 if (stat (device
, &statbuf
) || !S_ISBLK(statbuf
.st_mode
))
170 fd
= open(device
, O_RDONLY
);
174 if (lseek(fd
, 1024, SEEK_SET
) != 1024
175 || read(fd
, (char *) &sb
, sizeof(sb
)) != sizeof(sb
))
178 if (ext2magic(sb
.e2s
) == EXT2_SUPER_MAGIC
179 || ext2magic(sb
.e2s
) == EXT2_PRE_02B_MAGIC
180 || ext2magic(sb
.e2s
) == swapped(EXT2_SUPER_MAGIC
))
183 else if (minixmagic(sb
.ms
) == MINIX_SUPER_MAGIC
184 || minixmagic(sb
.ms
) == MINIX_SUPER_MAGIC2
185 || minixmagic(sb
.ms
) == swapped(MINIX_SUPER_MAGIC2
))
188 else if (extmagic(sb
.es
) == EXT_SUPER_MAGIC
)
192 if (lseek(fd
, 0, SEEK_SET
) != 0
193 || read(fd
, (char *) &xsb
, sizeof(xsb
)) != sizeof(xsb
))
196 if (xiafsmagic(xsb
.xiasb
) == _XIAFS_SUPER_MAGIC
)
198 else if(!strncmp(xsb
.romfs_magic
, "-rom1fs-", 8))
200 else if(!strncmp(xsb
.xfsb
.s_magic
, XFS_SUPER_MAGIC
, 4) ||
201 !strncmp(xsb
.xfsb
.s_magic
, XFS_SUPER_MAGIC2
, 4))
203 else if(!strncmp(xsb
.qnx4fs_magic
+4, "QNX4FS", 6))
205 else if(xsb
.bfs_magic
== 0x1badface)
207 else if(!strncmp(xsb
.ntfssb
.s_magic
, NTFS_SUPER_MAGIC
,
208 sizeof(xsb
.ntfssb
.s_magic
)))
210 else if(cramfsmagic(xsb
.cramfssb
) == CRAMFS_SUPER_MAGIC
)
212 else if ((!strncmp(xsb
.fatsb
.s_os
, "MSDOS", 5) ||
213 !strncmp(xsb
.fatsb
.s_os
, "MSWIN", 5) ||
214 !strncmp(xsb
.fatsb
.s_os
, "MTOOL", 5) ||
215 !strncmp(xsb
.fatsb
.s_os
, "mkdosfs", 7) ||
216 !strncmp(xsb
.fatsb
.s_os
, "kmkdosfs", 8))
217 && (!strncmp(xsb
.fatsb
.s_fs
, "FAT12 ", 8) ||
218 !strncmp(xsb
.fatsb
.s_fs
, "FAT16 ", 8) ||
219 !strncmp(xsb
.fatsb
.s_fs2
, "FAT32 ", 8)))
220 type
= "vfat"; /* only guessing - might as well be fat or umsdos */
224 if (lseek(fd
, 8192, SEEK_SET
) != 8192
225 || read(fd
, (char *) &ufssb
, sizeof(ufssb
)) != sizeof(ufssb
))
228 if (ufsmagic(ufssb
) == UFS_SUPER_MAGIC
) /* also test swapped version? */
233 if (lseek(fd
, 0x8000, SEEK_SET
) != 0x8000
234 || read(fd
, (char *) &isosb
, sizeof(isosb
)) != sizeof(isosb
))
237 if(strncmp(isosb
.iso
.id
, ISO_STANDARD_ID
, sizeof(isosb
.iso
.id
)) == 0
238 || strncmp(isosb
.hs
.id
, HS_STANDARD_ID
, sizeof(isosb
.hs
.id
)) == 0)
240 else if (may_be_udf(isosb
.iso
.id
))
245 if (lseek(fd
, 0x400, SEEK_SET
) != 0x400
246 || read(fd
, (char *) &hfssb
, sizeof(hfssb
)) != sizeof(hfssb
))
249 /* also check if block size is equal to 512 bytes,
250 since the hfs driver currently only has support
251 for block sizes of 512 bytes long, and to be
252 more accurate (sb magic is only a short int) */
253 if ((hfsmagic(hfssb
) == HFS_SUPER_MAGIC
&&
254 hfsblksize(hfssb
) == 0x20000) ||
255 (swapped(hfsmagic(hfssb
)) == HFS_SUPER_MAGIC
&&
256 hfsblksize(hfssb
) == 0x200))
261 if (lseek(fd
, 0x2000, SEEK_SET
) != 0x2000
262 || read(fd
, (char *) &hpfssb
, sizeof(hpfssb
)) != sizeof(hpfssb
))
265 if (hpfsmagic(hpfssb
) == HPFS_SUPER_MAGIC
)
270 if (lseek(fd
, 0xc00, SEEK_SET
) != 0xc00
271 || read(fd
, (char *) &adfssb
, sizeof(adfssb
)) != sizeof(adfssb
))
274 /* only a weak test */
275 if (may_be_adfs((u_char
*) &adfssb
)
276 && (adfsblksize(adfssb
) >= 8 &&
277 adfsblksize(adfssb
) <= 10))
282 /* perhaps the user tries to mount the swap space
283 on a new disk; warn her before she does mke2fs on it */
284 int pagesize
= getpagesize();
291 if (rd
> sizeof(buf
))
293 if (lseek(fd
, 0, SEEK_SET
) != 0
294 || read(fd
, buf
, rd
) != rd
)
296 if (may_be_swap(buf
+pagesize
) ||
297 may_be_swap(buf
+4096) || may_be_swap(buf
+8192))
311 guess_fstype_from_superblock(const char *spec
) {
312 char *type
= fstype(spec
);
314 printf (_("mount: you didn't specify a filesystem type for %s\n"),
317 printf (_(" I will try all types mentioned in %s or %s\n"),
318 ETC_FILESYSTEMS
, PROC_FILESYSTEMS
);
319 else if (!strcmp(type
, "swap"))
320 printf (_(" and it looks like this is swapspace\n"));
322 printf (_(" I will try type %s\n"), type
);
328 procfsnext(FILE *procfs
) {
332 while (fgets(line
, sizeof(line
), procfs
)) {
333 if (sscanf (line
, "nodev %[^\n]\n", fsname
) == 1) continue;
334 if (sscanf (line
, " %[^ \n]\n", fsname
) != 1) continue;
335 return strdup(fsname
);
340 /* Only use /proc/filesystems here, this is meant to test what
341 the kernel knows about, so /etc/filesystems is irrelevant.
342 Return: 1: yes, 0: no, -1: cannot open procfs */
344 is_in_procfs(const char *type
) {
349 procfs
= fopen(PROC_FILESYSTEMS
, "r");
352 while ((fsname
= procfsnext(procfs
)) != NULL
)
353 if (!strcmp(fsname
, type
)) {
363 /* return: 0: OK, -1: error in errno, 1: type not found */
364 /* when 1 is returned, *type is NULL */
366 procfsloop(int (*mount_fn
)(struct mountargs
*), struct mountargs
*args
,
375 procfs
= fopen(ETC_FILESYSTEMS
, "r");
377 procfs
= fopen(PROC_FILESYSTEMS
, "r");
381 while ((fsname
= procfsnext(procfs
)) != NULL
) {
386 printf(_("Trying %s\n"), fsname
);
389 if ((*mount_fn
) (args
) == 0) {
393 } else if (errno
!= EINVAL
&& is_in_procfs(fsname
) == 1) {