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 }