void RotateFile (pcapfile_t *pcapfile, time_t t_CloseRename, int live) { struct pcap_stat p_stat; void *_b; dbg_printf ("RotateFile() time: %s\n", UNIX2ISO (t_CloseRename)); // make sure, alternate buffer is already flushed pthread_mutex_lock (&pcapfile->m_pbuff); while (pcapfile->alternate_size) { pthread_cond_wait (&pcapfile->c_pbuff, &pcapfile->m_pbuff); } // swap buffers _b = pcapfile->data_buffer; pcapfile->data_buffer = pcapfile->alternate_buffer; pcapfile->data_ptr = pcapfile->data_buffer; pcapfile->alternate_buffer = _b; pcapfile->alternate_size = pcapfile->data_size; pcapfile->t_CloseRename = t_CloseRename; // release mutex and signal thread pthread_mutex_unlock (&pcapfile->m_pbuff); pthread_cond_signal (&pcapfile->c_pbuff); pcapfile->data_size = 0; if (live) { // not a capture file if (pcap_stats (pcapfile->p, &p_stat) < 0) { LogError ("pcap_stats() failed: %s", pcap_geterr (pcapfile->p)); } else { LogInfo ("Packets received: %u, dropped: %u, dropped by interface: %u ", p_stat.ps_recv, p_stat.ps_drop, p_stat.ps_ifdrop); } } } // End of RotateFile
void ExpireProfile(channel_t *channel, dirstat_t *current_stat, uint64_t maxsize, uint64_t maxlife, uint32_t runtime ) { int size_done, lifetime_done, done; char *expire_timelimit = ""; time_t now = time(NULL); uint64_t sizelimit, num_expired; if ( !channel ) return; done = 0; SetupSignalHandler(); if ( maxlife ) { // time_t t_expire = now - maxlife; // build an appropriate string for comparing time_t t_watermark = now - (time_t)((maxlife * current_stat->low_water)/100); // printf("Expire files before %s", ctime(&t_expire)); expire_timelimit = strdup(UNIX2ISO(t_watermark)); // printf("down to %s", ctime(&t_watermark)); // printf("Diff: %i\n", t_watermark - t_expire ); } size_done = maxsize == 0 || current_stat->filesize < maxsize; sizelimit = (current_stat->low_water * maxsize)/100; lifetime_done = maxlife == 0 || ( now - current_stat->first ) < maxlife; num_expired = 0; PrepareDirLists(channel); if ( runtime ) alarm(runtime); while ( !done ) { char *p; int file_removed; // search for the channel with oldest file. If all channel have same age, // get the last in the list channel_t *expire_channel = channel; channel_t *compare_channel = expire_channel->next; while ( compare_channel ) { if ( expire_channel->ftsent == NULL ) { expire_channel = compare_channel; } if ( compare_channel->ftsent == NULL ) { compare_channel = compare_channel->next; continue; } // at this point expire_channel and current_channel fts entries are valid if ( strcmp(expire_channel->ftsent->fts_name, compare_channel->ftsent->fts_name) >= 0 ) { expire_channel = compare_channel; } compare_channel = compare_channel->next; } if ( !expire_channel->ftsent ) { // no more entries in any channel - we are done done = 1; continue; } // flag is file got removed file_removed = 0; // expire_channel now points to the channel with oldest file // do expire p = &(expire_channel->ftsent->fts_name[7]); // printf("File: %s\n", expire_channel->ftsent->fts_path); if ( !size_done ) { // expire size-wise if needed // printf(" Size expire %llu %llu\n", current_stat->filesize, sizelimit); if ( current_stat->filesize > sizelimit ) { // need to delete this file if ( unlink(expire_channel->ftsent->fts_path) == 0 ) { // Update profile stat current_stat->filesize -= 512 * expire_channel->ftsent->fts_statp->st_blocks; current_stat->numfiles--; // Update channel stat expire_channel->dirstat->filesize -= 512 * expire_channel->ftsent->fts_statp->st_blocks; expire_channel->dirstat->numfiles--; // decrement number of files seen in this directory expire_channel->ftsent->fts_number--; file_removed = 1; num_expired++; } else { LogError( "unlink() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); } } else { // we are done size-wise // time of first file not expired = start time of channel/profile expire_channel->dirstat->first = current_stat->first = ISO2UNIX(p); size_done = 1; } } else if ( !lifetime_done ) { // printf(" Time expire \n"); // expire time-wise if needed // this part of the code is executed only when size-wise is already fullfilled if ( strcmp(p, expire_timelimit) < 0 ) { // need to delete this file if ( unlink(expire_channel->ftsent->fts_path) == 0 ) { // Update profile stat current_stat->filesize -= 512 * expire_channel->ftsent->fts_statp->st_blocks; current_stat->numfiles--; // Update channel stat expire_channel->dirstat->filesize -= 512 * expire_channel->ftsent->fts_statp->st_blocks; expire_channel->dirstat->numfiles--; // decrement number of files seen in this directory expire_channel->ftsent->fts_number--; file_removed = 1; num_expired++; } else { LogError( "unlink() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); } } else { // we are done time-wise // time of first file not expired = start time of channel/profile expire_channel->dirstat->first = current_stat->first = ISO2UNIX(p); lifetime_done = 1; } } else // all done done = 1; if ( timeout ) done = 1; // advance fts entry in expire channel to next file, if file was removed if ( file_removed ) { expire_channel->ftsent = fts_read(expire_channel->fts); while ( expire_channel->ftsent ) { if ( expire_channel->ftsent->fts_info == FTS_F ) { // entry is a file expire_channel->ftsent->fts_number++; if ( expire_channel->ftsent->fts_namelen == 19 && strncmp(expire_channel->ftsent->fts_name, "nfcapd.", 7) == 0 ) { // if ftsent points to next valid file char *p = &(expire_channel->ftsent->fts_name[7]); // next file is first (oldest) for channel and for profile - update first mark expire_channel->dirstat->first = current_stat->first = ISO2UNIX(p); break; } } else { switch (expire_channel->ftsent->fts_info) { case FTS_D: // entry is a directory // set number of files seen in this directory = 0 expire_channel->ftsent->fts_number = 0; // skip all '.' entries as well as hidden directories if ( expire_channel->ftsent->fts_level > 0 && expire_channel->ftsent->fts_name[0] == '.' ) fts_set(expire_channel->fts, expire_channel->ftsent, FTS_SKIP); // any valid directory needs to start with a digit ( %Y -> year ) if ( expire_channel->ftsent->fts_level > 0 && !isdigit(expire_channel->ftsent->fts_name[0]) ) fts_set(expire_channel->fts, expire_channel->ftsent, FTS_SKIP); break; case FTS_DP: // do not delete base data directory ( level == 0 ) if ( expire_channel->ftsent->fts_number == 0 && expire_channel->ftsent->fts_level > 0 ) { // directory is empty and can be deleted // printf("Will remove directory %s\n", expire_channel->ftsent->fts_path); if ( rmdir(expire_channel->ftsent->fts_path) != 0 ) { LogError( "rmdir() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); } } break; } } // otherwise loop expire_channel->ftsent = fts_read(expire_channel->fts); } // end advance fts entry file_removed = 0; } if ( expire_channel->ftsent == NULL ) { // this channel has no more files now expire_channel->dirstat->first = expire_channel->dirstat->last; if ( expire_channel->dirstat->numfiles ) { // if channel is empty, no files must be reported, but rebuild is done anyway LogError( "Inconsitency detected in channel %s. Will rebuild automatically.\n", expire_channel->datadir); LogError( "No more files found, but %llu expected.\n", expire_channel->dirstat->numfiles); } expire_channel->dirstat->numfiles = 0; expire_channel->dirstat->status = FORCE_REBUILD; } } // while ( !done ) if ( runtime ) alarm(0); if ( timeout ) { LogError( "Maximum execution time reached! Interrupt expire.\n"); } } // End of ExpireProfile
void ExpireDir(char *dir, dirstat_t *dirstat, uint64_t maxsize, uint64_t maxlife, uint32_t runtime ) { FTS *fts; FTSENT *ftsent; uint64_t sizelimit, num_expired; int done, size_done, lifetime_done, dir_files; char *const path[] = { dir, NULL }; char *expire_timelimit = NULL; time_t now = time(NULL); dir_files = 0; if ( dirstat->low_water == 0 ) dirstat->low_water = 95; if ( runtime ) { SetupSignalHandler(); alarm(runtime); } if ( maxlife ) { // build an appropriate string for comparing time_t t_expire = now - maxlife; time_t t_watermark = now - (time_t)((maxlife * dirstat->low_water)/100); // printf("Expire files before %s", ctime(&t_expire)); expire_timelimit = strdup(UNIX2ISO(t_watermark)); // printf("down to %s", ctime(&t_watermark)); // printf("Diff: %i\n", t_watermark - t_expire ); if ( dirstat->last < t_expire && (isatty(STDIN_FILENO) ) ) { // this means all files will get expired - are you sure ? char *s, s1[32], s2[32]; time_t t; struct tm *when; t = t_expire; when = localtime(&t); strftime(s1, 31, "%Y-%m-%d %H:%M:%S", when); s1[31] = '\0'; t = dirstat->last; when = localtime(&t); strftime(s2, 31, "%Y-%m-%d %H:%M:%S", when); s2[31] = '\0'; printf("Your max lifetime of %s will expire all file before %s\n", ScaleTime(maxlife), s1); printf("Your latest files are dated %s. This means all files will be deleted!\n", s2); printf("Are you sure? yes/[no] "); s = fgets(s1, 31, stdin); s1[31] = '\0'; if ( s && strncasecmp(s1, "yes\n", 31) == 0 ) { printf("Ok - you've beeen warned!\n"); } else { printf("Expire canceled!\n"); return; } } } done = 0; size_done = maxsize == 0 || dirstat->filesize < maxsize; lifetime_done = maxlife == 0 || ( now - dirstat->first ) < maxlife; sizelimit = (dirstat->low_water * maxsize)/100; num_expired = 0; fts = fts_open(path, FTS_LOGICAL, compare); while ( !done && ((ftsent = fts_read(fts)) != NULL) ) { if ( ftsent->fts_info == FTS_F ) { dir_files++; // count files in directories if ( ftsent->fts_namelen == 19 && strncmp(ftsent->fts_name, "nfcapd.", 7) == 0 ) { // nfcapd.200604301200 strlen = 19 char *s, *p = &(ftsent->fts_name[7]); // process only nfcapd. files // make sure it's really an nfcapd. file and we have // only digits in the rest of the file name s = p; while ( *s ) { if ( *s < '0' || *s > '9' ) break; s++; } // otherwise skip if ( *s ) continue; // expire size-wise if needed if ( !size_done ) { if ( dirstat->filesize > sizelimit ) { if ( unlink(ftsent->fts_path) == 0 ) { dirstat->filesize -= 512 * ftsent->fts_statp->st_blocks; num_expired++; dir_files--; } else { LogError( "unlink() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); } continue; // next file if file was unlinked } else { dirstat->first = ISO2UNIX(p); // time of first file not expired size_done = 1; } } // expire time-wise if needed // this part of the code is executed only when size-wise is fullfilled if ( !lifetime_done ) { if ( expire_timelimit && strcmp(p, expire_timelimit) < 0 ) { if ( unlink(ftsent->fts_path) == 0 ) { dirstat->filesize -= 512 * ftsent->fts_statp->st_blocks; num_expired++; dir_files--; } else { LogError( "unlink() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); } lifetime_done = 0; } else { dirstat->first = ISO2UNIX(p); // time of first file not expired lifetime_done = 1; } } done = (size_done && lifetime_done) || timeout; } } else { switch (ftsent->fts_info) { case FTS_D: // set pre-order flag dir_files = 0; // skip all '.' entries as well as hidden directories if ( ftsent->fts_level > 0 && ftsent->fts_name[0] == '.' ) fts_set(fts, ftsent, FTS_SKIP); // any valid directory needs to start with a digit ( %Y -> year ) if ( ftsent->fts_level > 0 && !isdigit(ftsent->fts_name[0]) ) fts_set(fts, ftsent, FTS_SKIP); break; case FTS_DP: // do not delete base data directory ( level == 0 ) if ( dir_files == 0 && ftsent->fts_level > 0 ) { // directory is empty and can be deleted // printf("Will remove directory %s\n", ftsent->fts_path); if ( rmdir(ftsent->fts_path) != 0 ) { LogError( "rmdir() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); } } break; } } } fts_close(fts); if ( !done ) { // all files expired and limits not reached // this may be possible, when files get time-wise expired and // the time limit is shorter than the latest file dirstat->first = dirstat->last; } if ( runtime ) alarm(0); if ( timeout ) { LogError( "Maximum execution time reached! Interrupt expire.\n"); } if ( num_expired > dirstat->numfiles ) { LogError( "Error updating stat record: Number of files inconsistent!\n"); LogError( "Will automatically rebuild this directory next time\n"); dirstat->numfiles = 0; dirstat->status = FORCE_REBUILD; } else { dirstat->numfiles -= num_expired; } if ( dirstat->numfiles == 0 ) { dirstat->first = dirstat->last = time(NULL); dirstat->status = FORCE_REBUILD; } free(expire_timelimit); } // End of ExpireDir