00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "ink_config.h"
00024 #include "ink_file.h"
00025 #include "I_Layout.h"
00026 #include "I_Version.h"
00027
00028 #define PROGRAM_NAME "traffic_logcat"
00029 #define MAX_LOGBUFFER_SIZE 65536
00030
00031 #include <poll.h>
00032
00033 #include "LogStandalone.cc"
00034
00035 #include "LogAccess.h"
00036 #include "LogField.h"
00037 #include "LogFilter.h"
00038 #include "LogFormat.h"
00039 #include "LogFile.h"
00040 #include "LogHost.h"
00041 #include "LogObject.h"
00042 #include "LogConfig.h"
00043 #include "LogBuffer.h"
00044 #include "LogUtils.h"
00045 #include "LogSock.h"
00046 #include "LogPredefined.h"
00047 #include "Log.h"
00048
00049
00050 static int version_flag = 0;
00051 static int help = 0;
00052 static int squid_flag = 0;
00053 static int follow_flag = 0;
00054 static int clf_flag = 0;
00055 static int elf_flag = 0;
00056 static int elf2_flag = 0;
00057 static int auto_filenames = 0;
00058 static int overwrite_existing_file = 0;
00059 static char output_file[1024];
00060 int auto_clear_cache_flag = 0;
00061
00062 static const ArgumentDescription argument_descriptions[] = {
00063
00064 {"output_file", 'o', "Specify output file", "S1023", &output_file, NULL, NULL},
00065 {"auto_filenames", 'a', "Automatically generate output names",
00066 "T", &auto_filenames, NULL, NULL},
00067 {"follow", 'f', "Follow the log file as it grows", "T", &follow_flag, NULL, NULL},
00068 {"clf", 'C', "Convert to Common Logging Format", "T", &clf_flag, NULL, NULL},
00069 {"elf", 'E', "Convert to Extended Logging Format", "T", &elf_flag, NULL, NULL},
00070 {"help", 'h', "Give this help", "T", &help, NULL, NULL},
00071 {"squid", 'S', "Convert to Squid Logging Format", "T", &squid_flag, NULL, NULL},
00072 {"debug_tags", 'T', "Colon-Separated Debug Tags", "S1023", error_tags, NULL, NULL},
00073 {"version", 'V', "Print Version Id", "T", &version_flag, NULL, NULL},
00074 {"overwrite_output", 'w', "Overwrite existing output file(s)", "T",
00075 &overwrite_existing_file, NULL, NULL},
00076 {"elf2", '2', "Convert to Extended2 Logging Format", "T", &elf2_flag, NULL,
00077 NULL}
00078 };
00079
00080 static const char *USAGE_LINE = "Usage: " PROGRAM_NAME " [-o output-file | -a] [-CEhS"
00081 #ifdef DEBUG
00082 "T"
00083 #endif
00084 "Vw2] [input-file ...]";
00085
00086
00087
00088 static int
00089 process_file(int in_fd, int out_fd)
00090 {
00091 char buffer[MAX_LOGBUFFER_SIZE];
00092 int nread, buffer_bytes;
00093 unsigned bytes = 0;
00094
00095 while (true) {
00096
00097
00098 Debug("logcat", "Reading buffer ...");
00099 memset(buffer, 0, sizeof(buffer));
00100
00101
00102
00103
00104 unsigned first_read_size = sizeof(uint32_t) + sizeof(uint32_t);
00105 unsigned header_size = sizeof(LogBufferHeader);
00106 LogBufferHeader *header = (LogBufferHeader *) & buffer[0];
00107
00108 nread = read(in_fd, buffer, first_read_size);
00109 if (!nread || nread == EOF)
00110 return 0;
00111
00112
00113
00114 if (header->cookie != LOG_SEGMENT_COOKIE) {
00115 fprintf(stderr, "Bad LogBuffer!\n");
00116 return 1;
00117 }
00118
00119
00120 unsigned second_read_size = header_size - first_read_size;
00121
00122 nread = read(in_fd, &buffer[first_read_size], second_read_size);
00123 if (!nread || nread == EOF) {
00124 if (follow_flag)
00125 return 0;
00126
00127 fprintf(stderr, "Bad LogBufferHeader read!\n");
00128 return 1;
00129 }
00130
00131
00132 uint32_t byte_count = header->byte_count;
00133
00134 if (byte_count > sizeof(buffer)) {
00135 fprintf(stderr, "Buffer too large!\n");
00136 return 1;
00137 }
00138 buffer_bytes = byte_count - header_size;
00139 if (buffer_bytes == 0)
00140 return 0;
00141 if (buffer_bytes < 0) {
00142 fprintf(stderr, "No buffer body!\n");
00143 return 1;
00144 }
00145
00146 nread = 0;
00147 while (nread < buffer_bytes) {
00148 int rc = read(in_fd, &buffer[header_size] + nread, buffer_bytes - nread);
00149
00150 if ((rc == EOF) && (!follow_flag)) {
00151 fprintf(stderr, "Bad LogBuffer read!\n");
00152 return 1;
00153 }
00154
00155 if (rc > 0)
00156 nread += rc;
00157 }
00158
00159 if (nread > buffer_bytes) {
00160 fprintf(stderr, "Read too many bytes!\n");
00161 return 1;
00162 }
00163
00164
00165
00166 const char * alt_format = NULL;
00167 if (squid_flag)
00168 alt_format = PreDefinedFormatInfo::squid;
00169 if (clf_flag)
00170 alt_format = PreDefinedFormatInfo::common;
00171 if (elf_flag)
00172 alt_format = PreDefinedFormatInfo::extended;
00173 if (elf2_flag)
00174 alt_format = PreDefinedFormatInfo::extended2;
00175
00176
00177
00178 if (header->fmt_fieldlist()) {
00179 bytes += LogFile::write_ascii_logbuffer(header, out_fd, ".", alt_format);
00180 } else {
00181
00182 }
00183 }
00184 }
00185
00186 static int
00187 open_output_file(char *output_file)
00188 {
00189 int file_desc = 0;
00190
00191 if (!overwrite_existing_file) {
00192 if (access(output_file, F_OK)) {
00193 if (errno != ENOENT) {
00194 fprintf(stderr, "Error accessing output file %s: ", output_file);
00195 perror(0);
00196 file_desc = -1;
00197 }
00198 } else {
00199 fprintf(stderr, "Error, output file %s already exists.\n" "Select a different filename or use the -w flag\n",
00200 output_file);
00201 file_desc = -1;
00202 }
00203 }
00204
00205 if (file_desc == 0) {
00206 file_desc = open(output_file, O_WRONLY | O_TRUNC | O_CREAT, 0640);
00207
00208 if (file_desc < 0) {
00209 fprintf(stderr, "Error while opening output file %s: ", output_file);
00210 perror(0);
00211 }
00212 }
00213
00214 return file_desc;
00215 }
00216
00217
00218
00219
00220
00221
00222 int
00223 main(int , char *argv[])
00224 {
00225 enum
00226 {
00227 NO_ERROR = 0,
00228 CMD_LINE_OPTION_ERROR = 1,
00229 DATA_PROCESSING_ERROR = 2
00230 };
00231
00232
00233
00234 appVersionInfo.setup(PACKAGE_NAME,PROGRAM_NAME, PACKAGE_VERSION, __DATE__,
00235 __TIME__, BUILD_MACHINE, BUILD_PERSON, "");
00236
00237
00238 Layout::create();
00239
00240
00241 output_file[0] = 0;
00242 process_args(argument_descriptions, countof(argument_descriptions), argv, USAGE_LINE);
00243
00244
00245
00246 if (version_flag) {
00247 fprintf(stderr, "%s\n", appVersionInfo.FullVersionInfoStr);
00248 _exit(NO_ERROR);
00249 }
00250
00251
00252 if (help) {
00253 usage(argument_descriptions, countof(argument_descriptions), USAGE_LINE);
00254 _exit(NO_ERROR);
00255 }
00256
00257
00258 if (output_file[0] != 0 && auto_filenames) {
00259 fprintf(stderr, "Error: specify only one of -o <file> and -a\n");
00260 _exit(CMD_LINE_OPTION_ERROR);
00261 }
00262
00263
00264 init_log_standalone_basic(PROGRAM_NAME);
00265
00266 Log::init(Log::NO_REMOTE_MANAGEMENT | Log::LOGCAT);
00267
00268
00269
00270 int out_fd = STDOUT_FILENO;
00271 if (output_file[0] != 0) {
00272 out_fd = open_output_file(output_file);
00273
00274 if (out_fd < 0) {
00275 _exit(DATA_PROCESSING_ERROR);
00276 }
00277 } else if (!auto_filenames) {
00278 out_fd = STDOUT_FILENO;
00279 }
00280
00281
00282 int error = NO_ERROR;
00283
00284 if (n_file_arguments) {
00285 int bin_ext_len = strlen(LOG_FILE_BINARY_OBJECT_FILENAME_EXTENSION);
00286 int ascii_ext_len = strlen(LOG_FILE_ASCII_OBJECT_FILENAME_EXTENSION);
00287
00288 for (unsigned i = 0; i < n_file_arguments; ++i) {
00289 int in_fd = open(file_arguments[i], O_RDONLY);
00290 if (in_fd < 0) {
00291 fprintf(stderr, "Error opening input file %s: ", file_arguments[i]);
00292 perror(0);
00293 error = DATA_PROCESSING_ERROR;
00294 } else {
00295 #if HAVE_POSIX_FADVISE
00296 posix_fadvise(in_fd, 0, 0, POSIX_FADV_DONTNEED);
00297 #endif
00298 if (auto_filenames) {
00299
00300
00301 int n = strlen(file_arguments[i]);
00302 int copy_len = (n >= bin_ext_len ? (strcmp(&file_arguments[i][n - bin_ext_len],
00303 LOG_FILE_BINARY_OBJECT_FILENAME_EXTENSION) ==
00304 0 ? n - bin_ext_len : n) : n);
00305
00306 char *out_filename = (char *)ats_malloc(copy_len + ascii_ext_len + 1);
00307
00308 memcpy(out_filename, file_arguments[i], copy_len);
00309 memcpy(&out_filename[copy_len], LOG_FILE_ASCII_OBJECT_FILENAME_EXTENSION, ascii_ext_len);
00310 out_filename[copy_len + ascii_ext_len] = 0;
00311
00312 out_fd = open_output_file(out_filename);
00313 ats_free(out_filename);
00314
00315 if (out_fd < 0) {
00316 error = DATA_PROCESSING_ERROR;
00317 continue;
00318 }
00319 }
00320 if (follow_flag)
00321 lseek(in_fd, 0, SEEK_END);
00322
00323 while (true) {
00324 if (process_file(in_fd, out_fd) != 0) {
00325 error = DATA_PROCESSING_ERROR;
00326 break;
00327 }
00328 if (!follow_flag)
00329 break;
00330 else
00331 usleep(10000);
00332 }
00333 }
00334 }
00335 } else {
00336
00337
00338 int tries = 3;
00339 while (--tries >= 0) {
00340 if (process_file(STDIN_FILENO, out_fd) != 0)
00341 tries = -1;
00342 }
00343 }
00344
00345 _exit(error);
00346 }