GCC Code Coverage Report


Directory: src/
File: src/support/env.c
Date: 2024-11-22 17:07:10
Exec Total Coverage
Lines: 47 47 100.0%
Functions: 2 2 100.0%
Branches: 26 30 86.7%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2021 Barcelona Supercomputing Center */
3 /* */
4 /* This file is part of the DLB library. */
5 /* */
6 /* DLB is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU Lesser General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* DLB is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU Lesser General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU Lesser General Public License */
17 /* along with DLB. If not, see <https://www.gnu.org/licenses/>. */
18 /*********************************************************************************/
19
20 #include "support/env.h"
21
22 #include "support/debug.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 /* Implementation based on glibc's setenv:
29 * https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/setenv.c
30 */
31 10 static void add_to_environ(const char *name, const char *value, char ***next_environ,
32 env_add_condition_t condition) {
33 10 const size_t namelen = strlen (name);
34 10 size_t size = 0;
35 char **ep;
36
37
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
13 for (ep=*next_environ; *ep != NULL; ++ep) {
38
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
11 if (!strncmp(*ep, name, namelen) && (*ep)[namelen] == '=')
39 break;
40 else
41 3 ++size;
42 }
43
44
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (*ep == NULL) {
45 /* Variable does not exist */
46
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (condition == ENV_UPDATE_IF_EXISTS) return;
47
48 /* Allocate new variable */
49 // realloc (num_existing_vars + 1(new_var) + 1(NULL))
50 1 char **new_environ = realloc(*next_environ, (size + 2)*sizeof(char*));
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 fatal_cond(!new_environ, "realloc failed");
52 1 *next_environ = new_environ;
53 // set last position of next_environ
54 1 new_environ[size+1] = NULL;
55 // pointer where new variable will be
56 1 ep = new_environ + size;
57
58 } else {
59 /* Variable does exist */
60
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (condition == ENV_OVERWRITE_NEVER) return;
61
62 // ep already points to the variable we will overwrite
63
64 /* Only if the variable exists and needs appending, allocate new buffer */
65
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (condition == ENV_APPEND) {
66 3 const size_t origlen = strlen(*ep);
67 3 const size_t newlen = origlen + 1 + strlen(value) +1;
68 3 char *new_np = realloc(*ep, newlen);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 fatal_cond(!new_np, "realloc failed");
70 3 *ep = new_np;
71 3 sprintf(new_np+origlen, " %s", value);
72 3 return;
73 }
74 }
75
76 5 const size_t varlen = strlen(name) + 1 + strlen(value) + 1;
77 5 char *np = malloc(varlen);
78 5 snprintf(np, varlen, "%s=%s", name, value);
79 5 *ep = np;
80 }
81
82 /* Modify environment:
83 * - name: environment variable name
84 * - value: environment variable value
85 * - next_environ: environ pointer, or NULL to modify current environment
86 * - condition: overwrite/append conditions
87 */
88 40 void dlb_setenv(const char *name, const char *value, char ***next_environ,
89 env_add_condition_t condition) {
90
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
40 if (next_environ == NULL) {
91 /* Modify current environment */
92 30 const char *current_value = getenv(name);
93
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 22 times.
30 if (!current_value) {
94
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (condition == ENV_UPDATE_IF_EXISTS) return;
95
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (condition == ENV_APPEND) condition = ENV_OVERWRITE_NEVER;
96 }
97 size_t len;
98 char *new_value;
99
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
28 switch(condition) {
100 7 case ENV_OVERWRITE_NEVER:
101 7 setenv(name, value, 0);
102 7 break;
103 9 case ENV_UPDATE_IF_EXISTS:
104 DLB_FALLTHROUGH;
105 case ENV_OVERWRITE_ALWAYS:
106 9 setenv(name, value, 1);
107 9 break;
108 12 case ENV_APPEND:
109 /* We can assume current_value is not NULL */
110 12 len = strlen(current_value) + 1 + strlen(value) + 1;
111 12 new_value = malloc(sizeof(char)*len);
112 12 sprintf(new_value, "%s %s", current_value, value);
113 12 setenv(name, new_value, 1);
114 12 free(new_value);
115 12 break;
116 }
117 } else {
118 /* Modify next_environ */
119 10 add_to_environ(name, value, next_environ, condition);
120 }
121 }
122