/** * afsql_dd_begin_txn: * * Commit SQL transaction. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_commit_txn(AFSqlDestDriver *self, gboolean lock) { gboolean success; success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL); if (lock) g_mutex_lock(self->db_thread_mutex); /* FIXME: this is a workaround because of the non-proper locking semantics * of the LogQueue. It might happen that the _queue() method sees 0 * elements in the queue, while the thread is still busy processing the * previous message. In that case arming the parallel push callback is * not needed and will cause assertions to fail. This is ugly and should * be fixed by properly defining the "blocking" semantics of the LogQueue * object w/o having to rely on user-code messing with parallel push * callbacks. */ log_queue_reset_parallel_push(self->queue); if (success) { log_queue_ack_backlog(self->queue, self->flush_lines_queued); } else { msg_notice("SQL transaction commit failed, rewinding backlog and starting again", NULL); log_queue_rewind_backlog(self->queue); } if (lock) g_mutex_unlock(self->db_thread_mutex); self->flush_lines_queued = 0; return success; }
static gssize log_transport_device_read_method(LogTransport *s, gpointer buf, gsize buflen, GSockAddr **sa) { LogTransportDevice *self = (LogTransportDevice *) s; gint rc; if (sa) *sa = NULL; do { if (self->timeout) alarm_set(self->timeout); rc = read(self->super.fd, buf, buflen); if (self->timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired()) { msg_notice("Nonblocking read has blocked, returning with an error", evt_tag_int("fd", self->super.fd), evt_tag_int("timeout", self->timeout), NULL); alarm_cancel(); break; } if (self->timeout) alarm_cancel(); } while (rc == -1 && errno == EINTR); return rc; }
static void log_db_parser_reload_database(LogDBParser *self) { struct stat st; if (stat(self->db_file, &st) < 0) { msg_error("Error stating pattern database file, no automatic reload will be performed", evt_tag_str("error", g_strerror(errno)), NULL); return; } if ((self->db_file_inode == st.st_ino && self->db_file_mtime == st.st_mtime)) { return; } self->db_file_inode = st.st_ino; self->db_file_mtime = st.st_mtime; if (!pattern_db_reload_ruleset(self->db, self->cfg, self->db_file)) { msg_error("Error reloading pattern database, no automatic reload will be performed", NULL); } else { /* free the old database if the new was loaded successfully */ msg_notice("Log pattern database reloaded", evt_tag_str("file", self->db_file), evt_tag_str("version", pattern_db_get_ruleset_version(self->db)), evt_tag_str("pub_date", pattern_db_get_ruleset_pub_date(self->db)), NULL); } }
static gssize log_transport_plain_write_method(LogTransport *s, const gpointer buf, gsize buflen) { LogTransportPlain *self = (LogTransportPlain *) s; gint rc; do { if (self->super.timeout) alarm_set(self->super.timeout); if (self->super.flags & LTF_APPEND) lseek(self->super.fd, 0, SEEK_END); rc = write(self->super.fd, buf, buflen); if (self->super.timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired()) { msg_notice("Nonblocking write has blocked, returning with an error", evt_tag_int("fd", self->super.fd), evt_tag_int("timeout", self->super.timeout), NULL); alarm_cancel(); break; } if (self->super.timeout) alarm_cancel(); if (self->super.flags & LTF_FSYNC) fsync(self->super.fd); } while (rc == -1 && errno == EINTR); return rc; }
static void afsocket_dd_notify(LogPipe *s, LogPipe *sender, gint notify_code, gpointer user_data) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; gchar buf[MAX_SOCKADDR_STRING]; switch (notify_code) { case NC_CLOSE: case NC_WRITE_ERROR: log_writer_reopen(self->writer, NULL); msg_notice("Syslog connection broken", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_int("time_reopen", self->time_reopen), NULL); if (self->reconnect_timer) { g_source_remove(self->reconnect_timer); self->reconnect_timer = 0; } self->reconnect_timer = g_timeout_add(self->time_reopen * 1000, afsocket_dd_reconnect_timer, self); break; } }
static void afsocket_sd_accept(gpointer s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; GSockAddr *peer_addr; gchar buf1[256], buf2[256]; gint new_fd; gboolean res; int accepts = 0; while (accepts < MAX_ACCEPTS_AT_A_TIME) { GIOStatus status; status = g_accept(self->fd, &new_fd, &peer_addr); if (status == G_IO_STATUS_AGAIN) { /* no more connections to accept */ break; } else if (status != G_IO_STATUS_NORMAL) { msg_error("Error accepting new connection", evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); return; } g_fd_set_nonblock(new_fd, TRUE); g_fd_set_cloexec(new_fd, TRUE); res = afsocket_sd_process_connection(self, peer_addr, self->bind_addr, new_fd); if (res) { if (peer_addr->sa.sa_family != AF_UNIX) msg_notice("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); else msg_verbose("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); } else { close(new_fd); } g_sockaddr_unref(peer_addr); accepts++; } return; }
static gboolean afsocket_dd_connected(AFSocketDestDriver *self) { gchar buf1[256], buf2[256]; int error = 0; socklen_t errorlen = sizeof(error); LogTransport *transport; LogProtoClient *proto; main_loop_assert_main_thread(); if (iv_fd_registered(&self->connect_fd)) iv_fd_unregister(&self->connect_fd); if (self->transport_mapper->sock_type == SOCK_STREAM) { if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &error, &errorlen) == -1) { msg_error("getsockopt(SOL_SOCKET, SO_ERROR) failed for connecting socket", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno), evt_tag_int("time_reopen", self->time_reopen), NULL); goto error_reconnect; } if (error) { msg_error("Syslog connection failed", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, error), evt_tag_int("time_reopen", self->time_reopen), NULL); goto error_reconnect; } } msg_notice("Syslog connection established", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL)), NULL); transport = afsocket_dd_construct_transport(self, self->fd); if (!transport) goto error_reconnect; proto = log_proto_client_factory_construct(self->proto_factory, transport, &self->writer_options.proto_options.super); log_writer_reopen(self->writer, proto); return TRUE; error_reconnect: close(self->fd); self->fd = -1; afsocket_dd_start_reconnect_timer(self); return FALSE; }
/* called to apply the new configuration once all I/O worker threads have finished */ static void main_loop_reload_config_apply(void) { if (main_loop_is_terminating()) { if (main_loop_new_config) { cfg_free(main_loop_new_config); main_loop_new_config = NULL; } return; } main_loop_old_config->persist = persist_config_new(); cfg_deinit(main_loop_old_config); cfg_persist_config_move(main_loop_old_config, main_loop_new_config); if (cfg_init(main_loop_new_config)) { msg_verbose("New configuration initialized"); persist_config_free(main_loop_new_config->persist); main_loop_new_config->persist = NULL; cfg_free(main_loop_old_config); current_configuration = main_loop_new_config; service_management_clear_status(); } else { msg_error("Error initializing new configuration, reverting to old config"); service_management_publish_status("Error initializing new configuration, using the old config"); cfg_persist_config_move(main_loop_new_config, main_loop_old_config); cfg_deinit(main_loop_new_config); if (!cfg_init(main_loop_old_config)) { /* hmm. hmmm, error reinitializing old configuration, we're hosed. * Best is to kill ourselves in the hope that the supervisor * restarts us. */ kill(getpid(), SIGQUIT); g_assert_not_reached(); } persist_config_free(main_loop_old_config->persist); main_loop_old_config->persist = NULL; cfg_free(main_loop_new_config); current_configuration = main_loop_old_config; goto finish; } /* this is already running with the new config in place */ app_post_config_loaded(); msg_notice("Configuration reload request received, reloading configuration"); finish: main_loop_new_config = NULL; main_loop_old_config = NULL; return; }
static void log_reader_idle_timeout(void *cookie) { LogReader *self = (LogReader *) cookie; msg_notice("Source timeout has elapsed, closing connection", evt_tag_int("fd", log_proto_server_get_fd(self->proto))); log_pipe_notify(self->control, NC_CLOSE, self); }
static void log_writer_error_suspend_elapsed(gpointer s) { LogWriter *self = (LogWriter *) s; self->suspended = FALSE; msg_notice("Error suspend timeout has elapsed, attempting to write again", evt_tag_int("fd", log_proto_client_get_fd(self->proto))); log_writer_start_watches(self); }
int tls_session_verify(TLSSession *self, int ok, X509_STORE_CTX *ctx) { /* untrusted means that we have to accept the certificate even if it is untrusted */ if (self->ctx->verify_mode & TVM_UNTRUSTED) return 1; /* accept certificate if its fingerprint matches, again regardless whether x509 certificate validation was successful */ if (ok && ctx->error_depth == 0 && !tls_session_verify_fingerprint(ctx)) { msg_notice("Certificate valid, but fingerprint constraints were not met, rejecting", NULL); return 0; } if (ok && ctx->error_depth != 0 && (ctx->current_cert->ex_flags & EXFLAG_CA) == 0) { msg_notice("Invalid certificate found in chain, basicConstraints.ca is unset in non-leaf certificate", NULL); ctx->error = X509_V_ERR_INVALID_CA; return 0; } /* reject certificate if it is valid, but its DN is not trusted */ if (ok && ctx->error_depth == 0 && !tls_session_verify_dn(ctx)) { msg_notice("Certificate valid, but DN constraints were not met, rejecting", NULL); ctx->error = X509_V_ERR_CERT_UNTRUSTED; return 0; } /* if the crl_dir is set in the configuration file but the directory is empty ignore this error */ if (!ok && ctx->error == X509_V_ERR_UNABLE_TO_GET_CRL) { msg_notice("CRL directory is set but no CRLs found", NULL); return 1; } if (!ok && ctx->error == X509_V_ERR_INVALID_PURPOSE) { msg_warning("Certificate valid, but purpose is invalid", NULL); return 1; } return ok; }
static gssize log_transport_plain_read_method(LogTransport *s, gpointer buf, gsize buflen, GSockAddr **sa) { LogTransportPlain *self = (LogTransportPlain *) s; gint rc; if ((self->super.flags & LTF_RECV) == 0) { if (sa) *sa = NULL; do { if (self->super.timeout) alarm_set(self->super.timeout); rc = read(self->super.fd, buf, buflen); if (self->super.timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired()) { msg_notice("Nonblocking read has blocked, returning with an error", evt_tag_int("fd", self->super.fd), evt_tag_int("timeout", self->super.timeout), NULL); alarm_cancel(); break; } if (self->super.timeout) alarm_cancel(); } while (rc == -1 && errno == EINTR); } else { union { #if HAVE_STRUCT_SOCKADDR_STORAGE struct sockaddr_storage __sas; #endif struct sockaddr __sa; } sas; socklen_t salen = sizeof(sas); do { rc = recvfrom(self->super.fd, buf, buflen, 0, (struct sockaddr *) &sas, &salen); } while (rc == -1 && errno == EINTR); if (rc != -1 && salen && sa) (*sa) = g_sockaddr_new((struct sockaddr *) &sas, salen); } return rc; }
static void dummy_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { DummyDestDriver *self = (DummyDestDriver *) s; msg_notice("Dummy plugin received a message", evt_tag_str("msg", log_msg_get_value(msg, LM_V_MESSAGE, NULL)), evt_tag_int("opt", self->opt), NULL); log_msg_ack(msg, path_options); log_msg_unref(msg); }
static void log_writer_work_finished(gpointer s) { LogWriter *self = (LogWriter *) s; main_loop_assert_main_thread(); self->flush_waiting_for_timeout = FALSE; if (self->pending_proto_present) { /* pending proto is only set in the main thread, so no need to * lock it before coming here. After we're syncing with the * log_writer_reopen() call, quite possibly coming from a * non-main thread. */ g_static_mutex_lock(&self->pending_proto_lock); if (self->proto) log_proto_free(self->proto); self->proto = self->pending_proto; self->pending_proto = NULL; self->pending_proto_present = FALSE; g_cond_signal(self->pending_proto_cond); g_static_mutex_unlock(&self->pending_proto_lock); } if (!self->work_result) { log_writer_broken(self, NC_WRITE_ERROR); if (self->proto) { log_writer_suspend(self); msg_notice("Suspending write operation because of an I/O error", evt_tag_int("fd", log_proto_get_fd(self->proto)), evt_tag_int("time_reopen", self->options->time_reopen), NULL); } goto exit; } if ((self->super.flags & PIF_INITIALIZED) && self->proto) { /* reenable polling the source, but only if we're still initialized */ log_writer_start_watches(self); } exit: log_pipe_unref(&self->super); }
void main_loop_run(void) { msg_notice("syslog-ng starting up", evt_tag_str("version", SYSLOG_NG_VERSION)); /* main loop */ service_management_indicate_readiness(); service_management_clear_status(); if (interactive_mode) { plugin_load_module("python", current_configuration, NULL); debugger_start(current_configuration); } iv_main(); service_management_publish_status("Shutting down..."); }
static void main_loop_exit_initiate(void) { if (main_loop_is_terminating()) return; msg_notice("syslog-ng shutting down", evt_tag_str("version", SYSLOG_NG_VERSION)); IV_TIMER_INIT(&main_loop_exit_timer); iv_validate_now(); main_loop_exit_timer.expires = iv_now; main_loop_exit_timer.handler = main_loop_exit_timer_elapsed; timespec_add_msec(&main_loop_exit_timer.expires, 100); iv_timer_register(&main_loop_exit_timer); __main_loop_is_terminating = TRUE; }
static gboolean log_writer_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { LogWriterWatch *self = (LogWriterWatch *) source; gint64 num_elements = log_queue_get_length(self->writer->queue); if (self->pollfd.revents & (G_IO_HUP | G_IO_IN) && self->input_means_connection_broken) { msg_error("EOF occurred while idle", evt_tag_int("fd", log_proto_get_fd(self->proto)), NULL); log_writer_broken(self->writer, NC_CLOSE); return FALSE; } else if (self->pollfd.revents & (G_IO_ERR) && num_elements == 0) { msg_error("POLLERR occurred while idle", evt_tag_int("fd", log_proto_get_fd(self->proto)), NULL); log_writer_broken(self->writer, NC_WRITE_ERROR); } else if (num_elements) { if (!log_writer_flush_log(self->writer, self->proto)) { self->error_suspend = TRUE; g_source_get_current_time(source, &self->error_suspend_target); g_time_val_add(&self->error_suspend_target, self->writer->options->time_reopen * 1e6); log_writer_broken(self->writer, NC_WRITE_ERROR); if (self->writer->source == (GSource *) self) { msg_notice("Suspending write operation because of an I/O error", evt_tag_int("fd", log_proto_get_fd(self->proto)), evt_tag_int("time_reopen", self->writer->options->time_reopen), NULL); } return TRUE; } } return TRUE; }
/** * afsql_dd_begin_txn: * * Commit SQL transaction. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_commit_txn(AFSqlDestDriver *self) { gboolean success; success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL); if (success) { log_queue_ack_backlog(self->queue, self->flush_lines_queued); } else { msg_notice("SQL transaction commit failed, rewinding backlog and starting again", NULL); log_queue_rewind_backlog(self->queue); } self->flush_lines_queued = 0; return success; }
gboolean cfg_allow_config_dups(GlobalConfig *self) { const gchar *s; if (cfg_is_config_version_older(self, 0x0303)) return TRUE; s = cfg_args_get(self->lexer->globals, "allow-config-dups"); if (s && atoi(s)) { return TRUE; } else { /* duplicate found, but allow-config-dups is not enabled, hint the user that he might want to use allow-config-dups */ msg_notice("WARNING: Duplicate configuration objects (sources, destinations, ...) are not allowed by default starting with syslog-ng 3.3, add \"@define allow-config-dups 1\" to your configuration to reenable", NULL); return FALSE; } }
static void afsocket_sd_close_connection(AFSocketSourceDriver *self, AFSocketSourceConnection *sc) { gchar buf1[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING]; if (sc->peer_addr->sa.sa_family != AF_UNIX) msg_notice("Syslog connection closed", evt_tag_int("fd", sc->sock), evt_tag_str("client", g_sockaddr_format(sc->peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); else msg_verbose("Syslog connection closed", evt_tag_int("fd", sc->sock), evt_tag_str("client", g_sockaddr_format(sc->peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); log_pipe_deinit(&sc->super); log_pipe_unref(&sc->super); self->num_connections--; }
int tls_session_verify_callback(int ok, X509_STORE_CTX *ctx) { SSL *ssl = X509_STORE_CTX_get_app_data(ctx); TLSSession *self = SSL_get_app_data(ssl); /* NOTE: Sometimes libssl calls this function with no current_cert. This happens when some global error is happen. At this situation we do not need to call any other check and callback */ if (X509_STORE_CTX_get_current_cert(ctx) == NULL) { switch (ctx->error) { case X509_V_ERR_NO_EXPLICIT_POLICY: /* NOTE: Because we set the CHECK_POLICY_FLAG if the certificate contains ExplicitPolicy constraint we would get this error. But this error is because we do not set the policy what we want to check for. */ ok = 1; break; default: msg_notice("Error occured during certificate validation", evt_tag_int("error", ctx->error), NULL); break; } } else { ok = tls_session_verify(self, ok, ctx); tls_log_certificate_validation_progress(ok, ctx); if (self->verify_func) return self->verify_func(ok, ctx, self->verify_data); } return ok; }
/* * log_transport_fd_is_locked: * @fd: file descriptor * * This function checks if a file lock is associated with a @fd. * * return code: * 1 - file is locked; * 0 - file is unlocked or fcntl() is failed. **/ static gboolean log_transport_fd_is_locked(int fd) { gint rc; struct flock lock; memset(&lock, 0, sizeof(lock)); errno = 0; rc = fcntl(fd, F_GETLK, &lock); if (rc != 0) { msg_notice("Check locking fd is failed" , evt_tag_int("fd", fd) , evt_tag_str("error", strerror(errno)) , NULL); return 0; } if (lock.l_type != F_UNLCK && lock.l_pid != 0) { return 1; } return 0; }
gboolean plugin_load_module(const gchar *module_name, GlobalConfig *cfg, CfgArgs *args) { GModule *mod; static GModule *main_module_handle; gboolean (*init_func)(GlobalConfig *cfg, CfgArgs *args); gchar *module_init_func; const gchar *mp; gchar *p; gboolean result; if (!main_module_handle) main_module_handle = g_module_open(NULL, 0); module_init_func = g_strdup_printf("%s_module_init", module_name); for (p = module_init_func; *p; p++) { if ((*p) == '-') *p = '_'; } if (g_module_symbol(main_module_handle, module_init_func, (gpointer *) &init_func)) { /* already linked in, no need to load explicitly */ goto call_init; } if (cfg->lexer) mp = cfg_args_get(cfg->lexer->globals, "module-path"); else mp = NULL; if (!mp) mp = module_path; mod = plugin_dlopen_module(module_name, mp); if (!mod) { g_free(module_init_func); return FALSE; } g_module_make_resident(mod); if (!g_module_symbol(mod, module_init_func, (gpointer *) &init_func)) { msg_error("Error finding init function in module", evt_tag_str("module", module_name), evt_tag_str("symbol", module_init_func), evt_tag_str("error", g_module_error()), NULL); g_free(module_init_func); return FALSE; } call_init: g_free(module_init_func); result = (*init_func)(cfg, args); if (result) msg_notice("Module loaded and initialized successfully", evt_tag_str("module", module_name), NULL); else msg_error("Module initialization failed", evt_tag_str("module", module_name), NULL); return result; }
static void afuser_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options) { AFUserDestDriver *self = (AFUserDestDriver *) s; gchar buf[8192]; struct utmp *ut; GString *timestamp; time_t now; now = msg->timestamps[LM_TS_RECVD].time.tv_sec; if (self->disable_until && self->disable_until > now) goto finish; timestamp = g_string_sized_new(0); log_stamp_format(&msg->timestamps[LM_TS_STAMP], timestamp, TS_FMT_FULL, -1, 0); g_snprintf(buf, sizeof(buf), "%s %s %s\n", timestamp->str, log_msg_get_value(msg, LM_V_HOST, NULL), log_msg_get_value(msg, LM_V_MESSAGE, NULL)); g_string_free(timestamp, TRUE); /* NOTE: there's a private implementations of getutent in utils.c on Systems which do not provide one. */ while ((ut = getutent())) { #if HAVE_MODERN_UTMP if (ut->ut_type == USER_PROCESS && ((self->username->len == 1 && self->username->str[0] == '*') || (self->username->len <= sizeof(ut->ut_user) && memcmp(self->username->str, ut->ut_user, self->username->len) == 0))) #else if ((self->username->len == 1 && self->username->str[0] == '*') || (self->username->len <= sizeof(ut->ut_name) && memcmp(self->username->str, ut->ut_name, self->username->len) == 0)) #endif { gchar line[128]; gchar *p = line; int fd; if (ut->ut_line[0] != '/') { strcpy(line, "/dev/"); p = line + 5; } else line[0] = 0; strncpy(p, ut->ut_line, sizeof(line) - (p - line)); fd = open(line, O_NOCTTY | O_APPEND | O_WRONLY | O_NONBLOCK); if (fd != -1) { alarm_set(10); if (write(fd, buf, strlen(buf)) < 0 && errno == EINTR && alarm_has_fired()) { msg_notice("Writing to the user terminal has blocked for 10 seconds, disabling for 10 minutes", evt_tag_str("user", self->username->str), NULL); self->disable_until = now + 600; } alarm_cancel(); close(fd); } } } endutent(); finish: log_msg_ack(msg, path_options); log_msg_unref(msg); }
static gboolean afsocket_dd_connected(AFSocketDestDriver *self) { gchar buf1[256], buf2[256]; int error = 0; socklen_t errorlen = sizeof(error); LogTransport *transport; LogProto *proto; guint32 transport_flags = 0; main_loop_assert_main_thread(); if (iv_fd_registered(&self->connect_fd)) iv_fd_unregister(&self->connect_fd); if (self->flags & AFSOCKET_STREAM) { transport_flags |= LTF_SHUTDOWN; if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &error, &errorlen) == -1) { msg_error("getsockopt(SOL_SOCKET, SO_ERROR) failed for connecting socket", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno), evt_tag_int("time_reopen", self->time_reopen), NULL); goto error_reconnect; } if (error) { msg_error("Syslog connection failed", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, error), evt_tag_int("time_reopen", self->time_reopen), NULL); goto error_reconnect; } } msg_notice("Syslog connection established", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL)), NULL); #if ENABLE_SSL if (self->tls_context) { TLSSession *tls_session; tls_session = tls_context_setup_session(self->tls_context); if (!tls_session) { goto error_reconnect; } tls_session_set_verify(tls_session, afsocket_dd_tls_verify_callback, self, NULL); transport = log_transport_tls_new(tls_session, self->fd, transport_flags); } else #endif transport = log_transport_plain_new(self->fd, transport_flags); if (self->flags & AFSOCKET_SYSLOG_PROTOCOL) { if (self->flags & AFSOCKET_STREAM) proto = log_proto_framed_client_new(transport); else proto = log_proto_text_client_new(transport); } else { proto = log_proto_text_client_new(transport); } log_writer_reopen(self->writer, proto); return TRUE; error_reconnect: close(self->fd); self->fd = -1; afsocket_dd_start_reconnect_timer(self); return FALSE; }
static gboolean log_writer_fd_prepare(GSource *source, gint *timeout) { LogWriterWatch *self = (LogWriterWatch *) source; gint64 num_elements = log_queue_get_length(self->writer->queue); GTimeVal now; GIOCondition proto_cond; self->pollfd.events = G_IO_ERR; self->pollfd.revents = 0; g_source_get_current_time(source, &now); if (log_proto_prepare(self->proto, &self->pollfd.fd, &proto_cond, timeout)) return TRUE; /* recalculate buckets */ if (self->writer->options->throttle > 0) { gint64 diff; gint new_buckets; /* throttling is enabled, calculate new buckets */ if (self->last_throttle_check.tv_sec != 0) { diff = g_time_val_diff(&now, &self->last_throttle_check); } else { diff = 0; self->last_throttle_check = now; } new_buckets = (self->writer->options->throttle * diff) / G_USEC_PER_SEC; if (new_buckets) { /* if new_buckets is zero, we don't save the current time as * last_throttle_check. The reason is that new_buckets could be * rounded to zero when only a minimal interval passes between * poll iterations. */ self->writer->throttle_buckets = MIN(self->writer->options->throttle, self->writer->throttle_buckets + new_buckets); self->last_throttle_check = now; } } if (G_UNLIKELY(self->error_suspend)) { *timeout = g_time_val_diff(&self->error_suspend_target, &now) / 1000; if (*timeout <= 0) { msg_notice("Error suspend timeout has elapsed, attempting to write again", evt_tag_int("fd", log_proto_get_fd(self->proto)), NULL); self->error_suspend = FALSE; *timeout = -1; } else { return FALSE; } } if ((self->writer->options->flush_lines == 0 && (!log_writer_throttling(self->writer) && num_elements != 0)) || (self->writer->options->flush_lines > 0 && (!log_writer_throttling(self->writer) && num_elements >= self->writer->options->flush_lines))) { /* we need to flush our buffers */ self->pollfd.events |= proto_cond; } else if (num_elements && !log_writer_throttling(self->writer)) { /* our buffer does not contain enough elements to flush, but we do not * want to wait more than flush_timeout time */ if (!self->flush_waiting_for_timeout) { /* start waiting */ *timeout = self->writer->options->flush_timeout; g_source_get_current_time(source, &self->flush_target); g_time_val_add(&self->flush_target, *timeout * 1000); self->flush_waiting_for_timeout = TRUE; } else { glong to = g_time_val_diff(&self->flush_target, &now) / 1000; if (to <= 0) { /* timeout elapsed, start polling again */ if (self->writer->flags & LW_ALWAYS_WRITABLE) return TRUE; self->pollfd.events = proto_cond; } else { *timeout = to; } } return FALSE; } else { if (num_elements && log_writer_throttling(self->writer)) { /* we are unable to send because of throttling, make sure that we * wake up when the rate limits lets us send at least 1 message */ *timeout = (1000 / self->writer->options->throttle) + 1; msg_debug("Throttling output", evt_tag_int("wait", *timeout), NULL); } } if (self->writer->flags & LW_DETECT_EOF && (self->pollfd.events & G_IO_IN) == 0) { self->pollfd.events |= G_IO_HUP | G_IO_IN; self->input_means_connection_broken = TRUE; } else { self->input_means_connection_broken = FALSE; } self->flush_waiting_for_timeout = FALSE; if ((self->pollfd.events & G_IO_OUT) && (self->writer->flags & LW_ALWAYS_WRITABLE)) { self->pollfd.revents = G_IO_OUT; return TRUE; } return FALSE; }
/***************************************************************************** * Processes HDD and SMART commands. *****************************************************************************/ void stat_hdd() { time_t tm; int channels_n, channel, device, i; int f_ata_request_supported, f_smart_supported, f_smart_enabled; struct ata_device dev[2]; u_llong sectors; struct dev_match_result matches[100]; union ccb ccb; msg_debug(1, "Processing of HDD/HDD_LIST/SMART command started"); /* check byte order */ #if BYTE_ORDER != LITTLE_ENDIAN msg_err(0, "%s: ussd supports only LITTLE_ENDIAN byte order", __FUNCTION__); stat_hdd_finish(); return; #endif /* get statistics of all devices from devstat library */ if ((f_stat_hdd_command_hdd || f_stat_hdd_command_hdd_list) && !stat_hdd_get_devstat()) { stat_hdd_finish(); return; } /* check if [IOC]ATAREQUEST ioctl request supported by system */ f_ata_request_supported = stat_hdd_is_ata_request_supported(); if (f_stat_hdd_command_hdd || f_stat_hdd_command_smart) { tm = get_remote_tm(); printf("%lu ata_request_supported %d\n", (u_long)tm, f_ata_request_supported); } /* determine number of ATA channels */ if (stat_hdd_get_ata_channels_n(&channels_n)) { /* process all channels */ for (channel = 0; channels_n < 0 || channel < channels_n; channel++) { msg_debug(2, "%s: Processing ATA channel %d", __FUNCTION__, channel); /* get channel devices */ bzero(dev, sizeof(dev)); if (!stat_hdd_get_ata_channel_devices(channel, dev)) { if (channels_n < 0) break; else continue; } /* check if channel has at least one device */ if (!*dev[0].name && !*dev[1].name) { msg_debug(2, "%s: No devices found", __FUNCTION__); continue; } /* Process all devices within channel */ for (device = 0; device < 2; device++) { /* skip if there is no device */ if (!*dev[device].name) continue; msg_debug(2, "%s: Found device %s", __FUNCTION__, dev[device].name); if (!stat_hdd_is_device_ata(&dev[device])) { msg_debug(2, "%s: Device is not ATA device", __FUNCTION__); continue; } /* process HDD_LIST command */ if (f_stat_hdd_command_hdd_list) { tm = get_remote_tm(); printf("%lu hdd_exists:%s 1\n", (u_long)tm, dev[device].name); } /* go to the next device if no HDD or SMART command given */ if (!f_stat_hdd_command_hdd && !f_stat_hdd_command_smart) { stat_hdd_fake_devstat(dev[device].name); continue; } /* refresh device parameters because they can be cached by system */ stat_hdd_refresh_ata_device_params(&dev[device]); /* process HDD command */ if (f_stat_hdd_command_hdd) { /* get device size */ sectors = stat_hdd_get_device_size(&dev[device]); tm = get_remote_tm(); printf("%lu hdd_model:%s %s\n", (u_long)tm, dev[device].name, dev[device].model); printf("%lu hdd_serno:%s %s\n", (u_long)tm, dev[device].name, dev[device].serial); printf("%lu hdd_revision:%s %s\n", (u_long)tm, dev[device].name, dev[device].revision); printf("%lu hdd_size_sectors:%s %llu\n", (u_long)tm, dev[device].name, sectors); printf("%lu hdd_size_mbytes:%s %llu\n", (u_long)tm, dev[device].name, sectors >> 11); /* print devstat statistics of device */ stat_hdd_print_devstat(dev[device].name); } stat_hdd_fake_devstat(dev[device].name); /* process SMART command in remaining code */ if (!f_stat_hdd_command_smart) continue; /* check if SMART supported by device */ f_smart_supported = stat_hdd_is_smart_supported(&dev[device]); /* check if SMART enabled on device */ f_smart_enabled = stat_hdd_is_smart_enabled(&dev[device]); /* enable SMART if requested */ if (conf.f_enable_smart && f_ata_request_supported && f_smart_supported && !f_smart_enabled && stat_hdd_ata_command_interface(&dev[device], SMART_ENABLE_OPERATIONS, NULL)) { f_smart_enabled = 1; msg_notice("SMART has been successfully enabled " "on device %s", dev[device].name); } tm = get_remote_tm(); printf("%lu smart_supported:%s %d\n", (u_long)tm, dev[device].name, f_smart_supported); printf("%lu smart_enabled:%s %d\n", (u_long)tm, dev[device].name, f_smart_enabled); /* don't try to get SMART if no attributes requested */ if (!f_stat_hdd_smart_attrs_requested) { msg_debug(2, "%s: No SMART attributes requested", __FUNCTION__); continue; } /* don't try to get SMART if system doesn't support [IOC]ATAREQUEST ioctl request */ if (!f_ata_request_supported) { msg_debug(2, "%s: Can't get SMART because system doesn't " "support [IOC]ATAREQUEST ioctl request", __FUNCTION__); continue; } /* don't try to get SMART if it is not supported by device */ if (!f_smart_supported) { msg_debug(2, "%s: SMART is not supported by device", __FUNCTION__); continue; } /* don't try to get SMART if it is not enabled on device */ if (!f_smart_enabled) { msg_debug(2, "%s: SMART is not enabled on device", __FUNCTION__); continue; } /* get SMART values */ if (!stat_hdd_ata_command_interface(&dev[device], SMART_READ_VALUES, (char *)&dev[device].smart_values)) continue; msg_debug(2, "%s: Got SMART values", __FUNCTION__); /* get SMART thresholds */ if (!stat_hdd_ata_command_interface(&dev[device], SMART_READ_THRESHOLDS, (char *)&dev[device].smart_thresholds)) continue; msg_debug(2, "%s: Got SMART thresholds", __FUNCTION__); /* process SMART attributes */ stat_hdd_process_smart_attributes(&dev[device]); } } msg_debug(2, "%s: All ATA channels processed", __FUNCTION__); } /* processing SCSI bus * now we're not support SMART on SCSI, sad but true */ msg_debug(2, "%s: Processing SCSI bus", __FUNCTION__); if ((channel = open(XPT_DEVICE, O_RDWR)) == -1) { msg_debug(1, "%s: open(%s) error %d (%s)", __FUNCTION__, XPT_DEVICE, errno, strerror(errno)); stat_hdd_finish(); return; } bzero(&ccb, sizeof(ccb)); ccb.ccb_h.path_id = CAM_XPT_PATH_ID; ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; ccb.ccb_h.func_code = XPT_DEV_MATCH; ccb.cdm.match_buf_len = sizeof(matches); ccb.cdm.matches = &matches[0]; if (ioctl(channel, CAMIOCOMMAND, &ccb) == -1) { msg_debug(1, "%s: ioctl(CAMIOCOMMAND) error %d (%s)", __FUNCTION__, errno, strerror(errno)); stat_hdd_finish(); return; } if ((ccb.ccb_h.status != CAM_REQ_CMP) || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { msg_debug(1, "%s: CAM return error %#x, CDM error %d\n", __FUNCTION__, ccb.ccb_h.status, ccb.cdm.status); stat_hdd_finish(); return; } /* walking CAM hierarchy */ for(device = 0; (unsigned) device < ccb.cdm.num_matches; device++) { if (ccb.cdm.matches[device].type == DEV_MATCH_DEVICE) { if (ccb.cdm.matches[device].result.device_result.flags & DEV_RESULT_UNCONFIGURED) continue; #if __FreeBSD_version > 800100 /* new atacam devices - see ada(4) */ if (ccb.cdm.matches[device].result.device_result.protocol == PROTO_ATA) { cam_strvis((void *) dev[0].model, ccb.cdm.matches[device].result.device_result.ident_data.model, sizeof(ccb.cdm.matches[device].result.device_result.ident_data.model), sizeof(dev[0].model)); cam_strvis((void *) dev[0].serial, ccb.cdm.matches[device].result.device_result.ident_data.serial, sizeof(ccb.cdm.matches[device].result.device_result.ident_data.serial), sizeof(dev[0].serial)); cam_strvis((void *) dev[0].revision, ccb.cdm.matches[device].result.device_result.ident_data.revision, sizeof(ccb.cdm.matches[device].result.device_result.ident_data.revision), sizeof(dev[0].revision)); memcpy(&dev[0].params, &ccb.cdm.matches[device].result.device_result.ident_data, sizeof(dev[0].params)); /* fake 3'rd device on IDE channel is atacam */ dev[0].device = 2; } else if (ccb.cdm.matches[device].result.device_result.protocol == PROTO_SCSI) { #endif cam_strvis((u_int8_t *) dev[0].model, (u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.vendor, sizeof(ccb.cdm.matches[device].result.device_result.inq_data.vendor), sizeof(dev[0].model)); if (strlen(dev[0].model) < sizeof(dev[0].model)+2) strlcat(dev[0].model, " ", sizeof(dev[0].model)); cam_strvis((u_int8_t *) dev[0].model+strlen(dev[0].model), (u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.product, sizeof(ccb.cdm.matches[device].result.device_result.inq_data.product), sizeof(dev[0].model)-strlen(dev[0].model)); cam_strvis((u_int8_t *) dev[0].revision, (u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.revision, sizeof(ccb.cdm.matches[device].result.device_result.inq_data.revision), sizeof(dev[0].revision)); /* fake 4'th device on IDE channel is SCSI disk */ dev[0].device = 3; msg_debug(2, "%s: found SCSI device, model is %s", __FUNCTION__, dev[0].model); #if __FreeBSD_version > 800100 } #endif } if (ccb.cdm.matches[device].type == DEV_MATCH_PERIPH) { for (i=0; i < dinfo.numdevs; i++) { if (((dinfo.devices[i].device_type & DEVSTAT_TYPE_MASK) != DEVSTAT_TYPE_DIRECT) || (dinfo.devices[i].device_type & DEVSTAT_TYPE_PASS)) continue; if (!strcmp(dinfo.devices[i].device_name, ccb.cdm.matches[device].result.periph_result.periph_name) && (unsigned) dinfo.devices[i].unit_number == ccb.cdm.matches[device].result.periph_result.unit_number) { snprintf(dev[0].name, sizeof(dev[0].name), "%s%d", ccb.cdm.matches[device].result.periph_result.periph_name, ccb.cdm.matches[device].result.periph_result.unit_number); msg_debug(2, "%s: periph %s have stat", __FUNCTION__, dev[0].name); if (dev[0].device == 2) stat_hdd_refresh_ata_device_params(&dev[0]); if (dev[0].device == 3) stat_hdd_refresh_cam_device_params(&dev[0]); if (f_stat_hdd_command_hdd_list) { tm = get_remote_tm(); printf("%lu hdd_exists:%s 1\n", (u_long)tm, dev[0].name); } if (f_stat_hdd_command_hdd) { sectors = stat_hdd_get_device_size(&dev[0]); tm = get_remote_tm(); printf("%lu hdd_model:%s %s\n", (u_long)tm, dev[0].name, dev[0].model); printf("%lu hdd_serno:%s %s\n", (u_long)tm, dev[0].name, dev[0].serial); printf("%lu hdd_revision:%s %s\n", (u_long)tm, dev[0].name, dev[0].revision); printf("%lu hdd_size_sectors:%s %llu\n", (u_long)tm, dev[0].name, sectors); printf("%lu hdd_size_mbytes:%s %llu\n", (u_long)tm, dev[0].name, sectors >> 11); stat_hdd_print_devstat(dev[0].name); } stat_hdd_fake_devstat(dev[0].name); if (!f_stat_hdd_command_smart) break; /* Now i don't know how to read SMART from SCSI */ if (dev[0].device == 3) { break; } f_smart_supported = stat_hdd_is_smart_supported(&dev[0]); f_smart_enabled = stat_hdd_is_smart_enabled(&dev[0]); if (conf.f_enable_smart && f_ata_request_supported && f_smart_supported && !f_smart_enabled && stat_hdd_ata_command_interface(&dev[0], SMART_ENABLE_OPERATIONS, NULL)) { f_smart_enabled = 1; msg_notice("SMART has been successfully enabled on device %s", dev[0].name); } tm = get_remote_tm(); printf("%lu smart_supported:%s %d\n", (u_long)tm, dev[0].name, f_smart_supported); printf("%lu smart_enabled:%s %d\n", (u_long)tm, dev[0].name, f_smart_enabled); if (!f_stat_hdd_smart_attrs_requested) { msg_debug(2, "%s: No SMART attributes requested", __FUNCTION__); break; } if (!f_smart_supported) { msg_debug(2, "%s: SMART is not supported by device", __FUNCTION__); break; } if (!f_smart_enabled) { msg_debug(2, "%s: SMART is not enabled on device", __FUNCTION__); break; } if (!stat_hdd_ata_command_interface(&dev[0], SMART_READ_VALUES, (char *)&dev[0].smart_values)) break; msg_debug(2, "%s: Got SMART values", __FUNCTION__); if (!stat_hdd_ata_command_interface(&dev[0], SMART_READ_THRESHOLDS, (char *)&dev[0].smart_thresholds)) break; msg_debug(2, "%s: Got SMART thresholds", __FUNCTION__); stat_hdd_process_smart_attributes(&dev[0]); break; } } } }
static gboolean log_proto_buffered_server_convert_from_raw(LogProtoBufferedServer *self, const guchar *raw_buffer, gsize raw_buffer_len) { /* some data was read */ gsize avail_in = raw_buffer_len; gsize avail_out; gchar *out; gint ret = -1; gboolean success = FALSE; LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self); do { avail_out = state->buffer_size - state->pending_buffer_end; out = (gchar *) self->buffer + state->pending_buffer_end; ret = g_iconv(self->convert, (gchar **) &raw_buffer, &avail_in, (gchar **) &out, &avail_out); if (ret == (gsize) -1) { switch (errno) { case EINVAL: if (self->stream_based) { /* Incomplete text, do not report an error, rather try to read again */ state->pending_buffer_end = state->buffer_size - avail_out; if (avail_in > 0) { if (avail_in > sizeof(state->raw_buffer_leftover)) { msg_error("Invalid byte sequence, the remaining raw buffer is larger than the supported leftover size", evt_tag_str("encoding", self->super.options->encoding), evt_tag_int("avail_in", avail_in), evt_tag_int("leftover_size", sizeof(state->raw_buffer_leftover))); goto error; } memcpy(state->raw_buffer_leftover, raw_buffer, avail_in); state->raw_buffer_leftover_size = avail_in; state->raw_buffer_size -= avail_in; msg_trace("Leftover characters remained after conversion, delaying message until another chunk arrives", evt_tag_str("encoding", self->super.options->encoding), evt_tag_int("avail_in", avail_in)); goto success; } } else { msg_error("Byte sequence too short, cannot convert an individual frame in its entirety", evt_tag_str("encoding", self->super.options->encoding), evt_tag_int("avail_in", avail_in)); goto error; } break; case E2BIG: state->pending_buffer_end = state->buffer_size - avail_out; /* extend the buffer */ if (state->buffer_size < self->super.options->max_buffer_size) { state->buffer_size *= 2; if (state->buffer_size > self->super.options->max_buffer_size) state->buffer_size = self->super.options->max_buffer_size; self->buffer = g_realloc(self->buffer, state->buffer_size); /* recalculate the out pointer, and add what we have now */ ret = -1; } else { msg_error("Incoming byte stream requires a too large conversion buffer, probably invalid character sequence", evt_tag_str("encoding", self->super.options->encoding), evt_tag_printf("buffer", "%.*s", (gint) state->pending_buffer_end, self->buffer)); goto error; } break; case EILSEQ: default: msg_notice("Invalid byte sequence or other error while converting input, skipping character", evt_tag_str("encoding", self->super.options->encoding), evt_tag_printf("char", "0x%02x", *(guchar *) raw_buffer)); goto error; } } else { state->pending_buffer_end = state->buffer_size - avail_out; } } while (avail_in > 0); success: success = TRUE; error: log_proto_buffered_server_put_state(self); return success; }
static void log_proto_buffered_server_apply_state(LogProtoBufferedServer *self, PersistEntryHandle handle, const gchar *persist_name) { struct stat st; gint64 ofs = 0; LogProtoBufferedServerState *state; gint fd; fd = self->super.transport->fd; self->persist_handle = handle; if (fstat(fd, &st) < 0) return; state = log_proto_buffered_server_get_state(self); if (!self->buffer) { self->buffer = g_malloc(state->buffer_size); } state->pending_buffer_end = 0; if (state->file_inode && state->file_inode == st.st_ino && state->file_size <= st.st_size && state->raw_stream_pos <= st.st_size) { ofs = state->raw_stream_pos; lseek(fd, ofs, SEEK_SET); } else { if (state->file_inode) { /* the stored state does not match the current file */ msg_notice("The current log file has a mismatching size/inode information, restarting from the beginning", evt_tag_str("state", persist_name), evt_tag_int("stored_inode", state->file_inode), evt_tag_int("cur_file_inode", st.st_ino), evt_tag_int("stored_size", state->file_size), evt_tag_int("cur_file_size", st.st_size), evt_tag_int("raw_stream_pos", state->raw_stream_pos)); } goto error; } if (state->raw_buffer_size) { gssize rc; guchar *raw_buffer; if (!self->super.options->encoding) { /* no conversion, we read directly into our buffer */ if (state->raw_buffer_size > state->buffer_size) { msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than buffer_size and no encoding is set, restarting from the beginning", evt_tag_str("state", persist_name), evt_tag_int("raw_buffer_size", state->raw_buffer_size), evt_tag_int("buffer_size", state->buffer_size), evt_tag_int("init_buffer_size", self->super.options->init_buffer_size)); goto error; } raw_buffer = self->buffer; } else { if (state->raw_buffer_size > self->super.options->max_buffer_size) { msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than max_buffer_size, restarting from the beginning", evt_tag_str("state", persist_name), evt_tag_int("raw_buffer_size", state->raw_buffer_size), evt_tag_int("init_buffer_size", self->super.options->init_buffer_size), evt_tag_int("max_buffer_size", self->super.options->max_buffer_size)); goto error; } raw_buffer = g_alloca(state->raw_buffer_size); } rc = log_transport_read(self->super.transport, raw_buffer, state->raw_buffer_size, NULL); if (rc != state->raw_buffer_size) { msg_notice("Error re-reading buffer contents of the file to be continued, restarting from the beginning", evt_tag_str("state", persist_name)); goto error; } state->pending_buffer_end = 0; if (self->super.options->encoding) { if (!log_proto_buffered_server_convert_from_raw(self, raw_buffer, rc)) { msg_notice("Error re-converting buffer contents of the file to be continued, restarting from the beginning", evt_tag_str("state", persist_name)); goto error; } } else { state->pending_buffer_end += rc; } if (state->buffer_pos > state->pending_buffer_end) { msg_notice("Converted buffer contents is smaller than the current buffer position, starting from the beginning of the buffer, some lines may be duplicated", evt_tag_str("state", persist_name)); state->buffer_pos = state->pending_buffer_pos = 0; } } else { /* although we do have buffer position information, but the * complete contents of the buffer is already processed, instead * of reading and then dropping it, position the file after the * indicated block */ state->raw_stream_pos += state->raw_buffer_size; ofs = state->raw_stream_pos; state->raw_buffer_size = 0; state->buffer_pos = state->pending_buffer_end = 0; lseek(fd, state->raw_stream_pos, SEEK_SET); } goto exit; error: ofs = 0; state->buffer_pos = 0; state->pending_buffer_end = 0; state->__deprecated_buffer_cached_eol = 0; state->raw_stream_pos = 0; state->raw_buffer_size = 0; state->raw_buffer_leftover_size = 0; lseek(fd, 0, SEEK_SET); exit: state->file_inode = st.st_ino; state->file_size = st.st_size; state->raw_stream_pos = ofs; state->pending_buffer_pos = state->buffer_pos; state->pending_raw_stream_pos = state->raw_stream_pos; state->pending_raw_buffer_size = state->raw_buffer_size; state->__deprecated_buffer_cached_eol = 0; state = NULL; log_proto_buffered_server_put_state(self); }