1 /*
2 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3 */
4
5 #include "ulog_session_file.h"
6
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "aos/errno.h"
12 #include "aos/kernel.h"
13 #include "cJSON.h"
14 #include "uagent.h"
15 #include "ulog/ulog.h"
16 #include "ulog_api.h"
17
18 /**
19 * record the log files operating. Recover(reset or get) in reload_log_argu()
20 * used and count in write_log_line()
21 */
22 static uint32_t operating_file_offset = 0;
23 static uint32_t gu32_log_file_size = LOCAL_FILE_SIZE;
24 static char guc_logfile_path[ULOG_FILE_PATH_SIZE / 2] = { 0 };
25 /**
26 * indicates if log on fs feature initialized
27 *
28 */
29 static uint8_t session_fs_init = 0;
30
31 static uint8_t log_file_failed = 0;
32
33 #if ULOG_RESERVED_FS
34 static char *ulog_fs_tmp[ULOG_RESERVED_FS_SIZE] = { NULL };
35
36 static uint16_t tmp_queue_in = 0;
37 static uint16_t tmp_queue_out = 0;
38
39 static void stop_operating();
40
push_fs_tmp(const char * data,const unsigned short len)41 static int push_fs_tmp(const char *data, const unsigned short len)
42 {
43 int rc = -1;
44 if (NULL != data && len != 0 && ((tmp_queue_in + 1) % ULOG_RESERVED_FS_SIZE) != tmp_queue_out) {
45 if (NULL == ulog_fs_tmp[tmp_queue_in]) {
46 ulog_fs_tmp[tmp_queue_in] = (char *)aos_malloc(len + 1);
47 if (NULL != ulog_fs_tmp[tmp_queue_in]) {
48 memcpy(ulog_fs_tmp[tmp_queue_in], data, len);
49 ulog_fs_tmp[tmp_queue_in][len] = '\0';
50 tmp_queue_in = (tmp_queue_in + 1) % ULOG_RESERVED_FS_SIZE;
51 rc = 0;
52 }
53 }
54 }
55 return rc;
56 }
57
pop_fs_tmp(char * data,const unsigned short len)58 static int pop_fs_tmp(char *data, const unsigned short len)
59 {
60 int rc = -EINVAL;
61 if (NULL != data && len != 0) {
62 if (tmp_queue_in == tmp_queue_out) {
63 rc = -1;
64 } else {
65 if (NULL != ulog_fs_tmp[tmp_queue_out]) {
66 strncpy(data, ulog_fs_tmp[tmp_queue_out], len - 1);
67 aos_free(ulog_fs_tmp[tmp_queue_out]);
68 ulog_fs_tmp[tmp_queue_out] = NULL;
69 tmp_queue_out = (tmp_queue_out + 1) % ULOG_RESERVED_FS_SIZE;
70 rc = 0;
71
72 } else {
73 rc = -EIO;
74 }
75 }
76 }
77 return rc;
78 }
79 #endif
80
81 #if ULOG_UPLOAD_LOG_FILE
82 #include "httpclient.h"
83 #include "sys/socket.h"
84 static httpclient_t *httpc_handle = NULL;
85
86 static char *up_uri = NULL;
87 static bool http_client_initd = false;
88
get_server_uri(const char * url,char ** server,char ** uri)89 static int get_server_uri(const char *url, char **server, char **uri)
90 {
91 int rc = -1;
92 if (NULL != url) {
93 uint8_t pos = -1;
94 if (0 == strncmp(url, URL_PREFIX_HTTP, strlen(URL_PREFIX_HTTP))) {
95 pos = strlen(URL_PREFIX_HTTP);
96 } else if (0 == strncmp(url, URL_PREFIX_HTTPS, strlen(URL_PREFIX_HTTPS))) {
97 pos = strlen(URL_PREFIX_HTTPS);
98 }
99 if (pos > 0) {
100 char *p = NULL;
101 p = strchr(&url[pos], '/');
102 if (NULL != p) {
103 p++;
104 *server = (char *)aos_malloc(p - url + 1);
105 if (NULL != *server) {
106 memcpy(*server, url, p - url);
107 (*server)[p - url] = '\0';
108 const short n = strlen(p);
109 *uri = (char *)aos_malloc(n + 1);
110 if (NULL != *uri) {
111 memcpy(*uri, p, n);
112 (*uri)[n] = '\0';
113 rc = 0;
114 } else {
115 aos_free(*server);
116 *server = NULL;
117 }
118 }
119 }
120 }
121 }
122 return rc;
123 }
124
report_up_process(const http_upload_fail_t status,const char process,const ulog_idx_type idx)125 static void report_up_process(const http_upload_fail_t status, const char process, const ulog_idx_type idx)
126 {
127 cJSON *resp = cJSON_CreateObject();
128 if (NULL != resp) {
129 char *text = NULL;
130 cJSON_AddItemToObject(resp, "idx", cJSON_CreateNumber(idx));
131 if (status >= http_upload_start) {
132 cJSON_AddItemToObject(resp, "process", cJSON_CreateNumber(process));
133 } else {
134 cJSON_AddItemToObject(resp, "error", cJSON_CreateNumber(status));
135 }
136 text = cJSON_PrintUnformatted(resp);
137 cJSON_Delete(resp);
138 uagent_send(UAGENT_MOD_ULOG, ULOG_LOG_LIST, strlen(text), text, send_policy_object);
139 cJSON_free(text);
140 }
141 }
142
http_start(const char * url,const unsigned short idx)143 int http_start(const char *url, const unsigned short idx)
144 {
145 int rc = -1;
146 if (!http_client_initd) {
147 http_client_initd = true;
148 }
149
150 if (httpc_handle == NULL) {
151 LOGI(ULOG_TAG_SELF, "http start %s idx %d", url, idx);
152 httpc_handle = (httpclient_t *)aos_malloc(sizeof(httpclient_t));
153 if (NULL != httpc_handle) {
154 up_uri = (uint8_t *)aos_malloc(strlen(url));
155 if (NULL != up_uri) {
156 strncpy(up_uri, url, strlen(url));
157 char buf[16];
158 snprintf(buf, 16, "up idx=%d", idx);
159 rc = ulog_man(buf);
160 } else {
161 aos_free(httpc_handle);
162 httpc_handle = NULL;
163 }
164 } else {
165 LOGE(ULOG_TAG_SELF, "allock http connect instanse fail");
166 }
167 } else {
168 LOGE(ULOG_TAG_SELF, "Last upload not finish");
169 }
170 return rc;
171 }
172
173 static uint8_t *rsp_buf = NULL;
174 static uint8_t *req_buf = NULL;
on_fs_upload(const uint32_t idx,const uint32_t start)175 void on_fs_upload(const uint32_t idx, const uint32_t start)
176 {
177 if (get_working_from_cfg_mm() == idx) {
178 on_fs_record_pause(1, 0);
179 }
180 int fd = open_log_file(idx, O_RDONLY, 0);
181 http_upload_fail_t http_operate = http_upload_common_fail;
182 if (fd >= 0) {
183 char *customer_header = "Accept: text/xml,text/javascript,text/html,application/json\r\n";
184 httpclient_set_custom_header(httpc_handle, customer_header);
185 char *upload_stream = (char *)aos_malloc(gu32_log_file_size + ULOG_SIZE);
186 if (NULL != upload_stream) {
187 int n = -1;
188 n = aos_read(fd, upload_stream, gu32_log_file_size + ULOG_SIZE);
189 if (0 < n) {
190 char retry = HTTP_REQ_RETRY;
191 httpclient_data_t client_data = { 0 };
192 rsp_buf = (uint8_t *)aos_malloc(RSP_BUF_SIZE);
193 req_buf = (uint8_t *)aos_malloc(RSP_BUF_SIZE);
194 if (rsp_buf != NULL && req_buf != NULL) {
195 memset(req_buf, 0, sizeof(req_buf));
196 client_data.header_buf = req_buf;
197 client_data.header_buf_len = sizeof(req_buf);
198
199 memset(rsp_buf, 0, sizeof(rsp_buf));
200 client_data.response_buf = rsp_buf;
201 client_data.response_buf_len = sizeof(rsp_buf);
202
203 client_data.post_buf = upload_stream;
204 client_data.post_buf_len = n;
205 client_data.post_content_type = "text/plain";
206
207 while (HTTP_SUCCESS != httpclient_put(httpc_handle, up_uri, &client_data)) {
208 if (--retry <= 0) {
209 break;
210 } else {
211 LOGW(ULOG_TAG_SELF, "fs rqst %d fail", n);
212 aos_msleep(1000);
213 }
214 }
215 if (retry > 0) {
216 http_operate = http_upload_finish;
217 } else {
218 http_operate = http_upload_memory_fail;
219 }
220 }
221 } else {
222 http_operate = http_upload_text_empty;
223 LOGW(ULOG_TAG_SELF, "nothing read");
224 }
225 aos_free(upload_stream);
226 } else {
227 http_operate = http_upload_memory_fail;
228 LOGE(ULOG_TAG_SELF, "allocate file fail");
229 }
230 } else {
231 LOGE(ULOG_TAG_SELF, "http construct header fail");
232 }
233 aos_close(fd);
234
235 report_up_process(http_operate, http_operate == http_upload_finish ? 100 : 0, idx);
236
237 httpclient_clse(httpc_handle);
238 aos_free(rsp_buf);
239 rsp_buf = NULL;
240 aos_free(req_buf);
241 req_buf = NULL;
242 aos_free(up_uri);
243 up_uri = NULL;
244 aos_free(httpc_handle);
245 httpc_handle = NULL;
246 /* try re-start record, no impact even the record no abort before */
247 on_fs_record_pause(0, 1);
248 }
249
250 #endif
251
252 /**
253 *
254 * Check if file already exist
255 *
256 * @param file_idx file index to be checked
257 * @return true indicats it is existed, or else not.
258 */
log_file_exist(const uint16_t file_idx)259 static bool log_file_exist(const uint16_t file_idx)
260 {
261 bool rc = false;
262 char ulog_file_name[ULOG_FILE_PATH_SIZE] = { 0 };
263 int fd = -1;
264
265 if (file_idx <= LOCAL_FILE_CNT) {
266 snprintf(ulog_file_name, sizeof(ulog_file_name), ULOG_FILE_FORMAT, guc_logfile_path, file_idx);
267 fd = aos_open(ulog_file_name, (O_RDWR | O_CREAT | O_EXCL)
268 #ifdef CSP_LINUXHOST
269 , 0644
270 #endif
271 );
272 SESSION_FS_DEBUG("check if file %s exist %d\n", ulog_file_name, fd);
273
274 if (fd < 0) {
275 #ifdef CSP_LINUXHOST
276 if (EEXIST == errno) {
277 SESSION_FS_DEBUG("file %s alreay exist\n", ulog_file_name);
278 rc = true;
279 }
280 #else /* !CSP_LINUXHOST */
281 if (fd == -EEXIST) {
282 SESSION_FS_DEBUG("file %s alreay exist\n", ulog_file_name);
283 rc = true;
284 }
285 #endif /* CSP_LINUXHOST */
286 } else {
287 /*TODO:why not close*/
288 aos_close(fd);
289 aos_unlink(ulog_file_name);
290 }
291 }
292 return rc;
293 }
294
open_create_log_file(const ulog_idx_type file_idx,const bool keep_open)295 static int open_create_log_file(const ulog_idx_type file_idx, const bool keep_open)
296 {
297 int fd = -1;
298 char ulog_file_name[ULOG_FILE_PATH_SIZE] = { 0 };
299
300 snprintf(ulog_file_name, sizeof(ulog_file_name), ULOG_FILE_FORMAT, guc_logfile_path, file_idx);
301 SESSION_FS_DEBUG("open create log %s\n", ulog_file_name);
302 aos_unlink(ulog_file_name);
303 fd = aos_open(ulog_file_name, (O_RDWR | O_CREAT | O_TRUNC)
304 #ifdef CSP_LINUXHOST
305 ,
306 0644
307 #endif
308 );
309 if (fd >= 0) {
310 if (!keep_open) {
311 aos_close(fd);
312 }
313 } else {
314 SESSION_FS_INFO("open create file %s fail fd %d, errno %d\n", ulog_file_name, fd, errno);
315 }
316 return fd;
317 }
318
open_log_file(const ulog_idx_type file_idx,int flag,const off_t off)319 int open_log_file(const ulog_idx_type file_idx, int flag, const off_t off)
320 {
321 int fd = -1;
322 char ulog_file_name[ULOG_FILE_PATH_SIZE];
323 memset(ulog_file_name, 0, sizeof(ulog_file_name));
324 snprintf(ulog_file_name, sizeof(ulog_file_name), ULOG_FILE_FORMAT, guc_logfile_path, file_idx);
325 fd = aos_open(ulog_file_name, flag);
326 if (fd >= 0) {
327 const int seek_off = aos_lseek(fd, off, SEEK_SET);
328 if (seek_off != off) {
329 SESSION_FS_INFO("seek fail %s %d\n", ulog_file_name, seek_off);
330 aos_close(fd);
331 fd = -1;
332 }
333 } else {
334 SESSION_FS_INFO("open %s flag %d fail fd %d\n", ulog_file_name, flag, fd);
335 }
336 return fd;
337 }
338
339 /**
340 *
341 * Copies one line from file_instanse into buf, On sucessful the destination buf
342 * buf is changed into NULL terminated C String. If log content size is longer
343 * than buf_len-1, remain will be not saved and NULL terminatated is implicitly
344 * appended at the end of destination.
345 *
346 * @param file_instanse file description from aos_open() before
347 * @param buf local buffer use for saved, ZERO format is not MUST
348 * @param buf_len buffer size
349 * @return actual log text length readed in argumenent buf;
350 * '\n',' is counted. Expected value: 1~buf_len-1
351 * 0 indicates EOF of the file, buf_len indicates the possible passing
352 * value is limited to read the whole line.
353 */
get_log_line(const int fd,char * buf,const uint16_t buf_len)354 int get_log_line(const int fd, char *buf, const uint16_t buf_len)
355 {
356 int rc = -1;
357 int cnt = 0;
358
359 if (fd < 0 || NULL == buf || buf_len <= 0) {
360 return -1;
361 }
362
363 memset(buf, 0, buf_len);
364 while ((cnt < buf_len) && (0 < aos_read(fd, &buf[cnt], 1))) {
365 if (buf[cnt] == LOG_LINE_SEPARATOR) {
366 break;
367 }
368 cnt++;
369 }
370
371 if (cnt == 0) {
372 /* Nothing read, this is an empty file */
373 rc = 0;
374 } else if (cnt < buf_len) {
375 if (buf[cnt - 1] == LOG_LINE_SEPARATOR) {
376 /* replacement/end with null terminated */
377 buf[cnt - 1] = 0;
378 } else {
379 buf[cnt] = 0;
380 }
381 rc = cnt;
382
383 } else { /* cnt == buf_len */
384 /* two possible result */
385 /* buffer len is just fit */
386 /* buffer is not sufficient to save whole line,
387 last characher will be missed and replace of null-terminated */
388 rc = cnt;
389
390 /* replacement with null terminated */
391 buf[cnt - 1] = 0;
392 }
393
394 return rc;
395 }
396
397 /**
398 *
399 * Write one line into specify log file, which instance is file_instanse. Append
400 * a LOG_LINE_SEPARATOR after log context to separate logs
401 *
402 * @param file_instanse file description from aos_open() before
403 * @param buf local buffer use for write
404 * @param keep_open keep opening after write finished
405 * @param operating indicates the rolling-back mechanism used.
406 * @return actual writen text length(includes length of LOG_LINE_SEPARATOR).
407 * -EINVAL indicates parameter illegal, other value indicates call
408 * aos_write failure
409 */
write_log_line(const int file_instanse,const char * buf,const bool keep_open)410 int write_log_line(const int file_instanse, const char *buf, const bool keep_open)
411 {
412 int rtn = -EINVAL;
413 if (file_instanse >= 0 && buf != NULL) {
414 int rc = -1;
415 rtn = aos_write(file_instanse, buf, strlen(buf));
416 if (rtn > 0) {
417 rc = aos_write(file_instanse, LOG_LINE_END_STR, 1);
418 if (1 == rc) {
419 rtn++;
420 } else {
421 rtn = rc;
422 }
423 aos_sync(file_instanse);
424 } else {
425 SESSION_FS_INFO("write fail rc %d\n", rtn);
426 }
427
428 if (!keep_open) {
429 aos_close(file_instanse);
430 }
431 }
432
433 return rtn;
434 }
435
436 /**
437 *
438 * Refresh ulog cfg item and saved in cfg file, also create the new ulog file
439 *
440 *
441 * @return 0 indicates create new log file sucessfully, but not means update
442 * config pass; -1 create new log file fail
443 */
update_new_log_file(const ulog_idx_type idx)444 static int update_new_log_file(const ulog_idx_type idx)
445 {
446 int rc = -1;
447 int fd = -1;
448
449 if (0 == update_mm_cfg(ulog_cfg_type_working, idx, ulog_cfg_para_none, NULL)) {
450 /* read it for test */
451 if (get_working_from_cfg_mm() == idx) {
452 /* create log file */
453 if (open_create_log_file(idx, false) >= 0) {
454 rc = 0;
455 char time_start[24];
456
457 ulog_format_time(time_start, sizeof(time_start));
458
459 update_mm_cfg(ulog_cfg_type_list, idx, ulog_cfg_para_start, time_start);
460 fd = open_create_log_file(ULOG_FILE_CFG_IDX, true);
461
462 if (fd >= 0) { /* need update cfg file */
463 if (0 != cfg_mm_2_file(fd)) {
464 /* sync to cfg file fail, have no impact unless the
465 * board boot-up before it sync write */
466 SESSION_FS_INFO("sync to cfg file fail %d\n", fd);
467 }
468 aos_close(fd);
469 } else {
470 SESSION_FS_INFO("refresh ulog cfg fail fd %d\n", fd);
471 }
472
473 } else {
474 SESSION_FS_INFO("sync to cfg file fail %d\n", fd);
475 }
476 } else {
477 SESSION_FS_INFO("Fatal Error Operate ulog mm cfg\n");
478 }
479 } else {
480 SESSION_FS_INFO("Fatal Error update ulog mm cfg\n");
481 }
482
483 return rc;
484 }
485
486 /**
487 *
488 * Reload log history arguments from ulog cfg file(ulog_000.log) in fs,
489 * includes operating_file_idx & operating_file_offset. New ulog_000.log
490 * will be created if none ulog_000.log found or text is illegal.
491 * This is vital for ulog pop via fs, ulog pop via fs will be forbidden if
492 * this step fail.
493 *
494 * return 0 if this step pass, else indicates this step fail
495 *
496 */
reload_log_argu()497 static int reload_log_argu()
498 {
499 int rc = -1;
500 struct aos_stat st_logstat = { 0 };
501 char ulog_file_name[ULOG_FILE_PATH_SIZE] = { 0 };
502 ulog_idx_type tmp_idx = ULOG_FILE_IDX_INVALID;
503
504 operating_file_offset = 0;
505
506 if (log_file_exist(ULOG_FILE_CFG_IDX)) {
507 /* ulog cfg exist, try to read it */
508 load_cfg_2_mm();
509 tmp_idx = get_working_from_cfg_mm();
510
511 SESSION_FS_INFO("[%s]log file idx %d\n", ULOG_TAG_SELF, tmp_idx);
512 if (tmp_idx <= LOCAL_FILE_CNT) {
513 snprintf(ulog_file_name, sizeof(ulog_file_name), ULOG_FILE_FORMAT, guc_logfile_path, tmp_idx);
514 rc = aos_stat(ulog_file_name, &st_logstat);
515 if (rc == 0) {
516 operating_file_offset += st_logstat.st_size;
517 } else {
518 /* no such log file exist, then create it */
519 rc = update_new_log_file(tmp_idx);
520 }
521 }
522 }
523
524 if (LOCAL_FILE_CNT < tmp_idx) {
525 rc = update_new_log_file(ULOG_FILE_IDX_START);
526 }
527
528 return rc;
529 }
530
on_show_ulog_file()531 void on_show_ulog_file()
532 {
533 aos_dir_t *dp;
534 SESSION_FS_INFO("log files in %s\n", guc_logfile_path);
535 dp = (aos_dir_t *)aos_opendir(guc_logfile_path);
536
537 if (dp != NULL) {
538 aos_dirent_t *out_dirent;
539 while (1) {
540 out_dirent = (aos_dirent_t *)aos_readdir(dp);
541 if (out_dirent != NULL) {
542 SESSION_FS_INFO("file name is %s\n", out_dirent->d_name);
543 } else {
544 break;
545 }
546 }
547 }
548 aos_closedir(dp);
549 }
550
stop_operating()551 static void stop_operating()
552 {
553 char time_stop[24];
554
555 ulog_format_time(time_stop, sizeof(time_stop));
556 update_mm_cfg(ulog_cfg_type_list, get_working_from_cfg_mm(), ulog_cfg_para_end, time_stop);
557 }
558
write_fail_retry()559 static void write_fail_retry()
560 {
561 int8_t retry = ULOG_FILE_FAIL_COUNT;
562 char log_file_name[ULOG_FILE_PATH_SIZE];
563 char buf[ULOG_SIZE];
564
565 log_file_failed++;
566 if (log_file_failed >= ULOG_FILE_FAIL_COUNT) {
567 snprintf(log_file_name, ULOG_FILE_PATH_SIZE, ULOG_FILE_FORMAT, guc_logfile_path, get_working_from_cfg_mm());
568 while (0 != aos_unlink(log_file_name)) {
569 if (--retry <= 0) {
570 SESSION_FS_INFO("file %s error on remove, retry %d\n", log_file_name, retry);
571 break;
572 }
573 }
574
575 if (retry > 0) {
576 SESSION_FS_INFO("remove file %s, then create new one %d\n", log_file_name, get_working_from_cfg_mm());
577 if (0 == update_new_log_file(get_working_from_cfg_mm())) {
578 #if ULOG_RESERVED_FS
579 memset(buf, 0, ULOG_SIZE);
580 while (0 == pop_fs_tmp(buf, ULOG_SIZE)) {
581 pop_out_on_fs(buf, strlen(buf));
582 memset(buf, 0, ULOG_SIZE);
583 }
584 #endif /* ULOG_RESERVED_FS */
585 }
586 }
587 }
588 }
589
590 /**
591 * @brief not thread-safe, but only be used in one task(ulog), so not necessary
592 * considering mutex
593 * @param data
594 * @param len
595 *
596 * @return -1 indicates not send out sucessfully
597 *
598 */
pop_out_on_fs(const char * data,const uint16_t len)599 int32_t pop_out_on_fs(const char *data, const uint16_t len)
600 {
601 int32_t rc = -1;
602 int fd = 0;
603 int write_rlt = 0;
604 ulog_idx_type idx = ULOG_FILE_IDX_INVALID;
605
606 idx = get_working_from_cfg_mm();
607 if (idx > LOCAL_FILE_CNT) {
608 SESSION_FS_INFO("fail to get working log file idx %d update working cfg\n", idx);
609 rc = reload_log_argu();
610 if (rc < 0) {
611 SESSION_FS_INFO("fail to pop log to fs for reload log cfg fail \n");
612 return -1;
613 }
614 /*this time idx will be fine not need to check*/
615 idx = get_working_from_cfg_mm();
616 }
617
618 fd = open_log_file(idx, O_WRONLY, operating_file_offset);
619 if (fd < 0) {
620 SESSION_FS_INFO(
621 "fail to pop log to fs for open working log file %d offset fail %d "
622 "\n",
623 idx, operating_file_offset, errno);
624 rc = -1;
625 #if ULOG_RESERVED_FS
626 rc = push_fs_tmp(data, len);
627 if (0 != rc) {
628 SESSION_FS_INFO("*(%d)", rc);
629 }
630 return rc;
631 #endif
632 }
633
634 write_rlt = write_log_line(fd, data, true);
635 aos_sync(fd);
636 aos_close(fd);
637 if (write_rlt < 0) {
638 SESSION_FS_INFO("write fail %d retry %d\n", write_rlt, log_file_failed);
639 rc = -1;
640 #if ULOG_RESERVED_FS
641 /* save them temporary */
642 rc = push_fs_tmp(data, len);
643 if (0 != rc) {
644 SESSION_FS_INFO("*(%d)", rc);
645 }
646 #endif /* ULOG_RESERVED_FS */
647 /* check fail count */
648 write_fail_retry();
649 return rc;
650 }
651
652 log_file_failed = 0;
653 operating_file_offset += write_rlt;
654 if (operating_file_offset >= gu32_log_file_size) {
655 stop_operating();
656
657 /* roll back if working index reaches end */
658 idx++;
659 if (idx > LOCAL_FILE_CNT) {
660 idx = ULOG_FILE_IDX_START;
661 }
662 operating_file_offset = 0;
663 rc = update_new_log_file(idx);
664 if (rc) {
665 SESSION_FS_INFO("creat new log file %d fail %d in pop to fs\n", idx, rc);
666 }
667 }
668
669 return 0;
670 }
671
on_fs_record_pause(const uint32_t on,const uint32_t off)672 void on_fs_record_pause(const uint32_t on, const uint32_t off)
673 {
674 if ((on ^ off) == 0) {
675 return;
676 }
677
678 SESSION_FS_INFO(ULOG_TAG_SELF, "ulog fs ctrl on %d off %d\n", on, off);
679 if (1 == on) {
680 stop_operating();
681 } else { /* resume the file record */
682 if (0 == reload_log_argu()) {
683 LOGI(ULOG_TAG_SELF, "reload ulog idx %d off %d", get_working_from_cfg_mm(), operating_file_offset);
684 #if ULOG_RESERVED_FS
685 char buf[ULOG_SIZE];
686 memset(buf, 0, ULOG_SIZE);
687 while (0 == pop_fs_tmp(buf, ULOG_SIZE)) {
688 pop_out_on_fs(buf, strlen(buf));
689 memset(buf, 0, ULOG_SIZE);
690 }
691 #endif
692 } else {
693 LOGE(ULOG_TAG_SELF, "restart ulog fs fail");
694 }
695 }
696 }
697
fs_control_cli(const char cmd,const char * param)698 void fs_control_cli(const char cmd, const char *param)
699 {
700 if (param != NULL) {
701 switch (cmd) {
702 case 't':
703 {
704 int control_cmd = strtoul(param, NULL, 10);
705 if (control_cmd) {
706 ulog_man("fspause on=1");
707 } else {
708 ulog_man("fspause off=1");
709 }
710 break;
711 }
712 default:
713 break;
714 }
715 }
716 }
717
ulog_fs_log_file_size(unsigned int filesize)718 int ulog_fs_log_file_size(unsigned int filesize)
719 {
720 if (filesize < ULOG_SIZE) {
721 return -1;
722 }
723
724 gu32_log_file_size = filesize;
725 return 0;
726 }
727
ulog_fs_log_file_path(char * filepath)728 int ulog_fs_log_file_path(char *filepath)
729 {
730 size_t len = 0;
731 size_t max_len = 0;
732 int ret = 0;
733 aos_dir_t *pstdir = NULL;
734 bool is_last_char_slash = false;
735
736 if (NULL == filepath) {
737 return -1;
738 }
739
740 len = strlen(filepath);
741 /*we need to reserve one byte for /0 and one byte for / */
742 max_len = (ULOG_FILE_PATH_SIZE / 2) - 1;
743 if (len > max_len) {
744 SESSION_FS_INFO("log file path length %d over size %d", len, max_len - 1);
745 return -1;
746 }
747 memset(guc_logfile_path, 0, sizeof(guc_logfile_path));
748 memcpy(guc_logfile_path, filepath, len);
749
750 /*remove / at first to make dir ,then and / */
751 is_last_char_slash = (filepath[len - 1] == '/');
752 if (is_last_char_slash) {
753 guc_logfile_path[len - 1] = 0;
754 }
755
756 /*check logfile path exist */
757 pstdir = aos_opendir(guc_logfile_path);
758 if (NULL == pstdir) {
759 /*log file path doesn't exist , creat it*/
760 ret = aos_mkdir(guc_logfile_path);
761 if (ret) {
762 SESSION_FS_INFO("%s %d log dir path %s doesn't exist and mkdir fail %d \r\n", __FILE__, __LINE__,
763 guc_logfile_path, ret);
764 goto finish;
765 }
766 } else {
767 aos_closedir(pstdir);
768 }
769
770 finish:
771 /*and / for log file process*/
772 if (is_last_char_slash) {
773 guc_logfile_path[len - 1] = '/';
774 }
775
776 return ret;
777 }
778
779 /**
780 * @brief ulog on fs init
781 *
782 * @return 0 indicates initialized sucessfully, or else fail
783 *
784 */
ulog_fs_init()785 int32_t ulog_fs_init()
786 {
787 int32_t rc = -1;
788 if (0 == session_fs_init) {
789 session_fs_init = 1;
790 cfg_init_mutex();
791 ulog_fs_log_file_path(ULOG_DEAULT_FS_PATH);
792 rc = reload_log_argu();
793 if (rc == 0) {
794 SESSION_FS_INFO("reload ulog idx %d len %d \n", get_working_from_cfg_mm(), operating_file_offset);
795 }
796 }
797 return rc;
798 }
799