/////////////////////////////////////////////////////////////// // dirs.cpp - File and Directory Operations // // ver 1.0 // // // // Language: Visual C++, ver 6.0 // // Platform: Micron Dual Pentium Pro 200, WinNT 4.0 // // Application: CSE691 demo // // Author: Jim Fawcett, CST 2-187, Syracuse Univ // // (315) 443-3948, fawcett@ecs.syr.edu // /////////////////////////////////////////////////////////////// #include #include #include #include "dirs.h" using namespace std; //----< get full path name >----------------------------------- string directory::fullPathName(const string &name) { char buffer[MAX_PATH]; char *filePart = NULL; if(::GetFullPathName(".",MAX_PATH,buffer,&filePart)) return buffer; else { _error = true; _type = "can't get path name from "; _type += name; return ""; } } //----< create directory >------------------------------------- bool directory::createDir(const string &dirName) { // string current = fullPathName("."); // current += '\\'; // current += dirName; if(!::CreateDirectory(dirName.c_str(),NULL)) { _error = true; _type = "failure to create directory"; return false; } _error = false; _type = ""; return true; } // //----< file constructor >------------------------------------- file::file(const string &name) : _name(name), _finding(false), _found(false), _hFile(INVALID_HANDLE_VALUE), _date(""), _time(""), _RWattrib(GENERIC_READ | GENERIC_WRITE), _SHattrib(0), _CRattrib(CREATE_NEW), _pSecurity(NULL) { directory temp; if(name.size() > 0) _path = temp.fullPathName(name); else _path = temp.fullPathName("."); _validOp(); } //----< return path part of full path >------------------------ string file::stripPath(const string &fullPath) { string strip = fullPath; size_t pos = strip.find_last_of('\\'); if(pos < strip.size()) strip.resize(pos); else { directory dir; strip = dir.fullPathName("."); } return strip; } // //----< find file from file name pattern >--------------------- bool file::find(const string &pattern) { if(!_finding) { _search = ::FindFirstFile(pattern.c_str(),&_findData); if(_search == INVALID_HANDLE_VALUE) { _invalidOp("file not found"); return false; } _finding = _found = true; _path = stripPath(pattern); _getName(); _getAttrib(); _getSize(); _getDate(); _getTime(); _validOp(); return true; } else { if(!::FindNextFile(_search,&_findData)) { closeFind(); _invalidOp("search finished"); return false; } } _path = stripPath(pattern); _getName(); _getAttrib(); _getSize(); _getDate(); _getTime(); _validOp(); return true; } //----< set internal file name >------------------------------- void file::_getName() { if(!_found) { _invalidOp("file not found"); _name = ""; return; } _name = string(_findData.cFileName); } // //----< set internal attribute >------------------------------- void file::_getAttrib() { if(!_found) { _invalidOp("file not found"); _attrib = 0; return; } _attrib = _findData.dwFileAttributes; } //----< set internal file size >------------------------------- void file::_getSize() { if(!_found) { _invalidOp("file not found"); _size = 0; return; } if(_findData.nFileSizeHigh != 0) { _invalidOp("file size too large"); _size = 0; return; } _size = _findData.nFileSizeLow; _validOp(); } //----< set internal file date >------------------------------- void file::_getDate() { if(!_found) { _invalidOp("file not found"); _date = ""; return; } FILETIME localFT, modifiedFT = _findData.ftLastWriteTime; FileTimeToLocalFileTime(&modifiedFT,&localFT); SYSTEMTIME st; FileTimeToSystemTime(&localFT,&st); ostrstream format; format.fill('0'); format << setw(2) << st.wMonth << '/' << setw(2) << st.wDay << '/' << st.wYear << ends; _date = format.str(); _validOp(); } // //----< set internal file time >------------------------------- void file::_getTime() { if(!_found) { _invalidOp("file not found"); _time = ""; return; } FILETIME localFT, modifiedFT = _findData.ftLastWriteTime; FileTimeToLocalFileTime(&modifiedFT,&localFT); SYSTEMTIME st; FileTimeToSystemTime(&localFT,&st); int hours; string AMPM; if(st.wHour > 11 && st.wMinute > 0) AMPM = " PM"; else AMPM = " AM"; if(st.wHour > 12) hours = st.wHour-12; else hours = st.wHour; ostrstream format; format.fill('0'); format << setw(2) << hours << ':' << setw(2) << st.wMinute << ':' << setw(2) << st.wSecond << AMPM << ends; _time = format.str(); _validOp(); } //----< return file name >------------------------------------- string file::name() { if(_found) { _validOp(); return _name; } _invalidOp("file not found"); return ""; } //----< return file size >------------------------------------- long int file::size() { if(_found) { _validOp(); return _size; } _invalidOp("file not found"); return 0; } // //----< return file date >------------------------------------- string file::date() { if(_found) { _validOp(); return _date; } _invalidOp("file not found"); return ""; } //----< return file time >------------------------------------- string file::time() { if(_found) { _validOp(); return _time; } _invalidOp("file not found"); return ""; } //----< return file information string >----------------------- string file::getFileInfo() { if(!_found) { _invalidOp("file not found"); return "file not found"; } ostrstream out1; out1.setf(ios::adjustfield,ios::right); out1 << date() << " " << time() << " " << setw(8) << size() << ends; ostrstream out2; out2.setf(ios::adjustfield,ios::left); out2 << " " << setw(15) << name() << ends; string out(100,' '); out = out1.str(); out += out2.str(); return out.c_str(); } //----< is this object a directory? >-------------------------- bool file::isDir() { if(!_found) { _invalidOp("file not found"); return false; } if(_attrib & FILE_ATTRIBUTE_DIRECTORY) return true; return false; } // //----< is this object a file? >------------------------------- bool file::isFile() { if(!_found) { _invalidOp("file not found"); return false; } if(_attrib & FILE_ATTRIBUTE_DIRECTORY) return false; if(_attrib & FILE_ATTRIBUTE_REPARSE_POINT) return false; return true; } //----< return file attributes string >------------------------ string file::getAttribs() { if(!_found) { _invalidOp("file not found"); return "no attributes"; } if(_attrib == 0xFFFFFFFF) { _invalidOp("bad file attributes"); return "bad file attributes"; } ostrstream out; if(FILE_ATTRIBUTE_ARCHIVE & _attrib) out << "archive "; if(FILE_ATTRIBUTE_COMPRESSED & _attrib) out << "compressed "; if(FILE_ATTRIBUTE_DIRECTORY & _attrib) out << "directory "; if(FILE_ATTRIBUTE_ENCRYPTED & _attrib) out << "encrypted "; if(FILE_ATTRIBUTE_HIDDEN & _attrib) out << "hidden "; if(FILE_ATTRIBUTE_NORMAL & _attrib) out << "normal "; if(FILE_ATTRIBUTE_OFFLINE & _attrib) out << "offline "; if(FILE_ATTRIBUTE_READONLY & _attrib) out << "readonly "; if(FILE_ATTRIBUTE_REPARSE_POINT & _attrib) out << "reparse_point "; if(FILE_ATTRIBUTE_SPARSE_FILE & _attrib) out << "sparse_file "; if(FILE_ATTRIBUTE_SYSTEM & _attrib) out << "system "; if(FILE_ATTRIBUTE_TEMPORARY & _attrib) out << "temporary "; out << ends; return out.str(); } // //----< set attributes for reading or writing file >----------- bool file::setRWAttrib(DWORD attrib) { bool ok = false; if(attrib | GENERIC_READ ) ok = true; if(attrib | GENERIC_WRITE) ok = true; if(ok) { _RWattrib = attrib; _validOp(); return true; } ok = false; if(attrib | FILE_SHARE_DELETE) ok = true; if(attrib | FILE_SHARE_READ ) ok = true; if(attrib | FILE_SHARE_WRITE ) ok = true; if(ok) { _SHattrib = attrib; _validOp(); return true; } _RWattrib = 0; _SHattrib = 0; _invalidOp("bad READ, WRITE, or SHARE attribute"); return false; } //----< set attributes for creation >-------------------------- bool file::setCRAttrib(DWORD attrib) { bool ok = false; if(attrib | CREATE_NEW ) ok = true; if(attrib | CREATE_ALWAYS ) ok = true; if(attrib | OPEN_EXISTING ) ok = true; if(attrib | OPEN_ALWAYS ) ok = true; if(attrib | TRUNCATE_EXISTING) ok = true; if(ok) { _CRattrib = attrib; _validOp(); return true; } _CRattrib = 0; _invalidOp("bad CREATE, OPEN, or TRUNCATE attribute"); return false; } // //----< create file >------------------------------------------ bool file::createFile(const string &name) { string path; if(name == "") { path = _path; path += '\\'; path += _name; } else { path = name; } DWORD attrib = FILE_ATTRIBUTE_NORMAL; HANDLE templateFile = NULL; _hFile = ::CreateFile( path.c_str(),_RWattrib,_SHattrib,_pSecurity, _CRattrib,attrib,templateFile ); if(_hFile == INVALID_HANDLE_VALUE) { _invalidOp("file not created"); return false; } _validOp(); return true; } // #ifdef TEST_DIRS //----< test stub >-------------------------------------------- // // assumes that: // - argv[1] is the name of destination file // - argv[2] is the name of source file // void main(int argc, char *argv[]) { cout << "\n Testing File and Directory Operations " << "\n =======================================\n"; if(argc < 3) { cout << "\n please enter name of destination file and source file\n"; return; } cout << "\n testing path and directory operations " << "\n ---------------------------------------"; directory dir; // show current path cout << "\n current path: \"" << dir.fullPathName(".") <<"\""; if(dir.error()) { cout << "\n dir::error = " << dir.errorType() << "\n\n"; return; } // set up destination directory string srcPath = dir.fullPathName("."); string destPath = srcPath + "\\temp"; cout << "\n source directory: \"" << srcPath.c_str() << "\""; if(dir.createDir(destPath)) cout << "\n new destination dir: \"" << destPath.c_str() << "\""; else cout << "\n destination directory: \"" << destPath.c_str() << "\" already exists"; cout << '\n'; // cout << "\n testing file operations " << "\n -------------------------"; // set up destination file file dfl; string destFile = destPath + string("\\") + string(argv[1]); if(dfl.find(destFile)) { dfl.closeFind(); cout << "\n destination file: \"" << dfl.name().c_str() << "\"" << "\n found on path: \"" << dfl.path().c_str() << "\""; } else cout << "\n destination file: \"" << destFile << "\" not found"; dfl.setRWAttrib(GENERIC_WRITE); dfl.setCRAttrib(CREATE_ALWAYS); if(dfl.createFile(destFile)) { dfl.find(destFile); cout << "\n file action: \"" << dfl.name().c_str() << "\" created"; } else cout << "\n file action: \"" << dfl.name().c_str() << "\" create failed"; if(dfl.fileHandle() == INVALID_HANDLE_VALUE) { cout << "\n can't open file \"" << dfl.name().c_str() << "\" for writing\n\n"; return; } cout << '\n'; // set up source file file sfl; string srcFile = srcPath + string("\\") + string(argv[2]); if(sfl.find(srcFile)) { sfl.closeFind(); cout << "\n source file: \"" << sfl.name().c_str() << "\"" << "\n found on path: \"" << sfl.path().c_str() << "\""; } else cout << "\n source file: \"" << destFile << "\" not found"; sfl.setRWAttrib(GENERIC_READ ); sfl.setCRAttrib(OPEN_EXISTING); if(sfl.createFile()) cout << "\n file action: \"" << sfl.name().c_str() << "\" opened"; else cout << "\n file action: : \"" << sfl.name().c_str() << "\" open failed"; if(sfl.fileHandle() == INVALID_HANDLE_VALUE) { cout << "\n can't open file \"" << sfl.name().c_str() << "\" for reading\n\n"; return; } cout << '\n'; // cout << "\n testing file read and write operations " << "\n ----------------------------------------"; // setup notify mechanism so program will wait for changes to be // registered with file system before extracting file statistics HANDLE hNotify = FindFirstChangeNotification( destPath.c_str(),FALSE,FILE_NOTIFY_CHANGE_SIZE ); // start copying const int blockSize = 256; char block[blockSize]; cout << "\n copying file in " << blockSize << " byte blocks:"; DWORD bytesRead, bytesWritten, sumBytes=0; do { if(!::ReadFile(sfl.fileHandle(),block,blockSize,&bytesRead,NULL)) { cout << "\n\n error reading source file \"" << srcFile << "\"\n\n"; return; } if(bytesRead == 0) break; if(!::WriteFile(dfl.fileHandle(),block,bytesRead,&bytesWritten,NULL)) { cout << "\n\n error writing destination file \"" << destFile << "\"\n\n"; return; } sumBytes += bytesWritten; } while(bytesWritten > 0); cout << "\n copied " << sumBytes << " bytes to destination file"; cout << '\n'; cout << "\n testing file information extraction " << "\n -------------------------------------"; // show stats cout << "\n source file information:" << "\n " << sfl.getFileInfo() << "\n " << sfl.getAttribs(); cout.flush(); // wait for new file size to be recorded in file system statistics WaitForSingleObject(hNotify,INFINITE); // gather revised file statistics dfl.closeFind(); dfl.find(destFile); cout << "\n destination file information:" << "\n " << dfl.getFileInfo() << "\n " << dfl.getAttribs(); cout << '\n'; // cout << "\n testing file pattern searches " << "\n -------------------------------\n"; cout << "\n for the file pattern \"*.*\" in " << sfl.path(); while(sfl.find("*.*")) cout << "\n " << sfl.getFileInfo() << " - " << sfl.getAttribs(); sfl.closeFind(); cout << '\n'; cout << "\n for the file pattern \"..\\*.\" in " << sfl.path(); while(sfl.find("..\\*.")) cout << "\n " << sfl.getFileInfo() << " - " << sfl.getAttribs(); cout << '\n'; cout << "\n testing file error handling " << "\n -----------------------------\n"; if(sfl.error()) cout << "\n last error = " << sfl.errorType(); sfl.clear(); if(sfl.error()) cout << "\n last error = " << sfl.errorType(); else cout << "\n after clearing no error found"; file errFl; errFl.find("foo"); cout << "\n attempting to find file \"foo\"" << "\n " << errFl.getFileInfo() << " - " << errFl.getAttribs(); if(errFl.error()) cout << "\n last error = " << errFl.errorType(); cout << "\n\n"; } #endif