diff --git a/src/async_std.rs b/src/async_std.rs index d8eae2b..dece1fc 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -10,7 +10,7 @@ use async_trait::async_trait; #[cfg(unix)] use async_std::os::unix::net::UnixStream; -use super::{IoResult, DEFAULT_CHUNK_SIZE, END_OF_STREAM, INSTREAM, PING, PONG, VERSION}; +use super::{IoResult, DEFAULT_CHUNK_SIZE, END_OF_STREAM, INSTREAM, PING, PONG, SHUTDOWN, VERSION}; async fn send_command( mut stream: RW, @@ -473,3 +473,22 @@ pub async fn scan_stream< let output_stream = connection.connect().await?; _scan_stream(input_stream, chunk_size, output_stream).await } + +/// Shuts down a ClamAV server +/// +/// This function establishes a connection to a ClamAV server and sends the +/// SHUTDOWN command to it. If the server is available, it will perform a clean +/// exit and shut itself down. The response will be empty. +/// +/// # Arguments +/// +/// * `connection`: The connection type to use - either TCP or a Unix socket connection +/// +/// # Returns +/// +/// An [`IoResult`] containing the server's response +/// +pub async fn shutdown(connection: T) -> IoResult { + let stream = connection.connect().await?; + send_command(stream, SHUTDOWN, None).await +} diff --git a/src/lib.rs b/src/lib.rs index 38c220d..52de451 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ const DEFAULT_CHUNK_SIZE: usize = 4096; /// ClamAV commands const PING: &[u8; 6] = b"zPING\0"; const VERSION: &[u8; 9] = b"zVERSION\0"; +const SHUTDOWN: &[u8; 10] = b"zSHUTDOWN\0"; const INSTREAM: &[u8; 10] = b"zINSTREAM\0"; const END_OF_STREAM: &[u8; 4] = &[0, 0, 0, 0]; @@ -467,3 +468,22 @@ pub fn scan_buffer( let stream = connection.connect()?; scan(buffer, chunk_size, stream) } + +/// Shuts down a ClamAV server +/// +/// This function establishes a connection to a ClamAV server and sends the +/// SHUTDOWN command to it. If the server is available, it will perform a clean +/// exit and shut itself down. The response will be empty. +/// +/// # Arguments +/// +/// * `connection`: The connection type to use - either TCP or a Unix socket connection +/// +/// # Returns +/// +/// An [`IoResult`] containing the server's response +/// +pub fn shutdown(connection: T) -> IoResult { + let stream = connection.connect()?; + send_command(stream, SHUTDOWN, None) +} diff --git a/src/tokio.rs b/src/tokio.rs index 43b5d76..538d9c4 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -12,7 +12,7 @@ use tokio::net::UnixStream; #[cfg(feature = "tokio-stream")] use tokio_stream::{Stream, StreamExt}; -use super::{IoResult, DEFAULT_CHUNK_SIZE, END_OF_STREAM, INSTREAM, PING, PONG, VERSION}; +use super::{IoResult, DEFAULT_CHUNK_SIZE, END_OF_STREAM, INSTREAM, PING, PONG, SHUTDOWN, VERSION}; async fn send_command( mut stream: RW, @@ -486,3 +486,22 @@ pub async fn scan_stream< let output_stream = connection.connect().await?; _scan_stream(input_stream, chunk_size, output_stream).await } + +/// Shuts down a ClamAV server +/// +/// This function establishes a connection to a ClamAV server and sends the +/// SHUTDOWN command to it. If the server is available, it will perform a clean +/// exit and shut itself down. The response will be empty. +/// +/// # Arguments +/// +/// * `connection`: The connection type to use - either TCP or a Unix socket connection +/// +/// # Returns +/// +/// An [`IoResult`] containing the server's response +/// +pub async fn shutdown(connection: T) -> IoResult { + let stream = connection.connect().await?; + send_command(stream, SHUTDOWN, None).await +}