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 zero, do not return entries for filesystems that
287 are automounter (dummy) entries. */
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)
312 me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
313 me->me_devname = xstrdup(mnt->mnt_fsname);
314 me->me_mountdir = xstrdup(mnt->mnt_dir);
315 me->me_type = xstrdup(mnt->mnt_type);
318 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 && (!strcmp (mnt->mnt_type, "ignore")
339 || !strcmp (mnt->mnt_type, "auto")))
342 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
343 me->me_devname = xstrdup (mnt->mnt_fsname);
344 me->me_mountdir = xstrdup (mnt->mnt_dir);
345 me->me_type = xstrdup (mnt->mnt_type);
346 devopt = strstr (mnt->mnt_opts, "dev=");
349 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
350 me->me_dev = xatoi (devopt + 6);
352 me->me_dev = xatoi (devopt + 4);
355 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
357 /* Add to the linked list. */
359 mtail = &me->me_next;
362 if (endmntent (fp) == 0)
365 #endif /* MOUNTED_GETMNTENT1. */
367 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
372 entries = getmntinfo (&fsp, MNT_NOWAIT);
375 while (entries-- > 0)
377 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
378 me->me_devname = xstrdup (fsp->f_mntfromname);
379 me->me_mountdir = xstrdup (fsp->f_mntonname);
380 me->me_type = fsp_to_string (fsp);
381 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
383 /* Add to the linked list. */
385 mtail = &me->me_next;
389 #endif /* MOUNTED_GETMNTINFO */
391 #ifdef MOUNTED_GETMNT /* Ultrix. */
398 0 <= (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
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_dev = fsd.fd_req.dev;
407 /* Add to the linked list. */
409 mtail = &me->me_next;
414 #endif /* MOUNTED_GETMNT. */
416 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
418 int numsys, counter, bufsize;
419 struct statfs *stats;
421 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
425 bufsize = (1 + numsys) * sizeof (struct statfs);
426 stats = (struct statfs *)xmalloc (bufsize);
427 numsys = getfsstat (stats, bufsize, MNT_WAIT);
435 for (counter = 0; counter < numsys; counter++)
437 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
438 me->me_devname = xstrdup (stats[counter].f_mntfromname);
439 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
440 me->me_type = mnt_names[stats[counter].f_type];
441 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
443 /* Add to the linked list. */
445 mtail = &me->me_next;
450 #endif /* MOUNTED_GETFSSTAT */
452 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
455 char *table = "/etc/mnttab";
458 fp = fopen (table, "r");
462 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
464 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
465 # ifdef GETFSTYP /* SVR3. */
466 me->me_devname = xstrdup (mnt.mt_dev);
468 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
469 strcpy (me->me_devname, "/dev/");
470 strcpy (me->me_devname + 5, mnt.mt_dev);
472 me->me_mountdir = xstrdup (mnt.mt_filsys);
473 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
475 # ifdef GETFSTYP /* SVR3. */
479 char typebuf[FSTYPSZ];
481 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
482 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
483 me->me_type = xstrdup (typebuf);
487 /* Add to the linked list. */
489 mtail = &me->me_next;
494 int saved_errno = errno;
500 if (fclose (fp) == EOF)
503 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
505 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
507 struct mntent **mnttbl=getmnttbl(),**ent;
508 for (ent=mnttbl;*ent;ent++)
510 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
511 me->me_devname = xstrdup ( (*ent)->mt_resource);
512 me->me_mountdir = xstrdup( (*ent)->mt_directory);
513 me->me_type = xstrdup ((*ent)->mt_fstype);
514 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
516 /* Add to the linked list. */
518 mtail = &me->me_next;
524 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
527 char *table = MNTTAB;
532 # if defined F_RDLCK && defined F_SETLKW
533 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
534 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
535 for this file name, we should use their macro name instead.
536 (Why not just lock MNTTAB directly? We don't know.) */
538 # define MNTTAB_LOCK "/etc/.mnttab.lock"
540 lockfd = open (MNTTAB_LOCK, O_RDONLY);
544 flock.l_type = F_RDLCK;
545 flock.l_whence = SEEK_SET;
548 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
551 int saved_errno = errno;
557 else if (errno != ENOENT)
562 fp = fopen (table, "r");
567 while ((ret = getmntent (fp, &mnt)) == 0)
569 /* Don't show automounted filesystems twice on e.g., Solaris. */
570 if (!all_fs && MNT_IGNORE (&mnt))
573 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
574 me->me_devname = xstrdup (mnt.mnt_special);
575 me->me_mountdir = xstrdup (mnt.mnt_mountp);
576 me->me_type = xstrdup (mnt.mnt_fstype);
577 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
579 /* Add to the linked list. */
581 mtail = &me->me_next;
584 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
587 if (0 <= lockfd && close (lockfd) != 0)
596 #endif /* MOUNTED_GETMNTENT2. */
598 #ifdef MOUNTED_VMOUNT /* AIX. */
601 char *entries, *thisent;
604 /* Ask how many bytes to allocate for the mounted filesystem info. */
605 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
606 entries = xmalloc (bufsize);
608 /* Get the list of mounted filesystems. */
609 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
611 for (thisent = entries; thisent < entries + bufsize;
612 thisent += vmp->vmt_length)
614 vmp = (struct vmount *) thisent;
615 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
616 if (vmp->vmt_flags & MNT_REMOTE)
620 /* Prepend the remote pathname. */
621 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
622 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
623 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
624 strcpy (me->me_devname, host);
625 strcat (me->me_devname, ":");
626 strcat (me->me_devname, path);
630 me->me_devname = xstrdup (thisent +
631 vmp->vmt_data[VMT_OBJECT].vmt_off);
633 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
634 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
635 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
637 /* Add to the linked list. */
639 mtail = &me->me_next;
643 #endif /* MOUNTED_VMOUNT. */
651 int saved_errno = errno;
656 me = mount_list->me_next;
657 free (mount_list->me_devname);
658 free (mount_list->me_mountdir);
659 /* FIXME: me_type is not always malloced. */