*** empty log message ***
[gnulib.git] / lib / mountlist.c
blobed91f9ec7e812e5a16fe1e437f928c6f6e1eef47
1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992, 1997-2001 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>
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 #else
29 void free ();
30 #endif
31 #if defined STDC_HEADERS || defined HAVE_STRING_H
32 # include <string.h>
33 #else
34 # include <strings.h>
35 #endif
36 #include "xalloc.h"
38 #ifndef strstr
39 char *strstr ();
40 #endif
42 #include <errno.h>
43 #ifndef errno
44 extern int errno;
45 #endif
47 #ifdef HAVE_FCNTL_H
48 # include <fcntl.h>
49 #endif
51 #ifdef HAVE_UNISTD_H
52 # include <unistd.h>
53 #endif
55 #if HAVE_SYS_PARAM_H
56 # include <sys/param.h>
57 #endif
59 #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
60 # if HAVE_SYS_UCRED_H
61 # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
62 # endif
63 # if HAVE_SYS_MOUNT_H
64 # include <sys/mount.h>
65 # endif
66 # if HAVE_SYS_FS_TYPES_H
67 # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
68 # endif
69 # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
70 # define FS_TYPE(Ent) ((Ent).f_fstypename)
71 # else
72 # define FS_TYPE(Ent) mnt_names[(Ent).f_type]
73 # endif
74 #endif /* MOUNTED_GETFSSTAT */
76 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
77 # include <mntent.h>
78 # if !defined MOUNTED
79 # if defined _PATH_MOUNTED /* GNU libc */
80 # define MOUNTED _PATH_MOUNTED
81 # endif
82 # if defined MNT_MNTTAB /* HP-UX. */
83 # define MOUNTED MNT_MNTTAB
84 # endif
85 # if defined MNTTABNAME /* Dynix. */
86 # define MOUNTED MNTTABNAME
87 # endif
88 # endif
89 #endif
91 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
92 # include <sys/mount.h>
93 #endif
95 #ifdef MOUNTED_GETMNT /* Ultrix. */
96 # include <sys/mount.h>
97 # include <sys/fs_types.h>
98 #endif
100 #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
101 # include <fs_info.h>
102 # include <dirent.h>
103 #endif
105 #ifdef MOUNTED_FREAD /* SVR2. */
106 # include <mnttab.h>
107 #endif
109 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
110 # include <mnttab.h>
111 # include <sys/fstyp.h>
112 # include <sys/statfs.h>
113 #endif
115 #ifdef MOUNTED_LISTMNTENT
116 # include <mntent.h>
117 #endif
119 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
120 # include <sys/mnttab.h>
121 #endif
123 #ifdef MOUNTED_VMOUNT /* AIX. */
124 # include <fshelp.h>
125 # include <sys/vfs.h>
126 #endif
128 #ifdef DOLPHIN
129 /* So special that it's not worth putting this in autoconf. */
130 # undef MOUNTED_FREAD_FSTYP
131 # define MOUNTED_GETMNTTBL
132 #endif
134 #if HAVE_SYS_MNTENT_H
135 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
136 # include <sys/mntent.h>
137 #endif
139 #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
140 # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
141 #else
142 # define MNT_IGNORE(M) 0
143 #endif
145 #include "mountlist.h"
146 #include "unlocked-io.h"
148 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
149 /* Return the value of the hexadecimal number represented by CP.
150 No prefix (like '0x') or suffix (like 'h') is expected to be
151 part of CP. */
152 /* FIXME: this can overflow */
154 static int
155 xatoi (char *cp)
157 int val;
159 val = 0;
160 while (*cp)
162 if (*cp >= 'a' && *cp <= 'f')
163 val = val * 16 + *cp - 'a' + 10;
164 else if (*cp >= 'A' && *cp <= 'F')
165 val = val * 16 + *cp - 'A' + 10;
166 else if (*cp >= '0' && *cp <= '9')
167 val = val * 16 + *cp - '0';
168 else
169 break;
170 cp++;
172 return val;
174 #endif /* MOUNTED_GETMNTENT1. */
176 #if MOUNTED_GETMNTINFO
178 # if ! HAVE_F_FSTYPENAME_IN_STATFS
179 static char *
180 fstype_to_string (short t)
182 switch (t)
184 # ifdef MOUNT_PC
185 case MOUNT_PC:
186 return "pc";
187 # endif
188 # ifdef MOUNT_MFS
189 case MOUNT_MFS:
190 return "mfs";
191 # endif
192 # ifdef MOUNT_LO
193 case MOUNT_LO:
194 return "lo";
195 # endif
196 # ifdef MOUNT_TFS
197 case MOUNT_TFS:
198 return "tfs";
199 # endif
200 # ifdef MOUNT_TMP
201 case MOUNT_TMP:
202 return "tmp";
203 # endif
204 # ifdef MOUNT_UFS
205 case MOUNT_UFS:
206 return "ufs" ;
207 # endif
208 # ifdef MOUNT_NFS
209 case MOUNT_NFS:
210 return "nfs" ;
211 # endif
212 # ifdef MOUNT_MSDOS
213 case MOUNT_MSDOS:
214 return "msdos" ;
215 # endif
216 # ifdef MOUNT_LFS
217 case MOUNT_LFS:
218 return "lfs" ;
219 # endif
220 # ifdef MOUNT_LOFS
221 case MOUNT_LOFS:
222 return "lofs" ;
223 # endif
224 # ifdef MOUNT_FDESC
225 case MOUNT_FDESC:
226 return "fdesc" ;
227 # endif
228 # ifdef MOUNT_PORTAL
229 case MOUNT_PORTAL:
230 return "portal" ;
231 # endif
232 # ifdef MOUNT_NULL
233 case MOUNT_NULL:
234 return "null" ;
235 # endif
236 # ifdef MOUNT_UMAP
237 case MOUNT_UMAP:
238 return "umap" ;
239 # endif
240 # ifdef MOUNT_KERNFS
241 case MOUNT_KERNFS:
242 return "kernfs" ;
243 # endif
244 # ifdef MOUNT_PROCFS
245 case MOUNT_PROCFS:
246 return "procfs" ;
247 # endif
248 # ifdef MOUNT_AFS
249 case MOUNT_AFS:
250 return "afs" ;
251 # endif
252 # ifdef MOUNT_CD9660
253 case MOUNT_CD9660:
254 return "cd9660" ;
255 # endif
256 # ifdef MOUNT_UNION
257 case MOUNT_UNION:
258 return "union" ;
259 # endif
260 # ifdef MOUNT_DEVFS
261 case MOUNT_DEVFS:
262 return "devfs" ;
263 # endif
264 # ifdef MOUNT_EXT2FS
265 case MOUNT_EXT2FS:
266 return "ext2fs" ;
267 # endif
268 default:
269 return "?";
272 # endif /* ! HAVE_F_FSTYPENAME_IN_STATFS */
274 /* __NetBSD__ || BSD_NET2 || __OpenBSD__ */
275 static char *
276 fsp_to_string (const struct statfs *fsp)
278 # if defined HAVE_F_FSTYPENAME_IN_STATFS
279 return (char *) (fsp->f_fstypename);
280 # else
281 return fstype_to_string (fsp->f_type);
282 # endif
285 #endif /* MOUNTED_GETMNTINFO */
287 #ifdef MOUNTED_VMOUNT /* AIX. */
288 static char *
289 fstype_to_string (int t)
291 struct vfs_ent *e;
293 e = getvfsbytype (t);
294 if (!e || !e->vfsent_name)
295 return "none";
296 else
297 return e->vfsent_name;
299 #endif /* MOUNTED_VMOUNT */
301 /* Return a list of the currently mounted filesystems, or NULL on error.
302 Add each entry to the tail of the list so that they stay in order.
303 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
304 the returned list are valid. Otherwise, they might not be. */
306 struct mount_entry *
307 read_filesystem_list (int need_fs_type)
309 struct mount_entry *mount_list;
310 struct mount_entry *me;
311 struct mount_entry **mtail = &mount_list;
313 #ifdef MOUNTED_LISTMNTENT
315 struct tabmntent *mntlist, *p;
316 struct mntent *mnt;
317 struct mount_entry *me;
319 /* the third and fourth arguments could be used to filter mounts,
320 but Crays doesn't seem to have any mounts that we want to
321 remove. Specifically, automount create normal NFS mounts.
324 if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
325 return NULL;
326 for (p = mntlist; p; p = p->next) {
327 mnt = p->ment;
328 me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
329 me->me_devname = xstrdup(mnt->mnt_fsname);
330 me->me_mountdir = xstrdup(mnt->mnt_dir);
331 me->me_type = xstrdup(mnt->mnt_type);
332 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
333 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
334 me->me_dev = -1;
335 *mtail = me;
336 mtail = &me->me_next;
338 freemntlist(mntlist);
340 #endif
342 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
344 struct mntent *mnt;
345 char *table = MOUNTED;
346 FILE *fp;
347 char *devopt;
349 fp = setmntent (table, "r");
350 if (fp == NULL)
351 return NULL;
353 while ((mnt = getmntent (fp)))
355 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
356 me->me_devname = xstrdup (mnt->mnt_fsname);
357 me->me_mountdir = xstrdup (mnt->mnt_dir);
358 me->me_type = xstrdup (mnt->mnt_type);
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)
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);
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;
377 if (endmntent (fp) == 0)
378 goto free_then_fail;
380 #endif /* MOUNTED_GETMNTENT1. */
382 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
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++)
392 char *fs_type = fsp_to_string (fsp);
394 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
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_dummy = ME_DUMMY (me->me_devname, me->me_type);
399 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
400 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
402 /* Add to the linked list. */
403 *mtail = me;
404 mtail = &me->me_next;
407 #endif /* MOUNTED_GETMNTINFO */
409 #ifdef MOUNTED_GETMNT /* Ultrix. */
411 int offset = 0;
412 int val;
413 struct fs_data fsd;
415 while (errno = 0,
416 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
417 (char *) 0)))
419 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
420 me->me_devname = xstrdup (fsd.fd_req.devname);
421 me->me_mountdir = xstrdup (fsd.fd_req.path);
422 me->me_type = gt_names[fsd.fd_req.fstype];
423 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
424 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
425 me->me_dev = fsd.fd_req.dev;
427 /* Add to the linked list. */
428 *mtail = me;
429 mtail = &me->me_next;
431 if (val < 0)
432 goto free_then_fail;
434 #endif /* MOUNTED_GETMNT. */
436 #if defined MOUNTED_FS_STAT_DEV /* BeOS */
438 /* The next_dev() and fs_stat_dev() system calls give the list of
439 all filesystems, including the information returned by statvfs()
440 (fs type, total blocks, free blocks etc.), but without the mount
441 point. But on BeOS all filesystems except / are mounted in the
442 rootfs, directly under /.
443 The directory name of the mount point is often, but not always,
444 identical to the volume name of the device.
445 We therefore get the list of subdirectories of /, and the list
446 of all filesystems, and match the two lists. */
448 DIR *dirp;
449 struct rootdir_entry
451 char *name;
452 dev_t dev;
453 ino_t ino;
454 struct rootdir_entry *next;
456 struct rootdir_entry *rootdir_list;
457 struct rootdir_entry **rootdir_tail;
458 int32 pos;
459 dev_t dev;
460 fs_info fi;
462 /* All volumes are mounted in the rootfs, directly under /. */
463 rootdir_list = NULL;
464 rootdir_tail = &rootdir_list;
465 dirp = opendir ("/");
466 if (dirp)
468 struct dirent *d;
470 while ((d = readdir (dirp)) != NULL)
472 char *name;
473 struct stat statbuf;
475 if (strcmp (d->d_name, "..") == 0)
476 continue;
478 if (strcmp (d->d_name, ".") == 0)
479 name = xstrdup ("/");
480 else
482 name = xmalloc (1 + strlen (d->d_name) + 1);
483 name[0] = '/';
484 strcpy (name + 1, d->d_name);
487 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
489 struct rootdir_entry *re;
491 re = (struct rootdir_entry *) xmalloc (sizeof (struct rootdir_entry));
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;
500 else
501 free (name);
503 closedir (dirp);
505 *rootdir_tail = NULL;
507 for (pos = 0; (dev = next_dev (&pos)) >= 0; )
508 if (fs_stat_dev (dev, &fi) >= 0)
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 = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
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_dev = fi.dev;
522 me->me_dummy = 0;
523 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
525 /* Add to the linked list. */
526 *mtail = me;
527 mtail = &me->me_next;
529 *mtail = NULL;
531 while (rootdir_list != NULL)
533 struct rootdir_entry *re = rootdir_list;
534 rootdir_list = re->next;
535 free (re->name);
536 free (re);
539 #endif /* MOUNTED_FS_STAT_DEV */
541 #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
543 int numsys, counter, bufsize;
544 struct statfs *stats;
546 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
547 if (numsys < 0)
548 return (NULL);
550 bufsize = (1 + numsys) * sizeof (struct statfs);
551 stats = (struct statfs *)xmalloc (bufsize);
552 numsys = getfsstat (stats, bufsize, MNT_WAIT);
554 if (numsys < 0)
556 free (stats);
557 return (NULL);
560 for (counter = 0; counter < numsys; counter++)
562 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
563 me->me_devname = xstrdup (stats[counter].f_mntfromname);
564 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
565 me->me_type = xstrdup (FS_TYPE (stats[counter]));
566 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
567 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
568 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
570 /* Add to the linked list. */
571 *mtail = me;
572 mtail = &me->me_next;
575 free (stats);
577 #endif /* MOUNTED_GETFSSTAT */
579 #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
581 struct mnttab mnt;
582 char *table = "/etc/mnttab";
583 FILE *fp;
585 fp = fopen (table, "r");
586 if (fp == NULL)
587 return NULL;
589 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
591 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
592 # ifdef GETFSTYP /* SVR3. */
593 me->me_devname = xstrdup (mnt.mt_dev);
594 # else
595 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
596 strcpy (me->me_devname, "/dev/");
597 strcpy (me->me_devname + 5, mnt.mt_dev);
598 # endif
599 me->me_mountdir = xstrdup (mnt.mt_filsys);
600 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
601 me->me_type = "";
602 # ifdef GETFSTYP /* SVR3. */
603 if (need_fs_type)
605 struct statfs fsd;
606 char typebuf[FSTYPSZ];
608 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
609 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
610 me->me_type = xstrdup (typebuf);
612 # endif
613 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
614 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
616 /* Add to the linked list. */
617 *mtail = me;
618 mtail = &me->me_next;
621 if (ferror (fp))
623 int saved_errno = errno;
624 fclose (fp);
625 errno = saved_errno;
626 goto free_then_fail;
629 if (fclose (fp) == EOF)
630 goto free_then_fail;
632 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
634 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
636 struct mntent **mnttbl=getmnttbl(),**ent;
637 for (ent=mnttbl;*ent;ent++)
639 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
640 me->me_devname = xstrdup ( (*ent)->mt_resource);
641 me->me_mountdir = xstrdup( (*ent)->mt_directory);
642 me->me_type = xstrdup ((*ent)->mt_fstype);
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. */
647 /* Add to the linked list. */
648 *mtail = me;
649 mtail = &me->me_next;
651 endmnttbl();
653 #endif
655 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
657 struct mnttab mnt;
658 char *table = MNTTAB;
659 FILE *fp;
660 int ret;
661 int lockfd = -1;
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)
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)
682 int saved_errno = errno;
683 close (lockfd);
684 errno = saved_errno;
685 return NULL;
688 else if (errno != ENOENT)
689 return NULL;
690 # endif
692 errno = 0;
693 fp = fopen (table, "r");
694 if (fp == NULL)
695 ret = errno;
696 else
698 while ((ret = getmntent (fp, &mnt)) == 0)
700 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
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_dummy = MNT_IGNORE (&mnt) != 0;
705 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
706 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
708 /* Add to the linked list. */
709 *mtail = me;
710 mtail = &me->me_next;
713 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
716 if (0 <= lockfd && close (lockfd) != 0)
717 ret = errno;
719 if (0 <= ret)
721 errno = ret;
722 goto free_then_fail;
725 #endif /* MOUNTED_GETMNTENT2. */
727 #ifdef MOUNTED_VMOUNT /* AIX. */
729 int bufsize;
730 char *entries, *thisent;
731 struct vmount *vmp;
733 /* Ask how many bytes to allocate for the mounted filesystem info. */
734 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
735 entries = xmalloc (bufsize);
737 /* Get the list of mounted filesystems. */
738 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
740 for (thisent = entries; thisent < entries + bufsize;
741 thisent += vmp->vmt_length)
743 char *options, *ignore;
745 vmp = (struct vmount *) thisent;
746 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
747 if (vmp->vmt_flags & MNT_REMOTE)
749 char *host, *path;
751 me->me_remote = 1;
752 /* Prepend the remote pathname. */
753 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
754 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
755 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
756 strcpy (me->me_devname, host);
757 strcat (me->me_devname, ":");
758 strcat (me->me_devname, path);
760 else
762 me->me_remote = 0;
763 me->me_devname = xstrdup (thisent +
764 vmp->vmt_data[VMT_OBJECT].vmt_off);
766 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
767 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
768 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
769 ignore = strstr (options, "ignore");
770 me->me_dummy = (ignore
771 && (ignore == options || ignore[-1] == ',')
772 && (ignore[sizeof "ignore" - 1] == ','
773 || ignore[sizeof "ignore" - 1] == '\0'));
774 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
776 /* Add to the linked list. */
777 *mtail = me;
778 mtail = &me->me_next;
780 free (entries);
782 #endif /* MOUNTED_VMOUNT. */
784 *mtail = NULL;
785 return mount_list;
788 free_then_fail:
790 int saved_errno = errno;
791 *mtail = NULL;
793 while (mount_list)
795 me = mount_list->me_next;
796 free (mount_list->me_devname);
797 free (mount_list->me_mountdir);
798 /* FIXME: me_type is not always malloced. */
799 free (mount_list);
800 mount_list = me;
803 errno = saved_errno;
804 return NULL;