Print this page
6198 Let's EOL cachefs


   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, "/");