Files
Jungfraujoch/writer/FileWriter.h
T
leonarski_fandClaude Opus 4.8 8858951419 rugnux: allow absolute output paths for offline processing
The FilePrefix/CheckPath guard forbids absolute paths and '..' traversal so a
remote client cannot make the broker/writer write outside their run directory.
Offline processing (rugnux -o, and the viewer writing next to the input file)
supplies its own trusted local path, so that guard should not apply to it.

Add a trusted opt-in that leaves the broker/writer path untouched:
- DatasetSettings/DiffractionExperiment::FilePrefixTrusted() sets the prefix
  without CheckPath (FilePrefix() = CheckPath + FilePrefixTrusted).
- FileWriter gains a trusted_path ctor flag that skips its own CheckPath.
- Rugnux uses both. Broker/writer never set them, so their behaviour is
  identical; this only widens what the offline CLI/viewer may write.

Previously 'rugnux -o /abs/path' threw ('Path cannot start with slash') while
building the _process.h5; the .mtz/.cif already bypassed the guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 09:39:46 +02:00

56 lines
2.4 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <numeric>
#include "HDF5DataFile.h"
#include "../common/JFJochMessages.h"
#include "../common/ZMQWrappers.h"
#include "HDF5NXmx.h"
#include "CBFWriter.h"
#include <unordered_set>
class FileWriter {
FileWriterFormat format = FileWriterFormat::NXmxLegacy;
StartMessage start_message;
std::unique_ptr<NXmx> master_file;
std::vector<std::unique_ptr<HDF5DataFile> > files;
std::vector<HDF5DataFileStatistics> stats;
std::unique_ptr<ZMQSocket> finalized_file_socket;
std::unique_ptr<CBFWriter> cbf_writer;
std::unordered_set<uint64_t> closed_files;
constexpr static uint64_t close_file_lag_images = 1000;
constexpr static uint64_t default_images_per_file = 1000;
void CreateHDF5MasterFile(const StartMessage& msg);
void CheckOutputFilesAvailable() const;
void AddStats(const std::optional<HDF5DataFileStatistics>& s);
void CloseFile(uint64_t file_number);
void CloseOldFiles(uint64_t current_image_number);
public:
// check_overwrite_at_start: fail the constructor if an output file already
// exists and overwrite is off. Only safe for transports with a back-channel
// (direct HDF5 pusher, TCP) that can report the failure to the broker before
// acquisition arms. The ZeroMQ pusher is fire-and-forget with no back-channel,
// so it must pass false: the writer then falls back to writing .tmp files and
// failing at the final rename (see docs/JFJOCH_WRITER.md).
// trusted_path: the caller supplied the output prefix itself (offline rugnux / the viewer's
// processing), so the multi-user CheckPath guard - which forbids absolute paths and '..' traversal
// for remotely-supplied prefixes - is skipped, allowing an absolute output path. The broker/writer
// never set it, so their behaviour is unchanged.
explicit FileWriter(const StartMessage &request, bool check_overwrite_at_start = true,
bool trusted_path = false);
void Write(const DataMessage& msg);
void WriteTIFF(const DataMessage& msg);
void WriteHDF5(const DataMessage& msg);
void WriteHDF5(const CompressedImage& msg);
void WriteHDF5(const EndMessage& msg);
std::vector<HDF5DataFileStatistics> Finalize();
void SetupFinalizedFileSocket(const std::string &addr);
std::optional<std::string> GetZMQAddr();
};