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