(root)/
util-linux-2.39/
libmount/
src/
optmap.c
       1  /* SPDX-License-Identifier: LGPL-2.1-or-later */
       2  /*
       3   * This file is part of libmount from util-linux project.
       4   *
       5   * Copyright (C) 2010-2018 Karel Zak <kzak@redhat.com>
       6   *
       7   * libmount is free software; you can redistribute it and/or modify it
       8   * under the terms of the GNU Lesser General Public License as published by
       9   * the Free Software Foundation; either version 2.1 of the License, or
      10   * (at your option) any later version.
      11   */
      12  
      13  /**
      14   * SECTION: optmap
      15   * @title: Option maps
      16   * @short_description: description for mount options
      17   *
      18   * The mount(2) linux syscall uses two arguments for mount options:
      19   *
      20   *	@mountflags: (see MS_* macros in linux/fs.h)
      21   *
      22   *	@mountdata: (usually a comma separated string of options)
      23   *
      24   * The libmount uses options-map(s) to describe mount options.
      25   *
      26   * The option description (map entry) includes:
      27   *
      28   *	@name: and argument name
      29   *
      30   *	@id: (in the map unique identifier or a mountflags, e.g MS_RDONLY)
      31   *
      32   *	@mask: (MNT_INVERT, MNT_NOMTAB)
      33   *
      34   * The option argument value is defined by:
      35   *
      36   *	"="   -- required argument, e.g "comment="
      37   *
      38   *	"[=]" -- optional argument, e.g. "loop[=]"
      39   *
      40   * Example:
      41   *
      42   * <informalexample>
      43   *   <programlisting>
      44   *     #define MY_MS_FOO   (1 << 1)
      45   *     #define MY_MS_BAR   (1 << 2)
      46   *
      47   *     libmnt_optmap myoptions[] = {
      48   *       { "foo",   MY_MS_FOO },
      49   *       { "nofoo", MY_MS_FOO | MNT_INVERT },
      50   *       { "bar=",  MY_MS_BAR },
      51   *       { NULL }
      52   *     };
      53   *   </programlisting>
      54   * </informalexample>
      55   *
      56   * The libmount defines two basic built-in options maps:
      57   *
      58   *	@MNT_LINUX_MAP: fs-independent kernel mount options (usually MS_* flags)
      59   *
      60   *	@MNT_USERSPACE_MAP: userspace specific mount options (e.g. "user", "loop")
      61   *
      62   * For more details about option map struct see "struct mnt_optmap" in
      63   * mount/mount.h.
      64   */
      65  #include "mountP.h"
      66  #include "strutils.h"
      67  
      68  /*
      69   * fs-independent mount flags (built-in MNT_LINUX_MAP)
      70   */
      71  static const struct libmnt_optmap linux_flags_map[] =
      72  {
      73     { "ro",       MS_RDONLY },                 /* read-only */
      74     { "rw",       MS_RDONLY, MNT_INVERT },     /* read-write */
      75     { "exec",     MS_NOEXEC, MNT_INVERT },     /* permit execution of binaries */
      76     { "noexec",   MS_NOEXEC },                 /* don't execute binaries */
      77     { "suid",     MS_NOSUID, MNT_INVERT },     /* honor suid executables */
      78     { "nosuid",   MS_NOSUID },                 /* don't honor suid executables */
      79     { "dev",      MS_NODEV, MNT_INVERT },      /* interpret device files  */
      80     { "nodev",    MS_NODEV },                  /* don't interpret devices */
      81  
      82     { "sync",     MS_SYNCHRONOUS },            /* synchronous I/O */
      83     { "async",    MS_SYNCHRONOUS, MNT_INVERT },/* asynchronous I/O */
      84  
      85     { "dirsync",  MS_DIRSYNC },                /* synchronous directory modifications */
      86     { "remount",  MS_REMOUNT, MNT_NOMTAB },    /* alter flags of mounted FS */
      87     { "bind",     MS_BIND },                   /* Remount part of the tree elsewhere */
      88     { "rbind",    MS_BIND | MS_REC },          /* Idem, plus mounted subtrees */
      89  #ifdef MS_NOSUB
      90     { "sub",      MS_NOSUB, MNT_INVERT },      /* allow submounts */
      91     { "nosub",    MS_NOSUB },                  /* don't allow submounts */
      92  #endif
      93  #ifdef MS_SILENT
      94     { "silent",	 MS_SILENT },                 /* be quiet  */
      95     { "loud",     MS_SILENT, MNT_INVERT },     /* print out messages. */
      96  #endif
      97  #ifdef MS_MANDLOCK
      98     { "mand",     MS_MANDLOCK },               /* Allow mandatory locks on this FS */
      99     { "nomand",   MS_MANDLOCK, MNT_INVERT },   /* Forbid mandatory locks on this FS */
     100  #endif
     101  #ifdef MS_NOATIME
     102     { "atime",    MS_NOATIME, MNT_INVERT },    /* Update access time */
     103     { "noatime",	 MS_NOATIME },                /* Do not update access time */
     104  #endif
     105  #ifdef MS_I_VERSION
     106     { "iversion", MS_I_VERSION },              /* Update inode I_version time */
     107     { "noiversion", MS_I_VERSION,  MNT_INVERT},/* Don't update inode I_version time */
     108  #endif
     109  #ifdef MS_NODIRATIME
     110     { "diratime", MS_NODIRATIME, MNT_INVERT }, /* Update dir access times */
     111     { "nodiratime", MS_NODIRATIME },           /* Do not update dir access times */
     112  #endif
     113  #ifdef MS_RELATIME
     114     { "relatime", MS_RELATIME },               /* Update access times relative to mtime/ctime */
     115     { "norelatime", MS_RELATIME, MNT_INVERT }, /* Update access time without regard to mtime/ctime */
     116  #endif
     117  #ifdef MS_STRICTATIME
     118     { "strictatime", MS_STRICTATIME },         /* Strict atime semantics */
     119     { "nostrictatime", MS_STRICTATIME, MNT_INVERT }, /* kernel default atime */
     120  #endif
     121  #ifdef MS_LAZYTIME
     122     { "lazytime", MS_LAZYTIME },               /* Update {a,m,c}time on the in-memory inode only */
     123     { "nolazytime", MS_LAZYTIME, MNT_INVERT },
     124  #endif
     125  #ifdef MS_PROPAGATION
     126     { "unbindable",  MS_UNBINDABLE,          MNT_NOHLPS | MNT_NOMTAB }, /* Unbindable */
     127     { "runbindable", MS_UNBINDABLE | MS_REC, MNT_NOHLPS | MNT_NOMTAB },
     128     { "private",     MS_PRIVATE,             MNT_NOHLPS | MNT_NOMTAB }, /* Private */
     129     { "rprivate",    MS_PRIVATE | MS_REC,    MNT_NOHLPS | MNT_NOMTAB },
     130     { "slave",       MS_SLAVE,               MNT_NOHLPS | MNT_NOMTAB }, /* Slave */
     131     { "rslave",      MS_SLAVE | MS_REC,      MNT_NOHLPS | MNT_NOMTAB },
     132     { "shared",      MS_SHARED,              MNT_NOHLPS | MNT_NOMTAB }, /* Shared */
     133     { "rshared",     MS_SHARED | MS_REC,     MNT_NOHLPS | MNT_NOMTAB },
     134  #endif
     135  #ifdef MS_NOSYMFOLLOW
     136     { "symfollow", MS_NOSYMFOLLOW, MNT_INVERT }, /* Don't follow symlinks */
     137     { "nosymfollow", MS_NOSYMFOLLOW },
     138  #endif
     139  #ifdef MS_MOVE
     140     { "move",	MS_MOVE,	MNT_NOHLPS | MNT_NOMTAB | MNT_NOFSTAB }, /* --move */
     141  #endif
     142     { NULL, 0, 0 }
     143  };
     144  
     145  /*
     146   * userspace mount option (built-in MNT_USERSPACE_MAP)
     147   */
     148  static const struct libmnt_optmap userspace_opts_map[] =
     149  {
     150     { "defaults", 0, 0 },               /* default options */
     151  
     152     { "auto",    MNT_MS_NOAUTO, MNT_NOHLPS | MNT_INVERT | MNT_NOMTAB },  /* Can be mounted using -a */
     153     { "noauto",  MNT_MS_NOAUTO, MNT_NOHLPS | MNT_NOMTAB },  /* Can only be mounted explicitly */
     154  
     155     { "user[=]", MNT_MS_USER },                             /* Allow ordinary user to mount (mtab) */
     156     { "nouser",  MNT_MS_USER, MNT_INVERT | MNT_NOMTAB },    /* Forbid ordinary user to mount */
     157  
     158     { "users",   MNT_MS_USERS, MNT_NOMTAB },                /* Allow ordinary users to mount */
     159     { "nousers", MNT_MS_USERS, MNT_INVERT | MNT_NOMTAB },   /* Forbid ordinary users to mount */
     160  
     161     { "owner",   MNT_MS_OWNER, MNT_NOMTAB },                /* Let the owner of the device mount */
     162     { "noowner", MNT_MS_OWNER, MNT_INVERT | MNT_NOMTAB },   /* Device owner has no special privs */
     163  
     164     { "group",   MNT_MS_GROUP, MNT_NOMTAB },                /* Let the group of the device mount */
     165     { "nogroup", MNT_MS_GROUP, MNT_INVERT | MNT_NOMTAB },   /* Device group has no special privs */
     166  
     167     /*
     168      * Note that traditional init scripts assume the _netdev option in /etc/mtab to
     169      * umount network block devices on shutdown.
     170      */
     171     { "_netdev", MNT_MS_NETDEV },                           /* Device requires network */
     172  
     173     { "comment=", MNT_MS_COMMENT, MNT_NOHLPS | MNT_NOMTAB },/* fstab comment only */
     174  
     175     { "x-",      MNT_MS_XCOMMENT,   MNT_NOHLPS | MNT_PREFIX },              /* persistent comments (utab) */
     176     { "X-",      MNT_MS_XFSTABCOMM, MNT_NOHLPS | MNT_NOMTAB | MNT_PREFIX }, /* fstab only comments */
     177  
     178     { "loop[=]", MNT_MS_LOOP, MNT_NOHLPS },                             /* use the loop device */
     179     { "offset=", MNT_MS_OFFSET, MNT_NOHLPS | MNT_NOMTAB },		   /* loop device offset */
     180     { "sizelimit=", MNT_MS_SIZELIMIT, MNT_NOHLPS | MNT_NOMTAB },	   /* loop device size limit */
     181     { "encryption=", MNT_MS_ENCRYPTION, MNT_NOHLPS | MNT_NOMTAB },	   /* loop device encryption */
     182  
     183     { "nofail",  MNT_MS_NOFAIL, MNT_NOMTAB },               /* Do not fail if ENOENT on dev */
     184  
     185     { "uhelper=", MNT_MS_UHELPER },			   /* /sbin/umount.<helper> */
     186  
     187     { "helper=", MNT_MS_HELPER },			   /* /sbin/mount.<helper> */
     188  
     189     { "verity.hashdevice=", MNT_MS_HASH_DEVICE, MNT_NOHLPS | MNT_NOMTAB },     /* mount a verity device */
     190     { "verity.roothash=",   MNT_MS_ROOT_HASH, MNT_NOHLPS | MNT_NOMTAB },		   /* verity device root hash */
     191     { "verity.hashoffset=", MNT_MS_HASH_OFFSET, MNT_NOHLPS | MNT_NOMTAB },	   /* verity device hash offset */
     192     { "verity.roothashfile=", MNT_MS_ROOT_HASH_FILE, MNT_NOHLPS | MNT_NOMTAB },/* verity device root hash (read from file) */
     193     { "verity.fecdevice=",   MNT_MS_FEC_DEVICE, MNT_NOHLPS | MNT_NOMTAB },		/* verity FEC device */
     194     { "verity.fecoffset=", MNT_MS_FEC_OFFSET, MNT_NOHLPS | MNT_NOMTAB },	      /* verity FEC area offset */
     195     { "verity.fecroots=", MNT_MS_FEC_ROOTS, MNT_NOHLPS | MNT_NOMTAB },	      /* verity FEC roots */
     196     { "verity.roothashsig=",    MNT_MS_ROOT_HASH_SIG, MNT_NOHLPS | MNT_NOMTAB },	/* verity device root hash signature file */
     197     { "verity.oncorruption=",   MNT_MS_VERITY_ON_CORRUPTION, MNT_NOHLPS | MNT_NOMTAB },	/* verity: action the kernel takes on corruption */
     198  
     199     { NULL, 0, 0 }
     200  };
     201  
     202  /**
     203   * mnt_get_builtin_map:
     204   * @id: map id -- MNT_LINUX_MAP or MNT_USERSPACE_MAP
     205   *
     206   * MNT_LINUX_MAP - Linux kernel fs-independent mount options
     207   *                 (usually MS_* flags, see linux/fs.h)
     208   *
     209   * MNT_USERSPACE_MAP - userspace mount(8) specific mount options
     210   *                     (e.g user=, _netdev, ...)
     211   *
     212   * Returns: static built-in libmount map.
     213   */
     214  const struct libmnt_optmap *mnt_get_builtin_optmap(int id)
     215  {
     216  	assert(id);
     217  
     218  	if (id == MNT_LINUX_MAP)
     219  		return linux_flags_map;
     220  	if (id == MNT_USERSPACE_MAP)
     221  		return userspace_opts_map;
     222  	return NULL;
     223  }
     224  
     225  /*
     226   * Looks up the @name in @maps and returns a map and in @mapent
     227   * returns the map entry
     228   */
     229  const struct libmnt_optmap *mnt_optmap_get_entry(
     230  				struct libmnt_optmap const **maps,
     231  				int nmaps,
     232  				const char *name,
     233  				size_t namelen,
     234  				const struct libmnt_optmap **mapent)
     235  {
     236  	int i;
     237  
     238  	assert(maps);
     239  	assert(nmaps);
     240  	assert(name);
     241  	assert(namelen);
     242  
     243  	if (mapent)
     244  		*mapent = NULL;
     245  
     246  	for (i = 0; i < nmaps; i++) {
     247  		const struct libmnt_optmap *map = maps[i];
     248  		const struct libmnt_optmap *ent;
     249  		const char *p;
     250  
     251  		for (ent = map; ent && ent->name; ent++) {
     252  			if (ent->mask & MNT_PREFIX) {
     253  				if (startswith(name, ent->name)) {
     254  					if (mapent)
     255  						*mapent = ent;
     256  					return map;
     257  				}
     258  				continue;
     259  			}
     260  			if (strncmp(ent->name, name, namelen) != 0)
     261  				continue;
     262  			p = ent->name + namelen;
     263  			if (*p == '\0' || *p == '=' || *p == '[') {
     264  				if (mapent)
     265  					*mapent = ent;
     266  				return map;
     267  			}
     268  		}
     269  	}
     270  	return NULL;
     271  }
     272