1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992 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
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include <sys/types.h>
25 #include "mountlist.h"
30 void free (void *ptr
);
32 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
38 #ifdef HAVE_SYS_PARAM_H
39 #include <sys/param.h>
42 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
43 #include <sys/mount.h>
44 #include <sys/fs_types.h>
45 #endif /* MOUNTED_GETFSSTAT */
47 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
50 #if defined(MNT_MNTTAB) /* HP-UX. */
51 #define MOUNTED MNT_MNTTAB
53 #if defined(MNTTABNAME) /* Dynix. */
54 #define MOUNTED MNTTABNAME
59 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
60 #include <sys/mount.h>
63 #ifdef MOUNTED_GETMNT /* Ultrix. */
64 #include <sys/mount.h>
65 #include <sys/fs_types.h>
68 #ifdef MOUNTED_FREAD /* SVR2. */
72 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
74 #include <sys/fstyp.h>
75 #include <sys/statfs.h>
78 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
79 #include <sys/mnttab.h>
82 #ifdef MOUNTED_VMOUNT /* AIX. */
101 #if defined(SCO_FLAVOR) && defined(__GNUC__)
102 extern char* strdup(const char*);
105 char *strstr (const char *haystack
, const char *needle
);
106 /* void error (void); FIXME -- needed? */
109 /* So special that it's not worth putting this in autoconf. */
110 #undef MOUNTED_FREAD_FSTYP
111 #define MOUNTED_GETMNTTBL
114 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
115 /* Return the value of the hexadecimal number represented by CP.
116 No prefix (like '0x') or suffix (like 'h') is expected to be
119 static int xatoi (char *cp
)
125 if (*cp
>= 'a' && *cp
<= 'f')
126 val
= val
* 16 + *cp
- 'a' + 10;
127 else if (*cp
>= 'A' && *cp
<= 'F')
128 val
= val
* 16 + *cp
- 'A' + 10;
129 else if (*cp
>= '0' && *cp
<= '9')
130 val
= val
* 16 + *cp
- '0';
137 #endif /* MOUNTED_GETMNTENT1. */
139 #if defined (MOUNTED_GETMNTINFO) && !defined (xBSD)
140 static char *fstype_to_string (short t
)
171 #endif /* MOUNTED_GETMNTINFO */
173 #ifdef MOUNTED_VMOUNT /* AIX. */
174 static char *fstype_to_string (int t
)
178 e
= getvfsbytype (t
);
179 if (!e
|| !e
->vfsent_name
)
182 return e
->vfsent_name
;
184 #endif /* MOUNTED_VMOUNT */
186 /* Return a list of the currently mounted filesystems, or NULL on error.
187 Add each entry to the tail of the list so that they stay in order.
188 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
189 the returned list are valid. Otherwise, they might not be.
190 If ALL_FS is zero, do not return entries for filesystems that
191 are automounter (dummy) entries. */
193 struct mount_entry
*read_filesystem_list (int need_fs_type
, int all_fs
)
195 struct mount_entry
*mount_list
;
196 struct mount_entry
*me
;
197 struct mount_entry
*mtail
;
199 /* Start the list off with a dummy entry. */
200 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
202 mount_list
= mtail
= me
;
204 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
207 char *table
= MOUNTED
;
211 fp
= setmntent (table
, "r");
215 while ((mnt
= getmntent (fp
))) {
216 if (!all_fs
&& (!strcmp (mnt
->mnt_type
, "ignore")
217 || !strcmp (mnt
->mnt_type
, "auto")))
220 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
221 me
->me_devname
= strdup (mnt
->mnt_fsname
);
222 me
->me_mountdir
= strdup (mnt
->mnt_dir
);
223 me
->me_type
= strdup (mnt
->mnt_type
);
224 devopt
= strstr (mnt
->mnt_opts
, "dev=");
226 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
227 me
->me_dev
= xatoi (devopt
+ 6);
229 me
->me_dev
= xatoi (devopt
+ 4);
231 me
->me_dev
= -1; /* Magic; means not known yet. */
234 /* Add to the linked list. */
239 if (endmntent (fp
) == 0)
242 #endif /* MOUNTED_GETMNTENT1. */
244 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
249 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
252 while (entries
-- > 0) {
253 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
254 me
->me_devname
= strdup (fsp
->f_mntfromname
);
255 me
->me_mountdir
= strdup (fsp
->f_mntonname
);
257 me
->me_type
= strdup (fsp
->f_fstypename
);
259 me
->me_type
= fstype_to_string (fsp
->f_type
);
261 me
->me_dev
= -1; /* Magic; means not known yet. */
264 /* Add to the linked list. */
270 #endif /* MOUNTED_GETMNTINFO */
272 #ifdef MOUNTED_GETMNT /* Ultrix. */
278 while ((val
= getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
,
280 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
281 me
->me_devname
= strdup (fsd
.fd_req
.devname
);
282 me
->me_mountdir
= strdup (fsd
.fd_req
.path
);
283 me
->me_type
= gt_names
[fsd
.fd_req
.fstype
];
284 me
->me_dev
= fsd
.fd_req
.dev
;
287 /* Add to the linked list. */
294 #endif /* MOUNTED_GETMNT. */
296 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
298 int numsys
, counter
, bufsize
;
299 struct statfs
*stats
;
301 numsys
= getfsstat ((struct statfs
*) 0, 0L, MNT_WAIT
);
305 bufsize
= (1 + numsys
) * sizeof (struct statfs
);
306 stats
= (struct statfs
*) malloc (bufsize
);
307 numsys
= getfsstat (stats
, bufsize
, MNT_WAIT
);
313 for (counter
= 0; counter
< numsys
; counter
++) {
314 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
315 me
->me_devname
= strdup (stats
[counter
].f_mntfromname
);
316 me
->me_mountdir
= strdup (stats
[counter
].f_mntonname
);
317 me
->me_type
= mnt_names
[stats
[counter
].f_type
];
318 me
->me_dev
= -1; /* Magic; means not known yet. */
321 /* Add to the linked list. */
328 #endif /* MOUNTED_GETFSSTAT */
330 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
333 char *table
= "/etc/mnttab";
336 fp
= fopen (table
, "r");
340 while (fread (&mnt
, sizeof mnt
, 1, fp
) > 0) {
341 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
342 #ifdef GETFSTYP /* SVR3. */
343 me
->me_devname
= strdup (mnt
.mt_dev
);
345 me
->me_devname
= malloc (strlen (mnt
.mt_dev
) + 6);
346 strcpy (me
->me_devname
, "/dev/");
347 strcpy (me
->me_devname
+ 5, mnt
.mt_dev
);
349 me
->me_mountdir
= strdup (mnt
.mt_filsys
);
350 me
->me_dev
= -1; /* Magic; means not known yet. */
352 #ifdef GETFSTYP /* SVR3. */
355 char typebuf
[FSTYPSZ
];
357 if (statfs (me
->me_mountdir
, &fsd
, sizeof fsd
, 0) != -1
358 && sysfs (GETFSTYP
, fsd
.f_fstyp
, typebuf
) != -1)
359 me
->me_type
= strdup (typebuf
);
364 /* Add to the linked list. */
369 if (fclose (fp
) == EOF
)
372 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
374 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
376 struct mntent
**mnttbl
= getmnttbl (), **ent
;
377 for (ent
= mnttbl
; *ent
; ent
++) {
378 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
379 me
->me_devname
= strdup ((*ent
)->mt_resource
);
380 me
->me_mountdir
= strdup ((*ent
)->mt_directory
);
381 me
->me_type
= strdup ((*ent
)->mt_fstype
);
382 me
->me_dev
= -1; /* Magic; means not known yet. */
385 /* Add to the linked list. */
393 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
396 char *table
= MNTTAB
;
400 fp
= fopen (table
, "r");
404 while ((ret
= getmntent (fp
, &mnt
)) == 0) {
405 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
406 me
->me_devname
= strdup (mnt
.mnt_special
);
407 me
->me_mountdir
= strdup (mnt
.mnt_mountp
);
408 me
->me_type
= strdup (mnt
.mnt_fstype
);
409 me
->me_dev
= -1; /* Magic; means not known yet. */
412 /* Add to the linked list. */
419 if (fclose (fp
) == EOF
)
422 #endif /* MOUNTED_GETMNTENT2. */
424 #ifdef MOUNTED_VMOUNT /* AIX. */
427 char *entries
, *thisent
;
430 /* Ask how many bytes to allocate for the mounted filesystem info. */
431 mntctl (MCTL_QUERY
, sizeof bufsize
, (struct vmount
*) &bufsize
);
432 entries
= malloc (bufsize
);
434 /* Get the list of mounted filesystems. */
435 mntctl (MCTL_QUERY
, bufsize
, (struct vmount
*) entries
);
437 for (thisent
= entries
; thisent
< entries
+ bufsize
;
438 thisent
+= vmp
->vmt_length
) {
439 vmp
= (struct vmount
*) thisent
;
440 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
441 if (vmp
->vmt_flags
& MNT_REMOTE
) {
444 /* Prepend the remote pathname. */
445 host
= thisent
+ vmp
->vmt_data
[VMT_HOSTNAME
].vmt_off
;
446 path
= thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
;
447 me
->me_devname
= malloc (strlen (host
) + strlen (path
) + 2);
448 strcpy (me
->me_devname
, host
);
449 strcat (me
->me_devname
, ":");
450 strcat (me
->me_devname
, path
);
452 me
->me_devname
= strdup (thisent
+
453 vmp
->vmt_data
[VMT_OBJECT
].vmt_off
);
455 me
->me_mountdir
= strdup (thisent
+ vmp
->vmt_data
[VMT_STUB
].vmt_off
);
456 me
->me_type
= strdup (fstype_to_string (vmp
->vmt_gfstype
));
457 me
->me_dev
= -1; /* vmt_fsid might be the info we want. */
460 /* Add to the linked list. */
466 #endif /* MOUNTED_VMOUNT. */
468 /* Free the dummy head. */
470 mount_list
= mount_list
->me_next
;
474 #endif /* NO_INFOMOUNT */
476 #if defined(NO_INFOMOUNT) && defined(__QNX__)
478 ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
479 ** this via the following code.
480 ** Note that, as this is based on CWD, it only fills one mount_entry
481 ** structure. See my_statfs() in utilunix.c for the "other side" of
492 #include <sys/disk.h>
493 #include <sys/fsys.h>
494 #include <sys/statfs.h>
496 #include "mountlist.h"
498 struct mount_entry
*read_filesystem_list(int need_fs_type
, int all_fs
)
500 struct _disk_entry de
;
503 char *tp
, dev
[_POSIX_NAME_MAX
], dir
[_POSIX_PATH_MAX
];
505 static struct mount_entry
*me
= NULL
;
509 if (me
->me_devname
) free(me
->me_devname
);
510 if (me
->me_mountdir
) free(me
->me_mountdir
);
511 if (me
->me_type
) free(me
->me_type
);
514 me
= (struct mount_entry
*)malloc(sizeof(struct mount_entry
));
516 if (!getcwd(dir
, _POSIX_PATH_MAX
)) return (NULL
);
518 if ((fd
= open(dir
, O_RDONLY
)) == -1) return (NULL
);
520 i
= disk_get_entry(fd
, &de
);
524 if (i
== -1) return (NULL
);
526 switch (de
.disk_type
)
528 case _UNMOUNTED
: tp
= "unmounted"; break;
529 case _FLOPPY
: tp
= "Floppy"; break;
530 case _HARD
: tp
= "Hard"; break;
531 case _RAMDISK
: tp
= "Ram"; break;
532 case _REMOVABLE
: tp
= "Removable"; break;
533 case _TAPE
: tp
= "Tape"; break;
534 case _CDROM
: tp
= "CDROM"; break;
535 default: tp
= "unknown";
538 if (fsys_get_mount_dev(dir
, &dev
) == -1) return (NULL
);
540 if (fsys_get_mount_pt(dev
, &dir
) == -1) return (NULL
);
542 me
->me_devname
= strdup(dev
);
543 me
->me_mountdir
= strdup(dir
);
544 me
->me_type
= strdup(tp
);
545 me
->me_dev
= de
.disk_type
;
548 fprintf(stderr
, "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
549 de
.disk_type
, tp
, _DRIVER_NAME_LEN
, _DRIVER_NAME_LEN
, de
.driver_name
, de
.disk_drv
);
550 fprintf(stderr
, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev
);
551 fprintf(stderr
, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir
);