blob: 3d2b076d7c32474d642c9a04cb0cfe6b216f24cf [file] [log] [blame]
w.deng15392b42025-06-16 15:34:57 +08001
mj.qu49441c22025-02-10 18:11:48 -08002#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <unistd.h>
6#include <fcntl.h>
7#include <errno.h>
w.deng82d2b052025-05-21 00:21:18 -07008#include "cfg_api.h"
mj.qu49441c22025-02-10 18:11:48 -08009
10#define BUFFER_SIZE (1024 * 20) // Define the buffer size for each read
11#define FIND_STR_LEN 128 // Define the length of the string to find
12#define FOTA_UPDATE_STATUS_FILE "/cache/zte_fota/update_status"
13
14// Custom memmem function
15static void* custom_memmem(const void* haystack, size_t haystack_len, const void* needle, size_t needle_len)
16{
17 if (needle_len == 0 || haystack_len < needle_len)
18 {
19 return NULL;
20 }
21
22 size_t i = 0;
23 const unsigned char* h = (const unsigned char*)haystack;
24 const unsigned char* n = (const unsigned char*)needle;
25
26 for (i = 0; i <= haystack_len - needle_len; ++i)
27 {
28 if (memcmp(h + i, n, needle_len) == 0)
29 {
30 return (void*)(h + i);
31 }
32 }
33
34 return NULL;
35}
36
37// Remove the last boundary marker from the file
38static int remove_last_boundary(const char *filename, const char *boundary_marker, int boundary_marker_len)
39{
40 int fd = open(filename, O_RDWR);
41 if (fd == -1)
42 {
43 perror("Unable to open file for reading and writing");
44 return 1;
45 }
46
47 // Get the file size
48 off_t file_size = lseek(fd, 0, SEEK_END);
49 if (file_size == -1)
50 {
51 perror("Unable to get file size");
52 close(fd);
53 return 1;
54 }
55
56 // Search for the boundary_marker from the end of the file
57 off_t search_start = file_size - FIND_STR_LEN;
58 if (search_start < 0)
59 {
60 search_start = 0;
61 }
62
63 lseek(fd, search_start, SEEK_SET);
64
65 char buffer[FIND_STR_LEN + 1]; // +1 for storing '\0'
66 int bytes_read = read(fd, buffer, FIND_STR_LEN);
67 if (bytes_read <= 0)
68 {
69 perror("Unable to read file");
70 close(fd);
71 return 1;
72 }
73 buffer[bytes_read] = '\0'; // Ensure the string is null-terminated
74
75 // Find the boundary_marker
76 char *boundary = custom_memmem(buffer, bytes_read, boundary_marker, boundary_marker_len);
77 if (boundary)
78 {
79 // Found boundary_marker, calculate the truncate position
80 off_t truncate_pos = search_start + (boundary - buffer);
81 if (ftruncate(fd, truncate_pos) == -1)
82 {
83 perror("Unable to truncate file");
84 close(fd);
85 return 1;
86 }
87 }
88
89 close(fd);
90 return 0;
91}
92
93// Function to handle file upload
94static int handle_file_upload(const char *source_filename, const char *target_filename, int content_length)
95{
96 char buffer[BUFFER_SIZE];
97 int bytes_read;
98 int target_fd = -1;
99 int source_fd = -1; // Source file descriptor
100 char *content_start_ptr = NULL;
101 int content_start = 0;
mj.quacba5cb2025-04-24 20:35:25 -0700102 const char *boundary_marker = "\r\n------"; // Boundary marker
mj.qu49441c22025-02-10 18:11:48 -0800103 int boundary_marker_len = strlen(boundary_marker);
104
105 // Open the target file
106 target_fd = open(target_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
107 if (target_fd == -1)
108 {
109 perror("Unable to open target file");
110 return 1;
111 }
112
113 // Open the source file
114 source_fd = open(source_filename, O_RDONLY);
115 if (source_fd == -1)
116 {
117 perror("Unable to open source file");
118 close(target_fd);
119 return 1;
120 }
121
122 // Read the request header to find the start position of file content
123 bytes_read = read(source_fd, buffer, BUFFER_SIZE);
124 if (bytes_read <= 0)
125 {
126 printf("Content-type: text/html\r\n\r\n");
127 printf("<h1>Error: Failed to read data</h1>");
128 printf("<p>Error number: %d - %s</p>", errno, strerror(errno));
129 close(target_fd);
130 close(source_fd);
131 return 1;
132 }
133
134 // Find the start position of the file content (usually after \r\n\r\n)
135 content_start_ptr = strstr(buffer, "\r\n\r\n");
136 if (!content_start_ptr)
137 {
138 printf("Content-type: text/html\r\n\r\n");
139 printf("<h1>Error: Unable to find the start position of file content</h1>");
140 close(target_fd);
141 close(source_fd);
142 return 1;
143 }
144
145 // Calculate the actual start position of the file content
146 content_start = content_start_ptr - buffer + 4;
147
148 // Write the first part of the file content
149 if (content_start < bytes_read)
150 {
151 if (write(target_fd, buffer + content_start, bytes_read - content_start) == -1)
152 {
153 perror("Unable to write to target file");
154 close(target_fd);
155 close(source_fd);
156 return 1;
157 }
158 }
159
160 // Update the remaining content length
161 content_length -= (bytes_read - content_start);
162
163 // Continue reading and writing the file in segments
164 while (content_length > 0)
165 {
166 bytes_read = read(source_fd, buffer, BUFFER_SIZE);
167 if (bytes_read <= 0)
168 {
169 // If reading is complete, normally break out of the loop
170 break;
171 }
172
173 // Write the file content
174 if (write(target_fd, buffer, bytes_read) == -1)
175 {
176 perror("Unable to write to target file");
177 close(target_fd);
178 close(source_fd);
179 return 1;
180 }
181
182 // Update the remaining content length
183 content_length -= bytes_read;
184 }
185
186 // Close file descriptors
187 close(target_fd);
188 close(source_fd);
189
190 // Remove the last boundary marker from the file
191 return remove_last_boundary(target_filename, boundary_marker, boundary_marker_len);
192}
193
194static int fota_is_file_exist(const char* path)
195{
196 if ( (path == NULL) || (*path == '\0') )
197 return 0;
198 if (access(path, R_OK) != 0)
199 return 0;
200
201 return 1;
202}
203
204static int fota_read_file(const char*path, char*buf, size_t sz)
205{
206 int fd = -1;
207 size_t cnt;
208
209 fd = open(path, O_RDONLY, 0);
210 if(fd < 0)
211 {
212 printf("fota_read_file failed to open %s: %s\n", path, strerror(errno));
213 cnt = -1;
214 return cnt;
215 }
216 cnt = read(fd, buf, sz - 1);
217 if(cnt <= 0)
218 {
219 printf("failed to read %s: %s\n", path, strerror(errno));
220 close(fd);
221 cnt = -1;
222 return cnt;
223 }
224 buf[cnt] = '\0';
225 if(buf[cnt - 1] == '\n')
226 {
227 cnt--;
228 buf[cnt] = '\0';
229 }
230 close(fd);
231
232 return cnt;
233}
234
235static int fota_read_file_int(const char* path, int *val)
236{
237 char buf[32];
238 char *end;
239 int ret;
240 int tmp;
241
242 ret = fota_read_file(path, buf, sizeof(buf));
243 if(ret < 0)
244 return -1;
245
246 errno = 0;
247 tmp = strtol(buf, &end, 0);
248 if (errno == ERANGE)
249 {
250 printf("strtol errno %d: %s\n", errno, strerror(errno));
251 }
252
253 if ((end == buf) || ((end < buf + sizeof(buf)) && (*end != '\0')))
254 {
255 return -1;
256 }
257
258 *val = tmp;
259
260 return 0;
261}
262
263static int fota_get_update_status(int *fota_status)
264{
265 int status = 0;
266 int ret = 0;
267 if(!fota_is_file_exist(FOTA_UPDATE_STATUS_FILE))
268 {
269 *fota_status = -1;
270 return -1;
271 }
272 ret = fota_read_file_int(FOTA_UPDATE_STATUS_FILE, &status);
273 if(ret < 0)
274 {
275 *fota_status = -1;
276 return -1;
277 }
278 *fota_status = status;
279 return 0;
280}
281
mj.qu290d6552025-02-11 22:34:46 -0800282static void print_json_response(int success, const char* message)
283{
284 printf("Content-type: application/json\r\n\r\n");
285 printf("{\"success\": %d, \"message\": \"%s\"}\n", success, message);
286}
287
mj.qu49441c22025-02-10 18:11:48 -0800288static void cgi_fota_update_progress()
289{
290 int upgradeStatus, result;
291
292 system("fota_upi -u verify > /dev/null 2>&1");
w.deng15392b42025-06-16 15:34:57 +0800293 sleep(1);
mj.qu290d6552025-02-11 22:34:46 -0800294 result = fota_get_update_status(&upgradeStatus);
295 if(result < 0)
296 {
w.deng82d2b052025-05-21 00:21:18 -0700297 cfg_set("fota_update_flag", "0");
mj.qu290d6552025-02-11 22:34:46 -0800298 print_json_response(0, "Fail to read update file");
299 }
300 else if(upgradeStatus != 0)
301 {
w.deng82d2b052025-05-21 00:21:18 -0700302 cfg_set("fota_update_flag", "0");
mj.qu290d6552025-02-11 22:34:46 -0800303 print_json_response(0, "Verify update file failed");
304 }
305 else
306 {
307 print_json_response(1, "File verification successful, start updating...");
mj.qu290d6552025-02-11 22:34:46 -0800308 system("fota_upi -u recovery > /dev/null 2>&1 &");
309 }
mj.qu49441c22025-02-10 18:11:48 -0800310}
311
312int main()
313{
mj.quc4b3b122025-02-12 23:53:45 -0800314 const char *source_filename = "/tmp/firmware_tmp_file"; // Source file path
mj.qu49441c22025-02-10 18:11:48 -0800315 const char *target_filename = "/cache/zte_fota/delta.package"; // Target file path
316 const char *content_length_str = NULL;
317 int content_length = 0;
318
319 system("rm -rf /cache/zte_fota");
320 system("mkdir -p /cache/zte_fota");
321
322 // Get environment variables
323 content_length_str = getenv("CONTENT_LENGTH");
324 if (!content_length_str)
325 {
mj.quc4b3b122025-02-12 23:53:45 -0800326 system("rm -rf /tmp/firmware_tmp_file");
mj.qu290d6552025-02-11 22:34:46 -0800327 print_json_response(0, "Missing CONTENT_LENGTH environment variable");
mj.qu49441c22025-02-10 18:11:48 -0800328 return 1;
329 }
330
331 content_length = atoi(content_length_str);
332 if (content_length <= 0)
333 {
mj.quc4b3b122025-02-12 23:53:45 -0800334 system("rm -rf /tmp/firmware_tmp_file");
mj.qu290d6552025-02-11 22:34:46 -0800335 print_json_response(0, "Invalid CONTENT_LENGTH");
mj.qu49441c22025-02-10 18:11:48 -0800336 return 1;
337 }
w.deng82d2b052025-05-21 00:21:18 -0700338 cfg_set("fota_update_flag", "1");
mj.qu49441c22025-02-10 18:11:48 -0800339 // Call the file upload handling function
340 if (handle_file_upload(source_filename, target_filename, content_length) != 0)
341 {
mj.quc4b3b122025-02-12 23:53:45 -0800342 system("rm -rf /tmp/firmware_tmp_file");
mj.qu290d6552025-02-11 22:34:46 -0800343 print_json_response(0, "File upload failed");
w.deng82d2b052025-05-21 00:21:18 -0700344 cfg_set("fota_update_flag", "0");
mj.qu49441c22025-02-10 18:11:48 -0800345 return 1;
346 }
347
348 // Output success information
mj.qu290d6552025-02-11 22:34:46 -0800349 //print_json_response(1, "File upload successful");
mj.quc4b3b122025-02-12 23:53:45 -0800350 system("rm -rf /tmp/firmware_tmp_file");
mj.qu49441c22025-02-10 18:11:48 -0800351
352 cgi_fota_update_progress();
353
mj.qu49441c22025-02-10 18:11:48 -0800354 return 0;
355}