• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

drakenclimber / libcgroup / 14407600166

10 Apr 2025 09:38AM UTC coverage: 56.088% (-3.6%) from 59.654%
14407600166

push

github

kamalesh-babulal
github: dist: Rework the unit tests

Add a configure option to enable/disable the unit tests. Because of their
dependency upon googletest, they're very difficult to run for distros.
This allows them to packaged with libcgroup, but they are disabled by
default.  They can be enabled via the config option `--enable-unittests`.

Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>

5574 of 9938 relevant lines covered (56.09%)

546.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.69
/src/wrapper.c
1
// SPDX-License-Identifier: LGPL-2.1-only
2
/**
3
 * Copyright IBM Corporation. 2008
4
 *
5
 * Author:        Dhaval Giani <dhaval@linux.vnet.ibm.com>
6
 *
7
 * Code initiated and designed by Dhaval Giani. All faults are most likely
8
 * his mistake.
9
 */
10

11
#define _GNU_SOURCE
12

13
#include <libcgroup.h>
14
#include <libcgroup-internal.h>
15

16
#include <inttypes.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <unistd.h>
20
#include <stdio.h>
21
#include <errno.h>
22

23
static void init_cgroup(struct cgroup *cgroup)
5,740✔
24
{
25
        cgroup->task_fperm = NO_PERMS;
5,740✔
26
        cgroup->control_fperm = NO_PERMS;
5,740✔
27
        cgroup->control_dperm = NO_PERMS;
5,740✔
28

29
        cgroup->control_gid = NO_UID_GID;
5,740✔
30
        cgroup->control_uid = NO_UID_GID;
5,740✔
31
        cgroup->tasks_gid = NO_UID_GID;
5,740✔
32
        cgroup->tasks_uid = NO_UID_GID;
5,740✔
33
}
5,740✔
34

35
void init_cgroup_table(struct cgroup *cgroups, size_t count)
99✔
36
{
37
        size_t i;
38

39
        for (i = 0; i < count; ++i)
4,356✔
40
                init_cgroup(&cgroups[i]);
4,257✔
41
}
99✔
42

43
struct cgroup *cgroup_new_cgroup(const char *name)
1,484✔
44
{
45
        struct cgroup *cgroup;
46

47
        if (!name)
1,484✔
48
                return NULL;
1✔
49

50
        cgroup = calloc(1, sizeof(struct cgroup));
1,483✔
51
        if (!cgroup)
1,483✔
52
                return NULL;
×
53

54
        init_cgroup(cgroup);
1,483✔
55
        strncpy(cgroup->name, name, FILENAME_MAX - 1);
1,483✔
56
        cgroup->name[FILENAME_MAX - 1] = '\0';
1,483✔
57

58
        return cgroup;
1,483✔
59
}
60

61
struct cgroup_controller *cgroup_add_controller(struct cgroup *cgroup, const char *name)
1,565✔
62
{
63
        struct cgroup_controller *controller;
64
        int i, ret;
65

66
        if (!cgroup || !name)
1,565✔
67
                return NULL;
3✔
68

69
        /* Still not sure how to handle the failure here. */
70
        if (cgroup->index >= CG_CONTROLLER_MAX)
1,562✔
71
                return NULL;
×
72

73
        /* Still not sure how to handle the failure here. */
74
        for (i = 0; i < cgroup->index; i++) {
2,562✔
75
                if (strncmp(name, cgroup->controller[i]->name, CONTROL_NAMELEN_MAX) == 0)
1,000✔
76
                        return NULL;
×
77
        }
78

79
        controller = calloc(1, sizeof(struct cgroup_controller));
1,562✔
80
        if (!controller)
1,562✔
81
                return NULL;
×
82

83
        strncpy(controller->name, name, CONTROL_NAMELEN_MAX - 1);
1,562✔
84
        controller->name[CONTROL_NAMELEN_MAX - 1] = '\0';
1,562✔
85

86
        controller->cgroup = cgroup;
1,562✔
87
        controller->index = 0;
1,562✔
88

89
        if (strcmp(controller->name, CGRP_FILE_PREFIX) == 0) {
1,562✔
90
                /*
91
                 * Operating on the "cgroup" controller is only allowed
92
                 * on cgroup v2 systems
93
                 */
94
                controller->version = CGROUP_V2;
82✔
95
        } else {
96
                ret = cgroup_get_controller_version(controller->name, &controller->version);
1,480✔
97
                if (ret) {
1,480✔
98
                        cgroup_dbg("failed to get cgroup version for controller %s\n",
2✔
99
                                   controller->name);
100
                        free(controller);
2✔
101
                        return NULL;
2✔
102
                }
103
        }
104

105
        cgroup->controller[cgroup->index] = controller;
1,560✔
106
        cgroup->index++;
1,560✔
107

108
        return controller;
1,560✔
109
}
110

111
int cgroup_add_all_controllers(struct cgroup *cgroup)
13✔
112
{
113
        struct cgroup_controller *cgc;
114
        struct controller_data info;
115
        enum cg_setup_mode_t mode;
116
        void *handle;
117
        int ret = 0;
13✔
118

119
        if (!cgroup)
13✔
120
                return ECGINVAL;
×
121

122
        mode = cgroup_setup_mode();
13✔
123

124
        /*
125
         * Per kernel documentation, cgroup-v2.rst, /proc/cgroups is "meaningless" for cgroup v2.
126
         * Use the cgroup's cgroup.controllers file instead
127
         */
128
        if (mode == CGROUP_MODE_UNIFIED) {
13✔
129
                char *ret_c, *controller, *stok_buff = NULL, line[CGV2_CONTROLLERS_LL_MAX];
13✔
130
                /*
131
                 * cg_cgroup_v2_mount_path (FILENAME_MAX) + cgroup->name (FILENAME_MAX) +
132
                 * strlen("cgroup.controllers") (18) + 2 forward slashes + 1 NULL terminator
133
                 */
134
                char cgroup_controllers_path[FILENAME_MAX * 2 + 18 + 2 + 1];
135
                FILE *fp;
136

137
                pthread_rwlock_rdlock(&cg_mount_table_lock);
13✔
138
                if (strlen(cg_cgroup_v2_mount_path) == 0) {
13✔
139
                        pthread_rwlock_unlock(&cg_mount_table_lock);
×
140
                        ret = ECGOTHER;
×
141
                        goto out;
×
142
                }
143

144
                snprintf(cgroup_controllers_path, sizeof(cgroup_controllers_path), "%s/%s/%s",
13✔
145
                         cg_cgroup_v2_mount_path, cgroup->name, CGV2_CONTROLLERS_FILE);
13✔
146
                pthread_rwlock_unlock(&cg_mount_table_lock);
13✔
147

148
                fp = fopen(cgroup_controllers_path, "re");
13✔
149
                if (!fp) {
13✔
150
                        ret = ECGOTHER;
×
151
                        goto out;
×
152
                }
153

154
                ret_c = fgets(line, CGV2_CONTROLLERS_LL_MAX, fp);
13✔
155
                fclose(fp);
13✔
156
                if (ret_c == NULL) {
13✔
157
                        /* no controllers are enabled */
158
                        goto out;
×
159
                }
160

161
                /* Remove the trailing newline */
162
                ret_c[strlen(ret_c) - 1] = '\0';
13✔
163

164
                /*
165
                 * cgroup.controllers returns a list of available controllers in
166
                 * the following format:
167
                 *        cpuset cpu io memory pids rdma
168
                 */
169
                controller = strtok_r(ret_c, " ", &stok_buff);
13✔
170
                do {
171
                        cgc = cgroup_add_controller(cgroup, controller);
51✔
172
                        if (!cgc) {
51✔
173
                                ret = ECGINVAL;
×
174
                                fprintf(stderr, "controller %s can't be added\n", controller);
×
175
                                goto end;
×
176
                        }
177
                } while ((controller = strtok_r(NULL, " ", &stok_buff)));
51✔
178
        } else {
179
                /* go through the controller list */
180
                ret = cgroup_get_all_controller_begin(&handle, &info);
×
181
                if ((ret != 0) && (ret != ECGEOF)) {
×
182
                        fprintf(stderr, "cannot read controller data: %s\n", cgroup_strerror(ret));
×
183
                        return ret;
×
184
                }
185

186
                while (ret == 0) {
×
187
                        if (info.hierarchy == 0) {
×
188
                                /*
189
                                 * the controller is not attached to any
190
                                 * hierarchy skip it.
191
                                 */
192
                                goto next;
×
193
                        }
194

195
                        /* add mounted controller to cgroup structure */
196
                        cgc = cgroup_add_controller(cgroup, info.name);
×
197
                        if (!cgc) {
×
198
                                ret = ECGINVAL;
×
199
                                fprintf(stderr, "controller %s can't be added\n", info.name);
×
200
                                goto end;
×
201
                        }
202

203
next:
×
204
                        ret = cgroup_get_all_controller_next(&handle, &info);
×
205
                        if (ret && ret != ECGEOF)
×
206
                                goto end;
×
207
                }
208

209
end:
×
210
                cgroup_get_all_controller_end(&handle);
×
211
                if (ret == ECGEOF)
×
212
                        ret = 0;
×
213
                if (ret)
×
214
                        fprintf(stderr,        "cgroup_get_controller_begin/next failed (%s)\n",
×
215
                                cgroup_strerror(ret));
216
        }
217

218
out:
×
219
        return ret;
13✔
220
}
221

222
static void cgroup_free_value(struct control_value *value)
4,434✔
223
{
224
        if (value->multiline_value)
4,434✔
225
                free(value->multiline_value);
54✔
226
        if (value->prev_name)
4,434✔
227
                free(value->prev_name);
58✔
228

229
        free(value);
4,434✔
230
}
4,434✔
231

232
void cgroup_free_controller(struct cgroup_controller *ctrl)
1,791✔
233
{
234
        int i;
235

236
        for (i = 0; i < ctrl->index; i++)
6,217✔
237
                cgroup_free_value(ctrl->values[i]);
4,426✔
238
        ctrl->index = 0;
1,791✔
239

240
        free(ctrl);
1,791✔
241
}
1,791✔
242

243
void cgroup_free_controllers(struct cgroup *cgroup)
1,802✔
244
{
245
        int i;
246

247
        if (!cgroup)
1,802✔
248
                return;
×
249

250
        for (i = 0; i < cgroup->index; i++)
3,587✔
251
                cgroup_free_controller(cgroup->controller[i]);
1,785✔
252

253
        cgroup->index = 0;
1,802✔
254
}
255

256
void cgroup_free(struct cgroup **cgroup)
1,690✔
257
{
258
        struct cgroup *cg = *cgroup;
1,690✔
259

260
        /* Passing NULL pointers is OK. We just return. */
261
        if (!cg)
1,690✔
262
                return;
227✔
263

264
        cgroup_free_controllers(cg);
1,463✔
265
        free(cg);
1,463✔
266
        *cgroup = NULL;
1,463✔
267
}
268

269
int cgroup_add_value_string(struct cgroup_controller *controller, const char *name,
4,061✔
270
                            const char *value)
