-
Notifications
You must be signed in to change notification settings - Fork 30
/
lib.rs
126 lines (113 loc) · 3.44 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (C) 2021 Red Hat, Inc. All rights reserved.
//
// Authors: Christine Caulfield <ccaulfie@redhat.com>
//
// This software licensed under LGPL-2.0+
//
//! This crate provides access to the kronosnet libraries libknet and libnozzle
//! from Rust. They are a fairly thin layer around the actual API calls but with Rust data types
//! and iterators.
//!
//! No more information about knet itself will be provided here, it is expected that if
//! you feel you need access to the knet API calls, you know what they do :)
//!
//! # Example
//! extern crate rust_kronosnet as kronosnet;
//! use kronosnet::libnozzle as nozzle;
//! use std::io::{Result};
//! use std::env;
//! use std::{thread, time};
//!
//! fn main() -> Result<()>
//! {
//! let mut nozzle_name = String::from("rustnoz");
//! let handle = match nozzle::open(&mut nozzle_name, &String::from(env::current_dir().unwrap().to_str().unwrap())) {
//! Ok(h) => {
//! println!("Opened device {}", nozzle_name);
//! h
//! },
//! Err(e) => {
//! println!("Error from open: {}", e);
//! return Err(e);
//! }
//! };
//!
//! match nozzle::add_ip(handle, &"192.160.100.1".to_string(), &"24".to_string()){
//! Ok(_) => {},
//! Err(e) => {
//! println!("Error from add_ip: {}", e);
//! return Err(e);
//! }
//! }
//!
//! match nozzle::set_mtu(handle, 157){
//! Ok(_) => {},
//! Err(e) => {
//! println!("Error from set_mtu: {}", e);
//! return Err(e);
//! }
//! }
//!
//! Ok(())
//! }
mod sys;
pub mod libnozzle;
use std::os::raw::c_char;
use std::ptr::copy_nonoverlapping;
use std::ffi::CString;
use std::io::{Error, Result, ErrorKind};
// General internal routine to copy bytes from a C array into a Rust String
fn string_from_bytes(bytes: *const ::std::os::raw::c_char, max_length: usize) -> Result<String>
{
let mut newbytes = Vec::<u8>::new();
newbytes.resize(max_length, 0u8);
unsafe {
// We need to fully copy it, not shallow copy it.
// Messy casting on both parts of the copy here to get it to work on both signed
// and unsigned char machines
copy_nonoverlapping(bytes as *mut i8, newbytes.as_mut_ptr() as *mut i8, max_length);
}
// Get length of the string in old-fashioned style
let mut length: usize = 0;
let mut count : usize = 0;
for i in &newbytes {
if *i == 0 && length == 0 {
length = count;
break;
}
count += 1;
}
// Cope with an empty string
if length == 0 {
return Ok(String::new());
}
let cs = CString::new(&newbytes[0..length as usize])?;
// This is just to convert the error type
match cs.into_string() {
Ok(s) => Ok(s),
Err(_) => Err(Error::new(ErrorKind::Other, "Cannot convert to String")),
}
}
// As below but always returns a string even if there was an error doing the conversion
fn string_from_bytes_safe(bytes: *const ::std::os::raw::c_char, max_length: usize) -> String
{
match string_from_bytes(bytes, max_length) {
Ok(s) => s,
Err(_)=> "".to_string()
}
}
fn string_to_bytes(s: &String, bytes: &mut [c_char]) ->Result<()>
{
let c_name = match CString::new(s.as_str()) {
Ok(n) => n,
Err(_) => return Err(Error::new(ErrorKind::Other, "Rust conversion error")),
};
if c_name.as_bytes().len() > bytes.len() {
return Err(Error::new(ErrorKind::Other, "String too long"));
}
unsafe {
// NOTE param order is 'wrong-way round' from C
copy_nonoverlapping(c_name.as_ptr(), bytes.as_mut_ptr(), bytes.len());
}
Ok(())
}