autocommit 2022-02-24 16:30:11 CET
This commit is contained in:
parent
666e475032
commit
7d28d30666
39 changed files with 1670 additions and 209 deletions
103
src/xwayland/xsocket.rs
Normal file
103
src/xwayland/xsocket.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
use crate::xwayland::XWaylandError;
|
||||
use crate::ErrorFmt;
|
||||
use std::io::{Read, Write};
|
||||
use std::rc::Rc;
|
||||
use uapi::{c, format_ustr, Errno, OwnedFd, Ustring};
|
||||
|
||||
const SOCK_DIR: &str = "/tmp/.X11-unix";
|
||||
|
||||
pub struct XSocket {
|
||||
pub id: u32,
|
||||
pub path: Ustring,
|
||||
pub lock_path: Ustring,
|
||||
}
|
||||
|
||||
impl Drop for XSocket {
|
||||
fn drop(&mut self) {
|
||||
let _ = uapi::unlink(&self.path);
|
||||
let _ = uapi::unlink(&self.lock_path);
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_socket(fd: &Rc<OwnedFd>, id: u32) -> Result<(XSocket, Rc<OwnedFd>), XWaylandError> {
|
||||
let path = format_ustr!("{}/X{}", SOCK_DIR, id);
|
||||
let lock_path = format_ustr!("/tmp/.X{}-lock", id);
|
||||
let mut lock_fd = 'open_lock_file: {
|
||||
for i in 0..2 {
|
||||
if let Ok(fd) = uapi::open(
|
||||
&*lock_path,
|
||||
c::O_CREAT | c::O_CLOEXEC | c::O_WRONLY | c::O_EXCL,
|
||||
0o444,
|
||||
) {
|
||||
break 'open_lock_file fd;
|
||||
}
|
||||
if i == 1 {
|
||||
return Err(XWaylandError::AlreadyInUse);
|
||||
}
|
||||
let mut fd = match uapi::open(&*lock_path, c::O_CLOEXEC | c::O_RDONLY, 0) {
|
||||
Ok(f) => f,
|
||||
Err(e) => return Err(XWaylandError::ReadLockFile(e.into())),
|
||||
};
|
||||
let mut pid = String::new();
|
||||
if let Err(e) = fd.read_to_string(&mut pid) {
|
||||
return Err(XWaylandError::ReadLockFile(e.into()));
|
||||
}
|
||||
let pid = match pid.trim().parse() {
|
||||
Ok(p) => p,
|
||||
Err(e) => return Err(XWaylandError::NotALockFile(e)),
|
||||
};
|
||||
match uapi::kill(pid, 0) {
|
||||
Err(Errno(c::ESRCH)) => {
|
||||
let _ = uapi::unlink(&lock_path);
|
||||
}
|
||||
_ => return Err(XWaylandError::AlreadyInUse),
|
||||
}
|
||||
}
|
||||
return Err(XWaylandError::AlreadyInUse);
|
||||
};
|
||||
let _ = uapi::unlink(&path);
|
||||
let mut addr: c::sockaddr_un = uapi::pod_zeroed();
|
||||
addr.sun_family = c::AF_UNIX as _;
|
||||
let sun_path = uapi::as_bytes_mut(&mut addr.sun_path[..]);
|
||||
sun_path[..path.len()].copy_from_slice(path.as_bytes());
|
||||
sun_path[path.len()] = 0;
|
||||
if let Err(e) = uapi::bind(fd.raw(), &addr) {
|
||||
return Err(XWaylandError::BindFailed(e.into()));
|
||||
}
|
||||
let s = format!("{:10}\n", uapi::getpid());
|
||||
if let Err(e) = lock_fd.write_all(s.as_bytes()) {
|
||||
return Err(XWaylandError::WriteLockFile(e.into()));
|
||||
}
|
||||
let xsocket = XSocket {
|
||||
id,
|
||||
path,
|
||||
lock_path,
|
||||
};
|
||||
Ok((xsocket, fd.clone()))
|
||||
}
|
||||
|
||||
pub(super) fn allocate_socket() -> Result<(XSocket, Rc<OwnedFd>), XWaylandError> {
|
||||
match uapi::stat(SOCK_DIR) {
|
||||
Err(Errno(c::ENOENT)) => return Err(XWaylandError::MissingSocketDir),
|
||||
Err(e) => return Err(XWaylandError::StatSocketDir(e.into())),
|
||||
Ok(s) if s.st_mode & c::S_IFMT != c::S_IFDIR => return Err(XWaylandError::NotASocketDir),
|
||||
_ => {
|
||||
if uapi::access(SOCK_DIR, c::W_OK).is_err() {
|
||||
return Err(XWaylandError::SocketDirNotWritable);
|
||||
}
|
||||
}
|
||||
}
|
||||
let fd = match uapi::socket(c::AF_UNIX, c::SOCK_STREAM | c::SOCK_CLOEXEC, 0) {
|
||||
Ok(f) => Rc::new(f),
|
||||
Err(e) => return Err(XWaylandError::SocketFailed(e.into())),
|
||||
};
|
||||
for i in 0..1000 {
|
||||
match bind_socket(&fd, i) {
|
||||
Ok(s) => return Ok(s),
|
||||
Err(e) => {
|
||||
log::warn!("Cannot use the :{} display: {}", i, ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(XWaylandError::AddressesInUse)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue