📄 posixstorage.cxx
字号:
// Copyright (c) 1994, 1995 James Clark// See the file COPYING for copying permission.#ifdef __GNUG__#pragma implementation#endif#include "splib.h"#include "PosixStorage.h"#include "RewindStorageObject.h"#include "StorageManager.h"#include "DescriptorManager.h"#include "MessageArg.h"#include "ErrnoMessageArg.h"#include "SearchResultMessageArg.h"#include "Message.h"#include "StringC.h"#include "StringOf.h"#include "CharsetInfo.h"#include "CodingSystem.h"#include "macros.h"#include "PosixStorageMessages.h"#include <sys/types.h>#include <stdio.h>#include <ctype.h>#ifdef SP_INCLUDE_IO_H#include <io.h> // for open, fstat, lseek, read prototypes#endif#ifdef SP_INCLUDE_UNISTD_H#include <unistd.h>#endif#ifdef SP_INCLUDE_OSFCN_H#include <osfcn.h>#endif#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <stddef.h>#ifndef S_ISREG#ifndef S_IFREG#define S_IFREG _S_IFREG#endif#ifndef S_IFMT#define S_IFMT _S_IFMT#endif#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)#endif /* not S_ISREG */#ifndef O_BINARY#define O_BINARY 0#endif#ifdef SP_WIDE_SYSTEM#include <windows.h>#endif#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endif#ifdef SP_WIDE_SYSTEMtypedef wchar_t FChar;#elsetypedef char FChar;#endifclass PosixBaseStorageObject : public RewindStorageObject {public: PosixBaseStorageObject(int fd, Boolean mayRewind); size_t getBlockSize() const;protected: enum { defaultBlockSize = 8192 }; int fd_; PackedBoolean eof_; Boolean seekToStart(Messenger &); virtual Boolean seek(off_t, Messenger &) = 0; static int xclose(int fd);private: Boolean canSeek(int fd); off_t startOffset_;};PosixBaseStorageObject::PosixBaseStorageObject(int fd, Boolean mayRewind): fd_(fd), eof_(0), RewindStorageObject(mayRewind, mayRewind && canSeek(fd)){}Boolean PosixBaseStorageObject::canSeek(int fd){ struct stat sb; if (fstat(fd, &sb) < 0 || !S_ISREG(sb.st_mode) || (startOffset_ = lseek(fd, off_t(0), SEEK_CUR)) < 0) return 0; else return 1;}Boolean PosixBaseStorageObject::seekToStart(Messenger &mgr){ eof_ = 0; return seek(startOffset_, mgr);}int PosixBaseStorageObject::xclose(int fd){ int ret; do { ret = ::close(fd); } while (ret < 0 && errno == EINTR); return ret;}class PosixStorageObject : public PosixBaseStorageObject, private DescriptorUser {public: PosixStorageObject(int fd, const StringC &, const String<FChar> &, Boolean mayRewind, DescriptorManager *); ~PosixStorageObject(); Boolean read(char *buf, size_t bufSize, Messenger &mgr, size_t &nread); Boolean suspend(); Boolean seek(off_t, Messenger &); void willNotRewind();private: void resume(Messenger &); PackedBoolean suspended_; off_t suspendPos_; const MessageType2 *suspendFailedMessage_; int suspendErrno_; StringC filename_; String<FChar> cfilename_; void systemError(Messenger &, const MessageType2 &, int);};inline int openFile(const FChar *s) {#ifdef SP_WIDE_SYSTEM int fd = _wopen(s, O_RDONLY|O_BINARY); if (fd < 0 && errno != ENOENT) { String<char> buf; int len = WideCharToMultiByte(CP_ACP, 0, s, -1, 0, 0, 0, 0); buf.resize(len + 1); WideCharToMultiByte(CP_ACP, 0, s, -1, buf.begin(), len, 0, 0); buf[len] = '\0'; return ::open(buf.data(), O_RDONLY|O_BINARY); } return fd;#else return ::open(s, O_RDONLY|O_BINARY);#endif }PosixStorageManager::PosixStorageManager(const char *type, const CharsetInfo *filenameCharset,#ifndef SP_WIDE_SYSTEM const OutputCodingSystem *filenameCodingSystem,#endif int maxFDs): IdStorageManager(filenameCharset), type_(type),#ifndef SP_WIDE_SYSTEM filenameCodingSystem_(filenameCodingSystem),#endif descriptorManager_(maxFDs){ Char newline = idCharset()->execToDesc('\n'); reString_.assign(&newline, 1);}const char *PosixStorageManager::type() const{ return type_;}void PosixStorageManager::addSearchDir(const StringC &str){ searchDirs_.push_back(str);}#ifdef SP_POSIX_FILENAMES#define FILENAME_TYPE_DEFINED// FIXME should use idCharset.Boolean PosixStorageManager::isAbsolute(const StringC &file) const{ return file.size() > 0 && file[0] == '/';}StringC PosixStorageManager::extractDir(const StringC &str) const{ for (size_t i = str.size(); i > 0; i--) if (str[i - 1] == '/') return StringC(str.data(), i); // include slash for root case return StringC();}StringC PosixStorageManager::combineDir(const StringC &dir, const StringC &base) const{ StringC result(dir); if (dir.size() > 0 && dir[dir.size() - 1] != '/') result += '/'; result += base; return result;}Boolean PosixStorageManager::transformNeutral(StringC &str, Boolean fold, Messenger &) const{ if (fold) for (size_t i = 0; i < str.size(); i++) { Char c = str[i]; if (c <= (unsigned char)-1) str[i] = tolower(str[i]); } return 1;}#endif /* SP_POSIX_FILENAMES */#ifdef SP_MSDOS_FILENAMES#define FILENAME_TYPE_DEFINEDBoolean PosixStorageManager::isAbsolute(const StringC &s) const{ if (s.size() == 0) return 0; return s[0] == '/' || s[0] == '\\' || (s.size() > 1 && s[1] == ':');}StringC PosixStorageManager::extractDir(const StringC &str) const{ for (size_t i = str.size(); i > 0; i--) if (str[i - 1] == '/' || str[i - 1] == '\\' || (i == 2 && str[i - 1] == ':')) return StringC(str.data(), i); // include separator return StringC();}StringC PosixStorageManager::combineDir(const StringC &dir, const StringC &base) const{ StringC result(dir); if (dir.size() > 0) { Char lastChar = dir[dir.size() - 1]; if (lastChar != '/' && lastChar != '\\' && !(dir.size() == 2 && lastChar == ':')) result += '\\'; } result += base; return result;}Boolean PosixStorageManager::transformNeutral(StringC &str, Boolean, Messenger &) const{ for (size_t i = 0; i < str.size(); i++) if (str[i] == '/') str[i] = '\\'; return 1;}#endif /* SP_MSDOS_FILENAMES */#ifdef SP_MAC_FILENAMES// Colons separate directory names// relative path-names start with a colon, or have no colons// absolute path-names don't start with a colon and have at least one colon#define FILENAME_TYPE_DEFINEDBoolean PosixStorageManager::isAbsolute(const StringC &s) const{ if (s.size() == 0) return 0; if (s[0] == ':') return 0; // starts with a colon => relative size_t ss = s.size(); for (size_t i = 0; i < ss; i++) if (s[i] == ':') return 1; // absolute return 0; // no colons => relative}StringC PosixStorageManager::extractDir(const StringC &str) const{ for (size_t i = str.size(); i > 0; i--) if (str[i - 1] == ':') return StringC(str.data(), i); // include separator return StringC();}StringC PosixStorageManager::combineDir(const StringC &dir, const StringC &base) const{ StringC result(dir); if (dir.size() > 0) { Char lastChar = dir[dir.size() - 1]; if (lastChar != ':') result += ':'; } if (base[0] == ':') { StringC newbase(base.data() + 1,base.size() - 1); result += newbase; } else result += base; return result;}Boolean PosixStorageManager::transformNeutral(StringC &str, Boolean, Messenger &) const{ if (str[0] == '/') { // absolute StringC nstr(str.data() + 1,str.size()-1); str = nstr; } else { // relative Char cc = ':'; StringC colon(&cc,1); str.insert(0,colon); } for (size_t i = 0; i < str.size(); i++) if (str[i] == '/') str[i] = ':'; return 1;}#endif /* SP_MAC_FILENAMES */#ifndef FILENAME_TYPE_DEFINEDBoolean PosixStorageManager::isAbsolute(const StringC &) const{ return 1;}StringC PosixStorageManager::extractDir(const StringC &) const{ return StringC();}StringC PosixStorageManager::combineDir(const StringC &, const StringC &base) const{ return base;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -