| 1 | /* |
| 2 | * Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"). |
| 5 | * You may not use this file except in compliance with the License. |
| 6 | * A copy of the License is located at |
| 7 | * |
| 8 | * http://aws.amazon.com/apache2.0 |
| 9 | * |
| 10 | * or in the "license" file accompanying this file. This file is distributed |
| 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| 12 | * express or implied. See the License for the specific language governing |
| 13 | * permissions and limitations under the License. |
| 14 | */ |
| 15 | |
| 16 | #include <aws/common/log_writer.h> |
| 17 | |
| 18 | #include <aws/common/string.h> |
| 19 | |
| 20 | #include <errno.h> |
| 21 | #include <stdio.h> |
| 22 | |
| 23 | #ifdef _MSC_VER |
| 24 | # pragma warning(disable : 4996) /* Disable warnings about fopen() being insecure */ |
| 25 | #endif /* _MSC_VER */ |
| 26 | |
| 27 | /* |
| 28 | * Basic log writer implementations - stdout, stderr, arbitrary file |
| 29 | */ |
| 30 | |
| 31 | struct aws_file_writer; |
| 32 | |
| 33 | struct aws_file_writer { |
| 34 | FILE *log_file; |
| 35 | bool close_file_on_cleanup; |
| 36 | }; |
| 37 | |
| 38 | static int s_aws_file_writer_write(struct aws_log_writer *writer, const struct aws_string *output) { |
| 39 | struct aws_file_writer *impl = (struct aws_file_writer *)writer->impl; |
| 40 | |
| 41 | size_t length = output->len; |
| 42 | if (fwrite(output->bytes, 1, length, impl->log_file) < length) { |
| 43 | return aws_translate_and_raise_io_error(errno); |
| 44 | } |
| 45 | |
| 46 | return AWS_OP_SUCCESS; |
| 47 | } |
| 48 | |
| 49 | static void s_aws_file_writer_clean_up(struct aws_log_writer *writer) { |
| 50 | struct aws_file_writer *impl = (struct aws_file_writer *)writer->impl; |
| 51 | |
| 52 | if (impl->close_file_on_cleanup) { |
| 53 | fclose(impl->log_file); |
| 54 | } |
| 55 | |
| 56 | aws_mem_release(writer->allocator, impl); |
| 57 | } |
| 58 | |
| 59 | static struct aws_log_writer_vtable s_aws_file_writer_vtable = { |
| 60 | .write = s_aws_file_writer_write, |
| 61 | .clean_up = s_aws_file_writer_clean_up, |
| 62 | }; |
| 63 | |
| 64 | /* |
| 65 | * Shared internal init implementation |
| 66 | */ |
| 67 | static int s_aws_file_writer_init_internal( |
| 68 | struct aws_log_writer *writer, |
| 69 | struct aws_allocator *allocator, |
| 70 | const char *file_name_to_open, |
| 71 | FILE *currently_open_file) { |
| 72 | |
| 73 | /* One or the other should be set */ |
| 74 | if (!((file_name_to_open != NULL) ^ (currently_open_file != NULL))) { |
| 75 | return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); |
| 76 | } |
| 77 | |
| 78 | /* Allocate and initialize the file writer */ |
| 79 | struct aws_file_writer *impl = aws_mem_calloc(allocator, 1, sizeof(struct aws_file_writer)); |
| 80 | if (impl == NULL) { |
| 81 | return AWS_OP_ERR; |
| 82 | } |
| 83 | |
| 84 | impl->log_file = NULL; |
| 85 | impl->close_file_on_cleanup = false; |
| 86 | |
| 87 | /* Open file if name passed in */ |
| 88 | if (file_name_to_open != NULL) { |
| 89 | impl->log_file = fopen(file_name_to_open, "a+" ); |
| 90 | if (impl->log_file == NULL) { |
| 91 | aws_mem_release(allocator, impl); |
| 92 | return aws_translate_and_raise_io_error(errno); |
| 93 | } |
| 94 | impl->close_file_on_cleanup = true; |
| 95 | } else { |
| 96 | impl->log_file = currently_open_file; |
| 97 | } |
| 98 | |
| 99 | writer->vtable = &s_aws_file_writer_vtable; |
| 100 | writer->allocator = allocator; |
| 101 | writer->impl = impl; |
| 102 | |
| 103 | return AWS_OP_SUCCESS; |
| 104 | } |
| 105 | |
| 106 | /* |
| 107 | * Public initialization interface |
| 108 | */ |
| 109 | int aws_log_writer_init_stdout(struct aws_log_writer *writer, struct aws_allocator *allocator) { |
| 110 | return s_aws_file_writer_init_internal(writer, allocator, NULL, stdout); |
| 111 | } |
| 112 | |
| 113 | int aws_log_writer_init_stderr(struct aws_log_writer *writer, struct aws_allocator *allocator) { |
| 114 | return s_aws_file_writer_init_internal(writer, allocator, NULL, stderr); |
| 115 | } |
| 116 | |
| 117 | int aws_log_writer_init_file( |
| 118 | struct aws_log_writer *writer, |
| 119 | struct aws_allocator *allocator, |
| 120 | struct aws_log_writer_file_options *options) { |
| 121 | return s_aws_file_writer_init_internal(writer, allocator, options->filename, options->file); |
| 122 | } |
| 123 | |
| 124 | void aws_log_writer_clean_up(struct aws_log_writer *writer) { |
| 125 | AWS_ASSERT(writer->vtable->clean_up); |
| 126 | (writer->vtable->clean_up)(writer); |
| 127 | } |
| 128 | |