e-tipsmemo

ごった煮

Rustでsambaアクセスする pavao使用

RustのソフトウェアでSambaで共有フォルダにアクセスしたい気がしたので適当なコードを書いてみる。
WSL上でいろいろ行っている。

準備

cargo new --bin samba_test
cd samba_test
cargo add pavao
cargo add clap --features derive

ここでbuildしてみると

The system library `smbclient` required by crate `pavao` was not found.

といったエラーがでてきた。

sudo apt install -y libsmbclient-dev libsmbclient

実装

use clap::Parser;
use pavao::{SmbClient, SmbCredentials, SmbOpenOptions, SmbOptions};
use regex::Regex;
use std::fs::File;
use std::io::Read;
use std::io::{BufRead, BufReader};
use std::process::exit;

/// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// Name of the person to greet
    #[arg(short, long)]
    username: Option<String>,

    #[arg(short, long)]
    password: Option<String>,

    #[arg(short, long)]
    loginfile: Option<String>,

    #[arg(short, long)]
    server: String,
}

pub fn login_info(
    username: Option<String>,
    password: Option<String>,
    loginfile: Option<String>,
) -> (String, String) {
    let (username, password) = match (username, password) {
        (Some(username), Some(password)) => (username, password),
        (_, _) => {
            let path = if let Some(path) = loginfile {
                path
            } else {
                println!("Specify username/password or login information file.");
                exit(1);
            };
            let file = File::open(path).unwrap();
            let mut reader = BufReader::new(file);
            let mut username = String::new();
            let mut password = String::new();
            let _ = reader.read_line(&mut username);
            let _ = reader.read_line(&mut password);
            let username = username.lines().collect::<String>();
            let password = password.lines().collect::<String>();
            (username, password)
        }
    };
    (username, password)
}

fn main() {
    let args = Args::parse();

    let (username, password) = login_info(args.username, args.password, args.loginfile);

    let server = format!("smb://{}", args.server);
    // Initialize a new client
    let client = SmbClient::new(
        SmbCredentials::default()
            .server(server)
            .username(username)
            .password(password),
        // .workgroup(workgroup),
        SmbOptions::default().one_share_per_server(true),
    )
    .unwrap();

    let path = r"/dtv/";

    let contents = client.list_dir(path).unwrap();
    for entry in contents {
        println!("{}", entry.name());
    }

    drop(client);
}

こんな感じで、

cargo run -- -s 192.168.100.28 -u username -p password

とか

cargo run -- -s 192.168.1.28 -l ../login.txt

sambaのログイン情報は適当に用意しておく。
clapを使用して簡単に引数設定できる。
頑張ればWindowsに保存されている情報とかつかってログインできるのだろうか?

結果



ちゃんとディレクトリ一覧を表示できた。

エラーハンドルとかよくわからないのでちゃんとやらなきゃいけない気がするけどベストプラクティスはどのようなものかとか、
DTV環境をもっと有意義なものにするためのソフトウェア開発をしていこうかなどと考えているがまず手始めになにをしようかなぁ
コピーとか移動はどうするのだろうか・・・