Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ rustix = { version = "0.38.22", features = ["mm", "fs"] }
[target.'cfg(target_os = "freebsd")'.dependencies]
libc = "0.2"

[target.'cfg(target_os = "openbsd")'.dependencies]
libc = "0.2.171"

[dev-dependencies]
image = { version = "0.24", default-features = false, features = ["png"] }
rustix = { version = "0.38.22", features = ["event", "mm"] }
Expand Down
15 changes: 0 additions & 15 deletions src/node/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,10 @@ pub const DRM_MAJOR: u32 = 87;
pub const DRM_MAJOR: u32 = 226;

/// Primary DRM node prefix.
#[cfg(not(target_os = "openbsd"))]
pub const PRIMARY_NAME: &str = "card";

/// Primary DRM node prefix.
#[cfg(target_os = "openbsd")]
pub const PRIMARY_NAME: &str = "drm";

/// Control DRM node prefix.
#[cfg(not(target_os = "openbsd"))]
pub const CONTROL_NAME: &str = "controlD";

/// Control DRM node prefix.
#[cfg(target_os = "openbsd")]
pub const CONTROL_NAME: &str = "drmC";

/// Render DRM node prefix.
#[cfg(not(target_os = "openbsd"))]
pub const RENDER_NAME: &str = "renderD";

/// Render DRM node prefix.
#[cfg(target_os = "openbsd")]
pub const RENDER_NAME: &str = "drmR";
42 changes: 38 additions & 4 deletions src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,40 @@ fn devname(dev: dev_t) -> Option<String> {
Some(String::from_utf8(dev_name).expect("Returned device name is not valid utf8"))
}

#[cfg(target_os = "openbsd")]
use std::sync::Mutex;

#[cfg(target_os = "openbsd")]
static DEVNAME_LOCK: Mutex<()> = Mutex::new(());
Comment on lines +234 to +238
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to keep this static locally inside the function for now? And/or do we expect other calls to devname()?

Note that this won't help if user code - through other means - calls libc::devname() without knowing about "your / our" lock 😅

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to keep this static locally inside the function for now? And/or do we expect other calls to devname()?

Sure, I can do that

Note that this won't help if user code - through other means - calls libc::devname() without knowing about "your / our" lock 😅

True, but that's how the underlying API works so not much we can do about it imho.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I suggested the lock, I wonder if we should instead mark devname unsafe and all functions using it, while documenting that this is unsound to call from multiple threads on some platforms.


#[cfg(target_os = "openbsd")]
fn devname(dev: dev_t) -> Option<String> {
use std::ffi::CStr;

let _lock = DEVNAME_LOCK.lock().unwrap();
let buf = unsafe {
libc::devname(
dev,
libc::S_IFCHR, // Must be S_IFCHR or S_IFBLK
)
};

if buf.is_null() {
return None;
}

let dev_str =
unsafe { CStr::from_ptr(buf).to_str() }.expect("Returned device name is not valid utf8");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think to_str() can be outside of the unsafe block where .expect() already resides.


// If no device matches the specified values, or no information is
// available, a pointer to the string "??" is returned.
if dev_str == "??" {
return None;
}

Some(dev_str.to_owned())
}

/// Returns if the given device by major:minor pair is a DRM device.
#[cfg(target_os = "linux")]
pub fn is_device_drm(dev: dev_t) -> bool {
Expand All @@ -241,7 +275,7 @@ pub fn is_device_drm(dev: dev_t) -> bool {
}

/// Returns if the given device by major:minor pair is a DRM device.
#[cfg(target_os = "freebsd")]
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
pub fn is_device_drm(dev: dev_t) -> bool {
devname(dev).map_or(false, |dev_name| {
dev_name.starts_with("drm/")
Expand All @@ -252,7 +286,7 @@ pub fn is_device_drm(dev: dev_t) -> bool {
}

/// Returns if the given device by major:minor pair is a DRM device.
#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")))]
pub fn is_device_drm(dev: dev_t) -> bool {
major(dev) == DRM_MAJOR
}
Expand Down Expand Up @@ -313,7 +347,7 @@ pub fn dev_path(dev: dev_t, ty: NodeType) -> io::Result<PathBuf> {
}

/// Returns the path of a specific type of node from the DRM device described by major and minor device numbers.
#[cfg(target_os = "freebsd")]
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
pub fn dev_path(dev: dev_t, ty: NodeType) -> io::Result<PathBuf> {
// Based on libdrm `drmGetMinorNameForFD`. Should be updated if the code
// there is replaced with anything more sensible...
Expand Down Expand Up @@ -351,7 +385,7 @@ pub fn dev_path(dev: dev_t, ty: NodeType) -> io::Result<PathBuf> {
}

/// Returns the path of a specific type of node from the DRM device described by major and minor device numbers.
#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")))]
pub fn dev_path(dev: dev_t, ty: NodeType) -> io::Result<PathBuf> {
use std::io::ErrorKind;

Expand Down