00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "meta-iostreams.h"
00026
00027 #include "directory.h"
00028
00029 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
00030 # define BOOST_UNIX 1
00031 #elif defined(_WINDOWS) || defined(__MINGW32__) || defined (_MSC_VER)
00032 # define BOOST_WINNT 1
00033 #endif
00034
00035
00036
00037
00038
00039
00040 #if defined(BOOST_UNIX)
00041
00042 #ifndef __USE_BSD
00043 #define __USE_BSD
00044 #endif
00045 #include <sys/stat.h>
00046 #include <dirent.h>
00047 #include <unistd.h>
00048 #include <pwd.h>
00049 #include <grp.h>
00050
00051 struct boost::filesystem::dir_it::representation
00052 {
00053 representation():
00054 m_handle(0),
00055 m_refcount(1),
00056 m_stat_p(false)
00057 {
00058 }
00059
00060 representation(std::string const &dirname):
00061 m_handle(opendir(dirname.c_str())),
00062 m_refcount(1),
00063 m_directory(dirname),
00064 m_stat_p(false)
00065 {
00066 if( m_directory.size() == 0 )
00067 m_directory = "./" ;
00068 if (m_directory[m_directory.size() - 1] != '/')
00069 m_directory += '/';
00070 operator++ ();
00071 }
00072
00073 ~representation() { if ( m_handle ) closedir(m_handle); }
00074
00075 representation *reference()
00076 {
00077 ++m_refcount;
00078 return this;
00079 }
00080 representation *release() { return --m_refcount? 0: this; }
00081
00082 representation &operator++()
00083 {
00084 if (m_handle)
00085 {
00086 m_stat_p = false;
00087 dirent *rc = readdir(m_handle);
00088 if (rc != 0)
00089 m_current = rc->d_name;
00090 else
00091 {
00092 m_current = "";
00093 closedir(m_handle);
00094 m_handle = 0;
00095 }
00096 }
00097
00098 return *this;
00099 }
00100
00101 bool operator== (representation const &rep) const
00102 {
00103 return (m_handle == 0) == (rep.m_handle == 0);
00104 }
00105
00106 std::string const &operator* () { return m_current; }
00107
00108 struct stat &get_stat()
00109 {
00110 if (!m_stat_p)
00111 stat( (m_directory + m_current).c_str(), &m_stat);
00112 return m_stat;
00113 }
00114
00115 void set_mode(mode_t m, bool nv)
00116 {
00117 if (((get_stat().st_mode & m) == 0) == nv)
00118 chmod((m_directory + m_current).c_str(), get_stat().st_mode ^ m);
00119 }
00120 void change_owner(uid_t uid) { chown((m_directory + m_current).c_str(), uid, get_stat().st_gid); }
00121 void change_group(gid_t gid) { chown((m_directory + m_current).c_str(), get_stat().st_uid, gid); }
00122
00123 private:
00124 DIR *m_handle;
00125 int m_refcount;
00126 std::string m_directory;
00127 std::string m_current;
00128 struct stat m_stat;
00129 bool m_stat_p;
00130 };
00131
00132 namespace boost
00133 {
00134 namespace filesystem
00135 {
00136
00137 template <> bool get<is_link>(dir_it const &it) { return S_ISLNK(it.rep->get_stat().st_mode); }
00138 template <> bool get<is_regular>(dir_it const &it) { return S_ISREG(it.rep->get_stat().st_mode); }
00139 template <> bool get<is_directory>(dir_it const &it) { return S_ISDIR(it.rep->get_stat().st_mode); }
00140 template <> bool get<is_char_device>(dir_it const &it) { return S_ISCHR(it.rep->get_stat().st_mode); }
00141 template <> bool get<is_block_device>(dir_it const &it) { return S_ISBLK(it.rep->get_stat().st_mode); }
00142 template <> bool get<is_fifo>(dir_it const &it) { return S_ISFIFO(it.rep->get_stat().st_mode); }
00143 template <> bool get<is_socket>(dir_it const &it) { return S_ISSOCK(it.rep->get_stat().st_mode); }
00144
00145 template <> bool get<user_read>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IRUSR; }
00146 template <> void set<user_read>(dir_it const &it, bool nv) { it.rep->set_mode(S_IRUSR, nv); }
00147 template <> bool get<user_write>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IWUSR; }
00148 template <> void set<user_write>(dir_it const &it, bool nv) { it.rep->set_mode(S_IWUSR, nv); }
00149 template <> bool get<user_execute>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IXUSR; }
00150 template <> void set<user_execute>(dir_it const &it, bool nv) { it.rep->set_mode(S_IXUSR, nv); }
00151 template <> bool get<set_uid>(dir_it const &it) { return it.rep->get_stat().st_mode & S_ISUID; }
00152 template <> void set<set_uid>(dir_it const &it, bool nv) { it.rep->set_mode(S_ISUID, nv); }
00153
00154 template <> bool get<group_read>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IRGRP; }
00155 template <> void set<group_read>(dir_it const &it, bool nv) { it.rep->set_mode(S_IRGRP, nv); }
00156 template <> bool get<group_write>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IWGRP; }
00157 template <> void set<group_write>(dir_it const &it, bool nv) { it.rep->set_mode(S_IWGRP, nv); }
00158 template <> bool get<group_execute>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IXGRP; }
00159 template <> void set<group_execute>(dir_it const &it, bool nv) { it.rep->set_mode(S_IXGRP, nv); }
00160 template <> bool get<set_gid>(dir_it const &it) { return it.rep->get_stat().st_mode & S_ISGID; }
00161 template <> void set<set_gid>(dir_it const &it, bool nv) { it.rep->set_mode(S_ISGID, nv); }
00162
00163 template <> bool get<other_read>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IROTH; }
00164 template <> void set<other_read>(dir_it const &it, bool nv) { it.rep->set_mode(S_IROTH, nv); }
00165 template <> bool get<other_write>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IWOTH; }
00166 template <> void set<other_write>(dir_it const &it, bool nv) { it.rep->set_mode(S_IWOTH, nv); }
00167 template <> bool get<other_execute>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IXOTH; }
00168 template <> void set<other_execute>(dir_it const &it, bool nv) { it.rep->set_mode(S_IXOTH, nv); }
00169 template <> bool get<sticky>(dir_it const &it) { return it.rep->get_stat().st_mode & S_ISVTX; }
00170 template <> void set<sticky>(dir_it const &it, bool nv) { it.rep->set_mode(S_ISVTX, nv); }
00171
00172 template <> nlink_t get<links>(dir_it const &it) { return it.rep->get_stat().st_nlink; }
00173 template <> size_t get<size>(dir_it const &it) { return it.rep->get_stat().st_size; }
00174 template <> unsigned long get<blocks>(dir_it const &it) { return it.rep->get_stat().st_blocks; }
00175 template <> unsigned long get<blksize>(dir_it const &it) { return it.rep->get_stat().st_blksize; }
00176
00177 template <> mtime::value_type get<mtime>(dir_it const &it) { return &it.rep->get_stat().st_mtime; }
00178 template <> atime::value_type get<atime>(dir_it const &it) { return &it.rep->get_stat().st_atime; }
00179 template <> ctime::value_type get<ctime>(dir_it const &it) { return &it.rep->get_stat().st_ctime; }
00180
00181 template <> uid_t get<uid>(dir_it const &it) { return it.rep->get_stat().st_uid; }
00182 template <> void set<uid>(dir_it const &it, uid_t uid) { it.rep->change_owner(uid); }
00183 template <> std::string get<uname>(dir_it const &it)
00184 {
00185 struct passwd *pw = getpwuid(it.rep->get_stat().st_uid);
00186 if (pw == 0)
00187 throw unknown_uid(it.rep->get_stat().st_uid);
00188 return pw->pw_name;
00189 }
00190 template <> void set<uname>(dir_it const &it, std::string name)
00191 {
00192 struct passwd *pw = getpwnam(name.c_str());
00193 if (pw != 0)
00194 it.rep->change_owner(pw->pw_uid);
00195 else
00196 throw unknown_uname(name);
00197 }
00198
00199 template <> gid_t get<gid>(dir_it const &it) { return it.rep->get_stat().st_gid; }
00200 template <> void set<gid>(dir_it const &it, gid_t gid) { it.rep->change_group(gid); }
00201 template <> std::string get<gname>(dir_it const &it)
00202 {
00203 struct group *grp = getgrgid(it.rep->get_stat().st_gid);
00204 if (grp == 0)
00205 throw unknown_gid(it.rep->get_stat().st_gid);
00206 return grp->gr_name;
00207 }
00208 template <> void set<gname>(dir_it const &it, std::string name)
00209 {
00210 struct group *grp = getgrnam(name.c_str());
00211 if (grp != 0)
00212 it.rep->change_group(grp->gr_gid);
00213 else
00214 throw unknown_gname(name);
00215 }
00216
00217
00218 template <> bool get<is_hidden>(dir_it const &it) { return (*it)[0] == '.'; }
00219 }
00220 }
00221
00222 #elif defined(BOOST_WINNT)
00223
00224 #include "io.h"
00225 #include "direct.h"
00226
00227 struct boost::filesystem::dir_it::representation
00228 {
00229 representation():
00230 m_handle(-1),
00231 m_refcount(1)
00232 {
00233 }
00234
00235 representation(std::string const &dirname):
00236 m_handle(_findfirst((dirname + "\\*").c_str(), &m_data)),
00237 m_refcount(1)
00238 {
00239 }
00240
00241 ~representation() { if (m_handle != -1) _findclose(m_handle); }
00242
00243 representation *reference()
00244 {
00245 ++m_refcount;
00246 return this;
00247 }
00248 representation *release() { return --m_refcount? 0: this; }
00249
00250 representation &operator++()
00251 {
00252 if (m_handle != -1)
00253 {
00254 if (_findnext(m_handle, &m_data) == -1)
00255 {
00256 _findclose(m_handle);
00257 m_handle = -1;
00258 }
00259
00260 }
00261
00262 return *this;
00263 }
00264
00265 bool operator== (representation const &rep) const
00266 {
00267 return (m_handle == -1) == (rep.m_handle == -1);
00268 }
00269
00270 std::string operator* () { return m_data.name; }
00271
00272
00273 struct _finddata_t const &get_data() const
00274 {
00275 return m_data;
00276 }
00277
00278 #if 0
00279 void set_mode(mode_t m, bool nv)
00280 {
00281 if (((get_stat().st_mode & m) == 0) == nv)
00282 chmod((m_directory + m_current).c_str(), get_stat().st_mode ^ m);
00283 }
00284 void change_owner(uid_t uid) { chown((m_directory + m_current).c_str(), uid, get_stat().st_gid); }
00285 void change_group(gid_t gid) { chown((m_directory + m_current).c_str(), get_stat().st_uid, gid); }
00286 #endif
00287
00288 private:
00289 struct _finddata_t m_data;
00290 long m_handle;
00291 int m_refcount;
00292 std::string m_directory;
00293 };
00294
00295 namespace boost
00296 {
00297 namespace filesystem
00298 {
00299 #if defined(__MINGW32__)
00300 template <> size_t get<size>(dir_it const &it)
00301 {
00302 return it.rep->get_data().size;
00303 }
00304 template <> mtime::value_type get<mtime>(dir_it const &it)
00305 {
00306 return &it.rep->get_data().time_write;
00307 }
00308 template <> bool get<is_directory>(dir_it const &it)
00309 {
00310 return (it.rep->get_data().attrib & _A_SUBDIR) != 0;
00311 }
00312 template <> bool get<is_regular>(dir_it const &it)
00313 {
00314 return (it.rep->get_data().attrib & _A_SUBDIR) == 0;
00315 }
00316 template <> bool get<is_hidden>(dir_it const &it)
00317 {
00318 return (it.rep->get_data().attrib & _A_HIDDEN) != 0;
00319 }
00320 template <> bool get<user_read>(dir_it const &it)
00321 {
00322 return true;
00323 }
00324 template <> bool get<user_write>(dir_it const &it)
00325 {
00326 return (it.rep->get_data().attrib & _A_RDONLY) == 0;
00327 }
00328 template <> bool get<user_execute>(dir_it const &it)
00329 {
00330 std::string name(*it);
00331 std::string ext(name.substr(name.find_last_of('.')));
00332 return ext == ".exe" || ext == ".bat";
00333 }
00334 #else
00335 get<size>::operator size::value_type() const
00336 {
00337 return m_it.rep->get_data().size;
00338 }
00339 get<mtime>::operator mtime::value_type() const
00340 {
00341 return &m_it.rep->get_data().time_write;
00342 }
00343 get<is_directory>::operator is_directory::value_type() const
00344 {
00345 return (m_it.rep->get_data().attrib & _A_SUBDIR) != 0;
00346 }
00347 get<is_regular>::operator is_regular::value_type() const
00348 {
00349 return (m_it.rep->get_data().attrib & _A_SUBDIR) == 0;
00350 }
00351 get<is_hidden>::operator is_hidden::value_type() const
00352 {
00353 return (m_it.rep->get_data().attrib & _A_HIDDEN) != 0;
00354 }
00355 get<user_read>::operator user_read::value_type() const
00356 {
00357 return true;
00358 }
00359 get<user_write>::operator user_write::value_type() const
00360 {
00361 return (m_it.rep->get_data().attrib & _A_RDONLY) == 0;
00362 }
00363 get<user_execute>::operator user_execute::value_type() const
00364 {
00365 std::string name(*m_it);
00366 std::string ext(name.substr(name.find_last_of('.')));
00367 return ext == ".exe" || ext == ".bat";
00368 }
00369 #endif // __MINGW32__
00370 }
00371 }
00372 #endif
00373
00374
00375
00376 boost::filesystem::dir_it::dir_it():
00377 rep(new representation())
00378 {
00379 }
00380
00381 boost::filesystem::dir_it::dir_it(std::string const &dirname):
00382 rep(new representation(dirname))
00383 {
00384 }
00385
00386 boost::filesystem::dir_it::dir_it(boost::filesystem::dir_it const &it):
00387 rep(it.rep->reference())
00388 {
00389 }
00390
00391 boost::filesystem::dir_it::~dir_it()
00392 {
00393 delete rep->release();
00394 }
00395
00396 boost::filesystem::dir_it &boost::filesystem::dir_it::operator= (boost::filesystem::dir_it const &it)
00397 {
00398 it.rep->reference();
00399 delete rep->release();
00400 rep = it.rep;
00401 return *this;
00402 }
00403
00404
00405
00406 std::string boost::filesystem::dir_it::operator* () const
00407 {
00408 return *(*rep);
00409 }
00410
00411 boost::filesystem::dir_it &boost::filesystem::dir_it::operator++ ()
00412 {
00413 ++(*rep);
00414 return *this;
00415 }
00416
00417 boost::filesystem::dir_it::proxy boost::filesystem::dir_it::operator++ (int)
00418 {
00419 std::string rc(*(*rep));
00420 ++(*rep);
00421 return rc;
00422 }
00423
00424
00425
00426 bool boost::filesystem::dir_it::operator== (boost::filesystem::dir_it const &it) const
00427 {
00428 return *rep == *(it.rep);
00429 }
00430
00431 bool boost::filesystem::dir_it::operator!= (boost::filesystem::dir_it const &it) const
00432 {
00433 return !(*rep == *(it.rep));
00434 }