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

mendersoftware / mender-mcu / 1744429624

31 Mar 2025 10:22AM UTC coverage: 57.657% (-0.03%) from 57.689%
1744429624

push

gitlab-ci

vpodzime
feat: Submit deployment logs for failed deployments

Ticket: MEN-7626
Changelog: none
Signed-off-by: Vratislav Podzimek <vratislav.podzimek+auto-signed@northern.tech>

66 of 66 new or added lines in 1 file covered. (100.0%)

172 existing lines in 2 files now uncovered.

2244 of 3892 relevant lines covered (57.66%)

73.49 hits per line

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

61.6
/src/platform/storage/zephyr/nvs/storage.c
1
/**
2
 * @file      storage.c
3
 * @brief     Mender storage interface for Zephyr platform
4
 *
5
 * Copyright joelguittet and mender-mcu-client contributors
6
 * Copyright Northern.tech AS
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
#include <errno.h>
22
#include <zephyr/drivers/flash.h>
23
#include <zephyr/fs/nvs.h>
24
#include <zephyr/sys/crc.h>
25
#include <zephyr/storage/flash_map.h>
26
#include "log.h"
27
#include "storage.h"
28

29
#ifdef CONFIG_MENDER_DEPLOYMENT_LOGS
30
#include <zephyr/fs/fcb.h>
31
#endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */
32

33
/**
34
 * @brief NVS storage
35
 */
36
#define MENDER_STORAGE_LABEL      storage_partition
37
#define MENDER_STORAGE_DEVICE     FIXED_PARTITION_DEVICE(MENDER_STORAGE_LABEL)
38
#define MENDER_STORAGE_OFFSET     FIXED_PARTITION_OFFSET(MENDER_STORAGE_LABEL)
39
#define MENDER_STORAGE_FLASH_AREA FIXED_PARTITION_ID(MENDER_STORAGE_LABEL)
40

41
/**
42
 * @brief NVS keys
43
 */
44
#define MENDER_STORAGE_NVS_PRIVATE_KEY     1
45
#define MENDER_STORAGE_NVS_PUBLIC_KEY      2
46
#define MENDER_STORAGE_NVS_DEPLOYMENT_DATA 3
47
#define MENDER_STORAGE_NVS_PROVIDES        4
48
#define MENDER_STORAGE_NVS_ARTICACT_NAME   5
49

50
/**
51
 * @brief Cached Artifact name
52
 */
53
static char *cached_artifact_name = NULL;
54

55
/**
56
 * @brief NVS storage handle
57
 */
58
static struct nvs_fs mender_storage_nvs_handle;
59

60
#ifdef CONFIG_MENDER_DEPLOYMENT_LOGS
61
/* just some fixed magic value the FCB implementation uses to mark
62
   in-use/erased/... sectors */
63
#define DEPLOYMENT_LOGS_MAGIC_VALUE 0x2AABEE35
64

65
/**
66
 * @brief A Flash Circular Buffer for storing deployment logs
67
 */
68
static struct fcb depl_logs_buffer;
69

70
#define DEPL_LOGS_MAX_MSG_LEN 255
71
#endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */
72

73
/**
74
 * @brief Flash sectors used by Mender
75
 */
76
#ifdef CONFIG_MENDER_DEPLOYMENT_LOGS
77
static struct flash_sector flash_sectors[CONFIG_MENDER_STORAGE_NVS_SECTOR_COUNT + CONFIG_MENDER_STORAGE_DEPLOYMENT_LOGS_SECTORS];
78
#else
79
static struct flash_sector flash_sectors[CONFIG_MENDER_STORAGE_NVS_SECTOR_COUNT];
80
#endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */
81

