50 std::unique_ptr<StoredMessage> next()
override ;
66GStore::FileIterator::FileIterator(
FileStore & store ,
const G::Path & dir ,
bool lock ) :
71 m_iter.
readType( dir ,
".envelope" ) ;
74GStore::FileIterator::~FileIterator()
77std::unique_ptr<GStore::StoredMessage> GStore::FileIterator::next()
79 while( m_iter.more() )
82 if( !message_id.valid() )
85 auto message_ptr = std::make_unique<StoredFile>( m_store , message_id ) ;
87 if( m_lock && !message_ptr->lock() )
89 G_WARNING(
"GStore::MessageStore: cannot lock file: \"" << m_iter.filePath().basename() <<
"\"" ) ;
95 ok = message_ptr->readEnvelope( reason ) && message_ptr->openContent( reason ) ;
98 G_WARNING(
"GStore::MessageStore: ignoring \"" << m_iter.filePath() <<
"\": " << reason ) ;
112 m_delivery_dir(delivery_dir) ,
126 return m_delivery_dir.
empty() ? m_dir : m_delivery_dir ;
131 return "X-MailRelay-" ;
137 if( generation == -5 )
139 else if( generation == -4 )
141 else if( generation == -3 )
143 else if( generation == -2 )
145 else if( generation == -1 )
154 format_in == format(0) ||
155 format_in == format(-1) ||
156 format_in == format(-2) ||
157 format_in == format(-3) ||
158 format_in == format(-4) ||
159 format_in == format(-5) ;
162void GStore::FileStore::checkPath(
const G::Path & directory_path )
171 error = dir_test.usable() ;
182 FileWriter claim_writer ;
183 ok = dir_test.writeable( tmp_filename ) ;
189 G_WARNING(
"GStore::MessageStore: " << format(
txt(
"directory not writable: \"%1%\"")) % directory_path ) ;
193std::string GStore::FileStore::location(
const MessageId &
id )
const
195 return envelopePath(
id).str() ;
200 auto stream_ptr = std::make_unique<std::ofstream>() ;
201 FileOp::openOut( *stream_ptr , path ) ;
212 if( state == State::New )
213 return m_dir /
id.
str().append(
".envelope.new") ;
214 else if( state == State::Locked )
215 return m_dir /
id.str().append(
".envelope.busy") ;
216 else if( state == State::Bad )
217 return m_dir /
id.str().append(
".envelope.bad") ;
219 return m_dir /
id.str().append(
".envelope") ;
227 return newId( m_seq ) ;
233 std::ostringstream ss ;
234 ss <<
"emailrelay." <<
G::Process::Id().str() <<
"." << timestamp <<
"." << seq ;
238bool GStore::FileStore::empty()
const
241 DirectoryReader claim_reader ;
242 list.
readType( m_dir ,
".envelope" , 1U ) ;
243 const bool no_more = !list.
more() ;
247std::vector<GStore::MessageId> GStore::FileStore::ids()
251 DirectoryReader claim_reader ;
252 list.
readType( m_dir ,
".envelope" ) ;
254 std::vector<GStore::MessageId> result ;
260std::vector<GStore::MessageId> GStore::FileStore::failures()
264 DirectoryReader claim_reader ;
265 list.
readType( m_dir ,
".envelope.bad" ) ;
267 std::vector<GStore::MessageId> result ;
273void GStore::FileStore::unfailAll()
277 DirectoryReader claim_reader ;
278 list.
readType( m_dir ,
".envelope.bad" ) ;
282 FileWriter claim_writer ;
287std::unique_ptr<GStore::MessageStore::Iterator> GStore::FileStore::iterator(
bool lock )
289 return std::make_unique<FileIterator>( *
this , m_dir , lock ) ;
292std::unique_ptr<GStore::StoredMessage> GStore::FileStore::get(
const MessageId &
id )
294 auto message = std::make_unique<StoredFile>( *
this ,
id ) ;
295 if( !message->lock() )
296 throw GetError(
id.str().append(
": cannot lock the envelope file") ) ;
299 if( !message->readEnvelope( reason ) )
300 throw GetError(
id.str().append(
": cannot read the envelope: ").append(reason) ) ;
302 if( !message->openContent( reason ) )
303 throw GetError(
id.str().append(
": cannot read the content: ").append(reason) ) ;
311 std::ifstream & envelope_stream = stream_p ? *stream_p : strm ;
312 if( !FileOp::openIn( envelope_stream , envelope_path ) )
320std::unique_ptr<GStore::NewMessage> GStore::FileStore::newMessage(
const std::string & from ,
323 return std::make_unique<NewFile>( *
this , from , smtp_info , from_auth_out , m_config.max_size ) ;
326void GStore::FileStore::updated()
328 G_DEBUG(
"GStore::FileStore::updated" ) ;
329 m_update_signal.emit() ;
334 return m_update_signal ;
339 return m_rescan_signal ;
342void GStore::FileStore::rescan()
344 messageStoreRescanSignal().emit() ;
367 G::Process::Umask(
G::Process::Umask::Mode::Tighter)
376int & GStore::FileStore::FileOp::errno_() noexcept
382bool GStore::FileStore::FileOp::rename(
const G::Path & src ,
const G::Path & dst )
384 FileWriter claim_writer ;
391bool GStore::FileStore::FileOp::renameOnto(
const G::Path & src ,
const G::Path & dst )
393 FileWriter claim_writer ;
400bool GStore::FileStore::FileOp::remove(
const G::Path & path )
noexcept
404 FileWriter claim_writer ;
416bool GStore::FileStore::FileOp::exists(
const G::Path & path )
418 FileReader claim_reader ;
425int GStore::FileStore::FileOp::fdopen(
const G::Path & path )
427 FileReader claim_reader ;
434std::ifstream & GStore::FileStore::FileOp::openIn( std::ifstream & stream ,
const G::Path & path )
436 FileReader claim_reader ;
443std::ofstream & GStore::FileStore::FileOp::openOut( std::ofstream & stream ,
const G::Path & path )
445 FileWriter claim_writer ;
452std::ofstream & GStore::FileStore::FileOp::openAppend( std::ofstream & stream ,
const G::Path & path )
454 FileWriter claim_writer ;
461bool GStore::FileStore::FileOp::hardlink(
const G::Path & src ,
const G::Path & dst )
463 FileWriter claim_writer ;
465 bool copied = false ;
475 if( !dir_stat.error && !dir_stat.is_link && dir_stat.inherit )
479 return linked || copied ;
482bool GStore::FileStore::FileOp::copy(
const G::Path & src ,
const G::Path & dst ,
bool use_hardlink )
485 return hardlink( src , dst ) ;
487 return copy( src , dst ) ;
490bool GStore::FileStore::FileOp::copy(
const G::Path & src ,
const G::Path & dst )
492 FileWriter claim_writer ;
499bool GStore::FileStore::FileOp::mkdir(
const G::Path & dir )
501 FileWriter claim_root ;
510 FileReader claim_reader ;
Used by GStore::FileStore, GStore::NewFile and GStore::StoredFile to claim read permissions for readi...
DirectoryReader()
Default constructor.
~DirectoryReader()
Destructor. Switches identity back.
A structure containing the contents of an envelope file, with support for file reading,...
static void read(std::istream &, Envelope &)
Reads an envelope from a stream.
A GStore::MessageStore::Iterator for GStore::FileStore.
FileReader()
Default constructor.
~FileReader()
Destructor. Switches identity back.
A concrete implementation of the MessageStore interface dealing in paired flat files.
G::Path deliveryDir() const
Returns the base directory for local delivery.
static std::string x()
Returns the prefix for envelope header lines.
FileStore(const G::Path &spool_dir, const G::Path &delivery_dir, const Config &config)
Constructor.
G::Path directory() const
Returns the spool directory path, as passed in to the constructor.
MessageId newId()
Hands out a new unique message id.
G::Path envelopePath(const MessageId &id, State=State::Normal) const
Returns the path for an envelope file.
static std::unique_ptr< std::ofstream > stream(const G::Path &path)
Opens an output stream to a message file using the appropriate effective userid and umask.
static Envelope readEnvelope(const G::Path &, std::ifstream *=nullptr)
Used by FileStore sibling classes to read an envelope file.
static std::string format(int generation=0)
Returns an identifier for the storage format implemented by this class, or some older generation of i...
G::Path contentPath(const MessageId &id) const
Returns the path for a content file.
static bool knownFormat(const std::string &format)
Returns true if the storage format string is recognised and supported for reading.
Used by GStore::FileStore, GStore::NewFile and GStore::StoredFile to claim write permissions.
FileWriter()
Default constructor.
~FileWriter()
Destructor. Switches identity back.
A somewhat opaque identifer for a GStore::MessageStore message id.
A iterator similar to G::DirectoryIterator but doing all file i/o in one go and providing a sorted re...
Path filePath() const
Returns the current path.
bool more()
Returns true if more and advances by one.
std::size_t readType(const Path &dir, std::string_view suffix, unsigned int limit=0U)
An initialiser that is to be used after default construction.
An encapsulation of a file system directory that works with G::DirectoryIterator.
static std::string tmp()
A convenience function for constructing a filename for writeable().
An overload discriminator for G::File::open().
static void open(std::ofstream &, const Path &)
Calls open() on the given output file stream.
static bool isDirectory(const Path &path, std::nothrow_t)
Returns true if the path exists() and is a directory.
static bool rename(const Path &from, const Path &to, std::nothrow_t) noexcept
Renames the file.
static bool remove(const Path &path, std::nothrow_t) noexcept
Deletes the file or directory. Returns false on error.
static Stat stat(const Path &path, bool symlink_nofollow=false)
Returns a file status structure.
static bool exists(const Path &file)
Returns true if the file (directory, device etc.) exists.
static bool renameOnto(const Path &from, const Path &to, std::nothrow_t) noexcept
Renames the file, deleting 'to' first if necessary.
static bool copy(const Path &from, const Path &to, std::nothrow_t)
Copies a file. Returns false on error.
static bool mkdir(const Path &dir, std::nothrow_t)
Creates a directory.
static bool hardlink(const Path &src, const Path &dst, std::nothrow_t)
Creates a hard link.
static void chgrp(const Path &file, const std::string &group)
Sets the file group ownership. Throws on error.
A Path object represents a file system path.
std::string basename() const
Returns the rightmost part of the path, ignoring "." parts.
Path withoutExtension() const
Returns a path without the basename extension, if any.
Path dirname() const
Returns the path without the rightmost part, ignoring "." parts.
bool simple() const
Returns true if the path has a single component (ignoring "." parts), ie.
Path withExtension(const std::string &ext) const
Returns the path with the new basename extension.
std::string str() const
Returns the path string.
bool empty() const noexcept
Returns true if the path is empty.
static std::string strerror(int errno_)
Translates an 'errno' value into a meaningful diagnostic string.
static int errno_(const SignalSafe &=G::SignalSafe()) noexcept
Returns the process's current 'errno' value.
static SystemTime now()
Factory function for the current time.
std::time_t s() const noexcept
Returns the number of seconds since the start of the epoch.
const char * txt(const char *p) noexcept
A briefer alternative to G::gettext().
Configuration structure for GStore::FileStore.
A base class for GStore::MessageStore iterators.
Information on the SMTP options used when submitted.
A slot holder, with connect() and emit() methods.