diff --git a/recording-daemon/metafile.c b/recording-daemon/metafile.c index 6329a0d7a..955baf1c1 100644 --- a/recording-daemon/metafile.c +++ b/recording-daemon/metafile.c @@ -398,21 +398,27 @@ void metafile_change(char *name) { close(fd); // process contents of metadata file - // XXX use "str" type? + // Track the byte offset in the buffer that corresponds to successfully parsed data char *head = s->str; char *endp = s->str + s->len; + char *last_good_pos = head; // Track last successfully parsed position + while (head < endp) { - char *section_start = head; // section header char *nl = memchr(head, '\n', endp - head); if (!nl || nl == head) { - ilog(LOG_WARN, "Missing section header in %s%s%s", FMT_M(name)); + // Incomplete data - this is expected when file is being written + // Log only at DEBUG level as this is a normal race condition + if (head < endp) { + dbg("Incomplete section header in %s%s%s (waiting for more data, %ld bytes remain)", + FMT_M(name), (long)(endp - head)); + } break; } if (memchr(head, '\0', nl - head)) { ilog(LOG_WARN, "NUL character in section header in %s%s%s", FMT_M(name)); // jump to the end of the read so we don't continually try and process this bad data - mf->pos += (endp - section_start); + last_good_pos = endp; break; } *(nl++) = '\0'; @@ -423,12 +429,14 @@ void metafile_change(char *name) { // content length nl = memchr(head, ':', endp - head); if (!nl || nl == head) { - ilog(LOG_WARN, "Content length for section %s missing in %s%s%s", section, FMT_M(name)); + dbg("Incomplete content length for section %s in %s%s%s (waiting for more data)", + section, FMT_M(name)); break; } *(nl++) = '\0'; if (*(nl++) != '\n') { - ilog(LOG_WARN, "Unterminated content length for section %s in %s%s%s", section, FMT_M(name)); + dbg("Unterminated content length for section %s in %s%s%s (waiting for more data)", + section, FMT_M(name)); break; } char *errp; @@ -442,19 +450,25 @@ void metafile_change(char *name) { // content if (endp - head < slen) { - ilog(LOG_WARN, "Content truncated in section %s in %s%s%s", section, FMT_M(name)); + dbg("Content truncated in section %s in %s%s%s (have %ld, need %lu, waiting for more data)", + section, FMT_M(name), (long)(endp - head), slen); break; } char *content = head; if (memchr(content, '\0', slen)) { ilog(LOG_WARN, "NUL character in content in section %s in %s%s%s", section, FMT_M(name)); // jump to the end of the read so we don't continually try and process this bad data - mf->pos += (endp - section_start); + last_good_pos = endp; break; } // double newline separator head += slen; + if (endp - head < 2) { + dbg("Missing separator after section %s in %s%s%s (waiting for more data)", + section, FMT_M(name)); + break; + } if (*head != '\n' || *(head + 1) != '\n') { ilog(LOG_WARN, "Separator missing after section %s in %s%s%s", section, FMT_M(name)); break; @@ -462,11 +476,19 @@ void metafile_change(char *name) { *head = '\0'; head += 2; + // Successfully parsed complete section - process it and update position meta_section(mf, section, content, slen); - // update read position by the amount of data we processed - // so that any issues causing a break above will resume at the - // correct position on the next inotify event - mf->pos += (head - section_start); + last_good_pos = head; // Mark this position as successfully parsed + } + + // Only update file position to reflect successfully parsed data + // Calculate how many bytes from the buffer we successfully processed + off_t bytes_parsed = last_good_pos - s->str; + mf->pos += bytes_parsed; + + if (bytes_parsed < s->len) { + dbg("Parsed %ld of %ld bytes for %s%s%s, will retry remaining %ld bytes on next event", + (long)bytes_parsed, (long)s->len, FMT_M(name), (long)(s->len - bytes_parsed)); } g_string_free(s, TRUE);