File _service:tar_scm:0004-iSulad-adapt-confile-lxccontainer-and-start.patch of Package lxc

3311
 
1
From 3e7fb35a35cff34be2bb7ace0b239d540fe0657f Mon Sep 17 00:00:00 2001
2
From: zhangxiaoyu <zhangxiaoyu58@huawei.com>
3
Date: Wed, 26 Jul 2023 14:57:33 +0800
4
Subject: [PATCH] [iSulad] adapt confile lxccontainer and start
5
6
Signed-off-by: zhangxiaoyu <zhangxiaoyu58@huawei.com>
7
---
8
 src/lxc/conf.c         |  11 -
9
 src/lxc/conf.h         |   4 -
10
 src/lxc/confile.c      | 558 +++++++++++++++++++++++++
11
 src/lxc/lxccontainer.c | 899 +++++++++++++++++++++++++++++++++++++++-
12
 src/lxc/lxccontainer.h | 197 +++++++++
13
 src/lxc/start.c        | 902 +++++++++++++++++++++++++++++++++++++++++
14
 src/lxc/start.h        |  18 +
15
 7 files changed, 2573 insertions(+), 16 deletions(-)
16
17
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
18
index a0e0375..187e60e 100644
19
--- a/src/lxc/conf.c
20
+++ b/src/lxc/conf.c
21
@@ -5242,7 +5242,6 @@ void lxc_conf_free(struct lxc_conf *conf)
22
    }
23
    free(conf->systemd);
24
    lxc_clear_init_args(conf);
25
-   lxc_clear_init_groups(conf);
26
    lxc_clear_populate_devices(conf);
27
    lxc_clear_rootfs_masked_paths(conf);
28
    lxc_clear_rootfs_ro_paths(conf);
29
@@ -7427,16 +7426,6 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf)
30
    return 0;
31
 }
32
 
33
-/*isulad clear init groups*/
34
-int lxc_clear_init_groups(struct lxc_conf *lxc_conf)
35
-{
36
-   free(lxc_conf->init_groups);
37
-   lxc_conf->init_groups = NULL;
38
-   lxc_conf->init_groups_len = 0;
39
-
40
-   return 0;
41
-}
42
-
43
 /*isulad: clear populate devices*/
44
 int lxc_clear_populate_devices(struct lxc_conf *c)
45
 {
46
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
47
index 683b8ba..108e05b 100644
48
--- a/src/lxc/conf.h
49
+++ b/src/lxc/conf.h
50
@@ -622,9 +622,6 @@ struct lxc_conf {
51
    char **init_argv;
52
    size_t init_argc;
53
 
54
-   gid_t *init_groups;
55
-   size_t init_groups_len;
56
-
57
    /* populate devices */
58
    struct lxc_list populate_devs;
59
    mode_t umask;  // umask value
60
@@ -794,7 +791,6 @@ __hidden extern int parse_cap(const char *cap_name, __u32 *cap);
61
 #ifdef HAVE_ISULAD
62
 // isulad add
63
 __hidden int lxc_clear_init_args(struct lxc_conf *lxc_conf);
64
-__hidden int lxc_clear_init_groups(struct lxc_conf *lxc_conf);
65
 __hidden int lxc_clear_populate_devices(struct lxc_conf *c);
66
 __hidden int lxc_clear_rootfs_masked_paths(struct lxc_conf *c);
67
 __hidden int lxc_clear_rootfs_ro_paths(struct lxc_conf *c);
68
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
69
index 7966d32..1492776 100644
70
--- a/src/lxc/confile.c
71
+++ b/src/lxc/confile.c
72
@@ -157,6 +157,18 @@ lxc_config_define(uts_name);
73
 lxc_config_define(sysctl);
74
 lxc_config_define(proc);
75
 lxc_config_define(sched_core);
76
+#ifdef HAVE_ISULAD
77
+lxc_config_define(init_args);
78
+lxc_config_define(populate_device);
79
+lxc_config_define(umask);
80
+lxc_config_define(rootfs_masked_paths);
81
+lxc_config_define(rootfs_ro_paths);
82
+lxc_config_define(systemd);
83
+lxc_config_define(console_log_driver);
84
+lxc_config_define(console_syslog_tag);
85
+lxc_config_define(console_syslog_facility);
86
+lxc_config_define(selinux_mount_context);
87
+#endif
88
 
89
 static int set_config_unsupported_key(const char *key, const char *value,
90
                      struct lxc_conf *lxc_conf, void *data)
91
@@ -274,6 +286,18 @@ static struct lxc_config_t config_jump_table[] = {
92
    { "lxc.uts.name",                   true,  set_config_uts_name,                   get_config_uts_name,                   clr_config_uts_name,                   },
93
    { "lxc.sysctl",                     false, set_config_sysctl,                     get_config_sysctl,                     clr_config_sysctl,                     },
94
    { "lxc.proc",                       false, set_config_proc,                       get_config_proc,                       clr_config_proc,                       },
95
+#ifdef HAVE_ISULAD
96
+   { "lxc.isulad.init.args",          set_config_init_args,                   get_config_init_args,                   clr_config_init_args,                 },
97
+   { "lxc.isulad.populate.device",    set_config_populate_device,             get_config_populate_device,             clr_config_populate_device,           },
98
+   { "lxc.isulad.umask",              set_config_umask,                       get_config_umask,                       clr_config_umask,                     },
99
+   { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths,         get_config_rootfs_masked_paths,         clr_config_rootfs_masked_paths,       },
100
+   { "lxc.isulad.rootfs.ropaths",     set_config_rootfs_ro_paths,             get_config_rootfs_ro_paths,             clr_config_rootfs_ro_paths,           },
101
+   { "lxc.isulad.systemd",            set_config_systemd,                     get_config_systemd,                     clr_config_systemd,                   },
102
+   { "lxc.console.logdriver",         set_config_console_log_driver,          get_config_console_log_driver,          clr_config_console_log_driver,        },
103
+   { "lxc.console.syslog_tag",        set_config_console_syslog_tag,          get_config_console_syslog_tag,          clr_config_console_syslog_tag,        },
104
+   { "lxc.console.syslog_facility",   set_config_console_syslog_facility,     get_config_console_syslog_facility,     clr_config_console_syslog_facility,   },
105
+   { "lxc.selinux.mount_context",     set_config_selinux_mount_context,       get_config_selinux_mount_context,       clr_config_selinux_mount_context,     },
106
+#endif
107
 };
108
 
109
 static struct lxc_config_t unsupported_config_key = {
110
@@ -1588,7 +1612,12 @@ static int set_config_environment(const char *key, const char *value,
111
    if (!new_env)
112
        return ret_errno(ENOMEM);
113
 
114
+#ifdef HAVE_ISULAD
115
+   /* isulad: recover space replaced by SPACE_MAGIC_STR */
116
+   dup = lxc_string_replace(SPACE_MAGIC_STR, " ", value);
117
+#else
118
    dup = strdup(value);
119
+#endif
120
    if (!dup)
121
        return ret_errno(ENOMEM);
122
 
123
@@ -2558,8 +2587,11 @@ static int set_config_console_rotate(const char *key, const char *value,
124
    if (ret)
125
        return ret_errno(EINVAL);
126
 
127
+#ifndef HAVE_ISULAD
128
+   /* isulad: support rotate muti-files */
129
    if (lxc_conf->console.log_rotate > 1)
130
        return log_error_errno(-EINVAL, EINVAL, "The \"lxc.console.rotate\" config key can only be set to 0 or 1");
131
+#endif
132
 
133
    return 0;
134
 }
135
@@ -3049,6 +3081,54 @@ struct parse_line_conf {
136
    bool from_include;
137
 };
138
 
139
+#ifdef HAVE_ISULAD
140
+// escape_string_decode compress some escape characters
141
+static char *escape_string_decode(const char *src)
142
+{
143
+   size_t src_end = 0;
144
+   size_t dst_end = 0;
145
+   size_t len = 0;
146
+   char *dst = NULL;
147
+
148
+   if (src == NULL) {
149
+       return NULL;
150
+   }
151
+
152
+   len = strlen(src);
153
+   if (len == 0) {
154
+       return NULL;
155
+   }
156
+
157
+   dst = calloc(1, len + 1);
158
+   if (dst == NULL) {
159
+       ERROR("Out of memory");
160
+       return NULL;
161
+   }
162
+
163
+   while(src_end < len) {
164
+       if (src[src_end] == '\\') {
165
+           switch (src[++src_end])
166
+           {
167
+               case 'r': dst[dst_end] = '\r'; break;
168
+               case 'n': dst[dst_end] = '\n'; break;
169
+               case 'f': dst[dst_end] = '\f'; break;
170
+               case 'b': dst[dst_end] = '\b'; break;
171
+               case 't': dst[dst_end] = '\t'; break;
172
+               case '\\': dst[dst_end] = '\\'; break;
173
+               // default do not decode
174
+               default: dst[dst_end++] = '\\'; dst[dst_end] = src[src_end]; break;
175
+           }
176
+       } else {
177
+           dst[dst_end] = src[src_end];
178
+       }
179
+       dst_end++;
180
+       src_end++;
181
+   }
182
+
183
+   return dst;
184
+}
185
+#endif
186
+
187
 static int parse_line(char *buffer, void *data)
188
 {
189
    __do_free char *linep = NULL;
190
@@ -3058,6 +3138,9 @@ static int parse_line(char *buffer, void *data)
191
    int ret;
192
    char *dup = buffer;
193
    struct parse_line_conf *plc = data;
194
+#ifdef HAVE_ISULAD
195
+   __do_free char *value_decode = NULL;
196
+#endif
197
 
198
    if (!plc->conf)
199
        return syserror_set(-EINVAL, "Missing config");
200
@@ -3118,7 +3201,15 @@ static int parse_line(char *buffer, void *data)
201
    }
202
 
203
    config = lxc_get_config(key);
204
+#ifdef HAVE_ISULAD
205
+   value_decode = escape_string_decode(value);
206
+   if (value_decode == NULL) {
207
+       ERROR("Value %s decode failed", value);
208
+   }
209
+   ret = config->set(key, value_decode ? value_decode: value, plc->conf, NULL);
210
+#else
211
    return config->set(key, value, plc->conf, NULL);
212
+#endif
213
 }
214
 
215
 static struct new_config_item *parse_new_conf_line(char *buffer)
216
@@ -3222,6 +3313,12 @@ bool lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c)
217
 
218
    lxc_list_for_each(it, defines) {
219
        struct new_config_item *new_item = it->elem;
220
+#ifdef HAVE_ISULAD
221
+       if (strcmp(new_item->key, LXC_IMAGE_OCI_KEY) == 0) {
222
+           c->set_oci_type(c, true);
223
+           continue;
224
+       }
225
+#endif
226
        bret = c->set_config_item(c, new_item->key, new_item->val);
227
        if (!bret)
228
            break;
229
@@ -6764,3 +6861,464 @@ static int clr_config_sched_core(const char *key, struct lxc_conf *c, void *data
230
    c->sched_core = false;
231
    return 0;
232
 }
233
+
234
+
235
+#ifdef HAVE_ISULAD
236
+/* isulad: set config for init args */
237
+static int set_config_init_args(const char *key, const char *value,
238
+                struct lxc_conf *lxc_conf, void *data)
239
+{
240
+   int ret = 0;
241
+   char **tmp = NULL;
242
+   char *new_value = NULL;
243
+
244
+   ret = set_config_string_item(&new_value, value);
245
+   if (ret || !new_value)
246
+       return ret;
247
+
248
+   tmp = (char **)realloc(lxc_conf->init_argv, (lxc_conf->init_argc + 1) * sizeof(char *));
249
+   if (!tmp) {
250
+       ERROR("Out of memory");
251
+       free(new_value);
252
+       return -1;
253
+   }
254
+
255
+   lxc_conf->init_argv = tmp;
256
+
257
+   lxc_conf->init_argv[lxc_conf->init_argc] = new_value;
258
+   lxc_conf->init_argc++;
259
+
260
+   return 0;
261
+}
262
+
263
+/* isulad: get config init args */
264
+static int get_config_init_args(const char *key, char *retv, int inlen,
265
+                 struct lxc_conf *c, void *data)
266
+{
267
+   int i, len, fulllen = 0;
268
+
269
+   if (!retv)
270
+       inlen = 0;
271
+   else
272
+       memset(retv, 0, inlen);
273
+
274
+   for (i = 0; i < c->init_argc; i++) {
275
+           strprint(retv, inlen, "%s", c->init_argv[i]);
276
+    }
277
+
278
+   return fulllen;
279
+}
280
+
281
+/* isulad: clr config init args*/
282
+static inline int clr_config_init_args(const char *key, struct lxc_conf *c,
283
+                  void *data)
284
+{
285
+   return lxc_clear_init_args(c);
286
+}
287
+
288
+/* isulad: set config for populate device */
289
+static int set_config_populate_device(const char *key, const char *value,
290
+                                      struct lxc_conf *lxc_conf, void *data)
291
+{
292
+   int ret = 0, major = 0, minor = 0;
293
+   uid_t uid = (uid_t)-1;
294
+   gid_t gid = (gid_t)-1;
295
+   char name[4096] = {0}; /* MAX dev path name */
296
+   char type[3] = {0};
297
+   char *replace_value = NULL;
298
+   mode_t filemode = 0;
299
+   struct lxc_list *iter = NULL;
300
+   struct lxc_list *dev_list = NULL;
301
+   struct lxc_populate_devs *dev_elem = NULL;
302
+
303
+   if (lxc_config_value_empty(value))
304
+       return lxc_clear_populate_devices(lxc_conf);
305
+
306
+   /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID
307
+    * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0
308
+    */
309
+   ret = sscanf(value, "%4095[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid);
310
+   if (ret != 7)
311
+       return -1;
312
+
313
+   /* find existing list element */
314
+   lxc_list_for_each(iter, &lxc_conf->populate_devs) {
315
+       dev_elem = iter->elem;
316
+
317
+       if (strcmp(name, dev_elem->name) != 0)
318
+           continue;
319
+
320
+       replace_value = safe_strdup(type);
321
+
322
+       free(dev_elem->type);
323
+       dev_elem->type = replace_value;
324
+       dev_elem->file_mode = filemode;
325
+       dev_elem->maj = major;
326
+       dev_elem->min = minor;
327
+       dev_elem->uid = (uid_t)uid;
328
+       dev_elem->gid = (gid_t)gid;
329
+       return 0;
330
+   }
331
+
332
+   /* allocate list element */
333
+   dev_list = malloc(sizeof(*dev_list));
334
+   if (dev_list == NULL)
335
+       goto on_error;
336
+
337
+   lxc_list_init(dev_list);
338
+
339
+   dev_elem = malloc(sizeof(*dev_elem));
340
+   if (dev_elem == NULL)
341
+       goto on_error;
342
+   memset(dev_elem, 0, sizeof(*dev_elem));
343
+
344
+   dev_elem->name = safe_strdup(name);
345
+
346
+   dev_elem->type = safe_strdup(type);
347
+
348
+   dev_elem->file_mode = filemode;
349
+   dev_elem->maj = major;
350
+   dev_elem->min = minor;
351
+   dev_elem->uid = (uid_t)uid;
352
+   dev_elem->gid = (gid_t)gid;
353
+
354
+   lxc_list_add_elem(dev_list, dev_elem);
355
+
356
+   lxc_list_add_tail(&lxc_conf->populate_devs, dev_list);
357
+
358
+   return 0;
359
+
360
+on_error:
361
+   free(dev_list);
362
+   if (dev_elem) {
363
+       free(dev_elem->name);
364
+       free(dev_elem->type);
365
+       free(dev_elem);
366
+   }
367
+   return -1;
368
+}
369
+
370
+/* isulad: get config populate device
371
+ * If you ask for 'lxc.populate.device', then all populate device
372
+ * entries will be printed, in 'lxc.populate.device = path_in_container:type:major:minor:mode:uid:gid' format.
373
+ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0
374
+ */
375
+static int get_config_populate_device(const char *key, char *retv, int inlen,
376
+                                      struct lxc_conf *c, void *data)
377
+{
378
+   int len;
379
+   struct lxc_list *it = NULL;
380
+   int fulllen = 0;
381
+
382
+   if (!retv)
383
+       inlen = 0;
384
+   else
385
+       memset(retv, 0, inlen);
386
+
387
+   lxc_list_for_each(it, &c->populate_devs) {
388
+       struct lxc_populate_devs *elem = it->elem;
389
+       strprint(retv, inlen, "lxc.populate.device = %s:%s:%d:%d:%o:%u:%u\n",
390
+                elem->name, elem->type, elem->maj,
391
+                elem->min, elem->file_mode, elem->uid, elem->gid);
392
+   }
393
+
394
+   return fulllen;
395
+}
396
+
397
+/* isulad: clr config populate devices*/
398
+static inline int clr_config_populate_device(const char *key, struct lxc_conf *c,
399
+                void *data)
400
+{
401
+   return lxc_clear_populate_devices(c);
402
+}
403
+
404
+/* isulad: set config for umask */
405
+static int set_config_umask(const char *key, const char *value,
406
+                 struct lxc_conf *lxc_conf, void *data)
407
+{
408
+   if (lxc_config_value_empty(value)) {
409
+       ERROR("Empty umask");
410
+       return -1;
411
+   }
412
+
413
+   if (strcmp(value, "normal") == 0) {
414
+       lxc_conf->umask = 0022;
415
+       return 0;
416
+   } else if (strcmp(value, "secure") == 0) {
417
+       lxc_conf->umask = 0027;
418
+       return 0;
419
+   } else {
420
+       ERROR("Invalid native umask: %s", value);
421
+       return -1;
422
+   }
423
+}
424
+
425
+/* isulad add: get umask value*/
426
+static int get_config_umask(const char *key, char *retv, int inlen,
427
+                 struct lxc_conf *c, void *data)
428
+{
429
+   return lxc_get_conf_size_t(c, retv, inlen, c->umask);
430
+}
431
+
432
+/* isulad add: clear umask value */
433
+static inline int clr_config_umask(const char *key, struct lxc_conf *c,
434
+                    void *data)
435
+{
436
+   c->umask = 0027;
437
+   return 0;
438
+}
439
+
440
+/* isulad: set config for rootfs masked paths */
441
+static int set_config_rootfs_masked_paths(const char *key, const char *value,
442
+                struct lxc_conf *lxc_conf, void *data)
443
+{
444
+   struct lxc_list *list_item = NULL;
445
+
446
+   if (lxc_config_value_empty(value))
447
+       return lxc_clear_rootfs_masked_paths(lxc_conf);
448
+
449
+   list_item = malloc(sizeof(*list_item));
450
+   if (list_item == NULL)
451
+       goto on_error;
452
+
453
+   list_item->elem = safe_strdup(value);
454
+
455
+   lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item);
456
+
457
+   return 0;
458
+
459
+on_error:
460
+   free(list_item);
461
+
462
+   return -1;
463
+}
464
+
465
+// isulad: get config rootfs masked paths
466
+static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen,
467
+                struct lxc_conf *c, void *data)
468
+{
469
+   int len, fulllen = 0;
470
+   struct lxc_list *it = NULL;
471
+
472
+   if (!retv)
473
+       inlen = 0;
474
+   else
475
+       memset(retv, 0, inlen);
476
+
477
+   lxc_list_for_each(it, &c->rootfs.maskedpaths) {
478
+       strprint(retv, inlen, "%s\n", (char *)it->elem);
479
+   }
480
+
481
+   return fulllen;
482
+}
483
+
484
+/* isulad: set config for rootfs ro paths */
485
+static int set_config_rootfs_ro_paths(const char *key, const char *value,
486
+                                      struct lxc_conf *lxc_conf, void *data)
487
+{
488
+   struct lxc_list *list_item = NULL;
489
+
490
+   if (lxc_config_value_empty(value))
491
+       return lxc_clear_rootfs_ro_paths(lxc_conf);
492
+
493
+   list_item = malloc(sizeof(*list_item));
494
+   if (list_item == NULL)
495
+       goto on_error;
496
+
497
+   list_item->elem = safe_strdup(value);
498
+
499
+   lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item);
500
+
501
+   return 0;
502
+
503
+on_error:
504
+   free(list_item);
505
+
506
+   return -1;
507
+}
508
+
509
+// isulad: get config rootfs ro paths
510
+static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen,
511
+                                      struct lxc_conf *c, void *data)
512
+{
513
+   int len, fulllen = 0;
514
+   struct lxc_list *it = NULL;
515
+
516
+   if (!retv)
517
+       inlen = 0;
518
+   else
519
+       memset(retv, 0, inlen);
520
+
521
+   lxc_list_for_each(it, &c->rootfs.ropaths) {
522
+       strprint(retv, inlen, "%s\n", (char *)it->elem);
523
+   }
524
+
525
+   return fulllen;
526
+}
527
+
528
+/* isulad: clr config rootfs masked paths */
529
+static inline int clr_config_rootfs_masked_paths(const char *key, struct lxc_conf *c,
530
+                void *data)
531
+{
532
+   return lxc_clear_rootfs_masked_paths(c);
533
+}
534
+
535
+/* isulad: clr config rootfs ro paths */
536
+static inline int clr_config_rootfs_ro_paths(const char *key, struct lxc_conf *c,
537
+                void *data)
538
+{
539
+   return lxc_clear_rootfs_ro_paths(c);
540
+}
541
+
542
+/* isulad: set config for systemd */
543
+static int set_config_systemd(const char *key, const char *value,
544
+                 struct lxc_conf *lxc_conf, void *data)
545
+{
546
+   if (lxc_config_value_empty(value)) {
547
+       ERROR("Empty umask");
548
+       return -1;
549
+   }
550
+   lxc_conf->systemd = strdup(value);
551
+   return 0;
552
+}
553
+
554
+/* isulad add: get systemd value*/
555
+static int get_config_systemd(const char *key, char *retv, int inlen,
556
+                 struct lxc_conf *c, void *data)
557
+{
558
+   return lxc_get_conf_str(retv, inlen, c->systemd);
559
+}
560
+
561
+/* isulad add: clear systemd value */
562
+static inline int clr_config_systemd(const char *key, struct lxc_conf *c,
563
+                    void *data)
564
+{
565
+   free(c->systemd);
566
+   c->systemd = NULL;
567
+   return 0;
568
+}
569
+
570
+static int set_config_console_log_driver(const char *key, const char *value,
571
+        struct lxc_conf *lxc_conf, void *data)
572
+{
573
+   return set_config_string_item(&lxc_conf->console.log_driver, value);
574
+}
575
+
576
+static int set_config_console_syslog_tag(const char *key, const char *value,
577
+        struct lxc_conf *lxc_conf, void *data)
578
+{
579
+   if (value == NULL) {
580
+       return -1;
581
+   }
582
+   return set_config_string_item(&lxc_conf->console.log_syslog_tag, value);
583
+}
584
+
585
+static int parse_facility(const char *facility)
586
+{
587
+#define FACILITIES_LEN 20
588
+   const char *facility_keys[FACILITIES_LEN] = {
589
+       "kern", "user", "mail", "daemon", "auth",
590
+       "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp",
591
+       "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"
592
+   };
593
+   const int facilities[FACILITIES_LEN] = {
594
+       LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH, LOG_SYSLOG,
595
+       LOG_LPR, LOG_NEWS, LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_FTP,
596
+       LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4,
597
+       LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7
598
+   };
599
+   int i = 0;
600
+
601
+   if (facility == NULL) {
602
+       return -1;
603
+   }
604
+
605
+   for (; i < FACILITIES_LEN; i++) {
606
+       if (strcmp(facility, facility_keys[i]) == 0) {
607
+           return facilities[i];
608
+       }
609
+   }
610
+
611
+   return -1;
612
+}
613
+
614
+static int set_config_console_syslog_facility(const char *key, const char *value,
615
+        struct lxc_conf *lxc_conf, void *data)
616
+{
617
+   int facility;
618
+
619
+   facility = parse_facility(value);
620
+   if (facility < 0) {
621
+       NOTICE("Invalid facility: %s", value);
622
+       facility = LOG_DAEMON;
623
+   }
624
+
625
+   lxc_conf->console.log_syslog_facility = facility;
626
+   return 0;
627
+}
628
+
629
+static int set_config_selinux_mount_context(const char *key, const char *value,
630
+    struct lxc_conf *lxc_conf, void *data)
631
+{
632
+   if (value != NULL && strcmp(value, "unconfined_t") == 0) {
633
+       return set_config_string_item(&lxc_conf->lsm_se_mount_context, NULL);
634
+   }
635
+
636
+   return set_config_string_item(&lxc_conf->lsm_se_mount_context, value);
637
+}
638
+
639
+static int get_config_console_log_driver(const char *key, char *retv, int inlen,
640
+        struct lxc_conf *c, void *data)
641
+{
642
+   return lxc_get_conf_str(retv, inlen, c->console.log_driver);
643
+}
644
+
645
+static int get_config_console_syslog_tag(const char *key, char *retv, int inlen,
646
+        struct lxc_conf *c, void *data)
647
+{
648
+   return lxc_get_conf_str(retv, inlen, c->console.log_syslog_tag);
649
+}
650
+
651
+static int get_config_console_syslog_facility(const char *key, char *retv, int inlen,
652
+        struct lxc_conf *c, void *data)
653
+{
654
+   return lxc_get_conf_int(c, retv, inlen, c->console.log_syslog_facility);
655
+}
656
+
657
+static int get_config_selinux_mount_context(const char *key, char *retv, int inlen,
658
+    struct lxc_conf *c, void *data)
659
+{
660
+   return lxc_get_conf_str(retv, inlen, c->lsm_se_mount_context);
661
+}
662
+
663
+static inline int clr_config_console_log_driver(const char *key,
664
+                struct lxc_conf *c, void *data)
665
+{
666
+   free(c->console.log_driver);
667
+   c->console.log_driver = NULL;
668
+   return 0;
669
+}
670
+
671
+static inline int clr_config_console_syslog_tag(const char *key,
672
+                struct lxc_conf *c, void *data)
673
+{
674
+   free(c->console.log_syslog_tag);
675
+   c->console.log_syslog_tag= NULL;
676
+   return 0;
677
+}
678
+
679
+static inline int clr_config_console_syslog_facility(const char *key,
680
+                struct lxc_conf *c, void *data)
681
+{
682
+   c->console.log_syslog_facility = LOG_DAEMON;
683
+   return 0;
684
+}
685
+
686
+static inline int clr_config_selinux_mount_context(const char *key,
687
+    struct lxc_conf *c, void *data)
688
+{
689
+   free(c->lsm_se_mount_context);
690
+   c->lsm_se_mount_context = NULL;
691
+   return 0;
692
+}
693
+#endif
694
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
695
index 8df6059..d4495f7 100644
696
--- a/src/lxc/lxccontainer.c
697
+++ b/src/lxc/lxccontainer.c
698
@@ -62,6 +62,10 @@
699
 #include "utils.h"
