zipios++  2.0.2
Zipios++ – a small C++ library that provides easy access to .zip files.
directorycollection.cpp
Go to the documentation of this file.
1 /*
2  Zipios++ - a small C++ library that provides easy access to .zip files.
3 
4  Copyright (C) 2000-2007 Thomas Sondergaard
5  Copyright (C) 2015 Made to Order Software Corporation
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
30 #if defined(_WINDOWS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32)
31 #define ZIPIOS_WINDOWS
32 #endif
33 
35 
37 
38 #include <fstream>
39 
40 #ifdef ZIPIOS_WINDOWS
41 #include <io.h>
42 #else
43 #include <dirent.h>
44 #include <errno.h>
45 #endif
46 
47 
48 namespace zipios
49 {
50 
66  //: m_entries_loaded(false) -- auto-init
67  //, m_recursive(true) -- auto-init
68  //, m_filepath("") -- auto-init
69 {
70 }
71 
72 
95 DirectoryCollection::DirectoryCollection(std::string const & path, bool recursive)
96  //: m_entries_loaded(false) -- auto-init
97  : m_recursive(recursive)
98  , m_filepath(path)
99 {
102 }
103 
104 
110 {
111  close();
112 }
113 
114 
121 {
122  m_entries_loaded = false;
123  m_filepath = "";
124 
126 }
127 
128 
145 {
146  loadEntries();
147 
148  return FileCollection::entries();
149 }
150 
151 
172 FileEntry::pointer_t DirectoryCollection::getEntry(std::string const & name, MatchPath matchpath) const
173 {
174  loadEntries();
175 
176  return FileCollection::getEntry(name, matchpath);
177 }
178 
179 
206 {
207  FileEntry::pointer_t ent(getEntry(entry_name, matchpath));
208  if(!ent || ent->isDirectory())
209  {
211  }
212 
213  DirectoryCollection::stream_pointer_t p(new std::ifstream(ent->getName(), std::ios::in | std::ios::binary));
214  return p;
215 }
216 
217 
228 {
229  loadEntries();
230 
231  return m_entries.size();
232 }
233 
234 
243 {
245 }
246 
247 
256 {
257  // WARNING: this has to stay here because the collection could get close()'s...
258  mustBeValid();
259 
260  if(!m_entries_loaded)
261  {
262  m_entries_loaded = true;
263 
264  // if the read fails then the directory may have been deleted
265  // in which case we want to invalidate this DirectoryCollection
266  // object
267  try
268  {
269  // include the root directory
271  const_cast<DirectoryCollection *>(this)->m_entries.push_back(entry);
272 
273  // now read the data inside that directory
274  if(m_filepath.isDirectory())
275  {
276  const_cast<DirectoryCollection *>(this)->load(FilePath());
277  }
278  }
279  catch(...)
280  {
281  const_cast<DirectoryCollection *>(this)->close();
282  throw;
283  }
284  }
285 }
286 
287 
298 {
299 #ifdef ZIPIOS_WINDOWS
300  struct read_dir_t
301  {
302  read_dir_t(FilePath const& path)
303  //: m_handle(0) -- auto-init
304  //, m_fileinfo() -- initialized below
305  //, m_read_first(false) -- auto-init
306  {
312  m_handle = _findfirsti64(path.getName().c_str(), &m_findinfo);
313  if(m_handle == 0)
314  {
315  if(errno == ENOENT)
316  {
317  // this can happen, the directory is empty and thus has
318  // absolutely no information
319  f_read_first = true;
320  }
321  else
322  {
323  throw IOException("an I/O error occured while reading a directory");
324  }
325  }
326  }
327 
328  ~read_dir_t()
329  {
330  // a completely empty directory may give us a "null pointer"
331  // when calling _[w]findfirst[i64]()
332  if(m_handle != 0)
333  {
334  _findclose(m_handle);
335  }
336  }
337 
338  std::string next()
339  {
340  if(m_read_first)
341  {
342  __int64 const r(_findnexti64(m_handle, &m_fileinfo));
343  if(r != 0)
344  {
345  if(errno != ENOENT)
346  {
347  throw IOException("an I/O error occured while reading a directory");
348  }
349  return std::string();
350  }
351  }
352  else
353  {
354  // the _findfirst() includes a response, use it!
355  m_read_first = true;
356  }
357 
358  return m_fileinfo.name;
359  }
360 
361  private:
362  long m_handle = 0;
363  struct _finddata_t m_fileinfo;
364  bool m_read_first = 0;
365  };
366 #else
367  struct read_dir_t
368  {
369  read_dir_t(FilePath const& path)
370  : m_dir(opendir(static_cast<std::string>(path).c_str()))
371  {
372  if(!m_dir)
373  {
374  throw IOException("an I/O error occured while trying to access directory");
375  }
376  }
377 
378  ~read_dir_t()
379  {
380  closedir(m_dir);
381  }
382 
383  std::string next()
384  {
385  errno = 0;
386  struct dirent *entry, e;
387  int const r(readdir_r(m_dir, &e, &entry));
388  if(r != 0)
389  {
390  throw IOException("an I/O error occured while reading a directory"); // LCOV_EXCL_LINE
391  }
392  if(entry == NULL)
393  {
394  return std::string();
395  }
396 
397  return entry->d_name;
398  }
399 
400  private:
401  DIR * m_dir;
402  };
403 #endif
404 
405  read_dir_t dir(m_filepath + subdir);
406  for(;;)
407  {
408  std::string const& name(dir.next());
409  if(name.empty())
410  {
411  break;
412  }
413 
414  // skip the "." and ".." directories, they are never added to
415  // a Zip archive
416  if(name != "." && name != "..")
417  {
418  FileEntry::pointer_t entry(new DirectoryEntry(m_filepath + subdir + name, ""));
419  m_entries.push_back(entry);
420 
421  if(m_recursive && entry->isDirectory())
422  {
423  load(subdir + name);
424  }
425  }
426  }
427 }
428 
429 
430 } // zipios namespace
431 
432 // Local Variables:
433 // mode: cpp
434 // indent-tabs-mode: nil
435 // c-basic-offset: 4
436 // tab-width: 4
437 // End:
438 
439 // vim: ts=4 sw=4 et
virtual FileEntry::pointer_t getEntry(std::string const &name, MatchPath matchpath=MatchPath::MATCH) const
Get an entry from this collection.
std::shared_ptr< FileCollection > pointer_t
virtual FileEntry::vector_t entries() const override
Retrieve a vector to the collection entries.
void loadEntries() const
This is an internal function that loads the file entries.
Various exceptions used throughout the Zipios++ library, all based on zipios::Exception.
bool isRegular() const
Check whether the file is a regular file.
Definition: filepath.cpp:372
std::shared_ptr< std::istream > stream_pointer_t
A shared pointer to an input stream.
virtual FileEntry::vector_t entries() const
Retrieve the array of entries.
Define the zipios::DirectoryCollection class.
A collection generated from reading a directory.
virtual size_t size() const override
Return the number of entries defined in this collection.
virtual void close() override
Close the directory collection.
virtual pointer_t clone() const override
Create another DirectoryCollection.
DirectoryCollection()
Initialize a DirectoryCollection object.
FileEntry::vector_t m_entries
bool isDirectory() const
Check whether the file is a directory.
Definition: filepath.cpp:386
An IOException is used to signal an I/O error.
virtual void close()
Close the current FileEntry of this FileCollection.
virtual void mustBeValid() const
Check whether the collection is valid.
void load(FilePath const &subdir)
This is the function loading all the file entries.
Handle a file path and name and its statistics.
Definition: filepath.hpp:46
virtual ~DirectoryCollection() override
Clean up a DirectoryCollection object.
A file entry that does not use compression.
virtual stream_pointer_t getInputStream(std::string const &entry_name, MatchPath matchpath=MatchPath::MATCH) override
Retrieve pointer to an istream.
virtual FileEntry::pointer_t getEntry(std::string const &name, MatchPath matchpath=MatchPath::MATCH) const override
Get an entry from the collection.
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:77
std::vector< pointer_t > vector_t
Definition: fileentry.hpp:78