6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * autod_parse.c
23 *
24 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/param.h>
35 #include <errno.h>
36 #include <pwd.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <sys/tiuser.h>
40 #include <locale.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <thread.h>
44 #include <rpc/rpc.h>
45 #include <rpcsvc/mount.h>
544 me->map_err = err;
545 if ((rc = set_mapent_opts(me, me->map_mntopts,
546 defaultopts, mapopts)) != PARSE_OK)
547 return (rc);
548 }
549
550 /* push the options to subdirs */
551 if (node->subdir != NULL) {
552 if (node->mapent && strcmp(node->mapent->map_fstype,
553 MNTTYPE_AUTOFS) == 0)
554 err = MAPENT_UATFS;
555 if ((rc = push_options(node->subdir, defaultopts,
556 mapopts, err)) != PARSE_OK)
557 return (rc);
558 }
559 node = node->leveldir;
560 }
561 return (rc);
562 }
563
564 #define BACKFSTYPE "backfstype" /* used in cachefs options */
565 #define BACKFSTYPE_EQ "backfstype="
566 #define FSTYPE "fstype"
567 #define FSTYPE_EQ "fstype="
568 #define NO_OPTS ""
569
570 /*
571 * set_mapent_opts(struct mapent *me, char *opts, char *defaultopts,
572 * char *mapopts)
573 * sets the mapentry's options, fstype and mounter fields by separating
574 * out the fstype part from the opts. Use default options if opts is NULL.
575 * Note taht defaultopts may be the same as mapopts.
576 * Returns PARSE_OK or appropriate error value.
577 */
578 static int
579 set_mapent_opts(struct mapent *me, char *opts, char *defaultopts,
580 char *mapopts)
581 {
582 char entryopts[AUTOFS_MAXOPTSLEN];
583 char fstype[MAX_FSLEN], mounter[MAX_FSLEN];
584 int rc = PARSE_OK;
585 bool_t fstype_opt = FALSE;
591 opts = defaultopts;
592 if (defaultopts == NULL) { /* NULL opts for entry */
593 strcpy(mounter, fstype);
594 goto done;
595 }
596 }
597 if (*opts == '-')
598 opts++;
599
600 /* separate opts into fstype and (other) entrypopts */
601 get_opts(opts, entryopts, fstype, &fstype_opt);
602
603 /* replace any existing opts */
604 if (me->map_mntopts != NULL)
605 free(me->map_mntopts);
606 if ((me->map_mntopts = strdup(entryopts)) == NULL)
607 return (ENOMEM);
608 strcpy(mounter, fstype);
609
610 /*
611 * The following ugly chunk of code crept in as a result of
612 * cachefs. If it's a cachefs mount of an nfs filesystem, then
613 * it's important to parse the nfs special field. Otherwise,
614 * just hand the special field to the fs-specific mount
615 */
616 if (strcmp(fstype, MNTTYPE_CACHEFS) == 0) {
617 struct mnttab m;
618 char *p;
619
620 m.mnt_mntopts = entryopts;
621 if ((p = hasmntopt(&m, BACKFSTYPE)) != NULL) {
622 int len = strlen(MNTTYPE_NFS);
623
624 p += strlen(BACKFSTYPE_EQ);
625
626 if (strncmp(p, MNTTYPE_NFS, len) == 0 &&
627 (p[len] == '\0' || p[len] == ',')) {
628 /*
629 * Cached nfs mount
630 */
631 (void) strcpy(fstype, MNTTYPE_NFS);
632 (void) strcpy(mounter, MNTTYPE_CACHEFS);
633 }
634 }
635 }
636
637 /*
638 * child options are exactly fstype = somefs, we need to do some
639 * more option pushing work.
640 */
641 if (fstype_opt == TRUE &&
642 (strcmp(me->map_mntopts, NO_OPTS) == 0)) {
643 free(me->map_mntopts);
644 if ((rc = fstype_opts(me, opts, defaultopts,
645 mapopts)) != PARSE_OK)
646 return (rc);
647 }
648
649 done:
650 if (((me->map_fstype = strdup(fstype)) == NULL) ||
651 ((me->map_mounter = strdup(mounter)) == NULL)) {
652 if (me->map_fstype != NULL)
653 free(me->map_fstype);
654 syslog(LOG_ERR, "set_mapent_opts: No memory");
655 return (ENOMEM);
656 }
657
658 return (rc);
659 }
660
661 /*
662 * Check the option string for an "fstype"
663 * option. If found, return the fstype
664 * and the option string with the fstype
665 * option removed, e.g.
666 *
667 * input: "fstype=cachefs,ro,nosuid"
668 * opts: "ro,nosuid"
669 * fstype: "cachefs"
670 *
671 * Also indicates if the fstype option was present
672 * by setting a flag, if the pointer to the flag
673 * is not NULL.
674 */
675 static void
676 get_opts(input, opts, fstype, fstype_opt)
677 char *input;
678 char *opts; /* output */
679 char *fstype; /* output */
680 bool_t *fstype_opt;
681 {
682 char *p, *pb;
683 char buf[MAXOPTSLEN];
684 char *placeholder;
685
686 *opts = '\0';
687 (void) strcpy(buf, input);
688 pb = buf;
689 while (p = (char *)strtok_r(pb, ",", &placeholder)) {
693 *fstype_opt = TRUE;
694 (void) strcpy(fstype, p + 7);
695 } else {
696 if (*opts)
697 (void) strcat(opts, ",");
698 (void) strcat(opts, p);
699 }
700 }
701 }
702
703 /*
704 * fstype_opts(struct mapent *me, char *opts, char *defaultopts,
705 * char *mapopts)
706 * We need to push global options to the child entry if it is exactly
707 * fstype=somefs.
708 */
709 static int
710 fstype_opts(struct mapent *me, char *opts, char *defaultopts,
711 char *mapopts)
712 {
713 char pushopts[AUTOFS_MAXOPTSLEN];
714 char pushentryopts[AUTOFS_MAXOPTSLEN];
715 char pushfstype[MAX_FSLEN];
716
717 if (defaultopts && *defaultopts == '-')
718 defaultopts++;
719
720 /*
721 * the options to push are the global defaults for the entry,
722 * if they exist, or mapopts, if the global defaults for the
723 * entry does not exist.
724 */
725 if (strcmp(defaultopts, opts) == 0) {
726 if (*mapopts == '-')
727 mapopts++;
728 get_opts(mapopts, pushentryopts, pushfstype, NULL);
729 strcpy(pushopts, mapopts);
730 } else {
731 get_opts(defaultopts, pushentryopts, pushfstype, NULL);
732 strcpy(pushopts, defaultopts);
733 }
734
735 if (strcmp(pushfstype, MNTTYPE_CACHEFS) == 0)
736 me->map_mntopts = strdup(pushopts);
737 else
738 me->map_mntopts = strdup(pushentryopts);
739
740 if (!me->map_mntopts) {
741 syslog(LOG_ERR, "fstype_opts: No memory");
742 return (ENOMEM);
743 }
744
745 return (PARSE_OK);
746 }
747
748 /*
749 * modify_mapents(struct mapent **mapents, char *mapname,
750 * char *mapopts, char *subdir, hiernode *rootnode,
751 * char *key, uint_t isdirect, bool_t mount_access)
752 * modifies the intermediate mapentry list into the final one, and passes
753 * back a pointer to it. The final list may contain faked mapentries for
754 * hiernodes that do not point to a mapentry, or converted mapentries, if
755 * hiernodes that point to a mapentry need to be converted from nfs to autofs.
756 * mounts. Entries that are not directly 1 level below the subdir are removed.
757 * Returns PARSE_OK or PARSE_ERROR
1972 exnext = ex->ex_next;
1973 exlen = strlen(ex->ex_dir);
1974 duplicate = 0;
1975 for (texp = &texlist; *texp; texp = &((*texp)->ex_next)) {
1976 if (exlen < (int)strlen((*texp)->ex_dir))
1977 break;
1978 duplicate = (strcmp(ex->ex_dir, (*texp)->ex_dir) == 0);
1979 if (duplicate) {
1980 /* disregard duplicate entry */
1981 freeex_ent(ex);
1982 break;
1983 }
1984 }
1985 if (!duplicate) {
1986 ex->ex_next = *texp;
1987 *texp = ex;
1988 }
1989 }
1990 exlist = texlist;
1991
1992 /*
1993 * The following ugly chunk of code crept in as
1994 * a result of cachefs. If it's a cachefs mount
1995 * of an nfs filesystem, then have it handled as
1996 * an nfs mount but have cachefs do the mount.
1997 */
1998 (void) strcpy(fstype, MNTTYPE_NFS);
1999 get_opts(mapopts, entryopts, fstype, NULL);
2000 (void) strcpy(mounter, fstype);
2001 if (strcmp(fstype, MNTTYPE_CACHEFS) == 0) {
2002 struct mnttab m;
2003 char *p;
2004
2005 m.mnt_mntopts = entryopts;
2006 if ((p = hasmntopt(&m, "backfstype")) != NULL) {
2007 int len = strlen(MNTTYPE_NFS);
2008
2009 p += 11;
2010 if (strncmp(p, MNTTYPE_NFS, len) == 0 &&
2011 (p[len] == '\0' || p[len] == ',')) {
2012 /*
2013 * Cached nfs mount
2014 */
2015 (void) strcpy(fstype, MNTTYPE_NFS);
2016 (void) strcpy(mounter, MNTTYPE_CACHEFS);
2017 }
2018 }
2019 }
2020
2021 /* Now create a mapent from the export list */
2022 ms = NULL;
2023 me = NULL;
2024
2025 for (ex = exlist; ex; ex = ex->ex_next) {
2026 mp = me;
2027 me = (struct mapent *)malloc(sizeof (*me));
2028 if (me == NULL)
2029 goto alloc_failed;
2030 (void) memset((char *)me, 0, sizeof (*me));
2031
2032 if (ms == NULL)
2033 ms = me;
2034 else
2035 mp->map_next = me;
2036
2037 if (isdirect)
2038 name[0] = '\0';
2039 else {
2040 (void) strcpy(name, "/");
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * autod_parse.c
23 *
24 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <syslog.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/param.h>
36 #include <errno.h>
37 #include <pwd.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #include <sys/tiuser.h>
41 #include <locale.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <thread.h>
45 #include <rpc/rpc.h>
46 #include <rpcsvc/mount.h>
545 me->map_err = err;
546 if ((rc = set_mapent_opts(me, me->map_mntopts,
547 defaultopts, mapopts)) != PARSE_OK)
548 return (rc);
549 }
550
551 /* push the options to subdirs */
552 if (node->subdir != NULL) {
553 if (node->mapent && strcmp(node->mapent->map_fstype,
554 MNTTYPE_AUTOFS) == 0)
555 err = MAPENT_UATFS;
556 if ((rc = push_options(node->subdir, defaultopts,
557 mapopts, err)) != PARSE_OK)
558 return (rc);
559 }
560 node = node->leveldir;
561 }
562 return (rc);
563 }
564
565 #define FSTYPE "fstype"
566 #define FSTYPE_EQ "fstype="
567 #define NO_OPTS ""
568
569 /*
570 * set_mapent_opts(struct mapent *me, char *opts, char *defaultopts,
571 * char *mapopts)
572 * sets the mapentry's options, fstype and mounter fields by separating
573 * out the fstype part from the opts. Use default options if opts is NULL.
574 * Note taht defaultopts may be the same as mapopts.
575 * Returns PARSE_OK or appropriate error value.
576 */
577 static int
578 set_mapent_opts(struct mapent *me, char *opts, char *defaultopts,
579 char *mapopts)
580 {
581 char entryopts[AUTOFS_MAXOPTSLEN];
582 char fstype[MAX_FSLEN], mounter[MAX_FSLEN];
583 int rc = PARSE_OK;
584 bool_t fstype_opt = FALSE;
590 opts = defaultopts;
591 if (defaultopts == NULL) { /* NULL opts for entry */
592 strcpy(mounter, fstype);
593 goto done;
594 }
595 }
596 if (*opts == '-')
597 opts++;
598
599 /* separate opts into fstype and (other) entrypopts */
600 get_opts(opts, entryopts, fstype, &fstype_opt);
601
602 /* replace any existing opts */
603 if (me->map_mntopts != NULL)
604 free(me->map_mntopts);
605 if ((me->map_mntopts = strdup(entryopts)) == NULL)
606 return (ENOMEM);
607 strcpy(mounter, fstype);
608
609 /*
610 * child options are exactly fstype = somefs, we need to do some
611 * more option pushing work.
612 */
613 if (fstype_opt == TRUE &&
614 (strcmp(me->map_mntopts, NO_OPTS) == 0)) {
615 free(me->map_mntopts);
616 if ((rc = fstype_opts(me, opts, defaultopts,
617 mapopts)) != PARSE_OK)
618 return (rc);
619 }
620
621 done:
622 if (((me->map_fstype = strdup(fstype)) == NULL) ||
623 ((me->map_mounter = strdup(mounter)) == NULL)) {
624 if (me->map_fstype != NULL)
625 free(me->map_fstype);
626 syslog(LOG_ERR, "set_mapent_opts: No memory");
627 return (ENOMEM);
628 }
629
630 return (rc);
631 }
632
633 /*
634 * Check the option string for an "fstype"
635 * option. If found, return the fstype
636 * and the option string with the fstype
637 * option removed, e.g.
638 *
639 * input: "fstype=nfs,ro,nosuid"
640 * opts: "ro,nosuid"
641 * fstype: "nfs"
642 *
643 * Also indicates if the fstype option was present
644 * by setting a flag, if the pointer to the flag
645 * is not NULL.
646 */
647 static void
648 get_opts(input, opts, fstype, fstype_opt)
649 char *input;
650 char *opts; /* output */
651 char *fstype; /* output */
652 bool_t *fstype_opt;
653 {
654 char *p, *pb;
655 char buf[MAXOPTSLEN];
656 char *placeholder;
657
658 *opts = '\0';
659 (void) strcpy(buf, input);
660 pb = buf;
661 while (p = (char *)strtok_r(pb, ",", &placeholder)) {
665 *fstype_opt = TRUE;
666 (void) strcpy(fstype, p + 7);
667 } else {
668 if (*opts)
669 (void) strcat(opts, ",");
670 (void) strcat(opts, p);
671 }
672 }
673 }
674
675 /*
676 * fstype_opts(struct mapent *me, char *opts, char *defaultopts,
677 * char *mapopts)
678 * We need to push global options to the child entry if it is exactly
679 * fstype=somefs.
680 */
681 static int
682 fstype_opts(struct mapent *me, char *opts, char *defaultopts,
683 char *mapopts)
684 {
685 char pushentryopts[AUTOFS_MAXOPTSLEN];
686 char pushfstype[MAX_FSLEN];
687
688 if (defaultopts && *defaultopts == '-')
689 defaultopts++;
690
691 /*
692 * the options to push are the global defaults for the entry,
693 * if they exist, or mapopts, if the global defaults for the
694 * entry does not exist.
695 */
696 if (strcmp(defaultopts, opts) == 0) {
697 if (*mapopts == '-')
698 mapopts++;
699 get_opts(mapopts, pushentryopts, pushfstype, NULL);
700 } else {
701 get_opts(defaultopts, pushentryopts, pushfstype, NULL);
702 }
703
704 me->map_mntopts = strdup(pushentryopts);
705
706 if (!me->map_mntopts) {
707 syslog(LOG_ERR, "fstype_opts: No memory");
708 return (ENOMEM);
709 }
710
711 return (PARSE_OK);
712 }
713
714 /*
715 * modify_mapents(struct mapent **mapents, char *mapname,
716 * char *mapopts, char *subdir, hiernode *rootnode,
717 * char *key, uint_t isdirect, bool_t mount_access)
718 * modifies the intermediate mapentry list into the final one, and passes
719 * back a pointer to it. The final list may contain faked mapentries for
720 * hiernodes that do not point to a mapentry, or converted mapentries, if
721 * hiernodes that point to a mapentry need to be converted from nfs to autofs.
722 * mounts. Entries that are not directly 1 level below the subdir are removed.
723 * Returns PARSE_OK or PARSE_ERROR
1938 exnext = ex->ex_next;
1939 exlen = strlen(ex->ex_dir);
1940 duplicate = 0;
1941 for (texp = &texlist; *texp; texp = &((*texp)->ex_next)) {
1942 if (exlen < (int)strlen((*texp)->ex_dir))
1943 break;
1944 duplicate = (strcmp(ex->ex_dir, (*texp)->ex_dir) == 0);
1945 if (duplicate) {
1946 /* disregard duplicate entry */
1947 freeex_ent(ex);
1948 break;
1949 }
1950 }
1951 if (!duplicate) {
1952 ex->ex_next = *texp;
1953 *texp = ex;
1954 }
1955 }
1956 exlist = texlist;
1957
1958 (void) strcpy(fstype, MNTTYPE_NFS);
1959 get_opts(mapopts, entryopts, fstype, NULL);
1960 (void) strcpy(mounter, fstype);
1961
1962 /* Now create a mapent from the export list */
1963 ms = NULL;
1964 me = NULL;
1965
1966 for (ex = exlist; ex; ex = ex->ex_next) {
1967 mp = me;
1968 me = (struct mapent *)malloc(sizeof (*me));
1969 if (me == NULL)
1970 goto alloc_failed;
1971 (void) memset((char *)me, 0, sizeof (*me));
1972
1973 if (ms == NULL)
1974 ms = me;
1975 else
1976 mp->map_next = me;
1977
1978 if (isdirect)
1979 name[0] = '\0';
1980 else {
1981 (void) strcpy(name, "/");
|