700
 #include "version.h"
701
 
702
+#ifdef HAVE_ISULAD
703
+#include "exec_commands.h"
704
+#endif
705
+
706
 #if HAVE_OPENSSL
707
 #include <openssl/evp.h>
708
 #endif
709
@@ -83,6 +87,11 @@
710
 
711
 lxc_log_define(lxccontainer, lxc);
712
 
713
+#ifdef HAVE_ISULAD
714
+typedef bool (*func_is_io_stat_read)(const char *value);
715
+typedef bool (*func_is_io_stat_write)(const char *value);
716
+#endif
717
+
718
 static bool do_lxcapi_destroy(struct lxc_container *c);
719
 static const char *lxcapi_get_config_path(struct lxc_container *c);
720
 #define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c)
721
@@ -272,6 +281,13 @@ static void lxc_container_free(struct lxc_container *c)
722
    free(c->config_path);
723
    c->config_path = NULL;
724
 
725
+#ifdef HAVE_ISULAD
726
+   free(c->exit_fifo);
727
+   c->exit_fifo = NULL;
728
+   free(c->ocihookfile);
729
+   c->ocihookfile = NULL;
730
+#endif
731
+
732
    free(c);
733
 }
734
 
735
@@ -652,6 +668,66 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
736
    return true;
737
 }
738
 
739
+#ifdef HAVE_ISULAD
740
+static bool load_ocihooks_locked(struct lxc_container *c)
741
+{
742
+   parser_error err = NULL;
743
+   oci_runtime_spec_hooks *hooks = NULL;
744
+
745
+   if (!c->lxc_conf)
746
+       c->lxc_conf = lxc_conf_init();
747
+
748
+   if (!c->lxc_conf)
749
+       return false;
750
+
751
+   hooks = oci_runtime_spec_hooks_parse_file(c->ocihookfile, NULL, &err);
752
+   if (!hooks) {
753
+       fprintf(stderr, "parse oci hooks config failed: %s\n", err);
754
+       free(err);
755
+       return true;
756
+   }
757
+   c->lxc_conf->ocihooks = hooks;
758
+
759
+   if (err)
760
+       free(err);
761
+   return true;
762
+}
763
+
764
+/*
765
+ * isulad: set oci hook file path
766
+ * */
767
+static bool set_oci_hook_config_filename(struct lxc_container *c)
768
+{
769
+#define OCI_HOOK_JSON_FILE_NAME "ocihooks.json"
770
+   char *newpath = NULL;
771
+   int len, ret;
772
+
773
+   if (!c->config_path)
774
+       return false;
775
+
776
+   /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */
777
+   if (strlen(c->config_path) + strlen(c->name) > SIZE_MAX - strlen(OCI_HOOK_JSON_FILE_NAME) - 3)
778
+       return false;
779
+   len = strlen(c->config_path) + strlen(c->name) + strlen(OCI_HOOK_JSON_FILE_NAME) + 3;
780
+
781
+   newpath = malloc(len);
782
+   if (newpath == NULL)
783
+       return false;
784
+
785
+   ret = snprintf(newpath, len, "%s/%s/%s", c->config_path, c->name, OCI_HOOK_JSON_FILE_NAME);
786
+   if (ret < 0 || ret >= len) {
787
+       fprintf(stderr, "Error printing out config file name\n");
788
+       free(newpath);
789
+       return false;
790
+   }
791
+
792
+   free(c->ocihookfile);
793
+   c->ocihookfile = newpath;
794
+
795
+   return true;
796
+}
797
+#endif
798
+
799
 static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
800
 {
801
    int lret;
802
@@ -685,6 +761,11 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
803
 
804
    ret = load_config_locked(c, fname);
805
 
806
+#ifdef HAVE_ISULAD
807
+   if (ret && file_exists(c->ocihookfile))
808
+       ret = load_ocihooks_locked(c);
809
+#endif
810
+
811
    if (need_disklock)
812
        container_disk_unlock(c);
813
    else
814
@@ -884,6 +965,33 @@ static bool wait_on_daemonized_start(struct lxc_handler *handler, int pid)
815
    return true;
816
 }
817
 
818
+#ifdef HAVE_ISULAD
819
+/* isulad: use init argv as init cmd */
820
+static char **use_init_args(char **init_argv, size_t init_args)
821
+{
822
+   size_t i;
823
+   int nargs = 0;
824
+   char **argv;
825
+
826
+   if (!init_argv)
827
+       return NULL;
828
+
829
+   do {
830
+       argv = malloc(sizeof(char *));
831
+   } while (!argv);
832
+
833
+   argv[0] = NULL;
834
+   for (i = 0; i < init_args; i++)
835
+       push_arg(&argv, init_argv[i], &nargs);
836
+
837
+   if (nargs == 0) {
838
+       free(argv);
839
+       return NULL;
840
+   }
841
+   return argv;
842
+}
843
+#endif
844
+
845
 static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
846
 {
847
    int ret;
848
@@ -894,6 +1002,11 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
849
        NULL,
850
    };
851
    char **init_cmd = NULL;
852
+#ifdef HAVE_ISULAD
853
+   int keepfds[] = {-1, -1, -1, -1, -1};
854
+   ssize_t size_read;
855
+   char errbuf[BUFSIZ + 1] = {0};
856
+#endif
857
 
858
    /* container does exist */
859
    if (!c)
860
@@ -940,6 +1053,30 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
861
            argv = init_cmd = split_init_cmd(conf->init_cmd);
862
    }
863
 
864
+#ifdef HAVE_ISULAD
865
+   if (!argv) {
866
+       argv = init_cmd = use_init_args(conf->init_argv, conf->init_argc);
867
+   }
868
+
869
+   // do not allow using default rootfs path when isulad
870
+   if (conf->rootfs.mount == NULL) {
871
+       ERROR("Empty rootfs path detected");
872
+       lxc_put_handler(handler);
873
+       return false;
874
+   }
875
+
876
+   // do not allow using default args when isulad
877
+   if (!argv) {
878
+       ERROR("Empty args detected");
879
+       lxc_put_handler(handler);
880
+       return false;
881
+   }
882
+
883
+   if (c->image_type_oci) {
884
+       handler->image_type_oci = true;
885
+   }
886
+#endif
887
+
888
    /* ... otherwise use default_args. */
889
    if (!argv) {
890
        if (useinit) {
891
@@ -959,10 +1096,23 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
892
        char title[2048];
893
        pid_t pid_first, pid_second;
894
 
895
+#ifdef HAVE_ISULAD
896
+       //isulad: pipdfd for get error message of child or grandchild process.
897
+       if (pipe2(conf->errpipe, O_CLOEXEC) != 0) {
898
+           SYSERROR("Failed to init errpipe");
899
+           free_init_cmd(init_cmd);
900
+           lxc_put_handler(handler);
901
+           return false;
902
+       }
903
+#endif
904
+
905
        pid_first = fork();
906
        if (pid_first < 0) {
907
            free_init_cmd(init_cmd);
908
            lxc_put_handler(handler);
909
+#ifdef HAVE_ISULAD
910
+           lxc_close_error_pipe(conf->errpipe);
911
+#endif
912
            return false;
913
        }
914
 
915
@@ -972,11 +1122,25 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
916
             * the PID file, child will do the free and unlink.
917
             */
918
            c->pidfile = NULL;
919
+#ifdef HAVE_ISULAD
920
+           close(conf->errpipe[1]);
921
+           conf->errpipe[1] = -1;
922
+#endif
923
 
924
            /* Wait for container to tell us whether it started
925
             * successfully.
926
             */
927
            started = wait_on_daemonized_start(handler, pid_first);
928
+#ifdef HAVE_ISULAD
929
+           if (!started) {
930
+               size_read = read(conf->errpipe[0], errbuf, BUFSIZ);
931
+               if (size_read > 0) {
932
+                   conf->errmsg = safe_strdup(errbuf);
933
+               }
934
+           }
935
+           close(conf->errpipe[0]);
936
+           conf->errpipe[0] = -1;
937
+#endif
938
 
939
            free_init_cmd(init_cmd);
940
            lxc_put_handler(handler);
941
@@ -1012,6 +1176,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
942
        if (pid_second != 0) {
943
            free_init_cmd(init_cmd);
944
            lxc_put_handler(handler);
945
+#ifdef HAVE_ISULAD
946
+           lxc_close_error_pipe(conf->errpipe);
947
+#endif
948
            _exit(EXIT_SUCCESS);
949
        }
950
 
951
@@ -1024,7 +1191,18 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
952
            _exit(EXIT_FAILURE);
953
        }
954
 
955
+#ifdef HAVE_ISULAD
956
+       keepfds[0] = handler->conf->maincmd_fd;
957
+       keepfds[1] = handler->state_socket_pair[0];
958
+       keepfds[2] = handler->state_socket_pair[1];
959
+       keepfds[4] = conf->errpipe[1];
960
+       close(conf->errpipe[0]);
961
+       conf->errpipe[0] = -1;
962
+       ret = lxc_check_inherited(conf, true, keepfds,
963
+                     sizeof(keepfds) / sizeof(keepfds[0]));
964
+#else
965
        ret = inherit_fds(handler, true);
966
+#endif
967
        if (ret < 0)
968
            _exit(EXIT_FAILURE);
969
 
970
@@ -1057,6 +1235,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
971
        if (w < 0) {
972
            free_init_cmd(init_cmd);
973
            lxc_put_handler(handler);
974
+#ifdef HAVE_ISULAD
975
+           lxc_close_error_pipe(conf->errpipe);
976
+#endif
977
 
978
            SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
979
 
980
@@ -1070,6 +1251,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
981
        if (ret < 0) {
982
            free_init_cmd(init_cmd);
983
            lxc_put_handler(handler);
984
+#ifdef HAVE_ISULAD
985
+           lxc_close_error_pipe(conf->errpipe);
986
+#endif
987
 
988
            SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
989
 
990
@@ -1080,6 +1264,19 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
991
        }
992
    }
993
 
994
+#ifdef HAVE_ISULAD
995
+   /* isulad: open exit fifo */
996
+   if (c->exit_fifo) {
997
+       conf->exit_fd = lxc_open(c->exit_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0);
998
+       if (conf->exit_fd < 0) {
999
+           ERROR("Failed to open exit fifo %s: %s.", c->exit_fifo, strerror(errno));
1000
+           lxc_put_handler(handler);
1001
+           ret = 1;
1002
+           goto on_error;
1003
+       }
1004
+   }
1005
+#endif
1006
+
1007
    conf->reboot = REBOOT_NONE;
1008
 
1009
    /* Unshare the mount namespace if requested */
1010
@@ -1111,19 +1308,53 @@ reboot:
1011
        }
1012
    }
1013
 
1014
+#ifdef HAVE_ISULAD
1015
+   keepfds[0] = handler->conf->maincmd_fd;
1016
+   keepfds[1] = handler->state_socket_pair[0];
1017
+   keepfds[2] = handler->state_socket_pair[1];
1018
+
1019
+   /* keep exit fifo fd */
1020
+   if (conf->exit_fd >= 0) {
1021
+       keepfds[3] = conf->exit_fd;
1022
+   }
1023
+   /* isulad: keep errpipe fd */
1024
+   if (c->daemonize)
1025
+       keepfds[4] = conf->errpipe[1];
1026
+
1027
+   ret = lxc_check_inherited(conf, c->daemonize, keepfds,
1028
+                 sizeof(keepfds) / sizeof(keepfds[0]));
1029
+   if (ret < 0) {
1030
+       lxc_put_handler(handler);
1031
+       ret = 1;
1032
+       goto on_error;
1033
+   }
1034
+#else
1035
    ret = inherit_fds(handler, c->daemonize);
1036
    if (ret < 0) {
1037
        lxc_put_handler(handler);
1038
        ret = 1;
1039
        goto on_error;
1040
    }
1041
+#endif
1042
 
1043
+#ifndef HAVE_ISULAD
1044
    if (useinit)
1045
        ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
1046
                  c->daemonize, &c->error_num);
1047
    else
1048
        ret = lxc_start(argv, handler, c->config_path, c->daemonize,
1049
                &c->error_num);
1050
+#else
1051
+   if (useinit) {
1052
+       ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
1053
+                 c->daemonize, &c->error_num, c->start_timeout);
1054
+   } else {
1055
+       handler->disable_pty = c->disable_pty;
1056
+       handler->open_stdin = c->open_stdin;
1057
+       ret = lxc_start(argv, handler, c->config_path, c->daemonize,
1058
+               &c->error_num, c->start_timeout);
1059
+   }
1060
+#endif
1061
 
