Skip to content

Commit

Permalink
Handling the ENODEV errors for Linux (closes #28)
Browse files Browse the repository at this point in the history
  • Loading branch information
svartalf committed May 30, 2019
1 parent 9e174e0 commit b020367
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 19 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.7.3] - 2019-05-30
### Fixed
- `ENODEV` errors for Linux are now handled the same as `ENOENT` [#28](https://github.com/svartalf/rust-battery/issues/28)

### Changed
- Relaxing `uom` dependency version to `^0.23` for `battery` crate
- Relaxing `libc` dependency version to `^0.2` for `battery-ffi` crate

## [0.7.2] - 2019-05-21
### Fixed
- `Battery::state_of_health` and `Battery::state_of_charge` are always returning values in `0.0 ≤ x ≤ 1.0` interval
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
[![Latest Version](https://img.shields.io/crates/v/battery.svg)](https://crates.io/crates/battery)
[![Latest Version](https://docs.rs/battery/badge.svg)](https://docs.rs/battery)
[![Build Status](https://travis-ci.org/svartalf/rust-battery.svg?branch=master)](https://travis-ci.org/svartalf/rust-battery)
[![dependency status](https://deps.rs/crate/battery/0.7.2/status.svg)](https://deps.rs/crate/battery/0.7.2)
[![dependency status](https://deps.rs/crate/battery/0.7.3/status.svg)](https://deps.rs/crate/battery/0.7.3)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.31+-yellow.svg)](https://github.com/rust-random/rand#rust-version-requirements)
![Apache 2.0 OR MIT licensed](https://img.shields.io/badge/license-Apache2.0%2FMIT-blue.svg)
[![backers](https://opencollective.com/rust-battery/tiers/backer/badge.svg?label=backer&color=brightgreen)](https://opencollective.com/rust-battery)

Expand All @@ -24,10 +25,14 @@ recalculated as necessary to be returned [SI measurement units](https://www.bipm

Until `1.0.0` version API might change in any moment, be careful.

# Rust version requirements

Both `battery` and `battery-ffi` crates are requiring at least Rustc version **1.31** or greater.

## Examples

See full-featured `battop` TUI application at [GitHub](https://github.com/svartalf/rust-battop/)
or at [crates.io](https://crates.rs/crate/battop).
or at [crates.io](https://crates.io/crate/battop).

For a simple example check `battery/examples/simple.rs` in the [repository](https://github.com/svartalf/rust-battery/blob/master/battery/examples/simple.rs)

Expand Down
6 changes: 3 additions & 3 deletions battery-ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "battery-ffi"
version = "0.7.2" # remember to update html_root_url
version = "0.7.3" # remember to update html_root_url
authors = ["svartalf <[email protected]>"]
edition = "2018"
description = "FFI bindings for battery crate"
Expand All @@ -24,11 +24,11 @@ crate-type = ["cdylib"]
default = ["cbindgen"]

[dependencies.battery]
version = "0.7.1"
version = "0.7.3"
path = "../battery"

[dependencies]
libc = "0.2.51"
libc = "^0.2"

[build-dependencies]
cbindgen = { version = "0.8.0", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion battery-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
//!
//! Also, check the `examples/` directory in the repository for examples with C and Python.

#![doc(html_root_url = "https://docs.rs/battery-ffi/0.7.2")]
#![doc(html_root_url = "https://docs.rs/battery-ffi/0.7.3")]

// cbindgen==0.8.0 fails to export typedefs for opaque pointers
// from the battery crate, if this line is missing
Expand Down
7 changes: 5 additions & 2 deletions battery/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "battery"
version = "0.7.2" # remember to update html_root_url
version = "0.7.3" # remember to update html_root_url
authors = ["svartalf <[email protected]>"]
edition = "2018"
description = "Cross-platform information about batteries"
Expand All @@ -19,7 +19,10 @@ is-it-maintained-open-issues = { repository = "svartalf/rust-battery" }
[dependencies]
cfg-if = "0.1"
num-traits = { version = "0.2", default_features = false }
uom = { version = "0.23.0", features = ["autoconvert", "f32", "si"] }
uom = { version = "^0.23", features = ["autoconvert", "f32", "si"] }

[dev-dependencies]
tempfile = "^3.0"

[target.'cfg(target_os = "linux")'.dependencies]
lazycell = "1.2.1"
Expand Down
9 changes: 6 additions & 3 deletions battery/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
//!
//! ## Examples
//!
//! For a quick example see [Manager](struct.Manager.html) type or `simple.rs` file in the `examples/` folder.
//! For a quick example see the [Manager](struct.Manager.html) type documentation
//! or [`simple.rs`](https://github.com/svartalf/rust-battery/blob/master/battery/examples/simple.rs)
//! file in the `examples/` folder.
//!
//! For a real-live example see [battop](https://crates.io/crates/battop) crate.
//! [battop](https://crates.io/crates/battop) crate is using this library as a knowledge source,
//! so check it out too for a real-life example.

#![deny(unused)]
#![deny(unstable_features)]
#![deny(bare_trait_objects)]
#![doc(html_root_url = "https://docs.rs/battery/0.7.2")]
#![doc(html_root_url = "https://docs.rs/battery/0.7.3")]

#[macro_use]
extern crate cfg_if;
Expand Down
3 changes: 3 additions & 0 deletions battery/src/platform/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ mod sysfs;
pub use self::device::SysFsDevice;
pub use self::iterator::SysFsIterator;
pub use self::manager::SysFsManager;

#[cfg(test)]
mod tests;
23 changes: 17 additions & 6 deletions battery/src/platform/linux/sysfs/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ use super::{Scope, Type};
use crate::units::{ElectricCharge, ElectricPotential, Energy, Power};
use crate::Result;

// From the `errno.h`.
// Easier than building whole `libc` dep.
const ENODEV: i32 = 19;

/// Read µWh value from the `energy_` file and convert into `Energy` type.
pub fn energy<T: AsRef<Path>>(path: T) -> Result<Option<Energy>> {
let path = path.as_ref();
Expand Down Expand Up @@ -87,19 +91,26 @@ pub fn scope<T: AsRef<Path>>(path: T) -> Result<Scope> {
///
/// Ok(Some(value)) - file was read properly
/// Ok(None) - file is missing
/// Err(_) - unable to access file for some reasons (except `NotFound`)
/// Err(_) - unable to access file for some reasons (except `NotFound` and `ENODEV`)
pub fn get_string<T: AsRef<Path>>(path: T) -> Result<Option<String>> {
match read_to_string(path) {
Ok(ref content) => {
// TODO: Get rid of allocation, read file only until `\n` comes
let trimmed = content.trim();
if trimmed.starts_with('\0') {
Ok(mut content) => {
if content.starts_with('\0') {
Err(io::Error::from(io::ErrorKind::InvalidData).into())
} else {
Ok(Some(trimmed.to_string()))
// In-place trim
if content.ends_with('\n') {
content.truncate(content.len() - 1);
}

Ok(Some(content))
}
}
Err(ref e) if e.kind() == io::ErrorKind::NotFound => Ok(None),
// Some drivers are creating the files, but attempt to read them
// fails with a `ENODEV` error.
// See https://github.com/svartalf/rust-battery/issues/28
Err(ref e) if e.raw_os_error() == Some(ENODEV) => Ok(None),
Err(e) => Err(e.into()),
}
}
Expand Down
38 changes: 38 additions & 0 deletions battery/src/platform/linux/tests/issue_28.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::fs;

use super::super::SysFsDevice;

// https://github.com/svartalf/rust-battery/issues/28
//
// This test is not actually covers the `ENODEV` case,
// but it would be nice to have some test cases,
// especially when people are so gracious to provide
// the test data.
#[test]
fn test_issue_28() {
let root = sysfs_test_suite!(
"charge_full_design" => 3600000,
"serial_number" => "41167",
"technology" => "Li-ion",
"charge_now" => 725000,
"present" => 1,
"manufacturer" => "Hewlett-Packard",
"type" => "Battery",
"charge_full" => 3424000,
"capacity" => 21,
"cycle_count" => 0,
"voltage_now" => 10663000,
"status" => "Discharging",
"alarm" => 340000,
"model_name" => "PABAS0241231",
"voltage_min_design" => 11400000,
"capacity_level" => "Normal"
);

let path = root.into_path();
let device = SysFsDevice::try_from(path.clone());

assert!(device.is_ok());

fs::remove_dir_all(path).unwrap();
}
22 changes: 22 additions & 0 deletions battery/src/platform/linux/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// This macro generates the bunch of files representing the
/// `/sys/class/power_supply/{name}/*` directory contents.
macro_rules! sysfs_test_suite {
( $( $name:expr => $value:expr ),* ) => {{
use ::std::io::Write as _;

let root = tempfile::tempdir().unwrap();

$(
let mut file = ::std::fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(root.path().join($name))
.unwrap();
file.write_fmt(format_args!("{}\n", $value)).unwrap();
)*

root
}};
}

mod issue_28;
2 changes: 1 addition & 1 deletion battery/src/types/battery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{State, Technology};
///
/// Consequent calls of the same method will return the same value.\
/// See the [Manager::refresh](struct.Manager.html#method.refresh) method,
/// which can be used to update information holded in the current `Battery`.
/// which can be used to update information hold in the current `Battery`.
///
/// Almost all methods are returning values in the [SI measurement units](https://www.bipm.org/en/measurement-units/),
/// represented as a units from the [uom](https://crates.io/crates/uom) crate.\
Expand Down
2 changes: 1 addition & 1 deletion ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -ex

cross build --target=${TARGET}

if [ "${TARGET}" = "i686-unknown-freebsd" ] || [ "${TARGET}" = "x86_64-unknown-freebsd" ]; then
if [[ "${TARGET}" = "i686-unknown-freebsd" ]] || [[ "${TARGET}" = "x86_64-unknown-freebsd" ]]; then
echo "'cross test' command is not available for '${TARGET}' target"
else
cross test --target=${TARGET}
Expand Down

0 comments on commit b020367

Please sign in to comment.