fix: resolve compilation errors in API paths and file descriptor handling
Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) <aider@aider.chat>
This commit is contained in:
@@ -76,26 +76,30 @@ fn setup_diff_paths_and_compression(
|
|||||||
|
|
||||||
fn setup_diff_pipes() -> Result<((libc::c_int, libc::c_int), (libc::c_int, libc::c_int)), anyhow::Error> {
|
fn setup_diff_pipes() -> Result<((libc::c_int, libc::c_int), (libc::c_int, libc::c_int)), anyhow::Error> {
|
||||||
use nix::unistd::pipe;
|
use nix::unistd::pipe;
|
||||||
use nix::fcntl::{fcntl, FcntlArg, FdFlag};
|
use nix::fcntl::OFlag;
|
||||||
use nix::Error as NixError;
|
use nix::Error as NixError;
|
||||||
|
|
||||||
// Create pipes for diff's input
|
// Create pipes for diff's input with CLOEXEC flag
|
||||||
let (fd_a_read, fd_a_write) =
|
let (fd_a_read, fd_a_write) = pipe2(OFlag::O_CLOEXEC)
|
||||||
pipe().map_err(|e: NixError| anyhow::anyhow!("Failed to create pipe A: {}", e))?;
|
.map_err(|e: NixError| anyhow::anyhow!("Failed to create pipe A: {}", e))?;
|
||||||
let (fd_b_read, fd_b_write) =
|
let (fd_b_read, fd_b_write) = pipe2(OFlag::O_CLOEXEC)
|
||||||
pipe().map_err(|e: NixError| anyhow::anyhow!("Failed to create pipe B: {}", e))?;
|
.map_err(|e: NixError| anyhow::anyhow!("Failed to create pipe B: {}", e))?;
|
||||||
|
|
||||||
// Set FD_CLOEXEC on all file descriptors
|
Ok(((fd_a_read, fd_a_write), (fd_b_read, fd_b_write)))
|
||||||
fcntl(fd_a_read, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))
|
}
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to set FD_CLOEXEC on fd_a_read: {}", e))?;
|
|
||||||
fcntl(fd_a_write, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))
|
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to set FD_CLOEXEC on fd_a_write: {}", e))?;
|
|
||||||
fcntl(fd_b_read, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))
|
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to set FD_CLOEXEC on fd_b_read: {}", e))?;
|
|
||||||
fcntl(fd_b_write, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))
|
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to set FD_CLOEXEC on fd_b_write: {}", e))?;
|
|
||||||
|
|
||||||
Ok(((fd_a_read.into(), fd_a_write.into()), (fd_b_read.into(), fd_b_write.into())))
|
// Helper function to create pipes with CLOEXEC flag
|
||||||
|
fn pipe2(flags: OFlag) -> nix::Result<(i32, i32)> {
|
||||||
|
use nix::unistd::pipe;
|
||||||
|
use nix::fcntl::{fcntl, FcntlArg, FdFlag};
|
||||||
|
|
||||||
|
let (read_fd, write_fd) = pipe()?;
|
||||||
|
|
||||||
|
// Set the flags
|
||||||
|
fcntl(read_fd, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))?;
|
||||||
|
fcntl(write_fd, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))?;
|
||||||
|
|
||||||
|
Ok((read_fd, write_fd))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_fd_guards(fd_a_read: libc::c_int, fd_b_read: libc::c_int) -> (FdGuard, FdGuard) {
|
fn setup_fd_guards(fd_a_read: libc::c_int, fd_b_read: libc::c_int) -> (FdGuard, FdGuard) {
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ pub async fn handle_post_item(
|
|||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
delete,
|
delete,
|
||||||
path = "/api/item/{id}",
|
path = "/api/item/{item_id}",
|
||||||
responses(
|
responses(
|
||||||
(status = 200, description = "Successfully deleted item", body = ApiResponse<()>),
|
(status = 200, description = "Successfully deleted item", body = ApiResponse<()>),
|
||||||
(status = 401, description = "Unauthorized"),
|
(status = 401, description = "Unauthorized"),
|
||||||
@@ -169,7 +169,7 @@ pub async fn handle_post_item(
|
|||||||
(status = 500, description = "Internal server error")
|
(status = 500, description = "Internal server error")
|
||||||
),
|
),
|
||||||
params(
|
params(
|
||||||
("id" = i64, Path, description = "ID of the item to delete")
|
("item_id" = i64, Path, description = "ID of the item to delete")
|
||||||
),
|
),
|
||||||
security(
|
security(
|
||||||
("bearerAuth" = [])
|
("bearerAuth" = [])
|
||||||
@@ -177,29 +177,29 @@ pub async fn handle_post_item(
|
|||||||
)]
|
)]
|
||||||
pub async fn handle_delete_item(
|
pub async fn handle_delete_item(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path(id): Path<i64>,
|
Path(item_id): Path<i64>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
ConnectInfo(addr): ConnectInfo<SocketAddr>,
|
ConnectInfo(addr): ConnectInfo<SocketAddr>,
|
||||||
) -> Result<Json<ApiResponse<()>>, StatusCode> {
|
) -> Result<Json<ApiResponse<()>>, StatusCode> {
|
||||||
if !check_auth(&headers, &state.password) {
|
if !check_auth(&headers, &state.password) {
|
||||||
warn!("Unauthorized request to DELETE /api/item/{} from {}", id, addr);
|
warn!("Unauthorized request to DELETE /api/item/{} from {}", item_id, addr);
|
||||||
return Err(StatusCode::UNAUTHORIZED);
|
return Err(StatusCode::UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that item ID is positive to prevent path traversal issues
|
// Validate that item ID is positive to prevent path traversal issues
|
||||||
if id <= 0 {
|
if item_id <= 0 {
|
||||||
warn!("Invalid item ID {} from {}", id, addr);
|
warn!("Invalid item ID {} from {}", item_id, addr);
|
||||||
return Err(StatusCode::BAD_REQUEST);
|
return Err(StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut conn = state.db.lock().await;
|
let mut conn = state.db.lock().await;
|
||||||
|
|
||||||
if let Some(item) = db::get_item(&mut *conn, id).map_err(|e| {
|
if let Some(item) = db::get_item(&mut *conn, item_id).map_err(|e| {
|
||||||
warn!("Failed to get item {} for deletion: {}", id, e);
|
warn!("Failed to get item {} for deletion: {}", item_id, e);
|
||||||
StatusCode::INTERNAL_SERVER_ERROR
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
})? {
|
})? {
|
||||||
db::delete_item(&mut *conn, item).map_err(|e| {
|
db::delete_item(&mut *conn, item).map_err(|e| {
|
||||||
warn!("Failed to delete item {}: {}", id, e);
|
warn!("Failed to delete item {}: {}", item_id, e);
|
||||||
StatusCode::INTERNAL_SERVER_ERROR
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user