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.34 2006/01/14 04:37:18 paddy_s Exp $
29 * generic version of code to read fstab
36 # include <sys/types.h>
43 static char *dev2rdev P((char *));
44 static int samefile P((struct stat[3], struct stat *));
47 * You are in a twisty maze of passages, all alike.
51 #if defined(HAVE_FSTAB_H) && !defined(HAVE_MNTENT_H) /* { */
55 #define GETFSENT_TYPE "BSD (Ultrix, AIX)"
70 int get_fstab_nextentry(fsent)
71 generic_fsent_t *fsent;
73 struct fstab *sys_fsent = getfsent();
74 static char *xfsname = NULL, *xmntdir = NULL;
75 static char *xfstype = NULL, *xmntopts = NULL;
79 fsent->fsname = xfsname = newstralloc(xfsname, sys_fsent->fs_spec);
80 fsent->mntdir = xmntdir = newstralloc(xmntdir, sys_fsent->fs_file);
81 fsent->freq = sys_fsent->fs_freq;
82 fsent->passno = sys_fsent->fs_passno;
84 fsent->fstype = xfstype = newstralloc(xfstype, sys_fsent->fs_name);
85 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_opts);
88 fsent->fstype = xfstype = newstralloc(xfstype, "unknown");
89 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_type);
91 fsent->fstype = xfstype = newstralloc(xfstype, sys_fsent->fs_vfstype);
92 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_mntops);
99 #if defined(HAVE_SYS_VFSTAB_H) /* } { */
101 ** SVR4 (GETFSENT_SOLARIS)
103 #define GETFSENT_TYPE "SVR4 (Solaris)"
105 #include <sys/vfstab.h>
107 static FILE *fstabf = NULL;
112 return (fstabf = fopen(VFSTAB, "r")) != NULL;
122 int get_fstab_nextentry(fsent)
123 generic_fsent_t *fsent;
125 struct vfstab sys_fsent;
127 if(getvfsent(fstabf, &sys_fsent) != 0)
130 fsent->fsname = sys_fsent.vfs_special;
131 fsent->fstype = sys_fsent.vfs_fstype;
132 fsent->mntdir = sys_fsent.vfs_mountp;
133 fsent->mntopts = sys_fsent.vfs_mntopts;
134 fsent->freq = 1; /* N/A */
135 fsent->passno = sys_fsent.vfs_fsckpass? atoi(sys_fsent.vfs_fsckpass) : 0;
140 # if defined(HAVE_MNTENT_H) /* } { */
143 ** System V.3 (GETFSENT_SVR3, GETFSENT_LINUX)
145 #define GETFSENT_TYPE "SVR3 (NeXTstep, Irix, Linux, HP-UX)"
149 #if defined(HAVE_ENDMNTENT)
150 #define AMCLOSE_MNTENT(x) endmntent(x)
152 #define AMCLOSE_MNTENT(x) fclose(x)
155 static FILE *fstabf1 = NULL; /* /proc/mounts */
156 static FILE *fstabf2 = NULL; /* MOUNTED */
157 static FILE *fstabf3 = NULL; /* MNTTAB */
162 #if defined(HAVE_SETMNTENT)
163 fstabf1 = setmntent("/proc/mounts", "r");
164 # if defined(MOUNTED)
165 fstabf2 = setmntent(MOUNTED, "r");
168 fstabf3 = setmntent(MNTTAB, "r");
172 fstabf3 = fopen(MNTTAB, "r");
175 return (fstabf1 != NULL || fstabf2 != NULL || fstabf3 != NULL);
181 AMCLOSE_MNTENT(fstabf1);
185 AMCLOSE_MNTENT(fstabf2);
189 AMCLOSE_MNTENT(fstabf3);
194 int get_fstab_nextentry(fsent)
195 generic_fsent_t *fsent;
197 struct mntent *sys_fsent = NULL;
200 sys_fsent = getmntent(fstabf1);
202 AMCLOSE_MNTENT(fstabf1);
206 if(!sys_fsent && fstabf2) {
207 sys_fsent = getmntent(fstabf2);
209 AMCLOSE_MNTENT(fstabf2);
213 if(!sys_fsent && fstabf3) {
214 sys_fsent = getmntent(fstabf3);
216 AMCLOSE_MNTENT(fstabf3);
224 fsent->fsname = sys_fsent->mnt_fsname;
225 fsent->fstype = sys_fsent->mnt_type;
226 fsent->mntdir = sys_fsent->mnt_dir;
227 fsent->mntopts = sys_fsent->mnt_opts;
228 fsent->freq = sys_fsent->mnt_freq;
229 fsent->passno = sys_fsent->mnt_passno;
234 # if defined(HAVE_SYS_MNTTAB_H) || defined(STATFS_SCO_OS5) /* } { */
236 /* we won't actually include mnttab.h, since it contains nothing useful.. */
238 #define GETFSENT_TYPE "SVR3 (Interactive UNIX)"
244 #define FSTAB "/etc/fstab"
246 static FILE *fstabf = NULL;
251 return (fstabf = fopen(FSTAB, "r")) != NULL;
261 static generic_fsent_t _fsent;
263 int get_fstab_nextentry(fsent)
264 generic_fsent_t *fsent;
266 static char *lfsnam = NULL;
267 static char *opts = NULL;
268 static char *cp = NULL;
273 for (; (cp = agets(fstabf)) != NULL; free(cp)) {
274 fsent->fsname = strtok(cp, " \t");
275 if ( fsent->fsname && *fsent->fsname != '#' )
278 if (cp == NULL) return 0;
280 fsent->mntdir = strtok((char *)NULL, " \t");
281 fsent->mntopts = strtok((char *)NULL, " \t");
282 if ( *fsent->mntopts != '-' ) {
283 fsent->fstype = fsent->mntopts;
284 fsent->mntopts = "rw";
287 if (strcmp(fsent->mntopts, "-r") == 0) {
288 fsent->mntopts = "ro";
291 if ((s = strchr(fsent->fstype, ',')) != NULL) {
293 strappend(fsent->mntopts, ",");
294 strappend(fsent->mntopts, s);
297 lfsnam = newstralloc(lfsnam, fsent->fstype);
299 while((ch = *s++) != '\0') {
300 if(isupper(ch)) ch = tolower(ch);
303 fsent->fstype = lfsnam;
306 if (strncmp(fsent->fstype, sc, sizeof(sc)-1) == 0)
307 fsent->fstype = "iso9660";
317 # if defined(HAVE_MNTTAB_H) /* } { */
319 #define GETFSENT_TYPE "SVR3 (SCO UNIX)"
322 #include <sys/fstyp.h>
323 #include <sys/statfs.h>
325 #define MNTTAB "/etc/mnttab"
328 * If these are defined somewhere please let me know.
331 #define MNT_READONLY 0101
332 #define MNT_READWRITE 0100
334 static FILE *fstabf = NULL;
339 return (fstabf = fopen(MNTTAB, "r")) != NULL;
349 static generic_fsent_t _fsent;
351 int get_fstab_nextentry(fsent)
352 generic_fsent_t *fsent;
355 char typebuf[FSTYPSZ];
356 static struct mnttab mnt;
359 if(!fread (&mnt, sizeof mnt, 1, fstabf))
362 fsent->fsname = mnt.mt_dev;
363 fsent->mntdir = mnt.mt_filsys;
366 if (statfs (fsent->mntdir, &fsd, sizeof fsd, 0) != -1
367 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) {
369 ep = fsent->fstype = malloc(strlen(typebuf)+2);
371 *ep++ = tolower(*dp++);
375 if ( mnt.mt_ro_flg == MNT_READONLY ) {
376 fsent->mntopts = "ro";
378 fsent->mntopts = "rw";
388 #define GETFSENT_TYPE "undefined"
397 *=====================================================================
398 * Convert either a block or character device name to a character (raw)
401 * static char *dev2rdev(const char *name);
403 * entry: name - device name to convert
404 * exit: matching character device name if found,
405 * otherwise returns the input
407 * The input must be an absolute path.
409 * The exit string area is always an alloc-d area that the caller is
410 * responsible for releasing.
411 *=====================================================================
414 static char *dev2rdev(name)
422 if(stat(name, &st) == 0 && S_ISCHR(st.st_mode)) {
424 * If the input is already a character device, just return it.
426 return stralloc(name);
432 if(ch == '\0' || ch != '/') return stralloc(name);
434 ch = *s++; /* start after first '/' */
436 * Break the input path at each '/' and create a new name with an
437 * 'r' before the right part. For instance:
439 * /dev/sd0a -> /dev/rsd0a
440 * /dev/dsk/c0t0d0s0 -> /dev/rdsk/c0t0d0s0 -> /dev/dsk/rc0t0d0s0
445 fname = newvstralloc(fname, name, "/r", s, NULL);
447 if(stat(fname, &st) == 0 && S_ISCHR(st.st_mode)) return fname;
452 return stralloc(name); /* no match */
455 static int samefile(stats, estat)
456 struct stat stats[3], *estat;
459 for(i = 0; i < 3; ++i) {
460 if (stats[i].st_dev == estat->st_dev &&
461 stats[i].st_ino == estat->st_ino)
467 int search_fstab(name, fsent, check_dev)
469 generic_fsent_t *fsent;
473 /* There is no real mount table so this will always fail and
474 * we are using GNU tar so we can just return here.
478 struct stat stats[3];
479 char *fullname = NULL;
486 stats[0].st_dev = stats[1].st_dev = stats[2].st_dev = -1;
488 if (stat(name, &stats[0]) == -1)
489 stats[0].st_dev = -1;
490 if (name[0] != '/') {
491 fullname = stralloc2(DEV_PREFIX, name);
492 if (stat(fullname, &stats[1]) == -1)
493 stats[1].st_dev = -1;
494 fullname = newstralloc2(fullname, RDEV_PREFIX, name);
495 if (stat(fullname, &stats[2]) == -1)
496 stats[2].st_dev = -1;
499 else if (stat((rdev = dev2rdev(name)), &stats[1]) == -1)
500 stats[1].st_dev = -1;
508 while(get_fstab_nextentry(fsent)) {
512 int smnt = -1, sfs = -1, sfsr = -1;
516 if(fsent->mntdir != NULL &&
517 (smnt = stat(fsent->mntdir, &mntstat)) == -1)
520 if(fsent->fsname != NULL) {
521 sfs = stat(fsent->fsname, &fsstat);
522 sfsr = stat((rdev = dev2rdev(fsent->fsname)), &fsrstat);
523 if(check_dev == 1 && sfs == -1 && sfsr == -1)
527 if((fsent->mntdir != NULL &&
529 samefile(stats, &mntstat)) ||
530 (fsent->fsname != NULL &&
532 samefile(stats, &fsstat)) ||
533 (fsent->fsname != NULL &&
535 samefile(stats, &fsrstat))) {
543 #endif /* !IGNORE_FSTAB */
546 int is_local_fstype(fsent)
547 generic_fsent_t *fsent;
549 if(fsent->fstype == NULL) /* unknown, assume local */
552 /* just eliminate fstypes known to be remote or unsavable */
554 return strcmp(fsent->fstype, "nfs") != 0 && /* NFS */
555 strcmp(fsent->fstype, "afs") != 0 && /* Andrew Filesystem */
556 strcmp(fsent->fstype, "swap") != 0 && /* Swap */
557 strcmp(fsent->fstype, "iso9660") != 0 && /* CDROM */
558 strcmp(fsent->fstype, "hs") != 0 && /* CDROM */
559 strcmp(fsent->fstype, "piofs") != 0; /* an AIX printer thing? */
563 char *amname_to_devname(str)
566 generic_fsent_t fsent;
568 if(search_fstab(str, &fsent, 1) && fsent.fsname != NULL)
570 else if(search_fstab(str, &fsent, 0) && fsent.fsname != NULL)
573 return dev2rdev(str);
576 char *amname_to_dirname(str)
579 generic_fsent_t fsent;
581 if(search_fstab(str, &fsent, 1) && fsent.mntdir != NULL)
583 else if(search_fstab(str, &fsent, 0) && fsent.mntdir != NULL)
586 return stralloc(str);
589 char *amname_to_fstype(str)
592 generic_fsent_t fsent;
594 if (!search_fstab(str, &fsent, 1) && !search_fstab(str, &fsent, 0))
597 return stralloc(fsent.fstype);
604 generic_fsent_t *fsent;
606 #define nchk(s) ((s)? (s) : "<NULL>")
607 printf("%-20.20s %-14.14s %-7.7s %4d %5d %s\n",
608 nchk(fsent->fsname), nchk(fsent->mntdir), nchk(fsent->fstype),
609 fsent->freq, fsent->passno, nchk(fsent->mntopts));
616 generic_fsent_t fsent;
619 unsigned long malloc_hist_1, malloc_size_1;
620 unsigned long malloc_hist_2, malloc_size_2;
624 set_pname("getfsent");
626 /* Don't die when child closes pipe */
627 signal(SIGPIPE, SIG_IGN);
629 malloc_size_1 = malloc_inuse(&malloc_hist_1);
632 fprintf(stderr, "getfsent_test: could not open fstab\n");
636 printf("getfsent (%s)\n",GETFSENT_TYPE);
637 printf("l/r fsname mntdir fstype freq pass# mntopts\n");
638 while(get_fstab_nextentry(&fsent)) {
639 printf("%c ",is_local_fstype(&fsent)? 'l' : 'r');
642 printf("--------\n");
646 name = newstralloc(name, "/usr");
647 if(search_fstab(name, &fsent, 1) || search_fstab(name, &fsent, 0)) {
648 printf("Found %s mount for %s:\n",
649 is_local_fstype(&fsent)? "local" : "remote", name);
653 printf("Mount for %s not found\n", name);
655 name = newstralloc(name, "/");
656 if(search_fstab(name, &fsent, 1) || search_fstab(name, &fsent, 0)) {
657 printf("Found %s mount for %s:\n",
658 is_local_fstype(&fsent)? "local" : "remote", name);
662 printf("Mount for %s not found\n", name);
664 name = newstralloc(name, "/");
665 s = amname_to_fstype(name);
666 printf("fstype of `%s': %s\n", name, s);
668 name = newstralloc(name, "/dev/root");
669 s = amname_to_fstype(name);
670 printf("fstype of `%s': %s\n", name, s);
672 name = newstralloc(name, "/usr");
673 s = amname_to_fstype(name);
674 printf("fstype of `%s': %s\n", name, s);
676 name = newstralloc(name, "c0t3d0s0");
677 s = amname_to_fstype(name);
678 printf("fstype of `%s': %s\n", name, s);
681 name = newstralloc(name, "/tmp/foo");
682 s = amname_to_devname(name);
683 printf("device of `%s': %s\n", name, s);
685 s = amname_to_dirname(name);
686 printf("dirname of `%s': %s\n", name, s);
688 s = amname_to_fstype(name);
689 printf("fstype of `%s': %s\n", name, s);
692 name = newstralloc(name, "./foo");
693 s = amname_to_devname(name);
694 printf("device of `%s': %s\n", name, s);
696 s = amname_to_dirname(name);
697 printf("dirname of `%s': %s\n", name, s);
699 s = amname_to_fstype(name);
700 printf("fstype of `%s': %s\n", name, s);
704 name = newstralloc(name, *++argv);
705 s = amname_to_devname(name);
706 printf("device of `%s': %s\n", name, s);
708 s = amname_to_dirname(name);
709 printf("dirname of `%s': %s\n", name, s);
711 s = amname_to_fstype(name);
712 printf("fstype of `%s': %s\n", name, s);
718 malloc_size_2 = malloc_inuse(&malloc_hist_2);
720 if(malloc_size_1 != malloc_size_2) {
721 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);