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 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++)
380 char *fs_type = fsp_to_string (fsp);
381 if (all_fs < 0 && REMOTE_FS_TYPE (fs_type))
384 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
385 me->me_devname = xstrdup (fsp->f_mntfromname);
386 me->me_mountdir = xstrdup (fsp->f_mntonname);
387 me->me_type = fs_type;
388 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
390 /* Add to the linked list. */
392 mtail = &me->me_next;
395 #endif /* MOUNTED_GETMNTINFO */
397 #ifdef MOUNTED_GETMNT /* Ultrix. */
404 0 <= (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
407 if (all_fs < 0 && REMOTE_FS_TYPE (gt_names[fsd.fd_req.fstype]))
410 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
411 me->me_devname = xstrdup (fsd.fd_req.devname);
412 me->me_mountdir = xstrdup (fsd.fd_req.path);
413 me->me_type = gt_names[fsd.fd_req.fstype];
414 me->me_dev = fsd.fd_req.dev;
416 /* Add to the linked list. */
418 mtail = &me->me_next;
423 #endif /* MOUNTED_GETMNT. */
425 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
427 int numsys, counter, bufsize;
428 struct statfs *stats;
430 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
434 bufsize = (1 + numsys) * sizeof (struct statfs);
435 stats = (struct statfs *)xmalloc (bufsize);
436 numsys = getfsstat (stats, bufsize, MNT_WAIT);
444 for (counter = 0; counter < numsys; counter++)
446 if (all_fs < 0 && REMOTE_FS_TYPE (mnt_names[stats[counter].f_type]))
449 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
450 me->me_devname = xstrdup (stats[counter].f_mntfromname);
451 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
452 me->me_type = mnt_names[stats[counter].f_type];
453 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
455 /* Add to the linked list. */
457 mtail = &me->me_next;
462 #endif /* MOUNTED_GETFSSTAT */
464 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
467 char *table = "/etc/mnttab";
470 fp = fopen (table, "r");
474 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
478 # ifdef GETFSTYP /* SVR3. */
479 if (need_fs_type || all_fs < 0)
482 char typebuf[FSTYPSZ];
484 if (statfs (mnt.mt_filsys, &fsd, sizeof fsd, 0) != -1
485 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
487 if (all_fs < 0 && REMOTE_FS_TYPE (typebuf))
489 fs_type = xstrdup (typebuf);
494 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
495 # ifdef GETFSTYP /* SVR3. */
496 me->me_devname = xstrdup (mnt.mt_dev);
498 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
499 strcpy (me->me_devname, "/dev/");
500 strcpy (me->me_devname + 5, mnt.mt_dev);
502 me->me_mountdir = xstrdup (mnt.mt_filsys);
503 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
504 me->me_type = fs_type;
506 /* Add to the linked list. */
508 mtail = &me->me_next;
513 int saved_errno = errno;
519 if (fclose (fp) == EOF)
522 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
524 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
526 struct mntent **mnttbl=getmnttbl(),**ent;
527 for (ent=mnttbl;*ent;ent++)
529 if (all_fs < 0 && REMOTE_FS_TYPE ((*ent)->mt_fstype))
532 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
533 me->me_devname = xstrdup ( (*ent)->mt_resource);
534 me->me_mountdir = xstrdup( (*ent)->mt_directory);
535 me->me_type = xstrdup ((*ent)->mt_fstype);
536 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
538 /* Add to the linked list. */
540 mtail = &me->me_next;
546 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
549 char *table = MNTTAB;
554 # if defined F_RDLCK && defined F_SETLKW
555 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
556 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
557 for this file name, we should use their macro name instead.
558 (Why not just lock MNTTAB directly? We don't know.) */
560 # define MNTTAB_LOCK "/etc/.mnttab.lock"
562 lockfd = open (MNTTAB_LOCK, O_RDONLY);
566 flock.l_type = F_RDLCK;
567 flock.l_whence = SEEK_SET;
570 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
573 int saved_errno = errno;
579 else if (errno != ENOENT)
584 fp = fopen (table, "r");
589 while ((ret = getmntent (fp, &mnt)) == 0)
591 /* Don't show automounted filesystems twice on e.g., Solaris. */
592 if (all_fs <= 0 && MNT_IGNORE (&mnt))
595 if (all_fs < 0 && REMOTE_FS_TYPE (mnt.mnt_fstype))
598 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
599 me->me_devname = xstrdup (mnt.mnt_special);
600 me->me_mountdir = xstrdup (mnt.mnt_mountp);
601 me->me_type = xstrdup (mnt.mnt_fstype);
602 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
604 /* Add to the linked list. */
606 mtail = &me->me_next;
609 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
612 if (0 <= lockfd && close (lockfd) != 0)
621 #endif /* MOUNTED_GETMNTENT2. */
623 #ifdef MOUNTED_VMOUNT /* AIX. */
626 char *entries, *thisent;
629 /* Ask how many bytes to allocate for the mounted filesystem info. */
630 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
631 entries = xmalloc (bufsize);
633 /* Get the list of mounted filesystems. */
634 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
636 for (thisent = entries; thisent < entries + bufsize;
637 thisent += vmp->vmt_length)
639 vmp = (struct vmount *) thisent;
640 if (all_fs < 0 && vmp->vmt_flags & MNT_REMOTE)
642 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
643 if (vmp->vmt_flags & MNT_REMOTE)
647 /* Prepend the remote pathname. */
648 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
649 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
650 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
651 strcpy (me->me_devname, host);
652 strcat (me->me_devname, ":");
653 strcat (me->me_devname, path);
657 me->me_devname = xstrdup (thisent +
658 vmp->vmt_data[VMT_OBJECT].vmt_off);
660 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
661 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
662 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
664 /* Add to the linked list. */
666 mtail = &me->me_next;
670 #endif /* MOUNTED_VMOUNT. */
678 int saved_errno = errno;
683 me = mount_list->me_next;
684 free (mount_list->me_devname);
685 free (mount_list->me_mountdir);
686 /* FIXME: me_type is not always malloced. */