log_writer.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. int errno_value = errno; /* Always cache errno before potential side-effect */
  23. return aws_translate_and_raise_io_error(errno_value);
  24. }
  25. return AWS_OP_SUCCESS;
  26. }
  27. static void s_aws_file_writer_clean_up(struct aws_log_writer *writer) {
  28. struct aws_file_writer *impl = (struct aws_file_writer *)writer->impl;
  29. if (impl->close_file_on_cleanup) {
  30. fclose(impl->log_file);
  31. }
  32. aws_mem_release(writer->allocator, impl);
  33. }
  34. static struct aws_log_writer_vtable s_aws_file_writer_vtable = {
  35. .write = s_aws_file_writer_write,
  36. .clean_up = s_aws_file_writer_clean_up,
  37. };
  38. /*
  39. * Shared internal init implementation
  40. */
  41. static int s_aws_file_writer_init_internal(
  42. struct aws_log_writer *writer,
  43. struct aws_allocator *allocator,
  44. const char *file_name_to_open,
  45. FILE *currently_open_file) {
  46. /* One or the other should be set */
  47. if (!((file_name_to_open != NULL) ^ (currently_open_file != NULL))) {
  48. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  49. }
  50. /* Allocate and initialize the file writer */
  51. struct aws_file_writer *impl = aws_mem_calloc(allocator, 1, sizeof(struct aws_file_writer));
  52. if (impl == NULL) {
  53. return AWS_OP_ERR;
  54. }
  55. impl->log_file = NULL;
  56. impl->close_file_on_cleanup = false;
  57. /* Open file if name passed in */
  58. if (file_name_to_open != NULL) {
  59. impl->log_file = aws_fopen(file_name_to_open, "a+");
  60. if (impl->log_file == NULL) {
  61. aws_mem_release(allocator, impl);
  62. return AWS_OP_ERR;
  63. }
  64. impl->close_file_on_cleanup = true;
  65. } else {
  66. impl->log_file = currently_open_file;
  67. }
  68. writer->vtable = &s_aws_file_writer_vtable;
  69. writer->allocator = allocator;
  70. writer->impl = impl;
  71. return AWS_OP_SUCCESS;
  72. }
  73. /*
  74. * Public initialization interface
  75. */
  76. int aws_log_writer_init_stdout(struct aws_log_writer *writer, struct aws_allocator *allocator) {
  77. return s_aws_file_writer_init_internal(writer, allocator, NULL, stdout);
  78. }
  79. int aws_log_writer_init_stderr(struct aws_log_writer *writer, struct aws_allocator *allocator) {
  80. return s_aws_file_writer_init_internal(writer, allocator, NULL, stderr);
  81. }
  82. int aws_log_writer_init_file(
  83. struct aws_log_writer *writer,
  84. struct aws_allocator *allocator,
  85. struct aws_log_writer_file_options *options) {
  86. return s_aws_file_writer_init_internal(writer, allocator, options->filename, options->file);
  87. }
  88. void aws_log_writer_clean_up(struct aws_log_writer *writer) {
  89. AWS_ASSERT(writer->vtable->clean_up);
  90. (writer->vtable->clean_up)(writer);
  91. }