diff options
Diffstat (limited to 'gl/mountlist.c')
| -rw-r--r-- | gl/mountlist.c | 399 |
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) | |||
| 369 | static char * | 367 | static char * |
| 370 | fstype_to_string (int t) | 368 | fstype_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) | |||
| 427 | static void | 422 | static void |
| 428 | unescape_tab (char *str) | 423 | unescape_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 | { |
