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