1 | #if defined(__linux__) |
---|---|
2 | |
3 | #include "hasLinuxCapability.h" |
4 | |
5 | #include <syscall.h> |
6 | #include <unistd.h> |
7 | #include <linux/capability.h> |
8 | #include <linux/netlink.h> |
9 | #include <Common/Exception.h> |
10 | |
11 | |
12 | namespace DB |
13 | { |
14 | |
15 | namespace ErrorCodes |
16 | { |
17 | extern const int NETLINK_ERROR; |
18 | } |
19 | |
20 | static __user_cap_data_struct getCapabilities() |
21 | { |
22 | /// See man getcap. |
23 | __user_cap_header_struct request{}; |
24 | request.version = _LINUX_CAPABILITY_VERSION_1; /// It's enough to check just single CAP_NET_ADMIN capability we are interested. |
25 | request.pid = getpid(); |
26 | |
27 | __user_cap_data_struct response{}; |
28 | |
29 | /// Avoid dependency on 'libcap'. |
30 | if (0 != syscall(SYS_capget, &request, &response)) |
31 | throwFromErrno("Cannot do 'capget' syscall", ErrorCodes::NETLINK_ERROR); |
32 | |
33 | return response; |
34 | } |
35 | |
36 | bool hasLinuxCapability(int cap) |
37 | { |
38 | static __user_cap_data_struct capabilities = getCapabilities(); |
39 | return (1 << cap) & capabilities.effective; |
40 | } |
41 | |
42 | } |
43 | |
44 | #endif |
45 |