log_writer.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/common/file.h>
  6. #include <aws/common/log_writer.h>
  7. #include <aws/common/string.h>
  8. #include <errno.h>
  9. #include <stdio.h>
  10. /*
  11. * Basic log writer implementations - stdout, stderr, arbitrary file
  12. */
  13. struct aws_file_writer;
  14. struct aws_file_writer {
  15. FILE *log_file;
  16. bool close_file_on_cleanup;
  17. };
  18. static int s_aws_file_writer_write(struct aws_log_writer *writer, const struct aws_string *output) {
  19. struct aws_file_writer *impl = (struct aws_file_writer *)writer->impl;
  20. size_t length = output->len;
  21. if (fwrite(output->bytes, 1, length, impl->log_file) < length) {
  22. return aws_translate_and_raise_io_error(errno);
  23. }
  24. return AWS_OP_SUCCESS;
  25. }
  26. static void s_aws_file_writer_clean_up(struct aws_log_writer *writer) {
  27. struct aws_file_writer *impl = (struct aws_file_writer *)writer->impl;
  28. if (impl->close_file_on_cleanup) {
  29. fclose(impl->log_file);
  30. }
  31. aws_mem_release(writer->allocator, impl);
  32. }
  33. static struct aws_log_writer_vtable s_aws_file_writer_vtable = {
  34. .write = s_aws_file_writer_write,
  35. .clean_up = s_aws_file_writer_clean_up,
  36. };
  37. /*
  38. * Shared internal init implementation
  39. */
  40. static int s_aws_file_writer_init_internal(
  41. struct aws_log_writer *writer,
  42. struct aws_allocator *allocator,
  43. const char *file_name_to_open,
  44. FILE *currently_open_file) {
  45. /* One or the other should be set */
  46. if (!((file_name_to_open != NULL) ^ (currently_open_file != NULL))) {
  47. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  48. }
  49. /* Allocate and initialize the file writer */
  50. struct aws_file_writer *impl = aws_mem_calloc(allocator, 1, sizeof(struct aws_file_writer));
  51. if (impl == NULL) {
  52. return AWS_OP_ERR;
  53. }
  54. impl->log_file = NULL;
  55. impl->close_file_on_cleanup = false;
  56. /* Open file if name passed in */
  57. if (file_name_to_open != NULL) {
  58. impl->log_file = aws_fopen(file_name_to_open, "a+");
  59. if (impl->log_file == NULL) {
  60. aws_mem_release(allocator, impl);
  61. return aws_translate_and_raise_io_error(errno);
  62. }
  63. impl->close_file_on_cleanup = true;
  64. } else {
  65. impl->log_file = currently_open_file;
  66. }
  67. writer->vtable = &s_aws_file_writer_vtable;
  68. writer->allocator = allocator;
  69. writer->impl = impl;
  70. return AWS_OP_SUCCESS;
  71. }
  72. /*
  73. * Public initialization interface
  74. */
  75. int aws_log_writer_init_stdout(struct aws_log_writer *writer, struct aws_allocator *allocator) {
  76. return s_aws_file_writer_init_internal(writer, allocator, NULL, stdout);
  77. }
  78. int aws_log_writer_init_stderr(struct aws_log_writer *writer, struct aws_allocator *allocator) {
  79. return s_aws_file_writer_init_internal(writer, allocator, NULL, stderr);
  80. }
  81. int aws_log_writer_init_file(
  82. struct aws_log_writer *writer,
  83. struct aws_allocator *allocator,
  84. struct aws_log_writer_file_options *options) {
  85. return s_aws_file_writer_init_internal(writer, allocator, options->filename, options->file);
  86. }
  87. void aws_log_writer_clean_up(struct aws_log_writer *writer) {
  88. AWS_ASSERT(writer->vtable->clean_up);
  89. (writer->vtable->clean_up)(writer);
  90. }