00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00015 #include <ders/dir.hpp>
00016 #include <dirent.h>
00017 #include <errno.h>
00018 #include <sys/stat.h>
00019 #include <ders/file.hpp>
00020 #include <ders/text_buf.hpp>
00021
00022 namespace {
00023
00024 using namespace ders;
00025
00026 struct pos_dir : public dir {
00027 sh_text dn;
00028 DIR* dr;
00029
00030 pos_dir(sh_text dname) : dn(dname), dr(0) {}
00031 ~pos_dir() { if (dr) closedir(dr); }
00032
00033 virtual bool find_next(entry&);
00034 virtual sh_text full_name(const entry& dent);
00035
00036 virtual void destroy(mem_pool& mp2) { destroy_this(this, mp2); }
00037 };
00038
00039 bool pos_dir::find_next(entry& dent)
00040 {
00041 mem_pool& mp=dn.pool();
00042
00043 if (!dr) {
00044 if ( !(dr=opendir(dn->size() ? dn->c_str() : ".")) ) {
00045 throw newFileErrorException(mp, _FLINE_, "Can't find first file",
00046 convert_errno(errno), dn);
00047 }
00048 }
00049
00050 dirent *ent=readdir(dr);
00051 if (!ent) return false;
00052
00053 *dent.name=ent->d_name;
00054 dent.isdir=false;
00055 dent.size=0;
00056
00057 struct stat statbuf;
00058 if (stat(pos_dir::full_name(dent)->c_str(), &statbuf)==0) {
00059 dent.isdir=statbuf.st_mode&S_IFDIR;
00060 dent.size=statbuf.st_size;
00061 }
00062
00063 return true;
00064 }
00065
00066 sh_text pos_dir::full_name(const entry& dent)
00067 {
00068 text_buf buf(dn);
00069 if (dn->size() && dn->back()!='/') buf+'/';
00070
00071 return buf+dent.name;
00072 }
00073
00074 }
00075
00076 namespace ders {
00077
00078 sh_dir new_dir(mem_pool& mp, const ch_rng& dname)
00079 {
00080 mp_newbuf<pos_dir> buf(mp);
00081 return sh_dir(buf.pool(), buf.rls(::new(buf.get()) pos_dir(nt(mp, dname))));
00082 }
00083
00084 error make_dir(mem_pool& mp, const ch_rng& dname)
00085 {
00086 return (mkdir(text(mp, dname).c_str(), S_IRWXU|S_IRWXG|S_IRWXO)==-1) ?
00087 convert_errno(errno) : ezero;
00088 }
00089
00090 }
00091