82
static mender_err_t
83
nvs_read_alloc(struct nvs_fs *nvs, uint16_t id, void **data, size_t *length) {
192✔
84
    ssize_t ret;
85

86
    /* Peek read to retrieve length of the data */
87
    uint8_t byte;
88
    ret = nvs_read(nvs, id, &byte, 0);
192✔
89
    if (ret <= 0) {
192✔
90
        return (0 == ret || -ENOENT == ret) ? MENDER_NOT_FOUND : MENDER_FAIL;
128✔
91
    }
92
    *length = (size_t)ret;
64✔
93

94
    /* Allocate memory */
95
    *data = mender_malloc(*length);
64✔
96
    if (NULL == *data) {
64✔
UNCOV
97
        mender_log_error("Unable to allocate memory for: %d", id);
×
UNCOV
98
        return MENDER_FAIL;
×
99
    }
100

101
    /* Read data */
102
    ret = nvs_read(nvs, id, *data, *length);
64✔
103
    if (ret < 0) {
64✔
UNCOV
104
        FREE_AND_NULL(*data);
×
UNCOV
105
        return MENDER_FAIL;
×
106
    }
107

108
    return MENDER_OK;
64✔
109
}
110

111
static inline bool
112
checked_nvs_write(struct nvs_fs *fs, uint16_t id, const void *data, size_t len) {
5✔
113
    ssize_t ret = nvs_write(fs, id, data, len);
5✔
114
    /* nvs_write() docs say:
115
     *    When a rewrite of the same data already stored is attempted, nothing is written to flash, thus 0 is returned.
116
     */
117
    return (len == ret) || (0 == ret);
5✔
118
}
119

120
static mender_err_t
121
crc_add(char **data, size_t *data_len) {
77✔
122

123
    assert(NULL != data);
77✔
124
    assert(NULL != data_len);
77✔
125

126
    uint32_t crc = crc32_ieee(*data, *data_len);
77✔
127
    char    *tmp = mender_realloc(*data, *data_len + sizeof(crc));
77✔
128
    if (NULL == tmp) {
77✔
UNCOV
129
        mender_log_error("Unable to allocate memory for deployment data");
×
UNCOV
130
        return MENDER_FAIL;
×
131
    }
132
    memcpy(tmp + *data_len, &crc, sizeof(crc));
77✔
133
    *data_len += sizeof(crc);
77✔
134
    *data = tmp;
77✔
135

136
    return MENDER_OK;
77✔
137
}
138

139
static mender_err_t
140
crc_check(const unsigned char *data, const size_t data_len) {
16✔
141

142
    assert(NULL != data);
16✔
143

144
    if (data_len > sizeof(uint32_t)) {
16✔
145

146
        /* Extract the CRC  */
147
        uint32_t crc = *(uint32_t *)(data + data_len - sizeof(crc));
16✔
148

149
        /* Compute CRC of the loaded data */
150
        uint32_t computed_crc = crc32_ieee(data, data_len - sizeof(crc));
16✔
151

152
        if (computed_crc != crc) {
16✔
153
            mender_log_error("CRC mismatch in deployment data");
×
154
            return MENDER_FAIL;
×
155
        }
156
    } else {
UNCOV
157
        mender_log_error("Invalid deployment data size (too small for CRC)");
×
UNCOV
158
        return MENDER_FAIL;
×
159
    }
160

161
    return MENDER_OK;
16✔
162
}
163

164
mender_err_t
165
mender_storage_init(void) {
29✔
166
    int      result;
167
    uint32_t n_sectors;
168

169
    /* Get flash info */
170
    mender_storage_nvs_handle.flash_device = MENDER_STORAGE_DEVICE;
29✔
171
    if (!device_is_ready(mender_storage_nvs_handle.flash_device)) {
29✔
UNCOV
172
        mender_log_error("Flash device not ready");
×
UNCOV
173
        return MENDER_FAIL;
×
174
    }
175

176
    n_sectors = sizeof(flash_sectors) / sizeof(flash_sectors[0]);
29✔
177
    result    = flash_area_get_sectors(MENDER_STORAGE_FLASH_AREA, &n_sectors, flash_sectors);
29✔
178
    if ((0 != result) && (-ENOMEM != result)) {
29✔
179
        /* -ENOMEM means there were more sectors than the supplied size of the
180
            sector array (flash_sectors), but we don't worry about that, we just
181
            need the info about the first N sectors we want to use. */
182
        mender_log_error("Failed to get info about flash sectors in the Mender flash area [%d]", -result);
×
UNCOV
183
        return MENDER_FAIL;
×
184
    }
185
    if (n_sectors != (sizeof(flash_sectors) / sizeof(flash_sectors[0]))) {
29✔
UNCOV
186
        mender_log_error(
×
187
            "Not enough sectors on the flash for Mender (required: %" PRIu32 "d, available: %zu)", sizeof(flash_sectors) / sizeof(flash_sectors[0]), n_sectors);
UNCOV
188
        return MENDER_FAIL;
×
189
    }
190

191
    mender_storage_nvs_handle.offset       = MENDER_STORAGE_OFFSET;
29✔
192
    mender_storage_nvs_handle.sector_size  = (uint16_t)flash_sectors[0].fs_size;
29✔
193
    mender_storage_nvs_handle.sector_count = CONFIG_MENDER_STORAGE_NVS_SECTOR_COUNT;
29✔
194

195
    /* Mount NVS */
196
    if (0 != (result = nvs_mount(&mender_storage_nvs_handle))) {
29✔
UNCOV
197
        mender_log_error("Unable to mount NVS storage, result = %d", result);
×
UNCOV
198
        return MENDER_FAIL;
×
199
    }
200
    mender_log_debug("Initialized Mender NVS with %u sectors (%zu bytes available)",
29✔
201
                     mender_storage_nvs_handle.sector_count,
202
                     (size_t)(mender_storage_nvs_handle.sector_count - 1) * mender_storage_nvs_handle.sector_size);
203

204
#ifdef CONFIG_MENDER_DEPLOYMENT_LOGS
205
    /* Initialize the Flash Circular Buffer (FCB) for deployment logs. */
206

207
    depl_logs_buffer.f_magic       = DEPLOYMENT_LOGS_MAGIC_VALUE;
29✔
208
    depl_logs_buffer.f_version     = 0; /* we don't version the data so 0 always */
29✔
209
    depl_logs_buffer.f_sector_cnt  = CONFIG_MENDER_STORAGE_DEPLOYMENT_LOGS_SECTORS;
29✔
210
    depl_logs_buffer.f_scratch_cnt = 0; /* no scratch sector, we don't use it */
29✔
211
    depl_logs_buffer.f_sectors     = flash_sectors + CONFIG_MENDER_STORAGE_NVS_SECTOR_COUNT;
29✔
212

213
    if (0 != (result = fcb_init(FIXED_PARTITION_ID(MENDER_STORAGE_LABEL), &depl_logs_buffer))) {
29✔
UNCOV
214
        mender_log_debug("Failed to initialize deployment logs FCB, erasing the particular flash area");
×
215

216
        const struct flash_area *fap;
217
        if (0 != (result = flash_area_open(FIXED_PARTITION_ID(MENDER_STORAGE_LABEL), &fap))) {
×
UNCOV
218
            mender_log_error("Unable to open the Mender storage flash area");
×
UNCOV
219
            return MENDER_FAIL;
×
220
        }
221

222
        /* flatten means: Erase flash area or fill with erase-value. */
223
        result = flash_area_flatten(
×
224
            fap, depl_logs_buffer.f_sectors[0].fs_off, depl_logs_buffer.f_sectors[0].fs_off * CONFIG_MENDER_STORAGE_DEPLOYMENT_LOGS_SECTORS);
×
225
        flash_area_close(fap);
×
UNCOV
226
        if (0 != result) {
×
UNCOV
227
            mender_log_error("Failed to erase the flash area for deployment logs");
×
228
        }
229
        /* Now, try again. */
230
        if (0 != (result = fcb_init(FIXED_PARTITION_ID(MENDER_STORAGE_LABEL), &depl_logs_buffer))) {
×
UNCOV
231
            mender_log_error("Unable to initialize the Flash Circular Buffer for deployment logs [%d]", -result);
×
UNCOV
232
            return MENDER_FAIL;
×
233
        }
234
    }
235
    mender_log_debug("Initialized deployment logs FCB with %u sectors (%zu bytes available)",
29✔
236
                     depl_logs_buffer.f_sector_cnt,
237
                     (depl_logs_buffer.f_sector_cnt - 1) * mender_storage_nvs_handle.sector_size);
238
#endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */
239

240
    return MENDER_OK;
29✔
241
}
242

243
#ifdef CONFIG_MENDER_DEPLOYMENT_LOGS
244
static mender_err_t
245
get_next_fcb_entry(const struct flash_area *fap, struct fcb_entry *entry, size_t msg_size) {
49✔
246
    int result = fcb_append(&depl_logs_buffer, msg_size, entry);
49✔
247
    if (-ENOSPC == result) {
49✔
248
        /* If no space, rotate the FCB (drop/erase one sector of data and start
249
           writing to it from the start) */
UNCOV
250
        if (0 != (result = fcb_rotate(&depl_logs_buffer))) {
×
251
            mender_log_error("Failed to rotate the deployment logs FCB");
×
252
            return MENDER_FAIL;
×
253
        }
UNCOV
254
        const char rotation_msg[] = "<wrn> ------- DEPLOYMENT LOGS ROTATED -------";
×
UNCOV
255
        result                    = fcb_append(&depl_logs_buffer, sizeof(rotation_msg), entry);
×
UNCOV
256
        if (0 != (result = flash_area_write(fap, entry->fe_sector->fs_off + entry->fe_data_off, rotation_msg, sizeof(rotation_msg)))) {
×
UNCOV
257
            mender_log_error("Failed to write message to the FCB entry [%d]", -result);
×
258
            return MENDER_FAIL;
×
259
        }
UNCOV
260
        result = fcb_append_finish(&depl_logs_buffer, entry);
×
UNCOV
261
        if (0 != result) {
×
262
            mender_log_error("Failed to finish append of a rotation entry to the deployment logs FCB");
×
263
            return MENDER_FAIL;
×
264
        }
265

266
        result = fcb_append(&depl_logs_buffer, msg_size, entry);
×
267
    }
268
    return (0 == result) ? MENDER_OK : MENDER_FAIL;
49✔
269
}
270

271
mender_err_t
272
mender_storage_deployment_log_append(const char *msg, size_t msg_size) {
49✔
273
    int          result;
274
    mender_err_t ret = MENDER_OK;
49✔
275

276
    msg_size = MIN(DEPL_LOGS_MAX_MSG_LEN + 1, msg_size);
49✔
277

278
    const struct flash_area *fap;
279
    if (0 != (result = flash_area_open(FIXED_PARTITION_ID(MENDER_STORAGE_LABEL), &fap))) {
49✔
UNCOV
280
        mender_log_error("Unable to open the Mender storage flash area [%d]", -result);
×
UNCOV
281
        return MENDER_FAIL;
×
282
    }
283

284
    struct fcb_entry entry = { 0 };
49✔
285
    if (MENDER_OK != get_next_fcb_entry(fap, &entry, msg_size)) {
49✔
UNCOV
286
        mender_log_error("Failed to append a new entry to the deployment logs FCB");
×
UNCOV
287
        ret = MENDER_FAIL;
×
288
        goto END;
×
289
    }
290
    /* else success, proceed */
291
    if (0 != (result = flash_area_write(fap, entry.fe_sector->fs_off + entry.fe_data_off, msg, msg_size))) {
49✔
UNCOV
292
        mender_log_error("Failed to write message to the FCB entry [%d]", -result);
×
UNCOV
293
        ret = MENDER_FAIL;
×
294
        goto END;
×
295
    }
296
    result = fcb_append_finish(&depl_logs_buffer, &entry);
49✔
297
    if (0 != result) {
49✔
UNCOV
298
        mender_log_error("Failed to finish append of a new entry to the deployment logs FCB");
×
UNCOV
299
        ret = MENDER_FAIL;
×
UNCOV
300
        goto END;
×
301
    }
302

303
END:
49✔
304
    flash_area_close(fap);
49✔
305

306
    return ret;
49✔
307
}
308

309
mender_err_t
310
mender_storage_deployment_log_walk(MenderDeploymentLogVisitor visitor_fn, void *ctx) {
6✔
311
    mender_err_t ret = MENDER_OK;
6✔
312
    int          result;
313
    char         msg[DEPL_LOGS_MAX_MSG_LEN + 1];
314

315
    const struct flash_area *fap;
316
    if (0 != (result = flash_area_open(FIXED_PARTITION_ID(MENDER_STORAGE_LABEL), &fap))) {
6✔
UNCOV
317
        mender_log_error("Unable to open the Mender storage flash area");
×
UNCOV
318
        return MENDER_FAIL;
×
319
    }
320

321
    struct fcb_entry entry = { 0 };
6✔
322
    result                 = fcb_getnext(&depl_logs_buffer, &entry);
6✔
323
    while (0 == result) {
20✔
324
        if (0 != (result = flash_area_read(fap, entry.fe_sector->fs_off + entry.fe_data_off, (void *)msg, MIN(DEPL_LOGS_MAX_MSG_LEN, entry.fe_data_len)))) {
14✔
UNCOV
325
            mender_log_error("Failed to read FCB entry from flash [%d]", -result);
×
UNCOV
326
            ret = MENDER_FAIL;
×
UNCOV
327
            goto END;
×
328
        }
329
        msg[MIN(DEPL_LOGS_MAX_MSG_LEN, entry.fe_data_len)] = '\0';
14✔
330
        visitor_fn(msg, ctx);
14✔
331
        result = fcb_getnext(&depl_logs_buffer, &entry);
14✔
332
    }
333
    if (-EBADMSG != result) {
6✔
334
        /* -EBADMSG seems to be the error returned when there's no more data in
335
            an FCB (see zephyr/subsys/fs/fcb/fcb_getnext.c) */
336
        mender_log_error("Failed to iterate over saved deployment logs [%d]", -result);
6✔
337
        ret = MENDER_FAIL;
6✔
338
        goto END;
6✔
339
    }
340

UNCOV
341
END:
×
342
    flash_area_close(fap);
6✔
343

344
    return ret;
6✔
345
}
346

347
mender_err_t
348
mender_storage_deployment_log_clear(void) {
12✔
349
    int result = fcb_clear(&depl_logs_buffer);
12✔
350
    return (0 == result) ? MENDER_OK : MENDER_FAIL;
12✔
351
}
352
#endif /* CONFIG_MENDER_DEPLOYMENT_LOGS */
353

354
mender_err_t
355
mender_storage_set_authentication_keys(unsigned char *private_key, size_t private_key_length, unsigned char *public_key, size_t public_key_length) {
13✔
356

357
    assert(NULL != private_key);
13✔
358
    assert(NULL != public_key);
13✔
359

360
    /* Write keys */
361
    if ((nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PRIVATE_KEY, private_key, private_key_length) < 0)
13✔
362
        || (nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PUBLIC_KEY, public_key, public_key_length) < 0)) {
13✔
UNCOV
363
        mender_log_error("Unable to write authentication keys");
×
UNCOV
364
        return MENDER_FAIL;
×
365
    }
366

367
    return MENDER_OK;
13✔
368
}
369

370
mender_err_t
371
mender_storage_get_authentication_keys(unsigned char **private_key, size_t *private_key_length, unsigned char **public_key, size_t *public_key_length) {
29✔
372

373
    assert(NULL != private_key);
29✔
374
    assert(NULL != private_key_length);
29✔
375
    assert(NULL != public_key);
29✔
376
    assert(NULL != public_key_length);
29✔
377

378
    /* Read private key */
379
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PRIVATE_KEY, (void **)private_key, private_key_length);
29✔
380
    if (MENDER_OK != ret) {
29✔
381
        if (MENDER_NOT_FOUND == ret) {
13✔
382
            mender_log_debug("Private key not available");
13✔
383
        } else {
384
            mender_log_error("Unable to read private key");
×
385
        }
386
        return ret;
13✔
387
    }
388

389
    /* Read public key */
390
    ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PUBLIC_KEY, (void **)public_key, public_key_length);
16✔
391
    if (MENDER_OK != ret) {
16✔
UNCOV
392
        if (MENDER_NOT_FOUND == ret) {
×
UNCOV
393
            mender_log_debug("Public key not available");
×
394
        } else {
UNCOV
395
            mender_log_error("Unable to read public key");
×
396
        }
397
        FREE_AND_NULL(*private_key);
×
398
        return ret;
×
399
    }
400

401
    return MENDER_OK;
16✔
402
}
403

404
mender_err_t
UNCOV
405
mender_storage_delete_authentication_keys(void) {
×
406

407
    /* Erase keys */
UNCOV
408
    if ((0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PRIVATE_KEY))
×
UNCOV
409
        || (0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PUBLIC_KEY))) {
×
UNCOV
410
        mender_log_error("Unable to erase authentication keys");
×
UNCOV
411
        return MENDER_FAIL;
×
412
    }
413

UNCOV
414
    return MENDER_OK;
×
415
}
416

417
mender_err_t
418
mender_storage_set_deployment_data(char *deployment_data) {
77✔
419

420
    assert(NULL != deployment_data);
77✔
421

422
    size_t data_len = strlen(deployment_data) + 1;
77✔
423

424
#ifdef CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC
425
    if (MENDER_OK != crc_add(&deployment_data, &data_len)) {
77✔
UNCOV
426
        return MENDER_FAIL;
×
427
    }
428
#endif /* CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC */
429

430
    /* Write deployment data  */
431
    if (nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_DEPLOYMENT_DATA, deployment_data, data_len) < 0) {
77✔
UNCOV
432
        mender_log_error("Unable to write deployment data");
×
UNCOV
433
        return MENDER_FAIL;
×
434
    }
435

436
    return MENDER_OK;
77✔
437
}
438

439
mender_err_t
440
mender_storage_get_deployment_data(char **deployment_data) {
29✔
441

442
    assert(NULL != deployment_data);
29✔
443
    size_t deployment_data_length = 0;
29✔
444

445
    /* Read deployment data */
446
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_DEPLOYMENT_DATA, (void **)deployment_data, &deployment_data_length);
29✔
447
    if (MENDER_OK != ret) {
29✔
448
        if (MENDER_NOT_FOUND == ret) {
13✔
449
            mender_log_debug("Deployment data not available");
13✔
450
        } else {
UNCOV
451
            mender_log_error("Unable to read deployment data");
×
452
        }
453
        return ret;
13✔
454
    }
455

456
#ifdef CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC
457
    if (MENDER_OK != crc_check(*deployment_data, deployment_data_length)) {
16✔
UNCOV
458
        return MENDER_FAIL;
×
459
    }
460
#endif /* CONFIG_MENDER_STORAGE_DEPLOYMENT_DATA_CRC */
461

462
    return MENDER_OK;
16✔
463
}
464

465
mender_err_t
466
mender_storage_delete_deployment_data(void) {
10✔
467

468
    /* Delete deployment data */
469
    if (0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_DEPLOYMENT_DATA)) {
10✔
UNCOV
470
        mender_log_error("Unable to delete deployment data");
×
UNCOV
471
        return MENDER_FAIL;
×
472
    }
473

474
    return MENDER_OK;
10✔
475
}
476

477
#ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT
478
#ifdef CONFIG_MENDER_PROVIDES_DEPENDS
479
mender_err_t
480
mender_storage_set_provides(mender_key_value_list_t *provides) {
5✔
481

482
    assert(NULL != provides);
5✔
483

484
    char *provides_str = NULL;
5✔
485
    if (MENDER_OK != mender_utils_key_value_list_to_string(provides, &provides_str)) {
5✔
UNCOV
486
        return MENDER_FAIL;
×
487
    }
488

489
    /* Write provides */
490
    if (nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PROVIDES, provides_str, strlen(provides_str) + 1) < 0) {
5✔
UNCOV
491
        mender_log_error("Unable to write provides");
×
UNCOV
492
        mender_free(provides_str);
×
UNCOV
493
        return MENDER_FAIL;
×
494
    }
495

496
    mender_free(provides_str);
5✔
497
    return MENDER_OK;
5✔
498
}
499

500
mender_err_t
501
mender_storage_get_provides(mender_key_value_list_t **provides) {
89✔
502
    assert(NULL != provides);
89✔
503
    assert(NULL == *provides); /* otherwise we prepend to a bad list going nowhere */
89✔
504

505
    size_t provides_length = 0;
89✔
506

507
    char *provides_str = NULL;
89✔
508
    /* Read provides */
509
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PROVIDES, (void **)&provides_str, &provides_length);
89✔
510
    if (MENDER_OK != ret) {
89✔
511
        if (MENDER_NOT_FOUND == ret) {
79✔
512
            mender_log_debug("Provides not available");
79✔
513
        } else {
UNCOV
514
            mender_log_error("Unable to read provides");
×
515
        }
516
        return ret;
79✔
517
    }
518

519
    /* Convert str to key-value list */
520
    if (MENDER_OK != mender_utils_string_to_key_value_list(provides_str, provides)) {
10✔
521
        mender_free(provides_str);
×
522
        return MENDER_FAIL;
×
523
    }
524
    mender_free(provides_str);
10✔
525
    return MENDER_OK;
10✔
526
}
527

528
mender_err_t
UNCOV
529
mender_storage_delete_provides(void) {
×
530

531
    /* Delete provides */
UNCOV
532
    if (0 != nvs_delete(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_PROVIDES)) {
×
UNCOV
533
        mender_log_error("Unable to delete provides");
×
UNCOV
534
        return MENDER_FAIL;
×
535
    }
536

UNCOV
537
    return MENDER_OK;
×
538
}
539
#endif /* CONFIG_MENDER_PROVIDES_DEPENDS */
540
#endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */
541

542
mender_err_t
543
mender_storage_set_artifact_name(const char *artifact_name) {
5✔
544

545
    assert(NULL != artifact_name);
5✔
546

547
    /* Write artifact_name */
548
    if (!checked_nvs_write(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_ARTICACT_NAME, artifact_name, strlen(artifact_name) + 1)) {
5✔
UNCOV
549
        mender_log_error("Unable to write artifact_name");
×
UNCOV
550
        return MENDER_FAIL;
×
551
    }
552

553
    mender_free(cached_artifact_name);
5✔
554
    cached_artifact_name = NULL;
5✔
555

556
    return MENDER_OK;
5✔
557
}
558

559
mender_err_t
560
mender_storage_get_artifact_name(const char **artifact_name) {
67✔
561

562
    assert(NULL != artifact_name);
67✔
563

564
    if (NULL != cached_artifact_name) {
67✔
565
        *artifact_name = cached_artifact_name;
38✔
566
        return MENDER_OK;
38✔
567
    }
568

569
    size_t artifact_name_length;
570

571
    /* Read artifact_name */
572
    mender_err_t ret = nvs_read_alloc(&mender_storage_nvs_handle, MENDER_STORAGE_NVS_ARTICACT_NAME, (void **)artifact_name, &artifact_name_length);
29✔
573
    if (MENDER_OK != ret) {
29✔
574
        if (MENDER_NOT_FOUND == ret) {
23✔
575
            if (NULL == (*artifact_name = mender_utils_strdup("unknown"))) {
23✔
UNCOV
576
                mender_log_error("Unable to allocate memory");
×
UNCOV
577
                return MENDER_FAIL;
×
578
            }
579
            cached_artifact_name = (char *)*artifact_name;
23✔
580
            return MENDER_OK;
23✔
581

582
        } else {
UNCOV
583
            mender_log_error("Unable to read artifact_name");
×
584
        }
585
    } else {
586
        cached_artifact_name = (char *)*artifact_name;
6✔
587
    }
588

589
    return ret;
6✔
590
}
591

592
mender_err_t
UNCOV
593
mender_storage_exit(void) {
×
594

UNCOV
595
    FREE_AND_NULL(cached_artifact_name);
×
596

UNCOV
597
    return MENDER_OK;
×
598
}
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

© 2025 Coveralls, Inc