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 (need_fs_type, all_fs)
291 int need_fs_type, all_fs;
293 struct mount_entry *mount_list;
294 struct mount_entry *me;
295 struct mount_entry *mtail;
297 /* Start the list off with a dummy entry. */
298 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
300 mount_list = mtail = me;
302 #ifdef MOUNTED_LISTMNTENT
304 struct tabmntent *mntlist, *p;
306 struct mount_entry *me;
308 /* the third and fourth arguments could be used to filter mounts,
309 but Crays doesn't seem to have any mounts that we want to
310 remove. Specifically, automount create normal NFS mounts.
313 if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
318 me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
319 me->me_devname = xstrdup(mnt->mnt_fsname);
320 me->me_mountdir = xstrdup(mnt->mnt_dir);
321 me->me_type = xstrdup(mnt->mnt_type);
328 freemntlist(mntlist);
332 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
335 char *table = MOUNTED;
339 fp = setmntent (table, "r");
343 while ((mnt = getmntent (fp)))
345 if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
346 || !strcmp (mnt->mnt_type, "auto")))
349 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
350 me->me_devname = xstrdup (mnt->mnt_fsname);
351 me->me_mountdir = xstrdup (mnt->mnt_dir);
352 me->me_type = xstrdup (mnt->mnt_type);
353 devopt = strstr (mnt->mnt_opts, "dev=");
356 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
357 me->me_dev = xatoi (devopt + 6);
359 me->me_dev = xatoi (devopt + 4);
362 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
365 /* Add to the linked list. */
370 if (endmntent (fp) == 0)
373 #endif /* MOUNTED_GETMNTENT1. */
375 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
380 entries = getmntinfo (&fsp, MNT_NOWAIT);
383 while (entries-- > 0)
385 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
386 me->me_devname = xstrdup (fsp->f_mntfromname);
387 me->me_mountdir = xstrdup (fsp->f_mntonname);
388 me->me_type = fsp_to_string (fsp);
389 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
392 /* Add to the linked list. */
398 #endif /* MOUNTED_GETMNTINFO */
400 #ifdef MOUNTED_GETMNT /* Ultrix. */
406 while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
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;
416 /* Add to the linked list. */
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 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
447 me->me_devname = xstrdup (stats[counter].f_mntfromname);
448 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
449 me->me_type = mnt_names[stats[counter].f_type];
450 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
453 /* Add to the linked list. */
460 #endif /* MOUNTED_GETFSSTAT */
462 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
465 char *table = "/etc/mnttab";
468 fp = fopen (table, "r");
472 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
474 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
475 # ifdef GETFSTYP /* SVR3. */
476 me->me_devname = xstrdup (mnt.mt_dev);
478 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
479 strcpy (me->me_devname, "/dev/");
480 strcpy (me->me_devname + 5, mnt.mt_dev);
482 me->me_mountdir = xstrdup (mnt.mt_filsys);
483 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
485 # ifdef GETFSTYP /* SVR3. */
489 char typebuf[FSTYPSZ];
491 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
492 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
493 me->me_type = xstrdup (typebuf);
498 /* Add to the linked list. */
503 if (fclose (fp) == EOF)
506 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
508 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
510 struct mntent **mnttbl=getmnttbl(),**ent;
511 for (ent=mnttbl;*ent;ent++)
513 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
514 me->me_devname = xstrdup ( (*ent)->mt_resource);
515 me->me_mountdir = xstrdup( (*ent)->mt_directory);
516 me->me_type = xstrdup ((*ent)->mt_fstype);
517 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
520 /* Add to the linked list. */
528 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
531 char *table = MNTTAB;
536 # if defined F_RDLCK && defined F_SETLKW
537 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
538 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
539 for this file name, we should use their macro name instead.
540 (Why not just lock MNTTAB directly? We don't know.) */
542 # define MNTTAB_LOCK "/etc/.mnttab.lock"
544 lockfd = open (MNTTAB_LOCK, O_RDONLY);
548 flock.l_type = F_RDLCK;
549 flock.l_whence = SEEK_SET;
552 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
558 fp = fopen (table, "r");
563 while ((ret = getmntent (fp, &mnt)) == 0)
565 /* Don't show automounted filesystems twice on e.g., Solaris. */
566 if (!all_fs && MNT_IGNORE (&mnt))
569 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
570 me->me_devname = xstrdup (mnt.mnt_special);
571 me->me_mountdir = xstrdup (mnt.mnt_mountp);
572 me->me_type = xstrdup (mnt.mnt_fstype);
573 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
576 /* Add to the linked list. */
581 if (fclose (fp) == EOF)
585 if (0 <= lockfd && close (lockfd) != 0)
591 #endif /* MOUNTED_GETMNTENT2. */
593 #ifdef MOUNTED_VMOUNT /* AIX. */
596 char *entries, *thisent;
599 /* Ask how many bytes to allocate for the mounted filesystem info. */
600 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
601 entries = xmalloc (bufsize);
603 /* Get the list of mounted filesystems. */
604 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
606 for (thisent = entries; thisent < entries + bufsize;
607 thisent += vmp->vmt_length)
609 vmp = (struct vmount *) thisent;
610 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
611 if (vmp->vmt_flags & MNT_REMOTE)
615 /* Prepend the remote pathname. */
616 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
617 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
618 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
619 strcpy (me->me_devname, host);
620 strcat (me->me_devname, ":");
621 strcat (me->me_devname, path);
625 me->me_devname = xstrdup (thisent +
626 vmp->vmt_data[VMT_OBJECT].vmt_off);
628 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
629 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
630 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
633 /* Add to the linked list. */
639 #endif /* MOUNTED_VMOUNT. */
641 /* Free the dummy head. */
643 mount_list = mount_list->me_next;