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