/* PIP - Platform Independent Primitives Directory Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "pidir.h" #if !defined(ANDROID) #ifdef WINDOWS const PIChar PIDir::separator = '\\'; #else const PIChar PIDir::separator = '/'; #endif PIDir::PIDir(const PIString & dir) { path_ = dir; } PIDir::PIDir(const PIFile & file) { path_ = file.path(); if (isExists()) return; int pos = path_.findLast(separator); path_.cutRight(path_.size_s() - pos); } bool PIDir::operator ==(const PIDir & d) const { return d.absolutePath() == absolutePath(); } bool PIDir::isAbsolute() const { if (path_.size() == 0) return false; #ifdef WINDOWS if (path_.size() < 3) return false; return (path_[1] == ":"); #else return (path_[0] == separator); #endif } PIString PIDir::absolutePath() const { if (isAbsolute()) return path_; PIDir d(path_); d.setDir(PIDir::current().path_ + separator + path_); return d.path_; } PIDir & PIDir::cleanPath() { PIString p(path_); if (p.size() == 0) { path_ = "."; return *this; } path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator)); bool is_abs = isAbsolute(); PIStringList l = PIString(p).split(separator); #ifdef WINDOWS PIString letter; if (is_abs) letter = l.take_front(); #endif l.removeAll("."); l.removeAll(""); bool found = true; while (found) { found = false; for (uint i = 0; i < l.size() - 1; ++i) { if (l.size() < 2) break; if (l[i] != ".." && l[i + 1] == "..") { if (l.size() + i > 2) l.remove(i, 2); else l.remove(i, 1); --i; found = true; } } } found = true; while (found) { found = false; if (l.size() > 0) if (l[0] == "..") {l.pop_front(); found = true;} } path_ = separator + l.join(separator); /// TODO think about windows if (!is_abs) path_.prepend("."); #ifdef WINDOWS else path_.prepend(letter); #endif if (path_.size() == 0) path_ = "."; return *this; } PIDir & PIDir::setDir(const PIString & path) { path_ = path; cleanPath(); return *this; } PIDir & PIDir::cd(const PIString & path) { if (path_.size() == 0) return *this; if (path_[path_.size() - 1] != separator) path_ += separator; path_ += path; return cleanPath(); } bool PIDir::make(bool withParents) { PIDir d = cleanedPath(); PIString tp; bool is_abs = isAbsolute(); if (withParents) { PIStringList l = d.path_.split(separator); for (int i = l.size_s() - 1; i >= 0; --i) { if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator); else { tp = separator; if (!is_abs) tp.push_front('.'); } //cout << tp << endl; if (isExists(tp)) { for (int j = i + 1; j <= l.size_s(); ++j) { tp = PIStringList(l).remove(j, l.size_s() - j).join(separator); //cout << tp << endl; if (makeDir(tp)) continue; else return false; } break; }; } } else if (makeDir(d.path_)) return true; return false; } PIVector PIDir::entries() { PIVector l; PIString p(cleanedPath().path_); #ifdef WINDOWS WIN32_FIND_DATA fd; memset(&fd, 0, sizeof(fd)); p += "\\*"; void * hf = FindFirstFile((LPCTSTR)(p.data()), &fd); if (!hf) return l; LARGE_INTEGER filesize; do { int m = 0; filesize.LowPart = filesize.HighPart = 0; if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) m |= S_IFHDN; if (fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) m |= S_IFBLK; if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) m |= S_IFDIR; else { m |= S_IFREG; filesize.LowPart = fd.nFileSizeLow; filesize.HighPart = fd.nFileSizeHigh; } l << DirEntry(fd.cFileName, m, filesize.QuadPart); memset(&fd, 0, sizeof(fd)); } while (FindNextFile(hf, &fd) != 0); FindClose(hf); #else dirent ** list; # ifndef QNX int cnt = scandir(p.data(), &list, 0, versionsort); # else int cnt = scandir(const_cast(p.data()), 0, 0, versionsort); # endif struct stat fs; for (int i = 0; i < cnt; ++i) { stat((p + separator + PIString(list[i]->d_name)).data(), &fs); l << DirEntry(list[i]->d_name, fs.st_mode, fs.st_size); if (list[i]->d_name[0] == '.') l.back().mode |= S_IFHDN; delete list[i]; } delete list; #endif return l; } bool PIDir::isExists(const PIString & path) { #ifdef WINDOWS return (GetFileAttributes((LPCTSTR)(path.data())) & FILE_ATTRIBUTE_DIRECTORY); #else DIR * dir_ = opendir(path.data()); if (dir_ == 0) return false; closedir(dir_); #endif return true; } PIDir PIDir::current() { char rc[1024]; #ifdef WINDOWS memset(rc, 0, 1024); if (GetCurrentDirectory(1024, (LPTSTR)rc) == 0) return PIString(); #else if (getcwd(rc, 1024) == 0) return PIString(); #endif return PIDir(rc); } PIDir PIDir::home() { char * rc = 0; #ifdef WINDOWS rc = new char[1024]; memset(rc, 0, 1024); if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEPATH%", (LPTSTR)rc, 1024) == 0) { delete[] rc; return PIDir(); } PIString s(rc); delete[] rc; return PIDir(s); #else rc = getenv("HOME"); if (rc == 0) return PIDir(); return PIDir(rc); #endif } PIDir PIDir::temporary() { char * rc = 0; #ifdef WINDOWS rc = new char[1024]; memset(rc, 0, 1024); int ret = GetTempPath(1024, (LPTSTR)rc); if (ret == 0) { delete[] rc; return PIDir(); } PIString s(rc); delete[] rc; return PIDir(s); #else rc = tmpnam(0); if (rc == 0) return PIDir(); PIString s(rc); return PIDir(s.left(s.findLast(PIDir::separator))); #endif } bool PIDir::make(const PIString & path, bool withParents) { PIDir d(path); if (d.isExists()) return true; return d.make(withParents); } bool PIDir::setCurrent(const PIString & path) { #ifdef WINDOWS if (SetCurrentDirectory((LPCTSTR)(path.data())) != 0) return true; #else if (chdir(path.data()) == 0) return true; #endif printf("[PIDir] setCurrent(\"%s\") error: %s\n", path.data(), errorString().c_str()); return false; } bool PIDir::makeDir(const PIString & path) { #ifdef WINDOWS if (CreateDirectory((LPCTSTR)(path.data()), NULL) != 0) return true; #else if (mkdir(path.data(), 16877) == 0) return true; #endif printf("[PIDir] makeDir(\"%s\") error: %s\n", path.data(), errorString().c_str()); return false; } bool PIDir::removeDir(const PIString & path) { #ifdef WINDOWS if (RemoveDirectory((LPCTSTR)(path.data())) != 0) return true; #else if (rmdir(path.data()) == 0) return true; #endif printf("[PIDir] removeDir(\"%s\") error: %s\n", path.data(), errorString().c_str()); return false; } bool PIDir::renameDir(const PIString & path, const PIString & new_name) { if (::rename(path.data(), new_name.data()) == 0) return true; printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().c_str()); return false; } #endif