1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992, 1997, 1998 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)
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. */
23 #include <sys/types.h>
24 #include "mountlist.h"
31 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
59 # include <sys/param.h>
62 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
63 # include <sys/mount.h>
64 # include <sys/fs_types.h>
65 #endif /* MOUNTED_GETFSSTAT */
67 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
69 # if !defined(MOUNTED)
70 # if defined(MNT_MNTTAB) /* HP-UX. */
71 # define MOUNTED MNT_MNTTAB
73 # if defined(MNTTABNAME) /* Dynix. */
74 # define MOUNTED MNTTABNAME
79 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
80 # include <sys/mount.h>
83 #ifdef MOUNTED_GETMNT /* Ultrix. */
84 # include <sys/mount.h>
85 # include <sys/fs_types.h>
88 #ifdef MOUNTED_FREAD /* SVR2. */
92 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
94 # include <sys/fstyp.h>
95 # include <sys/statfs.h>
98 #ifdef MOUNTED_LISTMNTENT
102 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
103 # include <sys/mnttab.h>
106 #ifdef MOUNTED_VMOUNT /* AIX. */
108 # include <sys/vfs.h>
112 /* So special that it's not worth putting this in autoconf. */
113 # undef MOUNTED_FREAD_FSTYP
114 # define MOUNTED_GETMNTTBL
117 #if HAVE_SYS_MNTENT_H
118 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
119 # include <sys/mntent.h>
122 #if defined (MNTOPT_IGNORE) && defined (HAVE_HASMNTOPT)
123 # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
125 # define MNT_IGNORE(M) 0
128 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
129 /* Return the value of the hexadecimal number represented by CP.
130 No prefix (like '0x') or suffix (like 'h') is expected to be
132 /* FIXME: this can overflow */
142 if (*cp >= 'a' && *cp <= 'f')
143 val = val * 16 + *cp - 'a' + 10;
144 else if (*cp >= 'A' && *cp <= 'F')
145 val = val * 16 + *cp - 'A' + 10;
146 else if (*cp >= '0' && *cp <= '9')
147 val = val * 16 + *cp - '0';
154 #endif /* MOUNTED_GETMNTENT1. */
156 #if MOUNTED_GETMNTINFO
158 # if ! HAVE_F_FSTYPENAME_IN_STATFS
160 fstype_to_string (short t)
252 # endif /* ! HAVE_F_FSTYPENAME_IN_STATFS */
254 /* __NetBSD__ || BSD_NET2 || __OpenBSD__ */
256 fsp_to_string (const struct statfs *fsp)
258 # if defined HAVE_F_FSTYPENAME_IN_STATFS
259 return fsp->f_fstypename;
261 return fstype_to_string (fsp->f_type);
265 #endif /* MOUNTED_GETMNTINFO */
267 #ifdef MOUNTED_VMOUNT /* AIX. */
269 fstype_to_string (int t)
273 e = getvfsbytype (t);
274 if (!e || !e->vfsent_name)
277 return e->vfsent_name;
279 #endif /* MOUNTED_VMOUNT */
281 /* Return a list of the currently mounted filesystems, or NULL on error.
282 Add each entry to the tail of the list so that they stay in order.
283 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
284 the returned list are valid. Otherwise, they might not be.
285 If ALL_FS is positive, return all entries; if zero, omit entries
286 for filesystems that are automounter (dummy) entries; if negative,
287 also omit non-local filesystems. */
290 read_filesystem_list (int need_fs_type, int all_fs)
292 struct mount_entry *mount_list;
293 struct mount_entry *me;
294 struct mount_entry **mtail = &mount_list;
296 #ifdef MOUNTED_LISTMNTENT
298 struct tabmntent *mntlist, *p;
300 struct mount_entry *me;
302 /* the third and fourth arguments could be used to filter mounts,
303 but Crays doesn't seem to have any mounts that we want to
304 remove. Specifically, automount create normal NFS mounts.
307 if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
309 for (p = mntlist; p; p = p->next) {
311 if (all_fs < 0 && REMOTE_FS_TYPE (mnt->mnt_type))
313 me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
314 me->me_devname = xstrdup(mnt->mnt_fsname);
315 me->me_mountdir = xstrdup(mnt->mnt_dir);
316 me->me_type = xstrdup(mnt->mnt_type);
319 mtail = &me->me_next;
321 freemntlist(mntlist);
325 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
328 char *table = MOUNTED;
332 fp = setmntent (table, "r");
336 while ((mnt = getmntent (fp)))
338 if (all_fs <= 0 && (!strcmp (mnt->mnt_type, "ignore")
339 || !strcmp (mnt->mnt_type, "auto")))
341 if (all_fs < 0 && REMOTE_FS_TYPE (mnt->mnt_type))
344 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
345 me->me_devname = xstrdup (mnt->mnt_fsname);
346 me->me_mountdir = xstrdup (mnt->mnt_dir);
347 me->me_type = xstrdup (mnt->mnt_type);
348 devopt = strstr (mnt->mnt_opts, "dev=");
351 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
352 me->me_dev = xatoi (devopt + 6);
354 me->me_dev = xatoi (devopt + 4);
357 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
359 /* Add to the linked list. */
361 mtail = &me->me_next;
364 if (endmntent (fp) == 0)
367 #endif /* MOUNTED_GETMNTENT1. */
369 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
374 entries = getmntinfo (&fsp, MNT_NOWAIT);
377 for (; entries-- > 0; fsp++)
379 char *fs_type = fsp_to_string (fsp);
380 if (all_fs < 0 && REMOTE_FS_TYPE (fs_type))
383 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
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_dev = (dev_t) -1; /* Magic; means not known yet. */
389 /* Add to the linked list. */
391 mtail = &me->me_next;
394 #endif /* MOUNTED_GETMNTINFO */
396 #ifdef MOUNTED_GETMNT /* Ultrix. */
403 0 <= (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
406 if (all_fs < 0 && REMOTE_FS_TYPE (gt_names[fsd.fd_req.fstype]))
409 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
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_dev = fsd.fd_req.dev;
415 /* Add to the linked list. */
417 mtail = &me->me_next;
422 #endif /* MOUNTED_GETMNT. */
424 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
426 int numsys, counter, bufsize;
427 struct statfs *stats;
429 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
433 bufsize = (1 + numsys) * sizeof (struct statfs);
434 stats = (struct statfs *)xmalloc (bufsize);
435 numsys = getfsstat (stats, bufsize, MNT_WAIT);
443 for (counter = 0; counter < numsys; counter++)
445 if (all_fs < 0 && REMOTE_FS_TYPE (mnt_names[stats[counter].f_type]))
448 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
449 me->me_devname = xstrdup (stats[counter].f_mntfromname);
450 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
451 me->me_type = mnt_names[stats[counter].f_type];
452 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
454 /* Add to the linked list. */
456 mtail = &me->me_next;
461 #endif /* MOUNTED_GETFSSTAT */
463 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
466 char *table = "/etc/mnttab";
469 fp = fopen (table, "r");
473 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
477 # ifdef GETFSTYP /* SVR3. */
478 if (need_fs_type || all_fs < 0)
481 char typebuf[FSTYPSZ];
483 if (statfs (mnt.mt_filsys, &fsd, sizeof fsd, 0) != -1
484 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
486 if (all_fs < 0 && REMOTE_FS_TYPE (typebuf))
488 fs_type = xstrdup (typebuf);
493 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
494 # ifdef GETFSTYP /* SVR3. */
495 me->me_devname = xstrdup (mnt.mt_dev);
497 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
498 strcpy (me->me_devname, "/dev/");
499 strcpy (me->me_devname + 5, mnt.mt_dev);
501 me->me_mountdir = xstrdup (mnt.mt_filsys);
502 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
503 me->me_type = fs_type;
505 /* Add to the linked list. */
507 mtail = &me->me_next;
512 int saved_errno = errno;
518 if (fclose (fp) == EOF)
521 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
523 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
525 struct mntent **mnttbl=getmnttbl(),**ent;
526 for (ent=mnttbl;*ent;ent++)
528 if (all_fs < 0 && REMOTE_FS_TYPE ((*ent)->mt_fstype))
531 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
532 me->me_devname = xstrdup ( (*ent)->mt_resource);
533 me->me_mountdir = xstrdup( (*ent)->mt_directory);
534 me->me_type = xstrdup ((*ent)->mt_fstype);
535 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
537 /* Add to the linked list. */
539 mtail = &me->me_next;
545 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
548 char *table = MNTTAB;
553 # if defined F_RDLCK && defined F_SETLKW
554 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
555 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
556 for this file name, we should use their macro name instead.
557 (Why not just lock MNTTAB directly? We don't know.) */
559 # define MNTTAB_LOCK "/etc/.mnttab.lock"
561 lockfd = open (MNTTAB_LOCK, O_RDONLY);
565 flock.l_type = F_RDLCK;
566 flock.l_whence = SEEK_SET;
569 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
572 int saved_errno = errno;
578 else if (errno != ENOENT)
583 fp = fopen (table, "r");
588 while ((ret = getmntent (fp, &mnt)) == 0)
590 /* Don't show automounted filesystems twice on e.g., Solaris. */
591 if (all_fs <= 0 && MNT_IGNORE (&mnt))
594 if (all_fs < 0 && REMOTE_FS_TYPE (mnt.mnt_fstype))
597 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
598 me->me_devname = xstrdup (mnt.mnt_special);
599 me->me_mountdir = xstrdup (mnt.mnt_mountp);
600 me->me_type = xstrdup (mnt.mnt_fstype);
601 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
603 /* Add to the linked list. */
605 mtail = &me->me_next;
608 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
611 if (0 <= lockfd && close (lockfd) != 0)
620 #endif /* MOUNTED_GETMNTENT2. */
622 #ifdef MOUNTED_VMOUNT /* AIX. */
625 char *entries, *thisent;
628 /* Ask how many bytes to allocate for the mounted filesystem info. */
629 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
630 entries = xmalloc (bufsize);
632 /* Get the list of mounted filesystems. */
633 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
635 for (thisent = entries; thisent < entries + bufsize;
636 thisent += vmp->vmt_length)
638 vmp = (struct vmount *) thisent;
639 if (all_fs < 0 && vmp->vmt_flags & MNT_REMOTE)
641 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
642 if (vmp->vmt_flags & MNT_REMOTE)
646 /* Prepend the remote pathname. */
647 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
648 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
649 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
650 strcpy (me->me_devname, host);
651 strcat (me->me_devname, ":");
652 strcat (me->me_devname, path);
656 me->me_devname = xstrdup (thisent +
657 vmp->vmt_data[VMT_OBJECT].vmt_off);
659 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
660 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
661 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
663 /* Add to the linked list. */
665 mtail = &me->me_next;
669 #endif /* MOUNTED_VMOUNT. */
677 int saved_errno = errno;
682 me = mount_list->me_next;
683 free (mount_list->me_devname);
684 free (mount_list->me_mountdir);
685 /* FIXME: me_type is not always malloced. */