summaryrefslogtreecommitdiffstats
path: root/lib/mountlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mountlist.c')
-rw-r--r--lib/mountlist.c788
1 files changed, 788 insertions, 0 deletions
diff --git a/lib/mountlist.c b/lib/mountlist.c
new file mode 100644
index 0000000..b667c44
--- /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
27void 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
36char *strstr ();
37#endif
38char *xmalloc ();
39char *xrealloc ();
40char *xstrdup ();
41
42#include <errno.h>
43#ifndef errno
44extern 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
136static int
137xatoi (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
161static char *
162fstype_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__ */
257static char *
258fsp_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. */
270static char *
271fstype_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
288struct mount_entry *
289read_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}