2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998, 2001 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: getfsent.c,v 1.38 2006/07/19 17:41:14 martinea Exp $
29 * generic version of code to read fstab
37 # include <sys/types.h>
42 static char *dev2rdev(char *);
45 * You are in a twisty maze of passages, all alike.
49 #if defined(HAVE_FSTAB_H) && !defined(HAVE_MNTENT_H) /* { */
53 #define GETFSENT_TYPE "BSD (Ultrix, AIX)"
72 generic_fsent_t * fsent)
74 struct fstab *sys_fsent = getfsent();
75 static char *xfsname = NULL, *xmntdir = NULL;
76 static char *xfstype = NULL, *xmntopts = NULL;
80 fsent->fsname = xfsname = newstralloc(xfsname, sys_fsent->fs_spec);
81 fsent->mntdir = xmntdir = newstralloc(xmntdir, sys_fsent->fs_file);
82 fsent->freq = sys_fsent->fs_freq;
83 fsent->passno = sys_fsent->fs_passno;
85 fsent->fstype = xfstype = newstralloc(xfstype, sys_fsent->fs_name);
86 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_opts);
89 fsent->fstype = xfstype = newstralloc(xfstype, _("unknown"));
90 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_type);
92 fsent->fstype = xfstype = newstralloc(xfstype, sys_fsent->fs_vfstype);
93 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_mntops);
100 #if defined(HAVE_SYS_VFSTAB_H) /* } { */
102 ** SVR4 (GETFSENT_SOLARIS)
104 #define GETFSENT_TYPE "SVR4 (Solaris)"
106 #include <sys/vfstab.h>
108 static FILE *fstabf = NULL;
114 return (fstabf = fopen(VFSTAB, "r")) != NULL;
127 generic_fsent_t * fsent)
129 struct vfstab sys_fsent;
131 memset(&sys_fsent, 0, SIZEOF(sys_fsent));
132 if(getvfsent(fstabf, &sys_fsent) != 0)
135 fsent->fsname = sys_fsent.vfs_special;
136 fsent->fstype = sys_fsent.vfs_fstype;
137 fsent->mntdir = sys_fsent.vfs_mountp;
138 fsent->mntopts = sys_fsent.vfs_mntopts;
139 fsent->freq = 1; /* N/A */
140 fsent->passno = sys_fsent.vfs_fsckpass? atoi(sys_fsent.vfs_fsckpass) : 0;
145 # if defined(HAVE_MNTENT_H) /* } { */
148 ** System V.3 (GETFSENT_SVR3, GETFSENT_LINUX)
150 #define GETFSENT_TYPE "SVR3 (NeXTstep, Irix, Linux, HP-UX)"
154 #if defined(HAVE_ENDMNTENT)
155 #define AMCLOSE_MNTENT(x) endmntent(x)
157 #define AMCLOSE_MNTENT(x) fclose(x)
160 static FILE *fstabf1 = NULL; /* /proc/mounts */
161 static FILE *fstabf2 = NULL; /* MOUNTED */
162 static FILE *fstabf3 = NULL; /* MNTTAB */
168 #if defined(HAVE_SETMNTENT)
169 fstabf1 = setmntent("/proc/mounts", "r");
170 # if defined(MOUNTED)
171 fstabf2 = setmntent(MOUNTED, "r");
174 fstabf3 = setmntent(MNTTAB, "r");
178 fstabf3 = fopen(MNTTAB, "r");
181 return (fstabf1 != NULL || fstabf2 != NULL || fstabf3 != NULL);
188 AMCLOSE_MNTENT(fstabf1);
192 AMCLOSE_MNTENT(fstabf2);
196 AMCLOSE_MNTENT(fstabf3);
203 generic_fsent_t * fsent)
205 struct mntent *sys_fsent = NULL;
208 sys_fsent = getmntent(fstabf1);
210 AMCLOSE_MNTENT(fstabf1);
214 if(!sys_fsent && fstabf2) {
215 sys_fsent = getmntent(fstabf2);
217 AMCLOSE_MNTENT(fstabf2);
221 if(!sys_fsent && fstabf3) {
222 sys_fsent = getmntent(fstabf3);
224 AMCLOSE_MNTENT(fstabf3);
232 fsent->fsname = sys_fsent->mnt_fsname;
233 fsent->fstype = sys_fsent->mnt_type;
234 fsent->mntdir = sys_fsent->mnt_dir;
235 fsent->mntopts = sys_fsent->mnt_opts;
236 fsent->freq = sys_fsent->mnt_freq;
237 fsent->passno = sys_fsent->mnt_passno;
242 # if defined(HAVE_SYS_MNTTAB_H) || defined(STATFS_SCO_OS5) /* } { */
244 /* we won't actually include mnttab.h, since it contains nothing useful.. */
246 #define GETFSENT_TYPE "SVR3 (Interactive UNIX)"
252 #define FSTAB "/etc/fstab"
254 static FILE *fstabf = NULL;
260 return (fstabf = fopen(FSTAB, "r")) != NULL;
271 static generic_fsent_t _fsent;
275 generic_fsent_t * fsent)
277 static char *lfsnam = NULL;
278 static char *opts = NULL;
279 static char *cp = NULL;
284 for (; (cp = agets(fstabf)) != NULL; free(cp)) {
287 fsent->fsname = strtok(cp, " \t");
288 if ( fsent->fsname && *fsent->fsname != '#' )
291 if (cp == NULL) return 0;
293 fsent->mntdir = strtok((char *)NULL, " \t");
294 fsent->mntopts = strtok((char *)NULL, " \t");
295 if ( *fsent->mntopts != '-' ) {
296 fsent->fstype = fsent->mntopts;
297 fsent->mntopts = "rw";
300 if (strcmp(fsent->mntopts, "-r") == 0) {
301 fsent->mntopts = "ro";
304 if ((s = strchr(fsent->fstype, ',')) != NULL) {
306 strappend(fsent->mntopts, ",");
307 strappend(fsent->mntopts, s);
310 lfsnam = newstralloc(lfsnam, fsent->fstype);
312 while((ch = *s++) != '\0') {
313 if(isupper(ch)) ch = tolower(ch);
316 fsent->fstype = lfsnam;
318 if (strncmp_const(fsent->fstype, "hs") == 0)
319 fsent->fstype = "iso9660";
328 # if defined(HAVE_MNTTAB_H) /* } { */
330 #define GETFSENT_TYPE "SVR3 (SCO UNIX)"
333 #include <sys/fstyp.h>
334 #include <sys/statfs.h>
336 #define MNTTAB "/etc/mnttab"
339 * If these are defined somewhere please let me know.
342 #define MNT_READONLY 0101
343 #define MNT_READWRITE 0100
345 static FILE *fstabf = NULL;
351 return (fstabf = fopen(MNTTAB, "r")) != NULL;
362 static generic_fsent_t _fsent;
366 generic_fsent_t *fsent)
369 char typebuf[FSTYPSZ];
370 static struct mnttab mnt;
373 if(!fread (&mnt, SIZEOF(mnt), 1, fstabf))
376 fsent->fsname = mnt.mt_dev;
377 fsent->mntdir = mnt.mt_filsys;
380 if (statfs (fsent->mntdir, &fsd, SIZEOF(fsd), 0) != -1
381 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) {
383 ep = fsent->fstype = malloc(strlen(typebuf)+2);
385 *ep++ = tolower(*dp++);
389 if ( mnt.mt_ro_flg == MNT_READONLY ) {
390 fsent->mntopts = "ro";
392 fsent->mntopts = "rw";
402 #define GETFSENT_TYPE "undefined"
411 *=====================================================================
412 * Convert either a block or character device name to a character (raw)
415 * static char *dev2rdev(const char *name);
417 * entry: name - device name to convert
418 * exit: matching character device name if found,
419 * otherwise returns the input
421 * The input must be an absolute path.
423 * The exit string area is always an alloc-d area that the caller is
424 * responsible for releasing.
425 *=====================================================================
437 if(stat(name, &st) == 0 && !S_ISBLK(st.st_mode)) {
439 * If the input is already a character device, just return it.
441 return stralloc(name);
447 if(ch == '\0' || ch != '/') return stralloc(name);
449 ch = *s++; /* start after first '/' */
451 * Break the input path at each '/' and create a new name with an
452 * 'r' before the right part. For instance:
454 * /dev/sd0a -> /dev/rsd0a
455 * /dev/dsk/c0t0d0s0 -> /dev/rdsk/c0t0d0s0 -> /dev/dsk/rc0t0d0s0
460 fname = newvstralloc(fname, name, "/r", s, NULL);
462 if(stat(fname, &st) == 0 && S_ISCHR(st.st_mode)) return fname;
467 return stralloc(name); /* no match */
471 static int samefile(struct stat[3], struct stat *);
475 struct stat stats[3],
479 for(i = 0; i < 3; ++i) {
480 if (stats[i].st_dev == estat->st_dev &&
481 stats[i].st_ino == estat->st_ino)
486 #endif /* !IGNORE_FSTAB */
491 generic_fsent_t * fsent,
495 /* There is no real mount table so this will always fail and
496 * we are using GNU tar so we can just return here.
498 (void)name; /* Quiet unused parameter warning */
499 (void)fsent; /* Quiet unused parameter warning */
500 (void)check_dev; /* Quiet unused parameter warning */
503 struct stat stats[3];
504 char *fullname = NULL;
511 memset(stats, 0, SIZEOF(stats));
512 stats[0].st_dev = stats[1].st_dev = stats[2].st_dev = (dev_t)-1;
514 if (stat(name, &stats[0]) == -1)
515 stats[0].st_dev = (dev_t)-1;
516 if (name[0] != '/') {
517 fullname = stralloc2(DEV_PREFIX, name);
518 if (stat(fullname, &stats[1]) == -1)
519 stats[1].st_dev = (dev_t)-1;
520 fullname = newstralloc2(fullname, RDEV_PREFIX, name);
521 if (stat(fullname, &stats[2]) == -1)
522 stats[2].st_dev = (dev_t)-1;
525 else if (stat((rdev = dev2rdev(name)), &stats[1]) == -1)
526 stats[1].st_dev = (dev_t)-1;
534 while(get_fstab_nextentry(fsent)) {
538 int smnt = -1, sfs = -1, sfsr = -1;
542 if(fsent->mntdir != NULL)
543 smnt = stat(fsent->mntdir, &mntstat);
545 if(fsent->fsname != NULL) {
546 sfs = stat(fsent->fsname, &fsstat);
547 sfsr = stat((rdev = dev2rdev(fsent->fsname)), &fsrstat);
548 if(check_dev == 1 && sfs == -1 && sfsr == -1)
552 if((fsent->mntdir != NULL &&
554 samefile(stats, &mntstat)) ||
555 (fsent->fsname != NULL &&
557 samefile(stats, &fsstat)) ||
558 (fsent->fsname != NULL &&
560 samefile(stats, &fsrstat))) {
568 #endif /* !IGNORE_FSTAB */
573 generic_fsent_t * fsent)
575 if(fsent->fstype == NULL) /* unknown, assume local */
578 /* just eliminate fstypes known to be remote or unsavable */
580 return strcmp(fsent->fstype, "nfs") != 0 && /* NFS */
581 strcmp(fsent->fstype, "afs") != 0 && /* Andrew Filesystem */
582 strcmp(fsent->fstype, "swap") != 0 && /* Swap */
583 strcmp(fsent->fstype, "iso9660") != 0 && /* CDROM */
584 strcmp(fsent->fstype, "hs") != 0 && /* CDROM */
585 strcmp(fsent->fstype, "piofs") != 0; /* an AIX printer thing? */
593 generic_fsent_t fsent;
595 if(search_fstab(str, &fsent, 1) && fsent.fsname != NULL)
597 else if(search_fstab(str, &fsent, 0) && fsent.fsname != NULL)
600 return dev2rdev(str);
607 generic_fsent_t fsent;
609 if(search_fstab(str, &fsent, 1) && fsent.mntdir != NULL)
611 else if(search_fstab(str, &fsent, 0) && fsent.mntdir != NULL)
614 return stralloc(str);
617 char *amname_to_fstype(
620 generic_fsent_t fsent;
622 if (!search_fstab(str, &fsent, 1) && !search_fstab(str, &fsent, 0))
625 return stralloc(fsent.fstype);
630 void print_entry(generic_fsent_t *fsent);
634 generic_fsent_t * fsent)
636 #define nchk(s) ((s)? (s) : "<NULL>")
637 g_printf("%-20.20s %-14.14s %-7.7s %4d %5d %s\n",
638 nchk(fsent->fsname), nchk(fsent->mntdir), nchk(fsent->fstype),
639 fsent->freq, fsent->passno, nchk(fsent->mntopts));
647 generic_fsent_t fsent;
652 * Configure program for internationalization:
653 * 1) Only set the message locale for now.
654 * 2) Set textdomain for all amanda related programs to "amanda"
655 * We don't want to be forced to support dozens of message catalogs.
657 setlocale(LC_MESSAGES, "C");
658 textdomain("amanda");
662 set_pname("getfsent");
666 /* Don't die when child closes pipe */
667 signal(SIGPIPE, SIG_IGN);
670 g_fprintf(stderr, _("getfsent_test: could not open fstab\n"));
674 g_printf("getfsent (%s)\n",GETFSENT_TYPE);
675 g_printf("l/r fsname mntdir fstype freq pass# mntopts\n");
676 while(get_fstab_nextentry(&fsent)) {
677 g_printf("%c ",is_local_fstype(&fsent)? 'l' : 'r');
680 g_printf("--------\n");
684 name = newstralloc(name, "/usr");
685 if(search_fstab(name, &fsent, 1) || search_fstab(name, &fsent, 0)) {
686 g_printf(_("Found %s mount for %s:\n"),
687 is_local_fstype(&fsent)? _("local") : _("remote"), name);
691 g_printf(_("Mount for %s not found\n"), name);
693 name = newstralloc(name, "/");
694 if(search_fstab(name, &fsent, 1) || search_fstab(name, &fsent, 0)) {
695 g_printf(_("Found %s mount for %s:\n"),
696 is_local_fstype(&fsent)? _("local") : _("remote"), name);
700 g_printf(_("Mount for %s not found\n"), name);
702 name = newstralloc(name, "/");
703 s = amname_to_fstype(name);
704 g_printf(_("fstype of `%s': %s\n"), name, s);
706 name = newstralloc(name, "/dev/root");
707 s = amname_to_fstype(name);
708 g_printf(_("fstype of `%s': %s\n"), name, s);
710 name = newstralloc(name, "/usr");
711 s = amname_to_fstype(name);
712 g_printf(_("fstype of `%s': %s\n"), name, s);
714 name = newstralloc(name, "c0t3d0s0");
715 s = amname_to_fstype(name);
716 g_printf(_("fstype of `%s': %s\n"), name, s);
719 name = newstralloc(name, "/tmp/foo");
720 s = amname_to_devname(name);
721 g_printf(_("device of `%s': %s\n"), name, s);
723 s = amname_to_dirname(name);
724 g_printf(_("dirname of `%s': %s\n"), name, s);
726 s = amname_to_fstype(name);
727 g_printf(_("fstype of `%s': %s\n"), name, s);
730 name = newstralloc(name, "./foo");
731 s = amname_to_devname(name);
732 g_printf(_("device of `%s': %s\n"), name, s);
734 s = amname_to_dirname(name);
735 g_printf(_("dirname of `%s': %s\n"), name, s);
737 s = amname_to_fstype(name);
738 g_printf(_("fstype of `%s': %s\n"), name, s);
742 name = newstralloc(name, *++argv);
743 s = amname_to_devname(name);
744 g_printf(_("device of `%s': %s\n"), name, s);
746 s = amname_to_dirname(name);
747 g_printf(_("dirname of `%s': %s\n"), name, s);
749 s = amname_to_fstype(name);
750 g_printf(_("fstype of `%s': %s\n"), name, s);