1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992, 1997-2004 Free Software Foundation, Inc.
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.
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.
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. */
18 #if HAVE_CONFIG_H
19 # include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include "xalloc.h"
29 #ifndef SIZE_MAX
30 # define SIZE_MAX ((size_t) -1)
31 #endif
33 #ifndef strstr
34 char *strstr ();
35 #endif
37 #include <errno.h>
38 #ifndef errno
39 extern int errno;
40 #endif
42 #ifdef HAVE_FCNTL_H
43 # include <fcntl.h>
44 #endif
46 #ifdef HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
50 #if HAVE_SYS_PARAM_H
51 # include <sys/param.h>
52 #endif
54 #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
55 # if HAVE_SYS_UCRED_H
56 # include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
57 NGROUPS is used as an array dimension in ucred.h */
58 # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
59 # endif
60 # if HAVE_SYS_MOUNT_H
61 # include <sys/mount.h>
62 # endif
63 # if HAVE_SYS_FS_TYPES_H
64 # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
65 # endif
66 # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
67 # define FS_TYPE(Ent) ((Ent).f_fstypename)
68 # else
69 # define FS_TYPE(Ent) mnt_names[(Ent).f_type]
70 # endif
71 #endif /* MOUNTED_GETFSSTAT */
73 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
74 # include <mntent.h>
75 # if !defined MOUNTED
76 # if defined _PATH_MOUNTED /* GNU libc */
77 # define MOUNTED _PATH_MOUNTED
78 # endif
79 # if defined MNT_MNTTAB /* HP-UX. */
80 # define MOUNTED MNT_MNTTAB
81 # endif
82 # if defined MNTTABNAME /* Dynix. */
83 # define MOUNTED MNTTABNAME
84 # endif
85 # endif
86 #endif
88 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
89 # include <sys/mount.h>
90 #endif
92 #ifdef MOUNTED_GETMNT /* Ultrix. */
93 # include <sys/mount.h>
94 # include <sys/fs_types.h>
95 #endif
97 #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
98 # include <fs_info.h>
99 # include <dirent.h>
100 #endif
102 #ifdef MOUNTED_FREAD /* SVR2. */
103 # include <mnttab.h>
104 #endif
106 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
107 # include <mnttab.h>
108 # include <sys/fstyp.h>
109 # include <sys/statfs.h>
110 #endif
112 #ifdef MOUNTED_LISTMNTENT
113 # include <mntent.h>
114 #endif
116 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
117 # include <sys/mnttab.h>
118 #endif
120 #ifdef MOUNTED_VMOUNT /* AIX. */
121 # include <fshelp.h>
122 # include <sys/vfs.h>
123 #endif
125 #ifdef DOLPHIN
126 /* So special that it's not worth putting this in autoconf. */
127 # undef MOUNTED_FREAD_FSTYP
128 # define MOUNTED_GETMNTTBL
129 #endif
131 #if HAVE_SYS_MNTENT_H
132 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
133 # include <sys/mntent.h>
134 #endif
136 #undef MNT_IGNORE
137 #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
138 # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
139 #else
140 # define MNT_IGNORE(M) 0
141 #endif
143 #include "mountlist.h"
144 #include "unlocked-io.h"
146 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
147 /* Return the value of the hexadecimal number represented by CP.
148 No prefix (like '0x') or suffix (like 'h') is expected to be
149 part of CP. */
150 /* FIXME: this can overflow */
152 static int
153 xatoi (char *cp)
154 {
155 int val;
157 val = 0;
158 while (*cp)
159 {
160 if (*cp >= 'a' && *cp <= 'f')
161 val = val * 16 + *cp - 'a' + 10;
162 else if (*cp >= 'A' && *cp <= 'F')
163 val = val * 16 + *cp - 'A' + 10;
164 else if (*cp >= '0' && *cp <= '9')
165 val = val * 16 + *cp - '0';
166 else
167 break;
168 cp++;
169 }
170 return val;
171 }
172 #endif /* MOUNTED_GETMNTENT1. */
174 #if MOUNTED_GETMNTINFO
176 # if ! HAVE_F_FSTYPENAME_IN_STATFS
177 static char *
178 fstype_to_string (short t)
179 {
180 switch (t)
181 {
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 "?";
268 }
269 }
270 # endif /* ! HAVE_F_FSTYPENAME_IN_STATFS */
272 /* __NetBSD__ || BSD_NET2 || __OpenBSD__ */
273 static char *
274 fsp_to_string (const struct statfs *fsp)
275 {
276 # if defined HAVE_F_FSTYPENAME_IN_STATFS
277 return (char *) (fsp->f_fstypename);
278 # else
279 return fstype_to_string (fsp->f_type);
280 # endif
281 }
283 #endif /* MOUNTED_GETMNTINFO */
285 #ifdef MOUNTED_VMOUNT /* AIX. */
286 static char *
287 fstype_to_string (int t)
288 {
289 struct vfs_ent *e;
291 e = getvfsbytype (t);
292 if (!e || !e->vfsent_name)
293 return "none";
294 else
295 return e->vfsent_name;
296 }
297 #endif /* MOUNTED_VMOUNT */
299 /* Return a list of the currently mounted filesystems, or NULL on error.
300 Add each entry to the tail of the list so that they stay in order.
301 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
302 the returned list are valid. Otherwise, they might not be. */
304 struct mount_entry *
305 read_filesystem_list (int need_fs_type)
306 {
307 struct mount_entry *mount_list;
308 struct mount_entry *me;
309 struct mount_entry **mtail = &mount_list;
311 #ifdef MOUNTED_LISTMNTENT
312 {
313 struct tabmntent *mntlist, *p;
314 struct mntent *mnt;
315 struct mount_entry *me;
317 /* the third and fourth arguments could be used to filter mounts,
318 but Crays doesn't seem to have any mounts that we want to
319 remove. Specifically, automount create normal NFS mounts.
320 */
322 if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
323 return NULL;
324 for (p = mntlist; p; p = p->next) {
325 mnt = p->ment;
326 me = xmalloc (sizeof *me);
327 me->me_devname = xstrdup (mnt->mnt_fsname);
328 me->me_mountdir = xstrdup (mnt->mnt_dir);
329 me->me_type = xstrdup (mnt->mnt_type);
330 me->me_type_malloced = 1;
331 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
332 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
333 me->me_dev = -1;
334 *mtail = me;
335 mtail = &me->me_next;
336 }
337 freemntlist (mntlist);
338 }
339 #endif
341 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
342 {
343 struct mntent *mnt;
344 char *table = MOUNTED;
345 FILE *fp;
346 char *devopt;
348 fp = setmntent (table, "r");
349 if (fp == NULL)
350 return NULL;
352 while ((mnt = getmntent (fp)))
353 {
354 me = xmalloc (sizeof *me);
355 me->me_devname = xstrdup (mnt->mnt_fsname);
356 me->me_mountdir = xstrdup (mnt->mnt_dir);
357 me->me_type = xstrdup (mnt->mnt_type);
358 me->me_type_malloced = 1;
359 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
360 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
361 devopt = strstr (mnt->mnt_opts, "dev=");
362 if (devopt)
363 {
364 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
365 me->me_dev = xatoi (devopt + 6);
366 else
367 me->me_dev = xatoi (devopt + 4);
368 }
369 else
370 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
372 /* Add to the linked list. */
373 *mtail = me;
374 mtail = &me->me_next;
375 }
377 if (endmntent (fp) == 0)
378 goto free_then_fail;
379 }
380 #endif /* MOUNTED_GETMNTENT1. */
382 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
383 {
384 struct statfs *fsp;
385 int entries;
387 entries = getmntinfo (&fsp, MNT_NOWAIT);
388 if (entries < 0)
389 return NULL;
390 for (; entries-- > 0; fsp++)
391 {
392 char *fs_type = fsp_to_string (fsp);
394 me = xmalloc (sizeof *me);
395 me->me_devname = xstrdup (fsp->f_mntfromname);
396 me->me_mountdir = xstrdup (fsp->f_mntonname);
397 me->me_type = fs_type;
398 me->me_type_malloced = 0;
399 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
400 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
401 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
403 /* Add to the linked list. */
404 *mtail = me;
405 mtail = &me->me_next;
406 }
407 }
408 #endif /* MOUNTED_GETMNTINFO */
410 #ifdef MOUNTED_GETMNT /* Ultrix. */
411 {
412 int offset = 0;
413 int val;
414 struct fs_data fsd;
416 while (errno = 0,
417 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
418 (char *) 0)))
419 {
420 me = xmalloc (sizeof *me);
421 me->me_devname = xstrdup (fsd.fd_req.devname);
422 me->me_mountdir = xstrdup (fsd.fd_req.path);
423 me->me_type = gt_names[fsd.fd_req.fstype];
424 me->me_type_malloced = 0;
425 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
426 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
427 me->me_dev = fsd.fd_req.dev;
429 /* Add to the linked list. */
430 *mtail = me;
431 mtail = &me->me_next;
432 }
433 if (val < 0)
434 goto free_then_fail;
435 }
436 #endif /* MOUNTED_GETMNT. */
438 #if defined MOUNTED_FS_STAT_DEV /* BeOS */
439 {
440 /* The next_dev() and fs_stat_dev() system calls give the list of
441 all filesystems, including the information returned by statvfs()
442 (fs type, total blocks, free blocks etc.), but without the mount
443 point. But on BeOS all filesystems except / are mounted in the
444 rootfs, directly under /.
445 The directory name of the mount point is often, but not always,
446 identical to the volume name of the device.
447 We therefore get the list of subdirectories of /, and the list
448 of all filesystems, and match the two lists. */
450 DIR *dirp;
451 struct rootdir_entry
452 {
453 char *name;
454 dev_t dev;
455 ino_t ino;
456 struct rootdir_entry *next;
457 };
458 struct rootdir_entry *rootdir_list;
459 struct rootdir_entry **rootdir_tail;
460 int32 pos;
461 dev_t dev;
462 fs_info fi;
464 /* All volumes are mounted in the rootfs, directly under /. */
465 rootdir_list = NULL;
466 rootdir_tail = &rootdir_list;
467 dirp = opendir ("/");
468 if (dirp)
469 {
470 struct dirent *d;
472 while ((d = readdir (dirp)) != NULL)
473 {
474 char *name;
475 struct stat statbuf;
477 if (strcmp (d->d_name, "..") == 0)
478 continue;
480 if (strcmp (d->d_name, ".") == 0)
481 name = xstrdup ("/");
482 else
483 {
484 name = xmalloc (1 + strlen (d->d_name) + 1);
485 name[0] = '/';
486 strcpy (name + 1, d->d_name);
487 }
489 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
490 {
491 struct rootdir_entry *re = xmalloc (sizeof *re);
492 re->name = name;
493 re->dev = statbuf.st_dev;
494 re->ino = statbuf.st_ino;
496 /* Add to the linked list. */
497 *rootdir_tail = re;
498 rootdir_tail = &re->next;
499 }
500 else
501 free (name);
502 }
503 closedir (dirp);
504 }
505 *rootdir_tail = NULL;
507 for (pos = 0; (dev = next_dev (&pos)) >= 0; )
508 if (fs_stat_dev (dev, &fi) >= 0)
509 {
510 /* Note: fi.dev == dev. */
511 struct rootdir_entry *re;
513 for (re = rootdir_list; re; re = re->next)
514 if (re->dev == fi.dev && re->ino == fi.root)
515 break;
517 me = xmalloc (sizeof *me);
518 me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
519 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
520 me->me_type = xstrdup (fi.fsh_name);
521 me->me_type_malloced = 1;
522 me->me_dev = fi.dev;
523 me->me_dummy = 0;
524 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
526 /* Add to the linked list. */
527 *mtail = me;
528 mtail = &me->me_next;
529 }
530 *mtail = NULL;
532 while (rootdir_list != NULL)
533 {
534 struct rootdir_entry *re = rootdir_list;
535 rootdir_list = re->next;
536 free (re->name);
537 free (re);
538 }
539 }
540 #endif /* MOUNTED_FS_STAT_DEV */
542 #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
543 {
544 int numsys, counter;
545 size_t bufsize;
546 struct statfs *stats;
548 numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
549 if (numsys < 0)
550 return (NULL);
551 if (SIZE_MAX / sizeof *stats <= numsys)
552 xalloc_die ();
554 bufsize = (1 + numsys) * sizeof *stats;
555 stats = xmalloc (bufsize);
556 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
558 if (numsys < 0)
559 {
560 free (stats);
561 return (NULL);
562 }
564 for (counter = 0; counter < numsys; counter++)
565 {
566 me = xmalloc (sizeof *me);
567 me->me_devname = xstrdup (stats[counter].f_mntfromname);
568 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
569 me->me_type = xstrdup (FS_TYPE (stats[counter]));
570 me->me_type_malloced = 1;
571 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
572 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
573 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
575 /* Add to the linked list. */
576 *mtail = me;
577 mtail = &me->me_next;
578 }
580 free (stats);
581 }
582 #endif /* MOUNTED_GETFSSTAT */
584 #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
585 {
586 struct mnttab mnt;
587 char *table = "/etc/mnttab";
588 FILE *fp;
590 fp = fopen (table, "r");
591 if (fp == NULL)
592 return NULL;
594 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
595 {
596 me = xmalloc (sizeof *me);
597 # ifdef GETFSTYP /* SVR3. */
598 me->me_devname = xstrdup (mnt.mt_dev);
599 # else
600 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
601 strcpy (me->me_devname, "/dev/");
602 strcpy (me->me_devname + 5, mnt.mt_dev);
603 # endif
604 me->me_mountdir = xstrdup (mnt.mt_filsys);
605 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
606 me->me_type = "";
607 me->me_type_malloced = 0;
608 # ifdef GETFSTYP /* SVR3. */
609 if (need_fs_type)
610 {
611 struct statfs fsd;
612 char typebuf[FSTYPSZ];
614 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
615 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
616 {
617 me->me_type = xstrdup (typebuf);
618 me->me_type_malloced = 1;
619 }
620 }
621 # endif
622 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
623 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
625 /* Add to the linked list. */
626 *mtail = me;
627 mtail = &me->me_next;
628 }
630 if (ferror (fp))
631 {
632 /* The last fread() call must have failed. */
633 int saved_errno = errno;
634 fclose (fp);
635 errno = saved_errno;
636 goto free_then_fail;
637 }
639 if (fclose (fp) == EOF)
640 goto free_then_fail;
641 }
642 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
644 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
645 {
646 struct mntent **mnttbl = getmnttbl (), **ent;
647 for (ent=mnttbl;*ent;ent++)
648 {
649 me = xmalloc (sizeof *me);
650 me->me_devname = xstrdup ( (*ent)->mt_resource);
651 me->me_mountdir = xstrdup ( (*ent)->mt_directory);
652 me->me_type = xstrdup ((*ent)->mt_fstype);
653 me->me_type_malloced = 1;
654 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
655 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
656 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
658 /* Add to the linked list. */
659 *mtail = me;
660 mtail = &me->me_next;
661 }
662 endmnttbl ();
663 }
664 #endif
666 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
667 {
668 struct mnttab mnt;
669 char *table = MNTTAB;
670 FILE *fp;
671 int ret;
672 int lockfd = -1;
674 # if defined F_RDLCK && defined F_SETLKW
675 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
676 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
677 for this file name, we should use their macro name instead.
678 (Why not just lock MNTTAB directly? We don't know.) */
679 # ifndef MNTTAB_LOCK
680 # define MNTTAB_LOCK "/etc/.mnttab.lock"
681 # endif
682 lockfd = open (MNTTAB_LOCK, O_RDONLY);
683 if (0 <= lockfd)
684 {
685 struct flock flock;
686 flock.l_type = F_RDLCK;
687 flock.l_whence = SEEK_SET;
688 flock.l_start = 0;
689 flock.l_len = 0;
690 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
691 if (errno != EINTR)
692 {
693 int saved_errno = errno;
694 close (lockfd);
695 errno = saved_errno;
696 return NULL;
697 }
698 }
699 else if (errno != ENOENT)
700 return NULL;
701 # endif
703 errno = 0;
704 fp = fopen (table, "r");
705 if (fp == NULL)
706 ret = errno;
707 else
708 {
709 while ((ret = getmntent (fp, &mnt)) == 0)
710 {
711 me = xmalloc (sizeof *me);
712 me->me_devname = xstrdup (mnt.mnt_special);
713 me->me_mountdir = xstrdup (mnt.mnt_mountp);
714 me->me_type = xstrdup (mnt.mnt_fstype);
715 me->me_type_malloced = 1;
716 me->me_dummy = MNT_IGNORE (&mnt) != 0;
717 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
718 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
720 /* Add to the linked list. */
721 *mtail = me;
722 mtail = &me->me_next;
723 }
725 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
726 }
728 if (0 <= lockfd && close (lockfd) != 0)
729 ret = errno;
731 if (0 <= ret)
732 {
733 errno = ret;
734 goto free_then_fail;
735 }
736 }
737 #endif /* MOUNTED_GETMNTENT2. */
739 #ifdef MOUNTED_VMOUNT /* AIX. */
740 {
741 int bufsize;
742 char *entries, *thisent;
743 struct vmount *vmp;
744 int n_entries;
745 int i;
747 /* Ask how many bytes to allocate for the mounted filesystem info. */
748 if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
749 return NULL;
750 entries = xmalloc (bufsize);
752 /* Get the list of mounted filesystems. */
753 n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
754 if (n_entries < 0)
755 {
756 int saved_errno = errno;
757 free (entries);
758 errno = saved_errno;
759 return NULL;
760 }
762 for (i = 0, thisent = entries;
763 i < n_entries;
764 i++, thisent += vmp->vmt_length)
765 {
766 char *options, *ignore;
768 vmp = (struct vmount *) thisent;
769 me = xmalloc (sizeof *me);
770 if (vmp->vmt_flags & MNT_REMOTE)
771 {
772 char *host, *path;
774 me->me_remote = 1;
775 /* Prepend the remote pathname. */
776 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
777 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
778 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
779 strcpy (me->me_devname, host);
780 strcat (me->me_devname, ":");
781 strcat (me->me_devname, path);
782 }
783 else
784 {
785 me->me_remote = 0;
786 me->me_devname = xstrdup (thisent +
787 vmp->vmt_data[VMT_OBJECT].vmt_off);
788 }
789 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
790 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
791 me->me_type_malloced = 1;
792 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
793 ignore = strstr (options, "ignore");
794 me->me_dummy = (ignore
795 && (ignore == options || ignore[-1] == ',')
796 && (ignore[sizeof "ignore" - 1] == ','
797 || ignore[sizeof "ignore" - 1] == '\0'));
798 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
800 /* Add to the linked list. */
801 *mtail = me;
802 mtail = &me->me_next;
803 }
804 free (entries);
805 }
806 #endif /* MOUNTED_VMOUNT. */
808 *mtail = NULL;
809 return mount_list;
812 free_then_fail:
813 {
814 int saved_errno = errno;
815 *mtail = NULL;
817 while (mount_list)
818 {
819 me = mount_list->me_next;
820 free (mount_list->me_devname);
821 free (mount_list->me_mountdir);
822 if (mount_list->me_type_malloced)
823 free (mount_list->me_type);
824 free (mount_list);
825 mount_list = me;
826 }
828 errno = saved_errno;
829 return NULL;
830 }
831 }