271
{
272
        int i;
273
        struct control_value *cntl_value;
274

275
        if (!controller || !name)
4,061✔
276
                return ECGINVAL;
3✔
277

278
        if (controller->index >= CG_NV_MAX)
4,058✔
279
                return ECGMAXVALUESEXCEEDED;
×
280

281
        for (i = 0; i < controller->index && i < CG_NV_MAX; i++) {
25,492✔
282
                if (!strcmp(controller->values[i]->name, name))
21,434✔
283
                        return ECGVALUEEXISTS;
×
284
        }
285

286
        cntl_value = calloc(1, sizeof(struct control_value));
4,058✔
287
        if (!cntl_value)
4,058✔
288
                return ECGCONTROLLERCREATEFAILED;
×
289

290
        strncpy(cntl_value->name, name, sizeof(cntl_value->name));
4,058✔
291
        cntl_value->name[sizeof(cntl_value->name)-1] = '\0';
4,058✔
292

293
        if (value) {
4,058✔
294
                if (strlen(value) >= sizeof(cntl_value->value)) {
3,881✔
295
                        fprintf(stderr, "value exceeds the maximum of %ld characters\n",
×
296
                                sizeof(cntl_value->value) - 1);
297
                        free(cntl_value);
×
298
                        return ECGCONFIGPARSEFAIL;
×
299
                }
300

301
                strncpy(cntl_value->value, value, sizeof(cntl_value->value));
3,881✔
302
                cntl_value->value[sizeof(cntl_value->value)-1] = '\0';
3,881✔
303
                cntl_value->dirty = true;
3,881✔
304
        }
305

306
        controller->values[controller->index] = cntl_value;
4,058✔
307
        controller->index++;
4,058✔
308

309
        return 0;
4,058✔
310
}
311

312
int cgroup_add_value_int64(struct cgroup_controller *controller, const char *name, int64_t value)
2✔
313
{
314
        char *val;
315
        int ret;
316

317
        ret = asprintf(&val, "%"PRId64, value);
2✔
318
        if (ret < 0) {
2✔
319
                last_errno = errno;
×
320
                return ECGOTHER;
×
321
        }
322

323
        ret = cgroup_add_value_string(controller, name, val);
2✔
324
        free(val);
2✔
325

326
        return ret;
2✔
327
}
328

329
int cgroup_add_value_uint64(struct cgroup_controller *controller, const char *name,
2✔
330
                            u_int64_t value)
331
{
332
        char *val;
333
        int ret;
334

335
        ret = asprintf(&val, "%" PRIu64, value);
2✔
336
        if (ret < 0) {
2✔
337
                last_errno = errno;
×
338
                return ECGOTHER;
×
339
        }
340

341
        ret = cgroup_add_value_string(controller, name, val);
2✔
342
        free(val);
2✔
343

344
        return ret;
2✔
345
}
346

347
int cgroup_add_value_bool(struct cgroup_controller *controller, const char *name, bool value)
2✔
348
{
349
        char *val;
350
        int ret;
351

352
        if (value)
2✔
353
                val = strdup("1");
×
354
        else
355
                val = strdup("0");
2✔
356
        if (!val) {
2✔
357
                last_errno = errno;
×
358
                return ECGOTHER;
×
359
        }
360

361
        ret = cgroup_add_value_string(controller, name, val);
2✔
362
        free(val);
2✔
363

364
        return ret;
2✔
365
}
366

367
int cgroup_remove_value(struct cgroup_controller * const controller, const char * const name)
8✔
368
{
369
        int i;
370

371
        for (i = 0; i < controller->index; i++) {
12✔
372
                if (strcmp(controller->values[i]->name, name) == 0) {
12✔
373
                        cgroup_free_value(controller->values[i]);
8✔
374

375
                        if (i == (controller->index - 1)) {
8✔
376
                                /* This is the last entry in the table. There's nothing to move */
377
                                controller->index--;
×
378
                        } else {
379
                                memmove(&controller->values[i],        &controller->values[i + 1],
8✔
380
                                sizeof(struct control_value *) * (controller->index - i - 1));
8✔
381
                                controller->index--;
8✔
382
                        }
383
                        return 0;
8✔
384
                }
385
        }
386

387
        return ECGROUPNOTEXIST;
×
388
}
389

