E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gdirectory_unix.cpp
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gdirectory_unix.cpp
19 //
20
21 #include "gdef.h"
22 #include "gdirectory.h"
23 #include "gprocess.h"
24 #include "gdatetime.h"
25 #include "gfile.h"
26 #include "gdebug.h"
27 #include "glog.h"
28 #include <sstream>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <dirent.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34
35 namespace G
36 {
37 class DirectoryIteratorImp ;
38 }
39
40 /// \class G::DirectoryIteratorImp
41 /// A pimple-pattern implementation class for DirectoryIterator using
42 /// opendir()/readdir().
43 ///
44 class G::DirectoryIteratorImp
45 {
46 private:
47 DIR * m_d ;
48 struct dirent * m_dp ;
49 Directory m_dir ;
50 bool m_error ;
51
52 public:
53 explicit DirectoryIteratorImp( const Directory & dir ) ;
54 ~DirectoryIteratorImp() ;
55 bool isDir() const ;
56 bool more() ;
57 bool error() const ;
58 std::string sizeString() const ;
59 Path filePath() const ;
60 std::string fileName() const ;
61
62 private:
63 void operator=( const DirectoryIteratorImp & ) ;
64 DirectoryIteratorImp( const DirectoryIteratorImp & ) ;
65 } ;
66
67 //
68
69 bool G::Directory::valid( bool for_creation ) const
70 {
71 bool rc = true ;
72 struct stat statbuf ;
73 if( ::stat( m_path.str().c_str() , &statbuf ) )
74 {
75 rc = false ; // doesnt exist
76 }
77 else if( !(statbuf.st_mode & S_IFDIR) )
78 {
79 rc = false ; // not a directory
80 }
81 else
82 {
83 DIR * p = ::opendir( m_path.str().c_str() ) ;
84 if( p == nullptr )
85 rc = false ; // cant open directory for reading
86 else
87 ::closedir( p ) ;
88 }
89
90 if( rc && for_creation )
91 {
92 // (not definitive -- see also GNU/Linux ::euidaccess())
93 if( 0 != ::access( m_path.str().c_str() , W_OK ) )
94 rc = false ;
95 }
96 return rc ;
97 }
98
99 std::string G::Directory::tmp()
100 {
101 std::ostringstream ss ;
102 ss << "." << DateTime::now() << "." << Process::Id() << ".tmp" ;
103 return ss.str() ;
104 }
105
106 bool G::Directory::writeable( std::string tmp_filename ) const
107 {
108 G::Path test_file( m_path ) ;
109 if( tmp_filename.empty() ) tmp_filename = tmp() ;
110 test_file.pathAppend( tmp_filename ) ;
111
112 int fd = ::open( test_file.str().c_str() , O_WRONLY | O_CREAT | O_EXCL , S_IRWXU ) ;
113 if( fd == -1 )
114 {
115 return false ;
116 }
117 ::close( fd ) ;
118 bool ok = 0 == ::unlink( test_file.str().c_str() ) ;
119 return ok ;
120 }
121
122 // ===
123
124 G::DirectoryIterator::DirectoryIterator( const Directory & dir ) :
125 m_imp( new DirectoryIteratorImp(dir) )
126 {
127 }
128
129 bool G::DirectoryIterator::error() const
130 {
131 return m_imp->error() ;
132 }
133
134 bool G::DirectoryIterator::more()
135 {
136 return m_imp->more() ;
137 }
138
139 G::Path G::DirectoryIterator::filePath() const
140 {
141 return m_imp->filePath() ;
142 }
143
144 std::string G::DirectoryIterator::fileName() const
145 {
146 return m_imp->fileName() ;
147 }
148
149 bool G::DirectoryIterator::isDir() const
150 {
151 return m_imp->isDir() ;
152 }
153
154 std::string G::DirectoryIterator::sizeString() const
155 {
156 return m_imp->sizeString() ;
157 }
158
159 G::DirectoryIterator::~DirectoryIterator()
160 {
161 delete m_imp ;
162 }
163
164 // ===
165
166 G::DirectoryIteratorImp::DirectoryIteratorImp( const Directory & dir ) :
167 m_d(nullptr) ,
168 m_dp(nullptr) ,
169 m_dir(dir) ,
170 m_error(true)
171 {
172 m_d = ::opendir( dir.path().str().c_str() ) ;
173 m_error = m_d == nullptr ;
174 }
175
176 bool G::DirectoryIteratorImp::error() const
177 {
178 return m_error ;
179 }
180
181 bool G::DirectoryIteratorImp::more()
182 {
183 while( !m_error )
184 {
185 m_dp = ::readdir( m_d ) ;
186 m_error = m_dp == nullptr ;
187 bool special = !m_error && ( fileName() == "." || fileName() == ".." ) ;
188 if( !special )
189 break ;
190 }
191 return !m_error ;
192 }
193
194 G::Path G::DirectoryIteratorImp::filePath() const
195 {
196 return m_dir.path() + fileName() ;
197 }
198
199 std::string G::DirectoryIteratorImp::fileName() const
200 {
201 return m_dp == nullptr ? std::string() : std::string(m_dp->d_name) ;
202 }
203
204 bool G::DirectoryIteratorImp::isDir() const
205 {
206 struct stat statbuf ;
207 return ::stat( filePath().str().c_str() , &statbuf ) == 0 && (statbuf.st_mode & S_IFDIR) ;
208 }
209
210 G::DirectoryIteratorImp::~DirectoryIteratorImp()
211 {
212 if( m_d != nullptr )
213 ::closedir( m_d ) ;
214 }
215
216 std::string G::DirectoryIteratorImp::sizeString() const
217 {
218 std::string s = G::File::sizeString( filePath() ) ;
219 return s.empty() ? std::string("0") : s ;
220 }
221
G::Path::str
std::string str() const
Returns the path string.
Definition: gpath.cpp:290
gdirectory.h
G::DirectoryIterator::sizeString
std::string sizeString() const
Returns the file size as a decimal string.
Definition: gdirectory_unix.cpp:154
glog.h
G::DirectoryIterator::filePath
Path filePath() const
Returns the path of the current item.
Definition: gdirectory_unix.cpp:139
std
STL namespace.
G::Directory::path
Path path() const
Returns the directory's path.
Definition: gdirectory.cpp:67
G::Directory::valid
bool valid(bool for_creating_files=false) const
Returns true if the object represents a valid directory.
Definition: gdirectory_unix.cpp:69
G::Directory::writeable
bool writeable(std::string probe_filename=tmp()) const
Tries to create and then delete an empty test file in the directory.
Definition: gdirectory_unix.cpp:106
G::DirectoryIterator::~DirectoryIterator
~DirectoryIterator()
Destructor.
Definition: gdirectory_unix.cpp:159
G::DateTime::now
static EpochTime now()
Returns the current epoch time.
Definition: gdatetime_unix.cpp:26
G::Directory
An encapsulation of a file system directory that allows for iterating through the set of contained fi...
Definition: gdirectory.h:45
G
Low-level classes.
Definition: garg.h:29
gfile.h
gprocess.h
G::Directory::tmp
static std::string tmp()
A convenience function for constructing a filename for writeable().
Definition: gdirectory_unix.cpp:99
gdatetime.h
G::DirectoryIterator::more
bool more()
Returns true if more and advances by one.
Definition: gdirectory_unix.cpp:134
G::DirectoryIterator::isDir
bool isDir() const
Returns true if the current item is a directory.
Definition: gdirectory_unix.cpp:149
G::Path::pathAppend
void pathAppend(const std::string &tail)
Appends a filename or a relative path to this path.
Definition: gpath.cpp:357
G::File::sizeString
static std::string sizeString(const Path &file)
Returns the file's size in string format.
Definition: gfile_unix.cpp:96
G::DirectoryIteratorImp
A pimple-pattern implementation class for DirectoryIterator using opendir()/readdir().
Definition: gdirectory_unix.cpp:44
G::DirectoryIterator::fileName
std::string fileName() const
Returns the name of the current item.
Definition: gdirectory_unix.cpp:144
G::DirectoryIterator::error
bool error() const
Returns true on error. The caller should stop the iteration.
Definition: gdirectory_unix.cpp:129
G::Path
A Path object represents a file system path.
Definition: gpath.h:72
G::DirectoryIterator::DirectoryIterator
DirectoryIterator(const Directory &dir)
Constructor taking a directory reference.
Definition: gdirectory_unix.cpp:124
gdebug.h