📄 file.cpp
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.// // 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; either version 2 of the License, or// (at your option) any later version.// // 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.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//// needed for GNU/LINUX glibc otherwise pread/pwrite wont work#ifdef __linux__#ifndef _XOPEN_SOURCE#define _XOPEN_SOURCE 500#endif/* * on old glibc's, this has to be * defined explicitly */#ifndef _XOPEN_SOURCE_EXTENDED#define _XOPEN_SOURCE_EXTENDED#endif#endif#include <cc++/config.h>#include <cc++/export.h>#include <cc++/exception.h>#include <cc++/thread.h>#include <cc++/file.h>#include <cc++/process.h>#include "private.h"#ifdef __BORLANDC__#include <stdio.h>#else#include <cstdio>#endif#include <sys/stat.h>#include <cerrno>#ifndef WIN32#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifdef HAVE_SYS_FILE_H#include <sys/file.h>#endif#ifdef HAVE_SYS_LOCKF_H#include <sys/lockf.h>#endif#ifdef COMMON_AIX_FIXES#undef LOCK_EX#undef LOCK_SH#endif#ifdef MACOSX#define MISSING_LOCKF #endif#ifndef F_LOCK#define MISSING_LOCKFenum{ F_ULOCK = 1, F_LOCK, F_TLOCK, F_TEST};#endif#endif // ndef WIN32 #if defined(_OSF_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE > 1#undef LOCK_EX#undef LOCK_SH#endif#if 0/* * not used anymore ? (hen) */static const char *clearfile(const char *pathname){ remove(pathname); return pathname;}static const char *clearfifo(const char *pathname, int mode){ remove(pathname); mkfifo(pathname, mode); return pathname;}#endif#ifdef CCXX_NAMESPACESnamespace ost {#endifRandomFile::RandomFile(const char *name) : Mutex(name) {#ifdef WIN32 fd = INVALID_HANDLE_VALUE; // immediate is not defined on Win32 #else fd = -1; flags.immediate = false;#endif flags.thrown = flags.initial = flags.temp = false; flags.count = 0; pathname = NULL;}RandomFile::RandomFile(const RandomFile &rf) : Mutex() { // first, `dup'-licate the file descriptor/handle#ifdef WIN32 HANDLE pidHandle = GetCurrentProcess(); HANDLE dupHandle; if(rf.fd != INVALID_HANDLE_VALUE) { if(!DuplicateHandle(pidHandle, rf.fd, pidHandle, &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) fd = INVALID_HANDLE_VALUE; else fd = dupHandle; } else fd = INVALID_HANDLE_VALUE;#else if(rf.fd > -1) fd = dup(rf.fd); else fd = -1;#endif flags = rf.flags; flags.count = 0; if(rf.pathname) pathname = newString(rf.pathname); else pathname = NULL;}RandomFile::~RandomFile(){ final();}File::Error RandomFile::restart(void){ return errOpenFailed;}File::Attr RandomFile::initialize(void){ return attrPublic;}void RandomFile::final(void){#ifdef WIN32 if(fd != INVALID_HANDLE_VALUE) { CloseHandle(fd); if(flags.temp && pathname) DeleteFile(pathname); }#else if(fd > -1) { close(fd); if(flags.temp && pathname) remove(pathname); }#endif if(pathname) { delString(pathname); pathname = NULL; }#ifdef WIN32 fd = INVALID_HANDLE_VALUE;#else fd = -1;#endif flags.count = 0; flags.initial = false;}RandomFile::Error RandomFile::error(Error id, char *str){ errstr = str; errid = id; if(!flags.thrown) { flags.thrown = true;#ifdef CCXX_EXCEPTIONS if(Thread::getException() == Thread::throwObject) throw(this);#ifdef COMMON_STD_EXCEPTION else if(Thread::getException() == Thread::throwException) { if(!str) str = ""; throw FileException(str); }#endif#endif } return id;}bool RandomFile::initial(void){ bool init;#ifdef WIN32 if(fd == INVALID_HANDLE_VALUE)#else if(fd < 0)#endif return false; enterMutex(); init = flags.initial; flags.initial = false; if(!init) { leaveMutex(); return false; }#ifdef WIN32 Attr access = initialize(); if(access == attrInvalid) { CloseHandle(fd); if(pathname) DeleteFile(pathname); fd = INVALID_HANDLE_VALUE; leaveMutex(); error(errInitFailed); return false; }#else int mode = (int)initialize(); if(!mode) { close(fd); fd = -1; if(pathname) remove(pathname); leaveMutex(); error(errInitFailed); return false; } fchmod(fd, mode);#endif leaveMutex(); return init;}#ifndef WIN32RandomFile::Error RandomFile::setCompletion(Complete mode){ long flag = fcntl(fd, F_GETFL); if(fd < 0) return errNotOpened; flags.immediate = false;#ifdef O_SYNC flag &= ~(O_SYNC | O_NDELAY);#else flag &= ~O_NDELAY;#endif switch(mode) { case completionImmediate:#ifdef O_SYNC flag |= O_SYNC;#endif flags.immediate = true; break; case completionDelayed: flag |= O_NDELAY; //completionDeferred: ? (hen) case completionDeferred: break; } fcntl(fd, F_SETFL, flag); return errSuccess;}#endifoff_t RandomFile::getCapacity(void){ off_t eof, pos = 0;#ifdef WIN32 if(!fd)#else if(fd < 0)#endif return 0; enterMutex();#ifdef WIN32 pos = SetFilePointer(fd, 0l, NULL, FILE_CURRENT); eof = SetFilePointer(fd, 0l, NULL, FILE_END); SetFilePointer(fd, pos, NULL, FILE_BEGIN);#else lseek(fd, pos, SEEK_SET); pos = lseek(fd, 0l, SEEK_CUR); eof = lseek(fd, 0l, SEEK_END);#endif leaveMutex(); return eof;}bool RandomFile::operator!(void){#ifdef WIN32 return fd == INVALID_HANDLE_VALUE;#else if(fd < 0) return true; return false;#endif}ThreadFile::ThreadFile(const char *path) : RandomFile(path){ first = NULL; open(path);}ThreadFile::~ThreadFile(){ final(); fcb_t *next; while(first) { next = first->next; delete first; first = next; }}ThreadFile::Error ThreadFile::restart(void){ return open(pathname);}ThreadFile::Error ThreadFile::open(const char *path){#ifdef WIN32 if(fd != INVALID_HANDLE_VALUE)#else if(fd > -1)#endif final(); if(path != pathname) { if(pathname) delString(pathname); pathname = newString(path); } flags.initial = false;#ifdef WIN32 fd = CreateFile(pathname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); if(fd == INVALID_HANDLE_VALUE) { flags.initial = true; fd = CreateFile(pathname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); } if(fd == INVALID_HANDLE_VALUE) return errOpenFailed;#else fd = ::open(pathname, O_RDWR); if(fd < 0) { flags.initial = true; fd = ::open(pathname, O_CREAT | O_RDWR | O_TRUNC, (int)attrPrivate); } if(fd < 0) return error(errOpenFailed);#ifdef LOCK_EX if(flock(fd, LOCK_EX | LOCK_NB)) { close(fd); fd = -1; return error(errOpenInUse); }#endif#endif // WIN32 return errSuccess;}ThreadFile::fcb_t *ThreadFile::getFCB(void){ fcb_t *fcb = (fcb_t *)state.getKey(); if(!fcb) { fcb = new fcb_t; fcb->next = first; first = fcb; fcb->address = NULL; fcb->len = 0; fcb->pos = 0; state.setKey(fcb); } return fcb;}ThreadFile::Error ThreadFile::fetch(caddr_t address, ccxx_size_t len, off_t pos){ fcb_t *fcb = getFCB();#ifdef WIN32 Thread::Cancel save; if(fd == INVALID_HANDLE_VALUE)#else if(fd < 0)#endif return errNotOpened; if(address) fcb->address = address; if(len) fcb->len = len; if(pos != -1) fcb->pos = pos;#ifdef WIN32 enterMutex(); save = Thread::enterCancel(); SetFilePointer(fd, fcb->pos, NULL, FILE_BEGIN); DWORD count; if(!ReadFile(fd, fcb->address, fcb->len, &count, NULL)) { Thread::exitCancel(save); leaveMutex(); return errReadFailure; } Thread::exitCancel(save); leaveMutex(); if(count < fcb->len) return errReadIncomplete; return errSuccess;#else#ifdef HAVE_PREAD_PWRITE int io = ::pread(fd, fcb->address, fcb->len, fcb->pos);#else enterMutex(); lseek(fd, fcb->pos, SEEK_SET); int io = ::read(fd, fcb->address, fcb->len); leaveMutex();#endif if((size_t) io == fcb->len) return errSuccess; if(io > -1) return errReadIncomplete; switch(errno) { case EINTR: return errReadInterrupted; default: return errReadFailure; }#endif // WIN32}ThreadFile::Error ThreadFile::update(caddr_t address, ccxx_size_t len, off_t pos){ fcb_t *fcb = getFCB();#ifdef WIN32 if(fd == INVALID_HANDLE_VALUE)#else if(fd < 0)#endif return errNotOpened; if(address) fcb->address = address; if(len) fcb->len = len; if(pos != -1) fcb->pos = pos;#ifdef WIN32 enterMutex(); Thread::Cancel save = Thread::enterCancel(); SetFilePointer(fd, fcb->pos, NULL, FILE_BEGIN); DWORD count; if(!WriteFile(fd, fcb->address, fcb->len, &count, NULL)) { Thread::exitCancel(save); leaveMutex(); return errWriteFailure; } Thread::exitCancel(save); leaveMutex(); if(count < fcb->len) return errWriteIncomplete; return errSuccess;#else#ifdef HAVE_PREAD_PWRITE int io = ::pwrite(fd, fcb->address, fcb->len, fcb->pos);#else enterMutex(); lseek(fd, fcb->pos, SEEK_SET); int io = ::write(fd, fcb->address, fcb->len); leaveMutex();#endif if((size_t) io == fcb->len) return errSuccess; if(io > -1) return errWriteIncomplete; switch(errno) { case EINTR: return errWriteInterrupted; default: return errWriteFailure; }#endif //WIN32}ThreadFile::Error ThreadFile::append(caddr_t address, ccxx_size_t len){ fcb_t *fcb = getFCB();#ifdef WIN32 if(fd == INVALID_HANDLE_VALUE)#else if(fd < 0)#endif return errNotOpened; if(address) fcb->address = address; if(len) fcb->len = len; enterMutex();#ifdef WIN32 Thread::Cancel save = Thread::enterCancel(); fcb->pos = SetFilePointer(fd, 0l, NULL, FILE_END); DWORD count; if(!WriteFile(fd, fcb->address, fcb->len, &count, NULL)) { Thread::exitCancel(save); leaveMutex(); return errWriteFailure; } Thread::exitCancel(save); leaveMutex(); if(count < fcb->len) return errWriteIncomplete; return errSuccess;#else fcb->pos = lseek(fd, 0l, SEEK_END); int io = ::write(fd, fcb->address, fcb->len); leaveMutex(); if((size_t) io == fcb->len) return errSuccess; if(io > -1) return errWriteIncomplete; switch(errno) { case EINTR: return errWriteInterrupted; default: return errWriteFailure; }#endif // WIN32}off_t ThreadFile::getPosition(void){ fcb_t *fcb = getFCB(); return fcb->pos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -