Skip to content

Commit 1017b01

Browse files
committed
stub ttbc_get_abspath and ttbc_input_get_mtime for reproducibility
1 parent 5415276 commit 1017b01

2 files changed

Lines changed: 69 additions & 2 deletions

File tree

crates/bridge_core/src/lib.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ pub struct CoreBridgeLauncher<'a> {
219219
hooks: &'a mut dyn DriverHooks,
220220
status: &'a mut dyn StatusBackend,
221221
security: SecuritySettings,
222+
filesystem_emulation_settings: FsEmulationSettings,
222223
}
223224

224225
impl<'a> CoreBridgeLauncher<'a> {
@@ -242,8 +243,18 @@ impl<'a> CoreBridgeLauncher<'a> {
242243
hooks,
243244
status,
244245
security,
246+
filesystem_emulation_settings: FsEmulationSettings::default(),
245247
}
246248
}
249+
250+
/// Configure filesystem emulation settings. These default to an "accurate"
251+
/// view of the provided IO subsystem, but can be restricted to provide
252+
/// reproducible file modified timestamps or hide absolute paths.
253+
pub fn with_fs_emulation_settings(&mut self, settings: FsEmulationSettings) -> &mut Self {
254+
self.filesystem_emulation_settings = settings;
255+
self
256+
}
257+
247258
/// Invoke a function to launch a bridged FFI engine with a global mutex
248259
/// held.
249260
///
@@ -262,7 +273,12 @@ impl<'a> CoreBridgeLauncher<'a> {
262273
F: FnOnce(&mut CoreBridgeState<'_>) -> Result<T>,
263274
{
264275
let _guard = ENGINE_LOCK.lock().unwrap();
265-
let mut state = CoreBridgeState::new(self.security.clone(), self.hooks, self.status);
276+
let mut state = CoreBridgeState::new(
277+
self.security.clone(),
278+
self.hooks,
279+
self.status,
280+
self.filesystem_emulation_settings.clone(),
281+
);
266282
let result = callback(&mut state);
267283

268284
if let Err(ref e) = result {
@@ -285,6 +301,9 @@ pub struct CoreBridgeState<'a> {
285301
/// The security settings for this invocation
286302
security: SecuritySettings,
287303

304+
/// The filesystem emulation settings for this invocation.
305+
fs_emulation_settings: FsEmulationSettings,
306+
288307
/// The driver hooks associated with this engine invocation.
289308
hooks: &'a mut dyn DriverHooks,
290309

@@ -312,6 +331,7 @@ impl<'a> CoreBridgeState<'a> {
312331
security: SecuritySettings,
313332
hooks: &'a mut dyn DriverHooks,
314333
status: &'a mut dyn StatusBackend,
334+
fs_emulation_settings: FsEmulationSettings,
315335
) -> CoreBridgeState<'a> {
316336
CoreBridgeState {
317337
security,
@@ -320,6 +340,7 @@ impl<'a> CoreBridgeState<'a> {
320340
output_handles: Vec::new(),
321341
input_handles: Vec::new(),
322342
latest_input_path: None,
343+
fs_emulation_settings,
323344
}
324345
}
325346

@@ -592,6 +613,9 @@ impl<'a> CoreBridgeState<'a> {
592613
}
593614

594615
fn input_get_mtime(&mut self, handle: *mut InputHandle) -> i64 {
616+
if let Some(mtime) = self.fs_emulation_settings.mtime_override {
617+
return mtime;
618+
}
595619
let rhandle: &mut InputHandle = unsafe { &mut *handle };
596620

597621
let maybe_time = match rhandle.get_unix_mtime() {
@@ -773,6 +797,32 @@ impl Default for SecuritySettings {
773797
}
774798
}
775799

800+
/// A type that stores configuration knobs related to filesystem emulation.
801+
/// These options are not security-critical, but are relevant for
802+
/// reproducible document builds. We default to an "accurate" view of the
803+
/// underlying IO subsystem and have options that stub the respective IO
804+
/// functions with fake / stable values.
805+
#[derive(Clone, Debug)]
806+
pub struct FsEmulationSettings {
807+
/// While absolute paths are useful (for SyncTeX and external tools that
808+
/// resolve paths to TeX sources), we can disable them for reproducibility.
809+
pub expose_absolute_paths: bool,
810+
811+
/// Ditto for file modification timestamps. In reproducible mode, we return
812+
/// the configured build time (i.e. `SOURCE_DATE_EPOCH`) instead of the
813+
/// modification timestamp reported by the IO subsystem.
814+
pub mtime_override: Option<i64>,
815+
}
816+
817+
impl Default for FsEmulationSettings {
818+
fn default() -> Self {
819+
Self {
820+
expose_absolute_paths: true,
821+
mtime_override: None,
822+
}
823+
}
824+
}
825+
776826
// The entry points.
777827

778828
/// Issue a warning.
@@ -968,6 +1018,9 @@ pub unsafe extern "C" fn ttbc_get_last_input_abspath(
9681018
buffer: *mut u8,
9691019
len: libc::size_t,
9701020
) -> libc::ssize_t {
1021+
if !es.fs_emulation_settings.expose_absolute_paths {
1022+
return 0;
1023+
}
9711024
match es.latest_input_path {
9721025
None => 0,
9731026

src/driver.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ use std::{
2828
str::FromStr,
2929
time::SystemTime,
3030
};
31-
use tectonic_bridge_core::{CoreBridgeLauncher, DriverHooks, SecuritySettings, SystemRequestError};
31+
use tectonic_bridge_core::{
32+
CoreBridgeLauncher, DriverHooks, FsEmulationSettings, SecuritySettings, SystemRequestError,
33+
};
3234
use tectonic_bundles::Bundle;
3335
use tectonic_engine_spx2html::AssetSpecification;
3436
use tectonic_io_base::{
@@ -1829,6 +1831,18 @@ impl ProcessingSession {
18291831

18301832
let mut launcher =
18311833
CoreBridgeLauncher::new_with_security(&mut self.bs, status, self.security.clone());
1834+
launcher.with_fs_emulation_settings(FsEmulationSettings {
1835+
// We enable absolute paths if synctex was requested or other
1836+
// external tools are involved.
1837+
expose_absolute_paths: self.synctex_enabled || self.security.allow_shell_escape(),
1838+
// Note: We always return "dummy" modification times. Should
1839+
// there be a configuration knob to return the real mtime?
1840+
mtime_override: self
1841+
.build_date
1842+
.duration_since(SystemTime::UNIX_EPOCH)
1843+
.map(|x| x.as_secs() as i64)
1844+
.ok(),
1845+
});
18321846

18331847
TexEngine::default()
18341848
.halt_on_error_mode(!self.unstables.continue_on_errors)

0 commit comments

Comments
 (0)