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