1999-09-09 Federico Mena Quintero <federico@redhat.com>
[midnight-commander.git] / src / mountlist.c
blob9871ba25d27ae4fb8fe3fb749c49696a4b643af4
1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
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.
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.
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. */
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 #ifndef NO_INFOMOUNT
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include "mountlist.h"
27 #ifdef STDC_HEADERS
28 #include <stdlib.h>
29 #else
30 void free (void *ptr);
31 #endif
32 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
33 #include <string.h>
34 #else
35 #include <strings.h>
36 #endif
38 #ifdef HAVE_SYS_PARAM_H
39 #include <sys/param.h>
40 #endif
42 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
43 #include <sys/mount.h>
44 #include <sys/fs_types.h>
45 #endif /* MOUNTED_GETFSSTAT */
47 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
48 #include <mntent.h>
49 #if !defined(MOUNTED)
50 #if defined(MNT_MNTTAB) /* HP-UX. */
51 #define MOUNTED MNT_MNTTAB
52 #endif
53 #if defined(MNTTABNAME) /* Dynix. */
54 #define MOUNTED MNTTABNAME
55 #endif
56 #endif
57 #endif
59 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
60 #include <sys/mount.h>
61 #endif
63 #ifdef MOUNTED_GETMNT /* Ultrix. */
64 #include <sys/mount.h>
65 #include <sys/fs_types.h>
66 #endif
68 #ifdef MOUNTED_FREAD /* SVR2. */
69 #include <mnttab.h>
70 #endif
72 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
73 #include <mnttab.h>
74 #include <sys/fstyp.h>
75 #include <sys/statfs.h>
76 #endif
78 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
79 #include <sys/mnttab.h>
80 #endif
82 #ifdef MOUNTED_VMOUNT /* AIX. */
83 #include <fshelp.h>
84 #include <sys/vfs.h>
85 #endif
87 /* 4.4BSD2 derived systems */
88 #if defined(__bsdi__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
89 # ifndef MOUNT_UFS
90 # define xBSD
91 # endif
92 #endif
94 /* void error (void); FIXME -- needed? */
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
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. */
107 static int xatoi (char *cp)
109 int val;
111 val = 0;
112 while (*cp) {
113 if (*cp >= 'a' && *cp <= 'f')
114 val = val * 16 + *cp - 'a' + 10;
115 else if (*cp >= 'A' && *cp <= 'F')
116 val = val * 16 + *cp - 'A' + 10;
117 else if (*cp >= '0' && *cp <= '9')
118 val = val * 16 + *cp - '0';
119 else
120 break;
121 cp++;
123 return val;
125 #endif /* MOUNTED_GETMNTENT1. */
127 #if defined (MOUNTED_GETMNTINFO) && !defined (xBSD)
128 static char *fstype_to_string (short t)
130 switch (t) {
131 case MOUNT_UFS:
132 return "ufs";
133 case MOUNT_NFS:
134 return "nfs";
135 #ifdef MOUNT_PC
136 case MOUNT_PC:
137 return "pc";
138 #endif
139 #ifdef MOUNT_MFS
140 case MOUNT_MFS:
141 return "mfs";
142 #endif
143 #ifdef MOUNT_LO
144 case MOUNT_LO:
145 return "lo";
146 #endif
147 #ifdef MOUNT_TFS
148 case MOUNT_TFS:
149 return "tfs";
150 #endif
151 #ifdef MOUNT_TMP
152 case MOUNT_TMP:
153 return "tmp";
154 #endif
155 default:
156 return "?";
159 #endif /* MOUNTED_GETMNTINFO */
161 #ifdef MOUNTED_VMOUNT /* AIX. */
162 static char *fstype_to_string (int t)
164 struct vfs_ent *e;
166 e = getvfsbytype (t);
167 if (!e || !e->vfsent_name)
168 return "none";
169 else
170 return e->vfsent_name;
172 #endif /* MOUNTED_VMOUNT */
174 /* Return a list of the currently mounted filesystems, or NULL on error.
175 Add each entry to the tail of the list so that they stay in order.
176 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
177 the returned list are valid. Otherwise, they might not be.
178 If ALL_FS is zero, do not return entries for filesystems that
179 are automounter (dummy) entries. */
181 struct mount_entry *read_filesystem_list (int need_fs_type, int all_fs)
183 struct mount_entry *mount_list;
184 struct mount_entry *me;
185 struct mount_entry *mtail;
187 /* Start the list off with a dummy entry. */
188 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
189 me->me_next = NULL;
190 mount_list = mtail = me;
192 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
194 struct mntent *mnt;
195 char *table = MOUNTED;
196 FILE *fp;
197 char *devopt;
199 fp = setmntent (table, "r");
200 if (fp == NULL)
201 return NULL;
203 while ((mnt = getmntent (fp))) {
204 if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
205 || !strcmp (mnt->mnt_type, "auto")))
206 continue;
208 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
209 me->me_devname = strdup (mnt->mnt_fsname);
210 me->me_mountdir = strdup (mnt->mnt_dir);
211 me->me_type = strdup (mnt->mnt_type);
212 devopt = strstr (mnt->mnt_opts, "dev=");
213 if (devopt) {
214 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
215 me->me_dev = xatoi (devopt + 6);
216 else
217 me->me_dev = xatoi (devopt + 4);
218 } else
219 me->me_dev = -1; /* Magic; means not known yet. */
220 me->me_next = NULL;
222 /* Add to the linked list. */
223 mtail->me_next = me;
224 mtail = me;
227 if (endmntent (fp) == 0)
228 return NULL;
230 #endif /* MOUNTED_GETMNTENT1. */
232 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
234 struct statfs *fsp;
235 int entries;
237 entries = getmntinfo (&fsp, MNT_NOWAIT);
238 if (entries < 0)
239 return NULL;
240 while (entries-- > 0) {
241 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
242 me->me_devname = strdup (fsp->f_mntfromname);
243 me->me_mountdir = strdup (fsp->f_mntonname);
244 #ifdef xBSD
245 me->me_type = strdup (fsp->f_fstypename);
246 #else
247 me->me_type = fstype_to_string (fsp->f_type);
248 #endif
249 me->me_dev = -1; /* Magic; means not known yet. */
250 me->me_next = NULL;
252 /* Add to the linked list. */
253 mtail->me_next = me;
254 mtail = me;
255 fsp++;
258 #endif /* MOUNTED_GETMNTINFO */
260 #ifdef MOUNTED_GETMNT /* Ultrix. */
262 int offset = 0;
263 int val;
264 struct fs_data fsd;
266 while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
267 (char *) 0)) > 0) {
268 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
269 me->me_devname = strdup (fsd.fd_req.devname);
270 me->me_mountdir = strdup (fsd.fd_req.path);
271 me->me_type = gt_names[fsd.fd_req.fstype];
272 me->me_dev = fsd.fd_req.dev;
273 me->me_next = NULL;
275 /* Add to the linked list. */
276 mtail->me_next = me;
277 mtail = me;
279 if (val < 0)
280 return NULL;
282 #endif /* MOUNTED_GETMNT. */
284 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
286 int numsys, counter, bufsize;
287 struct statfs *stats;
289 numsys = getfsstat ((struct statfs *) 0, 0L, MNT_WAIT);
290 if (numsys < 0)
291 return (NULL);
293 bufsize = (1 + numsys) * sizeof (struct statfs);
294 stats = (struct statfs *) malloc (bufsize);
295 numsys = getfsstat (stats, bufsize, MNT_WAIT);
297 if (numsys < 0) {
298 free (stats);
299 return (NULL);
301 for (counter = 0; counter < numsys; counter++) {
302 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
303 me->me_devname = strdup (stats[counter].f_mntfromname);
304 me->me_mountdir = strdup (stats[counter].f_mntonname);
305 me->me_type = mnt_names[stats[counter].f_type];
306 me->me_dev = -1; /* Magic; means not known yet. */
307 me->me_next = NULL;
309 /* Add to the linked list. */
310 mtail->me_next = me;
311 mtail = me;
314 free (stats);
316 #endif /* MOUNTED_GETFSSTAT */
318 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
320 struct mnttab mnt;
321 char *table = "/etc/mnttab";
322 FILE *fp;
324 fp = fopen (table, "r");
325 if (fp == NULL)
326 return NULL;
328 while (fread (&mnt, sizeof mnt, 1, fp) > 0) {
329 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
330 #ifdef GETFSTYP /* SVR3. */
331 me->me_devname = strdup (mnt.mt_dev);
332 #else
333 me->me_devname = malloc (strlen (mnt.mt_dev) + 6);
334 strcpy (me->me_devname, "/dev/");
335 strcpy (me->me_devname + 5, mnt.mt_dev);
336 #endif
337 me->me_mountdir = strdup (mnt.mt_filsys);
338 me->me_dev = -1; /* Magic; means not known yet. */
339 me->me_type = "";
340 #ifdef GETFSTYP /* SVR3. */
341 if (need_fs_type) {
342 struct statfs fsd;
343 char typebuf[FSTYPSZ];
345 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
346 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
347 me->me_type = strdup (typebuf);
349 #endif
350 me->me_next = NULL;
352 /* Add to the linked list. */
353 mtail->me_next = me;
354 mtail = me;
357 if (fclose (fp) == EOF)
358 return NULL;
360 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
362 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
364 struct mntent **mnttbl = getmnttbl (), **ent;
365 for (ent = mnttbl; *ent; ent++) {
366 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
367 me->me_devname = strdup ((*ent)->mt_resource);
368 me->me_mountdir = strdup ((*ent)->mt_directory);
369 me->me_type = strdup ((*ent)->mt_fstype);
370 me->me_dev = -1; /* Magic; means not known yet. */
371 me->me_next = NULL;
373 /* Add to the linked list. */
374 mtail->me_next = me;
375 mtail = me;
377 endmnttbl ();
379 #endif
381 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
383 struct mnttab mnt;
384 char *table = MNTTAB;
385 FILE *fp;
386 int ret;
388 fp = fopen (table, "r");
389 if (fp == NULL)
390 return NULL;
392 while ((ret = getmntent (fp, &mnt)) == 0) {
393 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
394 me->me_devname = strdup (mnt.mnt_special);
395 me->me_mountdir = strdup (mnt.mnt_mountp);
396 me->me_type = strdup (mnt.mnt_fstype);
397 me->me_dev = -1; /* Magic; means not known yet. */
398 me->me_next = NULL;
399 /* Add to the linked list. */
400 mtail->me_next = me;
401 mtail = me;
404 if (ret > 0)
405 return NULL;
406 if (fclose (fp) == EOF)
407 return NULL;
409 #endif /* MOUNTED_GETMNTENT2. */
411 #ifdef MOUNTED_VMOUNT /* AIX. */
413 int bufsize;
414 char *entries, *thisent;
415 struct vmount *vmp;
417 /* Ask how many bytes to allocate for the mounted filesystem info. */
418 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
419 entries = malloc (bufsize);
421 /* Get the list of mounted filesystems. */
422 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
424 for (thisent = entries; thisent < entries + bufsize;
425 thisent += vmp->vmt_length) {
426 vmp = (struct vmount *) thisent;
427 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
428 if (vmp->vmt_flags & MNT_REMOTE) {
429 char *host, *path;
431 /* Prepend the remote pathname. */
432 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
433 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
434 me->me_devname = malloc (strlen (host) + strlen (path) + 2);
435 strcpy (me->me_devname, host);
436 strcat (me->me_devname, ":");
437 strcat (me->me_devname, path);
438 } else {
439 me->me_devname = strdup (thisent +
440 vmp->vmt_data[VMT_OBJECT].vmt_off);
442 me->me_mountdir = strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
443 me->me_type = strdup (fstype_to_string (vmp->vmt_gfstype));
444 me->me_dev = -1; /* vmt_fsid might be the info we want. */
445 me->me_next = NULL;
447 /* Add to the linked list. */
448 mtail->me_next = me;
449 mtail = me;
451 free (entries);
453 #endif /* MOUNTED_VMOUNT. */
455 /* Free the dummy head. */
456 me = mount_list;
457 mount_list = mount_list->me_next;
458 free (me);
459 return mount_list;
461 #endif /* NO_INFOMOUNT */
463 #if defined(NO_INFOMOUNT) && defined(__QNX__)
465 ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
466 ** this via the following code.
467 ** Note that, as this is based on CWD, it only fills one mount_entry
468 ** structure. See my_statfs() in utilunix.c for the "other side" of
469 ** this hack.
472 #include <fcntl.h>
473 #include <stdio.h>
474 #include <stdlib.h>
475 #include <string.h>
476 #ifdef HAVE_UNISTD_H
477 # include <unistd.h>
478 #endif
479 #include <sys/disk.h>
480 #include <sys/fsys.h>
481 #include <sys/statfs.h>
483 #include "mountlist.h"
485 struct mount_entry *read_filesystem_list(int need_fs_type, int all_fs)
487 struct _disk_entry de;
488 struct statfs fs;
489 int i, fd;
490 char *tp, dev[_POSIX_NAME_MAX], dir[_POSIX_PATH_MAX];
492 static struct mount_entry *me = NULL;
494 if (me)
496 if (me->me_devname) free(me->me_devname);
497 if (me->me_mountdir) free(me->me_mountdir);
498 if (me->me_type) free(me->me_type);
500 else
501 me = (struct mount_entry *)malloc(sizeof(struct mount_entry));
503 if (!getcwd(dir, _POSIX_PATH_MAX)) return (NULL);
505 if ((fd = open(dir, O_RDONLY)) == -1) return (NULL);
507 i = disk_get_entry(fd, &de);
509 close(fd);
511 if (i == -1) return (NULL);
513 switch (de.disk_type)
515 case _UNMOUNTED: tp = "unmounted"; break;
516 case _FLOPPY: tp = "Floppy"; break;
517 case _HARD: tp = "Hard"; break;
518 case _RAMDISK: tp = "Ram"; break;
519 case _REMOVABLE: tp = "Removable"; break;
520 case _TAPE: tp = "Tape"; break;
521 case _CDROM: tp = "CDROM"; break;
522 default: tp = "unknown";
525 if (fsys_get_mount_dev(dir, &dev) == -1) return (NULL);
527 if (fsys_get_mount_pt(dev, &dir) == -1) return (NULL);
529 me->me_devname = strdup(dev);
530 me->me_mountdir = strdup(dir);
531 me->me_type = strdup(tp);
532 me->me_dev = de.disk_type;
534 #ifdef DEBUG
535 fprintf(stderr, "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
536 de.disk_type, tp, _DRIVER_NAME_LEN, _DRIVER_NAME_LEN, de.driver_name, de.disk_drv);
537 fprintf(stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev);
538 fprintf(stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir);
539 #endif
541 return (me);
543 #endif /* __QNX__ */