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