1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "analyze-condition.h"
7 #include "conf-parser.h"
8 #include "load-fragment.h"
11 typedef struct condition_definition
{
13 ConfigParserCallback parser
;
15 } condition_definition
;
17 static const condition_definition condition_definitions
[] = {
18 { "ConditionPathExists", config_parse_unit_condition_path
, CONDITION_PATH_EXISTS
},
19 { "ConditionPathExistsGlob", config_parse_unit_condition_path
, CONDITION_PATH_EXISTS_GLOB
},
20 { "ConditionPathIsDirectory", config_parse_unit_condition_path
, CONDITION_PATH_IS_DIRECTORY
},
21 { "ConditionPathIsSymbolicLink", config_parse_unit_condition_path
, CONDITION_PATH_IS_SYMBOLIC_LINK
},
22 { "ConditionPathIsMountPoint", config_parse_unit_condition_path
, CONDITION_PATH_IS_MOUNT_POINT
},
23 { "ConditionPathIsReadWrite", config_parse_unit_condition_path
, CONDITION_PATH_IS_READ_WRITE
},
24 { "ConditionDirectoryNotEmpty", config_parse_unit_condition_path
, CONDITION_DIRECTORY_NOT_EMPTY
},
25 { "ConditionFileNotEmpty", config_parse_unit_condition_path
, CONDITION_FILE_NOT_EMPTY
},
26 { "ConditionFileIsExecutable", config_parse_unit_condition_path
, CONDITION_FILE_IS_EXECUTABLE
},
27 { "ConditionNeedsUpdate", config_parse_unit_condition_path
, CONDITION_NEEDS_UPDATE
},
28 { "ConditionFirstBoot", config_parse_unit_condition_string
, CONDITION_FIRST_BOOT
},
29 { "ConditionKernelCommandLine", config_parse_unit_condition_string
, CONDITION_KERNEL_COMMAND_LINE
},
30 { "ConditionKernelVersion", config_parse_unit_condition_string
, CONDITION_KERNEL_VERSION
},
31 { "ConditionArchitecture", config_parse_unit_condition_string
, CONDITION_ARCHITECTURE
},
32 { "ConditionVirtualization", config_parse_unit_condition_string
, CONDITION_VIRTUALIZATION
},
33 { "ConditionSecurity", config_parse_unit_condition_string
, CONDITION_SECURITY
},
34 { "ConditionCapability", config_parse_unit_condition_string
, CONDITION_CAPABILITY
},
35 { "ConditionHost", config_parse_unit_condition_string
, CONDITION_HOST
},
36 { "ConditionACPower", config_parse_unit_condition_string
, CONDITION_AC_POWER
},
37 { "ConditionUser", config_parse_unit_condition_string
, CONDITION_USER
},
38 { "ConditionGroup", config_parse_unit_condition_string
, CONDITION_GROUP
},
39 { "ConditionControlGroupController", config_parse_unit_condition_string
, CONDITION_CONTROL_GROUP_CONTROLLER
},
41 { "AssertPathExists", config_parse_unit_condition_path
, CONDITION_PATH_EXISTS
},
42 { "AssertPathExistsGlob", config_parse_unit_condition_path
, CONDITION_PATH_EXISTS_GLOB
},
43 { "AssertPathIsDirectory", config_parse_unit_condition_path
, CONDITION_PATH_IS_DIRECTORY
},
44 { "AssertPathIsSymbolicLink", config_parse_unit_condition_path
, CONDITION_PATH_IS_SYMBOLIC_LINK
},
45 { "AssertPathIsMountPoint", config_parse_unit_condition_path
, CONDITION_PATH_IS_MOUNT_POINT
},
46 { "AssertPathIsReadWrite", config_parse_unit_condition_path
, CONDITION_PATH_IS_READ_WRITE
},
47 { "AssertDirectoryNotEmpty", config_parse_unit_condition_path
, CONDITION_DIRECTORY_NOT_EMPTY
},
48 { "AssertFileNotEmpty", config_parse_unit_condition_path
, CONDITION_FILE_NOT_EMPTY
},
49 { "AssertFileIsExecutable", config_parse_unit_condition_path
, CONDITION_FILE_IS_EXECUTABLE
},
50 { "AssertNeedsUpdate", config_parse_unit_condition_path
, CONDITION_NEEDS_UPDATE
},
51 { "AssertFirstBoot", config_parse_unit_condition_string
, CONDITION_FIRST_BOOT
},
52 { "AssertKernelCommandLine", config_parse_unit_condition_string
, CONDITION_KERNEL_COMMAND_LINE
},
53 { "AssertKernelVersion", config_parse_unit_condition_string
, CONDITION_KERNEL_VERSION
},
54 { "AssertArchitecture", config_parse_unit_condition_string
, CONDITION_ARCHITECTURE
},
55 { "AssertVirtualization", config_parse_unit_condition_string
, CONDITION_VIRTUALIZATION
},
56 { "AssertSecurity", config_parse_unit_condition_string
, CONDITION_SECURITY
},
57 { "AssertCapability", config_parse_unit_condition_string
, CONDITION_CAPABILITY
},
58 { "AssertHost", config_parse_unit_condition_string
, CONDITION_HOST
},
59 { "AssertACPower", config_parse_unit_condition_string
, CONDITION_AC_POWER
},
60 { "AssertUser", config_parse_unit_condition_string
, CONDITION_USER
},
61 { "AssertGroup", config_parse_unit_condition_string
, CONDITION_GROUP
},
62 { "AssertControlGroupController", config_parse_unit_condition_string
, CONDITION_CONTROL_GROUP_CONTROLLER
},
64 /* deprecated, but we should still parse them */
65 { "ConditionNull", config_parse_unit_condition_null
, 0 },
66 { "AssertNull", config_parse_unit_condition_null
, 0 },
69 static int parse_condition(Unit
*u
, const char *line
) {
73 if ((p
= startswith(line
, "Condition")))
74 target
= &u
->conditions
;
75 else if ((p
= startswith(line
, "Assert")))
78 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Cannot parse \"%s\".", line
);
80 for (size_t i
= 0; i
< ELEMENTSOF(condition_definitions
); i
++) {
81 const condition_definition
*c
= &condition_definitions
[i
];
83 p
= startswith(line
, c
->name
);
86 p
+= strspn(p
, WHITESPACE
);
88 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Expected \"=\" in \"%s\".", line
);
90 p
+= 1 + strspn(p
+ 1, WHITESPACE
);
92 return c
->parser(NULL
, "(stdin)", 0, NULL
, 0, c
->name
, c
->type
, p
, target
, u
);
95 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Cannot parse \"%s\".", line
);
99 static int log_helper(void *userdata
, int level
, int error
, const char *file
, int line
, const char *func
, const char *format
, ...) {
106 /* "upgrade" debug messages */
107 level
= MIN(LOG_INFO
, level
);
109 va_start(ap
, format
);
110 r
= log_object_internalv(level
, error
, file
, line
, func
,
121 int verify_conditions(char **lines
, UnitFileScope scope
) {
122 _cleanup_(manager_freep
) Manager
*m
= NULL
;
127 r
= manager_new(scope
, MANAGER_TEST_RUN_MINIMAL
, &m
);
129 return log_error_errno(r
, "Failed to initialize manager: %m");
131 log_debug("Starting manager...");
132 r
= manager_startup(m
, NULL
, NULL
);
136 r
= unit_new_for_name(m
, sizeof(Service
), "test.service", &u
);
138 return log_error_errno(r
, "Failed to create test.service: %m");
140 STRV_FOREACH(line
, lines
) {
141 r
= parse_condition(u
, *line
);
146 r
= condition_test_list(u
->asserts
, assert_type_to_string
, log_helper
, u
);
148 log_notice("Asserts %s.", r
> 0 ? "succeeded" : "failed");
150 q
= condition_test_list(u
->conditions
, condition_type_to_string
, log_helper
, u
);
152 log_notice("Conditions %s.", q
> 0 ? "succeeded" : "failed");
154 return r
> 0 && q
> 0 ? 0 : -EIO
;