commit d1d432d3505e4c9e5016688fde9431ef8dc5dd08 Author: Ivan Bushchik Date: Wed Jan 10 21:44:44 2024 +0300 Initial commit Signed-off-by: Ivan Bushchik diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6227ff1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,85 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "privod" +version = "0.1.0" +dependencies = [ + "cc", + "rand", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..064f405 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "privod" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" + + +[build-dependencies] +cc = "1.0.46" + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9863be0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2024 Ivan Bushchik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c7ee4c5 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Privod (оптический привод) + +Ejects CD/DVD/BD drive at random time (from 5 secs to 5 mins) + +Linux only. + +## Usage + +```shell +cargo run +``` + +`PATH_TO_DRIVE` is usually `/dev/sr0` + +## TODO + +- [ ] Delay setup + +## License + +The project is licensed under the terms of the [MIT license](./LICENSE). diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b0d7ebd --- /dev/null +++ b/build.rs @@ -0,0 +1,6 @@ +fn main() { + cc::Build::new() + .file("src/get_status.c") + .compile("get_status"); + println!("cargo:rerun-if-changed=src/get_status.c"); +} diff --git a/src/get_status.c b/src/get_status.c new file mode 100644 index 0000000..ee2bbf2 --- /dev/null +++ b/src/get_status.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +int get_status(char *drive_path) { + int cdrom; + int status=1; + + if ((cdrom = open(drive_path,O_RDONLY | O_NONBLOCK)) < 0) { + status=2; + } + + if (ioctl(cdrom,CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN) { + status=0; + } + + close(cdrom); + return status; +} + +void eject(char *drive_path) { + // Ignoring everything + int cdrom; + cdrom = open(drive_path, O_RDONLY | O_NONBLOCK); + ioctl (cdrom, CDROMEJECT); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..fcb5e43 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,32 @@ +use rand::Rng; +use std::ffi::{c_char, CString}; + +#[link(name = "get_status")] +extern "C" { + pub fn get_status(drive_path: *const c_char) -> std::ffi::c_int; + pub fn eject(drive_path: *const c_char); +} + +fn sleep_rnd() { + let sleeptime = rand::thread_rng().gen_range(5..300); + eprintln!("Sleeping for {} secs", &sleeptime); + std::thread::sleep(std::time::Duration::from_secs(sleeptime)); +} + +fn main() { + let dr_name = CString::new(std::env::args().collect::>()[1].as_bytes()).unwrap(); + println!("{:?}", unsafe { get_status(dr_name.as_ptr()) }); + unsafe { + loop { + if get_status(dr_name.as_ptr()) != 0x1 { + while get_status(dr_name.as_ptr()) != 0x1_i32 { + eprintln!("Status != 0x1, sleeping 100ms"); + std::thread::sleep(std::time::Duration::from_millis(100)); + } + sleep_rnd() + } + eject(dr_name.as_ptr()); + sleep_rnd(); + } + } +}