diff options
Diffstat (limited to 'gl/mountlist.c')
| -rw-r--r-- | gl/mountlist.c | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/gl/mountlist.c b/gl/mountlist.c new file mode 100644 index 00000000..bb01f91e --- /dev/null +++ b/gl/mountlist.c | |||
| @@ -0,0 +1,889 @@ | |||
| 1 | /* mountlist.c -- return a list of mounted file systems | ||
| 2 | |||
| 3 | Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, | ||
| 4 | 2004, 2005, 2006 Free Software Foundation, Inc. | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software Foundation, | ||
| 18 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
| 19 | |||
| 20 | #include <config.h> | ||
| 21 | |||
| 22 | #include "mountlist.h" | ||
| 23 | |||
| 24 | #include <limits.h> | ||
| 25 | #include <stdio.h> | ||
| 26 | #include <stdlib.h> | ||
| 27 | #include <string.h> | ||
| 28 | |||
| 29 | #include "xalloc.h" | ||
| 30 | |||
| 31 | #ifndef strstr | ||
| 32 | char *strstr (); | ||
| 33 | #endif | ||
| 34 | |||
| 35 | #include <errno.h> | ||
| 36 | |||
| 37 | #include <fcntl.h> | ||
| 38 | |||
| 39 | #include <unistd.h> | ||
| 40 | |||
| 41 | #if HAVE_SYS_PARAM_H | ||
| 42 | # include <sys/param.h> | ||
| 43 | #endif | ||
| 44 | |||
| 45 | #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */ | ||
| 46 | # if HAVE_SYS_UCRED_H | ||
| 47 | # include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS, | ||
| 48 | NGROUPS is used as an array dimension in ucred.h */ | ||
| 49 | # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */ | ||
| 50 | # endif | ||
| 51 | # if HAVE_SYS_MOUNT_H | ||
| 52 | # include <sys/mount.h> | ||
| 53 | # endif | ||
| 54 | # if HAVE_SYS_FS_TYPES_H | ||
| 55 | # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */ | ||
| 56 | # endif | ||
| 57 | # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME | ||
| 58 | # define FS_TYPE(Ent) ((Ent).f_fstypename) | ||
| 59 | # else | ||
| 60 | # define FS_TYPE(Ent) mnt_names[(Ent).f_type] | ||
| 61 | # endif | ||
| 62 | #endif /* MOUNTED_GETFSSTAT */ | ||
| 63 | |||
| 64 | #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ | ||
| 65 | # include <mntent.h> | ||
| 66 | # if !defined MOUNTED | ||
| 67 | # if defined _PATH_MOUNTED /* GNU libc */ | ||
| 68 | # define MOUNTED _PATH_MOUNTED | ||
| 69 | # endif | ||
| 70 | # if defined MNT_MNTTAB /* HP-UX. */ | ||
| 71 | # define MOUNTED MNT_MNTTAB | ||
| 72 | # endif | ||
| 73 | # if defined MNTTABNAME /* Dynix. */ | ||
| 74 | # define MOUNTED MNTTABNAME | ||
| 75 | # endif | ||
| 76 | # endif | ||
| 77 | #endif | ||
| 78 | |||
| 79 | #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ | ||
| 80 | # include <sys/mount.h> | ||
| 81 | #endif | ||
| 82 | |||
| 83 | #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ | ||
| 84 | # include <sys/statvfs.h> | ||
| 85 | #endif | ||
| 86 | |||
| 87 | #ifdef MOUNTED_GETMNT /* Ultrix. */ | ||
| 88 | # include <sys/mount.h> | ||
| 89 | # include <sys/fs_types.h> | ||
| 90 | #endif | ||
| 91 | |||
| 92 | #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */ | ||
| 93 | # include <fs_info.h> | ||
| 94 | # include <dirent.h> | ||
| 95 | #endif | ||
| 96 | |||
| 97 | #ifdef MOUNTED_FREAD /* SVR2. */ | ||
| 98 | # include <mnttab.h> | ||
| 99 | #endif | ||
| 100 | |||
| 101 | #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ | ||
| 102 | # include <mnttab.h> | ||
| 103 | # include <sys/fstyp.h> | ||
| 104 | # include <sys/statfs.h> | ||
| 105 | #endif | ||
| 106 | |||
| 107 | #ifdef MOUNTED_LISTMNTENT | ||
| 108 | # include <mntent.h> | ||
| 109 | #endif | ||
| 110 | |||
| 111 | #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ | ||
| 112 | # include <sys/mnttab.h> | ||
| 113 | #endif | ||
| 114 | |||
| 115 | #ifdef MOUNTED_VMOUNT /* AIX. */ | ||
| 116 | # include <fshelp.h> | ||
| 117 | # include <sys/vfs.h> | ||
| 118 | #endif | ||
| 119 | |||
| 120 | #ifdef DOLPHIN | ||
| 121 | /* So special that it's not worth putting this in autoconf. */ | ||
| 122 | # undef MOUNTED_FREAD_FSTYP | ||
| 123 | # define MOUNTED_GETMNTTBL | ||
| 124 | #endif | ||
| 125 | |||
| 126 | #if HAVE_SYS_MNTENT_H | ||
| 127 | /* This is to get MNTOPT_IGNORE on e.g. SVR4. */ | ||
| 128 | # include <sys/mntent.h> | ||
| 129 | #endif | ||
| 130 | |||
| 131 | #undef MNT_IGNORE | ||
| 132 | #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT | ||
| 133 | # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE) | ||
| 134 | #else | ||
| 135 | # define MNT_IGNORE(M) 0 | ||
| 136 | #endif | ||
| 137 | |||
| 138 | #if USE_UNLOCKED_IO | ||
| 139 | # include "unlocked-io.h" | ||
| 140 | #endif | ||
| 141 | |||
| 142 | #ifndef SIZE_MAX | ||
| 143 | # define SIZE_MAX ((size_t) -1) | ||
| 144 | #endif | ||
| 145 | |||
| 146 | /* The results of open() in this file are not used with fchdir, | ||
| 147 | therefore save some unnecessary work in fchdir.c. */ | ||
| 148 | #undef open | ||
| 149 | #undef close | ||
| 150 | |||
| 151 | /* The results of opendir() in this file are not used with dirfd and fchdir, | ||
| 152 | therefore save some unnecessary work in fchdir.c. */ | ||
| 153 | #undef opendir | ||
| 154 | #undef closedir | ||
| 155 | |||
| 156 | #ifndef ME_DUMMY | ||
| 157 | # define ME_DUMMY(Fs_name, Fs_type) \ | ||
| 158 | (strcmp (Fs_type, "autofs") == 0 \ | ||
| 159 | || strcmp (Fs_type, "none") == 0 \ | ||
| 160 | || strcmp (Fs_type, "proc") == 0 \ | ||
| 161 | || strcmp (Fs_type, "subfs") == 0 \ | ||
| 162 | /* for NetBSD 3.0 */ \ | ||
| 163 | || strcmp (Fs_type, "kernfs") == 0 \ | ||
| 164 | /* for Irix 6.5 */ \ | ||
| 165 | || strcmp (Fs_type, "ignore") == 0) | ||
| 166 | #endif | ||
| 167 | |||
| 168 | #ifndef ME_REMOTE | ||
| 169 | /* A file system is `remote' if its Fs_name contains a `:' | ||
| 170 | or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */ | ||
| 171 | # define ME_REMOTE(Fs_name, Fs_type) \ | ||
| 172 | (strchr (Fs_name, ':') != NULL \ | ||
| 173 | || ((Fs_name)[0] == '/' \ | ||
| 174 | && (Fs_name)[1] == '/' \ | ||
| 175 | && (strcmp (Fs_type, "smbfs") == 0 \ | ||
| 176 | || strcmp (Fs_type, "cifs") == 0))) | ||
| 177 | #endif | ||
| 178 | |||
| 179 | #if MOUNTED_GETMNTINFO | ||
| 180 | |||
| 181 | # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME | ||
| 182 | static char * | ||
| 183 | fstype_to_string (short int t) | ||
| 184 | { | ||
| 185 | switch (t) | ||
| 186 | { | ||
| 187 | # ifdef MOUNT_PC | ||
| 188 | case MOUNT_PC: | ||
| 189 | return "pc"; | ||
| 190 | # endif | ||
| 191 | # ifdef MOUNT_MFS | ||
| 192 | case MOUNT_MFS: | ||
| 193 | return "mfs"; | ||
| 194 | # endif | ||
| 195 | # ifdef MOUNT_LO | ||
| 196 | case MOUNT_LO: | ||
| 197 | return "lo"; | ||
| 198 | # endif | ||
| 199 | # ifdef MOUNT_TFS | ||
| 200 | case MOUNT_TFS: | ||
| 201 | return "tfs"; | ||
| 202 | # endif | ||
| 203 | # ifdef MOUNT_TMP | ||
| 204 | case MOUNT_TMP: | ||
| 205 | return "tmp"; | ||
| 206 | # endif | ||
| 207 | # ifdef MOUNT_UFS | ||
| 208 | case MOUNT_UFS: | ||
| 209 | return "ufs" ; | ||
| 210 | # endif | ||
| 211 | # ifdef MOUNT_NFS | ||
| 212 | case MOUNT_NFS: | ||
| 213 | return "nfs" ; | ||
| 214 | # endif | ||
| 215 | # ifdef MOUNT_MSDOS | ||
| 216 | case MOUNT_MSDOS: | ||
| 217 | return "msdos" ; | ||
| 218 | # endif | ||
| 219 | # ifdef MOUNT_LFS | ||
| 220 | case MOUNT_LFS: | ||
| 221 | return "lfs" ; | ||
| 222 | # endif | ||
| 223 | # ifdef MOUNT_LOFS | ||
| 224 | case MOUNT_LOFS: | ||
| 225 | return "lofs" ; | ||
| 226 | # endif | ||
| 227 | # ifdef MOUNT_FDESC | ||
| 228 | case MOUNT_FDESC: | ||
| 229 | return "fdesc" ; | ||
| 230 | # endif | ||
| 231 | # ifdef MOUNT_PORTAL | ||
| 232 | case MOUNT_PORTAL: | ||
| 233 | return "portal" ; | ||
| 234 | # endif | ||
| 235 | # ifdef MOUNT_NULL | ||
| 236 | case MOUNT_NULL: | ||
| 237 | return "null" ; | ||
| 238 | # endif | ||
| 239 | # ifdef MOUNT_UMAP | ||
| 240 | case MOUNT_UMAP: | ||
| 241 | return "umap" ; | ||
| 242 | # endif | ||
| 243 | # ifdef MOUNT_KERNFS | ||
| 244 | case MOUNT_KERNFS: | ||
| 245 | return "kernfs" ; | ||
| 246 | # endif | ||
| 247 | # ifdef MOUNT_PROCFS | ||
| 248 | case MOUNT_PROCFS: | ||
| 249 | return "procfs" ; | ||
| 250 | # endif | ||
| 251 | # ifdef MOUNT_AFS | ||
| 252 | case MOUNT_AFS: | ||
| 253 | return "afs" ; | ||
| 254 | # endif | ||
| 255 | # ifdef MOUNT_CD9660 | ||
| 256 | case MOUNT_CD9660: | ||
| 257 | return "cd9660" ; | ||
| 258 | # endif | ||
| 259 | # ifdef MOUNT_UNION | ||
| 260 | case MOUNT_UNION: | ||
| 261 | return "union" ; | ||
| 262 | # endif | ||
| 263 | # ifdef MOUNT_DEVFS | ||
| 264 | case MOUNT_DEVFS: | ||
| 265 | return "devfs" ; | ||
| 266 | # endif | ||
| 267 | # ifdef MOUNT_EXT2FS | ||
| 268 | case MOUNT_EXT2FS: | ||
| 269 | return "ext2fs" ; | ||
| 270 | # endif | ||
| 271 | default: | ||
| 272 | return "?"; | ||
| 273 | } | ||
| 274 | } | ||
| 275 | # endif | ||
| 276 | |||
| 277 | static char * | ||
| 278 | fsp_to_string (const struct statfs *fsp) | ||
| 279 | { | ||
| 280 | # if HAVE_STRUCT_STATFS_F_FSTYPENAME | ||
| 281 | return (char *) (fsp->f_fstypename); | ||
| 282 | # else | ||
| 283 | return fstype_to_string (fsp->f_type); | ||
| 284 | # endif | ||
| 285 | } | ||
| 286 | |||
| 287 | #endif /* MOUNTED_GETMNTINFO */ | ||
| 288 | |||
| 289 | #ifdef MOUNTED_VMOUNT /* AIX. */ | ||
| 290 | static char * | ||
| 291 | fstype_to_string (int t) | ||
| 292 | { | ||
| 293 | struct vfs_ent *e; | ||
| 294 | |||
| 295 | e = getvfsbytype (t); | ||
| 296 | if (!e || !e->vfsent_name) | ||
| 297 | return "none"; | ||
| 298 | else | ||
| 299 | return e->vfsent_name; | ||
| 300 | } | ||
| 301 | #endif /* MOUNTED_VMOUNT */ | ||
| 302 | |||
| 303 | |||
| 304 | #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2 | ||
| 305 | |||
| 306 | /* Return the device number from MOUNT_OPTIONS, if possible. | ||
| 307 | Otherwise return (dev_t) -1. */ | ||
| 308 | |||
| 309 | static dev_t | ||
| 310 | dev_from_mount_options (char const *mount_options) | ||
| 311 | { | ||
| 312 | /* GNU/Linux allows file system implementations to define their own | ||
| 313 | meaning for "dev=" mount options, so don't trust the meaning | ||
| 314 | here. */ | ||
| 315 | # ifndef __linux__ | ||
| 316 | |||
| 317 | static char const dev_pattern[] = ",dev="; | ||
| 318 | char const *devopt = strstr (mount_options, dev_pattern); | ||
| 319 | |||
| 320 | if (devopt) | ||
| 321 | { | ||
| 322 | char const *optval = devopt + sizeof dev_pattern - 1; | ||
| 323 | char *optvalend; | ||
| 324 | unsigned long int dev; | ||
| 325 | errno = 0; | ||
| 326 | dev = strtoul (optval, &optvalend, 16); | ||
| 327 | if (optval != optvalend | ||
| 328 | && (*optvalend == '\0' || *optvalend == ',') | ||
| 329 | && ! (dev == ULONG_MAX && errno == ERANGE) | ||
| 330 | && dev == (dev_t) dev) | ||
| 331 | return dev; | ||
| 332 | } | ||
| 333 | |||
| 334 | # endif | ||
| 335 | |||
| 336 | return -1; | ||
| 337 | } | ||
| 338 | |||
| 339 | #endif | ||
| 340 | |||
| 341 | /* Return a list of the currently mounted file systems, or NULL on error. | ||
| 342 | Add each entry to the tail of the list so that they stay in order. | ||
| 343 | If NEED_FS_TYPE is true, ensure that the file system type fields in | ||
| 344 | the returned list are valid. Otherwise, they might not be. */ | ||
| 345 | |||
| 346 | struct mount_entry * | ||
| 347 | read_file_system_list (bool need_fs_type) | ||
| 348 | { | ||
| 349 | struct mount_entry *mount_list; | ||
| 350 | struct mount_entry *me; | ||
| 351 | struct mount_entry **mtail = &mount_list; | ||
| 352 | |||
| 353 | #ifdef MOUNTED_LISTMNTENT | ||
| 354 | { | ||
| 355 | struct tabmntent *mntlist, *p; | ||
| 356 | struct mntent *mnt; | ||
| 357 | struct mount_entry *me; | ||
| 358 | |||
| 359 | /* the third and fourth arguments could be used to filter mounts, | ||
| 360 | but Crays doesn't seem to have any mounts that we want to | ||
| 361 | remove. Specifically, automount create normal NFS mounts. | ||
| 362 | */ | ||
| 363 | |||
| 364 | if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0) | ||
| 365 | return NULL; | ||
| 366 | for (p = mntlist; p; p = p->next) { | ||
| 367 | mnt = p->ment; | ||
| 368 | me = xmalloc (sizeof *me); | ||
| 369 | me->me_devname = xstrdup (mnt->mnt_fsname); | ||
| 370 | me->me_mountdir = xstrdup (mnt->mnt_dir); | ||
| 371 | me->me_type = xstrdup (mnt->mnt_type); | ||
| 372 | me->me_type_malloced = 1; | ||
| 373 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 374 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 375 | me->me_dev = -1; | ||
| 376 | *mtail = me; | ||
| 377 | mtail = &me->me_next; | ||
| 378 | } | ||
| 379 | freemntlist (mntlist); | ||
| 380 | } | ||
| 381 | #endif | ||
| 382 | |||
| 383 | #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ | ||
| 384 | { | ||
| 385 | struct mntent *mnt; | ||
| 386 | char *table = MOUNTED; | ||
| 387 | FILE *fp; | ||
| 388 | |||
| 389 | fp = setmntent (table, "r"); | ||
| 390 | if (fp == NULL) | ||
| 391 | return NULL; | ||
| 392 | |||
| 393 | while ((mnt = getmntent (fp))) | ||
| 394 | { | ||
| 395 | me = xmalloc (sizeof *me); | ||
| 396 | me->me_devname = xstrdup (mnt->mnt_fsname); | ||
| 397 | me->me_mountdir = xstrdup (mnt->mnt_dir); | ||
| 398 | me->me_type = xstrdup (mnt->mnt_type); | ||
| 399 | me->me_type_malloced = 1; | ||
| 400 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 401 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 402 | me->me_dev = dev_from_mount_options (mnt->mnt_opts); | ||
| 403 | |||
| 404 | /* Add to the linked list. */ | ||
| 405 | *mtail = me; | ||
| 406 | mtail = &me->me_next; | ||
| 407 | } | ||
| 408 | |||
| 409 | if (endmntent (fp) == 0) | ||
| 410 | goto free_then_fail; | ||
| 411 | } | ||
| 412 | #endif /* MOUNTED_GETMNTENT1. */ | ||
| 413 | |||
| 414 | #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ | ||
| 415 | { | ||
| 416 | struct statfs *fsp; | ||
| 417 | int entries; | ||
| 418 | |||
| 419 | entries = getmntinfo (&fsp, MNT_NOWAIT); | ||
| 420 | if (entries < 0) | ||
| 421 | return NULL; | ||
| 422 | for (; entries-- > 0; fsp++) | ||
| 423 | { | ||
| 424 | char *fs_type = fsp_to_string (fsp); | ||
| 425 | |||
| 426 | me = xmalloc (sizeof *me); | ||
| 427 | me->me_devname = xstrdup (fsp->f_mntfromname); | ||
| 428 | me->me_mountdir = xstrdup (fsp->f_mntonname); | ||
| 429 | me->me_type = fs_type; | ||
| 430 | me->me_type_malloced = 0; | ||
| 431 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 432 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 433 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
| 434 | |||
| 435 | /* Add to the linked list. */ | ||
| 436 | *mtail = me; | ||
| 437 | mtail = &me->me_next; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | #endif /* MOUNTED_GETMNTINFO */ | ||
| 441 | |||
| 442 | #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ | ||
| 443 | { | ||
| 444 | struct statvfs *fsp; | ||
| 445 | int entries; | ||
| 446 | |||
| 447 | entries = getmntinfo (&fsp, MNT_NOWAIT); | ||
| 448 | if (entries < 0) | ||
| 449 | return NULL; | ||
| 450 | for (; entries-- > 0; fsp++) | ||
| 451 | { | ||
| 452 | me = xmalloc (sizeof *me); | ||
| 453 | me->me_devname = xstrdup (fsp->f_mntfromname); | ||
| 454 | me->me_mountdir = xstrdup (fsp->f_mntonname); | ||
| 455 | me->me_type = xstrdup (fsp->f_fstypename); | ||
| 456 | me->me_type_malloced = 1; | ||
| 457 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 458 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 459 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
| 460 | |||
| 461 | /* Add to the linked list. */ | ||
| 462 | *mtail = me; | ||
| 463 | mtail = &me->me_next; | ||
| 464 | } | ||
| 465 | } | ||
| 466 | #endif /* MOUNTED_GETMNTINFO2 */ | ||
| 467 | |||
| 468 | #ifdef MOUNTED_GETMNT /* Ultrix. */ | ||
| 469 | { | ||
| 470 | int offset = 0; | ||
| 471 | int val; | ||
| 472 | struct fs_data fsd; | ||
| 473 | |||
| 474 | while (errno = 0, | ||
| 475 | 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, | ||
| 476 | (char *) 0))) | ||
| 477 | { | ||
| 478 | me = xmalloc (sizeof *me); | ||
| 479 | me->me_devname = xstrdup (fsd.fd_req.devname); | ||
| 480 | me->me_mountdir = xstrdup (fsd.fd_req.path); | ||
| 481 | me->me_type = gt_names[fsd.fd_req.fstype]; | ||
| 482 | me->me_type_malloced = 0; | ||
| 483 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 484 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 485 | me->me_dev = fsd.fd_req.dev; | ||
| 486 | |||
| 487 | /* Add to the linked list. */ | ||
| 488 | *mtail = me; | ||
| 489 | mtail = &me->me_next; | ||
| 490 | } | ||
| 491 | if (val < 0) | ||
| 492 | goto free_then_fail; | ||
| 493 | } | ||
| 494 | #endif /* MOUNTED_GETMNT. */ | ||
| 495 | |||
| 496 | #if defined MOUNTED_FS_STAT_DEV /* BeOS */ | ||
| 497 | { | ||
| 498 | /* The next_dev() and fs_stat_dev() system calls give the list of | ||
| 499 | all file systems, including the information returned by statvfs() | ||
| 500 | (fs type, total blocks, free blocks etc.), but without the mount | ||
| 501 | point. But on BeOS all file systems except / are mounted in the | ||
| 502 | rootfs, directly under /. | ||
| 503 | The directory name of the mount point is often, but not always, | ||
| 504 | identical to the volume name of the device. | ||
| 505 | We therefore get the list of subdirectories of /, and the list | ||
| 506 | of all file systems, and match the two lists. */ | ||
| 507 | |||
| 508 | DIR *dirp; | ||
| 509 | struct rootdir_entry | ||
| 510 | { | ||
| 511 | char *name; | ||
| 512 | dev_t dev; | ||
| 513 | ino_t ino; | ||
| 514 | struct rootdir_entry *next; | ||
| 515 | }; | ||
| 516 | struct rootdir_entry *rootdir_list; | ||
| 517 | struct rootdir_entry **rootdir_tail; | ||
| 518 | int32 pos; | ||
| 519 | dev_t dev; | ||
| 520 | fs_info fi; | ||
| 521 | |||
| 522 | /* All volumes are mounted in the rootfs, directly under /. */ | ||
| 523 | rootdir_list = NULL; | ||
| 524 | rootdir_tail = &rootdir_list; | ||
| 525 | dirp = opendir ("/"); | ||
| 526 | if (dirp) | ||
| 527 | { | ||
| 528 | struct dirent *d; | ||
| 529 | |||
| 530 | while ((d = readdir (dirp)) != NULL) | ||
| 531 | { | ||
| 532 | char *name; | ||
| 533 | struct stat statbuf; | ||
| 534 | |||
| 535 | if (strcmp (d->d_name, "..") == 0) | ||
| 536 | continue; | ||
| 537 | |||
| 538 | if (strcmp (d->d_name, ".") == 0) | ||
| 539 | name = xstrdup ("/"); | ||
| 540 | else | ||
| 541 | { | ||
| 542 | name = xmalloc (1 + strlen (d->d_name) + 1); | ||
| 543 | name[0] = '/'; | ||
| 544 | strcpy (name + 1, d->d_name); | ||
| 545 | } | ||
| 546 | |||
| 547 | if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) | ||
| 548 | { | ||
| 549 | struct rootdir_entry *re = xmalloc (sizeof *re); | ||
| 550 | re->name = name; | ||
| 551 | re->dev = statbuf.st_dev; | ||
| 552 | re->ino = statbuf.st_ino; | ||
| 553 | |||
| 554 | /* Add to the linked list. */ | ||
| 555 | *rootdir_tail = re; | ||
| 556 | rootdir_tail = &re->next; | ||
| 557 | } | ||
| 558 | else | ||
| 559 | free (name); | ||
| 560 | } | ||
| 561 | closedir (dirp); | ||
| 562 | } | ||
| 563 | *rootdir_tail = NULL; | ||
| 564 | |||
| 565 | for (pos = 0; (dev = next_dev (&pos)) >= 0; ) | ||
| 566 | if (fs_stat_dev (dev, &fi) >= 0) | ||
| 567 | { | ||
| 568 | /* Note: fi.dev == dev. */ | ||
| 569 | struct rootdir_entry *re; | ||
| 570 | |||
| 571 | for (re = rootdir_list; re; re = re->next) | ||
| 572 | if (re->dev == fi.dev && re->ino == fi.root) | ||
| 573 | break; | ||
| 574 | |||
| 575 | me = xmalloc (sizeof *me); | ||
| 576 | me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name); | ||
| 577 | me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name); | ||
| 578 | me->me_type = xstrdup (fi.fsh_name); | ||
| 579 | me->me_type_malloced = 1; | ||
| 580 | me->me_dev = fi.dev; | ||
| 581 | me->me_dummy = 0; | ||
| 582 | me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0; | ||
| 583 | |||
| 584 | /* Add to the linked list. */ | ||
| 585 | *mtail = me; | ||
| 586 | mtail = &me->me_next; | ||
| 587 | } | ||
| 588 | *mtail = NULL; | ||
| 589 | |||
| 590 | while (rootdir_list != NULL) | ||
| 591 | { | ||
| 592 | struct rootdir_entry *re = rootdir_list; | ||
| 593 | rootdir_list = re->next; | ||
| 594 | free (re->name); | ||
| 595 | free (re); | ||
| 596 | } | ||
| 597 | } | ||
| 598 | #endif /* MOUNTED_FS_STAT_DEV */ | ||
| 599 | |||
| 600 | #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ | ||
| 601 | { | ||
| 602 | int numsys, counter; | ||
| 603 | size_t bufsize; | ||
| 604 | struct statfs *stats; | ||
| 605 | |||
| 606 | numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT); | ||
| 607 | if (numsys < 0) | ||
| 608 | return (NULL); | ||
| 609 | if (SIZE_MAX / sizeof *stats <= numsys) | ||
| 610 | xalloc_die (); | ||
| 611 | |||
| 612 | bufsize = (1 + numsys) * sizeof *stats; | ||
| 613 | stats = xmalloc (bufsize); | ||
| 614 | numsys = getfsstat (stats, bufsize, MNT_NOWAIT); | ||
| 615 | |||
| 616 | if (numsys < 0) | ||
| 617 | { | ||
| 618 | free (stats); | ||
| 619 | return (NULL); | ||
| 620 | } | ||
| 621 | |||
| 622 | for (counter = 0; counter < numsys; counter++) | ||
| 623 | { | ||
| 624 | me = xmalloc (sizeof *me); | ||
| 625 | me->me_devname = xstrdup (stats[counter].f_mntfromname); | ||
| 626 | me->me_mountdir = xstrdup (stats[counter].f_mntonname); | ||
| 627 | me->me_type = xstrdup (FS_TYPE (stats[counter])); | ||
| 628 | me->me_type_malloced = 1; | ||
| 629 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 630 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 631 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
| 632 | |||
| 633 | /* Add to the linked list. */ | ||
| 634 | *mtail = me; | ||
| 635 | mtail = &me->me_next; | ||
| 636 | } | ||
| 637 | |||
| 638 | free (stats); | ||
| 639 | } | ||
| 640 | #endif /* MOUNTED_GETFSSTAT */ | ||
| 641 | |||
| 642 | #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */ | ||
| 643 | { | ||
| 644 | struct mnttab mnt; | ||
| 645 | char *table = "/etc/mnttab"; | ||
| 646 | FILE *fp; | ||
| 647 | |||
| 648 | fp = fopen (table, "r"); | ||
| 649 | if (fp == NULL) | ||
| 650 | return NULL; | ||
| 651 | |||
| 652 | while (fread (&mnt, sizeof mnt, 1, fp) > 0) | ||
| 653 | { | ||
| 654 | me = xmalloc (sizeof *me); | ||
| 655 | # ifdef GETFSTYP /* SVR3. */ | ||
| 656 | me->me_devname = xstrdup (mnt.mt_dev); | ||
| 657 | # else | ||
| 658 | me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6); | ||
| 659 | strcpy (me->me_devname, "/dev/"); | ||
| 660 | strcpy (me->me_devname + 5, mnt.mt_dev); | ||
| 661 | # endif | ||
| 662 | me->me_mountdir = xstrdup (mnt.mt_filsys); | ||
| 663 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
| 664 | me->me_type = ""; | ||
| 665 | me->me_type_malloced = 0; | ||
| 666 | # ifdef GETFSTYP /* SVR3. */ | ||
| 667 | if (need_fs_type) | ||
| 668 | { | ||
| 669 | struct statfs fsd; | ||
| 670 | char typebuf[FSTYPSZ]; | ||
| 671 | |||
| 672 | if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 | ||
| 673 | && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) | ||
| 674 | { | ||
| 675 | me->me_type = xstrdup (typebuf); | ||
| 676 | me->me_type_malloced = 1; | ||
| 677 | } | ||
| 678 | } | ||
| 679 | # endif | ||
| 680 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 681 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 682 | |||
| 683 | /* Add to the linked list. */ | ||
| 684 | *mtail = me; | ||
| 685 | mtail = &me->me_next; | ||
| 686 | } | ||
| 687 | |||
| 688 | if (ferror (fp)) | ||
| 689 | { | ||
| 690 | /* The last fread() call must have failed. */ | ||
| 691 | int saved_errno = errno; | ||
| 692 | fclose (fp); | ||
| 693 | errno = saved_errno; | ||
| 694 | goto free_then_fail; | ||
| 695 | } | ||
| 696 | |||
| 697 | if (fclose (fp) == EOF) | ||
| 698 | goto free_then_fail; | ||
| 699 | } | ||
| 700 | #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ | ||
| 701 | |||
| 702 | #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */ | ||
| 703 | { | ||
| 704 | struct mntent **mnttbl = getmnttbl (), **ent; | ||
| 705 | for (ent=mnttbl;*ent;ent++) | ||
| 706 | { | ||
| 707 | me = xmalloc (sizeof *me); | ||
| 708 | me->me_devname = xstrdup ( (*ent)->mt_resource); | ||
| 709 | me->me_mountdir = xstrdup ( (*ent)->mt_directory); | ||
| 710 | me->me_type = xstrdup ((*ent)->mt_fstype); | ||
| 711 | me->me_type_malloced = 1; | ||
| 712 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
| 713 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 714 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
| 715 | |||
| 716 | /* Add to the linked list. */ | ||
| 717 | *mtail = me; | ||
| 718 | mtail = &me->me_next; | ||
| 719 | } | ||
| 720 | endmnttbl (); | ||
| 721 | } | ||
| 722 | #endif | ||
| 723 | |||
| 724 | #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ | ||
| 725 | { | ||
| 726 | struct mnttab mnt; | ||
| 727 | char *table = MNTTAB; | ||
| 728 | FILE *fp; | ||
| 729 | int ret; | ||
| 730 | int lockfd = -1; | ||
| 731 | |||
| 732 | # if defined F_RDLCK && defined F_SETLKW | ||
| 733 | /* MNTTAB_LOCK is a macro name of our own invention; it's not present in | ||
| 734 | e.g. Solaris 2.6. If the SVR4 folks ever define a macro | ||
| 735 | for this file name, we should use their macro name instead. | ||
| 736 | (Why not just lock MNTTAB directly? We don't know.) */ | ||
| 737 | # ifndef MNTTAB_LOCK | ||
| 738 | # define MNTTAB_LOCK "/etc/.mnttab.lock" | ||
| 739 | # endif | ||
| 740 | lockfd = open (MNTTAB_LOCK, O_RDONLY); | ||
| 741 | if (0 <= lockfd) | ||
| 742 | { | ||
| 743 | struct flock flock; | ||
| 744 | flock.l_type = F_RDLCK; | ||
| 745 | flock.l_whence = SEEK_SET; | ||
| 746 | flock.l_start = 0; | ||
| 747 | flock.l_len = 0; | ||
| 748 | while (fcntl (lockfd, F_SETLKW, &flock) == -1) | ||
| 749 | if (errno != EINTR) | ||
| 750 | { | ||
| 751 | int saved_errno = errno; | ||
| 752 | close (lockfd); | ||
| 753 | errno = saved_errno; | ||
| 754 | return NULL; | ||
| 755 | } | ||
| 756 | } | ||
| 757 | else if (errno != ENOENT) | ||
| 758 | return NULL; | ||
| 759 | # endif | ||
| 760 | |||
| 761 | errno = 0; | ||
| 762 | fp = fopen (table, "r"); | ||
| 763 | if (fp == NULL) | ||
| 764 | ret = errno; | ||
| 765 | else | ||
| 766 | { | ||
| 767 | while ((ret = getmntent (fp, &mnt)) == 0) | ||
| 768 | { | ||
| 769 | me = xmalloc (sizeof *me); | ||
| 770 | me->me_devname = xstrdup (mnt.mnt_special); | ||
| 771 | me->me_mountdir = xstrdup (mnt.mnt_mountp); | ||
| 772 | me->me_type = xstrdup (mnt.mnt_fstype); | ||
| 773 | me->me_type_malloced = 1; | ||
| 774 | me->me_dummy = MNT_IGNORE (&mnt) != 0; | ||
| 775 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
| 776 | me->me_dev = dev_from_mount_options (mnt.mnt_mntopts); | ||
| 777 | |||
| 778 | /* Add to the linked list. */ | ||
| 779 | *mtail = me; | ||
| 780 | mtail = &me->me_next; | ||
| 781 | } | ||
| 782 | |||
| 783 | ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; | ||
| 784 | } | ||
| 785 | |||
| 786 | if (0 <= lockfd && close (lockfd) != 0) | ||
| 787 | ret = errno; | ||
| 788 | |||
| 789 | if (0 <= ret) | ||
| 790 | { | ||
| 791 | errno = ret; | ||
| 792 | goto free_then_fail; | ||
| 793 | } | ||
| 794 | } | ||
| 795 | #endif /* MOUNTED_GETMNTENT2. */ | ||
| 796 | |||
| 797 | #ifdef MOUNTED_VMOUNT /* AIX. */ | ||
| 798 | { | ||
| 799 | int bufsize; | ||
| 800 | char *entries, *thisent; | ||
| 801 | struct vmount *vmp; | ||
| 802 | int n_entries; | ||
| 803 | int i; | ||
| 804 | |||
| 805 | /* Ask how many bytes to allocate for the mounted file system info. */ | ||
| 806 | if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0) | ||
| 807 | return NULL; | ||
| 808 | entries = xmalloc (bufsize); | ||
| 809 | |||
| 810 | /* Get the list of mounted file systems. */ | ||
| 811 | n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); | ||
| 812 | if (n_entries < 0) | ||
| 813 | { | ||
| 814 | int saved_errno = errno; | ||
| 815 | free (entries); | ||
| 816 | errno = saved_errno; | ||
| 817 | return NULL; | ||
| 818 | } | ||
| 819 | |||
| 820 | for (i = 0, thisent = entries; | ||
| 821 | i < n_entries; | ||
| 822 | i++, thisent += vmp->vmt_length) | ||
| 823 | { | ||
| 824 | char *options, *ignore; | ||
| 825 | |||
| 826 | vmp = (struct vmount *) thisent; | ||
| 827 | me = xmalloc (sizeof *me); | ||
| 828 | if (vmp->vmt_flags & MNT_REMOTE) | ||
| 829 | { | ||
| 830 | char *host, *dir; | ||
| 831 | |||
| 832 | me->me_remote = 1; | ||
| 833 | /* Prepend the remote dirname. */ | ||
| 834 | host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; | ||
| 835 | dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; | ||
| 836 | me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2); | ||
| 837 | strcpy (me->me_devname, host); | ||
| 838 | strcat (me->me_devname, ":"); | ||
| 839 | strcat (me->me_devname, dir); | ||
| 840 | } | ||
| 841 | else | ||
| 842 | { | ||
| 843 | me->me_remote = 0; | ||
| 844 | me->me_devname = xstrdup (thisent + | ||
| 845 | vmp->vmt_data[VMT_OBJECT].vmt_off); | ||
| 846 | } | ||
| 847 | me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); | ||
| 848 | me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); | ||
| 849 | me->me_type_malloced = 1; | ||
| 850 | options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; | ||
| 851 | ignore = strstr (options, "ignore"); | ||
| 852 | me->me_dummy = (ignore | ||
| 853 | && (ignore == options || ignore[-1] == ',') | ||
| 854 | && (ignore[sizeof "ignore" - 1] == ',' | ||
| 855 | || ignore[sizeof "ignore" - 1] == '\0')); | ||
| 856 | me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */ | ||
| 857 | |||
| 858 | /* Add to the linked list. */ | ||
| 859 | *mtail = me; | ||
| 860 | mtail = &me->me_next; | ||
| 861 | } | ||
| 862 | free (entries); | ||
| 863 | } | ||
| 864 | #endif /* MOUNTED_VMOUNT. */ | ||
| 865 | |||
| 866 | *mtail = NULL; | ||
| 867 | return mount_list; | ||
| 868 | |||
| 869 | |||
| 870 | free_then_fail: | ||
| 871 | { | ||
| 872 | int saved_errno = errno; | ||
| 873 | *mtail = NULL; | ||
| 874 | |||
| 875 | while (mount_list) | ||
| 876 | { | ||
| 877 | me = mount_list->me_next; | ||
| 878 | free (mount_list->me_devname); | ||
| 879 | free (mount_list->me_mountdir); | ||
| 880 | if (mount_list->me_type_malloced) | ||
| 881 | free (mount_list->me_type); | ||
| 882 | free (mount_list); | ||
| 883 | mount_list = me; | ||
| 884 | } | ||
| 885 | |||
| 886 | errno = saved_errno; | ||
| 887 | return NULL; | ||
| 888 | } | ||
| 889 | } | ||
