1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 #include <getopt.h>
5 #include <stdbool.h>
6 #include <stdlib.h>
7 
8 #include "alloc-util.h"
9 #include "main-func.h"
10 #include "pretty-print.h"
11 #include "string-table.h"
12 #include "util.h"
13 #include "virt.h"
14 
15 static bool arg_quiet = false;
16 static enum {
17         ANY_VIRTUALIZATION,
18         ONLY_VM,
19         ONLY_CONTAINER,
20         ONLY_CHROOT,
21         ONLY_PRIVATE_USERS,
22 } arg_mode = ANY_VIRTUALIZATION;
23 
help(void)24 static int help(void) {
25         _cleanup_free_ char *link = NULL;
26         int r;
27 
28         r = terminal_urlify_man("systemd-detect-virt", "1", &link);
29         if (r < 0)
30                 return log_oom();
31 
32         printf("%s [OPTIONS...]\n\n"
33                "Detect execution in a virtualized environment.\n\n"
34                "  -h --help             Show this help\n"
35                "     --version          Show package version\n"
36                "  -c --container        Only detect whether we are run in a container\n"
37                "  -v --vm               Only detect whether we are run in a VM\n"
38                "  -r --chroot           Detect whether we are run in a chroot() environment\n"
39                "     --private-users    Only detect whether we are running in a user namespace\n"
40                "  -q --quiet            Don't output anything, just set return value\n"
41                "     --list             List all known and detectable types of virtualization\n"
42                "\nSee the %s for details.\n",
43                program_invocation_short_name,
44                link);
45 
46         return 0;
47 }
48 
parse_argv(int argc,char * argv[])49 static int parse_argv(int argc, char *argv[]) {
50 
51         enum {
52                 ARG_VERSION = 0x100,
53                 ARG_PRIVATE_USERS,
54                 ARG_LIST,
55         };
56 
57         static const struct option options[] = {
58                 { "help",          no_argument, NULL, 'h'               },
59                 { "version",       no_argument, NULL, ARG_VERSION       },
60                 { "container",     no_argument, NULL, 'c'               },
61                 { "vm",            no_argument, NULL, 'v'               },
62                 { "chroot",        no_argument, NULL, 'r'               },
63                 { "private-users", no_argument, NULL, ARG_PRIVATE_USERS },
64                 { "quiet",         no_argument, NULL, 'q'               },
65                 { "list",          no_argument, NULL, ARG_LIST          },
66                 {}
67         };
68 
69         int c;
70 
71         assert(argc >= 0);
72         assert(argv);
73 
74         while ((c = getopt_long(argc, argv, "hqcvr", options, NULL)) >= 0)
75 
76                 switch (c) {
77 
78                 case 'h':
79                         return help();
80 
81                 case ARG_VERSION:
82                         return version();
83 
84                 case 'q':
85                         arg_quiet = true;
86                         break;
87 
88                 case 'c':
89                         arg_mode = ONLY_CONTAINER;
90                         break;
91 
92                 case ARG_PRIVATE_USERS:
93                         arg_mode = ONLY_PRIVATE_USERS;
94                         break;
95 
96                 case 'v':
97                         arg_mode = ONLY_VM;
98                         break;
99 
100                 case 'r':
101                         arg_mode = ONLY_CHROOT;
102                         break;
103 
104                 case ARG_LIST:
105                         DUMP_STRING_TABLE(virtualization, Virtualization, _VIRTUALIZATION_MAX);
106                         return 0;
107 
108                 case '?':
109                         return -EINVAL;
110 
111                 default:
112                         assert_not_reached();
113                 }
114 
115         if (optind < argc)
116                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
117                                        "%s takes no arguments.",
118                                        program_invocation_short_name);
119 
120         return 1;
121 }
122 
run(int argc,char * argv[])123 static int run(int argc, char *argv[]) {
124         Virtualization v;
125         int r;
126 
127         /* This is mostly intended to be used for scripts which want
128          * to detect whether we are being run in a virtualized
129          * environment or not */
130 
131         log_setup();
132 
133         r = parse_argv(argc, argv);
134         if (r <= 0)
135                 return r;
136 
137         switch (arg_mode) {
138         case ONLY_VM:
139                 v = detect_vm();
140                 if (v < 0)
141                         return log_error_errno(v, "Failed to check for VM: %m");
142                 break;
143 
144         case ONLY_CONTAINER:
145                 v = detect_container();
146                 if (v < 0)
147                         return log_error_errno(v, "Failed to check for container: %m");
148                 break;
149 
150         case ONLY_CHROOT:
151                 r = running_in_chroot();
152                 if (r < 0)
153                         return log_error_errno(r, "Failed to check for chroot() environment: %m");
154                 return !r;
155 
156         case ONLY_PRIVATE_USERS:
157                 r = running_in_userns();
158                 if (r < 0)
159                         return log_error_errno(r, "Failed to check for user namespace: %m");
160                 return !r;
161 
162         case ANY_VIRTUALIZATION:
163         default:
164                 v = detect_virtualization();
165                 if (v < 0)
166                         return log_error_errno(v, "Failed to check for virtualization: %m");
167                 break;
168         }
169 
170         if (!arg_quiet)
171                 puts(virtualization_to_string(v));
172 
173         return v == VIRTUALIZATION_NONE;
174 }
175 
176 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
177