Committed some stilistic changes to the italian manual pages.
[midnight-commander.git] / src / mountlist.c
blobe59191439e919413b3be005cc742512b7939df80
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <sys/types.h>
23 #include <stdio.h>
25 /* This header needs to be included before sys/mount.h on *BSD */
26 #ifdef HAVE_SYS_PARAM_H
27 #include <sys/param.h>
28 #endif
30 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
31 #include <sys/mount.h>
32 #include <sys/fs_types.h>
33 #endif /* MOUNTED_GETFSSTAT */
35 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
36 #include <mntent.h>
37 #if !defined(MOUNTED)
38 #if defined(MNT_MNTTAB) /* HP-UX. */
39 #define MOUNTED MNT_MNTTAB
40 #endif
41 #if defined(MNTTABNAME) /* Dynix. */
42 #define MOUNTED MNTTABNAME
43 #endif
44 #endif
45 #endif
47 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
48 #include <sys/mount.h>
49 #endif
51 #ifdef MOUNTED_GETMNT /* Ultrix. */
52 #include <sys/mount.h>
53 #include <sys/fs_types.h>
54 #endif
56 #ifdef MOUNTED_FREAD /* SVR2. */
57 #include <mnttab.h>
58 #endif
60 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
61 #include <mnttab.h>
62 #include <sys/fstyp.h>
63 #include <sys/statfs.h>
64 #endif
66 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
67 #include <sys/mnttab.h>
68 #endif
70 #ifdef MOUNTED_VMOUNT /* AIX. */
71 #include <fshelp.h>
72 #include <sys/vfs.h>
73 #endif
75 #ifdef HAVE_SYS_STATFS_H
76 #include <sys/statfs.h>
77 #endif
79 #ifdef HAVE_INFOMOUNT_QNX
80 #include <sys/disk.h>
81 #include <sys/fsys.h>
82 #endif
84 #include "global.h"
85 #include "mountlist.h"
86 #include "fsusage.h"
87 #include "util.h"
89 /* void error (void); FIXME -- needed? */
91 #ifdef DOLPHIN
92 /* So special that it's not worth putting this in autoconf. */
93 #undef MOUNTED_FREAD_FSTYP
94 #define MOUNTED_GETMNTTBL
95 #endif
97 /* A mount table entry. */
98 struct mount_entry
100 char *me_devname; /* Device node pathname, including "/dev/". */
101 char *me_mountdir; /* Mount point directory pathname. */
102 char *me_type; /* "nfs", "4.2", etc. */
103 dev_t me_dev; /* Device number of me_mountdir. */
104 struct mount_entry *me_next;
107 #ifdef HAVE_INFOMOUNT_LIST
109 static struct mount_entry *mount_list = NULL;
111 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
112 /* Return the value of the hexadecimal number represented by CP.
113 No prefix (like '0x') or suffix (like 'h') is expected to be
114 part of CP. */
116 static int xatoi (char *cp)
118 int val;
120 val = 0;
121 while (*cp) {
122 if (*cp >= 'a' && *cp <= 'f')
123 val = val * 16 + *cp - 'a' + 10;
124 else if (*cp >= 'A' && *cp <= 'F')
125 val = val * 16 + *cp - 'A' + 10;
126 else if (*cp >= '0' && *cp <= '9')
127 val = val * 16 + *cp - '0';
128 else
129 break;
130 cp++;
132 return val;
134 #endif /* MOUNTED_GETMNTENT1 */
136 #if defined (MOUNTED_GETMNTINFO) && !defined (HAVE_F_FSTYPENAME)
137 static char *fstype_to_string (short t)
139 switch (t) {
140 case MOUNT_UFS:
141 return "ufs";
142 case MOUNT_NFS:
143 return "nfs";
144 #ifdef MOUNT_PC
145 case MOUNT_PC:
146 return "pc";
147 #endif
148 #ifdef MOUNT_MFS
149 case MOUNT_MFS:
150 return "mfs";
151 #endif
152 #ifdef MOUNT_LO
153 case MOUNT_LO:
154 return "lo";
155 #endif
156 #ifdef MOUNT_TFS
157 case MOUNT_TFS:
158 return "tfs";
159 #endif
160 #ifdef MOUNT_TMP
161 case MOUNT_TMP:
162 return "tmp";
163 #endif
164 default:
165 return "?";
168 #endif /* MOUNTED_GETMNTINFO && !HAVE_F_FSTYPENAME */
170 #ifdef MOUNTED_VMOUNT /* AIX. */
171 static char *
172 fstype_to_string (int t)
174 struct vfs_ent *e;
176 e = getvfsbytype (t);
177 if (!e || !e->vfsent_name)
178 return "none";
179 else
180 return e->vfsent_name;
182 #endif /* MOUNTED_VMOUNT */
184 /* Return a list of the currently mounted filesystems, or NULL on error.
185 Add each entry to the tail of the list so that they stay in order.
186 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
187 the returned list are valid. Otherwise, they might not be.
188 If ALL_FS is zero, do not return entries for filesystems that
189 are automounter (dummy) entries. */
191 static struct mount_entry *
192 read_filesystem_list (int need_fs_type, int all_fs)
194 struct mount_entry *mlist;
195 struct mount_entry *me;
196 struct mount_entry *mtail;
198 /* Start the list off with a dummy entry. */
199 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
200 me->me_next = NULL;
201 mlist = mtail = me;
203 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
204 #ifdef MOUNTED
206 struct mntent *mnt;
207 FILE *fp;
208 char *devopt;
210 fp = setmntent (MOUNTED, "r");
211 if (fp == NULL)
212 return NULL;
214 while ((mnt = getmntent (fp))) {
215 if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
216 || !strcmp (mnt->mnt_type, "auto")))
217 continue;
219 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
220 me->me_devname = strdup (mnt->mnt_fsname);
221 me->me_mountdir = strdup (mnt->mnt_dir);
222 me->me_type = strdup (mnt->mnt_type);
223 devopt = strstr (mnt->mnt_opts, "dev=");
224 if (devopt) {
225 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
226 me->me_dev = xatoi (devopt + 6);
227 else
228 me->me_dev = xatoi (devopt + 4);
229 } else
230 me->me_dev = -1; /* Magic; means not known yet. */
231 me->me_next = NULL;
233 /* Add to the linked list. */
234 mtail->me_next = me;
235 mtail = me;
238 if (endmntent (fp) == 0)
239 return NULL;
241 #endif /* MOUNTED */
242 #endif /* MOUNTED_GETMNTENT1 */
244 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
246 struct statfs *fsp;
247 int entries;
249 entries = getmntinfo (&fsp, MNT_NOWAIT);
250 if (entries < 0)
251 return NULL;
252 while (entries-- > 0) {
253 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
254 me->me_devname = strdup (fsp->f_mntfromname);
255 me->me_mountdir = strdup (fsp->f_mntonname);
256 #ifdef HAVE_F_FSTYPENAME
257 me->me_type = strdup (fsp->f_fstypename);
258 #else
259 me->me_type = fstype_to_string (fsp->f_type);
260 #endif
261 me->me_dev = -1; /* Magic; means not known yet. */
262 me->me_next = NULL;
264 /* Add to the linked list. */
265 mtail->me_next = me;
266 mtail = me;
267 fsp++;
270 #endif /* MOUNTED_GETMNTINFO */
272 #ifdef MOUNTED_GETMNT /* Ultrix. */
274 int offset = 0;
275 int val;
276 struct fs_data fsd;
278 while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
279 (char *) 0)) > 0) {
280 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
281 me->me_devname = strdup (fsd.fd_req.devname);
282 me->me_mountdir = strdup (fsd.fd_req.path);
283 me->me_type = gt_names[fsd.fd_req.fstype];
284 me->me_dev = fsd.fd_req.dev;
285 me->me_next = NULL;
287 /* Add to the linked list. */
288 mtail->me_next = me;
289 mtail = me;
291 if (val < 0)
292 return NULL;
294 #endif /* MOUNTED_GETMNT */
296 #ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
298 int numsys, counter, bufsize;
299 struct statfs *stats;
301 numsys = getfsstat ((struct statfs *) 0, 0L, MNT_WAIT);
302 if (numsys < 0)
303 return (NULL);
305 bufsize = (1 + numsys) * sizeof (struct statfs);
306 stats = (struct statfs *) malloc (bufsize);
307 numsys = getfsstat (stats, bufsize, MNT_WAIT);
309 if (numsys < 0) {
310 free (stats);
311 return (NULL);
313 for (counter = 0; counter < numsys; counter++) {
314 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
315 me->me_devname = strdup (stats[counter].f_mntfromname);
316 me->me_mountdir = strdup (stats[counter].f_mntonname);
317 me->me_type = mnt_names[stats[counter].f_type];
318 me->me_dev = -1; /* Magic; means not known yet. */
319 me->me_next = NULL;
321 /* Add to the linked list. */
322 mtail->me_next = me;
323 mtail = me;
326 free (stats);
328 #endif /* MOUNTED_GETFSSTAT */
330 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
332 struct mnttab mnt;
333 char *table = "/etc/mnttab";
334 FILE *fp;
336 fp = fopen (table, "r");
337 if (fp == NULL)
338 return NULL;
340 while (fread (&mnt, sizeof mnt, 1, fp) > 0) {
341 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
342 #ifdef GETFSTYP /* SVR3. */
343 me->me_devname = strdup (mnt.mt_dev);
344 #else
345 me->me_devname = malloc (strlen (mnt.mt_dev) + 6);
346 strcpy (me->me_devname, "/dev/");
347 strcpy (me->me_devname + 5, mnt.mt_dev);
348 #endif
349 me->me_mountdir = strdup (mnt.mt_filsys);
350 me->me_dev = -1; /* Magic; means not known yet. */
351 me->me_type = "";
352 #ifdef GETFSTYP /* SVR3. */
353 if (need_fs_type) {
354 struct statfs fsd;
355 char typebuf[FSTYPSZ];
357 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
358 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
359 me->me_type = strdup (typebuf);
361 #endif
362 me->me_next = NULL;
364 /* Add to the linked list. */
365 mtail->me_next = me;
366 mtail = me;
369 if (fclose (fp) == EOF)
370 return NULL;
372 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */
374 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
376 struct mntent **mnttbl = getmnttbl (), **ent;
377 for (ent = mnttbl; *ent; ent++) {
378 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
379 me->me_devname = strdup ((*ent)->mt_resource);
380 me->me_mountdir = strdup ((*ent)->mt_directory);
381 me->me_type = strdup ((*ent)->mt_fstype);
382 me->me_dev = -1; /* Magic; means not known yet. */
383 me->me_next = NULL;
385 /* Add to the linked list. */
386 mtail->me_next = me;
387 mtail = me;
389 endmnttbl ();
391 #endif /* MOUNTED_GETMNTTBL */
393 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
395 struct mnttab mnt;
396 char *table = MNTTAB;
397 FILE *fp;
398 int ret;
400 fp = fopen (table, "r");
401 if (fp == NULL)
402 return NULL;
404 while ((ret = getmntent (fp, &mnt)) == 0) {
405 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
406 me->me_devname = strdup (mnt.mnt_special);
407 me->me_mountdir = strdup (mnt.mnt_mountp);
408 me->me_type = strdup (mnt.mnt_fstype);
409 me->me_dev = -1; /* Magic; means not known yet. */
410 me->me_next = NULL;
411 /* Add to the linked list. */
412 mtail->me_next = me;
413 mtail = me;
416 if (ret > 0)
417 return NULL;
418 if (fclose (fp) == EOF)
419 return NULL;
421 #endif /* MOUNTED_GETMNTENT2 */
423 #ifdef MOUNTED_VMOUNT /* AIX. */
425 int bufsize;
426 char *entries, *thisent;
427 struct vmount *vmp;
429 /* Ask how many bytes to allocate for the mounted filesystem info. */
430 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
431 entries = malloc (bufsize);
433 /* Get the list of mounted filesystems. */
434 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
436 for (thisent = entries; thisent < entries + bufsize;
437 thisent += vmp->vmt_length) {
438 vmp = (struct vmount *) thisent;
439 me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
440 if (vmp->vmt_flags & MNT_REMOTE) {
441 char *host, *path;
443 /* Prepend the remote pathname. */
444 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
445 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
446 me->me_devname = malloc (strlen (host) + strlen (path) + 2);
447 strcpy (me->me_devname, host);
448 strcat (me->me_devname, ":");
449 strcat (me->me_devname, path);
450 } else {
451 me->me_devname = strdup (thisent +
452 vmp->vmt_data[VMT_OBJECT].vmt_off);
454 me->me_mountdir = strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
455 me->me_type = strdup (fstype_to_string (vmp->vmt_gfstype));
456 me->me_dev = -1; /* vmt_fsid might be the info we want. */
457 me->me_next = NULL;
459 /* Add to the linked list. */
460 mtail->me_next = me;
461 mtail = me;
463 free (entries);
465 #endif /* MOUNTED_VMOUNT */
467 /* Free the dummy head. */
468 me = mlist;
469 mlist = mlist->me_next;
470 free (me);
471 return mlist;
473 #endif /* HAVE_INFOMOUNT_LIST */
475 #ifdef HAVE_INFOMOUNT_QNX
477 ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
478 ** this via the following code.
479 ** Note that, as this is based on CWD, it only fills one mount_entry
480 ** structure. See my_statfs() in utilunix.c for the "other side" of
481 ** this hack.
484 static struct mount_entry *
485 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 /* DEBUG */
541 return (me);
543 #endif /* HAVE_INFOMOUNT_QNX */
545 void
546 init_my_statfs (void)
548 #ifdef HAVE_INFOMOUNT_LIST
549 mount_list = read_filesystem_list (1, 1);
550 #endif /* HAVE_INFOMOUNT_LIST */
553 void
554 my_statfs (struct my_statfs *myfs_stats, char *path)
556 #ifdef HAVE_INFOMOUNT_LIST
557 int i, len = 0;
558 struct mount_entry *entry = NULL;
559 struct mount_entry *temp = mount_list;
560 struct fs_usage fs_use;
562 while (temp){
563 i = strlen (temp->me_mountdir);
564 if (i > len && (strncmp (path, temp->me_mountdir, i) == 0))
565 if (!entry || (path [i] == PATH_SEP || path [i] == 0)){
566 len = i;
567 entry = temp;
569 temp = temp->me_next;
572 if (entry){
573 get_fs_usage (entry->me_mountdir, &fs_use);
575 myfs_stats->type = entry->me_dev;
576 myfs_stats->typename = entry->me_type;
577 myfs_stats->mpoint = entry->me_mountdir;
578 myfs_stats->device = entry->me_devname;
579 myfs_stats->avail = getuid () ? fs_use.fsu_bavail/2 : fs_use.fsu_bfree/2;
580 myfs_stats->total = fs_use.fsu_blocks/2;
581 myfs_stats->nfree = fs_use.fsu_ffree;
582 myfs_stats->nodes = fs_use.fsu_files;
583 } else
584 #endif /* HAVE_INFOMOUNT_LIST */
586 #ifdef HAVE_INFOMOUNT_QNX
588 ** This is the "other side" of the hack to read_filesystem_list() in
589 ** mountlist.c.
590 ** It's not the most efficient approach, but consumes less memory. It
591 ** also accomodates QNX's ability to mount filesystems on the fly.
593 struct mount_entry *entry;
594 struct fs_usage fs_use;
596 if ((entry = read_filesystem_list(0, 0)) != NULL)
598 get_fs_usage(entry->me_mountdir, &fs_use);
600 myfs_stats->type = entry->me_dev;
601 myfs_stats->typename = entry->me_type;
602 myfs_stats->mpoint = entry->me_mountdir;
603 myfs_stats->device = entry->me_devname;
605 myfs_stats->avail = fs_use.fsu_bfree / 2;
606 myfs_stats->total = fs_use.fsu_blocks / 2;
607 myfs_stats->nfree = fs_use.fsu_ffree;
608 myfs_stats->nodes = fs_use.fsu_files;
610 else
611 #endif /* HAVE_INFOMOUNT_QNX */
613 myfs_stats->type = 0;
614 myfs_stats->mpoint = "unknown";
615 myfs_stats->device = "unknown";
616 myfs_stats->avail = 0;
617 myfs_stats->total = 0;
618 myfs_stats->nfree = 0;
619 myfs_stats->nodes = 0;