xref: /linux-6.15/include/linux/fs_parser.h (revision 394033dc)
1b4d0d230SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
231d921c7SDavid Howells /* Filesystem parameter description and parser
331d921c7SDavid Howells  *
431d921c7SDavid Howells  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
531d921c7SDavid Howells  * Written by David Howells ([email protected])
631d921c7SDavid Howells  */
731d921c7SDavid Howells 
831d921c7SDavid Howells #ifndef _LINUX_FS_PARSER_H
931d921c7SDavid Howells #define _LINUX_FS_PARSER_H
1031d921c7SDavid Howells 
1131d921c7SDavid Howells #include <linux/fs_context.h>
1231d921c7SDavid Howells 
1331d921c7SDavid Howells struct path;
1431d921c7SDavid Howells 
1531d921c7SDavid Howells struct constant_table {
1631d921c7SDavid Howells 	const char	*name;
1731d921c7SDavid Howells 	int		value;
1831d921c7SDavid Howells };
1931d921c7SDavid Howells 
20328de528SAl Viro struct fs_parameter_spec;
21328de528SAl Viro struct fs_parse_result;
22328de528SAl Viro typedef int fs_param_type(struct p_log *,
23328de528SAl Viro 			  const struct fs_parameter_spec *,
24328de528SAl Viro 			  struct fs_parameter *,
25328de528SAl Viro 			  struct fs_parse_result *);
2631d921c7SDavid Howells /*
2731d921c7SDavid Howells  * The type of parameter expected.
2831d921c7SDavid Howells  */
29328de528SAl Viro fs_param_type fs_param_is_bool, fs_param_is_u32, fs_param_is_s32, fs_param_is_u64,
30328de528SAl Viro 	fs_param_is_enum, fs_param_is_string, fs_param_is_blob, fs_param_is_blockdev,
31c2f8fde8SChristian Brauner 	fs_param_is_path, fs_param_is_fd, fs_param_is_uid, fs_param_is_gid,
32c2f8fde8SChristian Brauner 	fs_param_is_file_or_string;
3331d921c7SDavid Howells 
3431d921c7SDavid Howells /*
3531d921c7SDavid Howells  * Specification of the type of value a parameter wants.
3631d921c7SDavid Howells  *
3731d921c7SDavid Howells  * Note that the fsparam_flag(), fsparam_string(), fsparam_u32(), ... macros
3831d921c7SDavid Howells  * should be used to generate elements of this type.
3931d921c7SDavid Howells  */
4031d921c7SDavid Howells struct fs_parameter_spec {
4131d921c7SDavid Howells 	const char		*name;
42328de528SAl Viro 	fs_param_type		*type;	/* The desired parameter type */
4331d921c7SDavid Howells 	u8			opt;	/* Option number (returned by fs_parse()) */
4431d921c7SDavid Howells 	unsigned short		flags;
4531d921c7SDavid Howells #define fs_param_neg_with_no	0x0002	/* "noxxx" is negative param */
466abfaaf1SLukas Czerner #define fs_param_can_be_empty	0x0004	/* "xxx=" is allowed */
4731d921c7SDavid Howells #define fs_param_deprecated	0x0008	/* The param is deprecated */
482710c957SAl Viro 	const void		*data;
4931d921c7SDavid Howells };
5031d921c7SDavid Howells 
5131d921c7SDavid Howells /*
5231d921c7SDavid Howells  * Result of parse.
5331d921c7SDavid Howells  */
5431d921c7SDavid Howells struct fs_parse_result {
5531d921c7SDavid Howells 	bool			negated;	/* T if param was "noxxx" */
5631d921c7SDavid Howells 	union {
5731d921c7SDavid Howells 		bool		boolean;	/* For spec_bool */
5831d921c7SDavid Howells 		int		int_32;		/* For spec_s32/spec_enum */
5931d921c7SDavid Howells 		unsigned int	uint_32;	/* For spec_u32{,_octal,_hex}/spec_enum */
6031d921c7SDavid Howells 		u64		uint_64;	/* For spec_u64 */
619f111059SEric Sandeen 		kuid_t		uid;
629f111059SEric Sandeen 		kgid_t		gid;
6331d921c7SDavid Howells 	};
6431d921c7SDavid Howells };
6531d921c7SDavid Howells 
667f5d3814SAl Viro extern int __fs_parse(struct p_log *log,
67d7167b14SAl Viro 		    const struct fs_parameter_spec *desc,
687f5d3814SAl Viro 		    struct fs_parameter *value,
697f5d3814SAl Viro 		    struct fs_parse_result *result);
70cc3c0b53SAl Viro 
fs_parse(struct fs_context * fc,const struct fs_parameter_spec * desc,struct fs_parameter * param,struct fs_parse_result * result)71cc3c0b53SAl Viro static inline int fs_parse(struct fs_context *fc,
72d7167b14SAl Viro 	     const struct fs_parameter_spec *desc,
73cc3c0b53SAl Viro 	     struct fs_parameter *param,
74cc3c0b53SAl Viro 	     struct fs_parse_result *result)
75cc3c0b53SAl Viro {
76cc3c0b53SAl Viro 	return __fs_parse(&fc->log, desc, param, result);
77cc3c0b53SAl Viro }
78cc3c0b53SAl Viro 
7931d921c7SDavid Howells extern int fs_lookup_param(struct fs_context *fc,
8031d921c7SDavid Howells 			   struct fs_parameter *param,
8131d921c7SDavid Howells 			   bool want_bdev,
82e3ea75eeSLukas Czerner 			   unsigned int flags,
8331d921c7SDavid Howells 			   struct path *_path);
8431d921c7SDavid Howells 
8534264ae3SAl Viro extern int lookup_constant(const struct constant_table tbl[], const char *name, int not_found);
8631d921c7SDavid Howells 
87*394033dcSIntegral extern const struct constant_table bool_names[];
88*394033dcSIntegral 
8931d921c7SDavid Howells #ifdef CONFIG_VALIDATE_FS_PARSER
9031d921c7SDavid Howells extern bool validate_constant_table(const struct constant_table *tbl, size_t tbl_size,
9131d921c7SDavid Howells 				    int low, int high, int special);
9296cafb9cSEric Sandeen extern bool fs_validate_description(const char *name,
93d7167b14SAl Viro 				    const struct fs_parameter_spec *desc);
9431d921c7SDavid Howells #else
validate_constant_table(const struct constant_table * tbl,size_t tbl_size,int low,int high,int special)9531d921c7SDavid Howells static inline bool validate_constant_table(const struct constant_table *tbl, size_t tbl_size,
9631d921c7SDavid Howells 					   int low, int high, int special)
9731d921c7SDavid Howells { return true; }
fs_validate_description(const char * name,const struct fs_parameter_spec * desc)9896cafb9cSEric Sandeen static inline bool fs_validate_description(const char *name,
99d7167b14SAl Viro 					   const struct fs_parameter_spec *desc)
10031d921c7SDavid Howells { return true; }
10131d921c7SDavid Howells #endif
10231d921c7SDavid Howells 
10331d921c7SDavid Howells /*
10431d921c7SDavid Howells  * Parameter type, name, index and flags element constructors.  Use as:
10531d921c7SDavid Howells  *
10631d921c7SDavid Howells  *  fsparam_xxxx("foo", Opt_foo)
10731d921c7SDavid Howells  *
10831d921c7SDavid Howells  * If existing helpers are not enough, direct use of __fsparam() would
10931d921c7SDavid Howells  * work, but any such case is probably a sign that new helper is needed.
11031d921c7SDavid Howells  * Helpers will remain stable; low-level implementation may change.
11131d921c7SDavid Howells  */
1122710c957SAl Viro #define __fsparam(TYPE, NAME, OPT, FLAGS, DATA) \
11331d921c7SDavid Howells 	{ \
11431d921c7SDavid Howells 		.name = NAME, \
11531d921c7SDavid Howells 		.opt = OPT, \
11631d921c7SDavid Howells 		.type = TYPE, \
1172710c957SAl Viro 		.flags = FLAGS, \
1182710c957SAl Viro 		.data = DATA \
11931d921c7SDavid Howells 	}
12031d921c7SDavid Howells 
121328de528SAl Viro #define fsparam_flag(NAME, OPT)	__fsparam(NULL, NAME, OPT, 0, NULL)
12231d921c7SDavid Howells #define fsparam_flag_no(NAME, OPT) \
123328de528SAl Viro 			__fsparam(NULL, NAME, OPT, fs_param_neg_with_no, NULL)
1242710c957SAl Viro #define fsparam_bool(NAME, OPT)	__fsparam(fs_param_is_bool, NAME, OPT, 0, NULL)
1252710c957SAl Viro #define fsparam_u32(NAME, OPT)	__fsparam(fs_param_is_u32, NAME, OPT, 0, NULL)
12631d921c7SDavid Howells #define fsparam_u32oct(NAME, OPT) \
127328de528SAl Viro 			__fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8)
12831d921c7SDavid Howells #define fsparam_u32hex(NAME, OPT) \
129ffbc3dd1SAlexey Dobriyan 			__fsparam(fs_param_is_u32_hex, NAME, OPT, 0, (void *)16)
1302710c957SAl Viro #define fsparam_s32(NAME, OPT)	__fsparam(fs_param_is_s32, NAME, OPT, 0, NULL)
1312710c957SAl Viro #define fsparam_u64(NAME, OPT)	__fsparam(fs_param_is_u64, NAME, OPT, 0, NULL)
1322710c957SAl Viro #define fsparam_enum(NAME, OPT, array)	__fsparam(fs_param_is_enum, NAME, OPT, 0, array)
13331d921c7SDavid Howells #define fsparam_string(NAME, OPT) \
1342710c957SAl Viro 				__fsparam(fs_param_is_string, NAME, OPT, 0, NULL)
1352710c957SAl Viro #define fsparam_blob(NAME, OPT)	__fsparam(fs_param_is_blob, NAME, OPT, 0, NULL)
1362710c957SAl Viro #define fsparam_bdev(NAME, OPT)	__fsparam(fs_param_is_blockdev, NAME, OPT, 0, NULL)
1372710c957SAl Viro #define fsparam_path(NAME, OPT)	__fsparam(fs_param_is_path, NAME, OPT, 0, NULL)
1382710c957SAl Viro #define fsparam_fd(NAME, OPT)	__fsparam(fs_param_is_fd, NAME, OPT, 0, NULL)
139c2f8fde8SChristian Brauner #define fsparam_file_or_string(NAME, OPT) \
140c2f8fde8SChristian Brauner 				__fsparam(fs_param_is_file_or_string, NAME, OPT, 0, NULL)
1419f111059SEric Sandeen #define fsparam_uid(NAME, OPT) __fsparam(fs_param_is_uid, NAME, OPT, 0, NULL)
1429f111059SEric Sandeen #define fsparam_gid(NAME, OPT) __fsparam(fs_param_is_gid, NAME, OPT, 0, NULL)
14331d921c7SDavid Howells 
1447b30851aSLuis Henriques (SUSE) /* String parameter that allows empty argument */
1457b30851aSLuis Henriques (SUSE) #define fsparam_string_empty(NAME, OPT) \
1467b30851aSLuis Henriques (SUSE) 	__fsparam(fs_param_is_string, NAME, OPT, fs_param_can_be_empty, NULL)
1477b30851aSLuis Henriques (SUSE) 
14831d921c7SDavid Howells #endif /* _LINUX_FS_PARSER_H */
149