(read_filesystem_list): Cast -1 to dev_t before assignment.
[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
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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_GETMNTENT2       /* SVR4.  */
84 #include <sys/mnttab.h>
85 #endif
86
87 #ifdef MOUNTED_VMOUNT           /* AIX.  */
88 #include <fshelp.h>
89 #include <sys/vfs.h>
90 #endif
91
92 #ifdef DOLPHIN
93 /* So special that it's not worth putting this in autoconf.  */
94 #undef MOUNTED_FREAD_FSTYP
95 #define MOUNTED_GETMNTTBL
96 #endif
97
98 #ifdef MOUNTED_GETMNTENT1       /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
99 /* Return the value of the hexadecimal number represented by CP.
100    No prefix (like '0x') or suffix (like 'h') is expected to be
101    part of CP. */
102
103 static int
104 xatoi (cp)
105      char *cp;
106 {
107   int val;
108
109   val = 0;
110   while (*cp)
111     {
112       if (*cp >= 'a' && *cp <= 'f')
113         val = val * 16 + *cp - 'a' + 10;
114       else if (*cp >= 'A' && *cp <= 'F')
115         val = val * 16 + *cp - 'A' + 10;
116       else if (*cp >= '0' && *cp <= '9')
117         val = val * 16 + *cp - '0';
118       else
119         break;
120       cp++;
121     }
122   return val;
123 }
124 #endif /* MOUNTED_GETMNTENT1.  */
125
126 #if defined (MOUNTED_GETMNTINFO) && !defined (__NetBSD__)
127 static char *
128 fstype_to_string (t)
129      short t;
130 {
131   switch (t)
132     {
133     case MOUNT_UFS:
134       return "ufs";
135     case MOUNT_NFS:
136       return "nfs";
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     default:
158       return "?";
159     }
160 }
161 #endif /* MOUNTED_GETMNTINFO */
162
163 #ifdef MOUNTED_VMOUNT           /* AIX.  */
164 static char *
165 fstype_to_string (t)
166      int t;
167 {
168   struct vfs_ent *e;
169
170   e = getvfsbytype (t);
171   if (!e || !e->vfsent_name)
172     return "none";
173   else
174     return e->vfsent_name;
175 }
176 #endif /* MOUNTED_VMOUNT */
177
178 /* Return a list of the currently mounted filesystems, or NULL on error.
179    Add each entry to the tail of the list so that they stay in order.
180    If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
181    the returned list are valid.  Otherwise, they might not be.
182    If ALL_FS is zero, do not return entries for filesystems that
183    are automounter (dummy) entries.  */
184
185 struct mount_entry *
186 read_filesystem_list (need_fs_type, all_fs)
187      int need_fs_type, all_fs;
188 {
189   struct mount_entry *mount_list;
190   struct mount_entry *me;
191   struct mount_entry *mtail;
192
193   /* Start the list off with a dummy entry. */
194   me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
195   me->me_next = NULL;
196   mount_list = mtail = me;
197
198 #ifdef MOUNTED_GETMNTENT1       /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
199   {
200     struct mntent *mnt;
201     char *table = MOUNTED;
202     FILE *fp;
203     char *devopt;
204
205     fp = setmntent (table, "r");
206     if (fp == NULL)
207       return NULL;
208
209     while ((mnt = getmntent (fp)))
210       {
211         if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
212                         || !strcmp (mnt->mnt_type, "auto")))
213           continue;
214
215         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
216         me->me_devname = xstrdup (mnt->mnt_fsname);
217         me->me_mountdir = xstrdup (mnt->mnt_dir);
218         me->me_type = xstrdup (mnt->mnt_type);
219         devopt = strstr (mnt->mnt_opts, "dev=");
220         if (devopt)
221           {
222             if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
223               me->me_dev = xatoi (devopt + 6);
224             else
225               me->me_dev = xatoi (devopt + 4);
226           }
227         else
228           me->me_dev = (dev_t) -1;      /* Magic; means not known yet. */
229         me->me_next = NULL;
230
231         /* Add to the linked list. */
232         mtail->me_next = me;
233         mtail = me;
234       }
235
236     if (endmntent (fp) == 0)
237       return NULL;
238   }
239 #endif /* MOUNTED_GETMNTENT1. */
240
241 #ifdef MOUNTED_GETMNTINFO       /* 4.4BSD.  */
242   {
243     struct statfs *fsp;
244     int entries;
245
246     entries = getmntinfo (&fsp, MNT_NOWAIT);
247     if (entries < 0)
248       return NULL;
249     while (entries-- > 0)
250       {
251         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
252         me->me_devname = xstrdup (fsp->f_mntfromname);
253         me->me_mountdir = xstrdup (fsp->f_mntonname);
254 #ifdef __NetBSD__
255         me->me_type = xstrdup (fsp->f_fstypename);
256 #else
257         me->me_type = fstype_to_string (fsp->f_type);
258 #endif
259         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
260         me->me_next = NULL;
261
262         /* Add to the linked list. */
263         mtail->me_next = me;
264         mtail = me;
265         fsp++;
266       }
267   }
268 #endif /* MOUNTED_GETMNTINFO */
269
270 #ifdef MOUNTED_GETMNT           /* Ultrix.  */
271   {
272     int offset = 0;
273     int val;
274     struct fs_data fsd;
275
276     while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
277                           (char *) 0)) > 0)
278       {
279         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
280         me->me_devname = xstrdup (fsd.fd_req.devname);
281         me->me_mountdir = xstrdup (fsd.fd_req.path);
282         me->me_type = gt_names[fsd.fd_req.fstype];
283         me->me_dev = fsd.fd_req.dev;
284         me->me_next = NULL;
285
286         /* Add to the linked list. */
287         mtail->me_next = me;
288         mtail = me;
289       }
290     if (val < 0)
291       return NULL;
292   }
293 #endif /* MOUNTED_GETMNT. */
294
295 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
296   {
297     int numsys, counter, bufsize;
298     struct statfs *stats;
299
300     numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT);
301     if (numsys < 0)
302       return (NULL);
303
304     bufsize = (1 + numsys) * sizeof (struct statfs);
305     stats = (struct statfs *)xmalloc (bufsize);
306     numsys = getfsstat (stats, bufsize, MNT_WAIT);
307
308     if (numsys < 0)
309       {
310         free (stats);
311         return (NULL);
312       }
313
314     for (counter = 0; counter < numsys; counter++)
315       {
316         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
317         me->me_devname = xstrdup (stats[counter].f_mntfromname);
318         me->me_mountdir = xstrdup (stats[counter].f_mntonname);
319         me->me_type = mnt_names[stats[counter].f_type];
320         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
321         me->me_next = NULL;
322
323         /* Add to the linked list. */
324         mtail->me_next = me;
325         mtail = me;
326       }
327
328     free (stats);
329   }
330 #endif /* MOUNTED_GETFSSTAT */
331
332 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23].  */
333   {
334     struct mnttab mnt;
335     char *table = "/etc/mnttab";
336     FILE *fp;
337
338     fp = fopen (table, "r");
339     if (fp == NULL)
340       return NULL;
341
342     while (fread (&mnt, sizeof mnt, 1, fp) > 0)
343       {
344         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
345 #ifdef GETFSTYP                 /* SVR3.  */
346         me->me_devname = xstrdup (mnt.mt_dev);
347 #else
348         me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
349         strcpy (me->me_devname, "/dev/");
350         strcpy (me->me_devname + 5, mnt.mt_dev);
351 #endif
352         me->me_mountdir = xstrdup (mnt.mt_filsys);
353         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
354         me->me_type = "";
355 #ifdef GETFSTYP                 /* SVR3.  */
356         if (need_fs_type)
357           {
358             struct statfs fsd;
359             char typebuf[FSTYPSZ];
360
361             if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
362                 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
363               me->me_type = xstrdup (typebuf);
364           }
365 #endif
366         me->me_next = NULL;
367
368         /* Add to the linked list. */
369         mtail->me_next = me;
370         mtail = me;
371       }
372
373     if (fclose (fp) == EOF)
374       return NULL;
375   }
376 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP.  */
377
378 #ifdef MOUNTED_GETMNTTBL        /* DolphinOS goes it's own way */
379   {
380     struct mntent **mnttbl=getmnttbl(),**ent;
381     for (ent=mnttbl;*ent;ent++)
382       {
383         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
384         me->me_devname = xstrdup ( (*ent)->mt_resource);
385         me->me_mountdir = xstrdup( (*ent)->mt_directory);
386         me->me_type =  xstrdup ((*ent)->mt_fstype);
387         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
388         me->me_next = NULL;
389
390         /* Add to the linked list. */
391         mtail->me_next = me;
392         mtail = me;
393       }
394     endmnttbl();
395   }
396 #endif
397
398 #ifdef MOUNTED_GETMNTENT2       /* SVR4.  */
399   {
400     struct mnttab mnt;
401     char *table = MNTTAB;
402     FILE *fp;
403     int ret;
404
405     fp = fopen (table, "r");
406     if (fp == NULL)
407       return NULL;
408
409     while ((ret = getmntent (fp, &mnt)) == 0)
410       {
411         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
412         me->me_devname = xstrdup (mnt.mnt_special);
413         me->me_mountdir = xstrdup (mnt.mnt_mountp);
414         me->me_type = xstrdup (mnt.mnt_fstype);
415         me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
416         me->me_next = NULL;
417
418         /* Add to the linked list. */
419         mtail->me_next = me;
420         mtail = me;
421       }
422
423     if (ret > 0)
424       return NULL;
425    if (fclose (fp) == EOF)
426       return NULL;
427   }
428 #endif /* MOUNTED_GETMNTENT2.  */
429
430 #ifdef MOUNTED_VMOUNT           /* AIX.  */
431   {
432     int bufsize;
433     char *entries, *thisent;
434     struct vmount *vmp;
435
436     /* Ask how many bytes to allocate for the mounted filesystem info.  */
437     mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
438     entries = xmalloc (bufsize);
439
440     /* Get the list of mounted filesystems.  */
441     mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
442
443     for (thisent = entries; thisent < entries + bufsize;
444          thisent += vmp->vmt_length)
445       {
446         vmp = (struct vmount *) thisent;
447         me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
448         if (vmp->vmt_flags & MNT_REMOTE)
449           {
450             char *host, *path;
451
452             /* Prepend the remote pathname.  */
453             host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
454             path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
455             me->me_devname = xmalloc (strlen (host) + strlen (path) + 2);
456             strcpy (me->me_devname, host);
457             strcat (me->me_devname, ":");
458             strcat (me->me_devname, path);
459           }
460         else
461           {
462             me->me_devname = xstrdup (thisent +
463                                       vmp->vmt_data[VMT_OBJECT].vmt_off);
464           }
465         me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
466         me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
467         me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want.  */
468         me->me_next = NULL;
469
470         /* Add to the linked list. */
471         mtail->me_next = me;
472         mtail = me;
473       }
474     free (entries);
475   }
476 #endif /* MOUNTED_VMOUNT. */
477
478   /* Free the dummy head. */
479   me = mount_list;
480   mount_list = mount_list->me_next;
481   free (me);
482   return mount_list;
483 }