<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>filemgr.cpp Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.2.15 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="namespaces.html">Namespace List</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="classes.html">Alphabetical List</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Compound Members</a> </center> <hr><h1>filemgr.cpp</h1><div class="fragment"><pre>00001 <font class="comment">/******************************************************************************</font> 00002 <font class="comment"> * filemgr.cpp - implementation of class FileMgr used for pooling file</font> 00003 <font class="comment"> * handles</font> 00004 <font class="comment"> *</font> 00005 <font class="comment"> * $Id: filemgr_8cpp-source.html,v 1.3 2002/06/20 20:23:08 mgruner Exp $</font> 00006 <font class="comment"> *</font> 00007 <font class="comment"> * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org)</font> 00008 <font class="comment"> * CrossWire Bible Society</font> 00009 <font class="comment"> * P. O. Box 2528</font> 00010 <font class="comment"> * Tempe, AZ 85280-2528</font> 00011 <font class="comment"> *</font> 00012 <font class="comment"> * This program is free software; you can redistribute it and/or modify it</font> 00013 <font class="comment"> * under the terms of the GNU General Public License as published by the</font> 00014 <font class="comment"> * Free Software Foundation version 2.</font> 00015 <font class="comment"> *</font> 00016 <font class="comment"> * This program is distributed in the hope that it will be useful, but</font> 00017 <font class="comment"> * WITHOUT ANY WARRANTY; without even the implied warranty of</font> 00018 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</font> 00019 <font class="comment"> * General Public License for more details.</font> 00020 <font class="comment"> *</font> 00021 <font class="comment"> */</font> 00022 00023 <font class="preprocessor">#include <filemgr.h></font> 00024 <font class="preprocessor">#include <utilstr.h></font> 00025 00026 <font class="preprocessor">#include <dirent.h></font> 00027 <font class="preprocessor">#include <fcntl.h></font> 00028 <font class="preprocessor">#include <sys/stat.h></font> 00029 <font class="preprocessor">#include <sys/types.h></font> 00030 <font class="preprocessor">#include <stdio.h></font> 00031 <font class="preprocessor">#include <string.h></font> 00032 <font class="preprocessor">#ifndef __GNUC__</font> 00033 <font class="preprocessor"></font><font class="preprocessor">#include <io.h></font> 00034 <font class="preprocessor">#else</font> 00035 <font class="preprocessor"></font><font class="preprocessor">#include <unistd.h></font> 00036 <font class="preprocessor">#endif</font> 00037 <font class="preprocessor"></font> 00038 <font class="comment">// ---------------- statics -----------------</font> 00039 FileMgr FileMgr::systemFileMgr; 00040 00041 <font class="comment">// --------------- end statics --------------</font> 00042 00043 00044 FileDesc::FileDesc(FileMgr *parent, <font class="keywordtype">char</font> *path, <font class="keywordtype">int</font> mode, <font class="keywordtype">int</font> perms, <font class="keywordtype">bool</font> tryDowngrade) { 00045 this->parent = parent; 00046 this->path = 0; 00047 stdstr(&this->path, path); 00048 this->mode = mode; 00049 this->perms = perms; 00050 this->tryDowngrade = tryDowngrade; 00051 offset = 0; 00052 fd = -77; 00053 } 00054 00055 00056 FileDesc::~FileDesc() { 00057 <font class="keywordflow">if</font> (fd > 0) 00058 close(fd); 00059 00060 <font class="keywordflow">if</font> (path) 00061 <font class="keyword">delete</font> [] path; 00062 } 00063 00064 00065 <font class="keywordtype">int</font> FileDesc::getFd() { 00066 <font class="keywordflow">if</font> (fd == -77) 00067 fd = parent->sysOpen(<font class="keyword">this</font>); 00068 <font class="keywordflow">return</font> fd; 00069 } 00070 00071 00072 FileMgr::FileMgr(<font class="keywordtype">int</font> maxFiles) { 00073 this->maxFiles = maxFiles; <font class="comment">// must be at least 2</font> 00074 files = 0; 00075 } 00076 00077 00078 FileMgr::~FileMgr() { 00079 FileDesc *tmp; 00080 00081 <font class="keywordflow">while</font>(files) { 00082 tmp = files->next; 00083 <font class="keyword">delete</font> files; 00084 files = tmp; 00085 } 00086 } 00087 00088 00089 FileDesc *FileMgr::open(<font class="keywordtype">char</font> *path, <font class="keywordtype">int</font> mode, <font class="keywordtype">bool</font> tryDowngrade) { 00090 <font class="keywordflow">return</font> open(path, mode, S_IREAD | S_IWRITE, tryDowngrade); 00091 } 00092 00093 FileDesc *FileMgr::open(<font class="keywordtype">char</font> *path, <font class="keywordtype">int</font> mode, <font class="keywordtype">int</font> perms, <font class="keywordtype">bool</font> tryDowngrade) { 00094 FileDesc **tmp, *tmp2; 00095 00096 <font class="keywordflow">for</font> (tmp = &files; *tmp; tmp = &((*tmp)->next)) { 00097 <font class="keywordflow">if</font> ((*tmp)->fd < 0) <font class="comment">// insert as first non-system_open file</font> 00098 <font class="keywordflow">break</font>; 00099 } 00100 00101 tmp2 = <font class="keyword">new</font> FileDesc(<font class="keyword">this</font>, path, mode, perms, tryDowngrade); 00102 tmp2->next = *tmp; 00103 *tmp = tmp2; 00104 00105 <font class="keywordflow">return</font> tmp2; 00106 } 00107 00108 00109 <font class="keywordtype">void</font> FileMgr::close(FileDesc *file) { 00110 FileDesc **loop; 00111 00112 <font class="keywordflow">for</font> (loop = &files; *loop; loop = &((*loop)->next)) { 00113 <font class="keywordflow">if</font> (*loop == file) { 00114 *loop = (*loop)->next; 00115 <font class="keyword">delete</font> file; 00116 <font class="keywordflow">break</font>; 00117 } 00118 } 00119 } 00120 00121 00122 <font class="comment">// to truncate a file at its current position</font> 00123 <font class="comment">// leaving byte at current possition intact</font> 00124 <font class="comment">// deleting everything afterward.</font> 00125 <font class="keywordtype">signed</font> <font class="keywordtype">char</font> FileMgr::trunc(FileDesc *file) { 00126 00127 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">char</font> *writeTest = <font class="stringliteral">"x"</font>; 00128 <font class="keywordtype">long</font> size = lseek(file->getFd(), 1, SEEK_CUR); 00129 <font class="keywordtype">char</font> nibble [ 32767 ]; 00130 <font class="keywordtype">bool</font> writable = write(file->getFd(), writeTest, 1); 00131 <font class="keywordtype">int</font> bytes = 0; 00132 00133 <font class="keywordflow">if</font> (writable) { 00134 <font class="comment">// get tmpfilename</font> 00135 <font class="keywordtype">char</font> *buf = <font class="keyword">new</font> <font class="keywordtype">char</font> [ strlen(file->path) + 10 ]; 00136 <font class="keywordtype">int</font> i; 00137 <font class="keywordflow">for</font> (i = 0; i < 9999; i++) { 00138 sprintf(buf, <font class="stringliteral">"%stmp%.4d"</font>, file->path, i); 00139 <font class="keywordflow">if</font> (!existsFile(buf)) 00140 <font class="keywordflow">break</font>; 00141 } 00142 <font class="keywordflow">if</font> (i == 9999) 00143 <font class="keywordflow">return</font> -2; 00144 00145 <font class="keywordtype">int</font> fd = ::open(buf, O_CREAT|O_RDWR, S_IREAD|S_IWRITE); 00146 <font class="keywordflow">if</font> (fd < 0) 00147 <font class="keywordflow">return</font> -3; 00148 00149 lseek(file->getFd(), 0, SEEK_SET); 00150 <font class="keywordflow">while</font> (size > 0) { 00151 bytes = read(file->getFd(), nibble, 32767); 00152 write(fd, nibble, (bytes < size)?bytes:size); 00153 size -= bytes; 00154 } 00155 <font class="comment">// zero out the file</font> 00156 ::close(file->fd); 00157 file->fd = ::open(file->path, O_TRUNC, S_IREAD|S_IWRITE); 00158 ::close(file->fd); 00159 file->fd = -77; <font class="comment">// force file open by filemgr</font> 00160 <font class="comment">// copy tmp file back (dumb, but must preserve file permissions)</font> 00161 lseek(fd, 0, SEEK_SET); 00162 <font class="keywordflow">do</font> { 00163 bytes = read(fd, nibble, 32767); 00164 write(file->getFd(), nibble, bytes); 00165 } <font class="keywordflow">while</font> (bytes == 32767); 00166 00167 ::close(fd); 00168 ::close(file->fd); 00169 unlink(buf); <font class="comment">// remove our tmp file</font> 00170 file->fd = -77; <font class="comment">// causes file to be swapped out forcing open on next call to getFd()</font> 00171 } 00172 <font class="keywordflow">else</font> { <font class="comment">// put offset back and return failure</font> 00173 lseek(file->getFd(), -1, SEEK_CUR); 00174 <font class="keywordflow">return</font> -1; 00175 } 00176 <font class="keywordflow">return</font> 0; 00177 } 00178 00179 00180 <font class="keywordtype">int</font> FileMgr::sysOpen(FileDesc *file) { 00181 FileDesc **loop; 00182 <font class="keywordtype">int</font> openCount = 1; <font class="comment">// because we are presently opening 1 file, and we need to be sure to close files to accomodate, if necessary</font> 00183 00184 <font class="keywordflow">for</font> (loop = &files; *loop; loop = &((*loop)->next)) { 00185 00186 <font class="keywordflow">if</font> ((*loop)->fd > 0) { 00187 <font class="keywordflow">if</font> (++openCount > maxFiles) { 00188 (*loop)->offset = lseek((*loop)->fd, 0, SEEK_CUR); 00189 ::close((*loop)->fd); 00190 (*loop)->fd = -77; 00191 } 00192 } 00193 00194 <font class="keywordflow">if</font> (*loop == file) { 00195 <font class="keywordflow">if</font> (*loop != files) { 00196 *loop = (*loop)->next; 00197 file->next = files; 00198 files = file; 00199 } 00200 <font class="keywordflow">if</font> ((!access(file->path, 04)) || ((file->mode & O_CREAT) == O_CREAT)) { <font class="comment">// check for at least file exists / read access before we try to open</font> 00201 <font class="keywordtype">char</font> tries = (((file->mode & O_RDWR) == O_RDWR) && (file->tryDowngrade)) ? 2 : 1; <font class="comment">// try read/write if possible</font> 00202 <font class="keywordflow">for</font> (<font class="keywordtype">int</font> i = 0; i < tries; i++) { 00203 <font class="keywordflow">if</font> (i > 0) { 00204 file->mode = (file->mode & ~O_RDWR); <font class="comment">// remove write access</font> 00205 file->mode = (file->mode | O_RDONLY);<font class="comment">// add read access</font> 00206 } 00207 file->fd = ::open(file->path, file->mode, file->perms); 00208 00209 <font class="keywordflow">if</font> (file->fd >= 0) 00210 <font class="keywordflow">break</font>; 00211 } 00212 00213 <font class="keywordflow">if</font> (file->fd >= 0) 00214 lseek(file->fd, file->offset, SEEK_SET); 00215 } 00216 <font class="keywordflow">else</font> file->fd = -1; 00217 <font class="keywordflow">if</font> (!*loop) 00218 <font class="keywordflow">break</font>; 00219 } 00220 } 00221 <font class="keywordflow">return</font> file->fd; 00222 } 00223 00224 00225 <font class="keywordtype">signed</font> <font class="keywordtype">char</font> FileMgr::existsFile(<font class="keyword">const</font> <font class="keywordtype">char</font> *ipath, <font class="keyword">const</font> <font class="keywordtype">char</font> *ifileName) 00226 { 00227 <font class="keywordtype">int</font> len = strlen(ipath) + ((ifileName)?strlen(ifileName):0) + 3; 00228 <font class="keywordtype">char</font> *ch; 00229 <font class="keywordtype">char</font> *path = <font class="keyword">new</font> <font class="keywordtype">char</font> [ len ]; 00230 strcpy(path, ipath); 00231 00232 <font class="keywordflow">if</font> ((path[strlen(path)-1] == <font class="charliteral">'\\'</font>) || (path[strlen(path)-1] == <font class="charliteral">'/'</font>)) 00233 path[strlen(path)-1] = 0; 00234 00235 <font class="keywordflow">if</font> (ifileName) { 00236 ch = path + strlen(path); 00237 sprintf(ch, <font class="stringliteral">"/%s"</font>, ifileName); 00238 } 00239 <font class="keywordtype">signed</font> <font class="keywordtype">char</font> retVal = !access(path, 04); 00240 <font class="keyword">delete</font> [] path; 00241 <font class="keywordflow">return</font> retVal; 00242 } 00243 00244 00245 <font class="keywordtype">signed</font> <font class="keywordtype">char</font> FileMgr::existsDir(<font class="keyword">const</font> <font class="keywordtype">char</font> *ipath, <font class="keyword">const</font> <font class="keywordtype">char</font> *idirName) 00246 { 00247 <font class="keywordtype">char</font> *ch; 00248 <font class="keywordtype">int</font> len = strlen(ipath) + ((idirName)?strlen(idirName):0) + 1; 00249 <font class="keywordflow">if</font> (idirName) 00250 len += strlen(idirName); 00251 <font class="keywordtype">char</font> *path = <font class="keyword">new</font> <font class="keywordtype">char</font> [ len ]; 00252 strcpy(path, ipath); 00253 00254 <font class="keywordflow">if</font> ((path[strlen(path)-1] == <font class="charliteral">'\\'</font>) || (path[strlen(path)-1] == <font class="charliteral">'/'</font>)) 00255 path[strlen(path)-1] = 0; 00256 00257 <font class="keywordflow">if</font> (idirName) { 00258 ch = path + strlen(path); 00259 sprintf(ch, <font class="stringliteral">"/%s"</font>, idirName); 00260 } 00261 <font class="keywordtype">signed</font> <font class="keywordtype">char</font> retVal = !access(path, 04); 00262 <font class="keyword">delete</font> [] path; 00263 <font class="keywordflow">return</font> retVal; 00264 } </pre></div><hr><address align="right"><small>Generated on Thu Jun 20 22:12:59 2002 for The Sword Project by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.15 </small></address> </body> </html>