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

Annotation of /lbbs/src/file_loader.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19 - (hide annotations)
Tue Nov 4 14:30:44 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.18: +2 -2 lines
Content type: text/x-csrc
Call shmctl() on valid shmid only

1 sysadm 1.18 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * file_loader
4     * - shared memory based file loader
5     *
6     * Copyright (C) 2004-2025 by Leaflet <leaflet@leafok.com>
7     */
8 sysadm 1.1
9     #include "file_loader.h"
10 sysadm 1.15 #include "log.h"
11     #include "str_process.h"
12 sysadm 1.1 #include "trie_dict.h"
13 sysadm 1.15 #include <errno.h>
14 sysadm 1.1 #include <fcntl.h>
15     #include <stdlib.h>
16 sysadm 1.3 #include <string.h>
17     #include <time.h>
18 sysadm 1.15 #include <unistd.h>
19     #include <sys/ipc.h>
20 sysadm 1.1 #include <sys/mman.h>
21 sysadm 1.15 #include <sys/shm.h>
22 sysadm 1.1 #include <sys/stat.h>
23 sysadm 1.3
24 sysadm 1.8 struct shm_header_t
25     {
26     int shmid;
27     size_t data_len;
28     long line_total;
29     };
30    
31 sysadm 1.1 static TRIE_NODE *p_trie_file_dict = NULL;
32    
33 sysadm 1.3 int file_loader_init()
34 sysadm 1.1 {
35 sysadm 1.3 if (p_trie_file_dict != NULL)
36 sysadm 1.1 {
37     log_error("File loader already initialized\n");
38     return -1;
39     }
40    
41     p_trie_file_dict = trie_dict_create();
42     if (p_trie_file_dict == NULL)
43     {
44     log_error("trie_dict_create() error\n");
45     return -2;
46     }
47    
48     return 0;
49     }
50    
51 sysadm 1.6 static void trie_file_dict_cleanup_cb(const char *filename, int64_t value)
52 sysadm 1.1 {
53 sysadm 1.11 int shmid = (int)value;
54 sysadm 1.6
55 sysadm 1.19 if (shmid != 0 && shmctl(shmid, IPC_RMID, NULL) == -1)
56 sysadm 1.1 {
57 sysadm 1.6 log_error("shmctl(shmid=%d, IPC_RMID) error (%d)\n", shmid, errno);
58 sysadm 1.1 }
59 sysadm 1.3 }
60 sysadm 1.1
61 sysadm 1.3 void file_loader_cleanup(void)
62     {
63     if (p_trie_file_dict == NULL)
64 sysadm 1.1 {
65 sysadm 1.3 return;
66 sysadm 1.1 }
67    
68 sysadm 1.3 trie_dict_traverse(p_trie_file_dict, trie_file_dict_cleanup_cb);
69 sysadm 1.11 trie_dict_destroy(p_trie_file_dict);
70 sysadm 1.6
71     p_trie_file_dict = NULL;
72 sysadm 1.1 }
73    
74 sysadm 1.11 int load_file(const char *filename)
75 sysadm 1.1 {
76     int fd;
77     struct stat sb;
78     void *p_data;
79 sysadm 1.3 size_t data_len;
80     int proj_id;
81     key_t key;
82 sysadm 1.1 size_t size;
83 sysadm 1.3 int shmid;
84     void *p_shm;
85     long line_total;
86     long line_offsets[MAX_SPLIT_FILE_LINES];
87     long *p_line_offsets;
88 sysadm 1.6 int64_t shmid_old;
89 sysadm 1.1
90     if ((fd = open(filename, O_RDONLY)) < 0)
91     {
92     log_error("open(%s) error (%d)\n", filename, errno);
93     return -1;
94     }
95    
96     if (fstat(fd, &sb) < 0)
97     {
98     log_error("fstat(fd) error (%d)\n", errno);
99     return -1;
100     }
101    
102 sysadm 1.3 data_len = (size_t)sb.st_size;
103     p_data = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, 0L);
104 sysadm 1.1 if (p_data == MAP_FAILED)
105     {
106     log_error("mmap() error (%d)\n", errno);
107     return -2;
108     }
109    
110     if (close(fd) < 0)
111     {
112     log_error("close(fd) error (%d)\n", errno);
113     return -1;
114     }
115    
116 sysadm 1.16 line_total = split_data_lines(p_data, SCREEN_COLS, line_offsets, MAX_SPLIT_FILE_LINES, 1, NULL);
117 sysadm 1.1
118 sysadm 1.3 // Allocate shared memory
119     proj_id = (int)(time(NULL) % getpid());
120     key = ftok(filename, proj_id);
121     if (key == -1)
122     {
123     log_error("ftok(%s %d) error (%d)\n", filename, proj_id, errno);
124     return -2;
125     }
126 sysadm 1.1
127 sysadm 1.8 size = sizeof(struct shm_header_t) + data_len + 1 + sizeof(long) * (size_t)(line_total + 1);
128 sysadm 1.3 shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
129     if (shmid == -1)
130     {
131     log_error("shmget(size = %d) error (%d)\n", size, errno);
132     return -3;
133     }
134     p_shm = shmat(shmid, NULL, 0);
135     if (p_shm == (void *)-1)
136     {
137 sysadm 1.6 log_error("shmat(shmid=%d) error (%d)\n", shmid, errno);
138 sysadm 1.3 return -3;
139     }
140    
141 sysadm 1.8 ((struct shm_header_t *)p_shm)->shmid = shmid;
142     ((struct shm_header_t *)p_shm)->data_len = data_len;
143     ((struct shm_header_t *)p_shm)->line_total = line_total;
144 sysadm 1.17 memcpy((char *)p_shm + sizeof(struct shm_header_t), p_data, data_len);
145 sysadm 1.1
146 sysadm 1.3 if (munmap(p_data, data_len) < 0)
147     {
148     log_error("munmap() error (%d)\n", errno);
149     return -2;
150     }
151 sysadm 1.1
152 sysadm 1.17 p_data = (char *)p_shm + sizeof(struct shm_header_t);
153     p_line_offsets = (long *)((char *)p_data + data_len + 1);
154 sysadm 1.3 memcpy(p_line_offsets, line_offsets, sizeof(long) * (size_t)(line_total + 1));
155 sysadm 1.1
156 sysadm 1.11 if (shmdt(p_shm) == -1)
157 sysadm 1.9 {
158 sysadm 1.11 log_error("shmdt(shmid=%d) error (%d)\n", shmid, errno);
159 sysadm 1.9 return -3;
160     }
161    
162 sysadm 1.11 if (trie_dict_get(p_trie_file_dict, filename, &shmid_old) == 1)
163 sysadm 1.3 {
164     if (shmctl((int)shmid_old, IPC_RMID, NULL) == -1)
165 sysadm 1.1 {
166 sysadm 1.3 log_error("shmctl(shmid=%d, IPC_RMID) error (%d)\n", (int)shmid_old, errno);
167     return -2;
168 sysadm 1.1 }
169     }
170    
171 sysadm 1.11 if (trie_dict_set(p_trie_file_dict, filename, (int64_t)shmid) != 1)
172 sysadm 1.3 {
173     log_error("trie_dict_set(%s) error\n", filename);
174    
175 sysadm 1.19 if (shmid != 0 && shmctl(shmid, IPC_RMID, NULL) == -1)
176 sysadm 1.3 {
177     log_error("shmctl(shmid=%d, IPC_RMID) error (%d)\n", shmid, errno);
178     }
179 sysadm 1.1
180 sysadm 1.3 return -4;
181     }
182 sysadm 1.1
183     return 0;
184     }
185    
186 sysadm 1.11 int unload_file(const char *filename)
187 sysadm 1.1 {
188 sysadm 1.11 int64_t shmid;
189 sysadm 1.1
190 sysadm 1.11 if (trie_dict_get(p_trie_file_dict, filename, &shmid) != 1)
191 sysadm 1.1 {
192     log_error("trie_dict_get(%s) not found\n", filename);
193     return -1;
194     }
195    
196 sysadm 1.3 if (shmctl((int)shmid, IPC_RMID, NULL) == -1)
197 sysadm 1.1 {
198 sysadm 1.3 log_error("shmctl(shmid=%d, IPC_RMID) error (%d)\n", (int)shmid, errno);
199 sysadm 1.1 }
200    
201     if (trie_dict_del(p_trie_file_dict, filename) != 1)
202     {
203     log_error("trie_dict_del(%s) error\n", filename);
204     return -2;
205     }
206    
207     return 0;
208     }
209    
210 sysadm 1.11 const 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)
211 sysadm 1.1 {
212 sysadm 1.11 int64_t shmid;
213 sysadm 1.3 const void *p_shm;
214 sysadm 1.1
215 sysadm 1.3 if (p_trie_file_dict == NULL)
216 sysadm 1.1 {
217     log_error("File loader not initialized\n");
218     return NULL;
219     }
220    
221 sysadm 1.11 if (trie_dict_get(p_trie_file_dict, filename, &shmid) != 1) // Not exist
222 sysadm 1.1 {
223     log_error("trie_dict_get(%s) not found\n", filename);
224     return NULL;
225     }
226    
227 sysadm 1.11 p_shm = shmat((int)shmid, NULL, SHM_RDONLY);
228     if (p_shm == (void *)-1)
229     {
230     log_error("shmat(shmid=%d) error (%d)\n", (int)shmid, errno);
231     return NULL;
232     }
233    
234 sysadm 1.8 *p_data_len = ((struct shm_header_t *)p_shm)->data_len;
235     *p_line_total = ((struct shm_header_t *)p_shm)->line_total;
236 sysadm 1.17 *pp_data = (char *)p_shm + sizeof(struct shm_header_t);
237     *pp_line_offsets = (const long *)((const char *)(*pp_data) + *p_data_len + 1);
238 sysadm 1.3
239     return p_shm;
240 sysadm 1.1 }
241 sysadm 1.11
242     int detach_file_shm(const void *p_shm)
243     {
244     if (p_shm == NULL)
245     {
246     return -2;
247     }
248    
249     if (shmdt(p_shm) == -1)
250     {
251     log_error("shmdt() error (%d)\n", errno);
252     return -1;
253     }
254    
255     return 0;
256     }

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