struct rmonitor_file_watch_event *parse_event(const char *fname, struct jx *spec) { struct rmonitor_file_watch_event *e = calloc(1, sizeof(*e)); //defaults: e->on_creation = 0; e->on_truncate = 0; e->max_count = -1; e->total_count = 0; e->cycle_count = 0; e->on_pattern = NULL; e->label = NULL; e->label = parse_str(fname, spec, "label", NULL); e->max_count = parse_int(fname, spec, "count", -1); e->on_pattern = parse_str(fname, spec, "on-pattern", e->on_pattern); e->on_creation = parse_boolean(fname, spec, "on-create", e->on_creation); e->on_truncate = parse_boolean(fname, spec, "on-truncate", e->on_truncate); int error = 0; if(!e->label) { error = 1; warn(D_RMON | D_NOTICE, "A label for '%s' was not given.", fname); } else if(string_match_regex(e->label, "[^A-Za-z0-9_-]")) { error = 1; warn(D_RMON | D_NOTICE, "Label for '%s' has characters not in [A-Za-z0-9_-]", fname); } else { int defined = 0; if(e->on_creation) { defined++; } if(e->on_truncate) { defined++; } if(e->on_pattern) { defined++; } if(defined != 1) { error = 1; warn(D_RMON | D_NOTICE, "Exactly one of on-create, on-truncate, or on-pattern should be specified for '%s'", fname); } } if(error) { free(e->label); free(e->on_pattern); free(e); return NULL; } return e; }
int whole_string_match_regex(const char *text, char *pattern) { char *new_pattern; int result; if(!pattern || !text) return 0; new_pattern = (char *) malloc(sizeof(char) * (strlen(pattern) + 3)); if(!new_pattern) return 0; new_pattern[0] = '\0'; if(*pattern != '^') strncat(new_pattern, "^", 1); strncat(new_pattern, pattern, strlen(pattern)); if(text[strlen(pattern) - 1] != '$') strncat(new_pattern, "$", 1); result = string_match_regex(text, new_pattern); free(new_pattern); return result; }
void rmonitor_watch_file_aux(struct rmonitor_file_watch_info *f) { struct rmonitor_file_watch_event *e; struct stat s; for(;;) { int created = 0; int shrank = 0; reset_events_counts(f); // if file is there, check if it was there before if(stat(f->filename, &s) == 0) { if(!f->exists) { created = 1; } f->exists = 1; } else { f->exists = 0; f->position = 0; f->last_mtime = 0; f->last_size = 0; f->last_ino = 0; } // check if file was truncated if(f->exists && f->last_mtime < s.st_mtime) { shrank = (f->last_size > s.st_size) || (f->last_ino != 0 && f->last_ino != s.st_ino); if(shrank) { if(f->from_start_if_truncated) { f->position = 0; } else { debug(D_RMON, "File '%s' was truncated. Some events may be lost.", f->filename); f->position = s.st_size; } } f->last_mtime = s.st_mtime; f->last_size = s.st_size; f->last_ino = s.st_ino; // count created and shrank events list_first_item(f->events); while((e = list_next_item(f->events))) { if(e->on_creation && created) { e->cycle_count++; e->total_count++; } if(e->on_truncate && shrank) { e->cycle_count++; e->total_count++; } } if(f->event_with_pattern) { FILE *fp = fopen(f->filename, "r"); if(!fp) { fatal("Could not open file '%s': %s.", strerror(errno)); } f->position = fseek(fp, f->position, SEEK_SET); if(f->position < 0) { fatal("Could not seek file '%s': %s.", strerror(errno)); } char *line; while((line = get_line(fp))) { list_first_item(f->events); while((e = list_next_item(f->events))) { if(e->max_count < 0 || e->max_count < e->total_count) { if(string_match_regex(line, e->on_pattern)) { e->cycle_count++; e->total_count++; } } } free(line); } f->position = ftell(fp); fclose(fp); } if(request_snapshot(f) < 0) { fatal("Could not contact resource_monitor."); } if(!at_least_one_event_still_active(f)) { debug(D_RMON, "No more active events for '%s'.", f->filename); exit(0); } if(f->delete_if_found) { unlink(f->filename); f->exists = 0; f->position = 0; f->last_size = 0; f->last_mtime = 0; f->last_ino = 0; } } else { sleep(1); } } }