.
[coreutils.git] / lib / mountlist.c
blob5018745a0d2cebd8fe095cb3177f12e4a192a8dd
1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992, 1997 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)
7 any later version.
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. */
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include "mountlist.h"
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 #else
29 void free ();
30 #endif
31 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
32 # include <string.h>
33 #else
34 # include <strings.h>
35 #endif
37 #ifndef strstr
38 char *strstr ();
39 #endif
40 char *xmalloc ();
41 char *xrealloc ();
42 char *xstrdup ();
43 void error ();
45 #ifdef HAVE_SYS_PARAM_H
46 # include <sys/param.h>
47 #endif
49 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
50 # include <sys/mount.h>
51 # include <sys/fs_types.h>
52 #endif /* MOUNTED_GETFSSTAT */
54 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
55 # include <mntent.h>
56 # if !defined(MOUNTED)
57 # if defined(MNT_MNTTAB) /* HP-UX. */
58 # define MOUNTED MNT_MNTTAB
59 # endif
60 # if defined(MNTTABNAME) /* Dynix. */
61 # define MOUNTED MNTTABNAME
62 # endif
63 # endif
64 #endif
66 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
67 # include <sys/mount.h>
68 #endif
70 #ifdef MOUNTED_GETMNT /* Ultrix. */
71 # include <sys/mount.h>
72 # include <sys/fs_types.h>
73 #endif
75 #ifdef MOUNTED_FREAD /* SVR2. */
76 # include <mnttab.h>
77 #endif
79 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
80 # include <mnttab.h>
81 # include <sys/fstyp.h>
82 # include <sys/statfs.h>
83 #endif
85 #ifdef MOUNTED_LISTMNTENT
86 # include <mntent.h>
87 #endif
89 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
90 # include <sys/mnttab.h>
91 #endif
93 #ifdef MOUNTED_VMOUNT /* AIX. */
94 # include <fshelp.h>
95 # include <sys/vfs.h>
96 #endif
98 #ifdef DOLPHIN
99 /* So special that it's not worth putting this in autoconf. */
100 # undef MOUNTED_FREAD_FSTYP
101 # define MOUNTED_GETMNTTBL
102 #endif
104 #ifdef HAVE_SYS_MNTENT_H
105 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
106 # include <sys/mntent.h>
107 #endif
109 #if defined (MNTOPT_IGNORE) && defined (HAVE_HASMNTOPT)
110 # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
111 #else
112 # define MNT_IGNORE(M) 0
113 #endif
115 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
116 /* Return the value of the hexadecimal number represented by CP.
117 No prefix (like '0x') or suffix (like 'h') is expected to be
118 part of CP. */
120 static int
121 xatoi (cp)
122 char *cp;
124 int val;
126 val = 0;
127 while (*cp)
129 if (*cp >= 'a' && *cp <= 'f')
130 val = val * 16 + *cp - 'a' + 10;
131 else if (*cp >= 'A' && *cp <= 'F')
132 val = val * 16 + *cp - 'A' + 10;
133 else if (*cp >= '0' && *cp <= '9')
134 val = val * 16 + *cp - '0';
135 else
136 break;
137 cp++;
139 return val;
141 #endif /* MOUNTED_GETMNTENT1. */
143 #if defined (MOUNTED_GETMNTINFO) && !defined (__NetBSD__) && !defined (__OpenBSD__)
144 static char *
145 fstype_to_string (t)
146 short t;
148 switch (t)
150 # ifdef MOUNT_PC
151 case MOUNT_PC:
152 return "pc";
153 # endif
154 # ifdef MOUNT_MFS
155 case MOUNT_MFS:
156 return "mfs";
157 # endif
158 # ifdef MOUNT_LO
159 case MOUNT_LO:
160 return "lo";
161 # endif
162 # ifdef MOUNT_TFS
163 case MOUNT_TFS:
164 return "tfs";
165 # endif
166 # ifdef MOUNT_TMP
167 case MOUNT_TMP:
168 return "tmp";
169 # endif
170 # ifdef MOUNT_UFS
171 case MOUNT_UFS:
172 return "ufs" ;
173 # endif
174 # ifdef MOUNT_NFS
175 case MOUNT_NFS:
176 return "nfs" ;
177 # endif
178 # ifdef MOUNT_MSDOS
179 case MOUNT_MSDOS:
180 return "msdos" ;
181 # endif
182 # ifdef MOUNT_LFS
183 case MOUNT_LFS:
184 return "lfs" ;
185 # endif
186 # ifdef MOUNT_LOFS
187 case MOUNT_LOFS:
188 return "lofs" ;
189 # endif
190 # ifdef MOUNT_FDESC
191 case MOUNT_FDESC:
192 return "fdesc" ;
193 # endif
194 # ifdef MOUNT_PORTAL
195 case MOUNT_PORTAL:
196 return "portal" ;
197 # endif
198 # ifdef MOUNT_NULL
199 case MOUNT_NULL:
200 return "null" ;
201 # endif
202 # ifdef MOUNT_UMAP
203 case MOUNT_UMAP:
204 return "umap" ;
205 # endif
206 # ifdef MOUNT_KERNFS
207 case MOUNT_KERNFS:
208 return "kernfs" ;
209 # endif
210 # ifdef MOUNT_PROCFS
211 case MOUNT_PROCFS:
212 return "procfs" ;
213 # endif
214 # ifdef MOUNT_AFS
215 case MOUNT_AFS:
216 return "afs" ;
217 # endif
218 # ifdef MOUNT_CD9660
219 case MOUNT_CD9660:
220 return "cd9660" ;
221 # endif
222 # ifdef MOUNT_UNION
223 case MOUNT_UNION:
224 return "union" ;
225 # endif
226 # ifdef MOUNT_DEVFS
227 case MOUNT_DEVFS:
228 return "devfs" ;
229 # endif
230 # ifdef MOUNT_EXT2FS
231 case MOUNT_EXT2FS:
232 return "ext2fs" ;
233 # endif
234 default:
235 return "?";
238 #endif /* MOUNTED_GETMNTINFO */
240 #ifdef MOUNTED_VMOUNT /* AIX. */
241 static char *
242 fstype_to_string (t)
243 int t;
245 struct vfs_ent *e;
247 e = getvfsbytype (t);
248 if (!e || !e->vfsent_name)
249 return "none";
250 else
251 return e->vfsent_name;
253 #endif /* MOUNTED_VMOUNT */
255 /* Return a list of the currently mounted filesystems, or NULL on error.
256 Add each entry to the tail of the list so that they stay in order.
257 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
258 the returned list are valid. Otherwise, they might not be.
259 If ALL_FS is zero, do not return entries for filesystems that
260 are automounter (dummy) entries. */
262 struct mount_entry *
263 read_filesystem_list (need_fs_type, all_fs)
264 int need_fs_type, all_fs;
266 struct mount_entry *mount_list;
267 struct mount_entry *me;
268 struct mount_entry *mtail;
270 /* Start the list off with a dummy entry. */
271 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
272 me->me_next = NULL;
273 mount_list = mtail = me;
275 #ifdef MOUNTED_LISTMNTENT
277 struct tabmntent *mntlist, *p;
278 struct mntent *mnt;
279 struct mount_entry *me;
281 /* the third and fourth arguments could be used to filter mounts,
282 but Crays doesn't seem to have any mounts that we want to
283 remove. Specifically, automount create normal NFS mounts.
286 if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
287 return NULL;
288 p = mntlist;
289 while(p){
290 mnt = p->ment;
291 me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
292 me->me_devname = xstrdup(mnt->mnt_fsname);
293 me->me_mountdir = xstrdup(mnt->mnt_dir);
294 me->me_type = xstrdup(mnt->mnt_type);
295 me->me_dev = -1;
296 me->me_next = NULL;
297 mtail->me_next = me;
298 mtail = me;
299 p = p->next;
301 freemntlist(mntlist);
303 #endif
305 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
307 struct mntent *mnt;
308 char *table = MOUNTED;
309 FILE *fp;
310 char *devopt;
312 fp = setmntent (table, "r");
313 if (fp == NULL)
314 return NULL;
316 while ((mnt = getmntent (fp)))
318 if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
319 || !strcmp (mnt->mnt_type, "auto")))
320 continue;
322 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
323 me->me_devname = xstrdup (mnt->mnt_fsname);
324 me->me_mountdir = xstrdup (mnt->mnt_dir);
325 me->me_type = xstrdup (mnt->mnt_type);
326 devopt = strstr (mnt->mnt_opts, "dev=");
327 if (devopt)
329 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
330 me->me_dev = xatoi (devopt + 6);
331 else
332 me->me_dev = xatoi (devopt + 4);
334 else
335 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
336 me->me_next = NULL;
338 /* Add to the linked list. */
339 mtail->me_next = me;
340 mtail = me;
343 if (endmntent (fp) == 0)
344 return NULL;
346 #endif /* MOUNTED_GETMNTENT1. */
348 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
350 struct statfs *fsp;
351 int entries;
353 entries = getmntinfo (&fsp, MNT_NOWAIT);
354 if (entries < 0)
355 return NULL;
356 while (entries-- > 0)
358 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
359 me->me_devname = xstrdup (fsp->f_mntfromname);
360 me->me_mountdir = xstrdup (fsp->f_mntonname);
361 # if defined (__NetBSD__) || defined (__OpenBSD__)
362 me->me_type = xstrdup (fsp->f_fstypename);
363 # else
364 me->me_type = fstype_to_string (fsp->f_type);
365 # endif
366 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
367 me->me_next = NULL;
369 /* Add to the linked list. */
370 mtail->me_next = me;
371 mtail = me;
372 fsp++;
375 #endif /* MOUNTED_GETMNTINFO */
377 #ifdef MOUNTED_GETMNT /* Ultrix. */
379 int offset = 0;
380 int val;
381 struct fs_data fsd;
383 while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
384 (char *) 0)) > 0)
386 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
387 me->me_devname = xstrdup (fsd.fd_req.devname);
388 me->me_mountdir = xstrdup (fsd.fd_req.path);
389 me->me_type = gt_names[fsd.fd_req.fstype];
390 me->me_dev = fsd.fd_req.dev;
391 me->me_next = NULL;
393 /* Add to the linked list. */
394 mtail->me_next = me;
395 mtail = me;
397 if (val < 0)
398 return NULL;
400 #endif /* MOUNTED_GETMNT. */
402 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
404 int numsys, counter, bufsize;
405 struct statfs *stats;
407 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
408 if (numsys < 0)
409 return (NULL);
411 bufsize = (1 + numsys) * sizeof (struct statfs);
412 stats = (struct statfs *)xmalloc (bufsize);
413 numsys = getfsstat (stats, bufsize, MNT_WAIT);
415 if (numsys < 0)
417 free (stats);
418 return (NULL);
421 for (counter = 0; counter < numsys; counter++)
423 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
424 me->me_devname = xstrdup (stats[counter].f_mntfromname);
425 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
426 me->me_type = mnt_names[stats[counter].f_type];
427 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
428 me->me_next = NULL;
430 /* Add to the linked list. */
431 mtail->me_next = me;
432 mtail = me;
435 free (stats);
437 #endif /* MOUNTED_GETFSSTAT */
439 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
441 struct mnttab mnt;
442 char *table = "/etc/mnttab";
443 FILE *fp;
445 fp = fopen (table, "r");
446 if (fp == NULL)
447 return NULL;
449 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
451 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
452 # ifdef GETFSTYP /* SVR3. */
453 me->me_devname = xstrdup (mnt.mt_dev);
454 # else
455 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
456 strcpy (me->me_devname, "/dev/");
457 strcpy (me->me_devname + 5, mnt.mt_dev);
458 # endif
459 me->me_mountdir = xstrdup (mnt.mt_filsys);
460 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
461 me->me_type = "";
462 # ifdef GETFSTYP /* SVR3. */
463 if (need_fs_type)
465 struct statfs fsd;
466 char typebuf[FSTYPSZ];
468 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
469 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
470 me->me_type = xstrdup (typebuf);
472 # endif
473 me->me_next = NULL;
475 /* Add to the linked list. */
476 mtail->me_next = me;
477 mtail = me;
480 if (fclose (fp) == EOF)
481 return NULL;
483 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
485 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
487 struct mntent **mnttbl=getmnttbl(),**ent;
488 for (ent=mnttbl;*ent;ent++)
490 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
491 me->me_devname = xstrdup ( (*ent)->mt_resource);
492 me->me_mountdir = xstrdup( (*ent)->mt_directory);
493 me->me_type = xstrdup ((*ent)->mt_fstype);
494 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
495 me->me_next = NULL;
497 /* Add to the linked list. */
498 mtail->me_next = me;
499 mtail = me;
501 endmnttbl();
503 #endif
505 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
507 struct mnttab mnt;
508 char *table = MNTTAB;
509 FILE *fp;
510 int ret;
512 fp = fopen (table, "r");
513 if (fp == NULL)
514 return NULL;
516 while ((ret = getmntent (fp, &mnt)) == 0)
518 /* Don't show automounted filesystems twice on e.g., Solaris. */
519 if (!all_fs && MNT_IGNORE (&mnt))
520 continue;
522 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
523 me->me_devname = xstrdup (mnt.mnt_special);
524 me->me_mountdir = xstrdup (mnt.mnt_mountp);
525 me->me_type = xstrdup (mnt.mnt_fstype);
526 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
527 me->me_next = NULL;
529 /* Add to the linked list. */
530 mtail->me_next = me;
531 mtail = me;
534 if (ret > 0)
535 return NULL;
536 if (fclose (fp) == EOF)
537 return NULL;
539 #endif /* MOUNTED_GETMNTENT2. */
541 #ifdef MOUNTED_VMOUNT /* AIX. */
543 int bufsize;
544 char *entries, *thisent;
545 struct vmount *vmp;
547 /* Ask how many bytes to allocate for the mounted filesystem info. */
548 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
549 entries = xmalloc (bufsize);
551 /* Get the list of mounted filesystems. */
552 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
554 for (thisent = entries; thisent < entries + bufsize;
555 thisent += vmp->vmt_length)
557 vmp = (struct vmount *) thisent;
558 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
559 if (vmp->vmt_flags & MNT_REMOTE)
561 char *host, *path;
563 /* Prepend the remote pathname. */
564 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
565 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
566 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
567 strcpy (me->me_devname, host);
568 strcat (me->me_devname, ":");
569 strcat (me->me_devname, path);
571 else
573 me->me_devname = xstrdup (thisent +
574 vmp->vmt_data[VMT_OBJECT].vmt_off);
576 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
577 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
578 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
579 me->me_next = NULL;
581 /* Add to the linked list. */
582 mtail->me_next = me;
583 mtail = me;
585 free (entries);
587 #endif /* MOUNTED_VMOUNT. */
589 /* Free the dummy head. */
590 me = mount_list;
591 mount_list = mount_list->me_next;
592 free (me);
593 return mount_list;