Advertisement
Superloup10

Untitled

Jan 26th, 2024
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.20 KB | None | 0 0
  1. use std::{fs, io};
  2. use std::ffi::{c_char, c_int, CStr};
  3. use std::path::Path;
  4.  
  5. pub const OK: c_int = 0;
  6. pub const FILE_OPEN_ERROR: c_int = 1;
  7. pub const CREATE_FILE_ERROR: c_int = 2;
  8. pub const SET_PERMISSION_ERROR: c_int = 3;
  9. pub const ZIP_ERROR: c_int = 4;
  10. pub const INVALID_STRING_CONVERSION_ERROR: c_int = 5;
  11.  
  12. #[no_mangle]
  13. pub extern "C" fn unzip(in_path: *mut c_char, out_path: *mut c_char) -> c_int {
  14. match unzip_impl(in_path, out_path) {
  15. Ok(_) => OK,
  16. Err(code) => code
  17. }
  18. }
  19.  
  20. type ResultExitCode<T> = Result<T, c_int>;
  21.  
  22. fn unzip_impl(in_path: *mut c_char, out_path: *mut c_char) -> ResultExitCode<()> {
  23. let in_path = c_chars_to_path(in_path)?;
  24. let out_path = c_chars_to_path(out_path)?;
  25. let file = fs::File::open(in_path).map_err(|_| FILE_OPEN_ERROR)?;
  26.  
  27. let mut archive = zip::ZipArchive::new(file).map_err(|_| ZIP_ERROR)?;
  28.  
  29. for i in 0..archive.len() {
  30. let mut file = archive.by_index(i).map_err(|_| ZIP_ERROR)?;
  31. let out_path = match file.enclosed_name() {
  32. Some(path) => out_path.join(path).to_owned(),
  33. None => continue
  34. };
  35.  
  36. if (*file.name()).ends_with('/') {
  37. fs::create_dir_all(&out_path).map_err(|_| CREATE_FILE_ERROR)?;
  38. } else {
  39. if let Some(p) = out_path.parent() {
  40. if !p.exists() {
  41. fs::create_dir_all(p).map_err(|_| CREATE_FILE_ERROR)?;
  42. }
  43. }
  44. let mut out_file = fs::File::create(&out_path).map_err(|_| CREATE_FILE_ERROR)?;
  45. io::copy(&mut file, &mut out_file).map_err(|_| CREATE_FILE_ERROR)?;
  46. }
  47.  
  48. #[cfg(unix)]
  49. {
  50. use std::os::unix::fs::PermissionsExt;
  51.  
  52. if let Some(mode) = file.unix_mode() {
  53. let permissions = fs::Permissions::from_mode(mode);
  54. fs::set_permissions(&out_path, permissions).map_err(|_| SET_PERMISSION_ERROR)?;
  55. }
  56. }
  57. }
  58. Ok(())
  59. }
  60.  
  61. fn c_chars_to_path<'a>(chars: *mut c_char) -> ResultExitCode<&'a Path> {
  62. let c_str = unsafe { CStr::from_ptr(chars) };
  63. let str = c_str.to_str().map_err(|_| INVALID_STRING_CONVERSION_ERROR)?;
  64. Ok(Path::new(str))
  65. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement