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 = &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)
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;
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 && (!strcmp (mnt->mnt_type, "ignore")
340 || !strcmp (mnt->mnt_type, "auto")))
343 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
344 me->me_devname = xstrdup (mnt->mnt_fsname);
345 me->me_mountdir = xstrdup (mnt->mnt_dir);
346 me->me_type = xstrdup (mnt->mnt_type);
347 devopt = strstr (mnt->mnt_opts, "dev=");
350 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
351 me->me_dev = xatoi (devopt + 6);
353 me->me_dev = xatoi (devopt + 4);
356 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
358 /* Add to the linked list. */
360 mtail = &me->me_next;
363 if (endmntent (fp) == 0)
366 #endif /* MOUNTED_GETMNTENT1. */
368 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
373 entries = getmntinfo (&fsp, MNT_NOWAIT);
376 while (entries-- > 0)
378 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
379 me->me_devname = xstrdup (fsp->f_mntfromname);
380 me->me_mountdir = xstrdup (fsp->f_mntonname);
381 me->me_type = fsp_to_string (fsp);
382 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
384 /* Add to the linked list. */
386 mtail = &me->me_next;
390 #endif /* MOUNTED_GETMNTINFO */
392 #ifdef MOUNTED_GETMNT /* Ultrix. */
399 0 <= (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
402 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
403 me->me_devname = xstrdup (fsd.fd_req.devname);
404 me->me_mountdir = xstrdup (fsd.fd_req.path);
405 me->me_type = gt_names[fsd.fd_req.fstype];
406 me->me_dev = fsd.fd_req.dev;
408 /* Add to the linked list. */
410 mtail = &me->me_next;
415 #endif /* MOUNTED_GETMNT. */
417 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
419 int numsys, counter, bufsize;
420 struct statfs *stats;
422 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
426 bufsize = (1 + numsys) * sizeof (struct statfs);
427 stats = (struct statfs *)xmalloc (bufsize);
428 numsys = getfsstat (stats, bufsize, MNT_WAIT);
436 for (counter = 0; counter < numsys; counter++)
438 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
439 me->me_devname = xstrdup (stats[counter].f_mntfromname);
440 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
441 me->me_type = mnt_names[stats[counter].f_type];
442 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
444 /* Add to the linked list. */
446 mtail = &me->me_next;
451 #endif /* MOUNTED_GETFSSTAT */
453 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
456 char *table = "/etc/mnttab";
459 fp = fopen (table, "r");
463 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
465 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
466 # ifdef GETFSTYP /* SVR3. */
467 me->me_devname = xstrdup (mnt.mt_dev);
469 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
470 strcpy (me->me_devname, "/dev/");
471 strcpy (me->me_devname + 5, mnt.mt_dev);
473 me->me_mountdir = xstrdup (mnt.mt_filsys);
474 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
476 # ifdef GETFSTYP /* SVR3. */
480 char typebuf[FSTYPSZ];
482 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
483 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
484 me->me_type = xstrdup (typebuf);
488 /* Add to the linked list. */
490 mtail = &me->me_next;
495 int saved_errno = errno;
501 if (fclose (fp) == EOF)
504 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
506 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
508 struct mntent **mnttbl=getmnttbl(),**ent;
509 for (ent=mnttbl;*ent;ent++)
511 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
512 me->me_devname = xstrdup ( (*ent)->mt_resource);
513 me->me_mountdir = xstrdup( (*ent)->mt_directory);
514 me->me_type = xstrdup ((*ent)->mt_fstype);
515 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
517 /* Add to the linked list. */
519 mtail = &me->me_next;
525 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
528 char *table = MNTTAB;
533 # if defined F_RDLCK && defined F_SETLKW
534 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
535 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
536 for this file name, we should use their macro name instead.
537 (Why not just lock MNTTAB directly? We don't know.) */
539 # define MNTTAB_LOCK "/etc/.mnttab.lock"
541 lockfd = open (MNTTAB_LOCK, O_RDONLY);
545 flock.l_type = F_RDLCK;
546 flock.l_whence = SEEK_SET;
549 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
552 int saved_errno = errno;
558 else if (errno != ENOENT)
563 fp = fopen (table, "r");
568 while ((ret = getmntent (fp, &mnt)) == 0)
570 /* Don't show automounted filesystems twice on e.g., Solaris. */
571 if (!all_fs && MNT_IGNORE (&mnt))
574 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
575 me->me_devname = xstrdup (mnt.mnt_special);
576 me->me_mountdir = xstrdup (mnt.mnt_mountp);
577 me->me_type = xstrdup (mnt.mnt_fstype);
578 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
580 /* Add to the linked list. */
582 mtail = &me->me_next;
585 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
588 if (0 <= lockfd && close (lockfd) != 0)
597 #endif /* MOUNTED_GETMNTENT2. */
599 #ifdef MOUNTED_VMOUNT /* AIX. */
602 char *entries, *thisent;
605 /* Ask how many bytes to allocate for the mounted filesystem info. */
606 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
607 entries = xmalloc (bufsize);
609 /* Get the list of mounted filesystems. */
610 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
612 for (thisent = entries; thisent < entries + bufsize;
613 thisent += vmp->vmt_length)
615 vmp = (struct vmount *) thisent;
616 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
617 if (vmp->vmt_flags & MNT_REMOTE)
621 /* Prepend the remote pathname. */
622 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
623 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
624 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
625 strcpy (me->me_devname, host);
626 strcat (me->me_devname, ":");
627 strcat (me->me_devname, path);
631 me->me_devname = xstrdup (thisent +
632 vmp->vmt_data[VMT_OBJECT].vmt_off);
634 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
635 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
636 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
638 /* Add to the linked list. */
640 mtail = &me->me_next;
644 #endif /* MOUNTED_VMOUNT. */
652 int saved_errno = errno;
657 me = mount_list->me_next;