Guest User

Untitled

a guest
May 21st, 2011
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.60 KB | None | 0 0
  1. #define _FILE_OFFSET_BITS   64
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <getopt.h>
  6. #include <time.h>
  7. #include <limits.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12.  
  13. #define CACHE_FILE  "/tmp/.parsesquid_cache"
  14. #define LOG_FILE    "/var/log/squid/access.log"
  15. #define TIME_INTERVAL 25000
  16.  
  17. #define NEW     0
  18. #define UPDATE  1
  19.  
  20. struct idx{
  21.     int time;
  22.     off_t offset;
  23. } s_cache;
  24.  
  25. void help(const char* name){
  26.     printf("\nИспользование:\n%s [Ключи]\nВыдает информацию о трафике, полученном извне и из кеша прокси\n", name);
  27.     printf("\t-h\t--help\t\t\tЭто сообщение\n");
  28.     printf("\t-f\t--from ДАТА\t\tУказать дату, с которой необходимо начать подсчет\n");
  29.     printf("\t-t\t--to ДАТА\t\tУказать дату, на которой необходимо закончить подсчет\n");
  30.     printf("\t-a\t--address addr\t\tУказать часть имени сайта, для которого производить подсчет\n");
  31.     printf("\t-u\t--update\t\tОбновить индексный файл\n");
  32.     printf("\t-n\t--new\t\tЗаново создать индексный файл\n");
  33.     printf("\nФормат даты: Д/М/Г-ч:м, Д/М/Г, ч:м, Д/М, М\n\n");
  34.     exit(0);
  35. }
  36.  
  37. int get_date(char *line){
  38.     time_t date;
  39.     struct tm time_, time_now;
  40.     time(&date);
  41.     time_now = *localtime(&date);
  42.     time_.tm_sec = 0;
  43.     if(sscanf(line, "%d/%d/%d-%d:%d", &time_.tm_mday, &time_.tm_mon, &time_.tm_year,
  44.         &time_.tm_hour, &time_.tm_min) == 5){time_.tm_mon -= 1;}
  45.     else if(!strchr(line, ':') && sscanf(line, "%d/%d/%d", &time_.tm_mday, &time_.tm_mon, &time_.tm_year) == 3){
  46.         date = -1; time_.tm_mon -= 1;}
  47.     else if(!strchr(line, ':') && sscanf(line, "%d/%d", &time_.tm_mday, &time_.tm_mon) == 2){
  48.         date = -1; time_.tm_mon -= 1; time_.tm_year = time_now.tm_year;}
  49.     else if(sscanf(line, "%d:%d", &time_.tm_hour, &time_.tm_min) == 2){
  50.         time_.tm_year = time_now.tm_year; time_.tm_mon = time_now.tm_mon;
  51.         time_.tm_mday = time_now.tm_mday;}
  52.     else if(!strchr(line, ':') && !strchr(line, '/') && !strchr(line, '.') && !strchr(line, '-')
  53.             && sscanf(line, "%d", &time_.tm_mon) == 1){
  54.         date = -1; time_.tm_mon -= 1; time_.tm_year = time_now.tm_year;
  55.         time_.tm_mday = 1;}
  56.     else{
  57.         printf("\nНеверный формат времени!\n");
  58.         printf("Форматы: D/M/Y-hh:mm, D/M/Y, hh:mm, D/M, M\n");
  59.         exit(1);
  60.     }
  61.     if(date == -1){
  62.         time_.tm_hour = 0;
  63.         time_.tm_min = 0;      
  64.     }
  65.     if(time_.tm_mon > 11 || time_.tm_mon < 0){
  66.         printf("\nМесяц вне диапазона 1..12\n");
  67.         exit(2);
  68.     }
  69.     if(time_.tm_mday > 31 || time_.tm_mday < 1){
  70.         printf("\nЧисло месяца вне диапазона 1..31, %d\n", time_.tm_mday);
  71.         exit(3);
  72.     }
  73.     if(time_.tm_year > 1900) time_.tm_year -= 1900;
  74.     else if(time_.tm_year > -1 && time_.tm_year < 100) time_.tm_year += 100;
  75.     else if(time_.tm_year < 0 || time_.tm_year > 200){
  76.         printf("\nНеверный формат года %d\n", time_.tm_year);
  77.         exit(4);
  78.     }
  79.     if(time_.tm_hour > 23 || time_.tm_hour < 0){
  80.         printf("\nВремя вне диапазона 0..23 часа\n");
  81.         exit(5);
  82.     }
  83.     if(time_.tm_min > 59 || time_.tm_min < 0){
  84.         printf("\nВремя вне диапазона 0..59 минут\n");
  85.         exit(6);
  86.     }
  87.     date = mktime(&time_);
  88. #ifdef DEBUG
  89.     printf("date: %d\n", date);
  90. #endif
  91.     return (int)date;
  92. }
  93.  
  94. void makecache(unsigned char flag){
  95.     int f_log, cache = open(CACHE_FILE, O_CREAT|O_RDWR, 00644);
  96.     off_t offset = 0, tmp = 0;
  97.     if(cache < 0){
  98.         printf("\nНе могу создать индекс-файл\n");
  99.         exit(7);
  100.     }
  101.     if(flag == UPDATE){
  102.         if((tmp = lseek(cache, -((off_t)(sizeof(struct idx))), SEEK_END)) > 0){
  103.             if(read(cache, &s_cache, sizeof(struct idx)) > 0){
  104.                 offset = s_cache.offset;
  105.             }
  106.         }
  107. #ifdef EBUG
  108.             printf("off=%lld\n", offset);
  109. #endif
  110.     }
  111.     off_t len = 0;
  112.     char *string = NULL;
  113.     struct stat filestat;
  114.     FILE *log = fopen(LOG_FILE, "r");
  115.     if(!log){
  116.         printf("\nНе могу открыть " LOG_FILE " \n");
  117.         exit(8);
  118.     }
  119.     f_log = fileno(log);
  120.     if(flag == NEW) printf("\nСоздаю индексный файл\n");
  121.     else printf("\nОбновляю индексный файл\n");
  122.     if(stat(LOG_FILE, &filestat) != 0){
  123.         printf("\nОшибка, " LOG_FILE ": не могу сделать stat\n");
  124.         exit(10);
  125.     }
  126.     if(lseek(f_log, offset, SEEK_SET) != 0){
  127.         printf("\nВнимание: " LOG_FILE " устарел, обновляю индексный файл полностью\n");
  128.         offset = 0;
  129.     }
  130.     s_cache.offset = offset;
  131.     if(getline(&string, &len, log) < 1){
  132.         printf("\nОшибка: " LOG_FILE "пуст\n");
  133.         exit(9);
  134.     }
  135.     off_t dataportion = filestat.st_size / 100;
  136.     int indpos = 1;
  137.     int frac = 0;
  138.     if(offset > 0) frac = atoi(string) / TIME_INTERVAL;
  139.     do{
  140.        
  141.         if( ( tmp = ((s_cache.time = atoi(string)) / TIME_INTERVAL)) != frac ){
  142.             write(cache, &s_cache, sizeof(struct idx));
  143. #ifdef DEBUG
  144.             printf("очередная строка, время: %d, смещение: %lld, sizeof(s_cache)=%d\n", s_cache.time, s_cache.offset, sizeof(struct idx));
  145. #endif
  146.             frac = tmp;
  147.         }
  148.         s_cache.offset = lseek(f_log, 0, SEEK_CUR);
  149.         if( (tmp = s_cache.offset / dataportion) > indpos ){
  150.             if( (tmp % 10) == 0) printf(" %lld%% ", tmp);
  151.             else printf(".");
  152.             indpos = tmp;
  153.             fflush(stdout);
  154.         }
  155.     } while(getline(&string, &len, log) > 0);
  156.     printf("\nГотово!\n");
  157.     free(string);
  158.     close(cache);
  159.     fclose(log);
  160. }
  161.  
  162. int count_bytes(off_t from_offset, off_t to_offset, int from_date, int to_date, char* addr){
  163.     off_t dataportion = (to_offset - from_offset) / 100, tmp, indpos = 0;
  164.     long long bytes_from_outside = 0, bytes_from_cache = 0;
  165.     char* string = NULL, *ptr;
  166.     off_t len = 0, curpos;
  167.     int time, bytes;
  168.     FILE *log = fopen(LOG_FILE, "r");
  169.     int f_log = fileno(log);
  170.     lseek(f_log, from_offset, SEEK_SET);
  171.     while(getline(&string, &len, log) > 0){
  172.         time = atoi(string);
  173.         curpos = lseek(f_log, 0, SEEK_CUR) - from_offset;
  174.         if( (tmp = curpos / dataportion) > indpos){
  175.             if( (tmp % 10) == 0) printf(" %lld%% ", tmp);
  176.             else printf(".");
  177.             indpos = tmp;
  178.             fflush(stdout);    
  179.         }
  180.         if(time < from_date) continue;
  181.         else if(time > to_date) break;
  182.         sscanf(string, "%*s %*s %*s %*s %d",  &bytes);
  183.         if(addr)
  184.             if(!strcasestr(string, addr)) continue;
  185.         if(strstr(string, "NONE")) bytes_from_cache += bytes;
  186.         else bytes_from_outside += bytes;
  187.     }
  188.     if(addr) printf("\nПоиск по подстроке URI:  \"%s\"", addr);
  189.     printf("\nПолучено информации\n\t\tиз мира: %lld байт (%.2f МБ);\n\t\tиз кэша: %lld байт (%.2f МБ)\n",
  190.         bytes_from_outside, (double)bytes_from_outside/1024./1024., bytes_from_cache,
  191.             (double)bytes_from_cache/1024./1024.);
  192.     free(string);
  193.     fclose(log);
  194.     return(time);
  195. }
  196.  
  197. int main(int argc, char** argv){
  198.     int from_date = 0, to_date = INT_MAX, last_cache_time, last_log_time;
  199.     struct stat filestat;
  200.     char* const short_options = "hf:t:una:";
  201.     char *addr = NULL;
  202.     struct option long_options[] = {
  203.         { "help",   0,  NULL,   'h'},
  204.         { "from",   1,  NULL,   'f'},
  205.         { "to",     1,  NULL,   't'},
  206.         { "update", 0,  NULL,   'u'},
  207.         { "new",    0,  NULL,   'n'},
  208.         { "address",    1,  NULL,   'a'},
  209.         { NULL,     0,  NULL,   0  }
  210.     };
  211.     int next_option;
  212.     do{
  213.         next_option = getopt_long(argc, argv, short_options, long_options, NULL);
  214.         switch(next_option){
  215.             case 'h': help(argv[0]);
  216.             break;
  217.             case 'f': from_date = get_date((char*)optarg);
  218.             break;
  219.             case 't': to_date = get_date((char*)optarg);
  220.             break;
  221.             case 'u': makecache(UPDATE); exit(0);
  222.             break;
  223.             case 'n': makecache(NEW); exit(0);
  224.             break;
  225.             case 'a': addr = strdup(optarg);
  226.             break;
  227.         }
  228.     }while(next_option != -1);
  229.     if(stat(CACHE_FILE, &filestat) != 0) makecache(NEW);
  230.     else if(filestat.st_size == 0) makecache(NEW);
  231.     int cache = open(CACHE_FILE, O_RDONLY);
  232.     off_t bytes_read;
  233.     unsigned char find_from = 1;
  234.     off_t from_offset = 0, to_offset = 0;
  235.     bytes_read = read(cache, &s_cache, sizeof(s_cache));
  236. #ifdef DEBUG
  237.     printf("\nfirst, time=%d, from=%lld\n", s_cache.time, s_cache.offset);
  238. #endif
  239.     while(bytes_read == sizeof(struct idx)){
  240. #ifdef DEBUG
  241.         printf("\ntime=%d, from=%lld, idxpos=%lld\n", s_cache.time, s_cache.offset, lseek(cache, 0, SEEK_CUR));
  242. #endif
  243.         if( (last_cache_time = s_cache.time) >= from_date && find_from){
  244.             find_from = 0;
  245.             from_offset = s_cache.offset;
  246.         }
  247.         else if(s_cache.time >= to_date)
  248.             to_offset = s_cache.offset;
  249.         bytes_read = read(cache, &s_cache, sizeof(struct idx));
  250.     }
  251.     close(cache);
  252.     if(find_from){
  253.         printf("\nНачальная дата поиска старше последней записи логов\n");
  254.         exit(11);
  255.     }
  256.     if(to_offset == 0){
  257.         stat(LOG_FILE, &filestat);
  258.         to_offset = filestat.st_size;
  259.     }
  260.     if(to_offset <= from_offset){
  261.         printf("\nНеверно выбраны начало и конец диапазона дат,\n"
  262.             "\tлибо сведения за указанный период отсутствуют\n");
  263.             exit(12);
  264.     }
  265.     printf("\nПровожу подсчет (от %lld до %lld)\n", from_offset, to_offset);
  266.     printf("\n====================================================================\n");
  267.     last_log_time = count_bytes(from_offset, to_offset, from_date, to_date, addr);
  268.     printf("\n====================================================================\n");
  269.     if(last_log_time - last_cache_time > TIME_INTERVAL){
  270.         printf("\nЗаписи файла кеша устарели. Обновляю...\n");
  271.         makecache(UPDATE);
  272. //      count_bytes(from_offset, to_offset, from_date, to_date);
  273.     }
  274.     exit(0);
  275. }
Add Comment
Please, Sign In to add comment