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
132 /* FIXME: this can overflow */
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. */
269 fstype_to_string (int t
)
273 e
= getvfsbytype (t
);
274 if (!e
|| !e
->vfsent_name
)
277 return e
->vfsent_name
;
279 #endif /* MOUNTED_VMOUNT */
281 /* Return a list of the currently mounted filesystems, or NULL on error.
282 Add each entry to the tail of the list so that they stay in order.
283 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
284 the returned list are valid. Otherwise, they might not be. */
287 read_filesystem_list (int need_fs_type
)
289 struct mount_entry
*mount_list
;
290 struct mount_entry
*me
;
291 struct mount_entry
**mtail
= &mount_list
;
293 #ifdef MOUNTED_LISTMNTENT
295 struct tabmntent
*mntlist
, *p
;
297 struct mount_entry
*me
;
299 /* the third and fourth arguments could be used to filter mounts,
300 but Crays doesn't seem to have any mounts that we want to
301 remove. Specifically, automount create normal NFS mounts.
304 if(listmntent(&mntlist
, KMTAB
, NULL
, NULL
) < 0)
306 for (p
= mntlist
; p
; p
= p
->next
) {
308 me
= (struct mount_entry
*) xmalloc(sizeof (struct mount_entry
));
309 me
->me_devname
= xstrdup(mnt
->mnt_fsname
);
310 me
->me_mountdir
= xstrdup(mnt
->mnt_dir
);
311 me
->me_type
= xstrdup(mnt
->mnt_type
);
312 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
313 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
316 mtail
= &me
->me_next
;
318 freemntlist(mntlist
);
322 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
325 char *table
= MOUNTED
;
329 fp
= setmntent (table
, "r");
333 while ((mnt
= getmntent (fp
)))
335 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
336 me
->me_devname
= xstrdup (mnt
->mnt_fsname
);
337 me
->me_mountdir
= xstrdup (mnt
->mnt_dir
);
338 me
->me_type
= xstrdup (mnt
->mnt_type
);
339 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
340 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
341 devopt
= strstr (mnt
->mnt_opts
, "dev=");
344 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
345 me
->me_dev
= xatoi (devopt
+ 6);
347 me
->me_dev
= xatoi (devopt
+ 4);
350 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
352 /* Add to the linked list. */
354 mtail
= &me
->me_next
;
357 if (endmntent (fp
) == 0)
360 #endif /* MOUNTED_GETMNTENT1. */
362 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
367 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
370 for (; entries
-- > 0; fsp
++)
372 char *fs_type
= fsp_to_string (fsp
);
374 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
375 me
->me_devname
= xstrdup (fsp
->f_mntfromname
);
376 me
->me_mountdir
= xstrdup (fsp
->f_mntonname
);
377 me
->me_type
= fs_type
;
378 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
379 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
380 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
382 /* Add to the linked list. */
384 mtail
= &me
->me_next
;
387 #endif /* MOUNTED_GETMNTINFO */
389 #ifdef MOUNTED_GETMNT /* Ultrix. */
396 0 < (val
= getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
,
399 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
400 me
->me_devname
= xstrdup (fsd
.fd_req
.devname
);
401 me
->me_mountdir
= xstrdup (fsd
.fd_req
.path
);
402 me
->me_type
= gt_names
[fsd
.fd_req
.fstype
];
403 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
404 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
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_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
442 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
443 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
445 /* Add to the linked list. */
447 mtail
= &me
->me_next
;
452 #endif /* MOUNTED_GETFSSTAT */
454 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
457 char *table
= "/etc/mnttab";
460 fp
= fopen (table
, "r");
464 while (fread (&mnt
, sizeof mnt
, 1, fp
) > 0)
466 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
467 # ifdef GETFSTYP /* SVR3. */
468 me
->me_devname
= xstrdup (mnt
.mt_dev
);
470 me
->me_devname
= xmalloc (strlen (mnt
.mt_dev
) + 6);
471 strcpy (me
->me_devname
, "/dev/");
472 strcpy (me
->me_devname
+ 5, mnt
.mt_dev
);
474 me
->me_mountdir
= xstrdup (mnt
.mt_filsys
);
475 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
477 # ifdef GETFSTYP /* SVR3. */
481 char typebuf
[FSTYPSZ
];
483 if (statfs (me
->me_mountdir
, &fsd
, sizeof fsd
, 0) != -1
484 && sysfs (GETFSTYP
, fsd
.f_fstyp
, typebuf
) != -1)
485 me
->me_type
= xstrdup (typebuf
);
488 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
489 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
491 /* Add to the linked list. */
493 mtail
= &me
->me_next
;
498 int saved_errno
= errno
;
504 if (fclose (fp
) == EOF
)
507 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
509 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
511 struct mntent
**mnttbl
=getmnttbl(),**ent
;
512 for (ent
=mnttbl
;*ent
;ent
++)
514 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
515 me
->me_devname
= xstrdup ( (*ent
)->mt_resource
);
516 me
->me_mountdir
= xstrdup( (*ent
)->mt_directory
);
517 me
->me_type
= xstrdup ((*ent
)->mt_fstype
);
518 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
519 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
520 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
522 /* Add to the linked list. */
524 mtail
= &me
->me_next
;
530 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
533 char *table
= MNTTAB
;
538 # if defined F_RDLCK && defined F_SETLKW
539 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
540 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
541 for this file name, we should use their macro name instead.
542 (Why not just lock MNTTAB directly? We don't know.) */
544 # define MNTTAB_LOCK "/etc/.mnttab.lock"
546 lockfd
= open (MNTTAB_LOCK
, O_RDONLY
);
550 flock
.l_type
= F_RDLCK
;
551 flock
.l_whence
= SEEK_SET
;
554 while (fcntl (lockfd
, F_SETLKW
, &flock
) == -1)
557 int saved_errno
= errno
;
563 else if (errno
!= ENOENT
)
568 fp
= fopen (table
, "r");
573 while ((ret
= getmntent (fp
, &mnt
)) == 0)
575 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
576 me
->me_devname
= xstrdup (mnt
.mnt_special
);
577 me
->me_mountdir
= xstrdup (mnt
.mnt_mountp
);
578 me
->me_type
= xstrdup (mnt
.mnt_fstype
);
579 me
->me_dummy
= MNT_IGNORE (&mnt
) != 0;
580 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
581 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
583 /* Add to the linked list. */
585 mtail
= &me
->me_next
;
588 ret
= fclose (fp
) == EOF
? errno
: 0 < ret
? 0 : -1;
591 if (0 <= lockfd
&& close (lockfd
) != 0)
600 #endif /* MOUNTED_GETMNTENT2. */
602 #ifdef MOUNTED_VMOUNT /* AIX. */
605 char *entries
, *thisent
;
608 /* Ask how many bytes to allocate for the mounted filesystem info. */
609 mntctl (MCTL_QUERY
, sizeof bufsize
, (struct vmount
*) &bufsize
);
610 entries
= xmalloc (bufsize
);
612 /* Get the list of mounted filesystems. */
613 mntctl (MCTL_QUERY
, bufsize
, (struct vmount
*) entries
);
615 for (thisent
= entries
; thisent
< entries
+ bufsize
;
616 thisent
+= vmp
->vmt_length
)
618 vmp
= (struct vmount
*) thisent
;
619 me
= (struct mount_entry
*) xmalloc (sizeof (struct mount_entry
));
620 if (vmp
->vmt_flags
& MNT_REMOTE
)
625 /* Prepend the remote pathname. */
626 host
= thisent
+ vmp
->vmt_data
[VMT_HOSTNAME
].vmt_off
;
627 path
= thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
;
628 me
->me_devname
= xmalloc (strlen (host
) + strlen (path
) + 2);
629 strcpy (me
->me_devname
, host
);
630 strcat (me
->me_devname
, ":");
631 strcat (me
->me_devname
, path
);
636 me
->me_devname
= xstrdup (thisent
+
637 vmp
->vmt_data
[VMT_OBJECT
].vmt_off
);
639 me
->me_mountdir
= xstrdup (thisent
+ vmp
->vmt_data
[VMT_STUB
].vmt_off
);
640 me
->me_type
= xstrdup (fstype_to_string (vmp
->vmt_gfstype
));
641 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
642 me
->me_dev
= (dev_t
) -1; /* vmt_fsid might be the info we want. */
644 /* Add to the linked list. */
646 mtail
= &me
->me_next
;
650 #endif /* MOUNTED_VMOUNT. */
658 int saved_errno
= errno
;
663 me
= mount_list
->me_next
;
664 free (mount_list
->me_devname
);
665 free (mount_list
->me_mountdir
);
666 /* FIXME: me_type is not always malloced. */