Line data Source code
1 : /* mountlist.c -- return a list of mounted file systems
2 :
3 : Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
4 : 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #include <config.h>
20 :
21 : #include "mountlist.h"
22 :
23 : #include <limits.h>
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <string.h>
27 :
28 : #include "xalloc.h"
29 :
30 : #include <errno.h>
31 :
32 : #include <fcntl.h>
33 :
34 : #include <unistd.h>
35 :
36 : #if HAVE_SYS_PARAM_H
37 : # include <sys/param.h>
38 : #endif
39 :
40 : #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
41 : # if HAVE_SYS_UCRED_H
42 : # include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
43 : NGROUPS is used as an array dimension in ucred.h */
44 : # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
45 : # endif
46 : # if HAVE_SYS_MOUNT_H
47 : # include <sys/mount.h>
48 : # endif
49 : # if HAVE_SYS_FS_TYPES_H
50 : # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
51 : # endif
52 : # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
53 : # define FS_TYPE(Ent) ((Ent).f_fstypename)
54 : # else
55 : # define FS_TYPE(Ent) mnt_names[(Ent).f_type]
56 : # endif
57 : #endif /* MOUNTED_GETFSSTAT */
58 :
59 : #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
60 : # include <mntent.h>
61 : # if !defined MOUNTED
62 : # if defined _PATH_MOUNTED /* GNU libc */
63 : # define MOUNTED _PATH_MOUNTED
64 : # endif
65 : # if defined MNT_MNTTAB /* HP-UX. */
66 : # define MOUNTED MNT_MNTTAB
67 : # endif
68 : # if defined MNTTABNAME /* Dynix. */
69 : # define MOUNTED MNTTABNAME
70 : # endif
71 : # endif
72 : #endif
73 :
74 : #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
75 : # include <sys/mount.h>
76 : #endif
77 :
78 : #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
79 : # include <sys/statvfs.h>
80 : #endif
81 :
82 : #ifdef MOUNTED_GETMNT /* Ultrix. */
83 : # include <sys/mount.h>
84 : # include <sys/fs_types.h>
85 : #endif
86 :
87 : #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
88 : # include <fs_info.h>
89 : # include <dirent.h>
90 : #endif
91 :
92 : #ifdef MOUNTED_FREAD /* SVR2. */
93 : # include <mnttab.h>
94 : #endif
95 :
96 : #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
97 : # include <mnttab.h>
98 : # include <sys/fstyp.h>
99 : # include <sys/statfs.h>
100 : #endif
101 :
102 : #ifdef MOUNTED_LISTMNTENT
103 : # include <mntent.h>
104 : #endif
105 :
106 : #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
107 : # include <sys/mnttab.h>
108 : #endif
109 :
110 : #ifdef MOUNTED_VMOUNT /* AIX. */
111 : # include <fshelp.h>
112 : # include <sys/vfs.h>
113 : #endif
114 :
115 : #ifdef DOLPHIN
116 : /* So special that it's not worth putting this in autoconf. */
117 : # undef MOUNTED_FREAD_FSTYP
118 : # define MOUNTED_GETMNTTBL
119 : #endif
120 :
121 : #if HAVE_SYS_MNTENT_H
122 : /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
123 : # include <sys/mntent.h>
124 : #endif
125 :
126 : #undef MNT_IGNORE
127 : #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
128 : # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
129 : #else
130 : # define MNT_IGNORE(M) 0
131 : #endif
132 :
133 : #if USE_UNLOCKED_IO
134 : # include "unlocked-io.h"
135 : #endif
136 :
137 : #ifndef SIZE_MAX
138 : # define SIZE_MAX ((size_t) -1)
139 : #endif
140 :
141 : /* The results of open() in this file are not used with fchdir,
142 : therefore save some unnecessary work in fchdir.c. */
143 : #undef open
144 : #undef close
145 :
146 : /* The results of opendir() in this file are not used with dirfd and fchdir,
147 : therefore save some unnecessary work in fchdir.c. */
148 : #undef opendir
149 : #undef closedir
150 :
151 : #ifndef ME_DUMMY
152 : # define ME_DUMMY(Fs_name, Fs_type) \
153 : (strcmp (Fs_type, "autofs") == 0 \
154 : || strcmp (Fs_type, "none") == 0 \
155 : || strcmp (Fs_type, "proc") == 0 \
156 : || strcmp (Fs_type, "subfs") == 0 \
157 : /* for NetBSD 3.0 */ \
158 : || strcmp (Fs_type, "kernfs") == 0 \
159 : /* for Irix 6.5 */ \
160 : || strcmp (Fs_type, "ignore") == 0)
161 : #endif
162 :
163 : #ifndef ME_REMOTE
164 : /* A file system is `remote' if its Fs_name contains a `:'
165 : or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */
166 : # define ME_REMOTE(Fs_name, Fs_type) \
167 : (strchr (Fs_name, ':') != NULL \
168 : || ((Fs_name)[0] == '/' \
169 : && (Fs_name)[1] == '/' \
170 : && (strcmp (Fs_type, "smbfs") == 0 \
171 : || strcmp (Fs_type, "cifs") == 0)))
172 : #endif
173 :
174 : #if MOUNTED_GETMNTINFO
175 :
176 : # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
177 : static char *
178 : fstype_to_string (short int t)
179 : {
180 : switch (t)
181 : {
182 : # ifdef MOUNT_PC
183 : case MOUNT_PC:
184 : return "pc";
185 : # endif
186 : # ifdef MOUNT_MFS
187 : case MOUNT_MFS:
188 : return "mfs";
189 : # endif
190 : # ifdef MOUNT_LO
191 : case MOUNT_LO:
192 : return "lo";
193 : # endif
194 : # ifdef MOUNT_TFS
195 : case MOUNT_TFS:
196 : return "tfs";
197 : # endif
198 : # ifdef MOUNT_TMP
199 : case MOUNT_TMP:
200 : return "tmp";
201 : # endif
202 : # ifdef MOUNT_UFS
203 : case MOUNT_UFS:
204 : return "ufs" ;
205 : # endif
206 : # ifdef MOUNT_NFS
207 : case MOUNT_NFS:
208 : return "nfs" ;
209 : # endif
210 : # ifdef MOUNT_MSDOS
211 : case MOUNT_MSDOS:
212 : return "msdos" ;
213 : # endif
214 : # ifdef MOUNT_LFS
215 : case MOUNT_LFS:
216 : return "lfs" ;
217 : # endif
218 : # ifdef MOUNT_LOFS
219 : case MOUNT_LOFS:
220 : return "lofs" ;
221 : # endif
222 : # ifdef MOUNT_FDESC
223 : case MOUNT_FDESC:
224 : return "fdesc" ;
225 : # endif
226 : # ifdef MOUNT_PORTAL
227 : case MOUNT_PORTAL:
228 : return "portal" ;
229 : # endif
230 : # ifdef MOUNT_NULL
231 : case MOUNT_NULL:
232 : return "null" ;
233 : # endif
234 : # ifdef MOUNT_UMAP
235 : case MOUNT_UMAP:
236 : return "umap" ;
237 : # endif
238 : # ifdef MOUNT_KERNFS
239 : case MOUNT_KERNFS:
240 : return "kernfs" ;
241 : # endif
242 : # ifdef MOUNT_PROCFS
243 : case MOUNT_PROCFS:
244 : return "procfs" ;
245 : # endif
246 : # ifdef MOUNT_AFS
247 : case MOUNT_AFS:
248 : return "afs" ;
249 : # endif
250 : # ifdef MOUNT_CD9660
251 : case MOUNT_CD9660:
252 : return "cd9660" ;
253 : # endif
254 : # ifdef MOUNT_UNION
255 : case MOUNT_UNION:
256 : return "union" ;
257 : # endif
258 : # ifdef MOUNT_DEVFS
259 : case MOUNT_DEVFS:
260 : return "devfs" ;
261 : # endif
262 : # ifdef MOUNT_EXT2FS
263 : case MOUNT_EXT2FS:
264 : return "ext2fs" ;
265 : # endif
266 : default:
267 : return "?";
268 : }
269 : }
270 : # endif
271 :
272 : static char *
273 : fsp_to_string (const struct statfs *fsp)
274 : {
275 : # if HAVE_STRUCT_STATFS_F_FSTYPENAME
276 : return (char *) (fsp->f_fstypename);
277 : # else
278 : return fstype_to_string (fsp->f_type);
279 : # endif
280 : }
281 :
282 : #endif /* MOUNTED_GETMNTINFO */
283 :
284 : #ifdef MOUNTED_VMOUNT /* AIX. */
285 : static char *
286 : fstype_to_string (int t)
287 : {
288 : struct vfs_ent *e;
289 :
290 : e = getvfsbytype (t);
291 : if (!e || !e->vfsent_name)
292 : return "none";
293 : else
294 : return e->vfsent_name;
295 : }
296 : #endif /* MOUNTED_VMOUNT */
297 :
298 :
299 : #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
300 :
301 : /* Return the device number from MOUNT_OPTIONS, if possible.
302 : Otherwise return (dev_t) -1. */
303 :
304 : static dev_t
305 1530 : dev_from_mount_options (char const *mount_options)
306 : {
307 : /* GNU/Linux allows file system implementations to define their own
308 : meaning for "dev=" mount options, so don't trust the meaning
309 : here. */
310 : # ifndef __linux__
311 :
312 : static char const dev_pattern[] = ",dev=";
313 : char const *devopt = strstr (mount_options, dev_pattern);
314 :
315 : if (devopt)
316 : {
317 : char const *optval = devopt + sizeof dev_pattern - 1;
318 : char *optvalend;
319 : unsigned long int dev;
320 : errno = 0;
321 : dev = strtoul (optval, &optvalend, 16);
322 : if (optval != optvalend
323 : && (*optvalend == '\0' || *optvalend == ',')
324 : && ! (dev == ULONG_MAX && errno == ERANGE)
325 : && dev == (dev_t) dev)
326 : return dev;
327 : }
328 :
329 : # endif
330 :
331 1530 : return -1;
332 : }
333 :
334 : #endif
335 :
336 : /* Return a list of the currently mounted file systems, or NULL on error.
337 : Add each entry to the tail of the list so that they stay in order.
338 : If NEED_FS_TYPE is true, ensure that the file system type fields in
339 : the returned list are valid. Otherwise, they might not be. */
340 :
341 : struct mount_entry *
342 45 : read_file_system_list (bool need_fs_type)
343 : {
344 : struct mount_entry *mount_list;
345 : struct mount_entry *me;
346 45 : struct mount_entry **mtail = &mount_list;
347 :
348 : #ifdef MOUNTED_LISTMNTENT
349 : {
350 : struct tabmntent *mntlist, *p;
351 : struct mntent *mnt;
352 : struct mount_entry *me;
353 :
354 : /* the third and fourth arguments could be used to filter mounts,
355 : but Crays doesn't seem to have any mounts that we want to
356 : remove. Specifically, automount create normal NFS mounts.
357 : */
358 :
359 : if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
360 : return NULL;
361 : for (p = mntlist; p; p = p->next) {
362 : mnt = p->ment;
363 : me = xmalloc (sizeof *me);
364 : me->me_devname = xstrdup (mnt->mnt_fsname);
365 : me->me_mountdir = xstrdup (mnt->mnt_dir);
366 : me->me_type = xstrdup (mnt->mnt_type);
367 : me->me_type_malloced = 1;
368 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
369 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
370 : me->me_dev = -1;
371 : *mtail = me;
372 : mtail = &me->me_next;
373 : }
374 : freemntlist (mntlist);
375 : }
376 : #endif
377 :
378 : #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
379 : {
380 : struct mntent *mnt;
381 45 : char *table = MOUNTED;
382 : FILE *fp;
383 :
384 45 : fp = setmntent (table, "r");
385 45 : if (fp == NULL)
386 0 : return NULL;
387 :
388 1620 : while ((mnt = getmntent (fp)))
389 : {
390 1530 : me = xmalloc (sizeof *me);
391 1530 : me->me_devname = xstrdup (mnt->mnt_fsname);
392 1530 : me->me_mountdir = xstrdup (mnt->mnt_dir);
393 1530 : me->me_type = xstrdup (mnt->mnt_type);
394 1530 : me->me_type_malloced = 1;
395 1530 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
396 1530 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
397 1530 : me->me_dev = dev_from_mount_options (mnt->mnt_opts);
398 :
399 : /* Add to the linked list. */
400 1530 : *mtail = me;
401 1530 : mtail = &me->me_next;
402 : }
403 :
404 45 : if (endmntent (fp) == 0)
405 0 : goto free_then_fail;
406 : }
407 : #endif /* MOUNTED_GETMNTENT1. */
408 :
409 : #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
410 : {
411 : struct statfs *fsp;
412 : int entries;
413 :
414 : entries = getmntinfo (&fsp, MNT_NOWAIT);
415 : if (entries < 0)
416 : return NULL;
417 : for (; entries-- > 0; fsp++)
418 : {
419 : char *fs_type = fsp_to_string (fsp);
420 :
421 : me = xmalloc (sizeof *me);
422 : me->me_devname = xstrdup (fsp->f_mntfromname);
423 : me->me_mountdir = xstrdup (fsp->f_mntonname);
424 : me->me_type = fs_type;
425 : me->me_type_malloced = 0;
426 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
427 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
428 : me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
429 :
430 : /* Add to the linked list. */
431 : *mtail = me;
432 : mtail = &me->me_next;
433 : }
434 : }
435 : #endif /* MOUNTED_GETMNTINFO */
436 :
437 : #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
438 : {
439 : struct statvfs *fsp;
440 : int entries;
441 :
442 : entries = getmntinfo (&fsp, MNT_NOWAIT);
443 : if (entries < 0)
444 : return NULL;
445 : for (; entries-- > 0; fsp++)
446 : {
447 : me = xmalloc (sizeof *me);
448 : me->me_devname = xstrdup (fsp->f_mntfromname);
449 : me->me_mountdir = xstrdup (fsp->f_mntonname);
450 : me->me_type = xstrdup (fsp->f_fstypename);
451 : me->me_type_malloced = 1;
452 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
453 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
454 : me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
455 :
456 : /* Add to the linked list. */
457 : *mtail = me;
458 : mtail = &me->me_next;
459 : }
460 : }
461 : #endif /* MOUNTED_GETMNTINFO2 */
462 :
463 : #ifdef MOUNTED_GETMNT /* Ultrix. */
464 : {
465 : int offset = 0;
466 : int val;
467 : struct fs_data fsd;
468 :
469 : while (errno = 0,
470 : 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
471 : (char *) 0)))
472 : {
473 : me = xmalloc (sizeof *me);
474 : me->me_devname = xstrdup (fsd.fd_req.devname);
475 : me->me_mountdir = xstrdup (fsd.fd_req.path);
476 : me->me_type = gt_names[fsd.fd_req.fstype];
477 : me->me_type_malloced = 0;
478 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
479 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
480 : me->me_dev = fsd.fd_req.dev;
481 :
482 : /* Add to the linked list. */
483 : *mtail = me;
484 : mtail = &me->me_next;
485 : }
486 : if (val < 0)
487 : goto free_then_fail;
488 : }
489 : #endif /* MOUNTED_GETMNT. */
490 :
491 : #if defined MOUNTED_FS_STAT_DEV /* BeOS */
492 : {
493 : /* The next_dev() and fs_stat_dev() system calls give the list of
494 : all file systems, including the information returned by statvfs()
495 : (fs type, total blocks, free blocks etc.), but without the mount
496 : point. But on BeOS all file systems except / are mounted in the
497 : rootfs, directly under /.
498 : The directory name of the mount point is often, but not always,
499 : identical to the volume name of the device.
500 : We therefore get the list of subdirectories of /, and the list
501 : of all file systems, and match the two lists. */
502 :
503 : DIR *dirp;
504 : struct rootdir_entry
505 : {
506 : char *name;
507 : dev_t dev;
508 : ino_t ino;
509 : struct rootdir_entry *next;
510 : };
511 : struct rootdir_entry *rootdir_list;
512 : struct rootdir_entry **rootdir_tail;
513 : int32 pos;
514 : dev_t dev;
515 : fs_info fi;
516 :
517 : /* All volumes are mounted in the rootfs, directly under /. */
518 : rootdir_list = NULL;
519 : rootdir_tail = &rootdir_list;
520 : dirp = opendir ("/");
521 : if (dirp)
522 : {
523 : struct dirent *d;
524 :
525 : while ((d = readdir (dirp)) != NULL)
526 : {
527 : char *name;
528 : struct stat statbuf;
529 :
530 : if (strcmp (d->d_name, "..") == 0)
531 : continue;
532 :
533 : if (strcmp (d->d_name, ".") == 0)
534 : name = xstrdup ("/");
535 : else
536 : {
537 : name = xmalloc (1 + strlen (d->d_name) + 1);
538 : name[0] = '/';
539 : strcpy (name + 1, d->d_name);
540 : }
541 :
542 : if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
543 : {
544 : struct rootdir_entry *re = xmalloc (sizeof *re);
545 : re->name = name;
546 : re->dev = statbuf.st_dev;
547 : re->ino = statbuf.st_ino;
548 :
549 : /* Add to the linked list. */
550 : *rootdir_tail = re;
551 : rootdir_tail = &re->next;
552 : }
553 : else
554 : free (name);
555 : }
556 : closedir (dirp);
557 : }
558 : *rootdir_tail = NULL;
559 :
560 : for (pos = 0; (dev = next_dev (&pos)) >= 0; )
561 : if (fs_stat_dev (dev, &fi) >= 0)
562 : {
563 : /* Note: fi.dev == dev. */
564 : struct rootdir_entry *re;
565 :
566 : for (re = rootdir_list; re; re = re->next)
567 : if (re->dev == fi.dev && re->ino == fi.root)
568 : break;
569 :
570 : me = xmalloc (sizeof *me);
571 : me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
572 : me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
573 : me->me_type = xstrdup (fi.fsh_name);
574 : me->me_type_malloced = 1;
575 : me->me_dev = fi.dev;
576 : me->me_dummy = 0;
577 : me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
578 :
579 : /* Add to the linked list. */
580 : *mtail = me;
581 : mtail = &me->me_next;
582 : }
583 : *mtail = NULL;
584 :
585 : while (rootdir_list != NULL)
586 : {
587 : struct rootdir_entry *re = rootdir_list;
588 : rootdir_list = re->next;
589 : free (re->name);
590 : free (re);
591 : }
592 : }
593 : #endif /* MOUNTED_FS_STAT_DEV */
594 :
595 : #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
596 : {
597 : int numsys, counter;
598 : size_t bufsize;
599 : struct statfs *stats;
600 :
601 : numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
602 : if (numsys < 0)
603 : return (NULL);
604 : if (SIZE_MAX / sizeof *stats <= numsys)
605 : xalloc_die ();
606 :
607 : bufsize = (1 + numsys) * sizeof *stats;
608 : stats = xmalloc (bufsize);
609 : numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
610 :
611 : if (numsys < 0)
612 : {
613 : free (stats);
614 : return (NULL);
615 : }
616 :
617 : for (counter = 0; counter < numsys; counter++)
618 : {
619 : me = xmalloc (sizeof *me);
620 : me->me_devname = xstrdup (stats[counter].f_mntfromname);
621 : me->me_mountdir = xstrdup (stats[counter].f_mntonname);
622 : me->me_type = xstrdup (FS_TYPE (stats[counter]));
623 : me->me_type_malloced = 1;
624 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
625 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
626 : me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
627 :
628 : /* Add to the linked list. */
629 : *mtail = me;
630 : mtail = &me->me_next;
631 : }
632 :
633 : free (stats);
634 : }
635 : #endif /* MOUNTED_GETFSSTAT */
636 :
637 : #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
638 : {
639 : struct mnttab mnt;
640 : char *table = "/etc/mnttab";
641 : FILE *fp;
642 :
643 : fp = fopen (table, "r");
644 : if (fp == NULL)
645 : return NULL;
646 :
647 : while (fread (&mnt, sizeof mnt, 1, fp) > 0)
648 : {
649 : me = xmalloc (sizeof *me);
650 : # ifdef GETFSTYP /* SVR3. */
651 : me->me_devname = xstrdup (mnt.mt_dev);
652 : # else
653 : me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
654 : strcpy (me->me_devname, "/dev/");
655 : strcpy (me->me_devname + 5, mnt.mt_dev);
656 : # endif
657 : me->me_mountdir = xstrdup (mnt.mt_filsys);
658 : me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
659 : me->me_type = "";
660 : me->me_type_malloced = 0;
661 : # ifdef GETFSTYP /* SVR3. */
662 : if (need_fs_type)
663 : {
664 : struct statfs fsd;
665 : char typebuf[FSTYPSZ];
666 :
667 : if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
668 : && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
669 : {
670 : me->me_type = xstrdup (typebuf);
671 : me->me_type_malloced = 1;
672 : }
673 : }
674 : # endif
675 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
676 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
677 :
678 : /* Add to the linked list. */
679 : *mtail = me;
680 : mtail = &me->me_next;
681 : }
682 :
683 : if (ferror (fp))
684 : {
685 : /* The last fread() call must have failed. */
686 : int saved_errno = errno;
687 : fclose (fp);
688 : errno = saved_errno;
689 : goto free_then_fail;
690 : }
691 :
692 : if (fclose (fp) == EOF)
693 : goto free_then_fail;
694 : }
695 : #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
696 :
697 : #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */
698 : {
699 : struct mntent **mnttbl = getmnttbl (), **ent;
700 : for (ent=mnttbl;*ent;ent++)
701 : {
702 : me = xmalloc (sizeof *me);
703 : me->me_devname = xstrdup ( (*ent)->mt_resource);
704 : me->me_mountdir = xstrdup ( (*ent)->mt_directory);
705 : me->me_type = xstrdup ((*ent)->mt_fstype);
706 : me->me_type_malloced = 1;
707 : me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
708 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
709 : me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
710 :
711 : /* Add to the linked list. */
712 : *mtail = me;
713 : mtail = &me->me_next;
714 : }
715 : endmnttbl ();
716 : }
717 : #endif
718 :
719 : #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
720 : {
721 : struct mnttab mnt;
722 : char *table = MNTTAB;
723 : FILE *fp;
724 : int ret;
725 : int lockfd = -1;
726 :
727 : # if defined F_RDLCK && defined F_SETLKW
728 : /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
729 : e.g. Solaris 2.6. If the SVR4 folks ever define a macro
730 : for this file name, we should use their macro name instead.
731 : (Why not just lock MNTTAB directly? We don't know.) */
732 : # ifndef MNTTAB_LOCK
733 : # define MNTTAB_LOCK "/etc/.mnttab.lock"
734 : # endif
735 : lockfd = open (MNTTAB_LOCK, O_RDONLY);
736 : if (0 <= lockfd)
737 : {
738 : struct flock flock;
739 : flock.l_type = F_RDLCK;
740 : flock.l_whence = SEEK_SET;
741 : flock.l_start = 0;
742 : flock.l_len = 0;
743 : while (fcntl (lockfd, F_SETLKW, &flock) == -1)
744 : if (errno != EINTR)
745 : {
746 : int saved_errno = errno;
747 : close (lockfd);
748 : errno = saved_errno;
749 : return NULL;
750 : }
751 : }
752 : else if (errno != ENOENT)
753 : return NULL;
754 : # endif
755 :
756 : errno = 0;
757 : fp = fopen (table, "r");
758 : if (fp == NULL)
759 : ret = errno;
760 : else
761 : {
762 : while ((ret = getmntent (fp, &mnt)) == 0)
763 : {
764 : me = xmalloc (sizeof *me);
765 : me->me_devname = xstrdup (mnt.mnt_special);
766 : me->me_mountdir = xstrdup (mnt.mnt_mountp);
767 : me->me_type = xstrdup (mnt.mnt_fstype);
768 : me->me_type_malloced = 1;
769 : me->me_dummy = MNT_IGNORE (&mnt) != 0;
770 : me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
771 : me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
772 :
773 : /* Add to the linked list. */
774 : *mtail = me;
775 : mtail = &me->me_next;
776 : }
777 :
778 : ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
779 : }
780 :
781 : if (0 <= lockfd && close (lockfd) != 0)
782 : ret = errno;
783 :
784 : if (0 <= ret)
785 : {
786 : errno = ret;
787 : goto free_then_fail;
788 : }
789 : }
790 : #endif /* MOUNTED_GETMNTENT2. */
791 :
792 : #ifdef MOUNTED_VMOUNT /* AIX. */
793 : {
794 : int bufsize;
795 : char *entries, *thisent;
796 : struct vmount *vmp;
797 : int n_entries;
798 : int i;
799 :
800 : /* Ask how many bytes to allocate for the mounted file system info. */
801 : if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
802 : return NULL;
803 : entries = xmalloc (bufsize);
804 :
805 : /* Get the list of mounted file systems. */
806 : n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
807 : if (n_entries < 0)
808 : {
809 : int saved_errno = errno;
810 : free (entries);
811 : errno = saved_errno;
812 : return NULL;
813 : }
814 :
815 : for (i = 0, thisent = entries;
816 : i < n_entries;
817 : i++, thisent += vmp->vmt_length)
818 : {
819 : char *options, *ignore;
820 :
821 : vmp = (struct vmount *) thisent;
822 : me = xmalloc (sizeof *me);
823 : if (vmp->vmt_flags & MNT_REMOTE)
824 : {
825 : char *host, *dir;
826 :
827 : me->me_remote = 1;
828 : /* Prepend the remote dirname. */
829 : host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
830 : dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
831 : me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
832 : strcpy (me->me_devname, host);
833 : strcat (me->me_devname, ":");
834 : strcat (me->me_devname, dir);
835 : }
836 : else
837 : {
838 : me->me_remote = 0;
839 : me->me_devname = xstrdup (thisent +
840 : vmp->vmt_data[VMT_OBJECT].vmt_off);
841 : }
842 : me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
843 : me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
844 : me->me_type_malloced = 1;
845 : options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
846 : ignore = strstr (options, "ignore");
847 : me->me_dummy = (ignore
848 : && (ignore == options || ignore[-1] == ',')
849 : && (ignore[sizeof "ignore" - 1] == ','
850 : || ignore[sizeof "ignore" - 1] == '\0'));
851 : me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
852 :
853 : /* Add to the linked list. */
854 : *mtail = me;
855 : mtail = &me->me_next;
856 : }
857 : free (entries);
858 : }
859 : #endif /* MOUNTED_VMOUNT. */
860 :
861 45 : *mtail = NULL;
862 45 : return mount_list;
863 :
864 :
865 0 : free_then_fail:
866 : {
867 0 : int saved_errno = errno;
868 0 : *mtail = NULL;
869 :
870 0 : while (mount_list)
871 : {
872 0 : me = mount_list->me_next;
873 0 : free (mount_list->me_devname);
874 0 : free (mount_list->me_mountdir);
875 0 : if (mount_list->me_type_malloced)
876 0 : free (mount_list->me_type);
877 0 : free (mount_list);
878 0 : mount_list = me;
879 : }
880 :
881 0 : errno = saved_errno;
882 0 : return NULL;
883 : }
884 : }
|