/[LeafOK_CVS]/lbbs/src/file_loader.c
ViewVC logotype

Contents of /lbbs/src/file_loader.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.22 - (show annotations)
Wed Nov 19 03:12:58 2025 UTC (3 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.21: +96 -112 lines
Content type: text/x-csrc
Use POSIX shared object instead of SysV shared segment in file_loader

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * file_loader
4 * - shared memory based file loader
5 *
6 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "file_loader.h"
14 #include "log.h"
15 #include "str_process.h"
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #include <unistd.h>
22 #include <sys/mman.h>
23 #include <sys/stat.h>
24
25 struct shm_header_t
26 {
27 size_t shm_size;
28 size_t data_len;
29 long line_total;
30 };
31
32 int load_file(const char *filename)
33 {
34 char filepath[FILE_PATH_LEN];
35 int fd;
36 struct stat sb;
37 void *p_data;
38 size_t data_len;
39 size_t size;
40 void *p_shm;
41 long line_total;
42 long line_offsets[MAX_SPLIT_FILE_LINES];
43 long *p_line_offsets;
44
45 if (filename == NULL)
46 {
47 log_error("NULL pointer error\n");
48 return -1;
49 }
50
51 if ((fd = open(filename, O_RDONLY)) < 0)
52 {
53 log_error("open(%s) error (%d)\n", filename, errno);
54 return -1;
55 }
56
57 if (fstat(fd, &sb) < 0)
58 {
59 log_error("fstat(fd) error (%d)\n", errno);
60 close(fd);
61 return -1;
62 }
63
64 data_len = (size_t)sb.st_size;
65 p_data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, 0L);
66 if (p_data == MAP_FAILED)
67 {
68 log_error("mmap() error (%d)\n", errno);
69 close(fd);
70 return -2;
71 }
72
73 if (close(fd) < 0)
74 {
75 log_error("close(fd) error (%d)\n", errno);
76 return -1;
77 }
78
79 line_total = split_data_lines(p_data, SCREEN_COLS, line_offsets, MAX_SPLIT_FILE_LINES, 1, NULL);
80
81 // Allocate shared memory
82 size = sizeof(struct shm_header_t) + data_len + 1 + sizeof(long) * (size_t)(line_total + 1);
83
84 if (unload_file(filename) < 0)
85 {
86 return -2;
87 }
88
89 strncpy(filepath, filename, sizeof(filepath) - 1);
90 filepath[sizeof(filepath) - 1] = '\0';
91
92 if ((fd = shm_open(basename(filepath), O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
93 {
94 log_error("shm_open(%s) error (%d)\n", basename(filepath), errno);
95 return -2;
96 }
97 if (ftruncate(fd, (off_t)size) == -1)
98 {
99 log_error("ftruncate(size=%d) error (%d)\n", size, errno);
100 close(fd);
101 return -2;
102 }
103
104 p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
105 if (p_shm == MAP_FAILED)
106 {
107 log_error("mmap() error (%d)\n", errno);
108 close(fd);
109 return -2;
110 }
111
112 if (close(fd) < 0)
113 {
114 log_error("close(fd) error (%d)\n", errno);
115 return -1;
116 }
117
118 ((struct shm_header_t *)p_shm)->shm_size = size;
119 ((struct shm_header_t *)p_shm)->data_len = data_len;
120 ((struct shm_header_t *)p_shm)->line_total = line_total;
121 memcpy((char *)p_shm + sizeof(struct shm_header_t), p_data, data_len);
122
123 if (munmap(p_data, data_len) < 0)
124 {
125 log_error("munmap() error (%d)\n", errno);
126 munmap(p_shm, size);
127 return -2;
128 }
129
130 p_data = (char *)p_shm + sizeof(struct shm_header_t);
131 p_line_offsets = (long *)((char *)p_data + data_len + 1);
132 memcpy(p_line_offsets, line_offsets, sizeof(long) * (size_t)(line_total + 1));
133
134 if (munmap(p_shm, size) < 0)
135 {
136 log_error("munmap() error (%d)\n", errno);
137 return -2;
138 }
139
140 return 0;
141 }
142
143 int unload_file(const char *filename)
144 {
145 char filepath[FILE_PATH_LEN];
146
147 if (filename == NULL)
148 {
149 log_error("NULL pointer error\n");
150 return -1;
151 }
152
153 strncpy(filepath, filename, sizeof(filepath) - 1);
154 filepath[sizeof(filepath) - 1] = '\0';
155
156 if (shm_unlink(basename(filepath)) == -1 && errno != ENOENT)
157 {
158 log_error("shm_unlink(%s) error (%d)\n", basename(filepath), errno);
159 return -2;
160 }
161
162 return 0;
163 }
164
165 void *get_file_shm_readonly(const char *filename, size_t *p_data_len, long *p_line_total, const void **pp_data, const long **pp_line_offsets)
166 {
167 char filepath[FILE_PATH_LEN];
168 int fd;
169 void *p_shm = NULL;
170 struct stat sb;
171 size_t size;
172
173 if (filename == NULL || p_data_len == NULL || p_line_total == NULL || pp_data == NULL || pp_line_offsets == NULL)
174 {
175 log_error("NULL pointer error\n");
176 return NULL;
177 }
178
179 strncpy(filepath, filename, sizeof(filepath) - 1);
180 filepath[sizeof(filepath) - 1] = '\0';
181
182 if ((fd = shm_open(basename(filepath), O_RDONLY, 0600)) == -1)
183 {
184 log_error("shm_open(%s) error (%d)\n", basename(filepath), errno);
185 return NULL;
186 }
187
188 if (fstat(fd, &sb) < 0)
189 {
190 log_error("fstat(fd) error (%d)\n", errno);
191 close(fd);
192 return NULL;
193 }
194
195 size = (size_t)sb.st_size;
196
197 p_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0L);
198 if (p_shm == MAP_FAILED)
199 {
200 log_error("mmap() error (%d)\n", errno);
201 close(fd);
202 return NULL;
203 }
204
205 if (close(fd) < 0)
206 {
207 log_error("close(fd) error (%d)\n", errno);
208 return NULL;
209 }
210
211 if (((struct shm_header_t *)p_shm)->shm_size != size)
212 {
213 log_error("Shared memory size mismatch (%ld != %ld)\n", ((struct shm_header_t *)p_shm)->shm_size, size);
214 munmap(p_shm, size);
215 return NULL;
216 }
217
218 *p_data_len = ((struct shm_header_t *)p_shm)->data_len;
219 *p_line_total = ((struct shm_header_t *)p_shm)->line_total;
220 *pp_data = (char *)p_shm + sizeof(struct shm_header_t);
221 *pp_line_offsets = (const long *)((const char *)(*pp_data) + *p_data_len + 1);
222
223 return p_shm;
224 }
225
226 int detach_file_shm(void *p_shm)
227 {
228 size_t size;
229
230 if (p_shm == NULL)
231 {
232 return -1;
233 }
234
235 size = ((struct shm_header_t *)p_shm)->shm_size;
236
237 if (munmap(p_shm, size) < 0)
238 {
239 log_error("munmap() error (%d)\n", errno);
240 return -2;
241 }
242
243 return 0;
244 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1