log_file.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * Bernard the first version
  9. * 2013-06-26 Grissiom refactor
  10. */
  11. #include <rtthread.h>
  12. #include <log_trace.h>
  13. #ifdef RT_USING_DFS
  14. #include <dfs_posix.h>
  15. struct file_device
  16. {
  17. struct rt_device parent;
  18. int fd;
  19. char *filename;
  20. };
  21. /* file device for log trace */
  22. static struct file_device _file_device;
  23. /* common device interface */
  24. static rt_err_t fdevice_open(rt_device_t dev, rt_uint16_t oflag)
  25. {
  26. int fd;
  27. struct file_device *fdev = (struct file_device *)dev;
  28. if (fdev->fd >= 0)
  29. return -RT_EBUSY;
  30. /* test and open */
  31. fd = open(fdev->filename, O_RDONLY, 0);
  32. if (fd >= 0)
  33. {
  34. close(fd);
  35. fd = open(fdev->filename, O_WRONLY | O_APPEND, 0);
  36. }
  37. else
  38. {
  39. /* file not exists */
  40. fd = open(fdev->filename, O_WRONLY | O_CREAT, 0);
  41. }
  42. fdev->fd = fd;
  43. return RT_EOK;
  44. }
  45. static rt_err_t fdevice_close(rt_device_t dev)
  46. {
  47. rt_err_t result;
  48. struct file_device *fdev = (struct file_device *)dev;
  49. if (fdev->fd < 0)
  50. return -RT_EBUSY;
  51. result = close(fdev->fd);
  52. if (result == 0)
  53. {
  54. fdev->fd = -1;
  55. }
  56. return result;
  57. }
  58. static rt_size_t fdevice_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  59. {
  60. struct file_device *fdev = (struct file_device *)dev;
  61. if (fdev->fd < 0)
  62. return 0;
  63. return write(fdev->fd, buffer, size);
  64. }
  65. static rt_err_t fdevice_control(rt_device_t dev, int cmd, void *arg)
  66. {
  67. struct file_device *fdev = (struct file_device *)dev;
  68. if (fdev->fd < 0)
  69. return 0;
  70. switch (cmd)
  71. {
  72. case LOG_TRACE_CTRL_FLUSH:
  73. if (fsync(fdev->fd) != 0)
  74. return RT_ERROR;
  75. break;
  76. default:
  77. break;
  78. }
  79. return RT_EOK;
  80. }
  81. #ifdef RT_USING_DEVICE_OPS
  82. const static struct rt_device_ops log_trace_ops =
  83. {
  84. RT_NULL,
  85. fdevice_open,
  86. fdevice_close,
  87. RT_NULL,
  88. fdevice_write,
  89. fdevice_control
  90. };
  91. #endif
  92. void log_trace_file_init(const char *filename)
  93. {
  94. rt_device_t device;
  95. device = rt_device_find("logfile");
  96. if (device == RT_NULL)
  97. {
  98. rt_memset(&_file_device, 0x00, sizeof(_file_device));
  99. _file_device.parent.type = RT_Device_Class_Char;
  100. #ifdef RT_USING_DEVICE_OPS
  101. _file_device.parent.ops = &log_trace_ops;
  102. #else
  103. _file_device.parent.init = RT_NULL;
  104. _file_device.parent.open = fdevice_open;
  105. _file_device.parent.close = fdevice_close;
  106. _file_device.parent.write = fdevice_write;
  107. _file_device.parent.control = fdevice_control;
  108. #endif
  109. rt_device_register(&_file_device.parent, "logfile", O_RDWR);
  110. }
  111. _file_device.filename = rt_strdup(filename);
  112. _file_device.fd = -1;
  113. }
  114. void log_trace_set_file(const char *filename)
  115. {
  116. log_trace_file_init(filename);
  117. log_trace_set_device("logfile");
  118. }
  119. #ifdef RT_USING_FINSH
  120. #include <finsh.h>
  121. FINSH_FUNCTION_EXPORT_ALIAS(log_trace_set_file, log_file, set output filename of log trace);
  122. #endif
  123. #endif /* RT_USING_DFS */