00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <filemgr.h>
00024 #include <utilstr.h>
00025
00026 #include <dirent.h>
00027 #include <fcntl.h>
00028 #include <sys/stat.h>
00029 #include <sys/types.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #ifndef __GNUC__
00033 #include <io.h>
00034 #else
00035 #include <unistd.h>
00036 #endif
00037
00038
00039 FileMgr FileMgr::systemFileMgr;
00040
00041
00042
00043
00044 FileDesc::FileDesc(FileMgr *parent, char *path, int mode, int perms, bool 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 if (fd > 0)
00058 close(fd);
00059
00060 if (path)
00061 delete [] path;
00062 }
00063
00064
00065 int FileDesc::getFd() {
00066 if (fd == -77)
00067 fd = parent->sysOpen(this);
00068 return fd;
00069 }
00070
00071
00072 FileMgr::FileMgr(int maxFiles) {
00073 this->maxFiles = maxFiles;
00074 files = 0;
00075 }
00076
00077
00078 FileMgr::~FileMgr() {
00079 FileDesc *tmp;
00080
00081 while(files) {
00082 tmp = files->next;
00083 delete files;
00084 files = tmp;
00085 }
00086 }
00087
00088
00089 FileDesc *FileMgr::open(char *path, int mode, bool tryDowngrade) {
00090 return open(path, mode, S_IREAD | S_IWRITE, tryDowngrade);
00091 }
00092
00093 FileDesc *FileMgr::open(char *path, int mode, int perms, bool tryDowngrade) {
00094 FileDesc **tmp, *tmp2;
00095
00096 for (tmp = &files; *tmp; tmp = &((*tmp)->next)) {
00097 if ((*tmp)->fd < 0)
00098 break;
00099 }
00100
00101 tmp2 = new FileDesc(this, path, mode, perms, tryDowngrade);
00102 tmp2->next = *tmp;
00103 *tmp = tmp2;
00104
00105 return tmp2;
00106 }
00107
00108
00109 void FileMgr::close(FileDesc *file) {
00110 FileDesc **loop;
00111
00112 for (loop = &files; *loop; loop = &((*loop)->next)) {
00113 if (*loop == file) {
00114 *loop = (*loop)->next;
00115 delete file;
00116 break;
00117 }
00118 }
00119 }
00120
00121
00122
00123
00124
00125 signed char FileMgr::trunc(FileDesc *file) {
00126
00127 static const char *writeTest = "x";
00128 long size = lseek(file->getFd(), 1, SEEK_CUR);
00129 char nibble [ 32767 ];
00130 bool writable = write(file->getFd(), writeTest, 1);
00131 int bytes = 0;
00132
00133 if (writable) {
00134
00135 char *buf = new char [ strlen(file->path) + 10 ];
00136 int i;
00137 for (i = 0; i < 9999; i++) {
00138 sprintf(buf, "%stmp%.4d", file->path, i);
00139 if (!existsFile(buf))
00140 break;
00141 }
00142 if (i == 9999)
00143 return -2;
00144
00145 int fd = ::open(buf, O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
00146 if (fd < 0)
00147 return -3;
00148
00149 lseek(file->getFd(), 0, SEEK_SET);
00150 while (size > 0) {
00151 bytes = read(file->getFd(), nibble, 32767);
00152 write(fd, nibble, (bytes < size)?bytes:size);
00153 size -= bytes;
00154 }
00155
00156 ::close(file->fd);
00157 file->fd = ::open(file->path, O_TRUNC, S_IREAD|S_IWRITE);
00158 ::close(file->fd);
00159 file->fd = -77;
00160
00161 lseek(fd, 0, SEEK_SET);
00162 do {
00163 bytes = read(fd, nibble, 32767);
00164 write(file->getFd(), nibble, bytes);
00165 } while (bytes == 32767);
00166
00167 ::close(fd);
00168 ::close(file->fd);
00169 unlink(buf);
00170 file->fd = -77;
00171 }
00172 else {
00173 lseek(file->getFd(), -1, SEEK_CUR);
00174 return -1;
00175 }
00176 return 0;
00177 }
00178
00179
00180 int FileMgr::sysOpen(FileDesc *file) {
00181 FileDesc **loop;
00182 int openCount = 1;
00183
00184 for (loop = &files; *loop; loop = &((*loop)->next)) {
00185
00186 if ((*loop)->fd > 0) {
00187 if (++openCount > maxFiles) {
00188 (*loop)->offset = lseek((*loop)->fd, 0, SEEK_CUR);
00189 ::close((*loop)->fd);
00190 (*loop)->fd = -77;
00191 }
00192 }
00193
00194 if (*loop == file) {
00195 if (*loop != files) {
00196 *loop = (*loop)->next;
00197 file->next = files;
00198 files = file;
00199 }
00200 if ((!access(file->path, 04)) || ((file->mode & O_CREAT) == O_CREAT)) {
00201 char tries = (((file->mode & O_RDWR) == O_RDWR) && (file->tryDowngrade)) ? 2 : 1;
00202 for (int i = 0; i < tries; i++) {
00203 if (i > 0) {
00204 file->mode = (file->mode & ~O_RDWR);
00205 file->mode = (file->mode | O_RDONLY);
00206 }
00207 file->fd = ::open(file->path, file->mode, file->perms);
00208
00209 if (file->fd >= 0)
00210 break;
00211 }
00212
00213 if (file->fd >= 0)
00214 lseek(file->fd, file->offset, SEEK_SET);
00215 }
00216 else file->fd = -1;
00217 if (!*loop)
00218 break;
00219 }
00220 }
00221 return file->fd;
00222 }
00223
00224
00225 signed char FileMgr::existsFile(const char *ipath, const char *ifileName)
00226 {
00227 int len = strlen(ipath) + ((ifileName)?strlen(ifileName):0) + 3;
00228 char *ch;
00229 char *path = new char [ len ];
00230 strcpy(path, ipath);
00231
00232 if ((path[strlen(path)-1] == '\\') || (path[strlen(path)-1] == '/'))
00233 path[strlen(path)-1] = 0;
00234
00235 if (ifileName) {
00236 ch = path + strlen(path);
00237 sprintf(ch, "/%s", ifileName);
00238 }
00239 signed char retVal = !access(path, 04);
00240 delete [] path;
00241 return retVal;
00242 }
00243
00244
00245 signed char FileMgr::existsDir(const char *ipath, const char *idirName)
00246 {
00247 char *ch;
00248 int len = strlen(ipath) + ((idirName)?strlen(idirName):0) + 1;
00249 if (idirName)
00250 len += strlen(idirName);
00251 char *path = new char [ len ];
00252 strcpy(path, ipath);
00253
00254 if ((path[strlen(path)-1] == '\\') || (path[strlen(path)-1] == '/'))
00255 path[strlen(path)-1] = 0;
00256
00257 if (idirName) {
00258 ch = path + strlen(path);
00259 sprintf(ch, "/%s", idirName);
00260 }
00261 signed char retVal = !access(path, 04);
00262 delete [] path;
00263 return retVal;
00264 }