parser.c (goaccess-1.7.1) | : | parser.c (goaccess-1.7.2) | ||
---|---|---|---|---|
skipping to change at line 137 | skipping to change at line 137 | |||
/* Allocate, initialize and add the given filename to our logs structure. | /* Allocate, initialize and add the given filename to our logs structure. | |||
* | * | |||
* On error, 1 is returned. | * On error, 1 is returned. | |||
* On success, the given filename is added to the Logs structure and 0 is | * On success, the given filename is added to the Logs structure and 0 is | |||
* returned. */ | * returned. */ | |||
int | int | |||
set_glog (Logs * logs, const char *filename) { | set_glog (Logs * logs, const char *filename) { | |||
GLog *tmp = NULL, *glog = NULL; | GLog *tmp = NULL, *glog = NULL; | |||
int newlen = 0; | int newlen = 0; | |||
char const *err; | char const *err; | |||
char *fvh = NULL, *fn = (char *) filename; | char *fvh = NULL, *fn = NULL; | |||
if (logs->size - 1 < logs->idx) { | if (logs->size - 1 < logs->idx) { | |||
newlen = logs->size + 1; | newlen = logs->size + 1; | |||
if (!(tmp = xrealloc (logs->glog, newlen * sizeof (GLog)))) | if (!(tmp = xrealloc (logs->glog, newlen * sizeof (GLog)))) | |||
return ERR_LOG_REALLOC_FAILURE; | return ERR_LOG_REALLOC_FAILURE; | |||
logs->glog = tmp; | logs->glog = tmp; | |||
memset (logs->glog + logs->idx, 0, (logs->idx + 1 - logs->size) * sizeof *lo gs->glog); | memset (logs->glog + logs->idx, 0, (logs->idx + 1 - logs->size) * sizeof *lo gs->glog); | |||
logs->size = newlen; | logs->size = newlen; | |||
} | } | |||
fn = xstrdup (filename); /* ensure fn is a string */ | ||||
glog = logs->glog; | glog = logs->glog; | |||
glog[logs->idx].errors = xcalloc (MAX_LOG_ERRORS, sizeof (char *)); | glog[logs->idx].errors = xcalloc (MAX_LOG_ERRORS, sizeof (char *)); | |||
glog[logs->idx].filename = xstrdup (fn); | glog[logs->idx].props.filename = xstrdup (fn); | |||
glog[logs->idx].fname = xstrdup (basename (fn)); | glog[logs->idx].props.fname = xstrdup (basename (fn)); | |||
if (!glog->pipe && conf.fname_as_vhost) { | if (!glog->pipe && conf.fname_as_vhost) { | |||
if (!(fvh = regex_extract_string (glog[logs->idx].fname, conf.fname_as_vhost | if (! | |||
, 1, &err))) | (fvh = | |||
FATAL ("%s %s[%s]", err, glog[logs->idx].fname, conf.fname_as_vhost); | regex_extract_string (glog[logs->idx].props.fname, conf.fname_as_vhost, | |||
1, &err))) | ||||
FATAL ("%s %s[%s]", err, glog[logs->idx].props.fname, conf.fname_as_vhost) | ||||
; | ||||
glog[logs->idx].fname_as_vhost = fvh; | glog[logs->idx].fname_as_vhost = fvh; | |||
} | } | |||
logs->processed = &(glog[logs->idx].processed); | logs->processed = &(glog[logs->idx].processed); | |||
logs->filename = glog[logs->idx].filename; | logs->filename = glog[logs->idx].props.filename; | |||
logs->idx++; | logs->idx++; | |||
free (fn); | ||||
return 0; | return 0; | |||
} | } | |||
/* Ensure the given filename is part of our original list of files. | /* Ensure the given filename is part of our original list of files. | |||
* | * | |||
* On error, 1 is returned. | * On error, 1 is returned. | |||
* On success, the given filename is added to the Logs structure and 0 is | * On success, the given filename is added to the Logs structure and 0 is | |||
* returned. */ | * returned. */ | |||
int | int | |||
skipping to change at line 236 | skipping to change at line 240 | |||
/* Free all log containers. */ | /* Free all log containers. */ | |||
void | void | |||
free_logs (Logs * logs) { | free_logs (Logs * logs) { | |||
GLog *glog = NULL; | GLog *glog = NULL; | |||
int i; | int i; | |||
for (i = 0; i < logs->size; ++i) { | for (i = 0; i < logs->size; ++i) { | |||
glog = &logs->glog[i]; | glog = &logs->glog[i]; | |||
free (glog->filename); | free (glog->props.filename); | |||
free (glog->fname); | free (glog->props.fname); | |||
free (glog->fname_as_vhost); | free (glog->fname_as_vhost); | |||
free_logerrors (glog); | free_logerrors (glog); | |||
free (glog->errors); | free (glog->errors); | |||
if (glog->pipe) { | if (glog->pipe) { | |||
fclose (glog->pipe); | fclose (glog->pipe); | |||
} | } | |||
} | } | |||
free (logs->glog); | free (logs->glog); | |||
free (logs); | free (logs); | |||
skipping to change at line 663 | skipping to change at line 667 | |||
const char *sn = NULL; | const char *sn = NULL; | |||
code = strtoull (tkn, &bEnd, 10); | code = strtoull (tkn, &bEnd, 10); | |||
if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE) { | if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE) { | |||
LOG_DEBUG (("unable to convert cipher code to a valid decimal.")); | LOG_DEBUG (("unable to convert cipher code to a valid decimal.")); | |||
goto fail; | goto fail; | |||
} | } | |||
/* ssl context */ | /* ssl context */ | |||
if (!(ctx = SSL_CTX_new (SSLv23_server_method ()))) { | if (!(ctx = SSL_CTX_new (SSLv23_server_method ()))) { | |||
LOG_DEBUG (("Unable to create a new SSL_CTX_new to extact TLS.")); | LOG_DEBUG (("Unable to create a new SSL_CTX_new to extract TLS.")); | |||
goto fail; | goto fail; | |||
} | } | |||
if (!(ssl = SSL_new (ctx))) { | if (!(ssl = SSL_new (ctx))) { | |||
LOG_DEBUG (("Unable to create a new instace of SSL_new to extact TLS.")); | LOG_DEBUG (("Unable to create a new instance of SSL_new to extract TLS.")); | |||
goto fail; | goto fail; | |||
} | } | |||
code_be = htobe16 (code); | code_be = htobe16 (code); | |||
memcpy (cipherid, &code_be, 2); | memcpy (cipherid, &code_be, 2); | |||
cipherid[2] = 0; | cipherid[2] = 0; | |||
if (!(c = SSL_CIPHER_find (ssl, cipherid))) { | if (!(c = SSL_CIPHER_find (ssl, cipherid))) { | |||
LOG_DEBUG (("Unable to find cipher to extact TLS.")); | LOG_DEBUG (("Unable to find cipher to extract TLS.")); | |||
goto fail; | goto fail; | |||
} | } | |||
if (!(sn = SSL_CIPHER_standard_name (c))) { | if (!(sn = SSL_CIPHER_standard_name (c))) { | |||
LOG_DEBUG (("Unable to get cipher standard name to extact TLS.")); | LOG_DEBUG (("Unable to get cipher standard name to extract TLS.")); | |||
goto fail; | goto fail; | |||
} | } | |||
*cipher = xstrdup (sn); | *cipher = xstrdup (sn); | |||
*tls_version = xstrdup (SSL_CIPHER_get_version (c)); | *tls_version = xstrdup (SSL_CIPHER_get_version (c)); | |||
free (tkn); | free (tkn); | |||
SSL_free (ssl); | SSL_free (ssl); | |||
SSL_CTX_free (ctx); | SSL_CTX_free (ctx); | |||
return 0; | return 0; | |||
skipping to change at line 1377 | skipping to change at line 1381 | |||
return ret; | return ret; | |||
} | } | |||
/* Attempt to extract the client IP from an X-Forwarded-For (XFF) field. | /* Attempt to extract the client IP from an X-Forwarded-For (XFF) field. | |||
* | * | |||
* If no IP is found, 1 is returned. | * If no IP is found, 1 is returned. | |||
* On success, the malloc'd token is assigned to a GLogItem->host and | * On success, the malloc'd token is assigned to a GLogItem->host and | |||
* 0 is returned. */ | * 0 is returned. */ | |||
static int | static int | |||
set_xff_host (GLogItem * logitem, char **str, char *skips, int out) { | set_xff_host (GLogItem * logitem, char *str, char *skips, int out) { | |||
char *ptr = NULL, *tkn = NULL; | char *ptr = NULL, *tkn = NULL; | |||
int invalid_ip = 1, len = 0, type_ip = TYPE_IPINV; | int invalid_ip = 1, len = 0, type_ip = TYPE_IPINV; | |||
int idx = 0, skips_len = 0; | int idx = 0, skips_len = 0; | |||
skips_len = strlen (skips); | skips_len = strlen (skips); | |||
ptr = *str; | ptr = str; | |||
while (*ptr != '\0') { | while (*ptr != '\0') { | |||
if ((len = strcspn (ptr, skips)) == 0) { | if ((len = strcspn (ptr, skips)) == 0) { | |||
len++, ptr++, idx++; | len++, ptr++, idx++; | |||
goto move; | goto move; | |||
} | } | |||
/* If our index does not match the number of delimiters and we have already a | /* If our index does not match the number of delimiters and we have already a | |||
* valid client IP, then we assume we have reached the length of the XFF */ | * valid client IP, then we assume we have reached the length of the XFF */ | |||
if (idx < skips_len && logitem->host) | if (idx < skips_len && logitem->host) | |||
break; | break; | |||
ptr += len; | ptr += len; | |||
/* extract possible IP */ | /* extract possible IP */ | |||
if (!(tkn = parsed_string (ptr, str, 0))) | if (!(tkn = parsed_string (ptr, &str, 0))) | |||
break; | break; | |||
invalid_ip = invalid_ipaddr (tkn, &type_ip); | invalid_ip = invalid_ipaddr (tkn, &type_ip); | |||
/* done, already have IP and current token is not a host */ | /* done, already have IP and current token is not a host */ | |||
if (logitem->host && invalid_ip) { | if (logitem->host && invalid_ip) { | |||
free (tkn); | free (tkn); | |||
break; | break; | |||
} | } | |||
if (!logitem->host && !invalid_ip) { | if (!logitem->host && !invalid_ip) { | |||
logitem->host = xstrdup (tkn); | logitem->host = xstrdup (tkn); | |||
logitem->type_ip = type_ip; | logitem->type_ip = type_ip; | |||
} | } | |||
free (tkn); | free (tkn); | |||
idx = 0; | idx = 0; | |||
/* found the client IP, break then */ | /* found the client IP, break then */ | |||
if (logitem->host && out) | if (logitem->host && out) | |||
break; | break; | |||
move: | move: | |||
*str += len; | str += len; | |||
} | } | |||
return logitem->host == NULL; | return logitem->host == NULL; | |||
} | } | |||
/* Attempt to find possible delimiters in the X-Forwarded-For (XFF) field. | /* Attempt to find possible delimiters in the X-Forwarded-For (XFF) field. | |||
* | * | |||
* If no IP is found, 1 is returned. | * If no IP is found, 1 is returned. | |||
* On success, the malloc'd token is assigned to a GLogItem->host and 0 is retur ned. */ | * On success, the malloc'd token is assigned to a GLogItem->host and 0 is retur ned. */ | |||
static int | static int | |||
skipping to change at line 1443 | skipping to change at line 1447 | |||
if (!(skips = extract_braces (p))) | if (!(skips = extract_braces (p))) | |||
return spec_err (logitem, ERR_SPEC_SFMT_MIS, **p, "{}"); | return spec_err (logitem, ERR_SPEC_SFMT_MIS, **p, "{}"); | |||
/* if the log format current char is not within the braces special chars, then | /* if the log format current char is not within the braces special chars, then | |||
* we assume the range of IPs are within hard delimiters */ | * we assume the range of IPs are within hard delimiters */ | |||
if (!strchr (skips, **p) && strchr (*str, **p)) { | if (!strchr (skips, **p) && strchr (*str, **p)) { | |||
strcpy (pch, (char[2]) { (char) **p, '\0' }); | strcpy (pch, (char[2]) { (char) **p, '\0' }); | |||
if (!(extract = parse_string (&(*str), pch, 1))) | if (!(extract = parse_string (&(*str), pch, 1))) | |||
goto clean; | goto clean; | |||
if (!(res = set_xff_host (logitem, &extract, skips, 1))) | if (!(res = set_xff_host (logitem, extract, skips, 1))) | |||
free (extract); | free (extract); | |||
(*str)++; /* move a char forward from the trailing delim */ | (*str)++; /* move a char forward from the trailing delim */ | |||
} else { | } else { | |||
res = set_xff_host (logitem, str, skips, 0); | res = set_xff_host (logitem, *str, skips, 0); | |||
} | } | |||
clean: | clean: | |||
free (skips); | free (skips); | |||
return res; | return res; | |||
} | } | |||
/* Handle special specifiers. | /* Handle special specifiers. | |||
* | * | |||
skipping to change at line 1482 | skipping to change at line 1486 | |||
} | } | |||
/* Iterate over the given log format. | /* Iterate over the given log format. | |||
* | * | |||
* On error, or unable to parse it, 1 is returned. | * On error, or unable to parse it, 1 is returned. | |||
* On success, the malloc'd token is assigned to a GLogItem member and | * On success, the malloc'd token is assigned to a GLogItem member and | |||
* 0 is returned. */ | * 0 is returned. */ | |||
static int | static int | |||
parse_format (GLogItem * logitem, char *str, char *lfmt) { | parse_format (GLogItem * logitem, char *str, char *lfmt) { | |||
char end[2 + 1] = { 0 }; | char end[2 + 1] = { 0 }; | |||
char *p = NULL; | char *p = NULL, *last = NULL; | |||
int perc = 0, tilde = 0, ret = 0; | int perc = 0, tilde = 0, ret = 0; | |||
if (str == NULL || *str == '\0') | if (str == NULL || *str == '\0') | |||
return 1; | return 1; | |||
/* iterate over the log format */ | /* iterate over the log format */ | |||
for (p = lfmt; *p; p++) { | last = lfmt + strlen (lfmt); | |||
for (p = lfmt; p < last; p++) { | ||||
if (*p == '%') { | if (*p == '%') { | |||
perc++; | perc++; | |||
continue; | continue; | |||
} | } | |||
if (*p == '~' && perc == 0) { | if (*p == '~' && perc == 0) { | |||
tilde++; | tilde++; | |||
continue; | continue; | |||
} | } | |||
if (*str == '\0') | if (*str == '\0') | |||
return spec_err (logitem, ERR_SPEC_LINE_INV, '-', NULL); | return spec_err (logitem, ERR_SPEC_LINE_INV, '-', NULL); | |||
skipping to change at line 1576 | skipping to change at line 1581 | |||
glog = &logs->glog[i]; | glog = &logs->glog[i]; | |||
if (!glog->log_erridx) | if (!glog->log_erridx) | |||
continue; | continue; | |||
fprintf (stderr, "==%d== GoAccess - version %s - %s %s\n", pid, GO_VERSION, __DATE__, | fprintf (stderr, "==%d== GoAccess - version %s - %s %s\n", pid, GO_VERSION, __DATE__, | |||
__TIME__); | __TIME__); | |||
fprintf (stderr, "==%d== Config file: %s\n", pid, conf.iconfigfile ? : NO_CO NFIG_FILE); | fprintf (stderr, "==%d== Config file: %s\n", pid, conf.iconfigfile ? : NO_CO NFIG_FILE); | |||
fprintf (stderr, "==%d== https://goaccess.io - <hello@goaccess.io>\n", pid); | fprintf (stderr, "==%d== https://goaccess.io - <hello@goaccess.io>\n", pid); | |||
fprintf (stderr, "==%d== Released under the MIT License.\n", pid); | fprintf (stderr, "==%d== Released under the MIT License.\n", pid); | |||
fprintf (stderr, "==%d==\n", pid); | fprintf (stderr, "==%d==\n", pid); | |||
fprintf (stderr, "==%d== FILE: %s\n", pid, glog->filename); | fprintf (stderr, "==%d== FILE: %s\n", pid, glog->props.filename); | |||
fprintf (stderr, "==%d== ", pid); | fprintf (stderr, "==%d== ", pid); | |||
fprintf (stderr, ERR_PARSED_NLINES, glog->log_erridx); | fprintf (stderr, ERR_PARSED_NLINES, glog->log_erridx); | |||
fprintf (stderr, " %s:\n", ERR_PARSED_NLINES_DESC); | fprintf (stderr, " %s:\n", ERR_PARSED_NLINES_DESC); | |||
fprintf (stderr, "==%d==\n", pid); | fprintf (stderr, "==%d==\n", pid); | |||
for (i = 0; i < glog->log_erridx; ++i) | for (i = 0; i < glog->log_erridx; ++i) | |||
fprintf (stderr, "==%d== %s\n", pid, glog->errors[i]); | fprintf (stderr, "==%d== %s\n", pid, glog->errors[i]); | |||
} | } | |||
fprintf (stderr, "==%d==\n", pid); | fprintf (stderr, "==%d==\n", pid); | |||
fprintf (stderr, "==%d== %s\n", pid, ERR_FORMAT_HEADER); | fprintf (stderr, "==%d== %s\n", pid, ERR_FORMAT_HEADER); | |||
} | } | |||
skipping to change at line 1747 | skipping to change at line 1752 | |||
/* Must be a LOG */ | /* Must be a LOG */ | |||
size = MIN (glog->snippetlen, lp->snippetlen); | size = MIN (glog->snippetlen, lp->snippetlen); | |||
if (glog->snippet[0] != '\0' && lp->snippet[0] != '\0' && | if (glog->snippet[0] != '\0' && lp->snippet[0] != '\0' && | |||
memcmp (glog->snippet, lp->snippet, size) == 0) | memcmp (glog->snippet, lp->snippet, size) == 0) | |||
return 1; | return 1; | |||
return 0; | return 0; | |||
} | } | |||
/* Determine if we should insert new record or if it's a duplicate record from | /* Determine if we should insert new record or if it's a duplicate record from | |||
* a previoulsy persisted dataset | * a previously persisted dataset | |||
* | * | |||
* Returns 1 if it thinks the record it's being restored from disk | * Returns 1 if it thinks the record it's being restored from disk | |||
* Returns 0 if we need to parse the record */ | * Returns 0 if we need to parse the record */ | |||
static int | static int | |||
should_restore_from_disk (GLog * glog) { | should_restore_from_disk (GLog * glog) { | |||
GLastParse lp = { 0 }; | GLastParse lp = { 0 }; | |||
if (!conf.restore) | if (!conf.restore) | |||
return 0; | return 0; | |||
lp = ht_get_last_parse (glog->inode); | lp = ht_get_last_parse (glog->props.inode); | |||
/* No last parse timestamp, continue parsing as we got nothing to compare | /* No last parse timestamp, continue parsing as we got nothing to compare | |||
* against */ | * against */ | |||
if (!lp.ts) | if (!lp.ts) | |||
return 0; | return 0; | |||
/* If our current line is greater or equal (zero indexed) to the last parsed | /* If our current line is greater or equal (zero indexed) to the last parsed | |||
* line and have equal timestamps, then keep parsing then */ | * line and have equal timestamps, then keep parsing then */ | |||
if (glog->inode && is_likely_same_log (glog, &lp)) { | if (glog->props.inode && is_likely_same_log (glog, &lp)) { | |||
if (glog->size > lp.size && glog->read >= lp.line) | if (glog->props.size > lp.size && glog->read >= lp.line) | |||
return 0; | return 0; | |||
return 1; | return 1; | |||
} | } | |||
/* No inode (probably a pipe), prior or equal timestamps means restore from | /* No inode (probably a pipe), prior or equal timestamps means restore from | |||
* disk (exclusive) */ | * disk (exclusive) */ | |||
if (!glog->inode && lp.ts >= glog->lp.ts) | if (!glog->props.inode && lp.ts >= glog->lp.ts) | |||
return 1; | return 1; | |||
/* If not likely the same content, then fallback to the following checks */ | /* If not likely the same content, then fallback to the following checks */ | |||
/* If timestamp is greater than last parsed, read the line then */ | /* If timestamp is greater than last parsed, read the line then */ | |||
if (glog->lp.ts > lp.ts) | if (glog->lp.ts > lp.ts) | |||
return 0; | return 0; | |||
/* Check if current log size is smaller than the one last parsed, if it is, | /* Check if current log size is smaller than the one last parsed, if it is, | |||
* it was possibly truncated and thus it may be smaller, so fallback to | * it was possibly truncated and thus it may be smaller, so fallback to | |||
* timestamp even if they are equal to the last parsed timestamp */ | * timestamp even if they are equal to the last parsed timestamp */ | |||
else if (glog->size < lp.size && glog->lp.ts == lp.ts) | else if (glog->props.size < lp.size && glog->lp.ts == lp.ts) | |||
return 0; | return 0; | |||
/* Everything else we ignore it. For instance, we if current log size is | /* Everything else we ignore it. For instance, we if current log size is | |||
* greater than the one last parsed, if the timestamp are equal, we ignore the | * greater than the one last parsed, if the timestamp are equal, we ignore the | |||
* request. | * request. | |||
* | * | |||
* **NOTE* We try to play safe here as we would rather miss a few lines | * **NOTE* We try to play safe here as we would rather miss a few lines | |||
* than double-count a few. */ | * than double-count a few. */ | |||
return 1; | return 1; | |||
} | } | |||
skipping to change at line 1808 | skipping to change at line 1813 | |||
static void | static void | |||
process_invalid (GLog * glog, GLogItem * logitem, const char *line) { | process_invalid (GLog * glog, GLogItem * logitem, const char *line) { | |||
GLastParse lp = { 0 }; | GLastParse lp = { 0 }; | |||
/* if not restoring from disk, then count entry as proceeded and invalid */ | /* if not restoring from disk, then count entry as proceeded and invalid */ | |||
if (!conf.restore) { | if (!conf.restore) { | |||
count_process_and_invalid (glog, line); | count_process_and_invalid (glog, line); | |||
return; | return; | |||
} | } | |||
lp = ht_get_last_parse (glog->inode); | lp = ht_get_last_parse (glog->props.inode); | |||
/* If our current line is greater or equal (zero indexed) to the last parsed | /* If our current line is greater or equal (zero indexed) to the last parsed | |||
* line then keep parsing then */ | * line then keep parsing then */ | |||
if (glog->inode && is_likely_same_log (glog, &lp)) { | if (glog->props.inode && is_likely_same_log (glog, &lp)) { | |||
/* only count invalids if we're past the last parsed line */ | /* only count invalids if we're past the last parsed line */ | |||
if (glog->size > lp.size && glog->read >= lp.line) | if (glog->props.size > lp.size && glog->read >= lp.line) | |||
count_process_and_invalid (glog, line); | count_process_and_invalid (glog, line); | |||
return; | return; | |||
} | } | |||
/* no timestamp to compare against, just count the invalid then */ | /* no timestamp to compare against, just count the invalid then */ | |||
if (!logitem->numdate) { | if (!logitem->numdate) { | |||
count_process_and_invalid (glog, line); | count_process_and_invalid (glog, line); | |||
return; | return; | |||
} | } | |||
skipping to change at line 2093 | skipping to change at line 2098 | |||
* On error, 1 is returned. | * On error, 1 is returned. | |||
* On success, 0 is returned. */ | * On success, 0 is returned. */ | |||
int | int | |||
set_initial_persisted_data (GLog * glog, FILE * fp, const char *fn) { | set_initial_persisted_data (GLog * glog, FILE * fp, const char *fn) { | |||
size_t len; | size_t len; | |||
/* reset the snippet */ | /* reset the snippet */ | |||
memset (glog->snippet, 0, sizeof (glog->snippet)); | memset (glog->snippet, 0, sizeof (glog->snippet)); | |||
glog->snippetlen = 0; | glog->snippetlen = 0; | |||
if (glog->size == 0) | if (glog->props.size == 0) | |||
return 1; | return 1; | |||
len = MIN (glog->size, READ_BYTES); | len = MIN (glog->props.size, READ_BYTES); | |||
if ((fread (glog->snippet, len, 1, fp)) != 1 && ferror (fp)) | if ((fread (glog->snippet, len, 1, fp)) != 1 && ferror (fp)) | |||
FATAL ("Unable to fread the specified log file '%s'", fn); | FATAL ("Unable to fread the specified log file '%s'", fn); | |||
glog->snippetlen = len; | glog->snippetlen = len; | |||
fseek (fp, 0, SEEK_SET); | fseek (fp, 0, SEEK_SET); | |||
return 0; | return 0; | |||
} | } | |||
static void | static void | |||
persist_last_parse (GLog * glog) { | persist_last_parse (GLog * glog) { | |||
/* insert last parsed data for the recently file parsed */ | /* insert last parsed data for the recently file parsed */ | |||
if (glog->inode && glog->size) { | if (glog->props.inode && glog->props.size) { | |||
glog->lp.line = glog->read; | glog->lp.line = glog->read; | |||
glog->lp.snippetlen = glog->snippetlen; | glog->lp.snippetlen = glog->snippetlen; | |||
memcpy (glog->lp.snippet, glog->snippet, glog->snippetlen); | memcpy (glog->lp.snippet, glog->snippet, glog->snippetlen); | |||
ht_insert_last_parse (glog->inode, glog->lp); | ht_insert_last_parse (glog->props.inode, glog->lp); | |||
} | } | |||
/* probably from a pipe */ | /* probably from a pipe */ | |||
else if (!glog->inode) { | else if (!glog->props.inode) { | |||
ht_insert_last_parse (0, glog->lp); | ht_insert_last_parse (0, glog->lp); | |||
} | } | |||
} | } | |||
/* Read the given log line by line and process its data. | /* Read the given log line by line and process its data. | |||
* | * | |||
* On error, 1 is returned. | * On error, 1 is returned. | |||
* On success, 0 is returned. */ | * On success, 0 is returned. */ | |||
static int | static int | |||
read_log (GLog * glog, int dry_run) { | read_log (GLog * glog, int dry_run) { | |||
FILE *fp = NULL; | FILE *fp = NULL; | |||
int piping = 0; | int piping = 0; | |||
struct stat fdstat; | struct stat fdstat; | |||
/* Ensure we have a valid pipe to read from stdin. Only checking for | /* Ensure we have a valid pipe to read from stdin. Only checking for | |||
* conf.read_stdin without verifying for a valid FILE pointer would certainly | * conf.read_stdin without verifying for a valid FILE pointer would certainly | |||
* lead to issues. */ | * lead to issues. */ | |||
if (glog->filename[0] == '-' && glog->filename[1] == '\0' && glog->pipe) { | if (glog->props.filename[0] == '-' && glog->props.filename[1] == '\0' && glog- >pipe) { | |||
fp = glog->pipe; | fp = glog->pipe; | |||
glog->piping = piping = 1; | glog->piping = piping = 1; | |||
} | } | |||
/* make sure we can open the log (if not reading from stdin) */ | /* make sure we can open the log (if not reading from stdin) */ | |||
if (!piping && (fp = fopen (glog->filename, "r")) == NULL) | if (!piping && (fp = fopen (glog->props.filename, "r")) == NULL) | |||
FATAL ("Unable to open the specified log file '%s'. %s", glog->filename, str | FATAL ("Unable to open the specified log file '%s'. %s", glog->props.filenam | |||
error (errno)); | e, | |||
strerror (errno)); | ||||
/* grab the inode of the file being parsed */ | /* grab the inode of the file being parsed */ | |||
if (!piping && stat (glog->filename, &fdstat) == 0) { | if (!piping && stat (glog->props.filename, &fdstat) == 0) { | |||
glog->inode = fdstat.st_ino; | glog->props.inode = fdstat.st_ino; | |||
glog->size = glog->lp.size = fdstat.st_size; | glog->props.size = glog->lp.size = fdstat.st_size; | |||
set_initial_persisted_data (glog, fp, glog->filename); | set_initial_persisted_data (glog, fp, glog->props.filename); | |||
} | } | |||
/* read line by line */ | /* read line by line */ | |||
if (read_lines (fp, glog, dry_run)) { | if (read_lines (fp, glog, dry_run)) { | |||
if (!piping) | if (!piping) | |||
fclose (fp); | fclose (fp); | |||
return 1; | return 1; | |||
} | } | |||
persist_last_parse (glog); | persist_last_parse (glog); | |||
skipping to change at line 2172 | skipping to change at line 2178 | |||
if (!piping) | if (!piping) | |||
fclose (fp); | fclose (fp); | |||
return 0; | return 0; | |||
} | } | |||
static void | static void | |||
set_log_processing (Logs * logs, GLog * glog) { | set_log_processing (Logs * logs, GLog * glog) { | |||
lock_spinner (); | lock_spinner (); | |||
logs->processed = &(glog->processed); | logs->processed = &(glog->processed); | |||
logs->filename = glog->filename; | logs->filename = glog->props.filename; | |||
unlock_spinner (); | unlock_spinner (); | |||
} | } | |||
/* Entry point to parse the log line by line. | /* Entry point to parse the log line by line. | |||
* | * | |||
* On error, 1 is returned. | * On error, 1 is returned. | |||
* On success, 0 is returned. */ | * On success, 0 is returned. */ | |||
int | int | |||
parse_log (Logs * logs, int dry_run) { | parse_log (Logs * logs, int dry_run) { | |||
GLog *glog = NULL; | GLog *glog = NULL; | |||
End of changes. 37 change blocks. | ||||
45 lines changed or deleted | 52 lines changed or added |