390
int cgroup_compare_controllers(struct cgroup_controller *cgca, struct cgroup_controller *cgcb)
60✔
391
{
392
        int i;
393

394
        if (!cgca || !cgcb)
60✔
395
                return ECGINVAL;
×
396

397
        if (strcmp(cgca->name, cgcb->name))
60✔
398
                return ECGCONTROLLERNOTEQUAL;
36✔
399

400
        if (cgca->index != cgcb->index)
24✔
401
                return ECGCONTROLLERNOTEQUAL;
×
402

403
        for (i = 0; i < cgca->index; i++) {
102✔
404
                struct control_value *cva = cgca->values[i];
78✔
405
                struct control_value *cvb = cgcb->values[i];
78✔
406

407
                if (strcmp(cva->name, cvb->name))
78✔
408
                        return ECGCONTROLLERNOTEQUAL;
×
409

410
                if (strcmp(cva->value, cvb->value))
78✔
411
                        return ECGCONTROLLERNOTEQUAL;
×
412
        }
413

414
        return 0;
24✔
415
}
416

417
int cgroup_compare_cgroup(struct cgroup *cgroup_a, struct cgroup *cgroup_b)
16✔
418
{
419
        int i, j;
420

421
        if (!cgroup_a || !cgroup_b)
16✔
422
                return ECGINVAL;
×
423

424
        if (strcmp(cgroup_a->name, cgroup_b->name))
16✔
425
                return ECGROUPNOTEQUAL;
×
426

427
        if (cgroup_a->tasks_uid != cgroup_b->tasks_uid)
16✔
428
                return ECGROUPNOTEQUAL;
2✔
429

430
        if (cgroup_a->tasks_gid != cgroup_b->tasks_gid)
14✔
431
                return ECGROUPNOTEQUAL;
2✔
432

433
        if (cgroup_a->control_uid != cgroup_b->control_uid)
12✔
434
                return ECGROUPNOTEQUAL;
2✔
435

436
        if (cgroup_a->control_gid != cgroup_b->control_gid)
10✔
437
                return ECGROUPNOTEQUAL;
2✔
438

439
        if (cgroup_a->index != cgroup_b->index)
8✔
440
                return ECGROUPNOTEQUAL;
×
441

442
        for (i = 0; i < cgroup_a->index; i++) {
32✔
443
                struct cgroup_controller *cgca = cgroup_a->controller[i];
24✔
444
                bool found_match = false;
24✔
445

446
                /*
447
                 * Don't penalize the user if the controllers are in different order
448
                 * from cgroup_a to cgroup_b
449
                 */
450
                for (j = 0; j < cgroup_b->index; j++) {
60✔
451
                        struct cgroup_controller *cgcb = cgroup_b->controller[j];
60✔
452

453
                        if (cgroup_compare_controllers(cgca, cgcb) == 0) {
60✔
454
                                found_match = true;
24✔
455
                                break;
24✔
456
                        }
457
                }
458

459
                if (!found_match)
24✔
460
                        return ECGCONTROLLERNOTEQUAL;
×
461
        }
462

463
        return 0;
8✔
464
}
465

466
int cgroup_set_uid_gid(struct cgroup *cgroup, uid_t tasks_uid, gid_t tasks_gid, uid_t control_uid,
232✔
467
                       gid_t control_gid)
468
{
469
        if (!cgroup)
232✔
470
                return ECGINVAL;
×
471

472
        cgroup->tasks_uid = tasks_uid;
232✔
473
        cgroup->tasks_gid = tasks_gid;
232✔
474
        cgroup->control_uid = control_uid;
232✔
475
        cgroup->control_gid = control_gid;
232✔
476

477
        return 0;
232✔
478
}
479

480
int cgroup_get_uid_gid(struct cgroup *cgroup, uid_t *tasks_uid, gid_t *tasks_gid,
6✔
481
                       uid_t *control_uid, gid_t *control_gid)
