@@ -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
224225impl < ' 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
0 commit comments