Skip to content

Commit a1c403d

Browse files
ethan-thompsonalandekok
authored andcommitted
feature: Added mkdir and rmdir xlats and updated docs and tests
Signed-off-by: ethan-thompson <ethan.thompson@networkradius.com>
1 parent b8f4ff6 commit a1c403d

File tree

4 files changed

+103
-0
lines changed

4 files changed

+103
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
= mkdir
2+
3+
The `mkdir` function creates directories and subdirectories. If the directory exists or was created successfully, it returns `true`. Otherwise if it could not be created, it returns `false.
4+
5+
[#syntax]
6+
== Syntax
7+
8+
`%file.mkdir(_string_)`
9+
10+
.Return: _bool_
11+
12+
.Create a directory
13+
====
14+
[source,unlang]
15+
----
16+
%file.mkdir("/var/log/radius/auth")
17+
----
18+
====
19+
20+
// Copyright (C) 2026 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
21+
// This documentation was developed by Network RADIUS SAS.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
= rmdir
2+
3+
The `rmdir` function removes a directory. If the directory exists and could be removed, it returns `true`. Otherwise if the directory does not exist, or if the directory could not be removed, it returns `false.
4+
5+
[#syntax]
6+
== Syntax
7+
8+
`%file.rmdir(_string_)`
9+
10+
.Return: _bool_
11+
12+
.Removing a directory
13+
====
14+
[source,unlang]
15+
----
16+
%file.rmdir("/var/log/radius/auth")
17+
----
18+
====
19+
20+
// Copyright (C) 2026 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
21+
// This documentation was developed by Network RADIUS SAS.

src/lib/unlang/xlat_builtin.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,48 @@ static xlat_action_t xlat_func_file_touch(TALLOC_CTX *ctx, fr_dcursor_t *out, UN
844844
return XLAT_ACTION_DONE;
845845
}
846846

847+
static xlat_action_t xlat_func_file_mkdir(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx,
848+
request_t *request, fr_value_box_list_t *args)
849+
{
850+
fr_value_box_t *dst, *vb;
851+
char const *dirname;
852+
853+
XLAT_ARGS(args, &vb);
854+
fr_assert(vb->type == FR_TYPE_STRING);
855+
dirname = vb->vb_strvalue;
856+
857+
MEM(dst = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL));
858+
fr_dcursor_append(out, dst);
859+
860+
dst->vb_bool = (fr_mkdir(NULL, dirname, -1, 0700, NULL, NULL) == 0);
861+
if (!dst->vb_bool) {
862+
REDEBUG3("Failed creating directory %s - %s", dirname, fr_syserror(errno));
863+
}
864+
865+
return XLAT_ACTION_DONE;
866+
}
867+
868+
static xlat_action_t xlat_func_file_rmdir(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx,
869+
request_t *request, fr_value_box_list_t *args)
870+
{
871+
fr_value_box_t *dst, *vb;
872+
char const *dirname;
873+
874+
XLAT_ARGS(args, &vb);
875+
fr_assert(vb->type == FR_TYPE_STRING);
876+
dirname = vb->vb_strvalue;
877+
878+
MEM(dst = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL));
879+
fr_dcursor_append(out, dst);
880+
881+
dst->vb_bool = (rmdir(dirname) == 0);
882+
if (!dst->vb_bool) {
883+
REDEBUG3("Failed removing directory %s - %s", dirname, fr_syserror(errno));
884+
}
885+
886+
return XLAT_ACTION_DONE;
887+
}
888+
847889
static xlat_arg_parser_t const xlat_func_taint_args[] = {
848890
{ .required = true, .type = FR_TYPE_VOID },
849891
{ .variadic = XLAT_ARG_VARIADIC_EMPTY_KEEP, .type = FR_TYPE_VOID },
@@ -4759,6 +4801,8 @@ do { \
47594801
XLAT_REGISTER_ARGS("file.size", xlat_func_file_size, FR_TYPE_UINT64, xlat_func_file_name_args);
47604802
XLAT_REGISTER_ARGS("file.tail", xlat_func_file_tail, FR_TYPE_STRING, xlat_func_file_name_count_args);
47614803
XLAT_REGISTER_ARGS("file.cat", xlat_func_file_cat, FR_TYPE_OCTETS, xlat_func_file_cat_args);
4804+
XLAT_REGISTER_ARGS("file.mkdir", xlat_func_file_mkdir, FR_TYPE_BOOL, xlat_func_file_name_args);
4805+
XLAT_REGISTER_ARGS("file.rmdir", xlat_func_file_rmdir, FR_TYPE_BOOL, xlat_func_file_name_args);
47624806

47634807
XLAT_REGISTER_ARGS("immutable", xlat_func_immutable_attr, FR_TYPE_NULL, xlat_pair_cursor_args);
47644808
XLAT_NEW("pairs.immutable");

src/tests/xlat/file.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ match no
3737
xlat_expr "foo/bar/" + %file.escape(%taint('..baz'))
3838
match foo/bar/_x2e_x2ebaz
3939

40+
xlat_expr %file.mkdir('src/tests/xlat/file/new-dir')
41+
xlat_expr %file.exists('src/tests/xlat/file/new-dir')
42+
match yes
43+
44+
xlat_expr %file.rmdir('src/tests/xlat/file/new-dir')
45+
xlat_expr %file.exists('src/tests/xlat/file/new-dir')
46+
match no
47+
48+
xlat_expr %file.mkdir('src/tests/xlat/file/nested/dir')
49+
xlat_expr %file.exists('src/tests/xlat/file/nested/dir')
50+
match yes
51+
52+
xlat_expr %file.rmdir('src/tests/xlat/file/nested/dir')
53+
xlat_expr %file.rmdir('src/tests/xlat/file/nested')
54+
xlat_expr %file.exists('src/tests/xlat/file/nested/dir')
55+
match no
56+
4057
#
4158
# Can now do expressions as function arguments
4259
#

0 commit comments

Comments
 (0)