forked from checkpoint-restore/criu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.h
294 lines (238 loc) · 7.76 KB
/
util.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#ifndef __CR_UTIL_H__
#define __CR_UTIL_H__
/*
* Some bits are stolen from perf and kvm tools
*/
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/statfs.h>
#include <sys/sysmacros.h>
#include <dirent.h>
#include <poll.h>
#include "int.h"
#include "common/compiler.h"
#include "xmalloc.h"
#include "common/bug.h"
#include "log.h"
#include "common/err.h"
#define PREF_SHIFT_OP(pref, op, size) ((size) op (pref ##BYTES_SHIFT))
#define KBYTES_SHIFT 10
#define MBYTES_SHIFT 20
#define GBYTES_SHIFT 30
#define KBYTES(size) PREF_SHIFT_OP(K, >>, size)
#define MBYTES(size) PREF_SHIFT_OP(M, >>, size)
#define GBYTES(size) PREF_SHIFT_OP(G, >>, size)
#define KILO(size) PREF_SHIFT_OP(K, <<, size)
#define MEGA(size) PREF_SHIFT_OP(M, <<, size)
#define GIGA(size) PREF_SHIFT_OP(G, <<, size)
struct vma_area;
struct list_head;
extern void pr_vma(unsigned int loglevel, const struct vma_area *vma_area);
#define pr_info_vma(vma_area) pr_vma(LOG_INFO, vma_area)
#define pr_msg_vma(vma_area) pr_vma(LOG_MSG, vma_area)
#define pr_vma_list(level, head) \
do { \
struct vma_area *vma; \
list_for_each_entry(vma, head, list) \
pr_vma(level, vma); \
} while (0)
#define pr_info_vma_list(head) pr_vma_list(LOG_INFO, head)
extern int move_fd_from(int *img_fd, int want_fd);
extern int close_safe(int *fd);
extern int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_reuse_fd);
#define reopen_fd_as(new_fd, old_fd) reopen_fd_as_safe(__FILE__, __LINE__, new_fd, old_fd, false)
#define reopen_fd_as_nocheck(new_fd, old_fd) reopen_fd_as_safe(__FILE__, __LINE__, new_fd, old_fd, true)
extern void close_proc(void);
extern int open_pid_proc(pid_t pid);
extern int close_pid_proc(void);
extern int set_proc_fd(int fd);
/*
* Values for pid argument of the proc opening routines below.
* SELF would open file under /proc/self
* GEN would open a file under /proc itself
* NONE is internal, don't use it ;)
*/
#define PROC_SELF 0
#define PROC_GEN -1
#define PROC_NONE -2
extern int do_open_proc(pid_t pid, int flags, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
#define __open_proc(pid, ier, flags, fmt, ...) \
({ \
int __fd = do_open_proc(pid, flags, \
fmt, ##__VA_ARGS__); \
if (__fd < 0 && (errno != (ier))) \
pr_perror("Can't open %d/" fmt " on procfs", \
pid, ##__VA_ARGS__); \
\
__fd; \
})
/* int open_proc(pid_t pid, const char *fmt, ...); */
#define open_proc(pid, fmt, ...) \
__open_proc(pid, 0, O_RDONLY, fmt, ##__VA_ARGS__)
/* int open_proc_rw(pid_t pid, const char *fmt, ...); */
#define open_proc_rw(pid, fmt, ...) \
__open_proc(pid, 0, O_RDWR, fmt, ##__VA_ARGS__)
#define open_proc_path(pid, fmt, ...) \
__open_proc(pid, 0, O_PATH, fmt, ##__VA_ARGS__)
/* DIR *opendir_proc(pid_t pid, const char *fmt, ...); */
#define opendir_proc(pid, fmt, ...) \
({ \
int __fd = open_proc(pid, fmt, ##__VA_ARGS__); \
DIR *__d = NULL; \
\
if (__fd >= 0) { \
__d = fdopendir(__fd); \
if (__d == NULL) \
pr_perror("Can't fdopendir %d " \
"(%d/" fmt " on procfs)", \
__fd, pid, ##__VA_ARGS__); \
} \
__d; \
})
/* FILE *fopen_proc(pid_t pid, const char *fmt, ...); */
#define fopen_proc(pid, fmt, ...) \
({ \
int __fd = open_proc(pid, fmt, ##__VA_ARGS__); \
FILE *__f = NULL; \
\
if (__fd >= 0) { \
__f = fdopen(__fd, "r"); \
if (__f == NULL) \
pr_perror("Can't fdopen %d " \
"(%d/" fmt " on procfs)", \
__fd, pid, ##__VA_ARGS__); \
} \
__f; \
})
#define DEVZERO (makedev(1, 5))
#define KDEV_MINORBITS 20
#define KDEV_MINORMASK ((1UL << KDEV_MINORBITS) - 1)
#define MKKDEV(ma, mi) (((ma) << KDEV_MINORBITS) | (mi))
static inline u32 kdev_major(u32 kdev)
{
return kdev >> KDEV_MINORBITS;
}
static inline u32 kdev_minor(u32 kdev)
{
return kdev & KDEV_MINORMASK;
}
static inline dev_t kdev_to_odev(u32 kdev)
{
/*
* New kernels encode devices in a new form.
* See kernel's fs/stat.c for details, there
* choose_32_64 helpers which are the key.
*/
unsigned major = kdev_major(kdev);
unsigned minor = kdev_minor(kdev);
return makedev(major, minor);
}
extern int copy_file(int fd_in, int fd_out, size_t bytes);
extern int is_anon_link_type(char *link, char *type);
#define is_hex_digit(c) \
(((c) >= '0' && (c) <= '9') || \
((c) >= 'a' && (c) <= 'f') || \
((c) >= 'A' && (c) <= 'F'))
#define CRS_CAN_FAIL 0x1 /* cmd can validly exit with non zero code */
extern int cr_system(int in, int out, int err, char *cmd, char *const argv[], unsigned flags);
extern int cr_system_userns(int in, int out, int err, char *cmd,
char *const argv[], unsigned flags, int userns_pid);
extern int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd);
extern int close_status_fd(void);
extern int is_root_user(void);
static inline bool dir_dots(const struct dirent *de)
{
return !strcmp(de->d_name, ".") || !strcmp(de->d_name, "..");
}
extern int is_empty_dir(int dirfd);
/*
* Size of buffer to carry the worst case or /proc/self/fd/N
* path. Since fd is an integer, we can easily estimate one :)
*/
#define PSFDS (sizeof("/proc/self/fd/2147483647"))
extern int read_fd_link(int lfd, char *buf, size_t size);
#define USEC_PER_SEC 1000000L
#define NSEC_PER_SEC 1000000000L
int vaddr_to_pfn(unsigned long vaddr, u64 *pfn);
/*
* Check whether @str starts with @sub and report the
* next character of @str in @end
*/
static inline bool strstartswith2(const char *str, const char *sub, char *end)
{
const char *osub = sub;
while (1) {
if (*sub == '\0') /* end of sub -- match */ {
if (end) {
if (sub == osub + 1) /* pure root */
*end = '/';
else
*end = *str;
}
return true;
}
if (*str == '\0') /* end of str, sub is NOT ended -- miss */
return false;
if (*str != *sub)
return false;
str++;
sub++;
}
}
static inline bool strstartswith(const char *str, const char *sub)
{
return strstartswith2(str, sub, NULL);
}
/*
* Checks whether the @path has @sub_path as a sub path, i.e.
* sub_path is the beginning of path and the last component
* match is full (next character terminates path component).
*
* Paths shouldn't contain excessive /-s, i.e. only one slash
* between path components and no slash at the end (except for
* the "/" path. This is pretty good assumption to what paths
* are used by criu.
*/
static inline bool issubpath(const char *path, const char *sub_path)
{
char end;
return strstartswith2(path, sub_path, &end) &&
(end == '/' || end == '\0');
}
/*
* mkdir -p
*/
int mkdirpat(int fd, const char *path, int mode);
/*
* Tests whether a path is a prefix of another path. This is different than
* strstartswith because "/foo" is _not_ a path prefix of "/foobar", since they
* refer to different directories.
*/
bool is_path_prefix(const char *path, const char *prefix);
FILE *fopenat(int dirfd, char *path, char *cflags);
void split(char *str, char token, char ***out, int *n);
int fd_has_data(int lfd);
int make_yard(char *path);
static inline int sk_wait_data(int sk)
{
struct pollfd pfd = {sk, POLLIN, 0};
return poll(&pfd, 1, -1);
}
void tcp_nodelay(int sk, bool on);
void tcp_cork(int sk, bool on);
const char *ns_to_string(unsigned int ns);
char *xstrcat(char *str, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
char *xsprintf(const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
void print_data(unsigned long addr, unsigned char *data, size_t size);
int setup_tcp_server(char *type);
int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk);
int setup_tcp_client(char *addr);
#define LAST_PID_PATH "sys/kernel/ns_last_pid"
#define PID_MAX_PATH "sys/kernel/pid_max"
#endif /* __CR_UTIL_H__ */