00001 // Copyright (C) 2001, Compaq Computer Corporation 00002 00003 // This file is part of Vesta. 00004 00005 // Vesta is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 00010 // Vesta is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with Vesta; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 // FS.H -- a simple exception-based interface to the file system 00020 00021 #ifndef _FS_H 00022 #define _FS_H 00023 00024 #include <sys/stat.h> // mode constants 00025 #include <errno.h> // defines "errno" global 00026 #include <Basics.H> 00027 00028 namespace FS 00029 { 00030 // exceptions 00031 class Error {}; 00032 class EndOfFile : Error {}; 00033 class DoesNotExist : Error {}; 00034 class AlreadyExists : Error {}; 00035 class Failure : Error { 00036 public: 00037 Failure(const Text &opName, const Text &arg = "<none>") throw () 00038 : opName(opName), arg(arg), FSerrno(errno) { } 00039 Failure(const Text &opName, const Text &arg, int err_no) throw () 00040 : opName(opName), arg(arg), FSerrno(err_no) { } 00041 00042 // Allow constructing an uninitialized Failure and assignment 00043 // for buffering a failure. 00044 Failure() throw() 00045 : FSerrno(0) {} 00046 inline Failure & operator=(const Failure &other) 00047 { 00048 opName = other.opName; 00049 arg = other.arg; 00050 FSerrno = other.FSerrno; 00051 return *this; 00052 } 00053 00054 // Accessors for the member variables 00055 inline int get_errno() const { return this->FSerrno; } 00056 inline const Text &get_op() const { return this->opName; } 00057 inline const Text &get_arg() const { return this->arg; } 00058 00059 private: 00060 int FSerrno; // Unix error number 00061 Text opName; // name of operation causing failure 00062 Text arg; // argument string 00063 }; 00064 00065 // methods 00066 void OpenReadOnly(const Text &fname, /*OUT*/ std::ifstream &ifs) 00067 throw (DoesNotExist, Failure); 00068 /* REQUIRES Unopened(ifs) */ 00069 /* Open the (existing) file named "fname" for reading, and set "ifs" to an 00070 input file stream on that file. The stream initially points at the 00071 start of the file. Throw "DoesNotExist" if the file could not be found; 00072 throw "Failure" with the associated error code in the event of any 00073 other failure. */ 00074 00075 void OpenForWriting(const Text &fname, /*OUT*/ std::ofstream &ofs) 00076 throw (Failure); 00077 /* REQUIRES Unopened(ofs) */ 00078 /* Open the file named "fname" for writing, and set "ofs" to an output 00079 file stream on that file. If the file does not exist, it is created. 00080 If it exists, the file is truncated. */ 00081 00082 void Seek(std::istream &ifs, std::streamoff offset, 00083 std::ios::seekdir orig = std::ios::beg) throw (Failure); 00084 void Seek(std::ostream &ofs, std::streamoff offset, 00085 std::ios::seekdir orig = std::ios::beg) throw (Failure); 00086 /* Seek to position "offset" relative to position "orig" in the input 00087 stream "ifs" or the output stream "ofs". If "orig" is "std::ios::beg", then 00088 offset is the number of bytes from the start of the file, if "orig" is 00089 "std::ios::cur", then offset is the number of bytes relative to the current 00090 position, and if "orig" is "std::ios::end", the offset is the number of 00091 bytes from the end of the file (with positive offsets counting 00092 backwards). Throws "Failure" in the event of a failure, in which case 00093 the position of "fd" within the file is unchanged. */ 00094 00095 std::streampos Posn(std::istream &ifs) throw (Failure); 00096 std::streampos Posn(std::ostream &ofs) throw (Failure); 00097 /* Return the current position in the input stream "ifs" or the output 00098 stream "ofs". Throws "FS::Failure" in the event of failure. */ 00099 00100 void Read(std::istream &ifs, char *buff, int n) 00101 throw (EndOfFile, Failure); 00102 /* Read "n" bytes from "ifs" into "buff". Throw "EndOfFile" if less than 00103 "n" bytes are available. Throw "Failure" in the event of any other 00104 failure. */ 00105 00106 void Write(std::ostream &ofs, char *buff, int n) throw (Failure); 00107 /* Write the "n" bytes pointed to by "buff" to "ofs". Throw "Failure" in 00108 the event of an I/O failure. */ 00109 00110 void Copy(std::istream &ifs, std::ostream &ofs, int len) 00111 throw (EndOfFile, Failure); 00112 /* Copy "len" bytes from "ifs" to "ofs". */ 00113 00114 bool AtEOF(std::istream &is) throw (); 00115 /* Return 'true' iff 'is' is at end-of-file. This is the case if the 00116 'eof' bit of 'is' is set, or if there are no more characters to be 00117 read from 'is'. Requires that no other error bits are set in 'is'. */ 00118 00119 void Flush(std::ostream &ofs) throw (Failure); 00120 /* Flush buffered write data for "ofs". Throw "Failure" in 00121 the event of an I/O failure. */ 00122 00123 void Close(std::ifstream &ifs) throw (Failure); 00124 void Close(std::ofstream &ofs) throw (Failure); 00125 void Close(std::fstream &fs) throw (Failure); 00126 /* Close the input stream "ifs", output stream "ofs", or I/O stream "fs". 00127 This invokes the stream's "close" method, and then throws "Failure" if 00128 the method failed. */ 00129 00130 void Delete(const Text &fname) throw (Failure); 00131 /* Delete the file named "fname". Throws "Failure" in the event of some 00132 filesystem error. */ 00133 00134 bool DeleteDir(const Text &dirname) throw (Failure); 00135 /* Atomically test if the directory "dirname" is empty, and if so, delete 00136 it and return true. If it is non-empty, return false. If "dirname" does 00137 not name a directory or if any other filesystem error occurs, throw 00138 "Failure". */ 00139 00140 bool Exists(const Text &fname) throw (); 00141 /* Test whether the given path exists. */ 00142 00143 bool IsFile(const Text &fname) throw (); 00144 /* Test whether the given path exists and is a regular file. */ 00145 00146 bool IsDirectory(const Text &fname) throw (); 00147 /* Test whether the given path exists and is a directory. */ 00148 00149 void Touch(const Text &fname, 00150 mode_t mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), 00151 bool allowOverwrite = true) 00152 throw (AlreadyExists, Failure); 00153 /* Create a file with permissions as specified by mode. If 00154 allowOverwrite is false and the file already exists, throw 00155 "AlreadyExists". If another error occurs, throw "Failure". */ 00156 00157 Text TempFname(Text prefix, Text (*suffix_func)(), 00158 mode_t mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) 00159 throw (Failure); 00160 /* Given a path prefix and a function for generating a suffix, 00161 create a new file with a unique filename. This function will 00162 make as many attempts as necessary to find an unused 00163 filename. */ 00164 00165 Text GetAbsolutePath(const Text &fname) throw(Failure); 00166 /* Returns an absolute path equivalent to fname. (If fname is a 00167 relative path, it prepends the current working directory to 00168 it.) Doesn't check existence of fname. */ 00169 00170 Text RemoveSpecialArcs(const Text &fname) throw(); 00171 /* Remove ".", ".." and empty arcs from fname. Doesn't check 00172 existence of fname. */ 00173 00174 void SplitPath(const Text &fname, 00175 /*OUT*/ Text &name, /*OUT*/ Text &parent) throw(Failure); 00176 /* Split fname into name and parent. First, fname is converted to 00177 an equivalent absolute path. Then "name" is set to its last 00178 arc and "parent" is set to its parent directory. Doesn't check 00179 existence of fname. */ 00180 00181 Text ParentDir(const Text &fname) throw (Failure); 00182 /* Return a path to the parent directory of the given pathname. 00183 (Really just a wrapper around SplitPath.) */ 00184 } 00185 00186 std::ostream& operator<<(std::ostream &os, const FS::Failure &f) throw (); 00187 00188 #endif // _FS_H