]> git.ipfire.org Git - thirdparty/util-linux.git/blob - mount/mount_guess_fstype.c
Imported from util-linux-2.11o tarball.
[thirdparty/util-linux.git] / mount / mount_guess_fstype.c
1 /*
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
6 * it was previously.
7 *
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
10 * checked.
11 *
12 * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect
13 *
14 * Wed Nov 11 11:33:55 1998: K.Garloff@ping.de, try /etc/filesystems before
15 * /proc/filesystems
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
18 * so useful anymore.]
19 *
20 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
21 * added Native Language Support
22 *
23 * 2000-12-01 Sepp Wijnands <mrrazz@garbage-coderz.net>
24 * added probes for cramfs, hfs, hpfs and adfs.
25 *
26 * 2001-10-26 Tim Launchbury
27 * added sysv magic.
28 *
29 * aeb - many changes.
30 *
31 */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include "linux_fs.h"
41 #include "mount_guess_fstype.h"
42 #include "sundries.h" /* for xstrdup */
43 #include "nls.h"
44
45 #define ETC_FILESYSTEMS "/etc/filesystems"
46 #define PROC_FILESYSTEMS "/proc/filesystems"
47
48 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
49
50 /* Most file system types can be recognized by a `magic' number
51 in the superblock. Note that the order of the tests is
52 significant: by coincidence a filesystem can have the
53 magic numbers for several file system types simultaneously.
54 For example, the romfs magic lives in the 1st sector;
55 xiafs does not touch the 1st sector and has its magic in
56 the 2nd sector; ext2 does not touch the first two sectors. */
57
58 static inline unsigned short
59 swapped(unsigned short a) {
60 return (a>>8) | (a<<8);
61 }
62
63 static inline int
64 assemble4le(unsigned char *p) {
65 return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
66 }
67
68 /*
69 char *guess_fstype(const char *device);
70
71 Probes the device and attempts to determine the type of filesystem
72 contained within.
73
74 Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
75 for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
76 Corrected the test for xiafs - aeb
77 Read the superblock only once - aeb
78 Added a very weak heuristic for vfat - aeb
79 Added iso9660, minix-v2, romfs, qnx4, udf, vxfs, swap - aeb
80 Added a test for high sierra (iso9660) - quinlan@bucknell.edu
81 Added ufs from a patch by jj. But maybe there are several types of ufs?
82 Added ntfs from a patch by Richard Russon.
83 Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
84 Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
85 Added ext3 - Andrew Morton
86 Added jfs - Christoph Hellwig
87 Added sysv - Tim Launchbury
88 Added udf - Bryce Nesbitt
89 */
90 static char
91 *magic_known[] = {
92 "adfs", "bfs", "cramfs", "ext", "ext2", "ext3",
93 "hfs", "hpfs", "iso9660", "jfs", "minix", "ntfs",
94 "qnx4", "reiserfs", "romfs", "swap", "sysv", "udf", "ufs",
95 "vxfs", "xfs", "xiafs"
96 };
97
98 static struct tried {
99 struct tried *next;
100 char *type;
101 } *tried = NULL;
102
103 static int
104 was_tested(const char *fstype) {
105 char **m;
106 struct tried *t;
107
108 for (m = magic_known; m - magic_known < SIZE(magic_known); m++)
109 if (!strcmp(*m, fstype))
110 return 1;
111 for (t = tried; t; t = t->next) {
112 if (!strcmp(t->type, fstype))
113 return 1;
114 }
115 return 0;
116 }
117
118 static void
119 set_tested(const char *fstype) {
120 struct tried *t = xmalloc(sizeof(struct tried));
121
122 t->next = tried;
123 t->type = xstrdup(fstype);
124 tried = t;
125 }
126
127 static void
128 free_tested(void) {
129 struct tried *t, *tt;
130
131 t = tried;
132 while(t) {
133 free(t->type);
134 tt = t->next;
135 free(t);
136 t = tt;
137 }
138 tried = NULL;
139 }
140
141 /*
142 * udf magic - I find that trying to mount garbage as an udf fs
143 * causes a very large kernel delay, almost killing the machine.
144 * So, we do not try udf unless there is positive evidence that it
145 * might work. Strings below taken from ECMA 167.
146 */
147 /*
148 * It seems that before udf 2.00 the volume descriptor was not well
149 * defined. For 2.00 you're supposed to keep scanning records until
150 * you find one NOT in this list. (See ECMA 2/8.3.1).
151 */
152 static char
153 *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
154 "NSR03", "TEA01" };
155
156
157 static int
158 may_be_udf(const char *id) {
159 char **m;
160
161 for (m = udf_magic; m - udf_magic < SIZE(udf_magic); m++)
162 if (!strncmp(*m, id, 5))
163 return 1;
164 return 0;
165 }
166
167 /* we saw "CD001" - may be iso9660 or udf - Bryce Nesbitt */
168 static int
169 is_really_udf(int fd) {
170 int j, bs;
171 struct iso_volume_descriptor isosb;
172
173 /* determine the block size by scanning in 2K increments
174 (block sizes larger than 2K will be null padded) */
175 for (bs = 1; bs < 16; bs++) {
176 lseek(fd, bs*2048+32768, SEEK_SET);
177 if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
178 return 0;
179 if (isosb.id[0])
180 break;
181 }
182
183 /* Scan up to another 64 blocks looking for additional VSD's */
184 for (j = 1; j < 64; j++) {
185 if (j > 1) {
186 lseek(fd, j*bs*2048+32768, SEEK_SET);
187 if (read(fd, (char *)&isosb, sizeof(isosb))
188 != sizeof(isosb))
189 return 0;
190 }
191 /* If we find NSR0x then call it udf:
192 NSR01 for UDF 1.00
193 NSR02 for UDF 1.50
194 NSR03 for UDF 2.00 */
195 if (!strncmp(isosb.id, "NSR0", 4))
196 return 1;
197 if (!may_be_udf(isosb.id))
198 return 0;
199 }
200
201 return 0;
202 }
203
204 static int
205 may_be_swap(const char *s) {
206 return (strncmp(s-10, "SWAP-SPACE", 10) == 0 ||
207 strncmp(s-10, "SWAPSPACE2", 10) == 0);
208 }
209
210 /* rather weak necessary condition */
211 static int
212 may_be_adfs(const u_char *s) {
213 u_char *p;
214 int sum;
215
216 p = (u_char *) s + 511;
217 sum = 0;
218 while(--p != s)
219 sum = (sum >> 8) + (sum & 0xff) + *p;
220
221 return (sum == p[511]);
222 }
223
224 static int is_reiserfs_magic_string (struct reiserfs_super_block * rs)
225 {
226 return (!strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING,
227 strlen ( REISERFS_SUPER_MAGIC_STRING)) ||
228 !strncmp (rs->s_magic, REISER2FS_SUPER_MAGIC_STRING,
229 strlen ( REISER2FS_SUPER_MAGIC_STRING)));
230 }
231
232 char *
233 do_guess_fstype(const char *device) {
234 int fd;
235 char *type = NULL;
236 union {
237 struct minix_super_block ms;
238 struct ext_super_block es;
239 struct ext2_super_block e2s;
240 struct vxfs_super_block vs;
241 } sb; /* stuff at 1024 */
242 union {
243 struct xiafs_super_block xiasb;
244 char romfs_magic[8];
245 char qnx4fs_magic[10]; /* ignore first 4 bytes */
246 long bfs_magic;
247 struct ntfs_super_block ntfssb;
248 struct fat_super_block fatsb;
249 struct xfs_super_block xfsb;
250 struct cramfs_super_block cramfssb;
251 } xsb;
252 struct ufs_super_block ufssb;
253 union {
254 struct iso_volume_descriptor iso;
255 struct hs_volume_descriptor hs;
256 } isosb;
257 struct reiserfs_super_block reiserfssb; /* block 64 or 8 */
258 struct jfs_super_block jfssb; /* block 32 */
259 struct hfs_super_block hfssb;
260 struct hpfs_super_block hpfssb;
261 struct adfs_super_block adfssb;
262 struct sysv_super_block svsb;
263 struct stat statbuf;
264
265 /* opening and reading an arbitrary unknown path can have
266 undesired side effects - first check that `device' refers
267 to a block device */
268 if (stat (device, &statbuf) || !S_ISBLK(statbuf.st_mode))
269 return 0;
270
271 fd = open(device, O_RDONLY);
272 if (fd < 0)
273 return 0;
274
275 /* do seeks and reads in disk order, otherwise a very short
276 partition may cause a failure because of read error */
277
278 if (!type) {
279 /* block 0 */
280 if (lseek(fd, 0, SEEK_SET) != 0
281 || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb))
282 goto io_error;
283
284 if (xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC)
285 type = "xiafs";
286 else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8))
287 type = "romfs";
288 else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4))
289 type = "xfs";
290 else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
291 type = "qnx4";
292 else if(xsb.bfs_magic == 0x1badface)
293 type = "bfs";
294 else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC,
295 sizeof(xsb.ntfssb.s_magic)))
296 type = "ntfs";
297 else if(cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC)
298 type = "cramfs";
299 else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) ||
300 !strncmp(xsb.fatsb.s_os, "MSWIN", 5) ||
301 !strncmp(xsb.fatsb.s_os, "MTOOL", 5) ||
302 !strncmp(xsb.fatsb.s_os, "mkdosfs", 7) ||
303 !strncmp(xsb.fatsb.s_os, "kmkdosfs", 8) ||
304 /* Michal Svec: created by fdformat, old msdos utility for
305 formatting large (1.7) floppy disks. */
306 !strncmp(xsb.fatsb.s_os, "CH-FOR18", 8))
307 && (!strncmp(xsb.fatsb.s_fs, "FAT12 ", 8) ||
308 !strncmp(xsb.fatsb.s_fs, "FAT16 ", 8) ||
309 !strncmp(xsb.fatsb.s_fs2, "FAT32 ", 8)))
310 type = "vfat"; /* only guessing - might as well be fat or umsdos */
311 }
312
313 if (!type) {
314 /* sector 1 */
315 if (lseek(fd, 512 , SEEK_SET) != 512
316 || read(fd, (char *) &svsb, sizeof(svsb)) != sizeof(svsb))
317 goto io_error;
318 if (sysvmagic(svsb) == SYSV_SUPER_MAGIC )
319 type = "sysv";
320 }
321
322 if (!type) {
323 /* block 1 */
324 if (lseek(fd, 1024, SEEK_SET) != 1024 ||
325 read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
326 goto io_error;
327
328 /* ext2 has magic in little-endian on disk, so "swapped" is
329 superfluous; however, there have existed strange byteswapped
330 PPC ext2 systems */
331 if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC ||
332 ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC ||
333 ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) {
334 type = "ext2";
335
336 /* maybe even ext3? */
337 if ((assemble4le(sb.e2s.s_feature_compat)
338 & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
339 assemble4le(sb.e2s.s_journal_inum) != 0)
340 type = "ext3"; /* "ext3,ext2" */
341 }
342
343 else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC ||
344 minixmagic(sb.ms) == MINIX_SUPER_MAGIC2 ||
345 minixmagic(sb.ms) == swapped(MINIX_SUPER_MAGIC2) ||
346 minixmagic(sb.ms) == MINIX2_SUPER_MAGIC ||
347 minixmagic(sb.ms) == MINIX2_SUPER_MAGIC2)
348 type = "minix";
349
350 else if (extmagic(sb.es) == EXT_SUPER_MAGIC)
351 type = "ext";
352
353 else if (vxfsmagic(sb.vs) == VXFS_SUPER_MAGIC)
354 type = "vxfs";
355 }
356
357 if (!type) {
358 /* block 1 */
359 if (lseek(fd, 0x400, SEEK_SET) != 0x400
360 || read(fd, (char *) &hfssb, sizeof(hfssb)) != sizeof(hfssb))
361 goto io_error;
362
363 /* also check if block size is equal to 512 bytes,
364 since the hfs driver currently only has support
365 for block sizes of 512 bytes long, and to be
366 more accurate (sb magic is only a short int) */
367 if ((hfsmagic(hfssb) == HFS_SUPER_MAGIC &&
368 hfsblksize(hfssb) == 0x20000) ||
369 (swapped(hfsmagic(hfssb)) == HFS_SUPER_MAGIC &&
370 hfsblksize(hfssb) == 0x200))
371 type = "hfs";
372 }
373
374 if (!type) {
375 /* block 3 */
376 if (lseek(fd, 0xc00, SEEK_SET) != 0xc00
377 || read(fd, (char *) &adfssb, sizeof(adfssb)) != sizeof(adfssb))
378 goto io_error;
379
380 /* only a weak test */
381 if (may_be_adfs((u_char *) &adfssb)
382 && (adfsblksize(adfssb) >= 8 &&
383 adfsblksize(adfssb) <= 10))
384 type = "adfs";
385 }
386
387 if (!type) {
388 int mag;
389
390 /* block 8 */
391 if (lseek(fd, 8192, SEEK_SET) != 8192
392 || read(fd, (char *) &ufssb, sizeof(ufssb)) != sizeof(ufssb))
393 goto io_error;
394
395 mag = ufsmagic(ufssb);
396 if (mag == UFS_SUPER_MAGIC_LE || mag == UFS_SUPER_MAGIC_BE)
397 type = "ufs";
398 }
399
400 if (!type) {
401 /* block 8 */
402 if (lseek(fd, REISERFS_OLD_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
403 REISERFS_OLD_DISK_OFFSET_IN_BYTES
404 || read(fd, (char *) &reiserfssb, sizeof(reiserfssb)) !=
405 sizeof(reiserfssb))
406 goto io_error;
407 if (is_reiserfs_magic_string(&reiserfssb))
408 type = "reiserfs";
409 }
410
411 if (!type) {
412 /* block 8 */
413 if (lseek(fd, 0x2000, SEEK_SET) != 0x2000
414 || read(fd, (char *) &hpfssb, sizeof(hpfssb)) != sizeof(hpfssb))
415 goto io_error;
416
417 if (hpfsmagic(hpfssb) == HPFS_SUPER_MAGIC)
418 type = "hpfs";
419 }
420
421 if (!type) {
422 /* block 32 */
423 if (lseek(fd, JFS_SUPER1_OFF, SEEK_SET) != JFS_SUPER1_OFF
424 || read(fd, (char *) &jfssb, sizeof(jfssb)) != sizeof(jfssb))
425 goto io_error;
426 if (!strncmp(jfssb.s_magic, JFS_MAGIC, 4))
427 type = "jfs";
428 }
429
430 if (!type) {
431 /* block 32 */
432 if (lseek(fd, 0x8000, SEEK_SET) != 0x8000
433 || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb))
434 goto io_error;
435
436 if (strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0) {
437 /* "CDROM" */
438 type = "iso9660";
439 } else if (strncmp(isosb.iso.id, ISO_STANDARD_ID,
440 sizeof(isosb.iso.id)) == 0) {
441 /* CD001 */
442 type = "iso9660";
443 if (is_really_udf(fd))
444 type = "udf";
445 } else if (may_be_udf(isosb.iso.id))
446 type = "udf";
447 }
448
449 if (!type) {
450 /* block 64 */
451 if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
452 REISERFS_DISK_OFFSET_IN_BYTES
453 || read(fd, (char *) &reiserfssb, sizeof(reiserfssb)) !=
454 sizeof(reiserfssb))
455 goto io_error;
456 if (is_reiserfs_magic_string(&reiserfssb))
457 type = "reiserfs";
458 }
459
460 if (!type) {
461 /* perhaps the user tries to mount the swap space
462 on a new disk; warn her before she does mke2fs on it */
463 int pagesize = getpagesize();
464 int rd;
465 char buf[32768];
466
467 rd = pagesize;
468 if (rd < 8192)
469 rd = 8192;
470 if (rd > sizeof(buf))
471 rd = sizeof(buf);
472 if (lseek(fd, 0, SEEK_SET) != 0
473 || read(fd, buf, rd) != rd)
474 goto io_error;
475 if (may_be_swap(buf+pagesize) ||
476 may_be_swap(buf+4096) || may_be_swap(buf+8192))
477 type = "swap";
478 }
479
480 close (fd);
481 return(type);
482
483 io_error:
484 if (errno)
485 perror(device);
486 else
487 fprintf(stderr, _("mount: error while guessing filesystem type\n"));
488 close(fd);
489 return 0;
490 }
491
492 char *
493 guess_fstype(const char *spec) {
494 char *type = do_guess_fstype(spec);
495 if (verbose) {
496 printf (_("mount: you didn't specify a filesystem type for %s\n"),
497 spec);
498 if (!type)
499 printf (_(" I will try all types mentioned in %s or %s\n"),
500 ETC_FILESYSTEMS, PROC_FILESYSTEMS);
501 else if (!strcmp(type, "swap"))
502 printf (_(" and it looks like this is swapspace\n"));
503 else
504 printf (_(" I will try type %s\n"), type);
505 }
506 return type;
507 }
508
509 static char *
510 procfsnext(FILE *procfs) {
511 char line[100];
512 char fsname[100];
513
514 while (fgets(line, sizeof(line), procfs)) {
515 if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue;
516 if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue;
517 return strdup(fsname);
518 }
519 return 0;
520 }
521
522 /* Only use /proc/filesystems here, this is meant to test what
523 the kernel knows about, so /etc/filesystems is irrelevant.
524 Return: 1: yes, 0: no, -1: cannot open procfs */
525 int
526 is_in_procfs(const char *type) {
527 FILE *procfs;
528 char *fsname;
529 int ret = -1;
530
531 procfs = fopen(PROC_FILESYSTEMS, "r");
532 if (procfs) {
533 ret = 0;
534 while ((fsname = procfsnext(procfs)) != NULL)
535 if (!strcmp(fsname, type)) {
536 ret = 1;
537 break;
538 }
539 fclose(procfs);
540 procfs = NULL;
541 }
542 return ret;
543 }
544
545 /* Try all types in FILESYSTEMS, except those in *types,
546 in case *types starts with "no" */
547 /* return: 0: OK, -1: error in errno, 1: type not found */
548 /* when 0 or -1 is returned, *types contains the type used */
549 /* when 1 is returned, *types is NULL */
550 int
551 procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
552 char **types) {
553 char *files[2] = { ETC_FILESYSTEMS, PROC_FILESYSTEMS };
554 FILE *procfs;
555 char *fsname;
556 char *notypes = NULL;
557 int no = 0;
558 int ret = 1;
559 int errsv = 0;
560 int i;
561
562 if (*types && !strncmp(*types, "no", 2)) {
563 no = 1;
564 notypes = (*types) + 2;
565 }
566 *types = NULL;
567
568 /* Use PROC_FILESYSTEMS only when ETC_FILESYSTEMS does not exist.
569 In some cases trying a filesystem that the kernel knows about
570 on the wrong data will crash the kernel; in such cases
571 ETC_FILESYSTEMS can be used to list the filesystems that we
572 are allowed to try, and in the order they should be tried.
573 End ETC_FILESYSTEMS with a line containing a single '*' only,
574 if PROC_FILESYSTEMS should be tried afterwards. */
575
576 for (i=0; i<2; i++) {
577 procfs = fopen(files[i], "r");
578 if (!procfs)
579 continue;
580 while ((fsname = procfsnext(procfs)) != NULL) {
581 if (!strcmp(fsname, "*")) {
582 fclose(procfs);
583 goto nexti;
584 }
585 if (was_tested (fsname))
586 continue;
587 if (no && matching_type(fsname, notypes))
588 continue;
589 set_tested (fsname);
590 args->type = fsname;
591 if (verbose) {
592 printf(_("Trying %s\n"), fsname);
593 fflush(stdout);
594 }
595 if ((*mount_fn) (args) == 0) {
596 *types = fsname;
597 ret = 0;
598 break;
599 } else if (errno != EINVAL &&
600 is_in_procfs(fsname) == 1) {
601 *types = "guess";
602 ret = -1;
603 errsv = errno;
604 break;
605 }
606 }
607 free_tested();
608 fclose(procfs);
609 errno = errsv;
610 return ret;
611 nexti:;
612 }
613 return 1;
614 }