serde_json = "1"
futures = "0.3"
base64 = "0.21"
-async_zip = { version = "0.0.12", default-features = false, features = ["deflate"] }
+async_zip = { version = "0.0.12", default-features = false, features = ["deflate", "chrono"] }
headers = "0.3"
mime_guess = "2.0"
if-addrs = "0.10.1"
use crate::streamer::Streamer;
-use crate::utils::{decode_uri, encode_uri, get_file_name, glob, try_get_file_name};
+use crate::utils::{
+ decode_uri, encode_uri, get_file_mtime_and_mode, get_file_name, glob, try_get_file_name,
+};
use crate::Args;
use anyhow::{anyhow, Result};
use walkdir::WalkDir;
use xml::escape::escape_str_pcdata;
use async_zip::write::ZipFileWriter;
-use async_zip::{Compression, ZipEntryBuilder};
+use async_zip::{Compression, ZipDateTime, ZipEntryBuilder};
use chrono::{LocalResult, TimeZone, Utc};
use futures::TryStreamExt;
use headers::{
Some(v) => v,
None => continue,
};
- let builder =
- ZipEntryBuilder::new(filename.into(), Compression::Deflate).unix_permissions(0o644);
+ let (datetime, mode) = get_file_mtime_and_mode(&zip_path).await?;
+ let builder = ZipEntryBuilder::new(filename.into(), Compression::Deflate)
+ .unix_permissions(mode)
+ .last_modification_date(ZipDateTime::from_chrono(&datetime));
let mut file = File::open(&zip_path).await?;
let mut file_writer = writer.write_entry_stream(builder).await?;
io::copy(&mut file, &mut file_writer).await?;
use anyhow::{anyhow, Context, Result};
+use chrono::{DateTime, Utc};
use std::{
borrow::Cow,
path::Path,
.unwrap_or_default()
}
+#[cfg(unix)]
+pub async fn get_file_mtime_and_mode(path: &Path) -> Result<(DateTime<Utc>, u16)> {
+ use std::os::unix::prelude::MetadataExt;
+ let meta = tokio::fs::metadata(path).await?;
+ let datetime: DateTime<Utc> = meta.modified()?.into();
+ Ok((datetime, meta.mode() as u16))
+}
+
+#[cfg(not(unix))]
+pub async fn get_file_mtime_and_mode(path: &Path) -> Result<(DateTime<Utc>, u16)> {
+ let meta = tokio::fs::metadata(&path).await?;
+ let datetime: DateTime<Utc> = meta.modified()?.into();
+ Ok((datetime, 0o644))
+}
+
pub fn try_get_file_name(path: &Path) -> Result<&str> {
path.file_name()
.and_then(|v| v.to_str())