#include "ttail_search_files.h" int _ttail_search_closest_files(ttail_t* t) { int ret; ret = _ttail_search_closest_files_init(t); if(ret) { return ret; } /* Checking that files are sorted well */ return 0; } int _ttail_search_closest_files_init(ttail_t* t) { struct stat stat; FILE *fp; size_t i; off_t *file_sz; t->session = (ttail_search_t*)malloc(sizeof(ttail_search_file_t)); if(!t->session) { perror("Unable to allocate memory for search session"); goto _ttail_search_closest_files_alloc_session_err; } memset(t->session, 0, sizeof(ttail_search_file_t)); file_sz = malloc(sizeof(off_t)*t->logfile_sz); if(!file_sz) { perror("Unable to allocate memory for file sizes"); goto _ttail_search_closest_files_alloc_err; } t->session->file.file_sz = file_sz; #ifdef HUGEFILE t->session->file.sz_div = 0; #endif for(i=0;ilogfile_sz;i++) { fp = t->logfile[i]; if(!fp) { if(_ttail_file_reopen(t,i)) { file_sz[i] = 0; continue; } } if(fstat(fileno(fp), &stat)) { perror("Unable to get file size"); goto _ttail_search_closest_files_err; } file_sz[i] = stat.st_size; } /* we got all real size, determining if we need a divisor */ /* * not implemented */ if(_ttail_search_closest_files_set_fsizes(t)) { goto _ttail_search_closest_files_err; } t->session->file.buf_sz = 128; t->session->file.buf = malloc(t->session->file.buf_sz); if(!t->session->file.buf) { goto _ttail_search_closest_files_err; } return 0; _ttail_search_closest_files_err: free(file_sz); t->session->file.file_sz = NULL; _ttail_search_closest_files_alloc_err: free(t->session); _ttail_search_closest_files_alloc_session_err: return -1; } int _ttail_search_closest_files_set_fsizes(ttail_t* t) { size_t i; off_t *vfile, *vsz; vfile = malloc(sizeof(off_t)*t->logfile_sz); if(!vfile) { perror("Unable to allocate memory for file size sum"); return -1; } t->session->file.vfile = vfile; vsz = &(t->session->file.vsz); *vsz = 0; for(i=0; ilogfile_sz;i++) { vfile[i] = *vsz; #ifdef HUGEFILE *vsz += t->session->file.file_sz[i] >> t->session->file.sz_div; #else *vsz += t->session->file.file_sz[i]; #endif } t->session->file.vpos = 0; return 0; } int _ttail_search_file_sorted(ttail_t* t) { /* files start & stop log tm, file start id = i*2 file stop = i*2+1 */ struct tm *ftm; ftm = malloc(sizeof(struct tm)*t->logfile_sz*2); if(!ftm) { perror("Unable to allocate memory"); return -1; } free(ftm); return -1; } int _ttail_file_minmax(ttail_t* t, size_t id, struct tm tm[2]) { FILE *fp; long cur; memset(tm, 0, sizeof(struct tm)*2); fp = t->logfile[id]; if(!fp) { return 1; } if(!fseek(fp, 0, SEEK_SET)) { perror("Unable to manipulate fp"); return -1; } while(1) { if(ttail_getline(t, id) < 0) { return 1; } if(!ttail_logline2date(t, ttail_getline_buf(t), tm)) { break; } } if(!fseek(fp, -1, SEEK_END)) { perror("Unable to manipulate fp"); return -1; } while(1) { if((cur = _ttail_file_start_line(fp)) < 0) { return -1; } if(ttail_getline(t, id) < 0) { return 1; } if(!ttail_logline2date(t, ttail_getline_buf(t), tm+1)) { break; } if(!cur) { return 1; } if(!fseek(fp, cur-1, SEEK_SET)) { perror("Unable to manipulate fp"); return -1; } } return 0; } int _ttail_file_reopen(ttail_t* t, size_t id) { if(t->logfile[id]) { fclose(t->logfile[id]); } t->logfile[id] = fopen(t->logfile_name[id], "r"); if(!t->logfile[id] && t->verbose > 2) { fprintf(stderr, "Unable to reopen '%s'\n", t->logfile_name[id]); } return t->logfile[id]?0:-1; } long _ttail_file_next_line(FILE* f) { ssize_t s; size_t r; char *buff; long res; int c; r=0; buff = NULL; s = getline(&buff, &r, f); if(s == -1) { goto _ttail_file_next_line_err; } while(1) { c = getc(f); if(c == EOF) { return 0; } else if(c!='\n') { if(fseek(f, -1, SEEK_CUR)<0) { goto _ttail_file_next_line_err; } break; } } res = ftell(f); free(buff); return res; _ttail_file_next_line_err: free(buff); return -1; } long _ttail_file_start_line(FILE* f) { #define _STARTLN_BUFFLEN 32 long res; /* function result */ long read_beg, cur, last, start; int read_sz; int c; if((start = ftell(f)) < 0) { return -1; } res = 0; read_beg = start; while(!res && start) { if(fseek(f, read_beg, SEEK_SET) < 0) { return -1; } start = read_beg; read_sz = start <= _STARTLN_BUFFLEN?start:_STARTLN_BUFFLEN; read_beg = start - read_sz; if(fseek(f, read_beg, SEEK_SET) < 0) { return -1; } last = -1; /* last pos we saw a '\n' */ cur = read_beg; while(cur <= start) { c = getc(f); if(c == EOF) { if(!res) { return 0; } break; } else if (c =='\n') { last = cur; } else if(last >= 0) { res = cur; last = -1; } cur++; } if(!read_beg) { break; } } if(fseek(f, res, SEEK_SET) < 0) { return -1; } return res; } void _ttail_search_file_free(ttail_t* t) { if(!t->session) { return; } if(t->session->file.buf) { free(t->session->file.buf); } if(t->session->file.file_sz) { free(t->session->file.file_sz); } if(t->session->file.vfile) { free(t->session->file.vfile); } free(t->session); }