1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
|
/******************************************************************************
*
* filemgr.h - class FileMgr: encapsulates all file IO and
* platform-specific eccentricities.
*
* $Id: filemgr.h 3812 2020-10-15 17:32:41Z scribe $
*
* Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org)
* CrossWire Bible Society
* P. O. Box 2528
* Tempe, AZ 85280-2528
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#ifndef FILEMGR_H
#define FILEMGR_H
#include <sys/stat.h>
#include <fcntl.h>
#include <defs.h>
#include <swcacher.h>
#include <swbuf.h>
#include <vector>
SWORD_NAMESPACE_START
class SWDLLEXPORT FileDesc;
struct SWDLLEXPORT DirEntry {
public:
SWBuf name;
unsigned long size;
bool isDirectory;
};
/**
* This class isolates all file io for SWORD, making OS
* level quirks easier to fix. This class is typically
* copied and replaced if necessary to get SWORD to run on
* a specific platform (e.g., Windows Mobile), but in
* the future, statics should be removed to make possible to
* instead simply subclass and override necessary methods.
*
* This class also provides many convenience methods which
* make working with data storage easier.
*
* Conceptually, this factory exposes an interface which
* allows SWORD to 'open' every file it wants, without
* worrying about OS limits, and takes care of opening and
* closing the actual file descriptors when necessary.
*/
class SWDLLEXPORT FileMgr : public SWCacher {
friend class FileDesc;
friend class __staticsystemFileMgr;
FileDesc *files;
int sysOpen(FileDesc * file);
protected:
static FileMgr *systemFileMgr;
public:
static unsigned int CREAT;
static unsigned int APPEND;
static unsigned int TRUNC;
static unsigned int RDONLY;
static unsigned int RDWR;
static unsigned int WRONLY;
static unsigned int IREAD;
static unsigned int IWRITE;
/** Maximum number of open files set in the constructor.
* determines the max number of real system files that
* filemgr will open. Adjust for tuning.
*/
int maxFiles;
static FileMgr *getSystemFileMgr();
static void setSystemFileMgr(FileMgr *newFileMgr);
/** Constructor.
* @param maxFiles The number of files that this FileMgr may open in parallel, if necessary.
*/
FileMgr(int maxFiles = 35);
/**
* Destructor. Clean things up. Will close all files opened by this FileMgr object.
*/
~FileMgr();
/** Open a file and return a FileDesc for it.
* The file itself will only be opened when FileDesc::getFd() is called.
* @param path Filename.
* @param mode File access mode.
* @param tryDowngrade if we can't open the file for permissions requested, try to open the file with less permissions
* @return FileDesc object for the requested file.
*/
FileDesc *open(const char *path, int mode, bool tryDowngrade);
FileDesc *open(const char *path, unsigned int mode, bool tryDowngrade) { return this->open(path, (int)mode, tryDowngrade); }
/** Open a file and return a FileDesc for it.
* The file itself will only be opened when FileDesc::getFd() is called.
* @param path Filename.
* @param mode File access mode.
* @param perms Permissions.
* @param tryDowngrade
* @return FileDesc object for the requested file.
*/
FileDesc *open(const char *path, unsigned int mode, unsigned int perms = IREAD | IWRITE, bool tryDowngrade = false) { return this->open(path, (int)mode, (int)perms, tryDowngrade); }
FileDesc *open(const char *path, int mode, int perms = IREAD | IWRITE, bool tryDowngrade = false);
/** Close a given file and delete its FileDesc object.
* Will only close the file if it was created by this FileMgr object.
* @param file The file to close.
*/
void close(FileDesc *file);
/** Cacher methods overridden
*/
virtual void flush();
virtual long resourceConsumption();
/** Get an environment variable from the OS
* @param variableName the name of the env variable to retrieve
*
* @return variable value from the OS
*/
static SWBuf getEnvValue(const char *variableName);
/** Check if a path can be access with supplied permissions
* @param path Path to the resource
* @param mode Desired access mode
*
* @return whether or not the resource can be accessed with the requested
* mode
*/
static bool hasAccess(const char *path, int mode);
/** Checks for the existence and readability of a file.
* @param ipath Path to file.
* @param ifileName Name of file to check for.
*/
static signed char existsFile(const char *ipath, const char *ifileName = 0);
/** Checks for the existence and readability of a directory.
* @param ipath Path to directory.
* @param idirName Name of directory to check for.
*/
static signed char existsDir(const char *ipath, const char *idirName = 0);
/** Given a directory path, returns contents of directory
* @param dirPath Path to directory
* @param includeSize Optimization flag to allow passing false
* to skip file size lookup (true forces both size and directory lookup)
* @param includeIsDirectory Optimization flag to allow passing false
* to skip isDirectory lookup
*
* @return a container of DirEntry records describing contents
*/
static std::vector<struct DirEntry> getDirList(const char *dirPath, bool includeSize = false, bool includeIsDirectory = true);
/** Truncate a file at its current position
* leaving byte at current possition intact deleting everything afterward.
* @param file The file to operate on.
*/
signed char trunc(FileDesc *file);
static char isDirectory(const char *path);
static long getFileSize(const char *path);
static int createParent(const char *pName);
static int createPathAndFile(const char *fName);
/** attempts to open a file readonly
* @param fName filename to open
* @return fd; < 0 = error
*/
static int openFile(const char *fName, int mode, int perms);
static int openFileReadOnly(const char *fName);
static void closeFile(int fd);
static long write(int fd, const void *buf, long count);
static int copyFile(const char *srcFile, const char *destFile);
static int copyDir(const char *srcDir, const char *destDir);
static int removeDir(const char *targetDir);
static int removeFile(const char *fName);
static char getLine(FileDesc *fDesc, SWBuf &line);
/**
* Determines where SWORD looks for the user's home folder. This is
* typically used as a place to find any additional personal SWORD
* modules which a user might wish to be added to a system-wide
* library (e.g., added from ~/.sword/mods.d/ or ~/sword/mods.d/)
*
* or if a user or UI wishes to override SWORD system configuration
* settings (e.g., /etc/sword.conf) with a custom configuration
* (e.g., ~/.sword/sword.conf)
*/
SWBuf getHomeDir();
};
/**
* This class represents one file. It works with the FileMgr object.
*/
class SWDLLEXPORT FileDesc {
friend class FileMgr;
long offset;
int fd; // -77 closed;
FileMgr *parent;
FileDesc *next;
FileDesc(FileMgr * parent, const char *path, int mode, int perms, bool tryDowngrade);
virtual ~FileDesc();
public:
/** @return File handle.
* NOTE: magic file descriptor -77 = closed to avoid os limits
*/
inline int getFd() {
if (fd == -77)
fd = parent->sysOpen(this);
// if ((fd < -1) && (fd != -77)) // kludge to handle ce
// return 777;
return fd;
}
long seek(long offset, int whence);
long read(void *buf, long count);
long write(const void *buf, long count);
/** Path to file.
*/
char *path;
/** File access mode.
*/
int mode;
/** File permissions.
*/
int perms;
/**
*/
bool tryDowngrade;
};
SWORD_NAMESPACE_END
#endif
|