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

Annotation of /lbbs/src/data_file_mgr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Fri Nov 7 14:44:47 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.1: +18 -5 lines
Content type: text/x-csrc
Refine

1 sysadm 1.1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * data_file_mgr
4     * - Edit / Preview data files
5     *
6     * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7     */
8    
9     #include "bbs.h"
10     #include "bbs_cmd.h"
11     #include "common.h"
12     #include "data_file_mgr.h"
13     #include "editor.h"
14     #include "log.h"
15     #include "screen.h"
16     #include "str_process.h"
17     #include <ctype.h>
18     #include <errno.h>
19     #include <fcntl.h>
20     #include <stdio.h>
21     #include <stdlib.h>
22     #include <unistd.h>
23     #include <sys/mman.h>
24     #include <sys/stat.h>
25    
26     enum _data_file_mgr_constant_t
27     {
28     DATA_FILE_MAX_LEN = 1024 * 1024 * 4, // 4MB
29     };
30    
31     struct data_file_item_t
32     {
33     const char *const name;
34     const char *const path;
35     };
36     typedef struct data_file_item_t DATA_FILE_ITEM;
37    
38     static const DATA_FILE_ITEM data_file_list[] = {
39     {"进站欢迎", DATA_WELCOME},
40     {"离站告别", DATA_GOODBYE},
41     {"登陆错误", DATA_LOGIN_ERROR},
42     {"活动看板", DATA_ACTIVE_BOARD},
43     {"浏览帮助", DATA_READ_HELP},
44     {"编辑帮助", DATA_EDITOR_HELP},
45     };
46    
47     static const int data_file_cnt = sizeof(data_file_list) / sizeof(DATA_FILE_ITEM);
48    
49     int data_file_mgr(void *param)
50     {
51     char path[FILE_PATH_LEN];
52     int fd = -1;
53     struct stat sb;
54     void *p_data = NULL;
55     size_t len_data = 0;
56     EDITOR_DATA *p_editor_data = NULL;
57     long len_data_new = 0;
58     char *p_data_new = NULL;
59     long line_total;
60     long line_offsets[MAX_SPLIT_FILE_LINES];
61     char buf[3] = "";
62     int ch = 0;
63     int previewed = 0;
64     int i;
65    
66     clearscr();
67     moveto(1, 1);
68     prints("数据文件列表: ");
69    
70     for (i = 0; i < data_file_cnt; i++)
71     {
72     moveto(3 + i, 4);
73     prints("%2d. %s", i + 1, data_file_list[i].name);
74     }
75    
76     get_data(SCREEN_ROWS, 1, "请输入需要编辑的文件编号: ", buf, sizeof(buf), 2);
77     i = atoi(buf) - 1;
78     if (i < 0 || i >= data_file_cnt)
79     {
80     return REDRAW;
81     }
82    
83     snprintf(path, sizeof(path), "%s.user", data_file_list[i].path);
84     if ((fd = open(path, O_RDONLY)) < 0 &&
85     (fd = open(data_file_list[i].path, O_RDONLY)) < 0)
86     {
87     log_error("open(%s) error (%d)\n", data_file_list[i].path, errno);
88     return REDRAW;
89     }
90    
91     if (fstat(fd, &sb) < 0)
92     {
93     log_error("fstat(fd) error (%d)\n", errno);
94     goto cleanup;
95     }
96    
97     len_data = (size_t)sb.st_size;
98     p_data = mmap(NULL, len_data, PROT_READ, MAP_SHARED, fd, 0L);
99     if (p_data == MAP_FAILED)
100     {
101     log_error("mmap() error (%d)\n", errno);
102     goto cleanup;
103     }
104    
105     if (close(fd) < 0)
106     {
107     log_error("close(fd) error (%d)\n", errno);
108     fd = -1;
109     goto cleanup;
110     }
111     fd = -1;
112    
113     p_editor_data = editor_data_load(p_data);
114     if (p_editor_data == NULL)
115     {
116     log_error("editor_data_load(data) error\n");
117     goto cleanup;
118     }
119    
120     if (munmap(p_data, len_data) < 0)
121     {
122     log_error("munmap() error (%d)\n", errno);
123     p_data = NULL;
124     goto cleanup;
125     }
126     p_data = NULL;
127    
128     p_data_new = malloc(DATA_FILE_MAX_LEN);
129     if (p_data_new == NULL)
130     {
131     log_error("malloc(content) error: OOM\n");
132     goto cleanup;
133     }
134    
135     for (ch = 'E'; !SYS_server_exit;)
136     {
137     if (ch == 'E')
138     {
139     editor_display(p_editor_data);
140     previewed = 0;
141     }
142    
143     clearscr();
144     moveto(1, 1);
145     if (previewed)
146     {
147     prints("(S)保存, (P)预览, (C)取消 or (E)再编辑? [P]: ");
148     }
149     else
150     {
151     prints("(P)预览, (C)取消 or (E)再编辑? [P]: ");
152     }
153     iflush();
154    
155     ch = igetch_t(BBS_max_user_idle_time);
156     switch (toupper(ch))
157     {
158     case KEY_NULL:
159     case KEY_TIMEOUT:
160     goto cleanup;
161     case CR:
162     case 'P':
163     len_data_new = editor_data_save(p_editor_data, p_data_new, DATA_FILE_MAX_LEN);
164     if (len_data_new < 0)
165     {
166     log_error("editor_data_save() error\n");
167     goto cleanup;
168     }
169     line_total = split_data_lines(p_data_new, SCREEN_COLS, line_offsets, MAX_SPLIT_FILE_LINES, 1, NULL);
170     display_data(p_data_new, line_total, line_offsets, 1, display_file_key_handler, DATA_READ_HELP);
171     previewed = 1;
172     continue;
173     case 'S':
174     if (!previewed)
175     {
176     continue;
177     }
178     break;
179     case 'C':
180     clearscr();
181     moveto(1, 1);
182     prints("取消更改...");
183     press_any_key();
184     goto cleanup;
185     case 'E':
186     ch = 'E';
187     continue;
188     default: // Invalid selection
189     continue;
190     }
191    
192     break;
193     }
194    
195 sysadm 1.2 if (SYS_server_exit) // Do not save data on shutdown
196     {
197     goto cleanup;
198     }
199    
200 sysadm 1.1 if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640)) < 0)
201     {
202     log_error("open(%s) error (%d)\n", path, errno);
203     goto cleanup;
204     }
205    
206     if (write(fd, p_data_new, (size_t)len_data_new) < 0)
207     {
208     log_error("write(len=%ld) error (%d)\n", len_data_new, errno);
209     goto cleanup;
210     }
211    
212     if (close(fd) < 0)
213     {
214     log_error("close(fd) error (%d)\n", errno);
215     fd = -1;
216     goto cleanup;
217     }
218    
219 sysadm 1.2 // Make another copy of the data file so that the user editored copy will be kept after upgrade / reinstall
220     if ((fd = open(data_file_list[i].path, O_WRONLY | O_CREAT | O_TRUNC, 0640)) < 0)
221     {
222     log_error("open(%s) error (%d)\n", data_file_list[i].path, errno);
223     goto cleanup;
224     }
225    
226     if (write(fd, p_data_new, (size_t)len_data_new) < 0)
227 sysadm 1.1 {
228 sysadm 1.2 log_error("write(len=%ld) error (%d)\n", len_data_new, errno);
229 sysadm 1.1 goto cleanup;
230     }
231    
232 sysadm 1.2 if (close(fd) < 0)
233 sysadm 1.1 {
234 sysadm 1.2 log_error("close(fd) error (%d)\n", errno);
235     fd = -1;
236 sysadm 1.1 goto cleanup;
237     }
238 sysadm 1.2 fd = -1;
239 sysadm 1.1
240     clearscr();
241     moveto(1, 1);
242     prints("修改已完成,需要重新加载配置后才会生效...");
243     press_any_key();
244    
245     cleanup:
246     if (p_editor_data != NULL)
247     {
248     editor_data_cleanup(p_editor_data);
249     }
250    
251     if (p_data_new != NULL)
252     {
253     free(p_data_new);
254     }
255    
256     if (p_data != NULL && munmap(p_data, len_data) < 0)
257     {
258     log_error("munmap() error (%d)\n", errno);
259     }
260    
261     if (fd >= 0 && close(fd) < 0)
262     {
263     log_error("close(fd) error (%d)\n", errno);
264     }
265    
266     return REDRAW;
267     }

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