-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathres.c
More file actions
130 lines (116 loc) · 2.61 KB
/
Copy pathres.c
File metadata and controls
130 lines (116 loc) · 2.61 KB
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
/*
* SPDX-FileType: SOURCE
*
* SPDX-FileCopyrightText: 2026 Nick Kossifidis <mick@ics.forth.gr>
* SPDX-FileCopyrightText: 2026 ICS/FORTH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <utils.h>
#include "res.h"
struct res_t *
res_from_file(const char *path, size_t max_size)
{
struct res_t *res = NULL;
struct stat st;
int prot, flags;
res = malloc(sizeof(struct res_t));
if (!res)
return NULL;
memset(res, 0, sizeof(struct res_t));
res->fd = -1;
res->type = RES_TYPE_FILE;
if (max_size > 0) {
res->writable = 1;
res->max_size = max_size;
res->fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (res->fd < 0) {
ERR("open %s: %s\n", path, strerror(errno));
goto cleanup;
}
if (ftruncate(res->fd, (off_t)max_size) < 0) {
ERR("ftruncate %s: %s\n", path, strerror(errno));
goto cleanup;
}
prot = PROT_READ | PROT_WRITE;
flags = MAP_SHARED;
} else {
res->writable = 0;
res->fd = open(path, O_RDONLY);
if (res->fd < 0) {
ERR("open %s: %s\n", path, strerror(errno));
goto cleanup;
}
if (fstat(res->fd, &st) < 0) {
ERR("fstat %s: %s\n", path, strerror(errno));
goto cleanup;
}
if (st.st_size == 0) {
ERR("empty file: %s\n", path);
goto cleanup;
}
res->size = (size_t)st.st_size;
res->max_size = res->size;
prot = PROT_READ;
flags = MAP_PRIVATE;
}
res->buf = mmap(NULL, res->max_size, prot, flags, res->fd, 0);
if (res->buf == MAP_FAILED) {
ERR("mmap %s: %s\n", path, strerror(errno));
res->buf = NULL;
goto cleanup;
}
madvise(res->buf, res->max_size, MADV_SEQUENTIAL);
if (!res->writable)
madvise(res->buf, res->max_size, MADV_WILLNEED);
return res;
cleanup:
if (res->fd >= 0)
close(res->fd);
free(res);
return NULL;
}
struct res_t *
res_from_mem(uint8_t *buf, size_t size)
{
struct res_t *res = NULL;
res = malloc(sizeof(struct res_t));
if (!res)
return NULL;
memset(res, 0, sizeof(struct res_t));
res->fd = -1;
res->type = RES_TYPE_MEM;
res->buf = buf;
res->size = size;
res->max_size = size;
res->writable = 1;
return res;
}
void
res_release(struct res_t *res)
{
if (!res)
return;
if (res->type == RES_TYPE_FILE && res->buf) {
if (res->writable) {
if (res->size > 0 && res->size < res->max_size) {
int r = ftruncate(res->fd, (off_t)res->size);
(void)r;
}
msync(res->buf, res->max_size, MS_SYNC);
}
munmap(res->buf, res->max_size);
if (res->fd >= 0)
close(res->fd);
} else if (res->type == RES_TYPE_MEM) {
free(res->buf);
}
free(res);
}