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