37 struct DirectoryReader ;
72 m_allow_delete(allow_delete)
74 checkPath( path , by_name , allow_delete ) ;
84 return m_allow_delete ;
92 void GPop::Store::checkPath(
G::Path dir_path ,
bool by_name ,
bool allow_delete )
96 if( !valid(dir_path,
false) )
97 throw InvalidDirectory() ;
111 if( !valid(iter.
filePath(),allow_delete) )
119 G_WARNING(
"GPop::Store: no sub-directories for pop-by-name found in \"" << dir_path <<
"\": "
120 <<
"create one sub-directory for each authorised pop account" ) ;
123 else if( !valid(dir_path,allow_delete) )
125 throw InvalidDirectory() ;
129 bool GPop::Store::valid(
G::Path dir_path ,
bool allow_delete )
136 FileDeleter claim_deleter ;
137 ok = dir_test.valid() && dir_test.writeable(tmp) ;
141 FileReader claim_reader ;
142 ok = dir_test.valid() ;
146 const char * op = allow_delete ?
"writing" :
"reading" ;
147 G_WARNING(
"GPop::Store: directory not valid for " << op <<
": \"" << dir_path <<
"\"" ) ;
154 GPop::StoreLock::File::File(
const G::Path & content_path ) :
155 name(content_path.basename()) ,
156 size(toSize(
G::File::sizeString(content_path.str())))
160 GPop::StoreLock::File::File(
const std::string & content_name ,
const std::string & size_string ) :
162 size(toSize(size_string))
166 bool GPop::StoreLock::File::operator<(
const File & rhs )
const
168 return name < rhs.name ;
190 m_dir = m_store->dir() ;
191 if( m_store->byName() )
192 m_dir.pathAppend( user ) ;
198 iter.
readType( m_dir ,
".envelope" ) ;
202 m_initial.insert( file ) ;
209 size_t limit = m_initial.size() * 1000U ;
210 for(
size_t i = 0U ; i < limit ; i++ )
212 std::ostringstream ss ;
213 ss <<
"dummy." << i <<
".content" ;
214 m_initial.insert( File(ss.str()) ) ;
219 m_current = m_initial ;
226 return m_store != NULL && ! m_user.empty() ;
236 return m_current.size() ;
243 for( Set::const_iterator p = m_current.begin() ; p != m_current.end() ; ++p )
251 return id >= 1 && id <= static_cast<int>(m_initial.size()) ;
254 GPop::StoreLock::Set::iterator GPop::StoreLock::find(
int id )
257 Set::iterator initial_p = m_initial.begin() ;
258 for(
int i = 1 ; i <
id && initial_p != m_initial.end() ; i++ , ++initial_p ) ;
262 GPop::StoreLock::Set::const_iterator GPop::StoreLock::find(
int id )
const
265 Set::const_iterator initial_p = m_initial.begin() ;
266 for(
int i = 1 ; i <
id && initial_p != m_initial.end() ; i++ , ++initial_p ) ;
270 GPop::StoreLock::Set::iterator GPop::StoreLock::find(
const std::string & name )
272 Set::iterator current_p = m_current.begin() ;
273 for( ; current_p != m_current.end() ; ++current_p )
275 if( (*current_p).name == name )
284 return (*find(
id)).size ;
292 for( Set::const_iterator p = m_current.begin() ; p != m_current.end() ; ++p , i++ )
294 if(
id == -1 ||
id == i )
295 list.push_back(
Entry(i,(*p).size,(*p).name) ) ;
305 G_DEBUG(
"GPop::StoreLock::get: " <<
id <<
": " << path(
id) ) ;
307 std::auto_ptr<std::ifstream> file ;
310 file <<=
new std::ifstream( path(
id).str().c_str() , std::ios_base::binary | std::ios_base::in ) ;
314 throw CannotRead( path(
id).str() ) ;
316 return std::auto_ptr<std::istream>( file.release() ) ;
324 Set::iterator initial_p = find(
id ) ;
325 Set::iterator current_p = find( (*initial_p).name ) ;
326 if( current_p != m_current.end() )
328 m_deleted.insert( *initial_p ) ;
329 m_current.erase( current_p ) ;
338 Store * store = m_store ;
345 void GPop::StoreLock::doCommit(
Store & store )
const
348 for( Set::const_iterator p = m_deleted.begin() ; p != m_deleted.end() ; ++p )
352 deleteFile( envelopePath(*p) , all_ok ) ;
353 if( unlinked(store,*p) )
354 deleteFile( contentPath(*p) , all_ok ) ;
358 G_DEBUG(
"StoreLock::doCommit: not deleting \"" << (*p).name <<
"\"" ) ;
362 throw CannotDelete() ;
365 void GPop::StoreLock::deleteFile(
const G::Path & path ,
bool & all_ok )
const
369 FileDeleter claim_deleter ;
372 all_ok = ok && all_ok ;
374 G_ERROR(
"StoreLock::remove: failed to delete " << path ) ;
380 Set::const_iterator p = find(
id) ;
384 G::Path GPop::StoreLock::path(
int id )
const
387 Set::const_iterator p = find(
id) ;
388 const File & file = (*p) ;
389 return contentPath( file ) ;
392 G::Path GPop::StoreLock::path(
const std::string & filename ,
bool fallback )
const
405 std::string GPop::StoreLock::envelopeName(
const std::string & content_name )
const
407 std::string filename = content_name ;
412 std::string GPop::StoreLock::contentName(
const std::string & envelope_name )
const
414 std::string filename = envelope_name ;
419 G::Path GPop::StoreLock::contentPath(
const std::string & envelope_name )
const
421 const bool try_parent_directory = true ;
422 return path( contentName(envelope_name) , try_parent_directory ) ;
425 G::Path GPop::StoreLock::contentPath(
const File & file )
const
427 const bool try_parent_directory = true ;
428 return path( file.name , try_parent_directory ) ;
431 G::Path GPop::StoreLock::envelopePath(
const File & file )
const
433 const bool try_parent_directory = false ;
434 return path( envelopeName(file.name) , try_parent_directory ) ;
441 m_current = m_initial ;
444 bool GPop::StoreLock::unlinked(
Store & store ,
const File & file )
const
448 G_DEBUG(
"StoreLock::unlinked: unlinked since not pop-by-name: " << file.name ) ;
452 G::Path normal_content_path = m_dir ; normal_content_path.
pathAppend( file.name ) ;
455 G_DEBUG(
"StoreLock::unlinked: unlinked since in its own directory: " << normal_content_path ) ;
464 DirectoryReader claim_reader ;
469 if( ! iter.
isDir() )
continue ;
470 G_DEBUG(
"Store::unlinked: checking sub-directory: " << iter.
fileName() ) ;
474 G_DEBUG(
"StoreLock::unlinked: still in use: envelope exists: " << envelope_path ) ;
483 G_DEBUG(
"StoreLock::unlinked: unlinked since no envelope found in any sub-directory" ) ;
std::string str() const
Returns the path string.
A trivial class which is used like G::Root by GPop::Store for reading files.
G::Path dir() const
Returns the spool directory path.
void rollback()
Rolls back remove()als but retains the lock.
bool more()
Returns true if more and advances by one.
bool locked() const
Returns true if locked.
A trivial specialisation of G::Root used by GPop::Store for deleting files.
StoreLockEntry::Size Size
G::Path filePath() const
Returns the current path.
A class which acquires the process's special privileges on construction and releases them on destruct...
void readAll(const Path &dir)
An initialiser that is to be used after default construction.
Store(G::Path spool_dir, bool by_name, bool allow_delete)
Constructor.
Size messageCount() const
Returns the store's message count.
Represents a file in the GPop::Store.
bool allowDelete() const
Returns true if files can be deleted.
void readType(const Path &dir, const std::string &suffix, unsigned int limit=0U)
An initialiser that is to be used after default construction.
An encapsulation of a file system directory which allows for iterating through the set of contained f...
void remove(int)
Marks the message for removal.
Size totalByteCount() const
Returns the store's total byte count.
A trivial class which is used like G::Root by GPop::Store for reading directory listings.
static bool replace(std::string &s, const std::string &from, const std::string &to, size_type *pos_p=NULL)
Replaces 'from' with 'to', starting at offset '*pos_p'.
static bool enabled()
Returns true if test features are enabled.
A Directory iterator that does all file i/o in one go.
static bool exists(const Path &file)
Returns true if the file (directory, link, device etc.) exists.
static bool remove(const Path &path, const NoThrow &)
Deletes the file or directory. Returns false on error.
static std::string tmp()
A convenience function for constructing a filename for writeable().
An overload discriminator class for File methods.
void lock(const std::string &user)
Initialisation.
std::auto_ptr< std::istream > get(int id) const
Retrieves the message content.
Size byteCount(int id) const
Returns a message size.
void commit()
Commits remove()als.
void pathAppend(const std::string &tail)
Appends a filename to the path.
G::Path fileName() const
Returns the current filename.
bool byName() const
Returns true if the spool directory is affected by the user name.
static unsigned long toULong(const std::string &s, bool limited=false)
Converts string 's' to an unsigned long.
bool valid(int id) const
Validates a message number.
bool isDir() const
Returns true if the current item is a directory.
StoreLock(Store &store)
Constructor.
A Path object represents a file system path.
List list(int id=-1) const
Lists messages in the store.
std::string uidl(int id) const
Returns a message's unique id.