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