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
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 xstrdup (fsp->f_fstypename);
261 return fstype_to_string (fsp->f_type);
265 #endif /* MOUNTED_GETMNTINFO */
267 #ifdef MOUNTED_VMOUNT /* AIX. */
274 e = getvfsbytype (t);
275 if (!e || !e->vfsent_name)
278 return e->vfsent_name;
280 #endif /* MOUNTED_VMOUNT */
282 /* Return a list of the currently mounted filesystems, or NULL on error.
283 Add each entry to the tail of the list so that they stay in order.
284 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
285 the returned list are valid. Otherwise, they might not be.
286 If ALL_FS is positive, return all entries; if zero, omit entries
287 for filesystems that are automounter (dummy) entries; if negative,
288 also omit non-local filesystems. */
291 read_filesystem_list (int need_fs_type, int all_fs)
293 struct mount_entry *mount_list;
294 struct mount_entry *me;
295 struct mount_entry **mtail = &mount_list;
297 #ifdef MOUNTED_LISTMNTENT
299 struct tabmntent *mntlist, *p;
301 struct mount_entry *me;
303 /* the third and fourth arguments could be used to filter mounts,
304 but Crays doesn't seem to have any mounts that we want to
305 remove. Specifically, automount create normal NFS mounts.
308 if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
310 for (p = mntlist; p; p = p->next) {
312 if (all_fs < 0 && REMOTE_FS_TYPE (mnt->mnt_type))
314 me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
315 me->me_devname = xstrdup(mnt->mnt_fsname);
316 me->me_mountdir = xstrdup(mnt->mnt_dir);
317 me->me_type = xstrdup(mnt->mnt_type);
320 mtail = &me->me_next;
322 freemntlist(mntlist);
326 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
329 char *table = MOUNTED;
333 fp = setmntent (table, "r");
337 while ((mnt = getmntent (fp)))
339 if (all_fs <= 0 && (!strcmp (mnt->mnt_type, "ignore")
340 || !strcmp (mnt->mnt_type, "auto")))
342 if (all_fs < 0 && REMOTE_FS_TYPE (mnt->mnt_type))
345 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
346 me->me_devname = xstrdup (mnt->mnt_fsname);
347 me->me_mountdir = xstrdup (mnt->mnt_dir);
348 me->me_type = xstrdup (mnt->mnt_type);
349 devopt = strstr (mnt->mnt_opts, "dev=");
352 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
353 me->me_dev = xatoi (devopt + 6);
355 me->me_dev = xatoi (devopt + 4);
358 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
360 /* Add to the linked list. */
362 mtail = &me->me_next;
365 if (endmntent (fp) == 0)
368 #endif /* MOUNTED_GETMNTENT1. */
370 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
375 entries = getmntinfo (&fsp, MNT_NOWAIT);
378 for (; entries-- > 0; fsp++)
382 # ifdef HAVE_F_FSTYPENAME_IN_STATFS
383 if (REMOTE_FS_TYPE (fsp->f_fstypename))
387 if (REMOTE_FS_TYPE (fstype_to_string (fsp->f_type)))
393 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
394 me->me_devname = xstrdup (fsp->f_mntfromname);
395 me->me_mountdir = xstrdup (fsp->f_mntonname);
396 me->me_type = fsp_to_string (fsp);
397 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
399 /* Add to the linked list. */
401 mtail = &me->me_next;
404 #endif /* MOUNTED_GETMNTINFO */
406 #ifdef MOUNTED_GETMNT /* Ultrix. */
413 0 <= (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
416 if (all_fs < 0 && REMOTE_FS_TYPE (gt_names[fsd.fd_req.fstype]))
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_dev = fsd.fd_req.dev;
425 /* Add to the linked list. */
427 mtail = &me->me_next;
432 #endif /* MOUNTED_GETMNT. */
434 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
436 int numsys, counter, bufsize;
437 struct statfs *stats;
439 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
443 bufsize = (1 + numsys) * sizeof (struct statfs);
444 stats = (struct statfs *)xmalloc (bufsize);
445 numsys = getfsstat (stats, bufsize, MNT_WAIT);
453 for (counter = 0; counter < numsys; counter++)
455 if (all_fs < 0 && REMOTE_FS_TYPE (mnt_names[stats[counter].f_type]))
458 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
459 me->me_devname = xstrdup (stats[counter].f_mntfromname);
460 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
461 me->me_type = mnt_names[stats[counter].f_type];
462 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
464 /* Add to the linked list. */
466 mtail = &me->me_next;
471 #endif /* MOUNTED_GETFSSTAT */
473 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
476 char *table = "/etc/mnttab";
479 fp = fopen (table, "r");
483 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
487 # ifdef GETFSTYP /* SVR3. */
488 if (need_fs_type || all_fs < 0)
491 char typebuf[FSTYPSZ];
493 if (statfs (mnt.mt_filsys, &fsd, sizeof fsd, 0) != -1
494 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
496 if (all_fs < 0 && REMOTE_FS_TYPE (typebuf))
498 fs_type = xstrdup (typebuf);
503 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
504 # ifdef GETFSTYP /* SVR3. */
505 me->me_devname = xstrdup (mnt.mt_dev);
507 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
508 strcpy (me->me_devname, "/dev/");
509 strcpy (me->me_devname + 5, mnt.mt_dev);
511 me->me_mountdir = xstrdup (mnt.mt_filsys);
512 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
513 me->me_type = fs_type;
515 /* Add to the linked list. */
517 mtail = &me->me_next;
522 int saved_errno = errno;
528 if (fclose (fp) == EOF)
531 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
533 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
535 struct mntent **mnttbl=getmnttbl(),**ent;
536 for (ent=mnttbl;*ent;ent++)
538 if (all_fs < 0 && REMOTE_FS_TYPE ((*ent)->mt_fstype))
541 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
542 me->me_devname = xstrdup ( (*ent)->mt_resource);
543 me->me_mountdir = xstrdup( (*ent)->mt_directory);
544 me->me_type = xstrdup ((*ent)->mt_fstype);
545 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
547 /* Add to the linked list. */
549 mtail = &me->me_next;
555 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
558 char *table = MNTTAB;
563 # if defined F_RDLCK && defined F_SETLKW
564 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
565 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
566 for this file name, we should use their macro name instead.
567 (Why not just lock MNTTAB directly? We don't know.) */
569 # define MNTTAB_LOCK "/etc/.mnttab.lock"
571 lockfd = open (MNTTAB_LOCK, O_RDONLY);
575 flock.l_type = F_RDLCK;
576 flock.l_whence = SEEK_SET;
579 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
582 int saved_errno = errno;
588 else if (errno != ENOENT)
593 fp = fopen (table, "r");
598 while ((ret = getmntent (fp, &mnt)) == 0)
600 /* Don't show automounted filesystems twice on e.g., Solaris. */
601 if (all_fs <= 0 && MNT_IGNORE (&mnt))
604 if (all_fs < 0 && REMOTE_FS_TYPE (mnt.mnt_fstype))
607 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
608 me->me_devname = xstrdup (mnt.mnt_special);
609 me->me_mountdir = xstrdup (mnt.mnt_mountp);
610 me->me_type = xstrdup (mnt.mnt_fstype);
611 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
613 /* Add to the linked list. */
615 mtail = &me->me_next;
618 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
621 if (0 <= lockfd && close (lockfd) != 0)
630 #endif /* MOUNTED_GETMNTENT2. */
632 #ifdef MOUNTED_VMOUNT /* AIX. */
635 char *entries, *thisent;
638 /* Ask how many bytes to allocate for the mounted filesystem info. */
639 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
640 entries = xmalloc (bufsize);
642 /* Get the list of mounted filesystems. */
643 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
645 for (thisent = entries; thisent < entries + bufsize;
646 thisent += vmp->vmt_length)
648 vmp = (struct vmount *) thisent;
649 if (all_fs < 0 && vmp->vmt_flags & MNT_REMOTE)
651 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
652 if (vmp->vmt_flags & MNT_REMOTE)
656 /* Prepend the remote pathname. */
657 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
658 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
659 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
660 strcpy (me->me_devname, host);
661 strcat (me->me_devname, ":");
662 strcat (me->me_devname, path);
666 me->me_devname = xstrdup (thisent +
667 vmp->vmt_data[VMT_OBJECT].vmt_off);
669 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
670 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
671 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
673 /* Add to the linked list. */
675 mtail = &me->me_next;
679 #endif /* MOUNTED_VMOUNT. */
687 int saved_errno = errno;
692 me = mount_list->me_next;
693 free (mount_list->me_devname);
694 free (mount_list->me_mountdir);
695 /* FIXME: me_type is not always malloced. */