(fsp_to_string): Clean out some crufty #ifdefs
[gnulib.git] / lib / mountlist.c
1 /* mountlist.c -- return a list of mounted filesystems
2    Copyright (C) 1991, 1992, 1997, 1998 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 #if 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 #ifndef strstr
38 char *strstr ();
39 #endif
40 char *xmalloc ();
41 char *xrealloc ();
42 char *xstrdup ();
43 void error ();
44
45 #if HAVE_SYS_PARAM_H
46 # include <sys/param.h>
47 #endif
48
49 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
50 # include <sys/mount.h>
51 # include <sys/fs_types.h>
52 #endif /* MOUNTED_GETFSSTAT */
53
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
65
66 #ifdef MOUNTED_GETMNTINFO       /* 4.4BSD.  */
67 # include <sys/mount.h>
68 #endif
69
70 #ifdef MOUNTED_GETMNT           /* Ultrix.  */
71 # include <sys/mount.h>
72 # include <sys/fs_types.h>
73 #endif
74
75 #ifdef MOUNTED_FREAD            /* SVR2.  */
76 # include <mnttab.h>
77 #endif
78
79 #ifdef MOUNTED_FREAD_FSTYP      /* SVR3.  */
80 # include <mnttab.h>
81 # include <sys/fstyp.h>
82 # include <sys/statfs.h>
83 #endif
84
85 #ifdef MOUNTED_LISTMNTENT
86 # include <mntent.h>
87 #endif
88
89 #ifdef MOUNTED_GETMNTENT2       /* SVR4.  */
90 # include <sys/mnttab.h>
91 #endif
92
93 #ifdef MOUNTED_VMOUNT           /* AIX.  */
94 # include <fshelp.h>
95 # include <sys/vfs.h>
96 #endif
97
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
103
104 #if HAVE_SYS_MNTENT_H
105 /* This is to get MNTOPT_IGNORE on e.g. SVR4.  */
106 # include <sys/mntent.h>
107 #endif
108
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
114
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. */
119
120 static int
121 xatoi (cp)
122      char *cp;
123 {
124   int val;
125
126   val = 0;
127   while (*cp)
128     {
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++;
138     }
139   return val;
140 }
141 #endif /* MOUNTED_GETMNTENT1.  */
142
143 #if MOUNTED_GETMNTINFO
144
145 static char *
146 fstype_to_string (short t)
147 {
148   switch (t)
149     {
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 "?";
236     }
237 }
238
239 /* __NetBSD__ || BSD_NET2 || __OpenBSD__ */
240 static char *
241 fsp_to_string (const struct statfs *fsp)
242 {
243 # if defined HAVE_F_FSTYPENAME_IN_STATFS
244   return xstrdup (fsp->f_fstypename);
245 # else
246   return fstype_to_string (fsp->f_type);
247 # endif
248 }
249
250 #endif /* MOUNTED_GETMNTINFO */
251
252 #ifdef MOUNTED_VMOUNT           /* AIX.  */
253 static char *
254 fstype_to_string (t)
255      int t;
256 {
257   struct vfs_ent *e;
258
259   e = getvfsbytype (t);
260   if (!e || !e->vfsent_name)
261     return "none";
262   else
263     return e->vfsent_name;
264 }
265 #endif /* MOUNTED_VMOUNT */
266
267 /* Return a list of the currently mounted filesystems, or NULL on error.
268    Add each entry to the tail of the list so that they stay in order.
269    If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
270    the returned list are valid.  Otherwise, they might not be.
271    If ALL_FS is zero, do not return entries for filesystems that
272    are automounter (dummy) entries.  */
273
274 struct mount_entry *
275 read_filesystem_list (need_fs_type, all_fs)
276      int need_fs_type, all_fs;
277 {
278   struct mount_entry *mount_list;
279   struct mount_entry *me;
280   struct mount_entry *mtail;
281
282   /* Start the list off with a dummy entry. */
283   me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
284   me->me_next = NULL;
285   mount_list = mtail = me;
286
287 #ifdef MOUNTED_LISTMNTENT
288   {
289     struct tabmntent *mntlist, *p;
290     struct mntent *mnt;
291     struct mount_entry *me;
292
293     /* the third and fourth arguments could be used to filter mounts,
294        but Crays doesn't seem to have any mounts that we want to
295        remove. Specifically, automount create normal NFS mounts.
296        */
297
298     if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0)
299       return NULL;
300     p = mntlist;
301     while(p){
302       mnt = p->ment;
303       me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry));
304       me->me_devname = xstrdup(mnt->mnt_fsname);
305       me->me_mountdir = xstrdup(mnt->mnt_dir);
306       me->me_type = xstrdup(mnt->mnt_type);
307       me->me_dev = -1;
308       me->me_next = NULL;
309       mtail->me_next = me;
310       mtail = me;
311       p = p->next;
312     }
313     freemntlist(mntlist);
314   }
315 #endif
316
317 #ifdef MOUNTED_GETMNTENT1       /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
318   {
319     struct mntent *mnt;
320     char *table = MOUNTED;
321     FILE *fp;
322     char *devopt;
323
324     fp = setmntent (table, "r");
325     if (fp == NULL)
326       return NULL;
327
328     while ((mnt = getmntent (fp)))
329       {
330         if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
331                         || !strcmp (mnt->mnt_type, "auto")))
332           continue;
333
334         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
335         me->me_devname = xstrdup (mnt->mnt_fsname);
336         me->me_mountdir = xstrdup (mnt->mnt_dir);
337         me->me_type = xstrdup (mnt->mnt_type);
338         devopt = strstr (mnt->mnt_opts, "dev=");
339         if (devopt)
340           {
341             if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
342               me->me_dev = xatoi (devopt + 6);
343             else
344               me->me_dev = xatoi (devopt + 4);
345           }
346         else
347           me->me_dev = (dev_t) -1;      /* Magic; means not known yet. */
348         me->me_next = NULL;
349
350         /* Add to the linked list. */
351         mtail->me_next = me;
352         mtail = me;
353       }
354
355     if (endmntent (fp) == 0)
356       return NULL;
357   }
358 #endif /* MOUNTED_GETMNTENT1. */
359
360 #ifdef MOUNTED_GETMNTINFO       /* 4.4BSD.  */
361   {
362     struct statfs *fsp;
363     int entries;
364
365     entries = getmntinfo (&fsp, MNT_NOWAIT);
366     if (entries < 0)
367       return NULL;
368     while (entries-- > 0)
369       {
370         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
371         me->me_devname = xstrdup (fsp->f_mntfromname);
372         me->me_mountdir = xstrdup (fsp->f_mntonname);
373         me->me_type = fsp_to_string (fsp);
374         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
375         me->me_next = NULL;
376
377         /* Add to the linked list. */
378         mtail->me_next = me;
379         mtail = me;
380         fsp++;
381       }
382   }
383 #endif /* MOUNTED_GETMNTINFO */
384
385 #ifdef MOUNTED_GETMNT           /* Ultrix.  */
386   {
387     int offset = 0;
388     int val;
389     struct fs_data fsd;
390
391     while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
392                           (char *) 0)) > 0)
393       {
394         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
395         me->me_devname = xstrdup (fsd.fd_req.devname);
396         me->me_mountdir = xstrdup (fsd.fd_req.path);
397         me->me_type = gt_names[fsd.fd_req.fstype];
398         me->me_dev = fsd.fd_req.dev;
399         me->me_next = NULL;
400
401         /* Add to the linked list. */
402         mtail->me_next = me;
403         mtail = me;
404       }
405     if (val < 0)
406       return NULL;
407   }
408 #endif /* MOUNTED_GETMNT. */
409
410 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
411   {
412     int numsys, counter, bufsize;
413     struct statfs *stats;
414
415     numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
416     if (numsys < 0)
417       return (NULL);
418
419     bufsize = (1 + numsys) * sizeof (struct statfs);
420     stats = (struct statfs *)xmalloc (bufsize);
421     numsys = getfsstat (stats, bufsize, MNT_WAIT);
422
423     if (numsys < 0)
424       {
425         free (stats);
426         return (NULL);
427       }
428
429     for (counter = 0; counter < numsys; counter++)
430       {
431         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
432         me->me_devname = xstrdup (stats[counter].f_mntfromname);
433         me->me_mountdir = xstrdup (stats[counter].f_mntonname);
434         me->me_type = mnt_names[stats[counter].f_type];
435         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
436         me->me_next = NULL;
437
438         /* Add to the linked list. */
439         mtail->me_next = me;
440         mtail = me;
441       }
442
443     free (stats);
444   }
445 #endif /* MOUNTED_GETFSSTAT */
446
447 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23].  */
448   {
449     struct mnttab mnt;
450     char *table = "/etc/mnttab";
451     FILE *fp;
452
453     fp = fopen (table, "r");
454     if (fp == NULL)
455       return NULL;
456
457     while (fread (&mnt, sizeof mnt, 1, fp) > 0)
458       {
459         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
460 # ifdef GETFSTYP                        /* SVR3.  */
461         me->me_devname = xstrdup (mnt.mt_dev);
462 # else
463         me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
464         strcpy (me->me_devname, "/dev/");
465         strcpy (me->me_devname + 5, mnt.mt_dev);
466 # endif
467         me->me_mountdir = xstrdup (mnt.mt_filsys);
468         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
469         me->me_type = "";
470 # ifdef GETFSTYP                        /* SVR3.  */
471         if (need_fs_type)
472           {
473             struct statfs fsd;
474             char typebuf[FSTYPSZ];
475
476             if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
477                 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
478               me->me_type = xstrdup (typebuf);
479           }
480 # endif
481         me->me_next = NULL;
482
483         /* Add to the linked list. */
484         mtail->me_next = me;
485         mtail = me;
486       }
487
488     if (fclose (fp) == EOF)
489       return NULL;
490   }
491 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP.  */
492
493 #ifdef MOUNTED_GETMNTTBL        /* DolphinOS goes it's own way */
494   {
495     struct mntent **mnttbl=getmnttbl(),**ent;
496     for (ent=mnttbl;*ent;ent++)
497       {
498         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
499         me->me_devname = xstrdup ( (*ent)->mt_resource);
500         me->me_mountdir = xstrdup( (*ent)->mt_directory);
501         me->me_type =  xstrdup ((*ent)->mt_fstype);
502         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
503         me->me_next = NULL;
504
505         /* Add to the linked list. */
506         mtail->me_next = me;
507         mtail = me;
508       }
509     endmnttbl();
510   }
511 #endif
512
513 #ifdef MOUNTED_GETMNTENT2       /* SVR4.  */
514   {
515     struct mnttab mnt;
516     char *table = MNTTAB;
517     FILE *fp;
518     int ret;
519
520     fp = fopen (table, "r");
521     if (fp == NULL)
522       return NULL;
523
524     while ((ret = getmntent (fp, &mnt)) == 0)
525       {
526         /* Don't show automounted filesystems twice on e.g., Solaris.  */
527         if (!all_fs && MNT_IGNORE (&mnt))
528           continue;
529
530         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
531         me->me_devname = xstrdup (mnt.mnt_special);
532         me->me_mountdir = xstrdup (mnt.mnt_mountp);
533         me->me_type = xstrdup (mnt.mnt_fstype);
534         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
535         me->me_next = NULL;
536
537         /* Add to the linked list. */
538         mtail->me_next = me;
539         mtail = me;
540       }
541
542     if (ret > 0)
543       return NULL;
544    if (fclose (fp) == EOF)
545       return NULL;
546   }
547 #endif /* MOUNTED_GETMNTENT2.  */
548
549 #ifdef MOUNTED_VMOUNT           /* AIX.  */
550   {
551     int bufsize;
552     char *entries, *thisent;
553     struct vmount *vmp;
554
555     /* Ask how many bytes to allocate for the mounted filesystem info.  */
556     mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
557     entries = xmalloc (bufsize);
558
559     /* Get the list of mounted filesystems.  */
560     mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
561
562     for (thisent = entries; thisent < entries + bufsize;
563          thisent += vmp->vmt_length)
564       {
565         vmp = (struct vmount *) thisent;
566         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
567         if (vmp->vmt_flags & MNT_REMOTE)
568           {
569             char *host, *path;
570
571             /* Prepend the remote pathname.  */
572             host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
573             path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
574             me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
575             strcpy (me->me_devname, host);
576             strcat (me->me_devname, ":");
577             strcat (me->me_devname, path);
578           }
579         else
580           {
581             me->me_devname = xstrdup (thisent +
582                                       vmp->vmt_data[VMT_OBJECT].vmt_off);
583           }
584         me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
585         me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
586         me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want.  */
587         me->me_next = NULL;
588
589         /* Add to the linked list. */
590         mtail->me_next = me;
591         mtail = me;
592       }
593     free (entries);
594   }
595 #endif /* MOUNTED_VMOUNT. */
596
597   /* Free the dummy head. */
598   me = mount_list;
599   mount_list = mount_list->me_next;
600   free (me);
601   return mount_list;
602 }