summaryrefslogtreecommitdiffstats
path: root/gl/mountlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/mountlist.c')
-rw-r--r--gl/mountlist.c399
1 files changed, 185 insertions, 214 deletions
diff --git a/gl/mountlist.c b/gl/mountlist.c
index dcff6f83..66b3f3d5 100644
--- a/gl/mountlist.c
+++ b/gl/mountlist.c
@@ -1,6 +1,6 @@
1/* mountlist.c -- return a list of mounted file systems 1/* mountlist.c -- return a list of mounted file systems
2 2
3 Copyright (C) 1991-1992, 1997-2025 Free Software Foundation, Inc. 3 Copyright (C) 1991-1992, 1997-2026 Free Software Foundation, Inc.
4 4
5 This program is free software: you can redistribute it and/or modify 5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@
41# include <sys/sysmacros.h> 41# include <sys/sysmacros.h>
42#endif 42#endif
43 43
44#if defined MOUNTED_GETFSSTAT /* OSF/1, also (obsolete) Apple Darwin 1.3 */ 44#if defined MOUNTED_GETFSSTAT /* (obsolete) Apple Darwin 1.3 */
45# if HAVE_SYS_UCRED_H 45# if HAVE_SYS_UCRED_H
46# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS, 46# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
47 NGROUPS is used as an array dimension in ucred.h */ 47 NGROUPS is used as an array dimension in ucred.h */
@@ -60,7 +60,7 @@
60# endif 60# endif
61#endif /* MOUNTED_GETFSSTAT */ 61#endif /* MOUNTED_GETFSSTAT */
62 62
63#ifdef MOUNTED_GETMNTENT1 /* glibc, HP-UX, IRIX, Cygwin, Android, 63#ifdef MOUNTED_GETMNTENT1 /* glibc, HP-UX, Cygwin, Android,
64 also (obsolete) 4.3BSD, SunOS */ 64 also (obsolete) 4.3BSD, SunOS */
65# include <mntent.h> 65# include <mntent.h>
66# include <sys/types.h> 66# include <sys/types.h>
@@ -171,23 +171,21 @@
171#endif 171#endif
172 172
173#define ME_DUMMY_0(Fs_name, Fs_type) \ 173#define ME_DUMMY_0(Fs_name, Fs_type) \
174 (strcmp (Fs_type, "autofs") == 0 \ 174 (streq (Fs_type, "autofs") \
175 || strcmp (Fs_type, "proc") == 0 \ 175 || streq (Fs_type, "proc") \
176 || strcmp (Fs_type, "subfs") == 0 \ 176 || streq (Fs_type, "subfs") \
177 /* for Linux 2.6/3.x */ \ 177 /* for Linux 2.6/3.x */ \
178 || strcmp (Fs_type, "debugfs") == 0 \ 178 || streq (Fs_type, "debugfs") \
179 || strcmp (Fs_type, "devpts") == 0 \ 179 || streq (Fs_type, "devpts") \
180 || strcmp (Fs_type, "fusectl") == 0 \ 180 || streq (Fs_type, "fusectl") \
181 || strcmp (Fs_type, "fuse.portal") == 0 \ 181 || streq (Fs_type, "fuse.portal") \
182 || strcmp (Fs_type, "mqueue") == 0 \ 182 || streq (Fs_type, "mqueue") \
183 || strcmp (Fs_type, "rpc_pipefs") == 0 \ 183 || streq (Fs_type, "rpc_pipefs") \
184 || strcmp (Fs_type, "sysfs") == 0 \ 184 || streq (Fs_type, "sysfs") \
185 /* FreeBSD, Linux 2.4 */ \ 185 /* FreeBSD, Linux 2.4 */ \
186 || strcmp (Fs_type, "devfs") == 0 \ 186 || streq (Fs_type, "devfs") \
187 /* for NetBSD 3.0 */ \ 187 /* for NetBSD 3.0 */ \
188 || strcmp (Fs_type, "kernfs") == 0 \ 188 || streq (Fs_type, "kernfs"))
189 /* for Irix 6.5 */ \
190 || strcmp (Fs_type, "ignore") == 0)
191 189
192/* Historically, we have marked as "dummy" any file system of type "none", 190/* Historically, we have marked as "dummy" any file system of type "none",
193 but now that programs like du need to know about bind-mounted directories, 191 but now that programs like du need to know about bind-mounted directories,
@@ -196,10 +194,10 @@
196#ifdef MOUNTED_GETMNTENT1 194#ifdef MOUNTED_GETMNTENT1
197# define ME_DUMMY(Fs_name, Fs_type, Bind) \ 195# define ME_DUMMY(Fs_name, Fs_type, Bind) \
198 (ME_DUMMY_0 (Fs_name, Fs_type) \ 196 (ME_DUMMY_0 (Fs_name, Fs_type) \
199 || (strcmp (Fs_type, "none") == 0 && !Bind)) 197 || (streq (Fs_type, "none") && !Bind))
200#else 198#else
201# define ME_DUMMY(Fs_name, Fs_type) \ 199# define ME_DUMMY(Fs_name, Fs_type) \
202 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0) 200 (ME_DUMMY_0 (Fs_name, Fs_type) || streq (Fs_type, "none"))
203#endif 201#endif
204 202
205#ifdef __CYGWIN__ 203#ifdef __CYGWIN__
@@ -240,19 +238,19 @@ me_remote (char const *fs_name, _GL_UNUSED char const *fs_type)
240 (strchr (Fs_name, ':') != NULL \ 238 (strchr (Fs_name, ':') != NULL \
241 || ((Fs_name)[0] == '/' \ 239 || ((Fs_name)[0] == '/' \
242 && (Fs_name)[1] == '/' \ 240 && (Fs_name)[1] == '/' \
243 && (strcmp (Fs_type, "smbfs") == 0 \ 241 && (streq (Fs_type, "smbfs") \
244 || strcmp (Fs_type, "smb3") == 0 \ 242 || streq (Fs_type, "smb3") \
245 || strcmp (Fs_type, "cifs") == 0)) \ 243 || streq (Fs_type, "cifs"))) \
246 || strcmp (Fs_type, "acfs") == 0 \ 244 || streq (Fs_type, "acfs") \
247 || strcmp (Fs_type, "afs") == 0 \ 245 || streq (Fs_type, "afs") \
248 || strcmp (Fs_type, "coda") == 0 \ 246 || streq (Fs_type, "coda") \
249 || strcmp (Fs_type, "auristorfs") == 0 \ 247 || streq (Fs_type, "auristorfs") \
250 || strcmp (Fs_type, "fhgfs") == 0 \ 248 || streq (Fs_type, "fhgfs") \
251 || strcmp (Fs_type, "gpfs") == 0 \ 249 || streq (Fs_type, "gpfs") \
252 || strcmp (Fs_type, "ibrix") == 0 \ 250 || streq (Fs_type, "ibrix") \
253 || strcmp (Fs_type, "ocfs2") == 0 \ 251 || streq (Fs_type, "ocfs2") \
254 || strcmp (Fs_type, "vxfs") == 0 \ 252 || streq (Fs_type, "vxfs") \
255 || strcmp ("-hosts", Fs_name) == 0) 253 || streq ("-hosts", Fs_name))
256#endif 254#endif
257 255
258#if MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */ 256#if MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */
@@ -369,9 +367,7 @@ fsp_to_string (const struct statfs *fsp)
369static char * 367static char *
370fstype_to_string (int t) 368fstype_to_string (int t)
371{ 369{
372 struct vfs_ent *e; 370 struct vfs_ent *e = getvfsbytype (t);
373
374 e = getvfsbytype (t);
375 if (!e || !e->vfsent_name) 371 if (!e || !e->vfsent_name)
376 return "none"; 372 return "none";
377 else 373 else
@@ -400,10 +396,9 @@ dev_from_mount_options (char const *mount_options)
400 char const *optval = devopt + sizeof dev_pattern - 1; 396 char const *optval = devopt + sizeof dev_pattern - 1;
401 if (c_isxdigit (*optval)) 397 if (c_isxdigit (*optval))
402 { 398 {
403 char *optvalend;
404 unsigned long int dev;
405 errno = 0; 399 errno = 0;
406 dev = strtoul (optval, &optvalend, 16); 400 char *optvalend;
401 unsigned long int dev = strtoul (optval, &optvalend, 16);
407 if (optval != optvalend 402 if (optval != optvalend
408 && (*optvalend == '\0' || *optvalend == ',') 403 && (*optvalend == '\0' || *optvalend == ',')
409 && ! (dev == ULONG_MAX && errno == ERANGE) 404 && ! (dev == ULONG_MAX && errno == ERANGE)
@@ -427,9 +422,9 @@ dev_from_mount_options (char const *mount_options)
427static void 422static void
428unescape_tab (char *str) 423unescape_tab (char *str)
429{ 424{
430 size_t i, j = 0; 425 size_t j = 0;
431 size_t len = strlen (str) + 1; 426 size_t len = strlen (str) + 1;
432 for (i = 0; i < len; i++) 427 for (size_t i = 0; i < len; i++)
433 { 428 {
434 if (str[i] == '\\' && (i + 4 < len) 429 if (str[i] == '\\' && (i + 4 < len)
435 && str[i + 1] >= '0' && str[i + 1] <= '3' 430 && str[i + 1] >= '0' && str[i + 1] <= '3'
@@ -468,18 +463,16 @@ read_file_system_list (bool need_fs_type)
468 struct mount_entry **mtail = &mount_list; 463 struct mount_entry **mtail = &mount_list;
469 (void) need_fs_type; 464 (void) need_fs_type;
470 465
471#ifdef MOUNTED_GETMNTENT1 /* glibc, HP-UX, IRIX, Cygwin, Android, 466#ifdef MOUNTED_GETMNTENT1 /* glibc, HP-UX, Cygwin, Android,
472 also (obsolete) 4.3BSD, SunOS */ 467 also (obsolete) 4.3BSD, SunOS */
473 { 468 {
474 FILE *fp;
475
476# if defined __linux__ || defined __ANDROID__ 469# if defined __linux__ || defined __ANDROID__
477 /* Try parsing mountinfo first, as that make device IDs available. 470 /* Try parsing mountinfo first, as that make device IDs available.
478 Note we could use libmount routines to simplify this parsing a little 471 Note we could use libmount routines to simplify this parsing a little
479 (and that code is in previous versions of this function), however 472 (and that code is in previous versions of this function), however
480 libmount depends on libselinux which pulls in many dependencies. */ 473 libmount depends on libselinux which pulls in many dependencies. */
481 char const *mountinfo = "/proc/self/mountinfo"; 474 char const *mountinfo = "/proc/self/mountinfo";
482 fp = fopen (mountinfo, "re"); 475 FILE *fp = fopen (mountinfo, "re");
483 if (fp != NULL) 476 if (fp != NULL)
484 { 477 {
485 char *line = NULL; 478 char *line = NULL;
@@ -497,61 +490,61 @@ read_file_system_list (bool need_fs_type)
497 &devmaj, &devmin, 490 &devmaj, &devmin,
498 &mntroot_s); 491 &mntroot_s);
499 492
500 if (rc != 2 && rc != 3) /* 3 if %n included in count. */ 493 if (rc == 2 || rc == 3) /* 3 if %n included in count. */
501 continue; 494 {
502 495 /* find end of MNTROOT. */
503 /* find end of MNTROOT. */ 496 char *mntroot = line + mntroot_s;
504 char *mntroot = line + mntroot_s; 497 char *blank = terminate_at_blank (mntroot);
505 char *blank = terminate_at_blank (mntroot); 498 if (blank)
506 if (! blank) 499 {
507 continue; 500 /* find end of TARGET. */
508 501 char *target = blank + 1;
509 /* find end of TARGET. */ 502 blank = terminate_at_blank (target);
510 char *target = blank + 1; 503 if (blank)
511 blank = terminate_at_blank (target); 504 {
512 if (! blank) 505 /* skip optional fields, terminated by " - " */
513 continue; 506 char *dash = strstr (blank + 1, " - ");
514 507 if (dash)
515 /* skip optional fields, terminated by " - " */ 508 {
516 char *dash = strstr (blank + 1, " - "); 509 /* advance past the " - " separator. */
517 if (! dash) 510 char *fstype = dash + 3;
518 continue; 511 blank = terminate_at_blank (fstype);
519 512 if (blank)
520 /* advance past the " - " separator. */ 513 {
521 char *fstype = dash + 3; 514 /* find end of SOURCE. */
522 blank = terminate_at_blank (fstype); 515 char *source = blank + 1;
523 if (! blank) 516 if (terminate_at_blank (source))
524 continue; 517 {
525 518 /* manipulate the sub-strings in place. */
526 /* find end of SOURCE. */ 519 unescape_tab (source);
527 char *source = blank + 1; 520 unescape_tab (target);
528 if (! terminate_at_blank (source)) 521 unescape_tab (mntroot);
529 continue; 522 unescape_tab (fstype);
530 523
531 /* manipulate the sub-strings in place. */ 524 me = xmalloc (sizeof *me);
532 unescape_tab (source); 525
533 unescape_tab (target); 526 me->me_devname = xstrdup (source);
534 unescape_tab (mntroot); 527 me->me_mountdir = xstrdup (target);
535 unescape_tab (fstype); 528 me->me_mntroot = xstrdup (mntroot);
536 529 me->me_type = xstrdup (fstype);
537 me = xmalloc (sizeof *me); 530 me->me_type_malloced = 1;
538 531 me->me_dev = makedev (devmaj, devmin);
539 me->me_devname = xstrdup (source); 532 /* we pass "false" for the "Bind" option as that's only
540 me->me_mountdir = xstrdup (target); 533 significant when the Fs_type is "none" which will not be
541 me->me_mntroot = xstrdup (mntroot); 534 the case when parsing "/proc/self/mountinfo", and only
542 me->me_type = xstrdup (fstype); 535 applies for static /etc/mtab files. */
543 me->me_type_malloced = 1; 536 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, false);
544 me->me_dev = makedev (devmaj, devmin); 537 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
545 /* we pass "false" for the "Bind" option as that's only 538
546 significant when the Fs_type is "none" which will not be 539 /* Add to the linked list. */
547 the case when parsing "/proc/self/mountinfo", and only 540 *mtail = me;
548 applies for static /etc/mtab files. */ 541 mtail = &me->me_next;
549 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, false); 542 }
550 me->me_remote = ME_REMOTE (me->me_devname, me->me_type); 543 }
551 544 }
552 /* Add to the linked list. */ 545 }
553 *mtail = me; 546 }
554 mtail = &me->me_next; 547 }
555 } 548 }
556 549
557 free (line); 550 free (line);
@@ -570,14 +563,14 @@ read_file_system_list (bool need_fs_type)
570 else /* fallback to /proc/self/mounts (/etc/mtab). */ 563 else /* fallback to /proc/self/mounts (/etc/mtab). */
571# endif /* __linux__ || __ANDROID__ */ 564# endif /* __linux__ || __ANDROID__ */
572 { 565 {
573 struct mntent *mnt;
574 char const *table = MOUNTED; 566 char const *table = MOUNTED;
575 567
576 fp = setmntent (table, "r"); 568 FILE *mfp = setmntent (table, "r");
577 if (fp == NULL) 569 if (mfp == NULL)
578 return NULL; 570 return NULL;
579 571
580 while ((mnt = getmntent (fp))) 572 struct mntent *mnt;
573 while ((mnt = getmntent (mfp)))
581 { 574 {
582 bool bind = hasmntopt (mnt, "bind"); 575 bool bind = hasmntopt (mnt, "bind");
583 576
@@ -596,7 +589,7 @@ read_file_system_list (bool need_fs_type)
596 mtail = &me->me_next; 589 mtail = &me->me_next;
597 } 590 }
598 591
599 if (endmntent (fp) == 0) 592 if (endmntent (mfp) == 0)
600 goto free_then_fail; 593 goto free_then_fail;
601 } 594 }
602 } 595 }
@@ -605,9 +598,7 @@ read_file_system_list (bool need_fs_type)
605#ifdef MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */ 598#ifdef MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */
606 { 599 {
607 struct statfs *fsp; 600 struct statfs *fsp;
608 int entries; 601 int entries = getmntinfo (&fsp, MNT_NOWAIT);
609
610 entries = getmntinfo (&fsp, MNT_NOWAIT);
611 if (entries < 0) 602 if (entries < 0)
612 return NULL; 603 return NULL;
613 for (; entries-- > 0; fsp++) 604 for (; entries-- > 0; fsp++)
@@ -634,9 +625,7 @@ read_file_system_list (bool need_fs_type)
634#ifdef MOUNTED_GETMNTINFO2 /* NetBSD, Minix */ 625#ifdef MOUNTED_GETMNTINFO2 /* NetBSD, Minix */
635 { 626 {
636 struct statvfs *fsp; 627 struct statvfs *fsp;
637 int entries; 628 int entries = getmntinfo (&fsp, MNT_NOWAIT);
638
639 entries = getmntinfo (&fsp, MNT_NOWAIT);
640 if (entries < 0) 629 if (entries < 0)
641 return NULL; 630 return NULL;
642 for (; entries-- > 0; fsp++) 631 for (; entries-- > 0; fsp++)
@@ -670,7 +659,6 @@ read_file_system_list (bool need_fs_type)
670 We therefore get the list of subdirectories of /, and the list 659 We therefore get the list of subdirectories of /, and the list
671 of all file systems, and match the two lists. */ 660 of all file systems, and match the two lists. */
672 661
673 DIR *dirp;
674 struct rootdir_entry 662 struct rootdir_entry
675 { 663 {
676 char *name; 664 char *name;
@@ -678,16 +666,11 @@ read_file_system_list (bool need_fs_type)
678 ino_t ino; 666 ino_t ino;
679 struct rootdir_entry *next; 667 struct rootdir_entry *next;
680 }; 668 };
681 struct rootdir_entry *rootdir_list;
682 struct rootdir_entry **rootdir_tail;
683 int32 pos;
684 dev_t dev;
685 fs_info fi;
686 669
687 /* All volumes are mounted in the rootfs, directly under /. */ 670 /* All volumes are mounted in the rootfs, directly under /. */
688 rootdir_list = NULL; 671 struct rootdir_entry *rootdir_list = NULL;
689 rootdir_tail = &rootdir_list; 672 struct rootdir_entry **rootdir_tail = &rootdir_list;
690 dirp = opendir ("/"); 673 DIR *dirp = opendir ("/");
691 if (dirp) 674 if (dirp)
692 { 675 {
693 struct dirent *d; 676 struct dirent *d;
@@ -697,61 +680,64 @@ read_file_system_list (bool need_fs_type)
697 char *name; 680 char *name;
698 struct stat statbuf; 681 struct stat statbuf;
699 682
700 if (strcmp (d->d_name, "..") == 0) 683 if (! streq (d->d_name, ".."))
701 continue;
702
703 if (strcmp (d->d_name, ".") == 0)
704 name = xstrdup ("/");
705 else
706 { 684 {
707 name = xmalloc (1 + strlen (d->d_name) + 1); 685 if (streq (d->d_name, "."))
708 name[0] = '/'; 686 name = xstrdup ("/");
709 strcpy (name + 1, d->d_name); 687 else
710 } 688 {
689 name = xmalloc (1 + strlen (d->d_name) + 1);
690 name[0] = '/';
691 strcpy (name + 1, d->d_name);
692 }
711 693
712 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) 694 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
713 { 695 {
714 struct rootdir_entry *re = xmalloc (sizeof *re); 696 struct rootdir_entry *re = xmalloc (sizeof *re);
715 re->name = name; 697 re->name = name;
716 re->dev = statbuf.st_dev; 698 re->dev = statbuf.st_dev;
717 re->ino = statbuf.st_ino; 699 re->ino = statbuf.st_ino;
718 700
719 /* Add to the linked list. */ 701 /* Add to the linked list. */
720 *rootdir_tail = re; 702 *rootdir_tail = re;
721 rootdir_tail = &re->next; 703 rootdir_tail = &re->next;
704 }
705 else
706 free (name);
722 } 707 }
723 else
724 free (name);
725 } 708 }
726 closedir (dirp); 709 closedir (dirp);
727 } 710 }
728 *rootdir_tail = NULL; 711 *rootdir_tail = NULL;
729 712
730 for (pos = 0; (dev = next_dev (&pos)) >= 0; ) 713 dev_t dev;
731 if (fs_stat_dev (dev, &fi) >= 0) 714 for (int32 pos = 0; (dev = next_dev (&pos)) >= 0; )
732 { 715 {
733 /* Note: fi.dev == dev. */ 716 fs_info fi;
734 struct rootdir_entry *re; 717 if (fs_stat_dev (dev, &fi) >= 0)
735 718 {
736 for (re = rootdir_list; re; re = re->next) 719 /* Note: fi.dev == dev. */
737 if (re->dev == fi.dev && re->ino == fi.root) 720 struct rootdir_entry *re;
738 break; 721 for (re = rootdir_list; re; re = re->next)
739 722 if (re->dev == fi.dev && re->ino == fi.root)
740 me = xmalloc (sizeof *me); 723 break;
741 me->me_devname = xstrdup (fi.device_name[0] != '\0' 724
742 ? fi.device_name : fi.fsh_name); 725 me = xmalloc (sizeof *me);
743 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name); 726 me->me_devname = xstrdup (fi.device_name[0] != '\0'
744 me->me_mntroot = NULL; 727 ? fi.device_name : fi.fsh_name);
745 me->me_type = xstrdup (fi.fsh_name); 728 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
746 me->me_type_malloced = 1; 729 me->me_mntroot = NULL;
747 me->me_dev = fi.dev; 730 me->me_type = xstrdup (fi.fsh_name);
748 me->me_dummy = 0; 731 me->me_type_malloced = 1;
749 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0; 732 me->me_dev = fi.dev;
750 733 me->me_dummy = 0;
751 /* Add to the linked list. */ 734 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
752 *mtail = me; 735
753 mtail = &me->me_next; 736 /* Add to the linked list. */
754 } 737 *mtail = me;
738 mtail = &me->me_next;
739 }
740 }
755 *mtail = NULL; 741 *mtail = NULL;
756 742
757 while (rootdir_list != NULL) 743 while (rootdir_list != NULL)
@@ -764,19 +750,17 @@ read_file_system_list (bool need_fs_type)
764 } 750 }
765#endif /* MOUNTED_FS_STAT_DEV */ 751#endif /* MOUNTED_FS_STAT_DEV */
766 752
767#if defined MOUNTED_GETFSSTAT /* OSF/1, also (obsolete) Apple Darwin 1.3 */ 753#if defined MOUNTED_GETFSSTAT /* (obsolete) Apple Darwin 1.3 */
768 { 754 {
769 int numsys, counter;
770 size_t bufsize;
771 struct statfs *stats;
772 755
773 numsys = getfsstat (NULL, 0L, MNT_NOWAIT); 756 int numsys = getfsstat (NULL, 0L, MNT_NOWAIT);
774 if (numsys < 0) 757 if (numsys < 0)
775 return NULL; 758 return NULL;
759
760 struct statfs *stats;
776 if (SIZE_MAX / sizeof *stats <= numsys) 761 if (SIZE_MAX / sizeof *stats <= numsys)
777 xalloc_die (); 762 xalloc_die ();
778 763 size_t bufsize = (1 + numsys) * sizeof *stats;
779 bufsize = (1 + numsys) * sizeof *stats;
780 stats = xmalloc (bufsize); 764 stats = xmalloc (bufsize);
781 numsys = getfsstat (stats, bufsize, MNT_NOWAIT); 765 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
782 766
@@ -786,7 +770,7 @@ read_file_system_list (bool need_fs_type)
786 return NULL; 770 return NULL;
787 } 771 }
788 772
789 for (counter = 0; counter < numsys; counter++) 773 for (int counter = 0; counter < numsys; counter++)
790 { 774 {
791 me = xmalloc (sizeof *me); 775 me = xmalloc (sizeof *me);
792 me->me_devname = xstrdup (stats[counter].f_mntfromname); 776 me->me_devname = xstrdup (stats[counter].f_mntfromname);
@@ -809,14 +793,13 @@ read_file_system_list (bool need_fs_type)
809 793
810#if defined MOUNTED_FREAD_FSTYP /* (obsolete) SVR3 */ 794#if defined MOUNTED_FREAD_FSTYP /* (obsolete) SVR3 */
811 { 795 {
812 struct mnttab mnt;
813 char *table = "/etc/mnttab"; 796 char *table = "/etc/mnttab";
814 FILE *fp;
815 797
816 fp = fopen (table, "re"); 798 FILE *fp = fopen (table, "re");
817 if (fp == NULL) 799 if (fp == NULL)
818 return NULL; 800 return NULL;
819 801
802 struct mnttab mnt;
820 while (fread (&mnt, sizeof mnt, 1, fp) > 0) 803 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
821 { 804 {
822 me = xmalloc (sizeof *me); 805 me = xmalloc (sizeof *me);
@@ -862,20 +845,19 @@ read_file_system_list (bool need_fs_type)
862 845
863#ifdef MOUNTED_GETEXTMNTENT /* Solaris >= 8 */ 846#ifdef MOUNTED_GETEXTMNTENT /* Solaris >= 8 */
864 { 847 {
865 struct extmnttab mnt;
866 const char *table = MNTTAB; 848 const char *table = MNTTAB;
867 FILE *fp;
868 int ret;
869 849
870 /* No locking is needed, because the contents of /etc/mnttab is generated 850 /* No locking is needed, because the contents of /etc/mnttab is generated
871 by the kernel. */ 851 by the kernel. */
872 852
873 errno = 0; 853 errno = 0;
874 fp = fopen (table, "re"); 854 FILE *fp = fopen (table, "re");
855 int ret;
875 if (fp == NULL) 856 if (fp == NULL)
876 ret = errno; 857 ret = errno;
877 else 858 else
878 { 859 {
860 struct extmnttab mnt;
879 while ((ret = getextmntent (fp, &mnt, 1)) == 0) 861 while ((ret = getextmntent (fp, &mnt, 1)) == 0)
880 { 862 {
881 me = xmalloc (sizeof *me); 863 me = xmalloc (sizeof *me);
@@ -909,10 +891,7 @@ read_file_system_list (bool need_fs_type)
909 891
910#ifdef MOUNTED_GETMNTENT2 /* Solaris < 8, also (obsolete) SVR4 */ 892#ifdef MOUNTED_GETMNTENT2 /* Solaris < 8, also (obsolete) SVR4 */
911 { 893 {
912 struct mnttab mnt;
913 const char *table = MNTTAB; 894 const char *table = MNTTAB;
914 FILE *fp;
915 int ret;
916 int lockfd = -1; 895 int lockfd = -1;
917 896
918# if defined F_RDLCK && defined F_SETLKW 897# if defined F_RDLCK && defined F_SETLKW
@@ -945,11 +924,13 @@ read_file_system_list (bool need_fs_type)
945# endif 924# endif
946 925
947 errno = 0; 926 errno = 0;
948 fp = fopen (table, "re"); 927 FILE *fp = fopen (table, "re");
928 int ret;
949 if (fp == NULL) 929 if (fp == NULL)
950 ret = errno; 930 ret = errno;
951 else 931 else
952 { 932 {
933 struct mnttab mnt;
953 while ((ret = getmntent (fp, &mnt)) == 0) 934 while ((ret = getmntent (fp, &mnt)) == 0)
954 { 935 {
955 me = xmalloc (sizeof *me); 936 me = xmalloc (sizeof *me);
@@ -984,34 +965,24 @@ read_file_system_list (bool need_fs_type)
984 965
985#ifdef MOUNTED_VMOUNT /* AIX */ 966#ifdef MOUNTED_VMOUNT /* AIX */
986 { 967 {
987 int bufsize;
988 void *entries;
989 char *thisent;
990 struct vmount *vmp;
991 int n_entries;
992 int i;
993
994 /* Ask how many bytes to allocate for the mounted file system info. */ 968 /* Ask how many bytes to allocate for the mounted file system info. */
995 entries = &bufsize; 969 int bufsize;
996 if (mntctl (MCTL_QUERY, sizeof bufsize, entries) != 0) 970 if (mntctl (MCTL_QUERY, sizeof bufsize, &bufsize) != 0)
997 return NULL; 971 return NULL;
998 entries = xmalloc (bufsize); 972 void *entries = xmalloc (bufsize);
999 973
1000 /* Get the list of mounted file systems. */ 974 /* Get the list of mounted file systems. */
1001 n_entries = mntctl (MCTL_QUERY, bufsize, entries); 975 int n_entries = mntctl (MCTL_QUERY, bufsize, entries);
1002 if (n_entries < 0) 976 if (n_entries < 0)
1003 { 977 {
1004 free (entries); 978 free (entries);
1005 return NULL; 979 return NULL;
1006 } 980 }
1007 981
1008 for (i = 0, thisent = entries; 982 char *thisent = entries;
1009 i < n_entries; 983 for (int i = 0; i < n_entries; i++)
1010 i++, thisent += vmp->vmt_length)
1011 { 984 {
1012 char *options, *ignore; 985 struct vmount *vmp = (struct vmount *) thisent;
1013
1014 vmp = (struct vmount *) thisent;
1015 me = xmalloc (sizeof *me); 986 me = xmalloc (sizeof *me);
1016 if (vmp->vmt_flags & MNT_REMOTE) 987 if (vmp->vmt_flags & MNT_REMOTE)
1017 { 988 {
@@ -1036,8 +1007,8 @@ read_file_system_list (bool need_fs_type)
1036 me->me_mntroot = NULL; 1007 me->me_mntroot = NULL;
1037 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); 1008 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
1038 me->me_type_malloced = 1; 1009 me->me_type_malloced = 1;
1039 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; 1010 char *options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
1040 ignore = strstr (options, "ignore"); 1011 char *ignore = strstr (options, "ignore");
1041 me->me_dummy = (ignore 1012 me->me_dummy = (ignore
1042 && (ignore == options || ignore[-1] == ',') 1013 && (ignore == options || ignore[-1] == ',')
1043 && (ignore[sizeof "ignore" - 1] == ',' 1014 && (ignore[sizeof "ignore" - 1] == ','
@@ -1047,6 +1018,8 @@ read_file_system_list (bool need_fs_type)
1047 /* Add to the linked list. */ 1018 /* Add to the linked list. */
1048 *mtail = me; 1019 *mtail = me;
1049 mtail = &me->me_next; 1020 mtail = &me->me_next;
1021
1022 thisent += vmp->vmt_length;
1050 } 1023 }
1051 free (entries); 1024 free (entries);
1052 } 1025 }
@@ -1055,25 +1028,23 @@ read_file_system_list (bool need_fs_type)
1055#ifdef MOUNTED_INTERIX_STATVFS /* Interix */ 1028#ifdef MOUNTED_INTERIX_STATVFS /* Interix */
1056 { 1029 {
1057 DIR *dirp = opendir ("/dev/fs"); 1030 DIR *dirp = opendir ("/dev/fs");
1058 char node[9 + NAME_MAX];
1059
1060 if (!dirp) 1031 if (!dirp)
1061 goto free_then_fail; 1032 goto free_then_fail;
1062 1033
1063 while (1) 1034 while (1)
1064 { 1035 {
1065 struct statvfs dev;
1066 struct dirent entry;
1067 struct dirent *result;
1068
1069 /* FIXME: readdir_r is planned to be withdrawn from POSIX and 1036 /* FIXME: readdir_r is planned to be withdrawn from POSIX and
1070 marked obsolescent in glibc. Use readdir instead. */ 1037 marked obsolescent in glibc. Use readdir instead. */
1038 struct dirent entry;
1039 struct dirent *result;
1071 if (readdir_r (dirp, &entry, &result) || result == NULL) 1040 if (readdir_r (dirp, &entry, &result) || result == NULL)
1072 break; 1041 break;
1073 1042
1043 char node[9 + NAME_MAX];
1074 strcpy (node, "/dev/fs/"); 1044 strcpy (node, "/dev/fs/");
1075 strcat (node, entry.d_name); 1045 strcat (node, entry.d_name);
1076 1046
1047 struct statvfs dev;
1077 if (statvfs (node, &dev) == 0) 1048 if (statvfs (node, &dev) == 0)
1078 { 1049 {
1079 me = xmalloc (sizeof *me); 1050 me = xmalloc (sizeof *me);
@@ -1107,18 +1078,18 @@ read_file_system_list (bool need_fs_type)
1107 if ASCII 'A' + i is an available drive. See: 1078 if ASCII 'A' + i is an available drive. See:
1108 <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getlogicaldrives>. */ 1079 <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getlogicaldrives>. */
1109 DWORD value = GetLogicalDrives (); 1080 DWORD value = GetLogicalDrives ();
1110 unsigned int i;
1111 1081
1112 for (i = 0; i < 26; ++i) 1082 for (unsigned int i = 0; i < 26; ++i)
1113 { 1083 {
1114 if (value & (1U << i)) 1084 if (value & (1U << i))
1115 { 1085 {
1116 char mountdir[4]; 1086 char mountdir[4];
1117 char fs_name[MAX_PATH + 1];
1118 mountdir[0] = 'A' + i; 1087 mountdir[0] = 'A' + i;
1119 mountdir[1] = ':'; 1088 mountdir[1] = ':';
1120 mountdir[2] = '\\'; 1089 mountdir[2] = '\\';
1121 mountdir[3] = '\0'; 1090 mountdir[3] = '\0';
1091
1092 char fs_name[MAX_PATH + 1];
1122 /* Test whether the drive actually exists, and 1093 /* Test whether the drive actually exists, and
1123 get the name of the file system. See: 1094 get the name of the file system. See:
1124 <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa>. */ 1095 <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa>. */
@@ -1141,10 +1112,10 @@ read_file_system_list (bool need_fs_type)
1141 For testing of SUBST: <https://ss64.com/nt/subst.html> 1112 For testing of SUBST: <https://ss64.com/nt/subst.html>
1142 For testing of NET USE: <https://ss64.com/nt/net-use.html> */ 1113 For testing of NET USE: <https://ss64.com/nt/net-use.html> */
1143 wchar_t drive[3]; 1114 wchar_t drive[3];
1144 wchar_t mapping[MAX_PATH + 1];
1145 drive[0] = L'A' + i; 1115 drive[0] = L'A' + i;
1146 drive[1] = L':'; 1116 drive[1] = L':';
1147 drive[2] = L'\0'; 1117 drive[2] = L'\0';
1118 wchar_t mapping[MAX_PATH + 1];
1148 DWORD mapping_len = QueryDosDeviceW (drive, mapping, sizeof (mapping) / sizeof (mapping[0])); 1119 DWORD mapping_len = QueryDosDeviceW (drive, mapping, sizeof (mapping) / sizeof (mapping[0]));
1149 if (mapping_len > 4 && wcsncmp (mapping, L"\\??\\", 4) == 0) 1120 if (mapping_len > 4 && wcsncmp (mapping, L"\\??\\", 4) == 0)
1150 { 1121 {