1062
    if (conf->reboot == REBOOT_REQ) {
1063
        INFO("Container requested reboot");
1064
@@ -2065,7 +2296,12 @@ WRAP_API_1(bool, lxcapi_reboot2, int)
1065
 static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
1066
 {
1067
    __do_close int pidfd = -EBADF, state_client_fd = -EBADF;
1068
+#ifdef HAVE_ISULAD
1069
+   // isulad: keep default signal the same as docker
1070
+   int haltsignal = SIGTERM;
1071
+#else
1072
    int haltsignal = SIGPWR;
1073
+#endif
1074
    pid_t pid = -1;
1075
    lxc_state_t states[MAX_STATE] = {0};
1076
    int killret, ret;
1077
@@ -2084,9 +2320,10 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
1078
    /* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */
1079
    if (c->lxc_conf && c->lxc_conf->haltsignal)
1080
        haltsignal = c->lxc_conf->haltsignal;
1081
+#ifndef HAVE_ISULAD
1082
    else if (task_blocks_signal(pid, (SIGRTMIN + 3)))
1083
        haltsignal = (SIGRTMIN + 3);
1084
-
1085
+#endif
1086
 
1087
    /*
1088
     * Add a new state client before sending the shutdown signal so
1089
@@ -2939,6 +3176,21 @@ static int lxc_unlink_exec_wrapper(void *data)
1090
    return unlink(arg);
1091
 }
1092
 
1093
+#ifdef HAVE_ISULAD
1094
+static void container_sock_dir_delete(const char *name)
1095
+{
1096
+   __do_free char *sock_dir = NULL;
1097
+
1098
+   sock_dir = generate_named_unix_sock_dir(name);
1099
+   if (sock_dir == NULL) {
1100
+       ERROR("Failed to generate exec unix sock dir");
1101
+       return;
1102
+   }
1103
+
1104
+   (void)lxc_rmdir_onedev(sock_dir, NULL);
1105
+}
1106
+#endif
1107
+
1108
 static bool container_destroy(struct lxc_container *c,
1109
                  struct lxc_storage *storage)
1110
 {
1111
@@ -2949,8 +3201,19 @@ static bool container_destroy(struct lxc_container *c,
1112
    bool bret = false;
1113
    int ret = 0;
1114
 
1115
+#ifdef HAVE_ISULAD
1116
+   if (!c)
1117
+       return false;
1118
+   // isulad: if container is not defined, we need to remove disk lock file
1119
+   // which is created in lxc_container_new.
1120
+   if (!do_lxcapi_is_defined(c)) {
1121
+       container_disk_removelock(c);
1122
+       return false;
1123
+   }
1124
+#else
1125
    if (!c || !do_lxcapi_is_defined(c))
1126
        return false;
1127
+#endif
1128
 
1129
    conf = c->lxc_conf;
1130
    if (container_disk_lock(c))
1131
@@ -3070,8 +3333,20 @@ static bool container_destroy(struct lxc_container *c,
1132
    if (ret < 0) {
1133
        ERROR("Failed to destroy directory \"%s\" for \"%s\"", path,
1134
              c->name);
1135
+#ifdef HAVE_ISULAD
1136
+       char msg[BUFSIZ] = { 0 };
1137
+       ret = snprintf(msg, BUFSIZ, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error");
1138
+       if (ret < 0 || ret >= BUFSIZ) {
1139
+           ERROR("Sprintf failed");
1140
+           goto out;
1141
+       }
1142
+       c->error_string = safe_strdup(msg);
1143
+#endif
1144
        goto out;
1145
    }
1146
+#ifdef HAVE_ISULAD
1147
+   container_sock_dir_delete(c->name);
1148
+#endif
1149
    INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name);
1150
 
1151
 on_success:
1152
@@ -3082,6 +3357,11 @@ out:
1153
        free(path);
1154
 
1155
    container_disk_unlock(c);
1156
+#ifdef HAVE_ISULAD
1157
+   if (bret && container_disk_removelock(c)) {
1158
+       bret = false;
1159
+   }
1160
+#endif
1161
    return bret;
1162
 }
1163
 
1164
@@ -4042,8 +4322,13 @@ static int lxcapi_attach(struct lxc_container *c,
1165
 
1166
    current_config = c->lxc_conf;
1167
 
1168
+#ifdef HAVE_ISULAD
1169
+   ret = lxc_attach(c, exec_function, exec_payload, options,
1170
+            attached_process, &c->lxc_conf->errmsg);
1171
+#else
1172
    ret = lxc_attach(c, exec_function, exec_payload, options,
1173
             attached_process);
1174
+#endif
1175
    current_config = NULL;
1176
    return ret;
1177
 }
1178
@@ -4063,7 +4348,11 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c,
1179
    command.program = (char *)program;
1180
    command.argv = (char **)argv;
1181
 
1182
+#ifdef HAVE_ISULAD
1183
+   ret = lxc_attach(c, lxc_attach_run_command, &command, options, &pid, NULL);
1184
+#else
1185
    ret = lxc_attach(c, lxc_attach_run_command, &command, options, &pid);
1186
+#endif
1187
    if (ret < 0)
1188
        return ret;
1189
 
1190
@@ -5257,6 +5546,560 @@ static int do_lxcapi_seccomp_notify_fd_active(struct lxc_container *c)
1191
 
1192
 WRAP_API(int, lxcapi_seccomp_notify_fd_active)
1193
 
1194
+#ifdef HAVE_ISULAD
1195
+/* isulad add set console fifos*/
1196
+static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out, const char *err)
1197
+{
1198
+   struct lxc_conf *conf = NULL;
1199
+
1200
+   if (!c || !c->lxc_conf)
1201
+       return false;
1202
+   if (container_mem_lock(c)) {
1203
+       ERROR("Error getting mem lock");
1204
+       return false;
1205
+   }
1206
+
1207
+   conf = c->lxc_conf;
1208
+   if (in) {
1209
+       if (conf->console.init_fifo[0])
1210
+           free(conf->console.init_fifo[0]);
1211
+       conf->console.init_fifo[0] = safe_strdup(in);
1212
+   }
1213
+   if (out) {
1214
+       if (conf->console.init_fifo[1])
1215
+           free(conf->console.init_fifo[1]);
1216
+       conf->console.init_fifo[1] = safe_strdup(out);
1217
+   }
1218
+   if (err) {
1219
+       if (conf->console.init_fifo[2])
1220
+           free(conf->console.init_fifo[2]);
1221
+       conf->console.init_fifo[2] = safe_strdup(err);
1222
+   }
1223
+
1224
+   container_mem_unlock(c);
1225
+   return true;
1226
+}
1227
+
1228
+WRAP_API_3(bool, lxcapi_set_terminal_default_fifos, const char *, const char *, const char *)
1229
+
1230
+/* isulad add set info file path */
1231
+static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file)
1232
+{
1233
+   struct lxc_conf *conf = NULL;
1234
+
1235
+   if (!c || !c->lxc_conf || !info_file)
1236
+       return false;
1237
+   if (container_mem_lock(c)) {
1238
+       ERROR("Error getting mem lock");
1239
+       return false;
1240
+   }
1241
+
1242
+   conf = c->lxc_conf;
1243
+   if (conf->container_info_file)
1244
+       free(conf->container_info_file);
1245
+   conf->container_info_file = safe_strdup(info_file);
1246
+
1247
+   container_mem_unlock(c);
1248
+   return true;
1249
+}
1250
+
1251
+WRAP_API_1(bool, lxcapi_set_container_info_file, const char *)
1252
+
1253
+static bool do_lxcapi_want_disable_pty(struct lxc_container *c, bool state)
1254
+{
1255
+   if (!c || !c->lxc_conf)
1256
+       return false;
1257
+
1258
+   if (container_mem_lock(c))
1259
+       return false;
1260
+
1261
+   c->disable_pty = state;
1262
+
1263
+   container_mem_unlock(c);
1264
+
1265
+   return true;
1266
+}
1267
+
1268
+WRAP_API_1(bool, lxcapi_want_disable_pty, bool)
1269
+
1270
+static bool do_lxcapi_want_open_stdin(struct lxc_container *c, bool state)
1271
+{
1272
+   if (!c || !c->lxc_conf)
1273
+       return false;
1274
+
1275
+   if (container_mem_lock(c))
1276
+       return false;
1277
+
1278
+   c->open_stdin = state;
1279
+
1280
+   container_mem_unlock(c);
1281
+
1282
+   return true;
1283
+}
1284
+
1285
+WRAP_API_1(bool, lxcapi_want_open_stdin, bool)
1286
+
1287
+/* isulad add clean resources */
1288
+static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo, const char *err_fifo)
1289
+{
1290
+   bool ret = true;
1291
+
1292
+   if (!c || !c->lxc_conf)
1293
+       return false;
1294
+   if (container_mem_lock(c)) {
1295
+       ERROR("Error getting mem lock");
1296
+       return false;
1297
+   }
1298
+
1299
+   if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo, err_fifo)) {
1300
+       ERROR("Error set console fifos");
1301
+       ret = false;
1302
+   }
1303
+
1304
+   container_mem_unlock(c);
1305
+   return ret;
1306
+}
1307
+
1308
+WRAP_API_3(bool, lxcapi_add_terminal_fifo, const char *, const char *, const char *)
1309
+
1310
+static bool do_lxcapi_set_terminal_winch(struct lxc_container *c, unsigned int height, unsigned int width)
1311
+{
1312
+   bool ret = true;
1313
+
1314
+   if (!c || !c->lxc_conf)
1315
+       return false;
1316
+   if (container_mem_lock(c)) {
1317
+       ERROR("Error getting mem lock");
1318
+       return false;
1319
+   }
1320
+
1321
+   if (lxc_cmd_set_terminal_winch(c->name, c->config_path, height, width)) {
1322
+       ERROR("Error set terminal winch");
1323
+       ret = false;
1324
+   }
1325
+
1326
+   container_mem_unlock(c);
1327
+   return ret;
1328
+}
1329
+
1330
+WRAP_API_2(bool, lxcapi_set_terminal_winch, unsigned int, unsigned int)
1331
+
1332
+static bool do_lxcapi_set_exec_terminal_winch(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width)
1333
+{
1334
+   bool ret = true;
1335
+
1336
+   if (!c || !c->lxc_conf)
1337
+       return false;
1338
+   if (container_mem_lock(c)) {
1339
+       ERROR("Error getting mem lock");
1340
+       return false;
1341
+   }
1342
+
1343
+   if (lxc_exec_cmd_set_terminal_winch(c->name, c->config_path, suffix, height, width)) {
1344
+       ERROR("Error set terminal winch");
1345
+       ret = false;
1346
+   }
1347
+
1348
+   container_mem_unlock(c);
1349
+   return ret;
1350
+}
1351
+
1352
+WRAP_API_3(bool, lxcapi_set_exec_terminal_winch, const char *, unsigned int, unsigned int)
1353
+
1354
+/* isulad add clean resources */
1355
+static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pid)
1356
+{
1357
+   int ret;
1358
+
1359
+   if (!c)
1360
+       return false;
1361
+
1362
+   ret = do_lxcapi_clean_resource(c->name, c->config_path, c->lxc_conf, pid);
1363
+   if (ret)
1364
+       ERROR("Failed to clean container %s resource", c->name);
1365
+   return ret == 0;
1366
+
1367
+}
1368
+
1369
+WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t)
1370
+
1371
+/* isulad get coantainer pids */
1372
+static bool do_lxcapi_get_container_pids(struct lxc_container *c, pid_t **pids,size_t *pids_len)
1373
+{
1374
+   int ret;
1375
+
1376
+   if (!c)
1377
+       return false;
1378
+
1379
+   ret = do_lxcapi_get_pids(c->name, c->config_path, c->lxc_conf, pids,pids_len);
1380
+   if (ret)
1381
+       ERROR("Failed to get container %s pids", c->name);
1382
+   return ret == 0;
1383
+
1384
+}
1385
+
1386
+WRAP_API_2(bool, lxcapi_get_container_pids, pid_t **,size_t *)
1387
+
1388
+/* isulad add start timeout */
1389
+static bool do_lxcapi_set_start_timeout(struct lxc_container *c,  unsigned int start_timeout)
1390
+{
1391
+   if (!c || !c->lxc_conf)
1392
+       return false;
1393
+   if (container_mem_lock(c)) {
1394
+       ERROR("Error getting mem lock");
1395
+       return false;
1396
+   }
1397
+   c->start_timeout = start_timeout;
1398
+   container_mem_unlock(c);
1399
+   return true;
1400
+}
1401
+
1402
+WRAP_API_1(bool, lxcapi_set_start_timeout, unsigned int)
1403
+
1404
+/* isulad add set image type */
1405
+static bool do_lxcapi_set_oci_type(struct lxc_container *c,  bool image_type_oci)
1406
+{
1407
+   if (!c || !c->lxc_conf)
1408
+       return false;
1409
+   if (container_mem_lock(c)) {
1410
+       ERROR("Error getting mem lock");
1411
+       return false;
1412
+   }
1413
+   c->image_type_oci = image_type_oci;
1414
+   container_mem_unlock(c);
1415
+   return true;
1416
+}
1417
+
1418
+WRAP_API_1(bool, lxcapi_set_oci_type, bool)
1419
+
1420
+static uint64_t metrics_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item)
1421
+{
1422
+    char buf[81] = {0};
1423
+    int len = 0;
1424
+    uint64_t val = 0;
1425
+
1426
+    len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
1427
+    if (len <= 0) {
1428
+        DEBUG("unable to read cgroup item %s", item);
1429
+        return 0;
1430
+    }
1431
+
1432
+    val = strtoull(buf, NULL, 0);
1433
+    return val;
1434
+}
1435
+
1436
+static uint64_t metrics_get_ull_with_max(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item)
1437
+{
1438
+    char buf[81] = {0};
1439
+    int len = 0;
1440
+    uint64_t val = 0;
1441
+
1442
+    len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
1443
+    if (len <= 0) {
1444
+        DEBUG("unable to read cgroup item %s", item);
1445
+        return 0;
1446
+    }
1447
+
1448
+    if (strcmp(buf, "max") == 0) {
1449
+   return ULONG_MAX;
1450
+    }
1451
+
1452
+    val = strtoull(buf, NULL, 0);
1453
+    return val;
1454
+}
1455
+
1456
+static inline bool is_blk_metrics_read(const char *value)
1457
+{
1458
+    return strcmp(value, "Read") == 0;
1459
+}
1460
+
1461
+static inline bool is_blk_metrics_write(const char *value)
1462
+{
1463
+    return strcmp(value, "Write") == 0;
1464
+}
1465
+
1466
+static inline bool is_blk_metrics_total(const char *value)
1467
+{
1468
+    return strcmp(value, "Total") == 0;
1469
+}
1470
+
1471
+static void metrics_get_blk_stats(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, struct lxc_blkio_metrics *stats)
1472
+{
1473
+    char *buf = NULL;
1474
+    int i = 0;
1475
+    int len = 0;
1476
+    int ret = 0;
1477
+    char **lines = NULL;
1478
+    char **cols = NULL;
1479
+
1480
+    len = cgroup_ops->get(cgroup_ops, item, NULL, 0, c->name, c->config_path);
1481
+    if (len <= 0) {
1482
+        DEBUG("unable to read cgroup item %s", item);
1483
+        return;
1484
+    }
1485
+
1486
+    buf = malloc(len + 1);
1487
+    (void)memset(buf, 0, len + 1);
1488
+    ret = cgroup_ops->get(cgroup_ops, item, buf, len, c->name, c->config_path);
1489
+    if (ret <= 0) {
1490
+        DEBUG("unable to read cgroup item %s", item);
1491
+        goto out;
1492
+    }
1493
+
1494
+    lines = lxc_string_split_and_trim(buf, '\n');
1495
+    if (lines == NULL) {
1496
+        goto out;
1497
+    }
1498
+
1499
+    (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics));
1500
+
1501
+    for (i = 0; lines[i]; i++) {
1502
+        cols = lxc_string_split_and_trim(lines[i], ' ');
1503
+        if (cols == NULL) {
1504
+            goto err_out;
1505
+        }
1506
+        if (lxc_array_len((void **)cols) == 3) {
1507
+            if (is_blk_metrics_read(cols[1])) {
1508
+                stats->read += strtoull(cols[2], NULL, 0);
1509
+            } else if (is_blk_metrics_write(cols[1])) {
1510
+                stats->write += strtoull(cols[2], NULL, 0);
1511
+            }
1512
+        }
1513
+        if (lxc_array_len((void **)cols) == 2 && is_blk_metrics_total(cols[0])) {
1514
+            stats->total = strtoull(cols[1], NULL, 0);
1515
+        }
1516
+
1517
+        lxc_free_array((void **)cols, free);
1518
+    }
1519
+err_out:
1520
+    lxc_free_array((void **)lines, free);
1521
+out:
1522
+    free(buf);
1523
+    return;
1524
+}
1525
+
1526
+static void metrics_get_io_stats_v2(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, struct lxc_blkio_metrics *stats, func_is_io_stat_read is_io_stat_read, func_is_io_stat_write is_io_stat_write)
1527
+{
1528
+    char *buf = NULL;
1529
+    int i = 0;
1530
+    int j = 0;
1531
+    int len = 0;
1532
+    int ret = 0;
1533
+    char **lines = NULL;
1534
+    char **cols = NULL;
1535
+    char **kv = NULL;
1536
+
1537
+    len = cgroup_ops->get(cgroup_ops, item, NULL, 0, c->name, c->config_path);
1538
+    if (len <= 0) {
1539
+        DEBUG("unable to read cgroup item %s", item);
1540
+        return;
1541
+    }
1542
+
1543
+    buf = malloc(len + 1);
1544
+    (void)memset(buf, 0, len + 1);
1545
+    ret = cgroup_ops->get(cgroup_ops, item, buf, len, c->name, c->config_path);
1546
+    if (ret <= 0) {
1547
+        DEBUG("unable to read cgroup item %s", item);
1548
+        goto out;
1549
+    }
1550
+
1551
+    lines = lxc_string_split_and_trim(buf, '\n');
1552
+    if (lines == NULL) {
1553
+        goto out;
1554
+    }
1555
+
1556
+    (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics));
1557
+    // line example:
1558
+    // 259:0 rbytes=0 wbytes=12288 rios=0 wios=4 dbytes=0 dios=0
1559
+    for (i = 0; lines[i]; i++) {
1560
+        cols = lxc_string_split_and_trim(lines[i], ' ');
1561
+        if (cols == NULL || lxc_array_len((void **)cols) < 2) {
1562
+            goto err_out;
1563
+        }
1564
+        len = lxc_array_len((void **)cols);
1565
+        for (j = 1; j < len; j++) {
1566
+            kv = lxc_string_split(cols[j], '=');
1567
+            if (kv == NULL || lxc_array_len((void **)kv) != 2) {
1568
+                lxc_free_array((void **)kv, free);
1569
+                continue;
1570
+            }
1571
+            if (is_io_stat_read(kv[0])) {
1572
+                stats->read += strtoull(kv[1], NULL, 0);
1573
+            } else if (is_io_stat_write(kv[0])) {
1574
+                stats->write += strtoull(kv[1], NULL, 0);
1575
+            }
1576
+            lxc_free_array((void **)kv, free);
1577
+        }
1578
+        lxc_free_array((void **)cols, free);
1579
+    }
1580
+
1581
+    stats->total = stats->read + stats->write;
1582
+
1583
+err_out:
1584
+    lxc_free_array((void **)lines, free);
1585
+out:
1586
+    free(buf);
1587
+    return;
1588
+}
1589
+
1590
+static uint64_t metrics_match_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, const char *match, int column)
1591
+{
1592
+#define BUFSIZE 4096
1593
+    char buf[BUFSIZE] = {0};
1594
+    int i = 0;
1595
+    int j = 0;
1596
+    int len = 0;
1597
+    uint64_t val = 0;
1598
+    char **lines = NULL;
1599
+    char **cols = NULL;
1600
+    size_t matchlen = 0;
1601
+
1602
+    len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
1603
+    if (len <= 0) {
1604
+        DEBUG("unable to read cgroup item %s", item);
1605
+        goto err_out;
1606
+    }
1607
+
1608
+    lines = lxc_string_split_and_trim(buf, '\n');
1609
+    if (lines == NULL) {
1610
+        goto err_out;
1611
+    }
1612
+
1613
+    matchlen = strlen(match);
1614
+    for (i = 0; lines[i]; i++) {
1615
+        if (strncmp(lines[i], match, matchlen) != 0) {
1616
+            continue;
1617
+        }
1618
+
1619
+        cols = lxc_string_split_and_trim(lines[i], ' ');
1620
+        if (cols == NULL) {
1621
+            goto err1;
1622
+        }
1623
+        for (j = 0; cols[j]; j++) {
1624
+            if (j == column) {
1625
+                val = strtoull(cols[j], NULL, 0);
1626
+                break;
1627
+            }
1628
+        }
1629
+        lxc_free_array((void **)cols, free);
1630
+        break;
1631
+    }
1632
+err1:
1633
+    lxc_free_array((void **)lines, free);
1634
+err_out:
1635
+    return val;
1636
+}
1637
+
1638
+static bool is_io_stat_rbytes(const char *value)
1639
+{
1640
+    return strcmp(value, "rbytes") == 0;
1641
+}
1642
+
1643
+static bool is_io_stat_wbytes(const char *value)
1644
+{
1645
+    return strcmp(value, "wbytes") == 0;
1646
+}
1647
+
1648
+static bool is_io_stat_rios(const char *value)
1649
+{
1650
+    return strcmp(value, "rios") == 0;
1651
+}
1652
+
1653
+static bool is_io_stat_wios(const char *value)
1654
+{
1655
+    return strcmp(value, "wios") == 0;
1656
+}
1657
+
1658
+static bool unified_metrics_get(struct lxc_container *c, struct cgroup_ops *cgroup_ops, struct lxc_container_metrics *metrics)
1659
+{
1660
+   // cpu
1661
+   metrics->cpu_use_nanos = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "usage_usec", 1) * 1000;
1662
+   metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "user_usec", 1) * 1000;
1663
+   metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "system_usec", 1) * 1000;
1664
+
1665
+   // io
1666
+   metrics_get_io_stats_v2(c, cgroup_ops, "io.stat", &metrics->io_service_bytes, is_io_stat_rbytes, is_io_stat_wbytes);
1667
+   metrics_get_io_stats_v2(c, cgroup_ops, "io.stat", &metrics->io_serviced, is_io_stat_rios, is_io_stat_wios);
1668
+
1669
+   // memory
1670
+   metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.current");
1671
+   metrics->mem_limit = metrics_get_ull_with_max(c, cgroup_ops, "memory.max");
1672
+   metrics->inactive_file_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "inactive_file", 1);
1673
+   metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "file", 1);
1674
+   metrics->cache_total = metrics->cache;
1675
+
1676
+   // cgroup v2 does not support kernel memory
1677
+   metrics->kmem_used = 0;
1678
+   metrics->kmem_limit = 0;
1679
+
1680
+   // pids
1681
+   metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current");
1682
+
1683
+   return true;
1684
+}
1685
+
1686
+/* isulad add get container metrics */
1687
+static bool do_lxcapi_get_container_metrics(struct lxc_container *c,  struct lxc_container_metrics *metrics)
1688
+{
1689
+   call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
1690
+   const char *state = NULL;
1691
+   if (c == NULL || c->lxc_conf == NULL || metrics == NULL) {
1692
+       return false;
1693
+   }
1694
+
1695
+   state = c->state(c);
1696
+   metrics->state = state;
1697
+
1698
+   if (!is_stopped(c)) {
1699
+       metrics->init = c->init_pid(c);
1700
+   } else {
1701
+       metrics->init = -1;
1702
+   }
1703
+
1704
+   cgroup_ops = cgroup_init(c->lxc_conf);
1705
+   if (cgroup_ops == NULL) {
1706
+       return false;
1707
+   }
1708
+
1709
+   if (cgroup_ops->cgroup_layout == CGROUP_LAYOUT_UNIFIED) {
1710
+       return unified_metrics_get(c, cgroup_ops, metrics);
1711
+   }
1712
+
1713
+   metrics->cpu_use_nanos = metrics_get_ull(c, cgroup_ops, "cpuacct.usage");
1714
+   metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current");
1715
+
1716
+   metrics->rss_bytes = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "rss", 1);
1717
+   metrics->page_faults = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "pgfault", 1);
1718
+   metrics->major_page_faults = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "pgmajfault", 1);
1719
+
1720
+   metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "user", 1);
1721
+   metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "system", 1);
1722
+
1723
+   // Try to read CFQ stats available on all CFQ enabled kernels first
1724
+   metrics_get_blk_stats(c, cgroup_ops, "blkio.io_serviced_recursive", &metrics->io_serviced);
1725
+   if (metrics->io_serviced.read == 0 && metrics->io_serviced.write == 0 && metrics->io_serviced.total == 0) {
1726
+       metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_service_bytes", &metrics->io_service_bytes);
1727
+       metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_serviced", &metrics->io_serviced);
1728
+   } else {
1729
+       metrics_get_blk_stats(c, cgroup_ops, "blkio.io_service_bytes_recursive", &metrics->io_service_bytes);
1730
+   }
1731
+
1732
+   metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.usage_in_bytes");
1733
+   metrics->mem_limit = metrics_get_ull(c, cgroup_ops, "memory.limit_in_bytes");
1734
+   metrics->kmem_used = metrics_get_ull(c, cgroup_ops, "memory.kmem.usage_in_bytes");
1735
+   metrics->kmem_limit = metrics_get_ull(c, cgroup_ops, "memory.kmem.limit_in_bytes");
1736
+
1737
+   metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "cache", 1);
1738
+   metrics->cache_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_cache", 1);
1739
+   metrics->inactive_file_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_inactive_file", 1);
1740
+
1741
+   return true;
1742
+}
1743
+
1744
+WRAP_API_1(bool, lxcapi_get_container_metrics, struct lxc_container_metrics *)
1745
+
1746
+#endif
1747
+
1748
 struct lxc_container *lxc_container_new(const char *name, const char *configpath)
