/* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id$ * * this program prints directory listings from a windows ce device * * todo: (DONE) add disk space free/used info */ #include #include #include #include #include "debug.h" #include "args.h" #include "vectorutils.h" #include "stringutils.h" #include "csidlpaths.h" #include #include "util/timeconvert.h" bool g_bRecurse= false; bool g_bVerbose= false; typedef std::map StringStringMap; #define AT_NONEXISTANT 1 #define AT_ISDIRECTORY 2 #define AT_ISFILE 3 int getCeAttributes(const std::string& name) { DWORD dwAttr = CeGetFileAttributes( (WCHAR*)expand_csidl(ToWString(name)).c_str() ); if (0xFFFFFFFF == dwAttr) return AT_NONEXISTANT; if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) return AT_ISDIRECTORY; return AT_ISFILE; } bool isCeDirectory(const std::string& name) { return getCeAttributes(name)==AT_ISDIRECTORY; } bool isCeFile(const std::string& name) { return getCeAttributes(name)==AT_ISFILE; } bool isCeNonExistant(const std::string& name) { return getCeAttributes(name)==AT_NONEXISTANT; } std::string concat_path(const std::string& p1, const std::string& p2) { std::string result(p1); if (result.size() && result[result.size()-1]!='/' && result[result.size()-1]!='\\') result += '\\'; result += p2; return result; } std::string GetBasePath(const std::string& name) { size_t lastslash= name.find_last_of("\\/"); if (lastslash==name.npos) return ""; return name.substr(0, lastslash); } /* 0x00000001 FILE_ATTRIBUTE_READONLY 0x00000002 FILE_ATTRIBUTE_HIDDEN 0x00000004 FILE_ATTRIBUTE_SYSTEM 0x00000010 FILE_ATTRIBUTE_DIRECTORY 0x00000020 FILE_ATTRIBUTE_ARCHIVE 0x00000040 FILE_ATTRIBUTE_INROM 0x00000080 FILE_ATTRIBUTE_NORMAL 0x00000100 FILE_ATTRIBUTE_TEMPORARY 0x00000200 FILE_ATTRIBUTE_SPARSE_FILE 0x00000400 FILE_ATTRIBUTE_REPARSE_POINT 0x00000800 FILE_ATTRIBUTE_COMPRESSED 0x00001000 FILE_ATTRIBUTE_OFFLINE 0x00001000 FILE_ATTRIBUTE_ROMSTATICREF 0x00002000 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 FILE_ATTRIBUTE_ROMMODULE 0x00004000 FILE_ATTRIBUTE_ENCRYPTED 0x00010000 FILE_ATTRIBUTE_HAS_CHILDREN 0x00020000 FILE_ATTRIBUTE_SHORTCUT */ std::string fileflags(DWORD dwAttr) { std::string attr; attr += (dwAttr&FILE_ATTRIBUTE_DIRECTORY) ? 'd' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_ARCHIVE) ? 'a' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_READONLY) ? 'r' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_HIDDEN) ? 'h' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_SYSTEM) ? 's' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_NORMAL) ? 'n' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_INROM) ? 'R' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_COMPRESSED) ? 'c' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_ROMMODULE) ? 'm' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_SPARSE_FILE) ? 'S' : '-'; attr += (dwAttr&FILE_ATTRIBUTE_REPARSE_POINT) ? 'p' : '-'; DWORD dwAll=FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_INROM|FILE_ATTRIBUTE_COMPRESSED|FILE_ATTRIBUTE_ROMMODULE|FILE_ATTRIBUTE_SPARSE_FILE|FILE_ATTRIBUTE_REPARSE_POINT; if (dwAttr&~dwAll) { attr += stringformat("[%08lx]", dwAttr&~dwAll); } return attr; } std::string MakeFileLine(const CE_FIND_DATA& wfd, const std::string& name) { std::string line; if (g_bVerbose) line= fileflags(wfd.dwFileAttributes)+" "; #ifdef _WIN32 SYSTEMTIME systime; FILETIME lfiletime; FileTimeToLocalFileTime(&wfd.ftLastWriteTime, &lfiletime); FileTimeToSystemTime(&lfiletime, &systime); line += stringformat("%04d-%02d-%02d %02d:%02d:%02d.%03d", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond,systime.wMilliseconds); #else time_t t= filetimetounix(&wfd.ftLastWriteTime); struct tm *tm=localtime(&t); line += stringformat("%04d-%02d-%02d %02d:%02d:%02d.%03d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, 0); #endif if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) line += stringformat(" %s\\", name.c_str()); else { // ignoring the possibility of 4G+ files on portable devices for now. line += stringformat(" %7d %s", wfd.nFileSizeLow, name.c_str()); } return line; } bool CeFileGlob(const std::string& name, StringStringMap& filelist, StringStringMap& dirlist) { CE_FIND_DATA wfd; std::Wstring wname= ToWString(name); std::Wstring ewname= expand_csidl(ToWString(name)); HANDLE hFind = CeFindFirstFile( (WCHAR*)expand_csidl(ToWString(name)).c_str(), &wfd); if (INVALID_HANDLE_VALUE == hFind) return false; std::string rootpath= GetBasePath(name); do { std::string fullpath= concat_path(rootpath, ToString(wfd.cFileName)); if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) dirlist[fullpath]= MakeFileLine(wfd, fullpath); else filelist[fullpath]= MakeFileLine(wfd, fullpath); } while (CeFindNextFile(hFind, &wfd)); CeFindClose(hFind); return true; } bool ProcessDirectory(const std::string& name, int level= 0) { StringStringMap files; StringStringMap subdirs; if (!CeFileGlob(concat_path(name,"*"), files, subdirs)) return false; for (StringStringMap::iterator i= files.begin() ; i!=files.end() ; ++i) printf("%s\n", (*i).second.c_str()); bool bOk= true; for (StringStringMap::iterator i= subdirs.begin() ; i!=subdirs.end() ; ++i) { printf("%s\n", (*i).second.c_str()); if (g_bRecurse) { // problem: CeFileGlob means both invalid path, and zero files /* bOk = bOk && */ ProcessDirectory((*i).first, level+1); } } return bOk; } bool ProcessFile(const std::string& name) { CE_FIND_DATA wfd; HANDLE hFind = CeFindFirstFile( (WCHAR*)expand_csidl(ToWString(name)).c_str(), &wfd); if (INVALID_HANDLE_VALUE == hFind) return false; printf("%s\n", MakeFileLine(wfd, name).c_str()); return true; } bool hasWildCards(const std::string& name) { return name.find_first_of("*?")!=name.npos; } bool ProcessName(const std::string& name) { int type= getCeAttributes(name); if (type==AT_ISDIRECTORY) return ProcessDirectory(name); else if (type==AT_ISFILE) return ProcessFile(name); else { printf("%s not found\n", name.c_str()); return false; } } void usage() { printf("(C) 2003-2008 Willem jan Hengeveld itsme@xs4all.nl\n"); printf("Usage: pdir [-r] dir ...\n"); printf(" -l to list special paths\n"); printf(" -r recurse into directories\n"); printf(" -v verbose listing: with file attributes\n"); } int main( int argc, char *argv[]) { DebugStdOut(); StringList dirlist; bool do_list_csidl_paths= false; for (int i=1 ; i