-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetadata.c
138 lines (102 loc) · 4.13 KB
/
metadata.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "metadata.h"
#include <assert.h>
#include <arpa/inet.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
struct metadata metadata_init(void)
{
struct metadata meta = {
.magic = htonl(METADATA_MAGIC),
.version = htons(METADATA_VERSION),
.short_label = { '\0' },
.img_size = 0,
.checksum = { '\0' },
};
return meta;
}
enum RET_CODES metadata_set_short_label(const char *const short_label, struct metadata *const meta_p)
{
assert(short_label != NULL);
assert(meta_p != NULL);
/* Don't allow uninitialised structs. */
assert(ntohl(meta_p->magic) == METADATA_MAGIC && "Metadata struct must be initialised by metadata_init().");
const size_t len = ({
size_t _len = strlen(short_label);
_len > METADATA_SHORT_LABEL_SIZE ? METADATA_SHORT_LABEL_SIZE : _len;
});
memcpy((void *) meta_p->short_label, short_label, len);
meta_p->short_label[METADATA_SHORT_LABEL_SIZE - 1] = '\0';
return FAIL_SUCC;
}
void metadata_set_img_size(const uint32_t img_size, struct metadata *const meta_p)
{
assert(meta_p != NULL);
meta_p->img_size = (img_size);
}
uint32_t metadata_get_img_size(const struct metadata *const meta_p)
{
uint32_t img_size;
assert(meta_p != NULL);
img_size = ntohl(meta_p->img_size);
if (img_size > IMAGE_SIZE) {
img_size = IMAGE_SIZE;
}
return img_size;
}
static enum RET_CODES metadata_parse(const int fd, struct metadata *const meta_p)
{
struct metadata meta;
CHECK_ERROR_GENERIC(read(fd, &meta, sizeof(meta)), ssize_t, FAIL_READ);
if (ntohl(meta.magic) != METADATA_MAGIC) {
return FAIL_NOMETA;
}
memcpy(meta_p, &meta, sizeof(struct metadata));
return FAIL_SUCC;
}
enum RET_CODES metadata_parse_slot(const int fd, const unsigned int slot, struct metadata *const meta_p)
{
const uint64_t offset = slot * MAGIC_OFFSET + IMAGE_SIZE;
enum RET_CODES rc;
CHECK_ERROR_GENERIC(lseek(fd, offset, SEEK_SET), off_t, FAIL_LSEEK);
rc = metadata_parse(fd, meta_p);
return rc;
}
enum RET_CODES metadata_write(const int fd, const unsigned int slot, const struct metadata *const meta_p)
{
const uint64_t offset = (MAGIC_OFFSET * slot) + IMAGE_SIZE;
assert(meta_p != NULL);
CHECK_ERROR_GENERIC(lseek(fd, offset, SEEK_SET), off_t, FAIL_LSEEK);
CHECK_ERROR_GENERIC(write(fd, meta_p, sizeof(*meta_p)), ssize_t, FAIL_WRITE);
return FAIL_SUCC;
}
enum RET_CODES metadata_write_checksum(const int fd, const unsigned int slot, const unsigned char *checksum, const uint32_t img_size)
{
const uint64_t offset_checksum = (MAGIC_OFFSET * slot) + IMAGE_SIZE + offsetof(struct metadata, checksum);
const uint64_t offset_img_size = (MAGIC_OFFSET * slot) + IMAGE_SIZE + offsetof(struct metadata, img_size);
uint32_t img_size_right_endian = htonl(img_size);
assert(checksum != NULL);
CHECK_ERROR_GENERIC(lseek(fd, offset_checksum, SEEK_SET), off_t, FAIL_LSEEK);
CHECK_ERROR_GENERIC(write(fd, (const void *) checksum, METADATA_CHECKSUM_SIZE), ssize_t, FAIL_WRITE);
CHECK_ERROR_GENERIC(lseek(fd, offset_img_size, SEEK_SET), off_t, FAIL_LSEEK);
CHECK_ERROR_GENERIC(write(fd, (void *) &img_size_right_endian, sizeof(img_size)), ssize_t, FAIL_WRITE);
return FAIL_SUCC;
}
enum RET_CODES metadata_write_short_label(const int fd, const unsigned int slot, const char *const short_label)
{
const uint64_t offset = (MAGIC_OFFSET * slot) + IMAGE_SIZE + offsetof(struct metadata, short_label);
const size_t len = ({
size_t _len = strlen(short_label);
_len > METADATA_SHORT_LABEL_SIZE ? METADATA_SHORT_LABEL_SIZE : _len;
});
char tmp_short_label[METADATA_SHORT_LABEL_SIZE] = { '\0' };
assert(short_label != NULL);
memcpy(tmp_short_label, short_label, len);
tmp_short_label[METADATA_SHORT_LABEL_SIZE - 1] = '\0';
CHECK_ERROR_GENERIC(lseek(fd, offset, SEEK_SET), off_t, FAIL_LSEEK);
CHECK_ERROR_GENERIC(write(fd, (void *) &tmp_short_label, METADATA_SHORT_LABEL_SIZE), ssize_t, FAIL_WRITE);
return FAIL_SUCC;
}