482
{
483
        if (!cgroup || !tasks_uid || !tasks_gid || !control_uid || !control_gid)
6✔
484
                return ECGINVAL;
5✔
485

486
        *tasks_uid = cgroup->tasks_uid;
1✔
487
        *tasks_gid = cgroup->tasks_gid;
1✔
488
        *control_uid = cgroup->control_uid;
1✔
489
        *control_gid = cgroup->control_gid;
1✔
490

491
        return 0;
1✔
492
}
493

494
struct cgroup_controller *cgroup_get_controller(struct cgroup *cgroup, const char *name)
538✔
495
{
496
        int i;
497
        struct cgroup_controller *cgc;
498

499
        if (!cgroup)
538✔
500
                return NULL;
×
501

502
        for (i = 0; i < cgroup->index; i++) {
784✔
503
                cgc = cgroup->controller[i];
422✔
504

505
                if (!strcmp(cgc->name, name))
422✔
506
                        return cgc;
176✔
507
        }
508

509
        return NULL;
362✔
510
}
511

512
int cgroup_get_value_string(struct cgroup_controller *controller, const char *name, char **value)
553✔
513
{
514
        int i;
515

516
        if (!controller || !name || !value)
553✔
517
                return ECGINVAL;
4✔
518

519
        for (i = 0; i < controller->index; i++) {
3,372✔
520
                struct control_value *val = controller->values[i];
3,372✔
521

522
                if (!strcmp(val->name, name)) {
3,372✔
523
                        *value = strdup(val->value);
549✔
524

525
                        if (!*value)
549✔
526
                                return ECGOTHER;
×
527

528
                        return 0;
549✔
529
                }
530
        }
531

532
        return ECGROUPVALUENOTEXIST;
×
533

534
}
535

536
int cgroup_set_value_string(struct cgroup_controller *controller, const char *name,
16✔
537
                            const char *value)
538
{
539
        int i;
540

541
        if (!controller || !name || !value)
16✔
542
                return ECGINVAL;
4✔
543

544
        for (i = 0; i < controller->index; i++) {
12✔
545
                struct control_value *val = controller->values[i];
12✔
546

547
                if (!strcmp(val->name, name)) {
12✔
548
                        strncpy(val->value, value, CG_CONTROL_VALUE_MAX);
12✔
549
                        val->value[sizeof(val->value)-1] = '\0';
12✔
550
                        val->dirty = true;
12✔
551
                        return 0;
12✔
552
                }
553
        }
554

555
        return cgroup_add_value_string(controller, name, value);
×
556
}
557

558
int cgroup_get_value_int64(struct cgroup_controller *controller, const char *name, int64_t *value)
5✔
559
{
560
        int i;
561

562
        if (!controller || !name || !value)
5✔
563
                return ECGINVAL;
4✔
564

565
        for (i = 0; i < controller->index; i++) {
1✔
566
                struct control_value *val = controller->values[i];
1✔
567

568
                if (!strcmp(val->name, name)) {
1✔
569
                        if (sscanf(val->value, "%" SCNd64, value) != 1)
1✔
570
                                return ECGINVAL;
×
571

572
                        return 0;
1✔
573
                }
574
        }
575

576
        return ECGROUPVALUENOTEXIST;
×
577
}
578

579
int cgroup_set_value_int64(struct cgroup_controller *controller, const char *name, int64_t value)
5✔
580
{
581
        int ret;
582
        int i;
583

584
        if (!controller || !name)
5✔
585
                return ECGINVAL;
2✔
586

587
        for (i = 0; i < controller->index; i++) {
3✔
588
                struct control_value *val = controller->values[i];
1✔
589

590
                if (!strcmp(val->name, name)) {
1✔
591
                        ret = snprintf(val->value, sizeof(val->value), "%" PRId64, value);
1✔
592
                        if (ret >= sizeof(val->value))
1✔
593
                                return ECGINVAL;
×
594

595
                        val->dirty = true;
1✔
596
                        return 0;
1✔
597
                }
598
        }
599

600
        return cgroup_add_value_int64(controller, name, value);
2✔
601
}
602