1749
 {
1750
    struct lxc_container *c;
1751
@@ -5310,10 +6153,24 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
1752
        goto err;
1753
    }
1754
 
1755
+#ifdef HAVE_ISULAD
1756
+   if (!set_oci_hook_config_filename(c)) {
1757
+       fprintf(stderr, "Error allocating oci hooks file pathname\n");
1758
+       goto err;
1759
+   }
1760
+
1761
+   if (load_config && file_exists(c->configfile)) {
1762
+       if (!lxcapi_load_config(c, NULL)) {
1763
+           fprintf(stderr, "Failed to load config for %s\n", name);
1764
+           goto err;
1765
+       }
1766
+   }
1767
+#else
1768
    if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) {
1769
        fprintf(stderr, "Failed to load config for %s\n", name);
1770
        goto err;
1771
    }
1772
+#endif
1773
 
1774
    rc = ongoing_create(c);
1775
    switch (rc) {
1776
@@ -5337,6 +6194,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
1777
 
1778
    c->daemonize            = true;
1779
    c->pidfile          = NULL;
1780
+#ifdef HAVE_ISULAD
1781
+   c->image_type_oci = false;
1782
+#endif
1783
 
1784
    /* Assign the member functions. */
1785
    c->is_defined           = lxcapi_is_defined;
1786
@@ -5400,6 +6260,20 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
1787
    c->umount           = lxcapi_umount;
1788
    c->seccomp_notify_fd        = lxcapi_seccomp_notify_fd;
1789
    c->seccomp_notify_fd_active = lxcapi_seccomp_notify_fd_active;
1790
+#ifdef HAVE_ISULAD
1791
+   c->set_container_info_file = lxcapi_set_container_info_file;
1792
+   c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos;
1793
+   c->add_terminal_fifos = lxcapi_add_terminal_fifo;
1794
+   c->set_terminal_winch = lxcapi_set_terminal_winch;
1795
+   c->set_exec_terminal_winch = lxcapi_set_exec_terminal_winch;
1796
+   c->want_disable_pty = lxcapi_want_disable_pty;
1797
+   c->want_open_stdin = lxcapi_want_open_stdin;
1798
+   c->clean_container_resource = lxcapi_clean_container_resource;
1799
+   c->get_container_pids = lxcapi_get_container_pids;
1800
+   c->set_start_timeout = lxcapi_set_start_timeout;
1801
+   c->set_oci_type = lxcapi_set_oci_type;
1802
+   c->get_container_metrics = lxcapi_get_container_metrics;
1803
+#endif
1804
 
1805
    return c;
1806
 
1807
@@ -5408,6 +6282,19 @@ err:
1808
    return NULL;
1809
 }
1810
 
1811
+#ifdef HAVE_ISULAD
1812
+// isulad: new container without load config to save time
1813
+struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath)
1814
+{
1815
+   return do_lxc_container_new(name, configpath, false);
1816
+}
1817
+
1818
+struct lxc_container *lxc_container_new(const char *name, const char *configpath)
1819
+{
1820
+   return do_lxc_container_new(name, configpath, true);
1821
+}
1822
+#endif
1823
+
1824
 int lxc_get_wait_states(const char **states)
1825
 {
1826
    int i;
1827
@@ -5578,11 +6465,21 @@ int list_active_containers(const char *lxcpath, char ***nret,
1828
                continue;
1829
        }
1830
 
1831
+#ifdef HAVE_ISULAD
1832
+       if (ct_name && ct_name_cnt) {
1833
+           if (array_contains(&ct_name, p, ct_name_cnt)) {
1834
+               if (is_hashed)
1835
+                   free(p);
1836
+               continue;
1837
+           }
1838
+       }
1839
+#else
1840
        if (array_contains(&ct_name, p, ct_name_cnt)) {
1841
            if (is_hashed)
1842
                free(p);
1843
            continue;
1844
        }
1845
+#endif
1846
 
1847
        if (!add_to_array(&ct_name, p, ct_name_cnt)) {
1848
            if (is_hashed)
1849
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
1850
index 3386bff..06e8f0b 100644
1851
--- a/src/lxc/lxccontainer.h
1852
+++ b/src/lxc/lxccontainer.h
1853
@@ -26,6 +26,10 @@ extern "C" {
1854
 #define LXC_CREATE_MAXFLAGS       (1 << 1) /*!< Number of \c LXC_CREATE* flags */
1855
 #define LXC_MOUNT_API_V1          1
1856
 
1857
+#ifdef HAVE_ISULAD
1858
+#define LXC_IMAGE_OCI_KEY "lxc.imagetype.oci"
1859
+#endif
1860
+
1861
 struct bdev_specs;
1862
 
1863
 struct lxc_snapshot;
1864
@@ -40,6 +44,44 @@ struct lxc_mount {
1865
    int version;
1866
 };
1867
 
1868
+#ifdef HAVE_ISULAD
1869
+struct lxc_blkio_metrics {
1870
+   uint64_t read;
1871
+   uint64_t write;
1872
+   uint64_t total;
1873
+};
1874
+
1875
+struct lxc_container_metrics {
1876
+    /* State of container */
1877
+    const char *state;
1878
+    /* The process ID of the init container */
1879
+    pid_t init;
1880
+    /* Current pids */
1881
+    uint64_t pids_current;
1882
+    /* CPU usage */
1883
+    uint64_t cpu_use_nanos;
1884
+    uint64_t cpu_use_user;
1885
+    uint64_t cpu_use_sys;
1886
+    /* BlkIO usage */
1887
+    struct lxc_blkio_metrics io_service_bytes;
1888
+    struct lxc_blkio_metrics io_serviced;
1889
+    /* Memory usage */
1890
+    uint64_t mem_used;
1891
+    uint64_t mem_limit;
1892
+    uint64_t rss_bytes;
1893
+    uint64_t page_faults;
1894
+    uint64_t major_page_faults;
1895
+    /* Kernel Memory usage */
1896
+    uint64_t kmem_used;
1897
+    uint64_t kmem_limit;
1898
+    /* Cache usage */
1899
+    uint64_t cache;
1900
+    uint64_t cache_total;
1901
+    /* total inactive file */
1902
+    uint64_t inactive_file_total;
1903
+};
1904
+#endif
1905
+
1906
 /*!
1907
  * An LXC container.
1908
  *
1909
@@ -107,6 +149,38 @@ struct lxc_container {
1910
    /*! Full path to configuration file */
1911
    char *config_path;
1912
 
1913
+#ifdef HAVE_ISULAD
1914
+   /*! isulad:
1915
+    * \private
1916
+    * exit FIFO File to open used monitor the state of lxc monitor process.
1917
+    */
1918
+   char *exit_fifo;
1919
+   /*! Whether container wishes to create pty or pipes for console log */
1920
+   bool disable_pty;
1921
+
1922
+   /*! Whether container wishes to keep stdin active */
1923
+   bool open_stdin;
1924
+
1925
+   /*!
1926
+    * \private
1927
+    * isulad: support oci hook from json file
1928
+    * full path of json file
1929
+    * */
1930
+   char *ocihookfile;
1931
+
1932
+   /*! isulad:
1933
+    * \private
1934
+    * start_timeout.
1935
+    */
1936
+   unsigned int start_timeout;
1937
+
1938
+   /*! isulad:
1939
+    * \private
1940
+    *  image_type_oci
1941
+    */
1942
+   bool image_type_oci;
1943
+#endif
1944
+
1945
    /*!
1946
     * \brief Determine if \c /var/lib/lxc/$name/config exists.
1947
     *
1948
@@ -884,6 +958,115 @@ struct lxc_container {
1949
     * \return Mount fd of the container's devpts instance.
1950
     */
1951
    int (*devpts_fd)(struct lxc_container *c);
1952
+
1953
+#ifdef HAVE_ISULAD
1954
+   /*! isulad add
1955
+    * \brief An API call to set the path of info file
1956
+    *
1957
+    * \param c Container.
1958
+    * \param info_file Value of the path of info file.
1959
+    *
1960
+    * \return \c true on success, else \c false.
1961
+    */
1962
+   bool (*set_container_info_file) (struct lxc_container *c, const char *info_file);
1963
+
1964
+   /*! isulad add
1965
+    * \brief An API call to change the path of the console default fifos
1966
+    *
1967
+    * \param c Container.
1968
+    * \param path Value of the console path.
1969
+    *
1970
+    * \return \c true on success, else \c false.
1971
+    */
1972
+   bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err);
1973
+
1974
+   /*! isulad add
1975
+    * \brief An API call to add the path of terminal fifos
1976
+    *
1977
+    * \param c Container.
1978
+    * \param path Value of the console path..
1979
+    *
1980
+    * \return \c true on success, else \c false.
1981
+    */
1982
+   bool (*add_terminal_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err);
1983
+
1984
+   bool (*set_terminal_winch)(struct lxc_container *c, unsigned int height, unsigned int width);
1985
+
1986
+   bool (*set_exec_terminal_winch)(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width);
1987
+
1988
+   /*!
1989
+    * \brief Change whether the container wants to create pty or pipes
1990
+    * from the console log.
1991
+    *
1992
+    * \param c Container.
1993
+    * \param state Value for the disable pty bit (0 or 1).
1994
+    *
1995
+    * \return \c true on success, else \c false.
1996
+    */
1997
+   bool (*want_disable_pty)(struct lxc_container *c, bool state);
1998
+
1999
+   /*!
2000
+    * \brief Change whether the container wants to keep stdin active
2001
+    * for parent process of container
2002
+    *
2003
+    * \param c Container.
2004
+    * \param state Value for the open_stdin bit (0 or 1).
2005
+    *
2006
+    * \return \c true on success, else \c false.
2007
+    */
2008
+   bool (*want_open_stdin)(struct lxc_container *c, bool state);
2009
+
2010
+   /*! isulad add
2011
+    * \brief An API call to clean resources of container
2012
+    *
2013
+    * \param c Container.
2014
+    * \param pid Value of container process.
2015
+    *
2016
+    * \return \c true on success, else \c false.
2017
+    */
2018
+   bool (*clean_container_resource) (struct lxc_container *c, pid_t pid);
2019
+
2020
+   /*! isulad add
2021
+    * \brief An API call to get container pids
2022
+    *
2023
+    * \param c Container.
2024
+    * \param pids Value of container pids.
2025
+    * \param pids_len Value of container pids len.
2026
+    * \param pid Value of container pid.
2027
+    * \return \c true on success, else \c false.
2028
+    */
2029
+   bool (*get_container_pids)(struct lxc_container *c,pid_t **pids,size_t *pids_len);
2030
+
2031
+   /*! isulad add
2032
+    * \brief An API call to set start timeout
2033
+    *
2034
+    * \param c Container.
2035
+    * \param start_timeout Value of start timeout.
2036
+    *
2037
+    * \return \c true on success, else \c false.
2038
+    */
2039
+   bool (*set_start_timeout)(struct lxc_container *c, unsigned int start_timeout);
2040
+
2041
+   /*! isulad add
2042
+    * \brief An API call to set oci type
2043
+    *
2044
+    * \param c Container.
2045
+    * \param image_type_oci image oci type.
2046
+    *
2047
+    * \return \c true on success, else \c false.
2048
+    */
2049
+   bool (*set_oci_type)(struct lxc_container *c, bool image_type_oci);
2050
+   
2051
+   /*! isulad add
2052
+    * \brief An API call to set start timeout
2053
+    *
2054
+    * \param c Container.
2055
+    * \param start_timeout Value of start timeout.
2056
+    *
2057
+    * \return \c true on success, else \c false.
2058
+    */
2059
+   bool (*get_container_metrics)(struct lxc_container *c, struct lxc_container_metrics *metrics);
2060
+#endif
2061
 };
2062
 
2063
 /*!
2064
@@ -1017,6 +1200,20 @@ struct lxc_console_log {
2065
  */
2066
 struct lxc_container *lxc_container_new(const char *name, const char *configpath);
2067
 
2068
+#ifdef HAVE_ISULAD
2069
+/*!
2070
+ * \brief Create a new container without loading config.
2071
+ *
2072
+ * \param name Name to use for container.
2073
+ * \param configpath Full path to configuration file to use.
2074
+ *
2075
+ * \return Newly-allocated container, or \c NULL on error.
2076
+ *
2077
+ * \note This function can only used for listing container.
2078
+ */
2079
+struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath);
2080
+#endif
2081
+
2082
 /*!
2083
  * \brief Add a reference to the specified container.
2084
  *
2085
diff --git a/src/lxc/start.c b/src/lxc/start.c
2086
index 9f68304..70af128 100644
2087
--- a/src/lxc/start.c
2088
+++ b/src/lxc/start.c
2089
@@ -344,7 +344,11 @@ static int setup_signal_fd(sigset_t *oldmask)
2090
 {
2091
    int ret;
2092
    sigset_t mask;
2093
+#ifdef HAVE_ISULAD
2094
+   const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH, SIGTERM};
2095
+#else
2096
    const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH};
2097
+#endif
2098
 
2099
    /* Block everything except serious error signals. */
2100
    ret = sigfillset(&mask);
2101
@@ -625,6 +629,16 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
2102
 
2103
    TRACE("Mainloop is ready");
2104
 
2105
+#ifdef HAVE_ISULAD
2106
+   // iSulad: close stdin pipe if we do not want open_stdin with container stdin
2107
+   if (!handler->conf->console.open_stdin) {
2108
+       if (handler->conf->console.pipes[0][1] > 0) {
2109
+           close(handler->conf->console.pipes[0][1]);
2110
+           handler->conf->console.pipes[0][1] = -1;
2111
+       }
2112
+   }
2113
+#endif
2114
+
2115
    ret = lxc_mainloop(&descr, -1);
2116
    if (descr.type == LXC_MAINLOOP_EPOLL)
2117
        close_prot_errno_disarm(descr.epfd);
2118
@@ -634,7 +648,11 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
2119
    if (console) {
2120
        ret = lxc_terminal_mainloop_add(&descr_console, console);
2121
        if (ret == 0)
2122
+#ifdef HAVE_ISULAD
2123
+           ret = isulad_safe_mainloop(&descr_console, 100);
2124
+#else
2125
            ret = lxc_mainloop(&descr_console, 0);
2126
+#endif
2127
    }
2128
 
2129
 out_mainloop_console:
2130
@@ -718,6 +736,12 @@ struct lxc_handler *lxc_init_handler(struct lxc_handler *old,
2131
    }
2132
 
2133
    handler->name = name;
2134
+
2135
+#ifdef HAVE_ISULAD
2136
+   handler->exit_code = -1; /* isulad: record exit code of container */
2137
+   handler->image_type_oci = false;
2138
+#endif
2139
+
2140
    if (daemonize)
2141
        handler->transient_pid = lxc_raw_getpid();
2142
    else
2143
@@ -768,6 +792,10 @@ int lxc_init(const char *name, struct lxc_handler *handler)
2144
    int ret;
2145
    const char *loglevel;
2146
    struct lxc_conf *conf = handler->conf;
2147
+#ifdef HAVE_ISULAD
2148
+   conf->console.disable_pty = handler->disable_pty;
2149
+   conf->console.open_stdin = handler->open_stdin;
2150
+#endif
2151
 
2152
    handler->monitor_pid = lxc_raw_getpid();
2153
    status_fd = open("/proc/self/status", O_RDONLY | O_CLOEXEC);
2154
@@ -908,6 +936,186 @@ void lxc_expose_namespace_environment(const struct lxc_handler *handler)
2155
    }
2156
 }
2157
 
2158
+
2159
+#ifdef HAVE_ISULAD
2160
+/* isulad: start timeout thread */
2161
+typedef enum {
2162
+   START_INIT,
2163
+   START_TIMEOUT,
2164
+   START_MAX,
2165
+} start_timeout_t;
2166
+
2167
+static start_timeout_t global_timeout_state = START_INIT;
2168
+static sem_t global_timeout_sem;
2169
+
2170
+struct start_timeout_conf {
2171
+   unsigned int timeout;
2172
+   int errfd;
2173
+};
2174
+
2175
+void trim_line(char *s)
2176
+{
2177
+   size_t len;
2178
+
2179
+   len = strlen(s);
2180
+   while ((len > 1) && (s[len - 1] == '\n'))
2181
+       s[--len] = '\0';
2182
+}
2183
+
2184
+static int _read_procs_file(const char *path, pid_t **pids, size_t *len)
2185
+{
2186
+   FILE *f;
2187
+   char *line = NULL;
2188
+   size_t sz = 0;
2189
+   pid_t *tmp_pids = NULL;
2190
+
2191
+   f = fopen_cloexec(path, "r");
2192
+   if (!f)
2193
+       return -1;
2194
+
2195
+   while (getline(&line, &sz, f) != -1) {
2196
+       pid_t pid;
2197
+       trim_line(line);
2198
+       pid = (pid_t)atoll(line);
2199
+       if (lxc_mem_realloc((void **)&tmp_pids, sizeof(pid_t) * (*len + 1), *pids, sizeof(pid_t) * (*len)) != 0) {
2200
+           free(*pids);
2201
+           *pids = NULL;
2202
+           ERROR("out of memory");
2203
+           free(line);
2204
+           fclose(f);
2205
+           return -1;
2206
+       }
2207
+       *pids = tmp_pids;
2208
+
2209
+       (*pids)[*len] = pid;
2210
+       (*len)++;
2211
+   }
2212
+
2213
+   free(line);
2214
+   fclose(f);
2215
+   return 0;
2216
+}
2217
+
2218
+static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len)
2219
+{
2220
+   struct dirent *direntp = NULL;
2221
+   DIR *dir = NULL;
2222
+   int ret, failed = 0;
2223
+   char pathname[PATH_MAX];
2224
+
2225
+   dir = opendir(dirpath);
2226
+   if (dir == NULL) {
2227
+       WARN("Failed to open \"%s\"", dirpath);
2228
+       return 0;
2229
+   }
2230
+
2231
+   while ((direntp = readdir(dir))) {
2232
+       struct stat mystat;
2233
+       int rc;
2234
+
2235
+       if (!strcmp(direntp->d_name, ".") ||
2236
+                       !strcmp(direntp->d_name, ".."))
2237
+           continue;
2238
+
2239
+       rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name);
2240
+       if (rc < 0 || rc >= PATH_MAX) {
2241
+           failed = 1;
2242
+           continue;
2243
+       }
2244
+
2245
+       if (strcmp(direntp->d_name, "cgroup.procs") == 0) {
2246
+           if (_read_procs_file(pathname, pids, len)) {
2247
+               failed = 1;
2248
+
2249
+           }
2250
+           continue;
2251
+       }
2252
+
2253
+       ret = lstat(pathname, &mystat);
2254
+       if (ret) {
2255
+           failed = 1;
2256
+           continue;
2257
+       }
2258
+
2259
+       if (S_ISDIR(mystat.st_mode)) {
2260
+           if (_recursive_read_cgroup_procs(pathname, pids, len) < 0)
2261
+               failed = 1;
2262
+       }
2263
+   }
2264
+
2265
+   ret = closedir(dir);
2266
+   if (ret) {
2267
+       WARN("Failed to close directory \"%s\"", dirpath);
2268
+       failed = 1;
2269
+   }
2270
+
2271
+   return failed ? -1 : 0;
2272
+}
2273
+
2274
+int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len)
2275
+{
2276
+   const char *devices_path = NULL;
2277
+
2278
+   devices_path = cg_ops->get_cgroup_full_path(cg_ops, "devices");
2279
+   if (!file_exists(devices_path)) {
2280
+       return 0;
2281
+   }
2282
+
2283
+   return _recursive_read_cgroup_procs(devices_path, pids, len);
2284
+}
2285
+
2286
+static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value)
2287
+{
2288
+   char *fullpath;
2289
+   int ret;
2290
+
2291
+   fullpath = must_make_path(cg_ops->get_cgroup_full_path(cg_ops, "freezer"), "freezer.state", NULL);
2292
+   ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666);
2293
+   free(fullpath);
2294
+   return ret;
2295
+}
2296
+
2297
+/* isulad: kill all process in container cgroup path */
2298
+static void signal_all_processes(struct lxc_handler *handler)
2299
+{
2300
+   int ret;
2301
+   struct cgroup_ops *cg_ops = handler->cgroup_ops;
2302
+   pid_t *pids = NULL;
2303
+   size_t len = 0, i;
2304
+
2305
+   ret = set_cgroup_freezer(cg_ops, "FROZEN");
2306
+   if (ret < 0 && errno != ENOENT) {
2307
+       WARN("cgroup_set frozen failed");
2308
+   }
2309
+
2310
+   ret = get_all_pids(cg_ops, &pids, &len);
2311
+   if (ret < 0) {
2312
+       WARN("failed to get all pids");
2313
+   }
2314
+
2315
+   for (i = 0; i < len; i++) {
2316
+       ret = kill(pids[i], SIGKILL);
2317
+       if (ret < 0 && errno != ESRCH) {
2318
+           WARN("Can not kill process (pid=%d) with SIGKILL for container %s", pids[i], handler->name);
2319
+       }
2320
+   }
2321
+
2322
+   ret = set_cgroup_freezer(cg_ops, "THAWED");
2323
+   if (ret < 0 && errno != ENOENT) {
2324
+       WARN("cgroup_set thawed failed");
2325
+   }
2326
+
2327
+   for (i = 0; i < len; i++) {
2328
+       ret = lxc_wait_for_pid_status(pids[i]);
2329
+       if (ret < 0 && errno != ECHILD) {
2330
+           WARN("Failed to wait pid %d for container %s: %s", pids[i], handler->name, strerror(errno));
2331
+       }
2332
+   }
2333
+
2334
+   free(pids);
2335
+}
2336
+#endif
2337
+
2338
 void lxc_end(struct lxc_handler *handler)
2339
 {
2340
    int ret;
2341
@@ -945,14 +1153,44 @@ void lxc_end(struct lxc_handler *handler)
2342
 
2343
    handler->lsm_ops->cleanup(handler->lsm_ops, handler->conf, handler->lxcpath);
2344
 
2345
+
2346
+#ifdef HAVE_ISULAD
2347
+   // close maincmd fd before destroy cgroup for isulad
2348
+   if (handler->conf->reboot == REBOOT_NONE) {
2349
+       /* For all new state clients simply close the command socket.
2350
+        * This will inform all state clients that the container is
2351
+        * STOPPED and also prevents a race between a open()/close() on
2352
+        * the command socket causing a new process to get ECONNREFUSED
2353
+        * because we haven't yet closed the command socket.
2354
+        */
2355
+       close_prot_errno_disarm(handler->conf->maincmd_fd);
2356
+       TRACE("Closed command socket");
2357
+   }
2358
+   int retry_count = 0;
2359
+   int max_retry = 10;
2360
+retry:
2361
+   if (cgroup_ops != NULL && !cgroup_ops->payload_destroy(cgroup_ops, handler)) {
2362
+           TRACE("Trying to kill all subprocess");
2363
+           signal_all_processes(handler);
2364
+           TRACE("Finished kill all subprocess");
2365
+           if (retry_count < max_retry) {
2366
+               usleep(100 * 1000); /* 100 millisecond */
2367
+               retry_count++;
2368
+               goto retry;
2369
+       }
2370
+       SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name);
2371
+   }
2372
+#else
2373
    if (cgroup_ops) {
2374
        cgroup_ops->payload_destroy(cgroup_ops, handler);
2375
        cgroup_ops->monitor_destroy(cgroup_ops, handler);
2376
    }
2377
+#endif
2378
 
2379
    put_lxc_rootfs(&handler->conf->rootfs, true);
2380
 
2381
    if (handler->conf->reboot == REBOOT_NONE) {
2382
+#ifndef HAVE_ISULAD
2383
        /* For all new state clients simply close the command socket.
2384
         * This will inform all state clients that the container is
2385
         * STOPPED and also prevents a race between a open()/close() on
2386
@@ -961,12 +1199,23 @@ void lxc_end(struct lxc_handler *handler)
2387
         */
2388
        close_prot_errno_disarm(handler->conf->maincmd_fd);
2389
        TRACE("Closed command socket");
2390
+#endif
2391
 
2392
        /* This function will try to connect to the legacy lxc-monitord
2393
         * state server and only exists for backwards compatibility.
2394
         */
2395
        lxc_monitor_send_state(name, STOPPED, handler->lxcpath);
2396
 
2397
+#ifdef HAVE_ISULAD
2398
+       /* isuald: write exit code to exit fifo */
2399
+       if (handler->conf->exit_fd >= 0) {
2400
+           ret = write(handler->conf->exit_fd, &handler->exit_code, sizeof(int));
2401
+           if (ret != sizeof(int)) {
2402
+               SYSERROR("Failed to write to exit code to exit fifo.");
2403
+           }
2404
+       }
2405
+#endif
2406
+
2407
        /* The command socket is closed so no one can acces the command
2408
         * socket anymore so there's no need to lock it.
2409
         */
2410
@@ -1060,6 +1309,25 @@ static int do_start(void *data)
2411
 
2412
    lxc_sync_fini_parent(handler);
2413
 
2414
+#ifdef HAVE_ISULAD
2415
+   sigset_t mask;
2416
+
2417
+   /*isulad: restore default signal handlers and unblock all signals*/
2418
+   for (int i = 1; i < NSIG; i++)
2419
+       signal(i, SIG_DFL);
2420
+
2421
+   ret = sigfillset(&mask);
2422
+   if (ret < 0) {
2423
+       SYSERROR("Failed to fill signal mask");
2424
+       goto out_warn_father;
2425
+   }
2426
+   ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
2427
+   if (ret < 0) {
2428
+       SYSERROR("Failed to set signal mask");
2429
+       goto out_warn_father;
2430
+   }
2431
+#endif
2432
+
2433
    if (lxc_abstract_unix_recv_one_fd(data_sock1, &status_fd, NULL, 0) < 0) {
2434
        ERROR("Failed to receive status file descriptor from parent process");
2435
        goto out_warn_father;
2436
@@ -1153,7 +1421,11 @@ static int do_start(void *data)
2437
     * means that migration won't work, but at least we won't spew output
2438
     * where it isn't wanted.
2439
     */
2440
+#ifdef HAVE_ISULAD
2441
+   if (!handler->disable_pty && handler->daemonize && !handler->conf->autodev) {
2442
+#else
2443
    if (handler->daemonize && !handler->conf->autodev) {
2444
+#endif
2445
        char path[PATH_MAX];
2446
 
2447
        ret = strnprintf(path, sizeof(path), "%s/dev/null",
2448
@@ -1269,6 +1541,9 @@ static int do_start(void *data)
2449
    /* Setup the container, ip, names, utsname, ... */
2450
    ret = lxc_setup(handler);
2451
    if (ret < 0) {
2452
+#ifdef HAVE_ISULAD
2453
+       lxc_write_error_message(handler->conf->errpipe[1], "Failed to setup lxc, please check the config file.");
2454
+#endif
2455
        ERROR("Failed to setup container \"%s\"", handler->name);
2456
        goto out_warn_father;
2457
    }
2458
@@ -1291,6 +1566,43 @@ static int do_start(void *data)
2459
        DEBUG("Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges");
2460
    }
2461
 
2462
+#ifdef HAVE_ISULAD
2463
+   /* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */
2464
+   if (handler->disable_pty) {
2465
+       if (handler->conf->console.pipes[0][1] >= 0) {
2466
+           close(handler->conf->console.pipes[0][1]);
2467
+           handler->conf->console.pipes[0][1] = -1;
2468
+       }
2469
+
2470
+       if (handler->conf->console.pipes[0][0] >= 0) {
2471
+           ret = dup2(handler->conf->console.pipes[0][0], STDIN_FILENO);
2472
+           if (ret < 0)
2473
+               goto out_warn_father;
2474
+       }
2475
+
2476
+       if (handler->conf->console.pipes[1][0] >= 0) {
2477
+           close(handler->conf->console.pipes[1][0]);
2478
+           handler->conf->console.pipes[1][0] = -1;
2479
+       }
2480
+
2481
+       if (handler->conf->console.pipes[1][1] >= 0) {
2482
+           ret = dup2(handler->conf->console.pipes[1][1], STDOUT_FILENO);
2483
+           if (ret < 0)
2484
+               goto out_warn_father;
2485
+       }
2486
+       if (handler->conf->console.pipes[2][0] >= 0) {
2487
+           close(handler->conf->console.pipes[2][0]);
2488
+           handler->conf->console.pipes[2][0] = -1;
2489
+       }
2490
+
2491
+       if (handler->conf->console.pipes[2][1] >= 0) {
2492
+           ret = dup2(handler->conf->console.pipes[2][1], STDERR_FILENO);
2493
+           if (ret < 0)
2494
+               goto out_warn_father;
2495
+       }
2496
+   }
2497
+#endif
2498
+
2499
    /* If we mounted a temporary proc, then unmount it now. */
2500
    tmp_proc_unmount(handler->conf);
2501
 
2502
@@ -1307,7 +1619,11 @@ static int do_start(void *data)
2503
 
2504
    close_prot_errno_disarm(handler->sigfd);
2505
 
2506
+#ifdef HAVE_ISULAD
2507
+   if (!handler->disable_pty && handler->conf->console.pty < 0 && handler->daemonize) {
2508
+#else
2509
    if (handler->conf->console.pty < 0 && handler->daemonize) {
2510
+#endif
2511
        if (devnull_fd < 0) {
2512
            devnull_fd = open_devnull();
2513
            if (devnull_fd < 0)
2514
@@ -1326,6 +1642,16 @@ static int do_start(void *data)
2515
    setsid();
2516
 
2517
    if (handler->conf->init_cwd) {
2518
+#ifdef HAVE_ISULAD
2519
+       /* try to craete workdir if not exist */
2520
+       struct stat st;
2521
+       if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) {
2522
+           SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd);
2523
+           lxc_write_error_message(handler->conf->errpipe[1], "%s:%d: Failed to create workdir: %s.",
2524
+                                   __FILE__, __LINE__, strerror(errno));
2525
+           goto out_warn_father;
2526
+       }
2527
+#endif
2528
        ret = chdir(handler->conf->init_cwd);
2529
        if (ret < 0) {
2530
            SYSERROR("Could not change directory to \"%s\"",
2531
@@ -1372,12 +1698,26 @@ static int do_start(void *data)
2532
        }
2533
    }
2534
 
2535
+#ifdef HAVE_ISULAD
2536
+   if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
2537
+       SYSERROR("Failed to keep permitted capabilities");
2538
+       goto out_warn_father;
2539
+   }
2540
+#endif
2541
+
2542
    /* The container has been setup. We can now switch to an unprivileged
2543
     * uid/gid.
2544
     */
2545
    new_uid = handler->conf->init_uid;
2546
    new_gid = handler->conf->init_gid;
2547
 
2548
+#ifdef HAVE_ISULAD
2549
+   // isulad: set env home in container, must before "Avoid unnecessary syscalls."
2550
+   if (lxc_setup_env_home(new_uid) < 0) {
2551
+       goto out_warn_father;
2552
+   }
2553
+#endif
2554
+
2555
    /* Avoid unnecessary syscalls. */
2556
    if (new_uid == nsuid)
2557
        new_uid = LXC_INVALID_UID;
2558
@@ -1419,6 +1759,19 @@ static int do_start(void *data)
2559
        goto out_warn_father;
2560
    }
2561
 
2562
+#ifdef HAVE_ISULAD
2563
+   /* isulad: drop the cap of current process */
2564
+   if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
2565
+       SYSERROR("Failed to clear permitted capabilities");
2566
+       goto out_warn_father;
2567
+   }
2568
+
2569
+   if (lxc_drop_caps(handler->conf)) {
2570
+       SYSERROR("Failed to drop caps");
2571
+       goto out_warn_father;
2572
+   }
2573
+#endif
2574
+
2575
    if (handler->conf->monitor_signal_pdeath != SIGKILL) {
2576
        ret = lxc_set_death_signal(handler->conf->monitor_signal_pdeath,
2577
                       handler->monitor_pid, status_fd);
2578
@@ -1433,7 +1786,12 @@ static int do_start(void *data)
2579
     * After this call, we are in error because this ops should not return
2580
     * as it execs.
2581
     */
2582
+#ifdef HAVE_ISULAD
2583
+   close_prot_errno_disarm(status_fd);
2584
+   handler->ops->start(handler, handler->data, handler->daemonize ? handler->conf->errpipe[1] : -1);
2585
+#else
2586
    handler->ops->start(handler, handler->data);
2587
+#endif
2588
 
2589
 out_warn_father:
2590
    /*
2591
@@ -1604,6 +1962,94 @@ static inline void resolve_cgroup_clone_flags(struct lxc_handler *handler)
2592
    handler->ns_unshare_flags   |= CLONE_NEWCGROUP;
2593
 }
2594
 
2595
+#ifdef HAVE_ISULAD
2596
+static int lxc_write_container_info(char *filename, pid_t pid, pid_t p_pid,
2597
+       unsigned long long start_at, unsigned long long p_start_at)
2598
+{
2599
+   FILE *pid_fp = NULL;
2600
+   int ret = 0;
2601
+
2602
+   pid_fp = lxc_fopen(filename, "w");
2603
+   if (pid_fp == NULL) {
2604
+       SYSERROR("Failed to create pidfile '%s'",filename);
2605
+       ret = -1;
2606
+       goto out;
2607
+   }
2608
+
2609
+   if (fprintf(pid_fp, "%d %llu %d %llu\n", pid, start_at, p_pid, p_start_at) < 0) {
2610
+       SYSERROR("Failed to write '%s'", filename);
2611
+       ret = -1;
2612
+       goto out;
2613
+   }
2614
+out:
2615
+   if (pid_fp)
2616
+       fclose(pid_fp);
2617
+   pid_fp = NULL;
2618
+   return ret;
2619
+}
2620
+
2621
+static int lxc_check_container_info(char *filename, pid_t pid, pid_t p_pid,
2622
+       unsigned long long start_at, unsigned long long p_start_at)
2623
+{
2624
+   int ret = 0;
2625
+   int num;
2626
+   char sbuf[1024] = {0}; /* bufs for stat */
2627
+   int saved_pid;      /* process id */
2628
+   int saved_ppid;     /* pid of parent process */
2629
+   unsigned long long saved_start_time;    /* start time of process -- seconds since 1-1-70 */
2630
+   unsigned long long saved_pstart_time;   /* start time of parent process -- seconds since 1-1-70 */
2631
+
2632
+   if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) {
2633
+       SYSERROR("Failed to read pidfile %s", filename);
2634
+       ret = -1;
2635
+       goto out;
2636
+   }
2637
+
2638
+   num = sscanf(sbuf, "%d %Lu %d %Lu", &saved_pid, &saved_start_time, &saved_ppid, &saved_pstart_time);
2639
+   if (num != 4) {
2640
+       SYSERROR("Call sscanf error");
2641
+       ret = -1;
2642
+       goto out;
2643
+   }
2644
+
2645
+   if (pid != saved_pid || p_pid != saved_ppid
2646
+                   || start_at != saved_start_time || p_start_at != saved_pstart_time) {
2647
+       ERROR("Check container info failed");
2648
+       ret = -1;
2649
+       goto out;
2650
+   }
2651
+
2652
+out:
2653
+   return ret;
2654
+}
2655
+
2656
+/* isuald: save pid/ppid info */
2657
+static int lxc_save_container_info(char *filename, pid_t pid)
2658
+{
2659
+   int ret = 0;
2660
+   pid_t p_pid = 0;
2661
+   unsigned long long start_at = 0;
2662
+   unsigned long long p_start_at = 0;
2663
+
2664
+   start_at = lxc_get_process_startat(pid);
2665
+   p_pid = getpid();
2666
+   p_start_at = lxc_get_process_startat(p_pid);
2667
+
2668
+   ret = lxc_write_container_info(filename, pid, p_pid, start_at, p_start_at);
2669
+   if (ret != 0) {
2670
+       goto out;
2671
+   }
2672
+
2673
+   ret = lxc_check_container_info(filename, pid, p_pid, start_at, p_start_at);
2674
+   if (ret != 0) {
2675
+       goto out;
2676
+   }
2677
+
2678
+out:
2679
+   return ret;
2680
+}
2681
+#endif
2682
+
2683
 /* lxc_spawn() performs crucial setup tasks and clone()s the new process which
2684
  * exec()s the requested container binary.
2685
  * Note that lxc_spawn() runs in the parent namespaces. Any operations performed
2686
@@ -1741,6 +2187,32 @@ static int lxc_spawn(struct lxc_handler *handler)
2687
        handler->clone_flags &= ~CLONE_PIDFD;
2688
    TRACE("Cloned child process %d", handler->pid);
2689
 
2690
+#ifdef HAVE_ISULAD
2691
+   /* isulad: close pipe after clone */
2692
+   if (handler->conf->console.pipes[0][0] >= 0) {
2693
+       close(handler->conf->console.pipes[0][0]);
2694
+       handler->conf->console.pipes[0][0] = -1;
2695
+   }
2696
+
2697
+   if (handler->conf->console.pipes[1][1] >= 0) {
2698
+       close(handler->conf->console.pipes[1][1]);
2699
+       handler->conf->console.pipes[1][1] = -1;
2700
+   }
2701
+
2702
+   if (handler->conf->console.pipes[2][1] >= 0) {
2703
+       close(handler->conf->console.pipes[2][1]);
2704
+       handler->conf->console.pipes[2][1] = -1;
2705
+   }
2706
+
2707
+   /* isulad: save pid/ppid info into file*/
2708
+   if (handler->conf->container_info_file) {
2709
+       if (lxc_save_container_info(handler->conf->container_info_file, handler->pid)) {
2710
+           ERROR("Failed to save cloned container pid");
2711
+           goto out_delete_net;
2712
+       }
2713
+   }
2714
+#endif
2715
+
2716
    ret = core_scheduling(handler);
2717
    if (ret < 0)
2718
        goto out_delete_net;
2719
@@ -1757,6 +2229,13 @@ static int lxc_spawn(struct lxc_handler *handler)
2720
    if (ret < 0)
2721
        SYSERROR("Failed to set environment variable: LXC_PID=%s", pidstr);
2722
 
2723
+#ifdef HAVE_ISULAD
2724
+   if (handler->cgroup_ops->container_cgroup) {
2725
+       if (setenv("LXC_CGROUP_PATH", handler->cgroup_ops->container_cgroup, 1))
2726
+           SYSERROR("Failed to set environment variable: LXC_CGROUP_PATH=%s.", handler->cgroup_ops->container_cgroup);
2727
+   }
2728
+#endif
2729
+
2730
    for (i = 0; i < LXC_NS_MAX; i++)
2731
        if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
2732
            INFO("Cloned %s", ns_info[i].flag_name);
2733
@@ -1848,7 +2327,11 @@ static int lxc_spawn(struct lxc_handler *handler)
2734
        goto out_delete_net;
2735
    }
2736
 
2737
+#ifdef HAVE_ISULAD
2738
+   ret = setup_resource_limits(conf, handler->pid, conf->errpipe[1]);
2739
+#else
2740
    ret = setup_resource_limits(conf, handler->pid);
2741
+#endif
2742
    if (ret < 0) {
2743
        ERROR("Failed to setup resource limits");
2744
        goto out_delete_net;
2745
@@ -1911,6 +2394,27 @@ static int lxc_spawn(struct lxc_handler *handler)
2746
        goto out_delete_net;
2747
    }
2748
 
2749
+#ifdef HAVE_ISULAD
2750
+   /* isulad: Run oci prestart hook at here */
2751
+   ret = run_oci_hooks(name, "oci-prestart", conf, lxcpath);
2752
+   if (ret < 0) {
2753
+       ERROR("Failed to run oci prestart hooks");
2754
+       goto out_delete_net;
2755
+   }
2756
+
2757
+   if (START_TIMEOUT == global_timeout_state) {
2758
+       lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name);
2759
+       ERROR("Starting the container \"%s\" timeout.", name);
2760
+       goto out_delete_net;
2761
+   }
2762
+
2763
+       /* Tell the child to continue its initialization. We'll get
2764
+        * LXC_SYNC_POST_OCI_PRESTART_HOOK when it is ready for us to run oci prestart hooks.
2765
+        */
2766
+       if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_OCI_PRESTART_HOOK))
2767
+               goto out_delete_net;
2768
+#endif
2769
+
2770
    if (!lxc_sync_wake_child(handler, START_SYNC_FDS))
2771
        goto out_delete_net;
2772
 
2773
@@ -1969,6 +2473,22 @@ static int lxc_spawn(struct lxc_handler *handler)
2774
    if (ret < 0)
2775
        goto out_abort;
2776
 
2777
+#ifdef HAVE_ISULAD
2778
+   /* isulad: Run oci prestart hook at here */
2779
+   ret = run_oci_hooks(name, "oci-poststart", conf, lxcpath);
2780
+   if (ret < 0) {
2781
+       ERROR("Failed to run oci poststart hooks");
2782
+       goto out_abort;
2783
+   }
2784
+
2785
+   if (START_TIMEOUT == global_timeout_state) {
2786
+       lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name);
2787
+       ERROR("Starting the container \"%s\" timeout.", name);
2788
+       goto out_abort;
2789
+   }
2790
+
2791
+#endif
2792
+
2793
    ret = lxc_set_state(name, handler, RUNNING);
2794
    if (ret < 0) {
2795
        ERROR("Failed to set state to \"%s\"", lxc_state2str(RUNNING));
2796
@@ -2014,9 +2534,82 @@ static int lxc_inherit_namespaces(struct lxc_handler *handler)
2797
    return 0;
2798
 }
2799
 
2800
+#ifdef HAVE_ISULAD
2801
+/* isulad: start timeout thread function */
2802
+static void* wait_start_timeout(void *arg)
2803
+{
2804
+   struct start_timeout_conf *conf = (struct start_timeout_conf *)arg;
2805
+
2806
+   sem_post(&global_timeout_sem);
2807
+
2808
+   if (!conf || conf->timeout < 1)
2809
+       goto out;
2810
+
2811
+   sleep(conf->timeout);
2812
+
2813
+   global_timeout_state = START_TIMEOUT;
2814
+
2815
+out:
2816
+   free(conf);
2817
+   return ((void *)0);
2818
+}
2819
+
2820
+/* isulad: create start timeout thread */
2821
+static int create_start_timeout_thread(struct lxc_conf *conf, unsigned int start_timeout)
2822
+{
2823
+   int ret = 0;
2824
+   pthread_t ptid;
2825
+   pthread_attr_t attr;
2826
+   struct start_timeout_conf *timeout_conf = NULL;
2827
+
2828
+   if (sem_init(&global_timeout_sem, 0, 0)) {
2829
+       ERROR("Failed to init start timeout semaphore");/*lint !e613*/
2830
+       ret = -1;
2831
+       return ret;
2832
+   }
2833
+
2834
+   timeout_conf = malloc(sizeof(struct start_timeout_conf));
2835
+   if (timeout_conf == NULL) {
2836
+       ERROR("Failed to malloc start timeout conf");
2837
+       ret = -1;
2838
+       goto out;
2839
+   }
2840
+
2841
+   memset(timeout_conf, 0, sizeof(struct start_timeout_conf));
2842
+   timeout_conf->errfd = conf->errpipe[1];
2843
+   timeout_conf->timeout = start_timeout;
2844
+
2845
+   pthread_attr_init(&attr);
2846
+   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2847
+   ret = pthread_create(&ptid, &attr, wait_start_timeout, timeout_conf);
2848
+   pthread_attr_destroy(&attr);
2849
+   if (ret != 0) {
2850
+       ERROR("Create start wait timeout thread failed");
2851
+       free(timeout_conf);
2852
+       goto out;
2853
+   }
2854
+
2855
+   sem_wait(&global_timeout_sem);
2856
+out:
2857
+   sem_destroy(&global_timeout_sem);
2858
+   return ret;
2859
+}
2860
+
2861
+// isulad: send '128 + signal' if container is killed by signal.
2862
+#define EXIT_SIGNAL_OFFSET 128
2863
+#endif
2864
+
2865
+#ifdef HAVE_ISULAD
2866
+int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2867
+       void *data, const char *lxcpath, bool daemonize, int *error_num,
2868
+       unsigned int start_timeout)
2869
+{
2870
+   int exit_code;
2871
+#else
2872
 int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2873
        void *data, const char *lxcpath, bool daemonize, int *error_num)
2874
 {
2875
+#endif
2876
    int ret, status;
2877
    const char *name = handler->name;
2878
    struct lxc_conf *conf = handler->conf;
2879
@@ -2032,6 +2625,17 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2880
    handler->daemonize = daemonize;
2881
    cgroup_ops = handler->cgroup_ops;
2882
 
2883
+#ifdef HAVE_ISULAD
2884
+   /* isulad: add start timeout limit */
2885
+   if (start_timeout > 0) {
2886
+       ret = create_start_timeout_thread(conf, start_timeout);
2887
+       if (ret) {
2888
+           ERROR("Failed to create start timeout thread for container \"%s\".", name);
2889
+           goto out_abort;
2890
+       }
2891
+   }
2892
+#endif
2893
+
2894
    if (!attach_block_device(handler->conf)) {
2895
        ERROR("Failed to attach block device");
2896
        ret = -1;
2897
@@ -2116,11 +2720,13 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2898
        goto out_delete_network;
2899
    }
2900
 
2901
+#ifndef HAVE_ISULAD
2902
    if (!handler->init_died && handler->pid > 0) {
2903
        ERROR("Child process is not killed");
2904
        ret = -1;
2905
        goto out_delete_network;
2906
    }
2907
+#endif
2908
 
2909
    status = lxc_wait_for_pid_status(handler->pid);
2910
    if (status < 0)
2911
@@ -2130,6 +2736,20 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2912
     * reboot. This should mean it was an lxc-execute which simply exited.
2913
     * In any case, treat it as a 'halt'.
2914
     */
2915
+#ifdef HAVE_ISULAD
2916
+   // isulad: recored log for container init exit
2917
+   if (WIFSIGNALED(status)) {
2918
+       int signal_nr = WTERMSIG(status);
2919
+       exit_code = EXIT_SIGNAL_OFFSET + signal_nr;
2920
+       ERROR("Container \"%s\" init exited with signal %d", name, signal_nr);
2921
+   } else if (WIFEXITED(status)) {
2922
+       exit_code = WEXITSTATUS(status);
2923
+       ERROR("Container \"%s\" init exited with status %d", name, exit_code);
2924
+   } else {
2925
+       exit_code = -1;
2926
+       ERROR("Container \"%s\" init exited with unknown status", name);
2927
+   }
2928
+#else
2929
    if (WIFSIGNALED(status)) {
2930
        int signal_nr = WTERMSIG(status);
2931
        switch(signal_nr) {
2932
@@ -2148,16 +2768,25 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2933
            break;
2934
        }
2935
    }
2936
+#endif
2937
 
2938
    ret = lxc_restore_phys_nics_to_netns(handler);
2939
    if (ret < 0)
2940
        ERROR("Failed to move physical network devices back to parent network namespace");
2941
 
2942
+#ifdef HAVE_ISULAD
2943
+   lxc_monitor_send_exit_code(name, exit_code, handler->lxcpath);
2944
+#else
2945
    lxc_monitor_send_exit_code(name, status, handler->lxcpath);
2946
+#endif
2947
    lxc_error_set_and_log(handler->pid, status);
2948
    if (error_num)
2949
        *error_num = handler->exit_status;
2950
 
2951
+#ifdef HAVE_ISULAD
2952
+   handler->exit_code = exit_code; /* record exit code */
2953
+#endif
2954
+
2955
    lxc_delete_network(handler);
2956
    detach_block_device(handler->conf);
2957
    lxc_end(handler);
2958
@@ -2187,7 +2816,11 @@ struct start_args {
2959
    char *const *argv;
2960
 };
2961
 
2962
+#ifdef HAVE_ISULAD
2963
+static int start(struct lxc_handler *handler, void* data, int fd)
2964
+#else
2965
 static int start(struct lxc_handler *handler, void* data)
2966
+#endif
2967
 {
2968
    struct start_args *arg = data;
2969
 
2970
@@ -2195,6 +2828,9 @@ static int start(struct lxc_handler *handler, void* data)
2971
 
2972
    execvp(arg->argv[0], arg->argv);
2973
    SYSERROR("Failed to exec \"%s\"", arg->argv[0]);
2974
+#ifdef HAVE_ISULAD
2975
+   lxc_write_error_message(fd, "exec: \"%s\": %s.", arg->argv[0], strerror(errno));
2976
+#endif
2977
    return 0;
2978
 }
2979
 
2980
@@ -2212,14 +2848,22 @@ static struct lxc_operations start_ops = {
2981
 };
2982
 
2983
 int lxc_start(char *const argv[], struct lxc_handler *handler,
2984
+#ifdef HAVE_ISULAD
2985
+         const char *lxcpath, bool daemonize, int *error_num, unsigned int start_timeout)
2986
+#else
2987
          const char *lxcpath, bool daemonize, int *error_num)
2988
+#endif
2989
 {
2990
    struct start_args start_arg = {
2991
        .argv = argv,
2992
    };
2993
 
2994
    TRACE("Doing lxc_start");
2995
+#ifdef HAVE_ISULAD
2996
+   return __lxc_start(handler, &start_ops, &start_arg, lxcpath, daemonize, error_num, start_timeout);
2997
+#else
2998
    return __lxc_start(handler, &start_ops, &start_arg, lxcpath, daemonize, error_num);
2999
+#endif
3000
 }
3001
 
3002
 static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
3003
@@ -2291,3 +2935,261 @@ static bool do_destroy_container(struct lxc_handler *handler)
3004
 
3005
    return storage_destroy(handler->conf);
3006
 }
3007
+
3008
+#ifdef HAVE_ISULAD
3009
+/*isulad: set env for clean resources */
3010
+static int clean_resource_set_env(struct lxc_handler *handler)
3011
+{
3012
+   const char *name = handler->name;
3013
+   struct lxc_conf *conf = handler->conf;
3014
+   char bufstr[PATH_MAX + 1];
3015
+   int i = 0;
3016
+   int j = 0;
3017
+   int len = 2; //set "LXC_PID" and "LXC_CGNS_AWARE"
3018
+
3019
+   if (conf == NULL || conf->ocihooks == NULL || conf->ocihooks->poststop_len == 0) {
3020
+       return 0;
3021
+   }
3022
+
3023
+   if (name) {
3024
+       len++;
3025
+   }
3026
+   if (conf->rcfile) {
3027
+       len++;
3028
+   }
3029
+   if (conf->rootfs.mount) {
3030
+       len++;
3031
+   }
3032
+   if (conf->rootfs.path) {
3033
+       len++;
3034
+   }
3035
+   if (conf->console.path) {
3036
+       len++;
3037
+   }
3038
+   if (conf->console.log_path) {
3039
+       len++;
3040
+   }
3041
+   if (handler->cgroup_ops->container_cgroup) {
3042
+       len++;
3043
+   }
3044
+
3045
+   for (; i < conf->ocihooks->poststop_len; i++) {
3046
+       size_t cap = conf->ocihooks->poststop[i]->env_len;
3047
+       size_t newcap = cap + len + 1;
3048
+       if (lxc_grow_array((void ***)&(conf->ocihooks->poststop[i]->env), &cap, newcap, 1) != 0) {
3049
+           return -1;
3050
+       }
3051
+       j = conf->ocihooks->poststop[i]->env_len;
3052
+       /* Start of environment variable setup for hooks. */
3053
+       if (name) {
3054
+           snprintf(bufstr, PATH_MAX + 1, "LXC_NAME=%s", name);
3055
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3056
+       }
3057
+       if (conf->rcfile) {
3058
+           snprintf(bufstr, PATH_MAX + 1, "LXC_CONFIG_FILE=%s", conf->rcfile);
3059
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3060
+       }
3061
+       if (conf->rootfs.mount) {
3062
+           snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount);
3063
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3064
+       }
3065
+       if (conf->rootfs.path) {
3066
+           snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_PATH=%s", conf->rootfs.path);
3067
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3068
+       }
3069
+       if (conf->console.path) {
3070
+           snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE=%s", conf->console.path);
3071
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3072
+       }
3073
+       if (conf->console.log_path) {
3074
+           snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path);
3075
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3076
+       }
3077
+       conf->ocihooks->poststop[i]->env[j++] = safe_strdup("LXC_CGNS_AWARE=1");
3078
+
3079
+       snprintf(bufstr, PATH_MAX + 1, "LXC_PID=%d", handler->pid);
3080
+       conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3081
+       if (handler->cgroup_ops->container_cgroup) {
3082
+           snprintf(bufstr, PATH_MAX + 1, "LXC_CGROUP_PATH=%s", handler->cgroup_ops->container_cgroup);
3083
+           conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3084
+       }
3085
+       conf->ocihooks->poststop[i]->env_len = j;
3086
+       /* End of environment variable setup for hooks. */
3087
+   }
3088
+   return 0;
3089
+}
3090
+
3091
+/*isulad: init handler for clean */
3092
+static struct lxc_handler *lxc_init_clean_handler(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid)
3093
+{
3094
+   int i;
3095
+   struct lxc_handler *handler;
3096
+
3097
+   handler = malloc(sizeof(*handler));
3098
+   if (handler == NULL)
3099
+       return NULL;
3100
+
3101
+   memset(handler, 0, sizeof(*handler));
3102
+
3103
+   /* Note that am_guest_unpriv() checks the effective uid. We
3104
+    * probably don't care if we are real root only if we are running
3105
+    * as root so this should be fine.
3106
+    */
3107
+   handler->am_root = !am_guest_unpriv();
3108
+   handler->data_sock[0] = handler->data_sock[1] = -1;
3109
+   handler->conf = conf;
3110
+   handler->lxcpath = lxcpath;
3111
+   handler->pinfd = -1;
3112
+   handler->sigfd = -EBADF;
3113
+   handler->pidfd = -EBADF;
3114
+   handler->init_died = false;
3115
+   handler->monitor_status_fd = -EBADF;
3116
+   handler->pid = pid;
3117
+   handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
3118
+   if (handler->conf->reboot == REBOOT_NONE)
3119
+       lxc_list_init(&handler->conf->state_clients);
3120
+
3121
+   for (i = 0; i < LXC_NS_MAX; i++)
3122
+       handler->nsfd[i] = -1;
3123
+
3124
+   handler->name = name;
3125
+   handler->exit_code = -1; /* isulad: record exit code of container */
3126
+
3127
+   handler->cgroup_ops = cgroup_init(conf);
3128
+   if (!handler->cgroup_ops) {
3129
+       ERROR("Failed to initialize cgroup driver");
3130
+       goto on_error;
3131
+   }
3132
+
3133
+   INFO("Container \"%s\" 's clean handler is initialized.", name);
3134
+
3135
+   return handler;
3136
+
3137
+on_error:
3138
+   lxc_put_handler(handler);
3139
+
3140
+   return NULL;
3141
+}
3142
+
3143
+/*isulad: init handler for clean */
3144
+static struct lxc_handler *lxc_init_pids_handler(char *name, char *lxcpath, struct lxc_conf *conf)
3145
+{
3146
+   int i;
3147
+   struct lxc_handler *handler;
3148
+
3149
+   handler = malloc(sizeof(*handler));
3150
+   if (handler == NULL)
3151
+       return NULL;
3152
+
3153
+   memset(handler, 0, sizeof(*handler));
3154
+
3155
+   /* Note that am_guest_unpriv() checks the effective uid. We
3156
+    * probably don't care if we are real root only if we are running
3157
+    * as root so this should be fine.
3158
+    */
3159
+   handler->am_root = !am_guest_unpriv();
3160
+   handler->data_sock[0] = handler->data_sock[1] = -1;
3161
+   handler->conf = conf;
3162
+   handler->lxcpath = lxcpath;
3163
+   handler->pinfd = -1;
3164
+   handler->sigfd = -EBADF;
3165
+   handler->init_died = false;
3166
+   handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
3167
+   handler->monitor_status_fd = -EBADF;
3168
+   handler->pidfd = -EBADF;
3169
+   if (handler->conf->reboot == REBOOT_NONE)
3170
+       lxc_list_init(&handler->conf->state_clients);
3171
+
3172
+   for (i = 0; i < LXC_NS_MAX; i++)
3173
+       handler->nsfd[i] = -1;
3174
+
3175
+   handler->name = name;
3176
+   handler->exit_code = -1; /* isulad: record exit code of container */
3177
+
3178
+   handler->cgroup_ops = cgroup_init(conf);
3179
+   if (!handler->cgroup_ops) {
3180
+       ERROR("Failed to initialize cgroup driver");
3181
+       goto on_error;
3182
+   }
3183
+
3184
+   INFO("Container \"%s\" 's clean handler is initialized.", name);
3185
+
3186
+   return handler;
3187
+
3188
+on_error:
3189
+   lxc_put_handler(handler);
3190
+
3191
+   return NULL;
3192
+}
3193
+
3194
+/*isulad: do_lxcapi_clean_resource */
3195
+int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid)
3196
+{
3197
+   int ret = 0;
3198
+   struct lxc_handler *handler = NULL;
3199
+   int retry_count = 0;
3200
+   int max_retry = 10;
3201
+
3202
+   handler = lxc_init_clean_handler(name, lxcpath, conf, pid);
3203
+   if (!handler) {
3204
+       ERROR("Failed to init container %s clean handler", name);
3205
+       ret = -1;
3206
+       goto out;
3207
+   }
3208
+
3209
+   if (clean_resource_set_env(handler) != 0) {
3210
+       ERROR("Failed to set env for poststop hooks");
3211
+       ret = -1;
3212
+       goto out;
3213
+   }
3214
+
3215
+   if (run_oci_hooks(handler->name, "oci-poststop", handler->conf, handler->lxcpath)) {
3216
+       ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", handler->name);
3217
+       ret = -1;
3218
+   }
3219
+
3220
+retry:
3221
+   if (!handler->cgroup_ops->payload_destroy(handler->cgroup_ops, handler)) {
3222
+       TRACE("Trying to kill all subprocess");
3223
+       signal_all_processes(handler);
3224
+       TRACE("Finished kill all subprocess");
3225
+       if (retry_count < max_retry) {
3226
+           usleep(100 * 1000); /* 100 millisecond */
3227
+           retry_count++;
3228
+           goto retry;
3229
+       }
3230
+       SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name);
3231
+       ret = -1;
3232
+   }
3233
+
3234
+out:
3235
+   lxc_put_handler(handler);
3236
+   return ret;
3237
+}
3238
+
3239
+/*isulad: do_lxcapi_get_pids */
3240
+int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len)
3241
+{
3242
+   int ret = 0;
3243
+   struct lxc_handler *handler = NULL;
3244
+   struct cgroup_ops *cg_ops = NULL;
3245
+
3246
+   handler = lxc_init_pids_handler(name, lxcpath, conf);
3247
+   if (!handler) {
3248
+       ERROR("Failed to init container %s clean handler", name);
3249
+       ret = -1;
3250
+       goto out;
3251
+   }
3252
+
3253
+   cg_ops = handler->cgroup_ops;
3254
+   ret = get_all_pids(cg_ops, pids, pids_len);
3255
+   if (ret < 0) {
3256
+       WARN("failed to get all pids");
3257
+   }
3258
+
3259
+out:
3260
+   lxc_put_handler(handler);
3261
+   return ret;
3262
+}
3263
+
3264
+#endif
3265
diff --git a/src/lxc/start.h b/src/lxc/start.h
3266
index bbd1a83..d03e5d5 100644
3267
--- a/src/lxc/start.h
3268
+++ b/src/lxc/start.h
3269
@@ -153,7 +153,11 @@ struct execute_args {
3270
 };
3271
 
3272
 struct lxc_operations {
3273
+#ifdef HAVE_ISULAD
3274
+   int (*start)(struct lxc_handler *, void *, int);
3275
+#else
3276
    int (*start)(struct lxc_handler *, void *);
3277
+#endif
3278
    int (*post_start)(struct lxc_handler *, void *);
3279
 };
3280
 
3281
@@ -184,12 +188,26 @@ static inline int inherit_fds(struct lxc_handler *handler, bool closeall)
3282
                   ARRAY_SIZE(handler->keep_fds));
3283
 }
3284
 
3285
+#ifdef HAVE_ISULAD
3286
+__hidden extern int __lxc_start(struct lxc_handler *handler,
3287
+       struct lxc_operations* ops, void *data, const char *lxcpath,
3288
+       bool daemonize, int *error_num, unsigned int start_timeout);
3289
+#else
3290
 __hidden extern int __lxc_start(struct lxc_handler *, struct lxc_operations *, void *, const char *,
3291
                bool, int *);
3292
+#endif
3293
 
3294
 __hidden extern int resolve_clone_flags(struct lxc_handler *handler);
3295
 __hidden extern void lxc_expose_namespace_environment(const struct lxc_handler *handler);
3296
 
3297
+#ifdef HAVE_ISULAD
3298
+/*isulad: do_lxcapi_clean_resource */
3299
+extern int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid);
3300
+
3301
+/*isulad: do_lxcapi_get_pids */
3302
+extern int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len);
3303
+#endif
3304
+
3305
 static inline bool container_uses_namespace(const struct lxc_handler *handler,
3306
                        unsigned int ns_flag)
3307
 {
3308
-- 
3309
2.25.1
3310
3311