#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/inotify.h>
#include <sys/select.h>
#include <signal.h>
#include "config.h"
#include "dhash.h"
#include "path_utils.h"
#include "logging.h"
#include "regexp.h"
#include "inotify_watch.h"
#include "util.h"
#include "lwatch.h"
Go to the source code of this file.
Defines | |
#define | _GNU_SOURCE |
Turn on GNU extensions. | |
#define | LOG_LEVEL_ARG 256 |
log_level command line argument | |
#define | LOG_TO_CONSOLE_ARG 257 |
log_to_console command line argument | |
#define | LOGFILE_PATH_ARG 258 |
logfile_path command line argument | |
#define | NO_LOGGING_TO_FILE_ARG 259 |
no_logging_to_file command line argument | |
#define | LOG_SHOW_LEVEL_ARG 260 |
log_show_level command line argument | |
#define | LOG_NO_SHOW_LEVEL_ARG 261 |
log_no_show_level command line argument | |
#define | LOG_SHOW_FILE_ARG 262 |
log_show_file command line argument | |
#define | LOG_NO_SHOW_FILE_ARG 263 |
log_no_show_file command line argument | |
#define | LOG_SHOW_LINE_ARG 264 |
log_show_line command line argument | |
#define | LOG_NO_SHOW_LINE_ARG 265 |
log_no_show_line command line argument | |
#define | LOG_SHOW_FUNCTION_ARG 266 |
log_show_function command line argument | |
#define | LOG_NO_SHOW_FUNCTION_ARG 267 |
log_no_show_function command line argument | |
#define | LOG_SHOW_TIME_ARG 268 |
log_show_time command line argument | |
#define | LOG_NO_SHOW_TIME_ARG 269 |
log_no_show_time command line argument | |
Enumerations | |
enum | prog_action_t { PROG_ACTION_MONITOR, PROG_ACTION_LIST, PROG_ACTION_FIND } |
Operational program modes, e.g. More... | |
enum | file_event_t { FILE_NO_CHANGE, FILE_APPENDED, FILE_REPLACED } |
Possible states of a file we're monitoring. More... | |
Functions | |
static const char * | file_event_string (file_event_t event_type) |
Translate a file_event_t enumeration into a string. | |
static int | reap_file_data (struct lwatch_path_info_t *path_info) |
The file has already been identified for reaping, perform the reap by collecting the file contents and updating our bookkeeping. | |
static int | get_create_path_info (const char *path, struct lwatch_path_info_t *path_info) |
Given a path name lookup it's path_info, if it doesn't exist create it. | |
static int | process_file_modification (const char *path) |
A file has been modified, record that it will need to be reaped. | |
static int | process_file_close (const char *path) |
A file has been closed, test if it will need to be reaped and record reap status. | |
static int | process_file_create (const char *path) |
A file has been opened, validate it's a watch target. | |
static int | process_file_delete (const char *path) |
A file has been deleted, record that it's file contents will be different. | |
static int | process_file_rename (const char *prev_path, const char *new_path) |
A file has been renamed, track both the old and new file contents. | |
static int | regexp_init (void) |
Initialize our regular expressions. | |
static int | regexp_fini (void) |
Close our regular expression usage by releasing resources. | |
static int | lwatch_init (void) |
Initialize the log watcher. | |
static int | lwatch_fini () |
Close down the log watch system. | |
static void | signal_handler (int signum) |
Respond to signals. | |
static const char * | lwatch_event_type_string (lwatch_event_type event_type) |
Given a lwatch_event_type enumeration return it's name as a string. | |
static const char * | lwatch_event_string (struct lwatch_event_t *event) |
Given a lwatch_event_t render it as a string. | |
static int | lwatch_event_callback (struct lwatch_event_t *event) |
Respond to the events sent by the monitoring back end. | |
static int | start_monitoring (const char *path_arg) |
Start monitoring a primary file. | |
static int | compare_stat_info (struct stat *stat_info, struct lwatch_path_info_t *path_info, file_event_t *result_arg) |
Compare operating system information about a file with our saved information, return how the file's state may have transformed. | |
static int | get_path_info_reap_candidacy (struct lwatch_path_info_t *path_info, bool *should_reap) |
Examine the file system, set parameter if the file should be reaped. | |
static int | set_path_info_reap_candidacy (struct lwatch_path_info_t *path_info) |
Determine if watched file needs to be reaped, set internal flag accordingly. | |
static int | update_stat_info_and_write (struct stat *cur_stat_info, struct lwatch_path_info_t *path_info) |
Merge stat information about a file into our struct and write the updated entry in the persistent database. | |
static int | dump_database () |
Display the contents of the persistent log watch database. | |
static int | validate_backups_in_database () |
Check the state of known backups since the last time we ran. | |
static int | process_pending_reaps () |
For each file in the database marked as needing to be reaped perform a reap. | |
static int | main_loop () |
Main loop when running in daemon monitor mode. | |
int | destroy_path_info (struct lwatch_path_info_t **ppath_info) |
Release lwatch_path_info_t resources, free it's memory, set variable to NULL. | |
int | update_stat_info (struct stat *cur_stat_info, struct lwatch_path_info_t *path_info) |
Merge stat information into path into our saved information about the file. | |
bool | is_log_backup (const char *path) |
Given a path name return true if it appears to be a rotated backup of a primary log file. | |
static bool | find_log_files_callback (const char *directory, const char *filename, const char *path, struct stat *info, void *user_data) |
Recursive directory walk callback used to find potential log files. | |
static int | find_log_files (const char *dir_path, int recursive) |
Find potential log files in a directory (and below). | |
static void | usage (void) |
Write the program usage help information. | |
int | main (int argc, char **argv) |
Main program entry point. | |
Variables | |
struct regexp_t | logrotate_numbered_backup_regexp = {"(.*/)?([^/]+)\\.(\\d+)(\\.gz|.\\bz2)?$"} |
regular expression which matches a numbered backup path name match 0 = full match match 1 = directory match 2 = basename match 3 = number match 4 = extension | |
struct regexp_t | logrotate_date_backup_regexp = {"(.*/)?([^/]+)-((\\d{4})(\\d{2})(\\d{2}))(\\.gz|.\\bz2)?$"} |
regular expression which matches a dated backup path name match 0 = full match match 1 = directory match 2 = basename match 3 = full date match 4 = year match 5 = month match 6 = day match 7 = extension | |
static int | reap_interval = 15 |
How often to reap log file updates (number of seconds). |
Definition in file lwatch.c.
enum file_event_t |
Possible states of a file we're monitoring.
FILE_NO_CHANGE | file has not changed |
FILE_APPENDED | file had data appended to it |
FILE_REPLACED | file had it's contents replaced |
Definition at line 351 of file lwatch.c.
00351 { 00352 FILE_NO_CHANGE, /**< file has not changed */ 00353 FILE_APPENDED, /**< file had data appended to it */ 00354 FILE_REPLACED, /**< file had it's contents replaced */ 00355 } file_event_t;
enum prog_action_t |
Operational program modes, e.g.
what the user wants the program to do.
PROG_ACTION_MONITOR | run in daemon mode monitoring files |
PROG_ACTION_LIST | dump the contents of file watch database |
PROG_ACTION_FIND | locate log files |
Definition at line 342 of file lwatch.c.
00342 { 00343 PROG_ACTION_MONITOR, /**< run in daemon mode monitoring files */ 00344 PROG_ACTION_LIST, /**< dump the contents of file watch database */ 00345 PROG_ACTION_FIND, /**< locate log files */ 00346 } prog_action_t;
static int compare_stat_info | ( | struct stat * | stat_info, | |
struct lwatch_path_info_t * | path_info, | |||
file_event_t * | result_arg | |||
) | [static] |
Compare operating system information about a file with our saved information, return how the file's state may have transformed.
[in] | stat_info | The stat information to compare against our saved information |
[in] | path_info | Our saved information about the file |
[in] | result_arg | A file_event_t enumeration describing the state transformation |
Definition at line 988 of file lwatch.c.
Referenced by get_path_info_reap_candidacy().
00989 { 00990 int error; 00991 file_event_t result; 00992 00993 error = SUCCESS; 00994 result = FILE_NO_CHANGE; 00995 00996 if (!(path_info->flags & STAT_DATA_VALID_FLAG)) { 00997 result = FILE_REPLACED; /* FIXME: is this really the correct state? */ 00998 goto exit; 00999 } 01000 01001 log_msg(LOG_DEBUG, _("st_size=%lu(%lu), st_dev=%llu(%llu) st_ino=%lu(%lu) st_mtime=%ld(%ld) \"%s\"\n"), 01002 01003 stat_info->st_size, path_info->size, 01004 stat_info->st_dev, path_info->dev, 01005 stat_info->st_ino, path_info->inode, 01006 stat_info->st_mtime, path_info->modification_time, 01007 path_info->path); 01008 01009 /* 01010 * First determine if this is the same file associate with the pathname 01011 */ 01012 01013 /* If the device or inode is different it must be a different file */ 01014 if ((stat_info->st_dev != path_info->dev) || (stat_info->st_ino != path_info->inode)) { 01015 result = FILE_REPLACED; 01016 } 01017 01018 /* If the size shrunk it must be a different file since log data is appended */ 01019 if (stat_info->st_size < path_info->size) { 01020 result = FILE_REPLACED; 01021 } 01022 01023 /* If the size increased the file was appended to */ 01024 if (stat_info->st_size > path_info->size) { 01025 result = FILE_APPENDED; 01026 } 01027 01028 exit: 01029 *result_arg = result; 01030 return error; 01031 }
int destroy_path_info | ( | struct lwatch_path_info_t ** | ppath_info | ) |
Release lwatch_path_info_t resources, free it's memory, set variable to NULL.
[out] | ppath_info | Pointer to a pointer of saved information about a file. Upon a successful return this pointer will be set to NULL. |
Definition at line 1151 of file lwatch.c.
01152 { 01153 struct lwatch_path_info_t *path_info; 01154 01155 if (!ppath_info) return EINVAL; 01156 path_info = *ppath_info; 01157 if (!path_info) return EINVAL; 01158 01159 free(path_info); 01160 *ppath_info = NULL; 01161 01162 return SUCCESS; 01163 }
static int dump_database | ( | ) | [static] |
Display the contents of the persistent log watch database.
Definition at line 1292 of file lwatch.c.
Referenced by main().
01293 { 01294 int error; 01295 struct database_iter_context_t *path_iter, *backup_iter; 01296 struct lwatch_path_info_t *path_info, *backup_path_info; 01297 01298 if ((error = database_query_all_paths_iter(&path_iter, NULL)) != SUCCESS) { 01299 log_msg(LOG_ERROR, _("database_query_all_iter failed (%s)\n"), error_string(error)); 01300 } 01301 01302 while ((path_info = path_iter->next(path_iter))) { 01303 if (path_info->flags & BACKUP_FLAG) 01304 continue; 01305 01306 printf("%s\n", path_info_string(path_info, "")); 01307 01308 if ((error = database_query_backups_of_target_iter(&backup_iter, path_info->path)) != SUCCESS) { 01309 log_msg(LOG_ERROR, _("database_query_backups_of_target_iter failed (%s)\n"), error_string(error)); 01310 } 01311 01312 while ((backup_path_info = backup_iter->next(backup_iter))) { 01313 printf("%s\n", path_info_string(backup_path_info, " ")); 01314 } 01315 free(backup_iter); 01316 } 01317 free(path_iter); 01318 01319 return SUCCESS; 01320 }
static const char * file_event_string | ( | file_event_t | event_type | ) | [static] |
Translate a file_event_t enumeration into a string.
[in] | event_type | The event type enumeartion whose string representation is sought. |
Definition at line 441 of file lwatch.c.
Referenced by get_path_info_reap_candidacy().
00442 { 00443 static __thread char buf[80]; /* thread local static buffer */ 00444 00445 switch(event_type) { 00446 case FILE_NO_CHANGE: return _("No change"); 00447 case FILE_APPENDED: return _("Appended"); 00448 case FILE_REPLACED: return _("Replaced"); 00449 default: 00450 snprintf(buf, sizeof(buf), "unknown(%d)", event_type); 00451 return buf; 00452 } 00453 00454 }
static int find_log_files | ( | const char * | dir_path, | |
int | recursive | |||
) | [static] |
Find potential log files in a directory (and below).
[in] | dir_path | Directory to search (from) |
[in] | recursive | True if the search should recursively descend into other directories. |
Definition at line 1605 of file lwatch.c.
Referenced by main().
01606 { 01607 int error; 01608 char path[PATH_MAX]; 01609 int count; 01610 01611 if ((error = make_normalized_absolute_path(path, sizeof(path), dir_path)) != SUCCESS) { 01612 log_msg(LOG_ERROR, _("failed make_normalized_absolute_path from \"%s\" (%s)\n"), 01613 dir_path, error_string(error)); 01614 return error; 01615 } 01616 01617 count = 0; 01618 directory_list(path, recursive, find_log_files_callback, &count); 01619 01620 return SUCCESS; 01621 }
static bool find_log_files_callback | ( | const char * | directory, | |
const char * | filename, | |||
const char * | path, | |||
struct stat * | info, | |||
void * | user_data | |||
) | [static] |
Recursive directory walk callback used to find potential log files.
[in] | directory | The current directory during the walk |
[in] | filename | The basename of the current directory entry |
[in] | path | The full pathname of the current directory entry (e.g. directory/filename) |
[in] | info | stat struct providing information about the directory entry |
[in] | user_data | Pointer to a count of found files |
Definition at line 1577 of file lwatch.c.
Referenced by find_log_files().
01578 { 01579 int *count = (int *)user_data; 01580 01581 if (!(S_ISREG(info->st_mode) || S_ISLNK(info->st_mode))) return true; 01582 01583 if (is_log_backup(path)) return true; 01584 01585 printf("%s\n", path); 01586 (*count)++; 01587 01588 return true; 01589 }
static int get_create_path_info | ( | const char * | path, | |
struct lwatch_path_info_t * | path_info | |||
) | [static] |
Given a path name lookup it's path_info, if it doesn't exist create it.
[in] | path | The path name to lookup. |
[out] | path_info | Pointer to path_info which will be initialized with result. |
Definition at line 463 of file lwatch.c.
Referenced by start_monitoring().
00464 { 00465 int error; 00466 00467 error = database_lookup_path_info(path, path_info); 00468 if ((error != SUCCESS) && (error != WATCH_DATABASE_ERROR_NOT_FOUND)) { 00469 log_msg(LOG_ERROR, _("database_lookup_path_info failed \"%s\" (%s)\n"), 00470 path, error_string(error)); 00471 return error; 00472 } 00473 00474 /* Did not exist in database, create a new path_info, intialize it, write it into the database */ 00475 if (error == WATCH_DATABASE_ERROR_NOT_FOUND) { 00476 if ((error = init_path_info(path_info, path)) != SUCCESS) { 00477 log_msg(LOG_ERROR, _("could not initialize path_info for path \"%s\" (%s)\n"), 00478 path, error_string(error)); 00479 return error; 00480 } 00481 00482 if ((error = database_write_path_info(path_info)) != SUCCESS) { 00483 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00484 path_info->path, error_string(error)); 00485 return error; 00486 } 00487 } 00488 00489 return SUCCESS; 00490 }
static int get_path_info_reap_candidacy | ( | struct lwatch_path_info_t * | path_info, | |
bool * | should_reap | |||
) | [static] |
Examine the file system, set parameter if the file should be reaped.
[in] | path_info | Our saved information about the file |
[out] | should_reap | Boolean result returned here |
Definition at line 1045 of file lwatch.c.
Referenced by set_path_info_reap_candidacy().
01046 { 01047 int error; 01048 struct stat cur_stat_info; 01049 file_event_t event_type; 01050 01051 *should_reap = false; 01052 01053 if (stat(path_info->path, &cur_stat_info) < 0) { 01054 error = errno; 01055 if (error == ENOENT) { /* file does not exist, not an error, just clear flag */ 01056 return SUCCESS; 01057 } 01058 log_msg(LOG_ERROR, _("cannot perform stat on \"%s\" (%s) \n"), 01059 path_info->path, error_string(error)); 01060 return error; 01061 } 01062 01063 if ((error = compare_stat_info(&cur_stat_info, path_info, &event_type)) != SUCCESS) { 01064 log_msg(LOG_ERROR, _("compare_stat_info failed \"%s\" (%s) \n"), 01065 path_info->path, error_string(error)); 01066 return error; 01067 } 01068 01069 log_msg(LOG_DEBUG, _("compare_stat_info(%s) returns %s\n"), 01070 path_info->path, file_event_string(event_type)); 01071 01072 01073 switch(event_type) { 01074 case FILE_NO_CHANGE: 01075 break; 01076 case FILE_APPENDED: 01077 case FILE_REPLACED: 01078 *should_reap = true; 01079 break; 01080 default: 01081 log_msg(LOG_ERROR, _("unknown event type = %d\n"), event_type); 01082 return EINVAL; 01083 } 01084 01085 return SUCCESS; 01086 }
bool is_log_backup | ( | const char * | path | ) |
Given a path name return true if it appears to be a rotated backup of a primary log file.
[in] | path | The path name to test. |
This routine uses regular expressions to intuit from a pathname if the pathname appears to follow a rotation backup naming convention. Only the pathname is considered, the file contents are not examined.
Currently there are two rotation backup naming conventions which are looked for, both are supported by the logrotate facility found on many machines.
Definition at line 1229 of file lwatch.c.
Referenced by find_log_files_callback(), and start_monitoring().
01230 { 01231 int num_matches; 01232 01233 if ((num_matches = regexp_search(&logrotate_numbered_backup_regexp, path)) > 0) { 01234 # if 0 01235 // FIXME: currently we don't use the sub-fields, this code is left as an 01236 // example of how to do that 01237 01238 char directory[PATH_MAX]; 01239 char filename[PATH_MAX]; 01240 char number[9]; 01241 char extension[PATH_MAX]; 01242 01243 regexp_substring(&logrotate_numbered_backup_regexp, 1, directory, sizeof(directory)); 01244 regexp_substring(&logrotate_numbered_backup_regexp, 2, filename, sizeof(filename)); 01245 regexp_substring(&logrotate_numbered_backup_regexp, 3, number, sizeof(number)); 01246 regexp_substring(&logrotate_numbered_backup_regexp, 4, extension, sizeof(extension)); 01247 01248 if (0) printf(" num_matches=%d directory=\"%s\" filename=\"%s\" number=\"%s\" extension=\"%s\" ", 01249 num_matches, directory, filename, number, extension); 01250 #endif 01251 return true; 01252 } 01253 if ((num_matches = regexp_search(&logrotate_date_backup_regexp, path)) > 0) { 01254 # if 0 01255 // FIXME: currently we don't use the sub-fields, this code is left as an 01256 // example of how to do that 01257 01258 char directory[PATH_MAX]; 01259 char filename[PATH_MAX]; 01260 char date[9]; 01261 char year[5]; 01262 char month[3]; 01263 char day[3]; 01264 char extension[PATH_MAX]; 01265 01266 regexp_substring(&logrotate_date_backup_regexp, 1, directory, sizeof(directory)); 01267 regexp_substring(&logrotate_date_backup_regexp, 2, filename, sizeof(filename)); 01268 regexp_substring(&logrotate_date_backup_regexp, 3, date, sizeof(date)); 01269 regexp_substring(&logrotate_date_backup_regexp, 4, year, sizeof(year)); 01270 regexp_substring(&logrotate_date_backup_regexp, 5, month, sizeof(month)); 01271 regexp_substring(&logrotate_date_backup_regexp, 6, day, sizeof(day)); 01272 regexp_substring(&logrotate_date_backup_regexp, 7, extension, sizeof(extension)); 01273 01274 if (0) printf(" num_matches=%d directory=\"%s\" filename=\"%s\" date=\"%s\" year=\"%s\" month=\"%s\" day=\"%s\" extension=\"%s\" ", 01275 num_matches, directory, filename, date, year, month, day, extension); 01276 #endif 01277 return true; 01278 } 01279 return false; 01280 }
static int lwatch_event_callback | ( | struct lwatch_event_t * | event | ) | [static] |
Respond to the events sent by the monitoring back end.
[in] | event | The lwatch_event_t to process |
Definition at line 864 of file lwatch.c.
00865 { 00866 int error; 00867 00868 log_msg(LOG_DEBUG, _("event: %s\n"), lwatch_event_string(event)); 00869 00870 switch(event->event_type) { 00871 case LWATCH_EVENT_CREATE: 00872 if ((error = process_file_create(event->path)) != SUCCESS) { 00873 log_msg(LOG_ERROR, _("process_file_create failed for \"%s\" (%s)\n"), 00874 event->path, error_string(error)); 00875 } 00876 break; 00877 case LWATCH_EVENT_OPEN: 00878 break; 00879 case LWATCH_EVENT_DELETE: 00880 if ((error = process_file_delete(event->path)) != SUCCESS) { 00881 log_msg(LOG_ERROR, _("process_file_delete failed for \"%s\" (%s)\n"), 00882 event->path, error_string(error)); 00883 } 00884 break; 00885 case LWATCH_EVENT_RENAME: 00886 if ((error = process_file_rename(event->rename.prev_path, event->rename.new_path)) != SUCCESS) { 00887 log_msg(LOG_ERROR, _("process_file_rename failed for \"%s\" --> \"%s\" (%s)\n"), 00888 event->rename.prev_path, event->rename.new_path, error_string(error)); 00889 } 00890 break; 00891 case LWATCH_EVENT_MODIFY: 00892 if ((error = process_file_modification(event->path)) != SUCCESS) { 00893 log_msg(LOG_ERROR, _("process_file_modification failed for \"%s\" (%s)\n"), 00894 event->path, error_string(error)); 00895 } 00896 break; 00897 case LWATCH_EVENT_CLOSE: 00898 if ((error = process_file_close(event->path)) != SUCCESS) { 00899 log_msg(LOG_ERROR, _("process_file_close failed for \"%s\" (%s)\n"), 00900 event->path, error_string(error)); 00901 } 00902 break; 00903 default: 00904 log_msg(LOG_ERROR, _("unknown watch event type \"%s\"\n"), lwatch_event_string(event)); 00905 return EINVAL; 00906 } 00907 00908 return SUCCESS; 00909 }
static const char * lwatch_event_string | ( | struct lwatch_event_t * | event | ) | [static] |
Given a lwatch_event_t render it as a string.
[in] | event | The lwatch_event_t whose string representation is desired |
Definition at line 829 of file lwatch.c.
Referenced by lwatch_event_callback().
00830 { 00831 static __thread char buf[512 + PATH_MAX * 2]; /* thread local static buffer */ 00832 char *p, *buf_end; 00833 00834 p = buf; /* current position in buffer */ 00835 buf_end = &buf[sizeof(buf)]; /* non-inclusive end of buffer */ 00836 *p = 0; 00837 00838 p += snprintf(p, buf_end - p, "[%s] ", lwatch_event_type_string(event->event_type)); 00839 if (p >= buf_end) goto fail; 00840 if (event->event_type == LWATCH_EVENT_RENAME) { 00841 p += snprintf(p, buf_end - p, "prev_path=\"%s\" ", event->rename.prev_path); 00842 if (p >= buf_end) goto fail; 00843 p += snprintf(p, buf_end - p, "new_path=\"%s\"", event->rename.new_path); 00844 if (p >= buf_end) goto fail; 00845 } else { 00846 p += snprintf(p, buf_end - p, "path=\"%s\"", event->path); 00847 if (p >= buf_end) goto fail; 00848 } 00849 00850 return buf; 00851 00852 fail: 00853 /* exhausted the buffer; NULL terminate then return truncated string */ 00854 buf_end[-1] = 0; /* should already be NULL terminated, but be safe */ 00855 return buf; 00856 }
static const char * lwatch_event_type_string | ( | lwatch_event_type | event_type | ) | [static] |
Given a lwatch_event_type enumeration return it's name as a string.
[in] | event_type | The event type enumeration who name is desired. |
Definition at line 806 of file lwatch.c.
Referenced by lwatch_event_string().
00807 { 00808 static __thread char buf[80]; /* thread local static buffer */ 00809 00810 switch(event_type) { 00811 case LWATCH_EVENT_CREATE: return "Created"; 00812 case LWATCH_EVENT_DELETE: return "Deleted"; 00813 case LWATCH_EVENT_RENAME: return "Renamed"; 00814 case LWATCH_EVENT_MODIFY: return "Modified"; 00815 case LWATCH_EVENT_OPEN: return "Opened"; 00816 case LWATCH_EVENT_CLOSE: return "Closed"; 00817 default: 00818 snprintf(buf, sizeof(buf), "unknown(%d)", event_type); 00819 return buf; 00820 } 00821 }
static int lwatch_fini | ( | ) | [static] |
Close down the log watch system.
Definition at line 767 of file lwatch.c.
Referenced by main().
00768 { 00769 int error; 00770 00771 if ((error = inotify_watch_fini()) != SUCCESS) { 00772 log_msg(LOG_ERROR, _("inotify_watch_fini() failed (%s)\n"), error_string(error)); 00773 } 00774 00775 return SUCCESS; 00776 }
static int lwatch_init | ( | void | ) | [static] |
Initialize the log watcher.
Definition at line 735 of file lwatch.c.
Referenced by main().
00736 { 00737 int error; 00738 00739 signal(SIGHUP, signal_handler); 00740 signal(SIGINT, signal_handler); 00741 signal(SIGQUIT, signal_handler); 00742 00743 keep_watching = true; 00744 00745 /* Initialize the monitoring backend */ 00746 if ((error = inotify_watch_init()) != SUCCESS) { 00747 log_msg(LOG_ERROR, _("inotify_watch_init() failed (%s)\n"), error_string(error)); 00748 return error; 00749 } 00750 /* Connect ourself to the backend via a callback */ 00751 register_lwatch_event_callback(lwatch_event_callback); 00752 00753 /* Check to see what changed since the last time we ran */ 00754 if ((error = validate_backups_in_database()) != SUCCESS) { 00755 log_msg(LOG_ERROR, _("validate_backups_in_database() failed (%s)\n"), error_string(error)); 00756 return error; 00757 } 00758 00759 return SUCCESS; 00760 }
int main | ( | int | argc, | |
char ** | argv | |||
) |
Main program entry point.
[in] | argc | Count of how many program arguments |
[in] | argv | Array of program argument strings |
Definition at line 1676 of file lwatch.c.
01677 { 01678 int error; 01679 int i; 01680 prog_action_t prog_action = PROG_ACTION_MONITOR; 01681 bool recursive = false; 01682 int log_level = LOG_WARN; 01683 char *logfile_path = NULL; 01684 01685 log_set_show_level(true); 01686 log_set_show_file(false); 01687 log_set_show_line(false); 01688 log_set_show_function(true); 01689 log_set_show_time(false); 01690 01691 01692 while (1) { 01693 int arg; 01694 int option_index = 0; 01695 static struct option long_options[] = { 01696 {"help", 0, 0, 'h'}, 01697 {"find", 0, 0, 'f'}, 01698 {"recursive", 0, 0, 'r'}, 01699 {"list", 0, 0, 'l'}, 01700 {"interval", 1, 0, 'i'}, 01701 {"log_level", 1, 0, LOG_LEVEL_ARG}, 01702 {"log_to_console", 0, 0, LOG_TO_CONSOLE_ARG}, 01703 {"logfile_path", 0, 0, LOGFILE_PATH_ARG}, 01704 {"no_logging_to_file", 0, 0, NO_LOGGING_TO_FILE_ARG}, 01705 {"log_show_level", 0, 0, LOG_SHOW_LEVEL_ARG}, 01706 {"log_no_show_level", 0, 0, LOG_NO_SHOW_LEVEL_ARG}, 01707 {"log_show_file", 0, 0, LOG_SHOW_FILE_ARG}, 01708 {"log_no_show_file", 0, 0, LOG_NO_SHOW_FILE_ARG}, 01709 {"log_show_line", 0, 0, LOG_SHOW_LINE_ARG}, 01710 {"log_no_show_line", 0, 0, LOG_NO_SHOW_LINE_ARG}, 01711 {"log_show_function", 0, 0, LOG_SHOW_FUNCTION_ARG}, 01712 {"log_no_show_function", 0, 0, LOG_NO_SHOW_FUNCTION_ARG}, 01713 {"log_show_time", 0, 0, LOG_SHOW_TIME_ARG}, 01714 {"log_no_show_time", 0, 0, LOG_NO_SHOW_TIME_ARG}, 01715 {0, 0, 0, 0} 01716 }; 01717 01718 arg = getopt_long(argc, argv, "hfrli:", 01719 long_options, &option_index); 01720 if (arg == -1) break; 01721 01722 switch (arg) { 01723 case 'h': 01724 usage(); 01725 exit(0); 01726 break; 01727 case 'f': 01728 prog_action = PROG_ACTION_FIND; 01729 break; 01730 case 'r': 01731 recursive = true; 01732 break; 01733 case 'l': 01734 prog_action = PROG_ACTION_LIST; 01735 break; 01736 case 'i': 01737 reap_interval = atoi(optarg); 01738 break; 01739 case LOG_LEVEL_ARG: 01740 if (log_level_from_string(optarg, &log_level) != SUCCESS) { 01741 fprintf(stderr, _("unknown log level: %s\n"), optarg); 01742 } 01743 break; 01744 case LOG_TO_CONSOLE_ARG: 01745 log_to_console(true); 01746 break; 01747 case LOGFILE_PATH_ARG: 01748 logfile_path = optarg; 01749 break; 01750 case NO_LOGGING_TO_FILE_ARG: 01751 log_to_file(false); 01752 break; 01753 01754 case LOG_SHOW_LEVEL_ARG: 01755 log_set_show_level(true); 01756 break; 01757 case LOG_NO_SHOW_LEVEL_ARG: 01758 log_set_show_level(false); 01759 break; 01760 case LOG_SHOW_FILE_ARG: 01761 log_set_show_file(true); 01762 break; 01763 case LOG_NO_SHOW_FILE_ARG: 01764 log_set_show_file(false); 01765 break; 01766 case LOG_SHOW_LINE_ARG: 01767 log_set_show_line(true); 01768 break; 01769 case LOG_NO_SHOW_LINE_ARG: 01770 log_set_show_line(false); 01771 break; 01772 case LOG_SHOW_FUNCTION_ARG: 01773 log_set_show_function(true); 01774 break; 01775 case LOG_NO_SHOW_FUNCTION_ARG: 01776 log_set_show_function(false); 01777 break; 01778 case LOG_SHOW_TIME_ARG: 01779 log_set_show_time(true); 01780 break; 01781 case LOG_NO_SHOW_TIME_ARG: 01782 log_set_show_time(false); 01783 break; 01784 01785 default: 01786 usage(); 01787 exit(1); 01788 break; 01789 } 01790 } 01791 01792 log_set_filepath(logfile_path); 01793 log_set_level(log_level); 01794 if ((error = log_init()) != SUCCESS) { 01795 fprintf(stderr, _("log initialization failed (%s)\n"), error_string(error)); 01796 return 1; 01797 } 01798 01799 if ((error = regexp_init()) != SUCCESS) { 01800 log_msg(LOG_ERROR, _("regexp initialization failed (%s)\n"), error_string(error)); 01801 return 1; 01802 } 01803 01804 if ((error = watch_database_init()) != SUCCESS) { 01805 log_msg(LOG_ERROR, _("watch_database initialization failed (%s)\n"), error_string(error)); 01806 return 1; 01807 } 01808 01809 if ((error = lwatch_init()) != SUCCESS) { 01810 log_msg(LOG_ERROR, _("lwatch initialization failed (%s)\n"), error_string(error)); 01811 return 1; 01812 } 01813 01814 switch (prog_action) { 01815 case PROG_ACTION_MONITOR: 01816 for (i = optind; i < argc; i++) { 01817 char *path = argv[i]; 01818 01819 if ((error = start_monitoring(path)) != SUCCESS) { 01820 log_msg(LOG_ERROR, _("could not monitor \"%s\" (%s)\n"), 01821 path, error_string(error)); 01822 } 01823 } 01824 01825 main_loop(); 01826 01827 /* Before we exit assure we reap any outstanding data which might still be pending */ 01828 if ((error = process_pending_reaps()) != SUCCESS) { 01829 log_msg(LOG_ERROR, _("error processing pending reaps (%s)\n"), 01830 error_string(error)); 01831 } 01832 01833 break; 01834 case PROG_ACTION_FIND: 01835 for (i = optind; i < argc; i++) { 01836 char *path = argv[i]; 01837 01838 if ((error = find_log_files(path, recursive)) != SUCCESS) { 01839 log_msg(LOG_ERROR, _("could not find log files \"%s\" (%s)\n"), 01840 path, error_string(error)); 01841 } 01842 } 01843 break; 01844 case PROG_ACTION_LIST: 01845 dump_database(); 01846 break; 01847 } 01848 01849 if ((error = lwatch_fini()) != SUCCESS) { 01850 log_msg(LOG_ERROR, _("lwatch finalization failed (%s)\n"), error_string(error)); 01851 } 01852 01853 if ((error = regexp_fini()) != SUCCESS) { 01854 log_msg(LOG_ERROR, _("regexp finalization failed (%s)\n"), error_string(error)); 01855 } 01856 01857 if ((error = watch_database_fini()) != SUCCESS) { 01858 log_msg(LOG_ERROR, _("watch_database finalization failed (%s)\n"), error_string(error)); 01859 } 01860 01861 if ((error = log_fini()) != SUCCESS) { 01862 fprintf(stderr, _("log finalization failed (%s)\n"), error_string(error)); 01863 } 01864 01865 return 0; 01866 }
static int main_loop | ( | ) | [static] |
Main loop when running in daemon monitor mode.
Definition at line 1518 of file lwatch.c.
Referenced by main().
01519 { 01520 int error; 01521 int result; 01522 fd_set read_fds; 01523 int inotify_fd; 01524 struct timeval timeout; 01525 01526 inotify_fd = get_inotify_fd(); 01527 01528 timeout.tv_sec = reap_interval; 01529 timeout.tv_usec = 0; 01530 01531 while (keep_watching) { 01532 FD_ZERO(&read_fds); 01533 FD_SET(inotify_fd, &read_fds); 01534 01535 result = select(inotify_fd + 1, &read_fds, NULL, NULL, &timeout); 01536 if (result == -1) { /* error */ 01537 error = errno; 01538 if (error != EINTR) { 01539 log_msg(LOG_ERROR, _("select error (%s)\n"), 01540 error_string(error)); 01541 } 01542 } else if (result) { /* data available */ 01543 read_events(); 01544 } else { /* timeout */ 01545 /* The timeout expired, it needs to be reset */ 01546 timeout.tv_sec = reap_interval; 01547 timeout.tv_usec = 0; 01548 01549 if ((error = process_pending_reaps()) != SUCCESS) { 01550 log_msg(LOG_ERROR, _("error processing pending reaps (%s)\n"), 01551 error_string(error)); 01552 } 01553 } 01554 } 01555 01556 return SUCCESS; 01557 }
static int process_file_close | ( | const char * | path | ) | [static] |
A file has been closed, test if it will need to be reaped and record reap status.
[in] | path | Path name of the watch target to take action on. |
Definition at line 526 of file lwatch.c.
Referenced by lwatch_event_callback().
00527 { 00528 int error; 00529 struct lwatch_path_info_t path_info; 00530 00531 if ((error = database_lookup_path_info(path, &path_info)) != SUCCESS) { 00532 log_msg(LOG_ERROR, _("database_lookup_path_info failed \"%s\" (%s)\n"), 00533 path, error_string(error)); 00534 return LWATCH_ERROR_CANNOT_FIND_PATH_INFO; 00535 } 00536 00537 if ((error = set_path_info_reap_candidacy(&path_info)) != SUCCESS) { 00538 log_msg(LOG_ERROR, _("get_path_info_reap_candidacy failed \"%s\" (%s)\n"), 00539 path, error_string(error)); 00540 return error; 00541 } 00542 00543 if ((error = database_write_path_info(&path_info)) != SUCCESS) { 00544 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00545 path_info.path, error_string(error)); 00546 return error; 00547 } 00548 00549 return SUCCESS; 00550 }
static int process_file_create | ( | const char * | path | ) | [static] |
A file has been opened, validate it's a watch target.
[in] | path | Path name of the watch target to take action on. |
Definition at line 558 of file lwatch.c.
Referenced by lwatch_event_callback().
00559 { 00560 int error; 00561 struct lwatch_path_info_t path_info; 00562 00563 if ((error = database_lookup_path_info(path, &path_info)) != SUCCESS) { 00564 log_msg(LOG_ERROR, _("database_lookup_path_info failed \"%s\" (%s)\n"), 00565 path, error_string(error)); 00566 return LWATCH_ERROR_CANNOT_FIND_PATH_INFO; 00567 } 00568 00569 return SUCCESS; 00570 }
static int process_file_delete | ( | const char * | path | ) | [static] |
A file has been deleted, record that it's file contents will be different.
[in] | path | Path name of the watch target to take action on. |
Definition at line 578 of file lwatch.c.
Referenced by lwatch_event_callback().
00579 { 00580 int error; 00581 struct lwatch_path_info_t path_info; 00582 00583 if ((error = database_lookup_path_info(path, &path_info)) != SUCCESS) { 00584 log_msg(LOG_ERROR, _("database_lookup_path_info failed \"%s\" (%s)\n"), 00585 path, error_string(error)); 00586 return LWATCH_ERROR_CANNOT_FIND_PATH_INFO; 00587 } 00588 00589 PATH_INFO_FLAG_SET_NEW_FILE(&path_info); 00590 00591 if ((error = database_write_path_info(&path_info)) != SUCCESS) { 00592 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00593 path_info.path, error_string(error)); 00594 return error; 00595 } 00596 00597 00598 return SUCCESS; 00599 }
static int process_file_modification | ( | const char * | path | ) | [static] |
A file has been modified, record that it will need to be reaped.
[in] | path | Path name of the watch target to take action on. |
Definition at line 498 of file lwatch.c.
Referenced by lwatch_event_callback().
00499 { 00500 int error; 00501 struct lwatch_path_info_t path_info; 00502 00503 if ((error = database_lookup_path_info(path, &path_info)) != SUCCESS) { 00504 log_msg(LOG_ERROR, _("database_lookup_path_info failed \"%s\" (%s)\n"), 00505 path, error_string(error)); 00506 return LWATCH_ERROR_CANNOT_FIND_PATH_INFO; 00507 } 00508 00509 path_info.flags |= NEEDS_REAPING_FLAG; 00510 00511 if ((error = database_write_path_info(&path_info)) != SUCCESS) { 00512 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00513 path_info.path, error_string(error)); 00514 return error; 00515 } 00516 00517 return SUCCESS; 00518 }
static int process_file_rename | ( | const char * | prev_path, | |
const char * | new_path | |||
) | [static] |
A file has been renamed, track both the old and new file contents.
[in] | prev_path | Previous path name of the watch target |
[in] | new_path | New path name of the watch target |
Definition at line 631 of file lwatch.c.
Referenced by lwatch_event_callback().
00632 { 00633 int error; 00634 struct lwatch_path_info_t prev_pathinfo, new_pathinfo; 00635 00636 log_msg(LOG_DEBUG, _("\"%s\" --> \"%s\"\n"), prev_path, new_path); 00637 00638 /* 00639 * The backend used to watch file events may not be capable of knowing both 00640 * the previous and new path names thus we have to be prepared for one of 00641 * the two names being empty, we call this a lost rename (no rename event 00642 * will be generated if neither is known). Logically it should be impossible 00643 * for the previous name to be lost because we had a watch established on 00644 * it, if the previous name is lost we consider this a serious 00645 * error. However we might not know what the watched file was renamed to. 00646 * A lost new name is not considered a serious error, it's just an 00647 * unfortunate lack of information, but we need to be prepared for it. 00648 */ 00649 00650 if (!prev_path[0]) { 00651 log_msg(LOG_ERROR, _("%s: previous path is empty, should have been a file in the set of watched files\n")); 00652 return LWATCH_ERROR_LOST_RENAME; 00653 } 00654 00655 if ((error = database_lookup_path_info(prev_path, &prev_pathinfo)) != SUCCESS) { 00656 log_msg(LOG_ERROR, _("database_lookup_path_info failed \"%s\" (%s)\n"), 00657 prev_path, error_string(error)); 00658 return LWATCH_ERROR_CANNOT_FIND_PATH_INFO; 00659 } 00660 00661 if (new_path[0]) { /* new path is known */ 00662 00663 /* copy the paths, mark it as a backup, save the path_info, monitor the new file */ 00664 new_pathinfo = prev_pathinfo; 00665 if ((error = copy_path(new_pathinfo.path, new_path, sizeof(new_pathinfo.path))) != SUCCESS) { 00666 log_msg(LOG_ERROR, _("failed to copy path \"%s\" (%s)\n"), new_path, error_string(error)); 00667 return error; 00668 } 00669 if ((error = copy_path(new_pathinfo.original_path, prev_path, sizeof(new_pathinfo.original_path))) != SUCCESS) { 00670 log_msg(LOG_ERROR, _("failed to copy path \"%s\" (%s)\n"), prev_path, error_string(error)); 00671 return error; 00672 } 00673 PATH_INFO_FLAG_SET_BACKUP(&new_pathinfo); 00674 00675 if ((error = database_write_path_info(&new_pathinfo)) != SUCCESS) { 00676 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00677 new_pathinfo.path, error_string(error)); 00678 } 00679 00680 if ((error = inotify_start_monitoring(new_path)) != SUCCESS) { 00681 log_msg(LOG_ERROR, _("could not inotify_start_monitoring for \"%s\" (%s)\n"), 00682 new_path, error_string(error)); 00683 } 00684 } 00685 00686 /* Record the primary file will be a new file */ 00687 prev_pathinfo.original_path[0] = 0; 00688 PATH_INFO_FLAG_SET_NEW_FILE(&prev_pathinfo); 00689 prev_pathinfo.reap_time = 0; 00690 prev_pathinfo.reap_position = 0; 00691 00692 if ((error = database_write_path_info(&prev_pathinfo)) != SUCCESS) { 00693 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00694 prev_pathinfo.path, error_string(error)); 00695 return error; 00696 } 00697 00698 return SUCCESS; 00699 }
static int process_pending_reaps | ( | ) | [static] |
For each file in the database marked as needing to be reaped perform a reap.
Definition at line 1426 of file lwatch.c.
Referenced by main(), and main_loop().
01427 { 01428 int error; 01429 struct database_iter_context_t *iter; 01430 struct lwatch_path_info_t *path_info; 01431 01432 log_msg(LOG_DEBUG, _("process_pending_reaps\n")); 01433 01434 if ((error = database_query_pending_reaps_iter(&iter)) != SUCCESS) { 01435 log_msg(LOG_ERROR, _("database_query_pending_reaps_iter failed (%s)\n"), 01436 error_string(error)); 01437 return error; 01438 } 01439 01440 while ((path_info = iter->next(iter))) { 01441 if ((error = reap_file_data(path_info)) != SUCCESS) { 01442 log_msg(LOG_ERROR, _("cannot reap file data for \"%s\" (%s)\n"), 01443 path_info->path, error_string(error)); 01444 } 01445 } 01446 free(iter); 01447 01448 return SUCCESS; 01449 }
static int reap_file_data | ( | struct lwatch_path_info_t * | path_info | ) | [static] |
The file has already been identified for reaping, perform the reap by collecting the file contents and updating our bookkeeping.
[in] | path_info | Our saved information about the file |
Definition at line 1458 of file lwatch.c.
Referenced by process_pending_reaps().
01459 { 01460 int error; 01461 struct stat stat_info; 01462 const char *path; 01463 size_t length; 01464 01465 path = path_info->path; 01466 if (stat(path, &stat_info) < 0) { 01467 error = errno; 01468 log_msg(LOG_ERROR, _("cannot perform stat on \"%s\" (%s) \n"), 01469 path, error_string(error)); 01470 01471 if (error == ENOENT) { /* path does not exist, report error, remove reap request */ 01472 int write_error; 01473 01474 log_msg(LOG_ERROR, _("deleted \"%s\" before being fully collected\n"), path); 01475 01476 path_info->flags &= ~NEEDS_REAPING_FLAG; 01477 01478 if ((write_error = database_write_path_info(path_info)) != SUCCESS) { 01479 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 01480 path_info->path, error_string(write_error)); 01481 } 01482 } 01483 return error; 01484 } 01485 01486 if (path_info->flags & INC_VERSION_FLAG) { 01487 path_info->version++; 01488 path_info->flags &= ~INC_VERSION_FLAG; 01489 } 01490 01491 length = stat_info.st_size - path_info->reap_position; 01492 01493 printf("REAP \"%s\" [%lu:%lu]\n", path, path_info->reap_position, path_info->reap_position + length); 01494 01495 path_info->reap_position = path_info->reap_position + length; 01496 path_info->reap_time = time(NULL); 01497 path_info->flags &= ~NEEDS_REAPING_FLAG; 01498 if ((error = update_stat_info_and_write(&stat_info, path_info)) != SUCCESS) { 01499 log_msg(LOG_ERROR, _("could not update_stat_info_and_write for \"%s\" (%s) \n"), 01500 path, error_string(error)); 01501 return error; 01502 } 01503 01504 return SUCCESS; 01505 }
static int regexp_fini | ( | void | ) | [static] |
Close our regular expression usage by releasing resources.
Definition at line 720 of file lwatch.c.
Referenced by main().
00721 { 00722 regexp_free(&logrotate_numbered_backup_regexp); 00723 regexp_free(&logrotate_date_backup_regexp); 00724 return SUCCESS; 00725 }
static int regexp_init | ( | void | ) | [static] |
Initialize our regular expressions.
Definition at line 706 of file lwatch.c.
Referenced by main().
00707 { 00708 int error; 00709 00710 if ((error = regexp_compile(&logrotate_numbered_backup_regexp)) != SUCCESS) return error; 00711 if ((error = regexp_compile(&logrotate_date_backup_regexp)) != SUCCESS) return error; 00712 return SUCCESS; 00713 }
static int set_path_info_reap_candidacy | ( | struct lwatch_path_info_t * | path_info | ) | [static] |
Determine if watched file needs to be reaped, set internal flag accordingly.
[in] | path_info | Our saved information about the file, flag updated here |
Definition at line 1094 of file lwatch.c.
Referenced by process_file_close(), start_monitoring(), and validate_backups_in_database().
01095 { 01096 int error; 01097 bool should_reap; 01098 01099 if ((error = get_path_info_reap_candidacy(path_info, &should_reap)) != SUCCESS) { 01100 if (error == ENOENT) { /* file does not exist, not an error, just clear flag */ 01101 path_info->flags &= ~NEEDS_REAPING_FLAG; 01102 return SUCCESS; 01103 } 01104 } 01105 01106 if (should_reap) { 01107 path_info->flags |= NEEDS_REAPING_FLAG; 01108 } else { 01109 path_info->flags &= ~NEEDS_REAPING_FLAG; 01110 } 01111 return SUCCESS; 01112 }
static void signal_handler | ( | int | signum | ) | [static] |
Respond to signals.
[in] | signum | The signal number we received |
Definition at line 784 of file lwatch.c.
Referenced by lwatch_init().
00785 { 00786 log_msg(LOG_INFO, _("received signal %s(%d)\n"), strsignal(signum), signum); 00787 00788 switch(signum) { 00789 case SIGHUP: 00790 break; 00791 case SIGINT: 00792 keep_watching = false; 00793 break; 00794 case SIGQUIT: 00795 keep_watching = false; 00796 break; 00797 } 00798 }
static int start_monitoring | ( | const char * | path_arg | ) | [static] |
Start monitoring a primary file.
[in] | path_arg | The path name to monitor, will be normalized and made absolute |
Definition at line 923 of file lwatch.c.
Referenced by main().
00924 { 00925 int error; 00926 struct lwatch_path_info_t path_info; 00927 char path[PATH_MAX]; 00928 00929 if ((error = make_normalized_absolute_path(path, sizeof(path), path_arg)) != SUCCESS) { 00930 log_msg(LOG_ERROR, _("failed make_normalized_absolute_path from \"%s\" (%s)\n"), 00931 path_arg, error_string(error)); 00932 return error; 00933 } 00934 00935 log_msg(LOG_INFO, _("monitoring \"%s\"\n"), path); 00936 00937 if (is_log_backup(path)) { 00938 log_msg(LOG_WARN, _("file \"%s\" appears to be a log backup, only original log files should be monitored\n"), 00939 path); 00940 } 00941 00942 if ((error = get_create_path_info(path, &path_info)) != SUCCESS) { 00943 log_msg(LOG_ERROR, _("get_create_path_info failed \"%s\" (%s)\n"), 00944 path, error_string(error)); 00945 return LWATCH_ERROR_CANNOT_MONITOR; 00946 } 00947 00948 PATH_INFO_FLAG_SET_TARGET(&path_info); 00949 00950 if ((error = set_path_info_reap_candidacy(&path_info)) != SUCCESS) { 00951 log_msg(LOG_ERROR, _("set_path_info_reap_candidacy failed \"%s\" (%s)\n"), 00952 path, error_string(error)); 00953 return LWATCH_ERROR_CANNOT_MONITOR; 00954 } 00955 00956 if ((error = database_write_path_info(&path_info)) != SUCCESS) { 00957 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 00958 path_info.path, error_string(error)); 00959 return error; 00960 } 00961 00962 if (!is_watch_target(path)) { 00963 if ((error = inotify_start_monitoring(path)) != SUCCESS) { 00964 log_msg(LOG_ERROR, _("could not inotify_start_monitoring for \"%s\" (%s)\n"), 00965 path, error_string(error)); 00966 return LWATCH_ERROR_CANNOT_MONITOR; 00967 } 00968 } 00969 00970 return SUCCESS; 00971 }
int update_stat_info | ( | struct stat * | cur_stat_info, | |
struct lwatch_path_info_t * | path_info | |||
) |
Merge stat information into path into our saved information about the file.
[in] | cur_stat_info | Pointer to stat data to update from, or if NULL call stat() to obtain info |
[in] | path_info | Our saved information about the file |
Definition at line 1173 of file lwatch.c.
Referenced by update_stat_info_and_write().
01174 { 01175 int error; 01176 struct stat stat_info; 01177 01178 if (cur_stat_info == NULL) { 01179 if (stat(path_info->path, &stat_info) < 0) { 01180 error = errno; 01181 log_msg(LOG_ERROR, _("cannot perform stat on \"%s\" (%s) \n"), 01182 path_info->path, error_string(error)); 01183 return error; 01184 } 01185 cur_stat_info = &stat_info; 01186 } 01187 01188 path_info->dev = cur_stat_info->st_dev; 01189 path_info->inode = cur_stat_info->st_ino; 01190 path_info->mode = cur_stat_info->st_mode; 01191 path_info->uid = cur_stat_info->st_uid; 01192 path_info->gid = cur_stat_info->st_gid; 01193 path_info->size = cur_stat_info->st_size; 01194 path_info->access_time = cur_stat_info->st_atime; 01195 path_info->modification_time = cur_stat_info->st_mtime; 01196 path_info->change_time = cur_stat_info->st_ctime; 01197 01198 path_info->flags |= STAT_DATA_VALID_FLAG; 01199 01200 return SUCCESS; 01201 }
static int update_stat_info_and_write | ( | struct stat * | cur_stat_info, | |
struct lwatch_path_info_t * | path_info | |||
) | [static] |
Merge stat information about a file into our struct and write the updated entry in the persistent database.
[in] | cur_stat_info | Pointer to stat data to update from, or if NULL call stat() to obtain info |
[in] | path_info | Our saved information about the file |
Definition at line 1123 of file lwatch.c.
Referenced by reap_file_data().
01124 { 01125 int error; 01126 01127 if ((error = update_stat_info(cur_stat_info, path_info)) != SUCCESS) { 01128 log_msg(LOG_ERROR, _("could not update_stat_info for \"%s\" (%s) \n"), 01129 path_info->path, error_string(error)); 01130 } 01131 01132 if ((error = database_write_path_info(path_info)) != SUCCESS) { 01133 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 01134 path_info->path, error_string(error)); 01135 return error; 01136 } 01137 return SUCCESS; 01138 }
static int validate_backups_in_database | ( | ) | [static] |
Check the state of known backups since the last time we ran.
Definition at line 1354 of file lwatch.c.
Referenced by lwatch_init().
01355 { 01356 int error; 01357 struct database_iter_context_t *path_iter; 01358 struct lwatch_path_info_t *path_info; 01359 01360 struct lwatch_path_info_t *path_info_updates; 01361 int i, alloc_increment, alloc_count, update_count; 01362 01363 alloc_increment = 8; 01364 alloc_count = 0; 01365 update_count = 0; 01366 path_info_updates = NULL; 01367 01368 if ((error = database_query_backups_iter(&path_iter)) != SUCCESS) { 01369 log_msg(LOG_ERROR, _("database_query_backups_iter failed (%s)\n"), error_string(error)); 01370 } 01371 01372 while ((path_info = path_iter->next(path_iter))) { 01373 if (!(path_info->flags & NEEDS_REAPING_FLAG)) { /* no sense in checking if flag is already set */ 01374 if ((error = set_path_info_reap_candidacy(path_info)) != SUCCESS) { 01375 log_msg(LOG_ERROR, _("set_path_info_reap_candidacy failed \"%s\" (%s)\n"), 01376 path_info->path, error_string(error)); 01377 } 01378 if (path_info->flags & NEEDS_REAPING_FLAG) { /* flag was set above, remember we have to update this path_info*/ 01379 if (update_count == alloc_count) { 01380 alloc_count += alloc_increment; 01381 if ((path_info_updates = realloc(path_info_updates, alloc_count * sizeof(struct lwatch_path_info_t))) == NULL) { 01382 error = ENOMEM; 01383 free(path_info_updates); 01384 free(path_iter); 01385 log_msg(LOG_ERROR, _("could not alloc memory for update array (%s)\n"), error_string(error)); 01386 return error; 01387 } 01388 } 01389 path_info_updates[update_count++] = *path_info; 01390 } 01391 } 01392 01393 if ((error = inotify_start_monitoring(path_info->path)) != SUCCESS) { 01394 log_msg(LOG_ERROR, _("could not inotify_start_monitoring for \"%s\" (%s)\n"), 01395 path_info->path, error_string(error)); 01396 } 01397 } 01398 free(path_iter); 01399 01400 /* If there were updates, now it's time to iterate over them and write the update */ 01401 for (i = 0, path_info = path_info_updates; i < update_count; i++, path_info++) { 01402 if ((error = database_write_path_info(path_info)) != SUCCESS) { 01403 log_msg(LOG_ERROR, _("could not insert path_info into database for \"%s\" (%s)\n"), 01404 path_info->path, error_string(error)); 01405 } 01406 } 01407 01408 if (path_info_updates) free(path_info_updates); 01409 01410 return SUCCESS; 01411 }