603
int cgroup_get_value_uint64(struct cgroup_controller *controller, const char *name,
5✔
604
                            u_int64_t *value)
605
{
606
        int i;
607

608
        if (!controller || !name || !value)
5✔
609
                return ECGINVAL;
4✔
610

611
        for (i = 0; i < controller->index; i++) {
1✔
612
                struct control_value *val = controller->values[i];
1✔
613

614
                if (!strcmp(val->name, name)) {
1✔
615
                        if (sscanf(val->value, "%" SCNu64, value) != 1)
1✔
616
                                return ECGINVAL;
×
617

618
                        return 0;
1✔
619
                }
620
        }
621

622
        return ECGROUPVALUENOTEXIST;
×
623
}
624

625
int cgroup_set_value_uint64(struct cgroup_controller *controller, const char *name,
5✔
626
                            u_int64_t value)
627
{
628
        int ret;
629
        int i;
630

631
        if (!controller || !name)
5✔
632
                return ECGINVAL;
2✔
633

634
        for (i = 0; i < controller->index; i++) {
3✔
635
                struct control_value *val = controller->values[i];
1✔
636

637
                if (!strcmp(val->name, name)) {
1✔
638
                        ret = snprintf(val->value, sizeof(val->value), "%" PRIu64, value);
1✔
639
                        if (ret >= sizeof(val->value))
1✔
640
                                return ECGINVAL;
×
641

642
                        val->dirty = true;
1✔
643
                        return 0;
1✔
644
                }
645
        }
646

647
        return cgroup_add_value_uint64(controller, name, value);
2✔
648
}
649

650
int cgroup_get_value_bool(struct cgroup_controller *controller, const char *name, bool *value)
5✔
651
{
652
        int i;
653

654
        if (!controller || !name || !value)
5✔
655
                return ECGINVAL;
4✔
656

657
        for (i = 0; i < controller->index; i++) {
1✔
658
                struct control_value *val = controller->values[i];
1✔
659

660
                if (!strcmp(val->name, name)) {
1✔
661
                        int cgc_val;
662

663
                        if (sscanf(val->value, "%d", &cgc_val) != 1)
1✔
664
                                return ECGINVAL;
×
665

666
                        if (cgc_val)
1✔
667
                                *value = true;
1✔
668
                        else
669
                                *value = false;
×
670

671
                        return 0;
1✔
672
                }
673
        }
674

675
        return ECGROUPVALUENOTEXIST;
×
676
}
677

678
int cgroup_set_value_bool(struct cgroup_controller *controller, const char *name, bool value)
5✔
679
{
680
        int ret;
681
        int i;
682

683
        if (!controller || !name)
5✔
684
                return ECGINVAL;
2✔
685

686
        for (i = 0; i < controller->index; i++) {
3✔
687
                struct control_value *val = controller->values[i];
1✔
688

689
                if (!strcmp(val->name, name)) {
1✔
690
                        if (value)
1✔
691
                                ret = snprintf(val->value, sizeof(val->value), "1");
1✔
692
                        else
693
                                ret = snprintf(val->value, sizeof(val->value), "0");
×
694

695
                        if (ret >= sizeof(val->value))
1✔
696
                                return ECGINVAL;
×
697

698
                        val->dirty = true;
1✔
699
                        return 0;
1✔
700

701
                }
702
        }
703

704
        return cgroup_add_value_bool(controller, name, value);
2✔
705
}
706

707
struct cgroup *create_cgroup_from_name_value_pairs(const char *name,
221✔
708
                                                   struct control_value *name_value, int nv_number)
