blob: 107b29670a5462395250bff8d879fd34a17236a0 [file] [log] [blame]
Amit Pundird477f822020-02-07 22:26:08 +05301#include <sys/stat.h>
2#include <sys/types.h>
3#include <errno.h>
4#include <fcntl.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9#include "rmtfs.h"
10
11#define MAX_CALLERS 10
12#define STORAGE_MAX_SIZE (16 * 1024 * 1024)
13
Amit Pundird477f822020-02-07 22:26:08 +053014#define BY_PARTLABEL_PATH "/dev/disk/by-partlabel"
Amit Pundird477f822020-02-07 22:26:08 +053015
16#define MIN(x, y) ((x) < (y) ? (x) : (y))
17
18struct partition {
19 const char *path;
20 const char *actual;
21 const char *partlabel;
22};
23
24struct rmtfd {
25 unsigned id;
26 unsigned node;
27 int fd;
28 unsigned dev_error;
29 const struct partition *partition;
30
31 void *shadow_buf;
32 size_t shadow_len;
33};
34
35static const char *storage_dir = "/boot";
36static int storage_read_only;
37static int storage_use_partitions;
38
39static const struct partition partition_table[] = {
40 { "/boot/modem_fs1", "modem_fs1", "modemst1" },
41 { "/boot/modem_fs2", "modem_fs2", "modemst2" },
42 { "/boot/modem_fsc", "modem_fsc", "fsc" },
43 { "/boot/modem_fsg", "modem_fsg", "fsg" },
Amit Pundir53c12872022-10-27 21:55:51 +053044 { "/boot/modem_tunning", "modem_tunning", "tunning" },
Amit Pundird477f822020-02-07 22:26:08 +053045 {}
46};
47
48static struct rmtfd rmtfds[MAX_CALLERS];
49
50static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file);
51
52int storage_init(const char *storage_root, bool read_only, bool use_partitions)
53{
54 int i;
55
56 if (storage_root)
57 storage_dir = storage_root;
58
59 if (use_partitions) {
Amit Pundir39f249c2020-02-24 13:23:55 +053060 if (!storage_root)
61 storage_dir = BY_PARTLABEL_PATH;
Amit Pundird477f822020-02-07 22:26:08 +053062 storage_use_partitions = true;
63 }
64
65 storage_read_only = read_only;
66
67 for (i = 0; i < MAX_CALLERS; i++) {
68 rmtfds[i].id = i;
69 rmtfds[i].fd = -1;
70 rmtfds[i].shadow_buf = NULL;
71 }
72
73 return 0;
74}
75
76struct rmtfd *storage_open(unsigned node, const char *path)
77{
78 char *fspath;
79 const struct partition *part;
80 struct rmtfd *rmtfd = NULL;
81 const char *file;
82 size_t pathlen;
83 int saved_errno;
84 int ret;
85 int fd;
86 int i;
87
88 for (part = partition_table; part->path; part++) {
89 if (strcmp(part->path, path) == 0)
90 goto found;
91 }
92
93 fprintf(stderr, "[RMTFS storage] request for unknown partition '%s', rejecting\n", path);
94 return NULL;
95
96found:
97 /* Check if this node already has the requested path open */
98 for (i = 0; i < MAX_CALLERS; i++) {
99 if ((rmtfds[i].fd != -1 || rmtfds[i].shadow_buf) &&
100 rmtfds[i].node == node &&
101 rmtfds[i].partition == part)
102 return &rmtfds[i];
103 }
104
105 for (i = 0; i < MAX_CALLERS; i++) {
106 if (rmtfds[i].fd == -1 && !rmtfds[i].shadow_buf) {
107 rmtfd = &rmtfds[i];
108 break;
109 }
110 }
111 if (!rmtfd) {
112 fprintf(stderr, "[storage] out of free rmtfd handles\n");
113 return NULL;
114 }
115
116 if (storage_use_partitions)
117 file = part->partlabel;
118 else
119 file = part->actual;
120
121 pathlen = strlen(storage_dir) + strlen(file) + 2;
122 fspath = alloca(pathlen);
123 snprintf(fspath, pathlen, "%s/%s", storage_dir, file);
124 if (!storage_read_only) {
125 fd = open(fspath, O_RDWR);
126 if (fd < 0) {
127 saved_errno = errno;
128 fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
129 fspath, part->path, strerror(saved_errno));
130 errno = saved_errno;
131 return NULL;
132 }
133 rmtfd->fd = fd;
134 rmtfd->shadow_len = 0;
135 } else {
136 ret = storage_populate_shadow_buf(rmtfd, fspath);
137 if (ret < 0) {
138 saved_errno = errno;
139 fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
140 fspath, part->path, strerror(saved_errno));
141 errno = saved_errno;
142 return NULL;
143 }
144 }
145
146 rmtfd->node = node;
147 rmtfd->partition = part;
148
149 return rmtfd;
150}
151
152void storage_close(struct rmtfd *rmtfd)
153{
Amit Pundir53c12872022-10-27 21:55:51 +0530154 if (rmtfd->fd >= 0) {
155 close(rmtfd->fd);
156 rmtfd->fd = -1;
157 }
Amit Pundird477f822020-02-07 22:26:08 +0530158
159 free(rmtfd->shadow_buf);
160 rmtfd->shadow_buf = NULL;
161 rmtfd->shadow_len = 0;
162
163 rmtfd->partition = NULL;
164}
165
166struct rmtfd *storage_get(unsigned node, int caller_id)
167{
168 struct rmtfd *rmtfd;
169
170 if (caller_id >= MAX_CALLERS)
171 return NULL;
172
173 rmtfd = &rmtfds[caller_id];
174 if (rmtfd->node != node)
175 return NULL;
176
177 return rmtfd;
178}
179
180int storage_get_caller_id(const struct rmtfd *rmtfd)
181{
182 return rmtfd->id;
183}
184
185int storage_get_error(const struct rmtfd *rmtfd)
186{
187 return rmtfd->dev_error;
188}
189
190void storage_exit(void)
191{
192 int i;
193
Amit Pundir53c12872022-10-27 21:55:51 +0530194 for (i = 0; i < MAX_CALLERS; i++)
195 storage_close(&rmtfds[i]);
Amit Pundird477f822020-02-07 22:26:08 +0530196}
197
198ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset)
199{
200 ssize_t n;
201
202 if (!storage_read_only) {
203 n = pread(rmtfd->fd, buf, nbyte, offset);
204 } else {
Amit Pundir53c12872022-10-27 21:55:51 +0530205 n = MIN((ssize_t)nbyte, (ssize_t)rmtfd->shadow_len - offset);
Amit Pundird477f822020-02-07 22:26:08 +0530206 if (n > 0)
John Stultz0b3c9bb2020-03-03 06:35:48 +0000207 memcpy(buf, (char*)rmtfd->shadow_buf + offset, n);
Amit Pundird477f822020-02-07 22:26:08 +0530208 else
209 n = 0;
210 }
211
212 if (n < nbyte)
John Stultz0b3c9bb2020-03-03 06:35:48 +0000213 memset((char*)buf + n, 0, nbyte - n);
Amit Pundird477f822020-02-07 22:26:08 +0530214
215 return nbyte;
216}
217
218ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
219{
220 size_t new_len = offset + nbyte;
221 void *new_buf;
222
223 if (!storage_read_only)
224 return pwrite(rmtfd->fd, buf, nbyte, offset);
225
226 if (new_len >= STORAGE_MAX_SIZE) {
227 fprintf(stderr, "write to %zd bytes exceededs max size\n", new_len);
228 errno = -EINVAL;
229 return -1;
230 }
231
232 if (new_len > rmtfd->shadow_len) {
233 new_buf = realloc(rmtfd->shadow_buf, new_len);
234 if (!new_buf) {
235 errno = -ENOMEM;
236 return -1;
237 }
238
239 rmtfd->shadow_buf = new_buf;
240 rmtfd->shadow_len = new_len;
241 }
242
John Stultz0b3c9bb2020-03-03 06:35:48 +0000243 memcpy((char*)rmtfd->shadow_buf + offset, buf, nbyte);
Amit Pundird477f822020-02-07 22:26:08 +0530244
245 return nbyte;
246}
247
Amit Pundir53c12872022-10-27 21:55:51 +0530248int storage_sync(struct rmtfd *rmtfd)
249{
250 if (storage_read_only)
251 return 0;
252
253 return fdatasync(rmtfd->fd);
254}
255
Amit Pundird477f822020-02-07 22:26:08 +0530256static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file)
257{
258 ssize_t len;
259 ssize_t n;
260 void *buf;
261 int ret;
262 int fd;
263
264 fd = open(file, O_RDONLY);
265 if (fd < 0)
266 return -1;
267
268 len = lseek(fd, 0, SEEK_END);
269 if (len < 0) {
270 ret = -1;
271 goto err_close_fd;
272 }
273
274 lseek(fd, 0, SEEK_SET);
275
276 buf = calloc(1, len);
277 if (!buf) {
278 ret = -1;
279 goto err_close_fd;
280 }
281
282 n = read(fd, buf, len);
283 if (n < 0) {
284 ret = -1;
285 goto err_close_fd;
286 }
287
288 rmtfd->shadow_buf = buf;
289 rmtfd->shadow_len = n;
290
291 ret = 0;
292
293err_close_fd:
294 close(fd);
295
296 return ret;
297}