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 | |