1extern crate libc;
9extern crate palin;
10
11use std::ffi;
12use std::fmt;
13use std::fmt::Display;
14use std::io::{self, Read};
15use std::fs::File;
16#[cfg(any(target_os = "windows", target_vendor = "apple", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
17use std::os::raw::c_char;
18#[cfg(not(any(target_os = "windows", target_os = "linux", target_os = "haiku")))]
19use std::os::raw::{c_int, c_double};
20
21#[cfg(any(target_vendor = "apple", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
22use libc::sysctl;
23#[cfg(any(target_vendor = "apple", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
24use std::mem::size_of_val;
25#[cfg(any(target_vendor = "apple", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
26use std::ptr::null_mut;
27#[cfg(not(target_os = "windows"))]
28use libc::timeval;
29#[cfg(any(target_os = "solaris", target_os = "illumos"))]
30use std::time::SystemTime;
31#[cfg(target_os = "linux")]
32use std::collections::HashMap;
33
34#[cfg(any(target_os = "solaris", target_os = "illumos"))]
35mod kstat;
36
37#[cfg(any(target_vendor = "apple", target_os="freebsd", target_os = "openbsd", target_os = "netbsd"))]
38static OS_CTL_KERN: libc::c_int = 1;
39#[cfg(any(target_vendor = "apple", target_os="freebsd", target_os = "openbsd", target_os = "netbsd"))]
40static OS_KERN_BOOTTIME: libc::c_int = 21;
41
42#[repr(C)]
44#[derive(Debug)]
45pub struct LoadAvg {
46 pub one: f64,
48 pub five: f64,
50 pub fifteen: f64,
52}
53
54#[repr(C)]
56#[derive(Debug)]
57pub struct MemInfo {
58 pub total: u64,
60 pub free: u64,
61 pub avail: u64,
62
63 pub buffers: u64,
64 pub cached: u64,
65
66 pub swap_total: u64,
68 pub swap_free: u64,
69}
70
71#[derive(Debug)]
75#[derive(Default)]
76pub struct LinuxOSReleaseInfo {
77 pub id: Option<String>,
88
89 pub id_like: Option<String>,
105
106 pub name: Option<String>,
113
114 pub pretty_name: Option<String>,
121
122 pub version: Option<String>,
129
130 pub version_id: Option<String>,
139
140 pub version_codename: Option<String>,
148
149 pub ansi_color: Option<String>,
157
158 pub logo: Option<String>,
166
167 pub cpe_name: Option<String>,
174
175 pub build_id: Option<String>,
185
186 pub variant: Option<String>,
198
199 pub variant_id: Option<String>,
207
208 pub home_url: Option<String>,
220
221 pub documentation_url: Option<String>,
225
226 pub support_url: Option<String>,
231
232 pub bug_report_url: Option<String>,
239
240 pub privacy_policy_url: Option<String>,
246}
247
248macro_rules! os_release_defaults {
249 (
250 $(
251 $(#[$meta:meta])*
252 $vis:vis fn $field:ident => $default:literal
253 )*
254 ) => {
255 $(
256 $(#[$meta])*
257 $vis fn $field(&self) -> &str {
258 match self.$field.as_ref() {
259 Some(value) => value,
260 None => $default,
261 }
262 }
263 )*
264 }
265}
266
267impl LinuxOSReleaseInfo {
268 os_release_defaults!(
269 pub fn id => "linux"
271 pub fn name => "Linux"
273 pub fn pretty_name => "Linux"
275 );
276}
277
278#[repr(C)]
280#[derive(Debug)]
281pub struct DiskInfo {
282 pub total: u64,
283 pub free: u64,
284}
285
286#[derive(Debug)]
288pub enum Error {
289 UnsupportedSystem,
290 ExecFailed(io::Error),
291 IO(io::Error),
292 SystemTime(std::time::SystemTimeError),
293 General(String),
294 Other(String),
295 Unknown,
296}
297
298impl fmt::Display for Error {
299 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
300 use self::Error::*;
301 match *self {
302 UnsupportedSystem => write!(fmt, "System is not supported"),
303 ExecFailed(ref e) => write!(fmt, "Execution failed: {}", e),
304 IO(ref e) => write!(fmt, "IO error: {}", e),
305 SystemTime(ref e) => write!(fmt, "System time error: {}", e),
306 General(ref e) => write!(fmt, "Error: {}", e),
307 Unknown => write!(fmt, "An unknown error occurred"),
308 Other(ref e) => write!(fmt, "Error: {}", e)
309 }
310 }
311}
312
313impl std::error::Error for Error {
314 fn description(&self) -> &str {
315 use self::Error::*;
316 match *self {
317 UnsupportedSystem => "unsupported system",
318 ExecFailed(_) => "execution failed",
319 IO(_) => "io error",
320 SystemTime(_) => "system time",
321 General(_) => "general error",
322 Other(_) => "other error",
323 Unknown => "unknown error",
324 }
325 }
326
327 fn cause(&self) -> Option<&dyn std::error::Error> {
328 use self::Error::*;
329 match *self {
330 UnsupportedSystem => None,
331 ExecFailed(ref e) => Some(e),
332 IO(ref e) => Some(e),
333 SystemTime(ref e) => Some(e),
334 Other(_) => None,
335 General(_) => None,
336 Unknown => None,
337 }
338 }
339}
340
341impl From<io::Error> for Error {
342 fn from(e: io::Error) -> Error {
343 Error::IO(e)
344 }
345}
346
347impl From<std::time::SystemTimeError> for Error {
348 fn from(e: std::time::SystemTimeError) -> Error {
349 Error::SystemTime(e)
350 }
351}
352
353impl From<Box<dyn std::error::Error>> for Error {
354 fn from(e: Box<dyn std::error::Error>) -> Error {
355 Error::General(e.to_string())
356 }
357}
358
359extern "C" {
360 #[cfg(any(target_vendor = "apple", target_os = "windows"))]
361 fn get_os_type() -> *const i8;
362 #[cfg(any(target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
363 fn get_os_release() -> *const i8;
364
365 #[cfg(all(not(any(target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")), any(unix, windows)))]
366 fn get_cpu_num() -> u32;
367 #[cfg(any(all(target_vendor = "apple", not(any(target_arch = "aarch64", target_arch = "arm"))), target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku"))]
368 fn get_cpu_speed() -> u64;
369
370 #[cfg(target_os = "windows")]
371 fn get_loadavg() -> LoadAvg;
372 #[cfg(any(target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku"))]
373 fn get_proc_total() -> u64;
374
375 #[cfg(any(target_vendor = "apple", target_os = "windows", target_os = "haiku"))]
376 fn get_mem_info() -> MemInfo;
377 #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
378 fn get_mem_info_bsd(mi: &mut MemInfo) ->i32;
379
380 #[cfg(any(target_os = "linux", target_vendor = "apple", target_os = "windows", target_os = "haiku"))]
381 fn get_disk_info() -> DiskInfo;
382 #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
383 fn get_disk_info_bsd(di: &mut DiskInfo) -> i32;
384}
385
386
387pub fn os_type() -> Result<String, Error> {
391 #[cfg(target_os = "linux")]
392 {
393 let mut s = String::new();
394 File::open("/proc/sys/kernel/ostype")?.read_to_string(&mut s)?;
395 s.pop(); Ok(s)
397 }
398 #[cfg(any(target_vendor = "apple", target_os = "windows"))]
399 {
400 let typ = unsafe { ffi::CStr::from_ptr(get_os_type() as *const c_char).to_bytes() };
401 Ok(String::from_utf8_lossy(typ).into_owned())
402 }
403 #[cfg(target_os = "solaris")]
404 {
405 Ok("solaris".to_string())
406 }
407 #[cfg(target_os = "illumos")]
408 {
409 Ok("illumos".to_string())
410 }
411 #[cfg(target_os = "freebsd")]
412 {
413 Ok("freebsd".to_string())
414 }
415 #[cfg(target_os = "openbsd")]
416 {
417 Ok("openbsd".to_string())
418 }
419 #[cfg(target_os = "netbsd")]
420 {
421 Ok("netbsd".to_string())
422 }
423 #[cfg(target_os = "haiku")]
424 {
425 Ok("haiku".to_string())
426 }
427 #[cfg(not(any(target_os = "linux", target_vendor = "apple", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku")))]
428 {
429 Err(Error::UnsupportedSystem)
430 }
431}
432
433pub fn os_release() -> Result<String, Error> {
437 #[cfg(target_os = "linux")]
438 {
439 let mut s = String::new();
440 File::open("/proc/sys/kernel/osrelease")?.read_to_string(&mut s)?;
441 s.pop(); Ok(s)
443 }
444 #[cfg(any(target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
445 {
446 unsafe {
447 let rp = get_os_release() as *const c_char;
448 if rp == std::ptr::null() {
449 Err(Error::Unknown)
450 } else {
451 let typ = ffi::CStr::from_ptr(rp).to_bytes();
452 Ok(String::from_utf8_lossy(typ).into_owned())
453 }
454 }
455 }
456 #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "haiku"))]
457 {
458 let release: Option<String> = unsafe {
459 let mut name: libc::utsname = std::mem::zeroed();
460 if libc::uname(&mut name) < 0 {
461 None
462 } else {
463 let cstr = std::ffi::CStr::from_ptr(name.release.as_mut_ptr());
464 Some(cstr.to_string_lossy().to_string())
465 }
466 };
467 match release {
468 None => Err(Error::Unknown),
469 Some(release) => Ok(release),
470 }
471 }
472 #[cfg(not(any(target_os = "linux", target_vendor = "apple", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku")))]
473 {
474 Err(Error::UnsupportedSystem)
475 }
476}
477
478pub fn linux_os_release() -> Result<LinuxOSReleaseInfo, Error> {
484 if !cfg!(target_os = "linux") {
485 return Err(Error::UnsupportedSystem);
486 }
487
488 let mut s = String::new();
489 File::open("/etc/os-release")?.read_to_string(&mut s)?;
490
491 let mut info: LinuxOSReleaseInfo = Default::default();
492 for l in s.split('\n') {
493 match parse_line_for_linux_os_release(l.trim().to_string()) {
494 Some((key, value)) =>
495 match (key.as_ref(), value) {
496 ("ID", val) => info.id = Some(val),
497 ("ID_LIKE", val) => info.id_like = Some(val),
498 ("NAME", val) => info.name = Some(val),
499 ("PRETTY_NAME", val) => info.pretty_name = Some(val),
500
501 ("VERSION", val) => info.version = Some(val),
502 ("VERSION_ID", val) => info.version_id = Some(val),
503 ("VERSION_CODENAME", val) => info.version_codename = Some(val),
504
505 ("ANSI_COLOR", val) => info.ansi_color = Some(val),
506 ("LOGO", val) => info.logo = Some(val),
507
508 ("CPE_NAME", val) => info.cpe_name = Some(val),
509 ("BUILD_ID", val) => info.build_id = Some(val),
510 ("VARIANT", val) => info.variant = Some(val),
511 ("VARIANT_ID", val) => info.variant_id = Some(val),
512
513 ("HOME_URL", val) => info.home_url = Some(val),
514 ("BUG_REPORT_URL", val) => info.bug_report_url = Some(val),
515 ("SUPPORT_URL", val) => info.support_url = Some(val),
516 ("DOCUMENTATION_URL", val) => info.documentation_url = Some(val),
517 ("PRIVACY_POLICY_URL", val) => info.privacy_policy_url = Some(val),
518 _ => {}
519 }
520 None => {}
521 }
522 }
523
524 Ok(info)
525}
526
527fn parse_line_for_linux_os_release(l: String) -> Option<(String, String)> {
528 let words: Vec<&str> = l.splitn(2, '=').collect();
529 if words.len() < 2 {
530 return None
531 }
532 let mut trim_value = String::from(words[1]);
533
534 if trim_value.starts_with('"') {
535 trim_value.remove(0);
536 }
537 if trim_value.ends_with('"') {
538 let len = trim_value.len();
539 trim_value.remove(len - 1);
540 }
541
542 return Some((String::from(words[0]), trim_value))
543}
544
545pub fn cpu_num() -> Result<u32, Error> {
549 #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
550 {
551 let ret = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
552 if ret < 1 || ret as i64 > std::u32::MAX as i64 {
553 Err(Error::IO(io::Error::last_os_error()))
554 } else {
555 Ok(ret as u32)
556 }
557 }
558 #[cfg(all(not(any(target_os = "solaris", target_os = "illumos", target_os="freebsd", target_os = "openbsd", target_os = "netbsd")), any(unix, windows)))]
559 {
560 unsafe { Ok(get_cpu_num()) }
561 }
562 #[cfg(not(any(target_os = "solaris", target_os = "illumos", unix, windows)))]
563 {
564 Err(Error::UnsupportedSystem)
565 }
566}
567
568pub fn cpu_speed() -> Result<u64, Error> {
572 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
573 {
574 Ok(kstat::cpu_mhz()?)
575 }
576 #[cfg(target_os = "linux")]
577 {
578 let mut s = String::new();
580 File::open("/proc/cpuinfo")?.read_to_string(&mut s)?;
581
582 let find_cpu_mhz = s.split('\n').find(|line|
583 line.starts_with("cpu MHz\t") ||
584 line.starts_with("BogoMIPS") ||
585 line.starts_with("clock\t") ||
586 line.starts_with("bogomips per cpu")
587 );
588
589 find_cpu_mhz.and_then(|line| line.split(':').last())
590 .and_then(|val| val.replace("MHz", "").trim().parse::<f64>().ok())
591 .map(|speed| speed as u64)
592 .ok_or(Error::Unknown)
593 }
594 #[cfg(any(all(target_vendor = "apple", not(any(target_arch = "aarch64", target_arch = "arm"))), target_os = "windows", target_os = "haiku"))]
595 {
596 unsafe { Ok(get_cpu_speed()) }
597 }
598 #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
599 {
600 let res: u64 = unsafe { get_cpu_speed() };
601 match res {
602 0 => Err(Error::IO(io::Error::last_os_error())),
603 _ => Ok(res),
604 }
605 }
606 #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "linux", all(target_vendor = "apple", not(any(target_arch = "aarch64", target_arch = "arm"))), target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku")))]
607 {
608 Err(Error::UnsupportedSystem)
609 }
610}
611
612pub fn loadavg() -> Result<LoadAvg, Error> {
616 #[cfg(target_os = "linux")]
617 {
618 let mut s = String::new();
619 File::open("/proc/loadavg")?.read_to_string(&mut s)?;
620 let loads = s.trim().split(' ')
621 .take(3)
622 .map(|val| val.parse::<f64>().unwrap())
623 .collect::<Vec<f64>>();
624 Ok(LoadAvg {
625 one: loads[0],
626 five: loads[1],
627 fifteen: loads[2],
628 })
629 }
630 #[cfg(any(target_os = "solaris", target_os = "illumos", target_vendor = "apple", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
631 {
632 let mut l: [c_double; 3] = [0f64; 3];
633 if unsafe { libc::getloadavg(l.as_mut_ptr(), l.len() as c_int) } < 3 {
634 Err(Error::Unknown)
635 } else {
636 Ok(LoadAvg {
637 one: l[0],
638 five: l[1],
639 fifteen: l[2],
640 })
641 }
642 }
643 #[cfg(any(target_os = "windows"))]
644 {
645 Ok(unsafe { get_loadavg() })
646 }
647 #[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
648 {
649 Err(Error::UnsupportedSystem)
650 }
651}
652
653pub fn proc_total() -> Result<u64, Error> {
655 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
656 {
657 Ok(kstat::nproc()?)
658 }
659 #[cfg(target_os = "linux")]
660 {
661 let mut s = String::new();
662 File::open("/proc/loadavg")?.read_to_string(&mut s)?;
663 s.split(' ')
664 .nth(3)
665 .and_then(|val| val.split('/').last())
666 .and_then(|val| val.parse::<u64>().ok())
667 .ok_or(Error::Unknown)
668 }
669 #[cfg(any(target_vendor = "apple", target_os = "windows", target_os = "haiku"))]
670 {
671 Ok(unsafe { get_proc_total() })
672 }
673 #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
674 {
675 let res: u64 = unsafe { get_proc_total() };
676 match res {
677 0 => Err(Error::IO(io::Error::last_os_error())),
678 _ => Ok(res),
679 }
680 }
681 #[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku")))]
682 {
683 Err(Error::UnsupportedSystem)
684 }
685}
686
687#[cfg(any(target_os = "solaris", target_os = "illumos"))]
688fn pagesize() -> Result<u32, Error> {
689 let ret = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
690 if ret < 1 || ret > std::u32::MAX as i64 {
691 Err(Error::Unknown)
692 } else {
693 Ok(ret as u32)
694 }
695}
696
697pub fn mem_info() -> Result<MemInfo, Error> {
701 #[cfg(target_os = "linux")]
702 {
703 let mut s = String::new();
704 File::open("/proc/meminfo")?.read_to_string(&mut s)?;
705 let mut meminfo_hashmap = HashMap::new();
706 for line in s.lines() {
707 let mut split_line = line.split_whitespace();
708 let label = split_line.next();
709 let value = split_line.next();
710 if value.is_some() && label.is_some() {
711 let label = label.unwrap().split(':').nth(0).ok_or(Error::Unknown)?;
712 let value = value.unwrap().parse::<u64>().ok().ok_or(Error::Unknown)?;
713 meminfo_hashmap.insert(label, value);
714 }
715 }
716 let total = *meminfo_hashmap.get("MemTotal").ok_or(Error::Unknown)?;
717 let free = *meminfo_hashmap.get("MemFree").ok_or(Error::Unknown)?;
718 let buffers = *meminfo_hashmap.get("Buffers").ok_or(Error::Unknown)?;
719 let cached = *meminfo_hashmap.get("Cached").ok_or(Error::Unknown)?;
720 let avail = meminfo_hashmap.get("MemAvailable").map(|v| v.clone()).or_else(|| {
721 let sreclaimable = *meminfo_hashmap.get("SReclaimable")?;
722 let shmem = *meminfo_hashmap.get("Shmem")?;
723 Some(free + buffers + cached + sreclaimable - shmem)
724 }).ok_or(Error::Unknown)?;
725 let swap_total = *meminfo_hashmap.get("SwapTotal").ok_or(Error::Unknown)?;
726 let swap_free = *meminfo_hashmap.get("SwapFree").ok_or(Error::Unknown)?;
727 Ok(MemInfo {
728 total,
729 free,
730 avail,
731 buffers,
732 cached,
733 swap_total,
734 swap_free,
735 })
736 }
737 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
738 {
739 let pagesize = pagesize()? as u64;
740 let pages = kstat::pages()?;
741 return Ok(MemInfo {
742 total: pages.physmem * pagesize / 1024,
743 avail: 0,
744 free: pages.freemem * pagesize / 1024,
745 cached: 0,
746 buffers: 0,
747 swap_total: 0,
748 swap_free: 0,
749 });
750 }
751 #[cfg(any(target_vendor = "apple", target_os = "windows", target_os = "haiku"))]
752 {
753 Ok(unsafe { get_mem_info() })
754 }
755 #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
756 {
757 let mut mi:MemInfo = MemInfo{total: 0, free: 0, avail: 0, buffers: 0,
758 cached: 0, swap_total: 0, swap_free: 0};
759 let res: i32 = unsafe { get_mem_info_bsd(&mut mi) };
760 match res {
761 -1 => Err(Error::IO(io::Error::last_os_error())),
762 0 => Ok(mi),
763 _ => Err(Error::Unknown),
764 }
765 }
766 #[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku")))]
767 {
768 Err(Error::UnsupportedSystem)
769 }
770}
771
772pub fn disk_info() -> Result<DiskInfo, Error> {
776 #[cfg(any(target_os = "linux", target_vendor = "apple", target_os = "windows", target_os = "haiku"))]
777 {
778 Ok(unsafe { get_disk_info() })
779 }
780 #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
781 {
782 let mut di:DiskInfo = DiskInfo{total: 0, free: 0};
783 let res: i32 = unsafe { get_disk_info_bsd(&mut di) };
784 match res {
785 -1 => Err(Error::IO(io::Error::last_os_error())),
786 0 => Ok(di),
787 _ => Err(Error::Unknown),
788 }
789 }
790 #[cfg(not(any(target_os = "linux", target_vendor = "apple", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "haiku")))]
791 {
792 Err(Error::UnsupportedSystem)
793 }
794}
795
796#[cfg(target_family = "unix")]
798pub fn hostname() -> Result<String, Error> {
799 unsafe {
800 let buf_size = libc::sysconf(libc::_SC_HOST_NAME_MAX) as usize;
801 let mut buf = Vec::<u8>::with_capacity(buf_size + 1);
802 if libc::gethostname(buf.as_mut_ptr() as *mut libc::c_char, buf_size) < 0 {
803 return Err(Error::IO(io::Error::last_os_error()));
804 }
805 let hostname_len = libc::strnlen(buf.as_ptr() as *const libc::c_char, buf_size);
806 buf.set_len(hostname_len);
807 Ok(ffi::CString::new(buf).unwrap().into_string().unwrap())
808 }
809}
810
811#[cfg(target_family = "windows")]
812pub fn hostname() -> Result<String, Error> {
813 use std::process::Command;
814 Command::new("hostname")
815 .output()
816 .map_err(Error::ExecFailed)
817 .map(|output| String::from_utf8(output.stdout).unwrap().trim().to_string())
818}
819
820#[cfg(not(windows))]
822pub fn boottime() -> Result<timeval, Error> {
823 let mut bt = timeval {
824 tv_sec: 0,
825 tv_usec: 0
826 };
827
828 #[cfg(any(target_os = "linux", target_os="android"))]
829 {
830 let mut s = String::new();
831 File::open("/proc/uptime")?.read_to_string(&mut s)?;
832 let secs = s.trim().split(' ')
833 .take(2)
834 .map(|val| val.parse::<f64>().unwrap())
835 .collect::<Vec<f64>>();
836 bt.tv_sec = secs[0] as libc::time_t;
837 bt.tv_usec = secs[1] as libc::suseconds_t;
838 return Ok(bt);
839 }
840 #[cfg(any(target_vendor = "apple", target_os="freebsd", target_os = "openbsd", target_os = "netbsd"))]
841 {
842 let mut mib = [OS_CTL_KERN, OS_KERN_BOOTTIME];
843 let mut size: libc::size_t = size_of_val(&bt) as libc::size_t;
844 unsafe {
845 if sysctl(&mut mib[0], 2,
846 &mut bt as *mut timeval as *mut libc::c_void,
847 &mut size, null_mut(), 0) == -1 {
848 return Err(Error::IO(io::Error::last_os_error()));
849 } else {
850 return Ok(bt);
851 }
852 }
853 }
854 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
855 {
856 let start = kstat::boot_time()?;
857 let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
858 let now = now.as_secs();
859 if now < start {
860 return Err(Error::General("time went backwards".into()));
861 }
862 bt.tv_sec = (now - start) as i64;
863 return Ok(bt);
864 }
865
866 #[cfg(target_os = "haiku")]
867 {
868 unsafe {
869 let mut sysinfo: libc::system_info = std::mem::zeroed();
870 if libc::get_system_info(&mut sysinfo) == libc::B_OK {
871 let mut now: libc::time_t = 0;
872 libc::time(&mut now);
873 bt.tv_sec = now - (sysinfo.boot_time / 1000000);
874 bt.tv_usec = (sysinfo.boot_time % 1000000) as libc::suseconds_t;
875 return Ok(bt);
876 }
877 }
878 return Err(Error::IO(io::Error::last_os_error()));
879 }
880
881 #[warn(unreachable_code)]
882 Err(Error::UnsupportedSystem)
883}
884
885
886#[derive(Debug)]
888pub struct WindowsGraphicsCard {
889 pub name: Vec<String>,
890 pub description: Vec<String>,
891 pub caption: Vec<String>,
892 pub status: Vec<String>,
893 pub status_info: Vec<String>,
894 pub availability: Vec<String>,
895 pub driver_version: Vec<String>,
896 pub adapter_ram: Vec<String>,
897 pub adapter_dac_type: Vec<String>,
898 pub current_refresh_rate: Vec<String>,
899 pub max_refresh_rate: Vec<String>,
900 pub min_refresh_rate: Vec<String>,
901 pub current_bits_per_pixel: Vec<String>,
902 pub current_horizontal_resolution: Vec<String>,
903 pub current_vertical_resolution: Vec<String>,
904 pub current_number_of_colors: Vec<String>,
905 pub current_number_of_columns: Vec<String>,
906 pub current_number_of_rows: Vec<String>,
907 pub current_scan_mode: Vec<String>,
908 pub device_id: Vec<String>,
909 pub dither_type: Vec<String>,
910 pub driver_date: Vec<String>,
911 pub icm_intent: Vec<String>,
912 pub icm_method: Vec<String>,
913 pub inf_file_name: Vec<String>,
914 pub inf_section: Vec<String>,
915 pub install_date: Vec<String>,
916 pub installed_display_drivers: Vec<String>,
917 pub max_memory_supported: Vec<String>,
918 pub max_number_controlled: Vec<String>,
919 pub monochrome: Vec<String>,
920 pub number_of_color_planes: Vec<String>,
921 pub number_of_video_pages: Vec<String>,
922 pub pnp_device_id: Vec<String>,
923 pub power_management_capabilities: Vec<String>,
924 pub power_management_supported: Vec<String>,
925 pub protocol_supported: Vec<String>,
926 pub reserved_system_palette_entries: Vec<String>,
927 pub specification_version: Vec<String>,
928 pub system_creation_classname: Vec<String>,
929 pub system_name: Vec<String>,
930 pub system_palette_entries: Vec<String>,
931 pub time_of_last_reset: Vec<String>,
932 pub video_architecture: Vec<String>,
933 pub video_memory_type: Vec<String>,
934 pub video_mode: Vec<String>,
935 pub video_mode_description: Vec<String>,
936 pub video_processor: Vec<String>,
937 pub accelerator_capabilities: Vec<String>,
938 pub capability_descriptions: Vec<String>,
939 pub color_table_entries: Vec<String>,
940 pub config_manager_error_code: Vec<String>,
941 pub config_manager_user_config: Vec<String>,
942 pub creation_classname: Vec<String>
943}
944
945pub fn get_graphics_info() -> std::result::Result<WindowsGraphicsCard, std::io::Error> {
947 if !cfg!(target_os = "windows") {
948 return Err(std::io::Error::new(std::io::ErrorKind::Other, "The 'get_graphics_info()' function is only available on windows."));
949 }
950 use std::process::{Command, Output};
951 use std::str;
952
953 let name = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("name").output().unwrap();
954 let driver_version = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("driverversion").output().unwrap();
955 let adapter_ram = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("adapterram").output().unwrap();
956 let video_mode_description = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("VideoModeDescription").output().unwrap();
957 let current_refresh_rate = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentRefreshRate").output().unwrap();
958 let current_bits_per_pixel = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentBitsPerPixel").output().unwrap();
959 let current_number_of_colors = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentNumberOfColors").output().unwrap();
960 let current_number_of_columns = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentNumberOfColumns").output().unwrap();
961 let current_number_of_rows = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentNumberOfRows").output().unwrap();
962 let current_horizontal_resolution = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentHorizontalResolution").output().unwrap();
963 let current_vertical_resolution = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentVerticalResolution").output().unwrap();
964 let current_scan_mode = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CurrentScanMode").output().unwrap();
965 let device_id = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("DeviceID").output().unwrap();
966 let dither_type = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("DitherType").output().unwrap();
967 let driver_date = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("DriverDate").output().unwrap();
968 let icm_intent = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ICMIntent").output().unwrap();
969 let icm_method = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ICMMethod").output().unwrap();
970 let inf_file_name = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("InfFilename").output().unwrap();
971 let inf_section = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("InfSection").output().unwrap();
972 let install_date = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("InstallDate").output().unwrap();
973 let installed_display_drivers = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("InstalledDisplayDrivers").output().unwrap();
974 let max_memory_supported = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("MaxMemorySupported").output().unwrap();
975 let max_number_controlled = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("MaxNumberControlled").output().unwrap();
976 let max_refresh_rate = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("MaxRefreshRate").output().unwrap();
977 let min_refresh_rate = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("MinRefreshRate").output().unwrap();
978 let monochrome = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("Monochrome").output().unwrap();
979 let number_of_color_planes = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("NumberOfColorPlanes").output().unwrap();
980 let number_of_video_pages = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("NumberOfVideoPages").output().unwrap();
981 let pnp_device_id = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("PNPDeviceID").output().unwrap();
982 let power_management_capabilities = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("PowerManagementCapabilities").output().unwrap();
983 let power_management_supported = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("PowerManagementSupported").output().unwrap();
984 let description = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("Description").output().unwrap();
985 let protocol_supported = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ProtocolSupported").output().unwrap();
986 let reserved_system_palette_entries = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ReservedSystemPaletteEntries").output().unwrap();
987 let specification_version = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("SpecificationVersion").output().unwrap();
988 let status = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("Status").output().unwrap();
989 let status_info = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("StatusInfo").output().unwrap();
990 let system_creation_classname = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("SystemCreationClassName").output().unwrap();
991 let system_name = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("SystemName").output().unwrap();
992 let system_palette_entries = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("SystemPaletteEntries").output().unwrap();
993 let time_of_last_reset = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("TimeOfLastReset").output().unwrap();
994 let video_architecture = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("VideoArchitecture").output().unwrap();
995 let video_memory_type = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("VideoMemoryType").output().unwrap();
996 let video_mode = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("VideoMode").output().unwrap();
997 let video_processor = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("VideoProcessor").output().unwrap();
998 let accelerator_capabilities = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("AcceleratorCapabilities").output().unwrap();
999 let adapter_dac_type = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("AdapterDACType").output().unwrap();
1000 let availability = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("Availability").output().unwrap();
1001 let capability_descriptions = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CapabilityDescriptions").output().unwrap();
1002 let caption = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("Caption").output().unwrap();
1003 let color_table_entries = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ColorTableEntries").output().unwrap();
1004 let config_manager_error_code = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ConfigManagerErrorCode").output().unwrap();
1005 let config_manager_user_config = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("ConfigManagerUserConfig").output().unwrap();
1006 let creation_classname = Command::new("wmic").arg("path").arg("win32_VideoController").arg("get").arg("CreationClassName").output().unwrap();
1007
1008 fn windows_outputs_cleanup(output: Output) -> Vec<String> {
1009 let parse_output = str::from_utf8(&output.stdout).unwrap();
1010
1011 let mut new_string_array = vec![];
1012
1013 for (index, line) in parse_output.lines().enumerate() {
1014 if index != 0 && line != "" {
1015 let line = line.replace("\r", "").trim().to_string();
1016
1017 if line != "".to_string() {
1018 new_string_array.push(line.to_string())
1019 }
1020 }
1021 }
1022
1023 return new_string_array;
1024 }
1025
1026 Ok(WindowsGraphicsCard {
1027 accelerator_capabilities: windows_outputs_cleanup(accelerator_capabilities),
1028 name: windows_outputs_cleanup(name),
1029 description: windows_outputs_cleanup(description),
1030 caption: windows_outputs_cleanup(caption),
1031 driver_version: windows_outputs_cleanup(driver_version),
1032 availability: windows_outputs_cleanup(availability),
1033 adapter_ram: windows_outputs_cleanup(adapter_ram),
1034 adapter_dac_type: windows_outputs_cleanup(adapter_dac_type),
1035 current_refresh_rate: windows_outputs_cleanup(current_refresh_rate),
1036 max_refresh_rate: windows_outputs_cleanup(max_refresh_rate),
1037 min_refresh_rate: windows_outputs_cleanup(min_refresh_rate),
1038 current_bits_per_pixel: windows_outputs_cleanup(current_bits_per_pixel),
1039 current_number_of_colors: windows_outputs_cleanup(current_number_of_colors),
1040 current_number_of_columns: windows_outputs_cleanup(current_number_of_columns),
1041 current_number_of_rows: windows_outputs_cleanup(current_number_of_rows),
1042 current_horizontal_resolution: windows_outputs_cleanup(current_horizontal_resolution),
1043 current_vertical_resolution: windows_outputs_cleanup(current_vertical_resolution),
1044 current_scan_mode: windows_outputs_cleanup(current_scan_mode),
1045 device_id: windows_outputs_cleanup(device_id),
1046 dither_type: windows_outputs_cleanup(dither_type),
1047 driver_date: windows_outputs_cleanup(driver_date),
1048 icm_intent: windows_outputs_cleanup(icm_intent),
1049 icm_method: windows_outputs_cleanup(icm_method),
1050 inf_file_name: windows_outputs_cleanup(inf_file_name),
1051 inf_section: windows_outputs_cleanup(inf_section),
1052 install_date: windows_outputs_cleanup(install_date),
1053 installed_display_drivers: windows_outputs_cleanup(installed_display_drivers),
1054 max_memory_supported: windows_outputs_cleanup(max_memory_supported),
1055 max_number_controlled: windows_outputs_cleanup(max_number_controlled),
1056 monochrome: windows_outputs_cleanup(monochrome),
1057 number_of_color_planes: windows_outputs_cleanup(number_of_color_planes),
1058 number_of_video_pages: windows_outputs_cleanup(number_of_video_pages),
1059 pnp_device_id: windows_outputs_cleanup(pnp_device_id),
1060 power_management_capabilities: windows_outputs_cleanup(power_management_capabilities),
1061 power_management_supported: windows_outputs_cleanup(power_management_supported),
1062 protocol_supported: windows_outputs_cleanup(protocol_supported),
1063 reserved_system_palette_entries: windows_outputs_cleanup(reserved_system_palette_entries),
1064 specification_version: windows_outputs_cleanup(specification_version),
1065 status: windows_outputs_cleanup(status),
1066 status_info: windows_outputs_cleanup(status_info),
1067 system_creation_classname: windows_outputs_cleanup(system_creation_classname),
1068 system_name: windows_outputs_cleanup(system_name),
1069 system_palette_entries: windows_outputs_cleanup(system_palette_entries),
1070 time_of_last_reset: windows_outputs_cleanup(time_of_last_reset),
1071 video_architecture: windows_outputs_cleanup(video_architecture),
1072 video_memory_type: windows_outputs_cleanup(video_memory_type),
1073 video_mode: windows_outputs_cleanup(video_mode),
1074 video_mode_description: windows_outputs_cleanup(video_mode_description),
1075 video_processor: windows_outputs_cleanup(video_processor),
1076 capability_descriptions: windows_outputs_cleanup(capability_descriptions),
1077 color_table_entries: windows_outputs_cleanup(color_table_entries),
1078 config_manager_error_code: windows_outputs_cleanup(config_manager_error_code),
1079 config_manager_user_config: windows_outputs_cleanup(config_manager_user_config),
1080 creation_classname: windows_outputs_cleanup(creation_classname)
1081 })
1082}
1083
1084#[cfg(any(target_os = "windows", target_os = "linux"))]
1086pub fn check_computer_type<'a>() -> std::result::Result<&'a str, Error> {
1087 use std::process::{Command, Output};
1088 use std::str;
1089 let mut result = "Unknown";
1090
1091 #[cfg(target_os = "windows")]
1092 {
1093 fn computer_type_cleanup_for_windows<'a>(our_output: Output) -> &'a str {
1094 let get_output = str::from_utf8(&our_output.stdout).unwrap()
1095 .replace("\r", "")
1096 .replace("\n", "")
1097 .replace("chassistypes", "")
1098 .replace("-", "")
1099 .replace(" ", "");
1100
1101 return match get_output.as_str() {
1102 "{1}" => "Other", "{2}" => "Unknown", "{3}" => "Desktop", "{4}" => "Low Profile Desktop", "{5}" => "Pizza Box",
1103 "{6}" => "Mini Tower", "{7}" => "Tower", "{8}" => "Portable", "{9}" => "Laptop", "{10}" => "Notebook", "{11}" => "Handheld",
1104 "{12}" => "Docking Station", "{13}" => "All-in-One", "{14}" => "Sub-Notebook", "{15}" => "Space Saving", "{16}" => "Lunch Box",
1105 "{17}" => "Main System Chassis", "{18}" => "Expansion Chassis", "{19}" => "Sub-Chassis", "{20}" => "Bus Expansion Chassis",
1106 "{21}" => "Peripheral Chassis", "{22}" => "Storage Chassis", "{23}" => "Rack Mount Chassis", "{24}" => "Sealed-Case PC",
1107 &_ => "Unknown"
1108 }
1109 }
1110
1111 let chassis_type_number = Command::new("powershell")
1112 .arg("Get-WmiObject")
1113 .arg("win32_systemenclosure | select chassistypes")
1114 .output();
1115
1116 match chassis_type_number {
1117 Ok(chassis_num) => result = computer_type_cleanup_for_windows(chassis_num),
1118 Err(err) => return Err(Error::ExecFailed(err))
1119 };
1120
1121
1122 };
1123
1124 #[cfg(target_os = "linux")]
1125 {
1126 let check_bat0 = Command::new("sh")
1127 .arg("-c")
1128 .arg("test -d /sys/class/power_supply/BAT0")
1129 .output();
1130
1131
1132 let check_bat0 = match check_bat0 {
1133 Ok(bat) => bat.status.success(),
1134 Err(error) => return Err(Error::ExecFailed(error))
1135 };
1136
1137 let check_bat1 = Command::new("sh")
1138 .arg("-c")
1139 .arg("test -d /sys/class/power_supply/BAT1")
1140 .output();
1141
1142 let check_bat1 = match check_bat1 {
1143 Ok(bat) => bat.status.success(),
1144 Err(error) => return Err(Error::ExecFailed(error))
1145 };
1146
1147 let check_bat2 = Command::new("sh")
1148 .arg("-c")
1149 .arg("test -d /sys/class/power_supply/BAT2")
1150 .output();
1151
1152 let check_bat2 = match check_bat2 {
1153 Ok(bat) => bat.status.success(),
1154 Err(error) => return Err(Error::ExecFailed(error))
1155 };
1156
1157 let check_bat3 = Command::new("sh")
1158 .arg("-c")
1159 .arg("test -d /sys/class/power_supply/BAT3")
1160 .output();
1161
1162 let check_bat3 = match check_bat3 {
1163 Ok(bat) => bat.status.success(),
1164 Err(error) => return Err(Error::ExecFailed(error))
1165 };
1166
1167 if check_bat0 || check_bat1 || check_bat2 || check_bat3 {
1168 result = "Notebook";
1169 } else {
1170 result = "Desktop";
1171 }
1172 }
1173
1174 return Ok(result);
1175}
1176
1177
1178#[cfg(any(target_os = "windows", target_os = "linux"))]
1180pub fn get_current_user() -> String {
1181 use std::process::Command;
1182 use std::str::from_utf8;
1183 let result;
1184
1185 #[cfg(target_os = "windows")]
1186 {
1187 let current_user_command = Command::new("cmd")
1188 .arg("/C")
1189 .arg("echo")
1190 .arg("%username%")
1191 .output()
1192 .expect("cannot figured out user");
1193
1194 result = from_utf8(¤t_user_command.stdout).unwrap().trim().to_string()
1195 }
1196
1197 #[cfg(target_os = "linux")]
1198 {
1199 let current_user_command = Command::new("whoami")
1200 .output()
1201 .expect("cannot figured out user");
1202
1203 result = from_utf8(¤t_user_command.stdout).unwrap().trim().to_string()
1204 }
1205
1206 return result
1207}
1208
1209#[cfg(any(target_os = "windows", target_os = "linux"))]
1211pub fn get_public_ipv4_address() -> std::result::Result<String, Error> {
1212 let mut ip_address = String::new();
1213
1214 #[cfg(target_os = "linux")]
1215 {
1216 extern crate palin;
1217 use palin::{check_if_curl_exist, check_if_dig_exist, check_if_wget_exist};
1218
1219 if check_if_dig_exist() {
1220 let dig_command = std::process::Command::new("dig").arg("+short").arg("myip.opendns.com").arg("@resolver1.opendns.com").output();
1221
1222 match dig_command {
1223 Ok(answer) => {
1224 let parse_answer = std::str::from_utf8(&answer.stdout).unwrap();
1225
1226 ip_address = parse_answer.trim().to_string();
1227 },
1228 Err(error) => return Err(Error::Other(error.to_string()))
1229 }
1230 } else if check_if_wget_exist() {
1231 let wget_command = std::process::Command::new("wget").arg("-qO-").arg("ifconfig.me/ip").output();
1232
1233 match wget_command {
1234 Ok(answer) => {
1235 let parse_answer = std::str::from_utf8(&answer.stdout).unwrap();
1236
1237 ip_address = parse_answer.trim().to_string();
1238 },
1239 Err(error) => return Err(Error::Other(error.to_string()))
1240 }
1241 } else if check_if_curl_exist() {
1242 let curl_command = std::process::Command::new("curl").arg("ifconfig.me/ip").output();
1243
1244 match curl_command {
1245 Ok(answer) => {
1246 let parse_answer = std::str::from_utf8(&answer.stdout).unwrap();
1247
1248 ip_address = parse_answer.trim().to_string();
1249 },
1250 Err(error) => return Err(Error::Other(error.to_string()))
1251 }
1252 }
1253 }
1254
1255 #[cfg(target_os = "windows")]
1256 {
1257 let get_ip_address = std::process::Command::new("powershell").arg("-Command").arg("(Invoke-WebRequest -Uri \"http://ifconfig.me/ip\").Content").output();
1258
1259 match get_ip_address {
1260 Ok(answer) => {
1261 let parse_answer = std::str::from_utf8(&answer.stdout).unwrap();
1262
1263 ip_address = parse_answer.trim().to_string()
1264 },
1265 Err(error) => return Err(Error::Other(error.to_string()))
1266 }
1267 }
1268
1269 return Ok(ip_address)
1270}
1271
1272pub fn is_program_installed(program: &str) -> bool {
1274 let check1 = std::process::Command::new(program).output();
1275
1276 match check1 {
1277 Ok(_) => return true,
1278 Err(_) => ()
1279 };
1280
1281 let check2 = std::process::Command::new(program).arg("version").output();
1282
1283 match check2 {
1284 Ok(_) => return true,
1285 Err(_) => ()
1286 };
1287
1288 let check3 = std::process::Command::new(program).arg("--version").output();
1289
1290 match check3 {
1291 Ok(_) => return true,
1292 Err(_) => ()
1293 }
1294
1295 let check4 = std::process::Command::new(program).arg("-version").output();
1296
1297 match check4 {
1298 Ok(_) => return true,
1299 Err(_) => ()
1300 }
1301
1302 let check5 = std::process::Command::new(program).arg("-v").output();
1303
1304 match check5 {
1305 Ok(_) => return true,
1306 Err(_) => ()
1307 }
1308
1309 return false
1310}
1311
1312
1313#[derive(Debug)]
1315pub struct HardSearchOptions{
1316 pub case_sensitive: bool,
1317 pub search_hardness: u8
1318}
1319
1320pub fn is_program_installed_search_hard(program: &str, options: HardSearchOptions) -> std::result::Result<bool, std::io::Error> {
1322 if !cfg!(target_os = "windows") {
1323 return Err(std::io::Error::new(std::io::ErrorKind::Other, "The 'is_program_installed_search_hard()' function is only available on windows."));
1324 }
1325
1326 if options.search_hardness == 0 {
1327 return Ok(false);
1328 }
1329
1330 let check1 = std::process::Command::new(program).output();
1331
1332 match check1 {
1333 Ok(_) => return Ok(true),
1334 Err(_) => ()
1335 };
1336
1337 if options.search_hardness == 1 {
1338 return Ok(false);
1339 }
1340
1341 let check2 = std::process::Command::new(program).arg("version").output();
1342
1343 match check2 {
1344 Ok(_) => return Ok(true),
1345 Err(_) => ()
1346 };
1347
1348 if options.search_hardness == 2 {
1349 return Ok(false);
1350 }
1351
1352 let check3 = std::process::Command::new(program).arg("--version").output();
1353
1354 match check3 {
1355 Ok(_) => return Ok(true),
1356 Err(_) => ()
1357 }
1358
1359 if options.search_hardness == 3 {
1360 return Ok(false);
1361 }
1362
1363 let check4 = std::process::Command::new("powershell").arg("Get-Package").output();
1364
1365 match check4 {
1366 Ok(answer) => {
1367 let parse_answer = String::from_utf8_lossy(&answer.stdout);
1368
1369 for line in parse_answer.lines() {
1370 if options.case_sensitive {
1371 if line.trim().starts_with(program) {
1372 return Ok(true);
1373 }
1374 } else {
1375 let left_side = line.trim().to_lowercase();
1376 let left_side = String::from_utf8_lossy(left_side.as_bytes());
1377 let left_side = left_side.as_ref();
1378 let right_side = program.to_lowercase();
1379 let right_side = String::from_utf8_lossy(right_side.as_bytes());
1380 let right_side = right_side.as_ref();
1381
1382 if left_side.contains(right_side) {
1383 return Ok(true)
1384 }
1385 }
1386 }
1387 },
1388 Err(_) => ()
1389 }
1390
1391 if options.search_hardness == 4 {
1392 return Ok(false);
1393 }
1394
1395 let check5 = std::process::Command::new("powershell").arg("Get-AppxPackage").output();
1396
1397 match check5 {
1398 Ok(answer) => {
1399 let parse_answer = String::from_utf8_lossy(&answer.stdout);
1400
1401 for line in parse_answer.lines() {
1402 match options.case_sensitive {
1403 true => {
1404 if line.starts_with("Name") {
1405 let split_the_line: &str = line.split(":").collect::<Vec<&str>>()[1].trim();
1406
1407 if program == split_the_line {
1408 return Ok(true);
1409 }
1410 }
1411
1412 if line.starts_with("PackageFullName") {
1413 let split_the_line: &str = line.split(":").collect::<Vec<&str>>()[1].trim();
1414
1415 if program == split_the_line {
1416 return Ok(true);
1417 }
1418 }
1419
1420 if line.starts_with("PackageFamilyName") {
1421 let split_the_line: &str = line.split(":").collect::<Vec<&str>>()[1].trim();
1422
1423 if program == split_the_line {
1424 return Ok(true);
1425 }
1426 }
1427 },
1428 false => {
1429 if line.starts_with("Name") {
1430 let split_the_line: &str = line.split(":").collect::<Vec<&str>>()[1].trim();
1431
1432 let left_side = split_the_line.trim().to_lowercase();
1433 let left_side = String::from_utf8_lossy(left_side.as_bytes());
1434 let left_side = left_side.as_ref();
1435 let right_side = program.to_lowercase();
1436 let right_side = String::from_utf8_lossy(right_side.as_bytes());
1437 let right_side = right_side.as_ref();
1438
1439 if left_side == right_side {
1440 return Ok(true)
1441 }
1442 }
1443
1444 if line.starts_with("PackageFullName") {
1445 let split_the_line: &str = line.split(":").collect::<Vec<&str>>()[1].trim();
1446
1447 let left_side = split_the_line.trim().to_lowercase();
1448 let left_side = String::from_utf8_lossy(left_side.as_bytes());
1449 let left_side = left_side.as_ref();
1450 let right_side = program.to_lowercase();
1451 let right_side = String::from_utf8_lossy(right_side.as_bytes());
1452 let right_side = right_side.as_ref();
1453
1454 if left_side == right_side {
1455 return Ok(true)
1456 }
1457 }
1458
1459 if line.starts_with("PackageFamilyName") {
1460 let split_the_line: &str = line.split(":").collect::<Vec<&str>>()[1].trim();
1461
1462 let left_side = split_the_line.trim().to_lowercase();
1463 let left_side = String::from_utf8_lossy(left_side.as_bytes());
1464 let left_side = left_side.as_ref();
1465 let right_side = program.to_lowercase();
1466 let right_side = String::from_utf8_lossy(right_side.as_bytes());
1467 let right_side = right_side.as_ref();
1468
1469 if left_side == right_side {
1470 return Ok(true)
1471 }
1472 }
1473 }
1474 }
1475 }
1476 },
1477 Err(_) => ()
1478 }
1479
1480 if options.search_hardness == 5 {
1481 return Ok(false);
1482 }
1483
1484 let check6 = std::process::Command::new("powershell").arg("wmic").arg("product").arg("get").arg("name").output();
1485
1486 match check6 {
1487 Ok(answer) => {
1488 let parse_answer = String::from_utf8_lossy(&answer.stdout);
1489
1490 for line in parse_answer.lines() {
1491 if options.case_sensitive {
1492 if line.trim() == program {
1493 return Ok(true);
1494 }
1495 } else {
1496 if line.trim().to_lowercase().as_bytes() == program.to_lowercase().as_bytes() {
1497 return Ok(true)
1498 }
1499 }
1500 }
1501 },
1502 Err(error) => {
1503 eprintln!("for that reason we cannot take wmic output: {}", error)
1504 }
1505 }
1506
1507 return Ok(false)
1508}
1509
1510#[derive(Debug)]
1512pub struct RamInFo {
1513 pub mhz: i32,
1514 pub ddr_type: String
1515}
1516
1517pub fn get_ram_infos() -> std::result::Result<Vec<RamInFo>, std::io::Error> {
1519 if !cfg!(target_os = "windows") {
1520 return Err(std::io::Error::new(std::io::ErrorKind::Other, "The 'get_ram_infos()' function is only available on windows."));
1521 }
1522
1523 let ram_info_command = std::process::Command::new("wmic").arg("memorychip").arg("get").arg("speed").output();
1524
1525 match ram_info_command {
1526 Ok(answer) => {
1527 let parse_the_answer = std::str::from_utf8(&answer.stdout).unwrap();
1528 let mut rams = vec![];
1529
1530 for (index, line) in parse_the_answer.lines().into_iter().enumerate() {
1531 let mut mhz: i32 = 0;
1532 let mut ddr_type: String = "".to_string();
1533
1534 if index == 0 || line.trim() == "" {
1535 continue;
1536 }
1537
1538 mhz = line.trim().parse::<i32>().unwrap();
1539
1540 if mhz >= 200 && mhz <= 400 {
1541 ddr_type = "ddr1".to_string();
1542 }
1543
1544 if mhz >= 400 && mhz <= 800 {
1545 ddr_type = "ddr2".to_string();
1546 }
1547
1548 if mhz > 800 && mhz <= 1860 {
1549 ddr_type = "ddr3".to_string();
1550 }
1551
1552 if mhz >= 2133 && mhz <= 3200 {
1553 ddr_type = "ddr4".to_string();
1554 }
1555
1556 if mhz > 3200 && mhz <= 8400 {
1557 ddr_type = "ddr5".to_string();
1558 }
1559
1560 let ram_info = RamInFo {
1561 ddr_type, mhz
1562 };
1563
1564 rams.push(ram_info);
1565 }
1566
1567 return Ok(rams);
1568 },
1569 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, error.to_string()))
1570 }
1571}
1572
1573pub fn get_system_env_var(var_name: &str) -> std::result::Result<String, std::io::Error> {
1575 #[cfg(target_os = "windows")]
1576 {
1577 let sanitize_var_name = var_name.to_ascii_uppercase();
1578 let format_the_command = format!("[System.Environment]::GetEnvironmentVariable('{}', 'Machine')", sanitize_var_name);
1579
1580 let output = std::process::Command::new("powershell")
1581 .arg("-Command")
1582 .arg(format_the_command)
1583 .output();
1584
1585 return match output {
1586 Ok(var_list) => Ok(String::from_utf8_lossy(&var_list.stdout).to_string()),
1587 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::Other, error.to_string()))
1588 }
1589 }
1590
1591 #[cfg(target_os = "linux")]
1592 {
1593 let sanitize_var_name = var_name.to_ascii_uppercase();
1594
1595 let output = std::process::Command::new("printenv")
1596 .arg(sanitize_var_name)
1597 .output();
1598
1599 return match output {
1600 Ok(var_list) => Ok(String::from_utf8_lossy(&var_list.stdout).to_string()),
1601 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::Other, error.to_string()))
1602 }
1603 }
1604}
1605
1606pub fn get_user_env_var(var_name: &str) -> std::result::Result<String, std::io::Error> {
1608 if !cfg!(target_os = "windows") {
1609 return Err(std::io::Error::new(std::io::ErrorKind::Other, "The 'get_user_env_var()' function is only available on windows."));
1610 }
1611
1612 let sanitize_var_name = var_name.to_ascii_uppercase();
1613 let format_the_command = format!("[System.Environment]::GetEnvironmentVariable('{}', 'User')", sanitize_var_name);
1614
1615 let output = std::process::Command::new("powershell")
1616 .arg("-Command")
1617 .arg(format_the_command)
1618 .output();
1619
1620 return match output {
1621 Ok(var_list) => Ok(String::from_utf8_lossy(&var_list.stdout).to_string()),
1622 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::Other, error.to_string()))
1623 }
1624}
1625
1626#[cfg(target_os = "windows")]
1627#[derive(Debug)]
1628pub struct LanguageOptions {
1629 pub country: String,
1630 pub name: String,
1631 pub shortening: String,
1632 pub lcid: String
1633}
1634
1635#[cfg(target_os = "linux")]
1636#[derive(Debug)]
1637pub struct LanguageOptions {
1638 pub shortening: String,
1639 pub character_encoding: String,
1640 pub country: String,
1641}
1642
1643pub fn get_language_options() -> std::result::Result<LanguageOptions, std::io::Error> {
1645 #[cfg(target_os = "windows")]
1646 {
1647 let get_lang_options_command = std::process::Command::new("powershell.exe").arg("Get-WinSystemLocale").output();
1648
1649 match get_lang_options_command {
1650 Ok(output) => {
1651 let parse_output = String::from_utf8_lossy(&output.stdout);
1652
1653 for line in parse_output.lines() {
1654 if line.starts_with(" ") || line.starts_with("LCID") || line.starts_with("-") || line == "" {
1655 continue;
1656 }
1657
1658 let split_the_line: Vec<&str> = line.split(" ").collect::<Vec<&str>>();
1659
1660 let mut lcid = "".to_string();
1661 let mut shortening = "".to_string();
1662 let mut name = "".to_string();
1663 let mut country = "".to_string();
1664
1665 let mut i: u8 = 0;
1666 for infos in split_the_line {
1667 if i == 0 {
1668 i = i + 1;
1669
1670 lcid = infos.to_string()
1671 }
1672
1673 if infos == "" {
1674 continue;
1675 }
1676
1677 if infos.contains("-") {
1678 shortening = infos.split("-").collect::<Vec<&str>>()[0].to_string()
1679 } else {
1680 if infos != "" {
1681 if infos == "T�rk�e" {
1682 country = "Türkiye".to_string();
1683 name = "Türkçe".to_string();
1684 } else {
1685 if infos.starts_with("(") {
1686 country = infos.replace("(", "").replace("(", "")
1687 } else {
1688 name = infos.to_string()
1689 }
1690 }
1691 }
1692 }
1693
1694 }
1695
1696 return Ok(LanguageOptions{
1697 lcid,
1698 country,
1699 name,
1700 shortening
1701 })
1702 }
1703
1704 return Ok(LanguageOptions {
1705 lcid: "".to_string(),
1706 country: "".to_string(),
1707 name: "".to_string(),
1708 shortening: "".to_string()
1709 })
1710 },
1711 Err(error) => {
1712 Err(std::io::Error::new(std::io::ErrorKind::Other, error))
1713 }
1714 }
1715 }
1716
1717 #[cfg(target_os = "linux")]
1718 {
1719 let get_lang_options_command = std::process::Command::new("locale").output();
1720
1721 match get_lang_options_command {
1722 Ok(output) => {
1723 let parse_answer = String::from_utf8_lossy(&output.stdout);
1724
1725 let mut shortening = "".to_string();
1726 let mut character_encoding = "".to_string();
1727 let mut country = "".to_string();
1728
1729 for line in parse_answer.lines() {
1730 if line.starts_with("LANG") {
1731 let split_the_line = line.split("=").collect::<Vec<&str>>()[1];
1732
1733 let split_the_line_second_time = split_the_line.split(".").collect::<Vec<&str>>();
1734
1735 character_encoding = split_the_line_second_time[1].to_string();
1736
1737 let stltt = split_the_line_second_time[0].split("_").collect::<Vec<&str>>();
1738
1739 shortening = stltt[0].to_string();
1740 country = stltt[1].to_string();
1741
1742 break;
1743 } else {
1744 continue;
1745 }
1746 }
1747
1748 return Ok(LanguageOptions {
1749 shortening,
1750 country,
1751 character_encoding
1752 })
1753 },
1754 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::Other, error))
1755 }
1756
1757 }
1758}
1759
1760pub enum EnvLevel {
1762 User, Machine
1763}
1764
1765impl Display for EnvLevel {
1766 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1767 match self {
1768 &EnvLevel::Machine => write!(f, "System"),
1769 &EnvLevel::User => write!(f, "User"),
1770 }
1771 }
1772}
1773
1774pub struct EnvOptions {
1776 pub level: EnvLevel,
1777 pub name: String,
1778 pub value: String
1779}
1780
1781pub fn append_env(options: EnvOptions) -> std::result::Result<(), std::io::Error> {
1783 if !cfg!(target_os = "windows") {
1784 return Err(std::io::Error::new(std::io::ErrorKind::Other, "The 'append_env()' function is only available on windows."));
1785 }
1786
1787 let format_the_command: String;
1788
1789 match options.level {
1790 EnvLevel::User => {
1791 let variable = get_user_env_var(&options.name);
1792
1793 match variable {
1794 Ok(value) => {
1795 let appended_var = format!("{};{}", value, options.value);
1796
1797 format_the_command = format!("[System.Environment]::SetEnvironmentVariable('{}', '{}', 'User')", options.name, appended_var);
1798
1799 },
1800 Err(error) => {
1801 return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("That error occured when we try to find {} variable in user's variable: {}", options.name, error)))
1802 }
1803 }
1804 },
1805 EnvLevel::Machine => {
1806 let variable = get_system_env_var(&options.name);
1807
1808 match variable {
1809 Ok(value) => {
1810 let appended_var = format!("{};{}", value, options.value);
1811
1812 format_the_command = format!("[System.Environment]::SetEnvironmentVariable('{}', '{}', 'Machine')", options.name, appended_var)
1813
1814 },
1815 Err(error) => {
1816 return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("That error occured when we try to find {} variable in system's variable: {}", options.name, error)))
1817 }
1818 }
1819 }
1820 }
1821
1822 let execute_appending = std::process::Command::new("powershell.exe")
1823 .arg("-Command")
1824 .arg(format_the_command)
1825 .output();
1826
1827 match execute_appending {
1828 Ok(_) => {
1829 println!("{}'s {} env successfully updated.", options.level, options.name);
1830 Ok(())
1831 },
1832 Err(error) => {
1833 Err(std::io::Error::new(std::io::ErrorKind::Other, format!("That Error Occured When we updating the {}'s {} Env: {}", options.level, options.name, error)))
1834 }
1835 }
1836}
1837
1838
1839pub fn set_env(options: EnvOptions) -> std::result::Result<(), std::io::Error> {
1841 if !cfg!(target_os = "windows") {
1842 return Err(std::io::Error::new(std::io::ErrorKind::Other, "The 'set_env()' function is only available on windows."));
1843 }
1844
1845 let format_the_command: String;
1846
1847 match options.level {
1848 EnvLevel::User => format_the_command = format!("[System.Environment]::SetEnvironmentVariable('{}', '{}', 'User')", options.name, options.value),
1849 EnvLevel::Machine => format_the_command = format!("[System.Environment]::SetEnvironmentVariable('{}', '{}', 'Machine')", options.name, options.value),
1850 }
1851
1852 let execute_appending = std::process::Command::new("powershell.exe")
1853 .arg("-Command")
1854 .arg(format_the_command)
1855 .output();
1856
1857 match execute_appending {
1858 Ok(_) => {
1859 println!("{}'s {} env successfully updated.", options.level, options.name);
1860 Ok(())
1861 },
1862 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("That Error Occured When we updating the {}'s {} Env: {}", options.level, options.name, error)))
1863 }
1864}
1865
1866#[derive(Debug, Clone)]
1868pub struct UserConfigurations {
1869 pub home_dir: String,
1870 pub shell: String
1871}
1872
1873pub fn get_home_dir_and_shell(username: &str) -> Result<UserConfigurations, std::io::Error> {
1875 if !cfg!(target_os = "linux") {
1876 return Err(std::io::Error::new(std::io::ErrorKind::Other, "'get_home_dir_and_shell()' function is only available on linux."));
1877 }
1878
1879 let path = std::path::Path::new("/etc/passwd");
1880
1881 let file = File::open(&path);
1882
1883 match file {
1884 Ok(file) => {
1885 use std::io::BufRead;
1886
1887 let mut i: usize = 0;
1888
1889 for line in std::io::BufReader::new(file).lines() {
1890 if i == 0 {
1891 i = 1;
1892 }
1893
1894 match line {
1895 Ok(line) => {
1896 match line.starts_with(username) {
1897 true => {
1898 let mut split_the_lines = line.split(":");
1899
1900 match split_the_lines.nth(5) {
1901 Some(home_dir) => {
1902 match split_the_lines.nth(0) {
1903 Some(shell) => {
1904 return Ok(UserConfigurations {
1905 home_dir: home_dir.to_string(),
1906 shell: shell.to_string()
1907 })
1908 },
1909 None => return Err(std::io::Error::new(std::io::ErrorKind::Other, "Error: The /etc/passwd configurations for your user is configured unusually, we cannot find the seventh element on the row of given user."))
1910 }
1911 },
1912 None => return Err(std::io::Error::new(std::io::ErrorKind::Other, "Error: The /etc/passwd configurations for your user is configured unusually, we cannot find the sixth element on the row of given user."))
1913 }
1914 }
1915 false => continue,
1916 }
1917 },
1918 Err(error) => {
1919 return match error.kind() {
1920 std::io::ErrorKind::AddrInUse => Err(std::io::Error::new(std::io::ErrorKind::AddrInUse, error)),
1921 std::io::ErrorKind::AddrNotAvailable => Err(std::io::Error::new(std::io::ErrorKind::AddrNotAvailable, error)),
1922 std::io::ErrorKind::AlreadyExists => Err(std::io::Error::new(std::io::ErrorKind::AlreadyExists, error)),
1923 std::io::ErrorKind::BrokenPipe => Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, error)),
1924 std::io::ErrorKind::ConnectionAborted => Err(std::io::Error::new(std::io::ErrorKind::ConnectionAborted, error)),
1925 std::io::ErrorKind::ConnectionRefused => Err(std::io::Error::new(std::io::ErrorKind::ConnectionRefused, error)),
1926 std::io::ErrorKind::ConnectionReset => Err(std::io::Error::new(std::io::ErrorKind::ConnectionReset, error)),
1927 std::io::ErrorKind::Interrupted => Err(std::io::Error::new(std::io::ErrorKind::Interrupted, error)),
1928 std::io::ErrorKind::InvalidData => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, error)),
1929 std::io::ErrorKind::InvalidInput => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, error)),
1930 std::io::ErrorKind::NotConnected => Err(std::io::Error::new(std::io::ErrorKind::NotConnected, error)),
1931 std::io::ErrorKind::NotFound => Err(std::io::Error::new(std::io::ErrorKind::NotFound, error)),
1932 std::io::ErrorKind::OutOfMemory => Err(std::io::Error::new(std::io::ErrorKind::OutOfMemory, error)),
1933 std::io::ErrorKind::PermissionDenied => Err(std::io::Error::new(std::io::ErrorKind::PermissionDenied, error)),
1934 std::io::ErrorKind::TimedOut => Err(std::io::Error::new(std::io::ErrorKind::TimedOut, error)),
1935 std::io::ErrorKind::UnexpectedEof => Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, error)),
1936 std::io::ErrorKind::Unsupported => Err(std::io::Error::new(std::io::ErrorKind::Unsupported, error)),
1937 std::io::ErrorKind::WouldBlock => Err(std::io::Error::new(std::io::ErrorKind::WouldBlock, error)),
1938 std::io::ErrorKind::WriteZero => Err(std::io::Error::new(std::io::ErrorKind::WriteZero, error)),
1939 _ => Err(std::io::Error::new(std::io::ErrorKind::Other, error)),
1940 }
1941 }
1942 }
1943 }
1944
1945 match i {
1946 0 => return Err(std::io::Error::new(std::io::ErrorKind::Other, "An unexpected behavior occured: We could open Your /etc/passwd file but it is empty, which is almost impossible.")),
1947 _ => return Err(std::io::Error::new(std::io::ErrorKind::Other, "It's here because of the rust synthax, impossible to came here."))
1948 }
1949 },
1950 Err(error) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, error))
1951 };
1952}
1953
1954#[cfg(any(target_os = "windows", target_os = "linux"))]
1956pub fn get_timezone() -> Result<String, std::io::Error> {
1957 if !cfg!(target_os = "windows") && !cfg!(target_os = "linux") {
1958 return Err(std::io::Error::new(std::io::ErrorKind::Other, "'get_timezone()' function is only available on linux and windows."));
1959 }
1960
1961 let mut timezone = String::new();
1962
1963 #[cfg(target_os = "windows")]
1964 {
1965 let get_timezone = std::process::Command::new("powershell.exe").arg("Get-TimeZone").output();
1966
1967 match get_timezone {
1968 Ok(tz) => {
1969 let output = String::from_utf8_lossy(&tz.stdout);
1970
1971 for line in output.lines() {
1972 if line.starts_with("Id") {
1973 timezone = line.split(" : ").nth(1).unwrap().to_string();
1974 }
1975 }
1976 },
1977 Err(error) => return Err(error)
1978 }
1979 }
1980
1981 #[cfg(target_os = "linux")]
1982 {
1983 let path = std::path::Path::new("/etc/timezone");
1984
1985 let file = File::open(&path);
1986
1987 match file {
1988 Ok(file) => {
1989 use std::io::BufRead;
1990
1991 for line in std::io::BufReader::new(file).lines() {
1992 match line {
1993 Ok(l) => {
1994 if !l.starts_with(" ") {
1995 timezone = l
1996 }
1997 },
1998 Err(error) => {
1999 return match error.kind() {
2000 std::io::ErrorKind::AddrInUse => Err(std::io::Error::new(std::io::ErrorKind::AddrInUse, error)),
2001 std::io::ErrorKind::AddrNotAvailable => Err(std::io::Error::new(std::io::ErrorKind::AddrNotAvailable, error)),
2002 std::io::ErrorKind::AlreadyExists => Err(std::io::Error::new(std::io::ErrorKind::AlreadyExists, error)),
2003 std::io::ErrorKind::BrokenPipe => Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, error)),
2004 std::io::ErrorKind::ConnectionAborted => Err(std::io::Error::new(std::io::ErrorKind::ConnectionAborted, error)),
2005 std::io::ErrorKind::ConnectionRefused => Err(std::io::Error::new(std::io::ErrorKind::ConnectionRefused, error)),
2006 std::io::ErrorKind::ConnectionReset => Err(std::io::Error::new(std::io::ErrorKind::ConnectionReset, error)),
2007 std::io::ErrorKind::Interrupted => Err(std::io::Error::new(std::io::ErrorKind::Interrupted, error)),
2008 std::io::ErrorKind::InvalidData => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, error)),
2009 std::io::ErrorKind::InvalidInput => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, error)),
2010 std::io::ErrorKind::NotConnected => Err(std::io::Error::new(std::io::ErrorKind::NotConnected, error)),
2011 std::io::ErrorKind::NotFound => Err(std::io::Error::new(std::io::ErrorKind::NotFound, error)),
2012 std::io::ErrorKind::OutOfMemory => Err(std::io::Error::new(std::io::ErrorKind::OutOfMemory, error)),
2013 std::io::ErrorKind::PermissionDenied => Err(std::io::Error::new(std::io::ErrorKind::PermissionDenied, error)),
2014 std::io::ErrorKind::TimedOut => Err(std::io::Error::new(std::io::ErrorKind::TimedOut, error)),
2015 std::io::ErrorKind::UnexpectedEof => Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, error)),
2016 std::io::ErrorKind::Unsupported => Err(std::io::Error::new(std::io::ErrorKind::Unsupported, error)),
2017 std::io::ErrorKind::WouldBlock => Err(std::io::Error::new(std::io::ErrorKind::WouldBlock, error)),
2018 std::io::ErrorKind::WriteZero => Err(std::io::Error::new(std::io::ErrorKind::WriteZero, error)),
2019 _ => Err(std::io::Error::new(std::io::ErrorKind::Other, error)),
2020 }
2021 }
2022 }
2023 }
2024
2025 },
2026 Err(error) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, error))
2027 }
2028 }
2029
2030 Ok(timezone)
2031}
2032
2033#[cfg(test)]
2034mod test {
2035 use super::*;
2036
2037 #[test]
2038 pub fn test_os_type() {
2039 let typ = os_type().unwrap();
2040 assert!(typ.len() > 0);
2041 println!("os_type(): {}", typ);
2042 }
2043
2044 #[test]
2045 pub fn test_os_release() {
2046 let release = os_release().unwrap();
2047 assert!(release.len() > 0);
2048 println!("os_release(): {}", release);
2049 }
2050
2051 #[test]
2052 pub fn test_cpu_num() {
2053 let num = cpu_num().unwrap();
2054 assert!(num > 0);
2055 println!("cpu_num(): {}", num);
2056 }
2057
2058 #[test]
2059 #[cfg(not(all(target_vendor = "apple", target_arch = "aarch64")))]
2060 pub fn test_cpu_speed() {
2061 let speed = cpu_speed().unwrap();
2062 assert!(speed > 0);
2063 println!("cpu_speed(): {}", speed);
2064 }
2065
2066 #[test]
2067 pub fn test_loadavg() {
2068 let load = loadavg().unwrap();
2069 println!("loadavg(): {:?}", load);
2070 }
2071
2072 #[test]
2073 pub fn test_proc_total() {
2074 let procs = proc_total().unwrap();
2075 assert!(procs > 0);
2076 println!("proc_total(): {}", procs);
2077 }
2078
2079 #[test]
2080 pub fn test_mem_info() {
2081 let mem = mem_info().unwrap();
2082 assert!(mem.total > 0);
2083 println!("mem_info(): {:?}", mem);
2084 }
2085
2086 #[test]
2087 #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
2088 pub fn test_disk_info() {
2089 let info = disk_info().unwrap();
2090 println!("disk_info(): {:?}", info);
2091 }
2092
2093 #[test]
2094 pub fn test_hostname() {
2095 let host = hostname().unwrap();
2096 assert!(host.len() > 0);
2097 println!("hostname(): {}", host);
2098 }
2099
2100 #[cfg(target_os = "windows")]
2101 #[test]
2102 pub fn test_get_graphics_info(){
2103 let graphics = get_graphics_info();
2104 println!("Graphics info: {:?}", graphics);
2105 }
2106
2107 #[cfg(any(target_os = "linux", target_os = "windows"))]
2108 #[test]
2109 pub fn test_check_computer_type() {
2110 let pc_type = check_computer_type();
2111 println!("computer type: {}", pc_type.unwrap());
2112 }
2113
2114 #[test]
2115 #[cfg(not(windows))]
2116 pub fn test_boottime() {
2117 let bt = boottime().unwrap();
2118 println!("boottime(): {} {}", bt.tv_sec, bt.tv_usec);
2119 assert!(bt.tv_sec > 0 || bt.tv_usec > 0);
2120 }
2121
2122 #[test]
2123 #[cfg(target_os = "linux")]
2124 pub fn test_linux_os_release() {
2125 let os_release = linux_os_release().unwrap();
2126 println!("linux_os_release(): {:?}", os_release.name)
2127 }
2128
2129 #[cfg(any(target_os = "windows", target_os = "linux"))]
2130 #[test]
2131 pub fn test_get_public_ipv4_address(){
2132 assert_ne!(String::new(), get_public_ipv4_address().unwrap())
2133 }
2134
2135 #[cfg(target_os = "windows")]
2136 #[test]
2137 pub fn test_is_program_installed_search_hard(){
2138 let hard_search_options = HardSearchOptions {
2139 case_sensitive: false, search_hardness: 5 };
2142
2143 assert_eq!(true, is_program_installed_search_hard("miCroSoft eDgE", hard_search_options).unwrap());
2144
2145 let hard_search_options_2 = HardSearchOptions {
2146 case_sensitive: true,
2147 search_hardness: 5
2148 };
2149
2150 assert_eq!(true, is_program_installed_search_hard("Microsoft Edge", hard_search_options_2).unwrap())
2151 }
2152
2153 #[cfg(target_os = "windows")]
2154 #[test]
2155 pub fn test_get_ram_infos() {
2156 let ram_infos = get_ram_infos().unwrap();
2157 assert!(ram_infos.len() > 0);
2158 println!("get_ram_infos(): {:#?}", ram_infos);
2159 }
2160
2161 #[cfg(any(target_os = "windows", target_os = "linux"))]
2162 #[test]
2163 pub fn test_get_system_env_var(){
2164 let path_env_var = get_system_env_var("PATH");
2165
2166 assert_eq!(true, path_env_var.is_ok());
2167 }
2168
2169 #[cfg(target_os = "windows")]
2170 #[test]
2171 pub fn test_get_user_env_var(){
2172 let path_env_var = get_user_env_var("PATH");
2173
2174 assert_eq!(true, path_env_var.is_ok());
2175 }
2176
2177 #[cfg(any(target_os = "windows", target_os = "linux"))]
2178 #[test]
2179 pub fn test_get_timezone(){
2180 let timezone = get_timezone();
2181
2182 assert_eq!(true, timezone.is_ok())
2183 }
2184}