Skip to content

Commit 56dc70b

Browse files
committed
Support unix domain socket
Run unpfs with: 'unix!/tmp/unpfs-socket!0' /exportdir And then mount with: sudo mount -t 9p -o version=9p2000.L,trans=unix,uname=$USER /tmp/unpfs-socket:0 /mountdir
1 parent 54ad649 commit 56dc70b

File tree

2 files changed

+62
-31
lines changed

2 files changed

+62
-31
lines changed

example/unpfs/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ impl Filesystem for Unpfs {
301301
fn unpfs_main(args: Vec<String>) -> rs9p::Result<i32> {
302302
if args.len() < 3 {
303303
println!("Usage: {} proto!address!port mountpoint", args[0]);
304-
println!(" where: proto = tcp");
304+
println!(" where: proto = tcp | unix");
305305
return Ok(-1);
306306
}
307307

src/srv.rs

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use byteorder::{ReadBytesExt, WriteBytesExt};
77
use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
88
use std::collections::HashMap;
99
use std::net::TcpListener;
10+
use std::os::unix::net::UnixListener;
1011
use std::sync::{Arc, Mutex};
11-
use std::{process, thread};
1212

1313
use crate::error;
1414
use crate::error::errno::*;
@@ -381,6 +381,37 @@ fn dispatch_once<FsFid>(
381381
Ok((response, msg.tag))
382382
}
383383

384+
// Just for ReadBytesExt and WriteBytesExt
385+
trait ReadWriteBytesExt: std::io::Read + std::io::Write {}
386+
387+
impl<T> ReadWriteBytesExt for T where T: std::io::Read + std::io::Write {}
388+
389+
trait SocketListener {
390+
fn accept_client(&self) -> Result<(Box<dyn ReadWriteBytesExt + Send>, String)>;
391+
}
392+
393+
impl SocketListener for TcpListener {
394+
fn accept_client(&self) -> Result<(Box<dyn ReadWriteBytesExt + Send>, String)> {
395+
let (stream, remote) = self.accept()?;
396+
utils::setup_tcp_stream(&stream)?;
397+
398+
return Ok((Box::new(stream), remote.to_string()));
399+
}
400+
}
401+
402+
impl SocketListener for UnixListener {
403+
fn accept_client(&self) -> Result<(Box<dyn ReadWriteBytesExt + Send>, String)> {
404+
let (stream, remote) = self.accept()?;
405+
let remote = remote
406+
.as_pathname()
407+
.and_then(std::path::Path::to_str)
408+
.unwrap_or(":unnamed:")
409+
.to_owned();
410+
411+
return Ok((Box::new(stream), remote));
412+
}
413+
}
414+
384415
/// Start the 9P filesystem (fork child processes).
385416
///
386417
/// This function forks a child process to handle its 9P messages
@@ -389,12 +420,16 @@ pub fn srv<Fs: Filesystem>(filesystem: Fs, addr: &str) -> Result<()> {
389420
let (proto, sockaddr) =
390421
utils::parse_proto(addr).ok_or(io_err!(InvalidInput, "Invalid protocol or address"))?;
391422

392-
if proto != "tcp" {
393-
return res!(io_err!(
394-
InvalidInput,
395-
format!("Unsupported protocol: {}", proto)
396-
));
397-
}
423+
let listener: Box<dyn SocketListener> = match proto {
424+
"tcp" => Box::new(TcpListener::bind(&sockaddr[..])?),
425+
"unix" => Box::new(UnixListener::bind(&sockaddr[..])?),
426+
_ => {
427+
return res!(io_err!(
428+
InvalidInput,
429+
format!("Unsupported protocol: {}", proto)
430+
));
431+
}
432+
};
398433

399434
// Do not wait for child processes
400435
unsafe {
@@ -404,21 +439,18 @@ pub fn srv<Fs: Filesystem>(filesystem: Fs, addr: &str) -> Result<()> {
404439
)?;
405440
}
406441

407-
let listener = TcpListener::bind(&sockaddr[..])?;
408-
409442
loop {
410-
let (stream, remote) = listener.accept()?;
443+
let (stream, remote) = listener.accept_client()?;
411444

412445
match nix::unistd::fork()? {
413446
nix::unistd::ForkResult::Parent { .. } => {}
414447
nix::unistd::ForkResult::Child => {
415448
info!("ServerProcess={} starts", remote);
416449

417-
utils::setup_tcp_stream(&stream)?;
418450
let result = ServerInstance::new(filesystem, stream)?.dispatch();
419451

420452
info!("ServerProcess={} finished: {:?}", remote, result);
421-
process::exit(1);
453+
std::process::exit(1);
422454
}
423455
}
424456
}
@@ -432,30 +464,29 @@ pub fn srv_spawn<Fs: Filesystem + Send + 'static>(filesystem: Fs, addr: &str) ->
432464
let (proto, sockaddr) =
433465
utils::parse_proto(addr).ok_or(io_err!(InvalidInput, "Invalid protocol or address"))?;
434466

435-
if proto != "tcp" {
436-
return res!(io_err!(
437-
InvalidInput,
438-
format!("Unsupported protocol: {}", proto)
439-
));
440-
}
467+
let listener: Box<dyn SocketListener> = match proto {
468+
"tcp" => Box::new(TcpListener::bind(&sockaddr[..])?),
469+
"unix" => Box::new(UnixListener::bind(&sockaddr[..])?),
470+
_ => {
471+
return res!(io_err!(
472+
InvalidInput,
473+
format!("Unsupported protocol: {}", proto)
474+
))
475+
}
476+
};
441477

442478
let arc_fs = Arc::new(Mutex::new(filesystem));
443-
let listener = TcpListener::bind(&sockaddr[..])?;
444479

445480
loop {
446-
let (stream, remote) = listener.accept()?;
447-
let (fs, thread_name) = (arc_fs.clone(), remote.to_string());
481+
let (stream, remote) = listener.accept_client()?;
482+
let fs = arc_fs.clone();
448483

449-
let _ = thread::Builder::new()
450-
.name(thread_name.clone())
451-
.spawn(move || {
452-
info!("ServerThread={:?} started", thread_name);
484+
let _ = std::thread::Builder::new().spawn(move || {
485+
info!("ServerThread={:?} started", remote);
453486

454-
let result = utils::setup_tcp_stream(&stream)
455-
.map_err(From::from)
456-
.and_then(|_| SpawnServerInstance::new(fs, stream)?.dispatch());
487+
let result = SpawnServerInstance::new(fs, stream).and_then(|mut s| s.dispatch());
457488

458-
info!("ServerThread={:?} finished: {:?}", thread_name, result);
459-
});
489+
info!("ServerThread={} finished: {:?}", remote, result);
490+
});
460491
}
461492
}

0 commit comments

Comments
 (0)