709
{
710
        struct cgroup_controller *cgc;
711
        struct cgroup *src_cgroup;
712
        char con[FILENAME_MAX];
713

714
        int ret;
715
        int i;
716

717
        /* create source cgroup */
718
        src_cgroup = cgroup_new_cgroup(name);
221✔
719
        if (!src_cgroup) {
221✔
720
                fprintf(stderr, "can't create cgroup: %s\n", cgroup_strerror(ECGFAIL));
×
721
                goto scgroup_err;
×
722
        }
723

724
        /* Add pairs name-value to relevant controllers of this cgroup. */
725
        for (i = 0; i < nv_number; i++) {
417✔
726

727
                if ((strchr(name_value[i].name, '.')) == NULL) {
196✔
728
                        fprintf(stderr, "wrong -r  parameter (%s=%s)\n", name_value[i].name,
×
729
                                name_value[i].value);
×
730
                        goto scgroup_err;
×
731
                }
732

733
                strncpy(con, name_value[i].name, FILENAME_MAX - 1);
196✔
734
                con[FILENAME_MAX - 1] = '\0';
196✔
735

736
                strtok(con, ".");
196✔
737

738
                /*
739
                 * find out whether we have to add the controller or
740
                 * cgroup already contains it.
741
                 */
742
                cgc = cgroup_get_controller(src_cgroup, con);
196✔
743
                if (!cgc) {
196✔
744
                        /* add relevant controller */
745
                        cgc = cgroup_add_controller(src_cgroup, con);
196✔
746
                        if (!cgc) {
196✔
747
                                fprintf(stderr, "controller %s can't be add\n",        con);
×
748
                                goto scgroup_err;
×
749
                        }
750
                }
751

752
                /* add name-value pair to this controller */
753
                ret = cgroup_add_value_string(cgc, name_value[i].name, name_value[i].value);
196✔
754
                if (ret) {
196✔
755
                        fprintf(stderr, "name-value pair %s=%s can't be set\n",        name_value[i].name,
×
756
                                name_value[i].value);
×
757
                        goto scgroup_err;
×
758
                }
759
        }
760

761
        return src_cgroup;
221✔
762

763
scgroup_err:
×
764
        cgroup_free(&src_cgroup);
×
765

766
        return NULL;
×
767
}
768

769
int cgroup_get_value_name_count(struct cgroup_controller *controller)
146✔
770
{
771
        if (!controller)
146✔
772
                return -1;
×
773

774
        return controller->index;
146✔
775
}
776

777

778
char *cgroup_get_value_name(struct cgroup_controller *controller, int index)
720✔
779
{
780

781
        if (!controller)
720✔
782
                return NULL;
×
783

784
        if (index < controller->index)
720✔
785
                return (controller->values[index])->name;
720✔
786
        else
787
                return NULL;
×
788
}
789

790
char *cgroup_get_cgroup_name(struct cgroup *cgroup)
×
791
{
792
        if (!cgroup)
×
793
                return NULL;
×
794

795
        return cgroup->name;
×
796
}
797

798

799
/*
800
 * Return true if cgroup setup mode is cgroup v1 (legacy), else
801
 * returns false.
802
 */
803
bool is_cgroup_mode_legacy(void)
2✔
804
{
805
        enum cg_setup_mode_t setup_mode;
806

807
        setup_mode = cgroup_setup_mode();
2✔
808
        return (setup_mode == CGROUP_MODE_LEGACY);
2✔
809
}
810

811
/*
812
 * Return true if cgroup setup mode is cgroup v1/v2 (hybrid), else
813
 * returns false.
814
 */
815
bool is_cgroup_mode_hybrid(void)
2✔
816
{
817
        enum cg_setup_mode_t setup_mode;
818

819
        setup_mode = cgroup_setup_mode();
2✔
820
        return (setup_mode == CGROUP_MODE_HYBRID);
2✔
821
}
822

823
/*
824
 * Return true if cgroup setup mode is cgroup v2 (unified), else
825
 * returns false.
826
 */
827
bool is_cgroup_mode_unified(void)
80✔
828
{
829
        enum cg_setup_mode_t setup_mode;
830

831
        setup_mode = cgroup_setup_mode();
80✔
832
        return (setup_mode == CGROUP_MODE_UNIFIED);
80✔
833
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc