diff options
Diffstat (limited to 'lib/Handle.cc')
-rw-r--r-- | lib/Handle.cc | 1316 |
1 files changed, 658 insertions, 658 deletions
diff --git a/lib/Handle.cc b/lib/Handle.cc index c38f47e..bbd3e04 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -1,658 +1,658 @@ -/* - * Baltisot - * Copyright (C) 1999-2003 Nicolas "Pixel" Noble - * - * 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 - */ - -/* $Id: Handle.cc,v 1.71 2004-07-23 16:56:03 pixel Exp $ */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "generic.h" - -#if defined WORDS_BIGENDIAN -#if defined HAVE_BYTESWAP_H -#include <byteswap.h> -#else -inline Uint16 bswap_16(Uint16 w) { - return (w >> 8) | (w << 8); -} - -inline Uint32 bswap_32(Uint32 w) { - return (w >> 24) | ((w >> 8) & 0x0000ff00) | ((w << 8) & 0x00ff0000) | (w << 24); -} -#endif -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#else -#include <io.h> -#endif - -#ifndef _WIN32 -#include <sys/mman.h> -#endif - -#include "Handle.h" -#include "gettext.h" - -enum { - DEFLATE, - INFLATE -}; - -Handle::Handle(const Handle & nh) : itell(0), hFile(0), h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(nh.closed), nonblock(nh.closed), zfile(0), z(0), hMapObject(0), mapped(0) -{ -#ifdef DEBUG - printm(M_INFO, String(_("Duplication of handle ")) + nh.h + _(" to ") + h + "\n"); -#endif - if ((h >= 0) && (nh.z)) { - SetZ(nh.z); - } -} - -Handle::~Handle() { -#ifdef DEBUG - printm(M_INFO, String(_("Destroying handle ")) + h + "\n"); -#endif - close(); -} - -Handle::Handle(int nh) : h(nh), closed(false), nonblock(false), zfile(0), z(0), hMapObject(0), mapped(0) -{ -#ifdef DEBUG - printm(M_INFO, String(_("Initialising handle ")) + h + "\n"); -#endif -} - -int Handle::GetHandle() { - return h; -} - -void * Handle::GetHFile() { - return hFile; -} - -int Handle::GetHandle() const { - return h; -} - -ssize_t Handle::write(const void *cbuf, size_t count) throw (GeneralException) { - ssize_t r, tr = 0; - bool done, full = false; - const char * buf = (const char *)cbuf; - - if (closed) { - throw IOGeneral("Unable to write: handle `" + GetName() + "' is closed."); - } - - if (!count) - return 0; - - do { - done = true; - errno = 0; - if ((r = uwrite(buf, count)) < 0) { - if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) { - // Avant de déclarer une erreur, on vérifie si ce n'est pas un - // problème lié au fait qu'il n'y a plus de place libre. Cela peut - // arriver si l'on agit sur un pipe ou un handle. Nous - // attendons encore une fois avant de déclarer l'erreur, - // grace au drapeau full. - if (full) { - throw IOException(GetName(), IO_WRITE, count); - } else { - done = false; - full = true; - if (nonblock) { -#ifdef DEBUG - printm(M_INFO, _("write: throwing IOAgain for handle ") + GetName() + "\n"); -#endif - throw IOAgain(); - } else { -#ifdef HAVE_SLEEP - sleep(1); -#endif - } - } - } else { - throw IOException(GetName(), IO_WRITE, count); - } - } else if (((size_t) r) != count) { - if (nonblock) { - return r; - } - full = done = false; - buf += r; - tr += r; - } - } while (!done); - - return r + tr; -} - -ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) { - ssize_t r; - - if (closed) { - throw IOGeneral("Unable to read: handle `" + GetName() + "' is closed."); - } - - if (!count) - return 0; - -#ifdef FULLDEBUG - printm(M_INFO, String(_("read: reading ")) + count + _(" bytes from handle ") + GetHandle() + "\n"); -#endif - - errno = 0; - while ((r = uread(buf, count)) < 0) { - if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) { - // Avant de déclarer une erreur, on vérifie si ce n'est pas un - // problème lié au fait qu'il n'y a plus d'octets. - if (nonblock) { -#ifdef DEBUG - printm(M_INFO, _("read: throwing IOAgain for handle ") + GetName() + "\n"); -#endif - throw IOAgain(); - } - } else { - throw IOException(GetName(), IO_READ, count); - } - } - - if (!r) { - close(); - } - - return r; -} - -bool Handle::IsClosed(void) const { - return closed; -} - -bool Handle::IsNonBlock(void) const { - return nonblock; -} - -void Handle::SetNonBlock(void) { -#ifdef HAVE_FCNTL - if ((h >= 0) || !nonblock) { - fcntl(h, F_SETFL, O_NONBLOCK); - } - nonblock = true; -#endif -} - -Handle & operator<<(Handle & h, const String & s) { - const char * p; - - p = s.to_charp(); - h.write(p, strlen(p)); - - return h; -} - -Handle & operator>>(Handle & h, String & s) { - char t[BUFSIZ]; - int i = 0, r; - - while ((r = h.read(&(t[i]), 1)) && (i != (BUFSIZ - 1))) { - // Il y a souvent des \r\n dans les sockets par exemple, - // ou bien en lisant des fichiers au format MS-DOS. On - // ignore le \r pour ne garder que le \n, standard sous Unix. - if (t[i] == '\r') { - continue; - } - if (t[i] == '\n') { - break; - } else { - i++; - } - } - - t[i] = '\0'; - s = t; - return h; -} - -void Handle::close() throw (GeneralException) { - if (IsClosed()) { - return; - } - - Flush(); - - if (h >= 0) { - if (z >= 10) { - int err; - if (c == DEFLATE) { - err = deflateEnd(&zstrm); - if (err != Z_OK) { - throw GeneralException(String(_("Error during deflateEnd: ")) + zstrm.msg); - } - } else { - err = inflateEnd(&zstrm); - if (err != Z_OK) { - throw GeneralException(String(_("Error during inflateEnd: ")) + zstrm.msg); - } - } - err = ::close(h); - if (err) { - throw GeneralException(String(_("Error during (zstream) close: ")) + strerror(errno)); - } - } else if (z) { -#ifdef DEBUG - printm(M_INFO, String(_("Performing gzclose on handle ")) + h + "\n"); -#endif - int err = gzclose(zfile); -#ifdef DEBUG - printm(M_INFO, String(_("gzclose returned ")) + err + "\n"); -#endif - if (err) { - if (err == Z_ERRNO) { - throw GeneralException(String(_("Error during close: ")) + strerror(errno)); - } else { - throw GeneralException(String(_("Error in zlib during gzclose: ")) + gzerror(zfile, &err)); - } - } - } else { - if (!hFile) { - int err = ::close(h); - if (err) { - throw GeneralException(String(_("Error during close: ")) + strerror(errno)); - } - } - } -#if defined (_WIN32) && !defined (NO_HFILE) - if (hFile) { - CloseHandle(hFile); - hFile = 0; - } -#endif - } - - if (mapped) { - munmap(); - } - - h = -1; - closed = 1; -} - -bool Handle::CanRead(void) const { - return false; -} - -bool Handle::CanWrite(void) const { - return false; -} - -String Handle::GetName(void) const { - return _("Bare Handle - should not happend"); -} - -ssize_t Handle::GetSize(void) const { - return -1; -} - -time_t Handle::GetModif(void) const { - return -1; -} - -bool Handle::CanWatch(void) const { - return true; -} - -int Handle::Dup() const throw (GeneralException) { - int d; - - if ((d = dup(h)) < 0) { - throw IOGeneral(String(_("Error dupping file `")) + GetName() + _("' (handle ") + h + "): " + strerror(errno) + " (" + errno + ")"); - } - return d; -} - -void Handle::SetZ(int az) throw (GeneralException) { - if (z) { - throw GeneralException(_("Can't SetZ a Handle twice.")); - } - if (h < 0) { - throw GeneralException(_("Can't SetZ a virtual Handle.")); - } - if (az >= 10) { -#ifdef DEBUG - printm(M_INFO, _("Setting up zstream using inflate/deflate...\n")); -#endif - int err; - zstrm.zalloc = Z_NULL; - zstrm.zfree = Z_NULL; - if (CanWrite()) { - c = DEFLATE; - err = deflateInit(&zstrm, az - 10); - if (err != Z_OK) { - throw GeneralException(String(_("Error in deflateInit: ")) + zstrm.msg); - } - } else { - c = INFLATE; - zstrm.next_in = 0; - zstrm.avail_in = 0; - err = inflateInit(&zstrm); - if (err != Z_OK) { - throw GeneralException(String(_("Error in inflateInit: ")) + zstrm.msg); - } - } - } else if (az) { - char format[5]; - int index = 0; - if (CanRead()) { - format[index++] = 'r'; - } - if (CanWrite()) { - format[index++] = 'w'; - } - format[index++] = (char) (az + '0'); - format[index++] = 'b'; - format[index] = 0; -#ifdef FULLDEBUG - printm(M_INFO, String(_("Performing gzdopen on handle ")) + h + _(" with mode \"") + format + "\"\n"); -#endif - if (!(zfile = gzdopen(h, format))) { - throw GeneralException(String(_("Was not able to gzdopen: ")) + strerror(errno)); - } - z = az; - } -} - -ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) { - if (z >= 10) { - } else if (z) { -#ifdef FULLDEBUG - printm(M_INFO, String(_("Performing gzwrite of ")) + count + _(" byte(s) for handle ") + h + "\n"); -#endif -#ifdef HAVE_WD_ZLIB - int err = gzwrite(zfile, buf, count); -#else - int err = gzwrite(zfile, (char *) buf, count); -#endif - if (err == 0) { - const char * m = gzerror(zfile, &err); - if (err == Z_ERRNO) { - return -1; - } else { - throw GeneralException(String(_("Error in zlib during gzwrite: ")) + m); - } - } - itell += err; - return err; - } else { - itell += count = ::write(h, buf, count); - return count; - } -} - -ssize_t Handle::uread(void * buf, size_t count) { - if (z >= 10) { - } if (z) { -#ifdef DEBUG - printm(M_BARE, String(_("Performing gzread of ")) + count + _(" byte(s) for handle ") + h + "\n"); -#endif - int err = gzread(zfile, buf, count); - if (err == -1) { - gzerror(zfile, &err); - if (err == Z_ERRNO) { - return -1; - } else { - return 0; - } - } - itell += err; - return err; - } else { -#if defined (_WIN32) && !defined (NO_HFILE) - if (hFile) { - DWORD rcount; - if (!ReadFile(hFile, buf, count, &rcount, 0)) { - // Error.. - } - itell += count = rcount; - } else -#endif - itell += count = ::read(h, buf, count); - return count; - } -} - -off_t Handle::tell() const { - if (z) { - return gztell(zfile); - } else { - return itell; - } -} - -bool Handle::CanSeek() const { - return 0; -} - -off_t Handle::seek(off_t offset, int whence) throw(GeneralException) { - if (z) { - return itell = gzseek(zfile, offset, whence); - } else { - throw IOGeneral(_("Handle ") + GetName() + _(" can't seek")); - } -} - -Uint8 Handle::readU8() { - Uint8 r; - read(&r, 1); - return r; -} - -Uint16 Handle::readU16() { - Uint16 r; - read(&r, 2); -#ifdef WORDS_BIGENDIAN - return bswap_16(r); -#else - return r; -#endif -} - -Uint32 Handle::readU32() { - Uint32 r; - read(&r, 4); -#ifdef WORDS_BIGENDIAN - return bswap_32(r); -#else - return r; -#endif -} - -void Handle::writeU8(Uint8 v) { - write(&v, 1); -} - -void Handle::writeU16(Uint16 v) { -#ifdef WORDS_BIGENDIAN - Uint16 t = bswap_16(v); - write(&t, 2); -#else - write(&v, 2); -#endif -} - -void Handle::writeU32(Uint32 v) { -#ifdef WORDS_BIGENDIAN - Uint32 t = bswap_32(v); - write(&t, 4); -#else - write(&v, 4); -#endif -} - -void Handle::copyto(Handle * dest, ssize_t s) { - copy(this, dest, s); -} - -void Handle::copyfrom(Handle * src, ssize_t s) { - copy(src, this, s); -} - -void copyone(Handle * s, Handle * d, ssize_t size) { - long i; - unsigned char c; - long r; - - if (size < 0) - size = s->GetSize(); - - for (i = 0; (i < size) || (size < 0); i++) { - r = s->read(&c, 1); - if (r == 0) { - break; - } - d->write(&c, 1); - } -} - -#define BSIZE 20480 - -void copy(Handle * s, Handle * d, ssize_t size) { - long i; - static unsigned char b[BSIZE]; - long r; - - if (size < 0) - size = s->GetSize(); - - LOCK; - - while (size) { - if ((size > BSIZE) || (size < 0)) { - r = s->read(b, BSIZE); - if (r) - d->write(b, r); - } else { - r = s->read(b, size); - if (r) - d->write(b, r); - } - if (!r) - break; - if (size > 0) - size -= r; - } - - UNLOCK; -} - -void Handle::Flush() { - if (!CanWrite()) - return; - if (h < 0) - return; - if (z >= 10) { - - } else if (z) { - gzflush(&z, Z_FULL_FLUSH); - } else { -#ifdef HAVE_FSYNC - fsync(h); -#endif - } -} - -void * Handle::mmap(off_t offset, size_t length) throw (GeneralException) { - void * r; - - if (h == -1) { - throw GeneralException("Can't mmap() a virtual handle"); - } -#ifdef _WIN32 - if (!hFile) { - throw GeneralException("Can't mmap() a non-hFile handle under windows"); - } -#endif - if (mapped) { - throw GeneralException("Handle already mmap()ped"); - } - mapped = true; - if (length == -1) { - length = GetSize(); - } - maplength = length; -#ifndef _WIN32 - r = ::mmap(0, length, (CanRead() ? PROT_READ : 0) | (CanWrite() ? PROT_WRITE : 0), MAP_SHARED, h, offset); - if (!r) { - throw GeneralException(String("Was not able to mmap(): ") + strerror(errno)); - } -#else - hMapObject = CreateFileMapping( - hFile, - 0, - CanWrite() ? PAGE_READWRITE : PAGE_READONLY, - 0, - length, - GetName().to_charp()); - if (hMapObject != NULL) { - r = MapViewOfFile( - hMapObject, - CanWrite() ? FILE_MAP_WRITE : FILE_MAP_READ, - 0, - offset, - length); - if (!r) { - CloseHandle(hMapObject); - throw GeneralException("Was not able to MapViewOfFile()"); - } - } else { - throw GeneralException("Was not able to CreateFileMapping()"); - } -#endif - - mappedarea = r; - - return r; -} - -void Handle::munmap() throw (GeneralException) { - if (!mapped) { - throw GeneralException("Can't munmap, was not mapped"); - } -#ifndef _WIN32 - if (::munmap(mappedarea, maplength)) { - throw GeneralException(String("Was not able to munmap(): ") + strerror(errno)); - } -#else - if (!UnmapViewOfFile(mappedarea)) { - throw GeneralException("Was not able to UnmapViewOfFile()"); - } - CloseHandle(hMapObject); -#endif - mapped = false; - mappedarea = 0; - maplength = 0; -} +/*
+ * Baltisot
+ * Copyright (C) 1999-2003 Nicolas "Pixel" Noble
+ *
+ * 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
+ */
+
+/* $Id: Handle.cc,v 1.72 2004-11-27 21:35:19 pixel Exp $ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "generic.h"
+
+#if defined WORDS_BIGENDIAN
+#if defined HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+inline Uint16 bswap_16(Uint16 w) {
+ return (w >> 8) | (w << 8);
+}
+
+inline Uint32 bswap_32(Uint32 w) {
+ return (w >> 24) | ((w >> 8) & 0x0000ff00) | ((w << 8) & 0x00ff0000) | (w << 24);
+}
+#endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#ifndef _WIN32
+#include <sys/mman.h>
+#endif
+
+#include "Handle.h"
+#include "gettext.h"
+
+enum {
+ DEFLATE,
+ INFLATE
+};
+
+Handle::Handle(const Handle & nh) : itell(0), hFile(0), h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(nh.closed), nonblock(nh.closed), zfile(0), z(0), hMapObject(0), mapped(0)
+{
+#ifdef DEBUG
+ printm(M_INFO, String(_("Duplication of handle ")) + nh.h + _(" to ") + h + "\n");
+#endif
+ if ((h >= 0) && (nh.z)) {
+ SetZ(nh.z);
+ }
+}
+
+Handle::~Handle() {
+#ifdef DEBUG
+ printm(M_INFO, String(_("Destroying handle ")) + h + "\n");
+#endif
+ close();
+}
+
+Handle::Handle(int nh) : h(nh), closed(false), nonblock(false), zfile(0), z(0), hMapObject(0), mapped(0)
+{
+#ifdef DEBUG
+ printm(M_INFO, String(_("Initialising handle ")) + h + "\n");
+#endif
+}
+
+int Handle::GetHandle() {
+ return h;
+}
+
+void * Handle::GetHFile() {
+ return hFile;
+}
+
+int Handle::GetHandle() const {
+ return h;
+}
+
+ssize_t Handle::write(const void *cbuf, size_t count) throw (GeneralException) {
+ ssize_t r, tr = 0;
+ bool done, full = false;
+ const char * buf = (const char *)cbuf;
+
+ if (closed) {
+ throw IOGeneral("Unable to write: handle `" + GetName() + "' is closed.");
+ }
+
+ if (!count)
+ return 0;
+
+ do {
+ done = true;
+ errno = 0;
+ if ((r = uwrite(buf, count)) < 0) {
+ if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) {
+ // Avant de déclarer une erreur, on vérifie si ce n'est pas un
+ // problème lié au fait qu'il n'y a plus de place libre. Cela peut
+ // arriver si l'on agit sur un pipe ou un handle. Nous
+ // attendons encore une fois avant de déclarer l'erreur,
+ // grace au drapeau full.
+ if (full) {
+ throw IOException(GetName(), IO_WRITE, count);
+ } else {
+ done = false;
+ full = true;
+ if (nonblock) {
+#ifdef DEBUG
+ printm(M_INFO, _("write: throwing IOAgain for handle ") + GetName() + "\n");
+#endif
+ throw IOAgain();
+ } else {
+#ifdef HAVE_SLEEP
+ sleep(1);
+#endif
+ }
+ }
+ } else {
+ throw IOException(GetName(), IO_WRITE, count);
+ }
+ } else if (((size_t) r) != count) {
+ if (nonblock) {
+ return r;
+ }
+ full = done = false;
+ buf += r;
+ tr += r;
+ }
+ } while (!done);
+
+ return r + tr;
+}
+
+ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) {
+ ssize_t r;
+
+ if (closed) {
+ throw IOGeneral("Unable to read: handle `" + GetName() + "' is closed.");
+ }
+
+ if (!count)
+ return 0;
+
+#ifdef FULLDEBUG
+ printm(M_INFO, String(_("read: reading ")) + count + _(" bytes from handle ") + GetHandle() + "\n");
+#endif
+
+ errno = 0;
+ while ((r = uread(buf, count)) < 0) {
+ if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) {
+ // Avant de déclarer une erreur, on vérifie si ce n'est pas un
+ // problème lié au fait qu'il n'y a plus d'octets.
+ if (nonblock) {
+#ifdef DEBUG
+ printm(M_INFO, _("read: throwing IOAgain for handle ") + GetName() + "\n");
+#endif
+ throw IOAgain();
+ }
+ } else {
+ throw IOException(GetName(), IO_READ, count);
+ }
+ }
+
+ if (!r) {
+ close();
+ }
+
+ return r;
+}
+
+bool Handle::IsClosed(void) const {
+ return closed;
+}
+
+bool Handle::IsNonBlock(void) const {
+ return nonblock;
+}
+
+void Handle::SetNonBlock(void) {
+#ifdef HAVE_FCNTL
+ if ((h >= 0) || !nonblock) {
+ fcntl(h, F_SETFL, O_NONBLOCK);
+ }
+ nonblock = true;
+#endif
+}
+
+Handle & operator<<(Handle & h, const String & s) {
+ const char * p;
+
+ p = s.to_charp();
+ h.write(p, strlen(p));
+
+ return h;
+}
+
+Handle & operator>>(Handle & h, String & s) {
+ char t[BUFSIZ];
+ int i = 0, r;
+
+ while ((r = h.read(&(t[i]), 1)) && (i != (BUFSIZ - 1))) {
+ // Il y a souvent des \r\n dans les sockets par exemple,
+ // ou bien en lisant des fichiers au format MS-DOS. On
+ // ignore le \r pour ne garder que le \n, standard sous Unix.
+ if (t[i] == '\r') {
+ continue;
+ }
+ if (t[i] == '\n') {
+ break;
+ } else {
+ i++;
+ }
+ }
+
+ t[i] = '\0';
+ s = t;
+ return h;
+}
+
+void Handle::close() throw (GeneralException) {
+ if (IsClosed()) {
+ return;
+ }
+
+ Flush();
+
+ if (h >= 0) {
+ if (z >= 10) {
+ int err;
+ if (c == DEFLATE) {
+ err = deflateEnd(&zstrm);
+ if (err != Z_OK) {
+ throw GeneralException(String(_("Error during deflateEnd: ")) + zstrm.msg);
+ }
+ } else {
+ err = inflateEnd(&zstrm);
+ if (err != Z_OK) {
+ throw GeneralException(String(_("Error during inflateEnd: ")) + zstrm.msg);
+ }
+ }
+ err = ::close(h);
+ if (err) {
+ throw GeneralException(String(_("Error during (zstream) close: ")) + strerror(errno));
+ }
+ } else if (z) {
+#ifdef DEBUG
+ printm(M_INFO, String(_("Performing gzclose on handle ")) + h + "\n");
+#endif
+ int err = gzclose(zfile);
+#ifdef DEBUG
+ printm(M_INFO, String(_("gzclose returned ")) + err + "\n");
+#endif
+ if (err) {
+ if (err == Z_ERRNO) {
+ throw GeneralException(String(_("Error during close: ")) + strerror(errno));
+ } else {
+ throw GeneralException(String(_("Error in zlib during gzclose: ")) + gzerror(zfile, &err));
+ }
+ }
+ } else {
+ if (!hFile) {
+ int err = ::close(h);
+ if (err) {
+ throw GeneralException(String(_("Error during close: ")) + strerror(errno));
+ }
+ }
+ }
+#if defined (_WIN32) && !defined (NO_HFILE)
+ if (hFile) {
+ CloseHandle(hFile);
+ hFile = 0;
+ }
+#endif
+ }
+
+ if (mapped) {
+ munmap();
+ }
+
+ h = -1;
+ closed = 1;
+}
+
+bool Handle::CanRead(void) const {
+ return false;
+}
+
+bool Handle::CanWrite(void) const {
+ return false;
+}
+
+String Handle::GetName(void) const {
+ return _("Bare Handle - should not happend");
+}
+
+ssize_t Handle::GetSize(void) const {
+ return -1;
+}
+
+time_t Handle::GetModif(void) const {
+ return -1;
+}
+
+bool Handle::CanWatch(void) const {
+ return true;
+}
+
+int Handle::Dup() const throw (GeneralException) {
+ int d;
+
+ if ((d = dup(h)) < 0) {
+ throw IOGeneral(String(_("Error dupping file `")) + GetName() + _("' (handle ") + h + "): " + strerror(errno) + " (" + errno + ")");
+ }
+ return d;
+}
+
+void Handle::SetZ(int az) throw (GeneralException) {
+ if (z) {
+ throw GeneralException(_("Can't SetZ a Handle twice."));
+ }
+ if (h < 0) {
+ throw GeneralException(_("Can't SetZ a virtual Handle."));
+ }
+ if (az >= 10) {
+#ifdef DEBUG
+ printm(M_INFO, _("Setting up zstream using inflate/deflate...\n"));
+#endif
+ int err;
+ zstrm.zalloc = Z_NULL;
+ zstrm.zfree = Z_NULL;
+ if (CanWrite()) {
+ c = DEFLATE;
+ err = deflateInit(&zstrm, az - 10);
+ if (err != Z_OK) {
+ throw GeneralException(String(_("Error in deflateInit: ")) + zstrm.msg);
+ }
+ } else {
+ c = INFLATE;
+ zstrm.next_in = 0;
+ zstrm.avail_in = 0;
+ err = inflateInit(&zstrm);
+ if (err != Z_OK) {
+ throw GeneralException(String(_("Error in inflateInit: ")) + zstrm.msg);
+ }
+ }
+ } else if (az) {
+ char format[5];
+ int index = 0;
+ if (CanRead()) {
+ format[index++] = 'r';
+ }
+ if (CanWrite()) {
+ format[index++] = 'w';
+ }
+ format[index++] = (char) (az + '0');
+ format[index++] = 'b';
+ format[index] = 0;
+#ifdef FULLDEBUG
+ printm(M_INFO, String(_("Performing gzdopen on handle ")) + h + _(" with mode \"") + format + "\"\n");
+#endif
+ if (!(zfile = gzdopen(h, format))) {
+ throw GeneralException(String(_("Was not able to gzdopen: ")) + strerror(errno));
+ }
+ z = az;
+ }
+}
+
+ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) {
+ if (z >= 10) {
+ } else if (z) {
+#ifdef FULLDEBUG
+ printm(M_INFO, String(_("Performing gzwrite of ")) + count + _(" byte(s) for handle ") + h + "\n");
+#endif
+#ifdef HAVE_WD_ZLIB
+ int err = gzwrite(zfile, buf, count);
+#else
+ int err = gzwrite(zfile, (char *) buf, count);
+#endif
+ if (err == 0) {
+ const char * m = gzerror(zfile, &err);
+ if (err == Z_ERRNO) {
+ return -1;
+ } else {
+ throw GeneralException(String(_("Error in zlib during gzwrite: ")) + m);
+ }
+ }
+ itell += err;
+ return err;
+ } else {
+ itell += count = ::write(h, buf, count);
+ return count;
+ }
+}
+
+ssize_t Handle::uread(void * buf, size_t count) {
+ if (z >= 10) {
+ } if (z) {
+#ifdef DEBUG
+ printm(M_BARE, String(_("Performing gzread of ")) + count + _(" byte(s) for handle ") + h + "\n");
+#endif
+ int err = gzread(zfile, buf, count);
+ if (err == -1) {
+ gzerror(zfile, &err);
+ if (err == Z_ERRNO) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ itell += err;
+ return err;
+ } else {
+#if defined (_WIN32) && !defined (NO_HFILE)
+ if (hFile) {
+ DWORD rcount;
+ if (!ReadFile(hFile, buf, count, &rcount, 0)) {
+ // Error..
+ }
+ itell += count = rcount;
+ } else
+#endif
+ itell += count = ::read(h, buf, count);
+ return count;
+ }
+}
+
+off_t Handle::tell() const {
+ if (z) {
+ return gztell(zfile);
+ } else {
+ return itell;
+ }
+}
+
+bool Handle::CanSeek() const {
+ return 0;
+}
+
+off_t Handle::seek(off_t offset, int whence) throw(GeneralException) {
+ if (z) {
+ return itell = gzseek(zfile, offset, whence);
+ } else {
+ throw IOGeneral(_("Handle ") + GetName() + _(" can't seek"));
+ }
+}
+
+Uint8 Handle::readU8() {
+ Uint8 r;
+ read(&r, 1);
+ return r;
+}
+
+Uint16 Handle::readU16() {
+ Uint16 r;
+ read(&r, 2);
+#ifdef WORDS_BIGENDIAN
+ return bswap_16(r);
+#else
+ return r;
+#endif
+}
+
+Uint32 Handle::readU32() {
+ Uint32 r;
+ read(&r, 4);
+#ifdef WORDS_BIGENDIAN
+ return bswap_32(r);
+#else
+ return r;
+#endif
+}
+
+void Handle::writeU8(Uint8 v) {
+ write(&v, 1);
+}
+
+void Handle::writeU16(Uint16 v) {
+#ifdef WORDS_BIGENDIAN
+ Uint16 t = bswap_16(v);
+ write(&t, 2);
+#else
+ write(&v, 2);
+#endif
+}
+
+void Handle::writeU32(Uint32 v) {
+#ifdef WORDS_BIGENDIAN
+ Uint32 t = bswap_32(v);
+ write(&t, 4);
+#else
+ write(&v, 4);
+#endif
+}
+
+void Handle::copyto(Handle * dest, ssize_t s) {
+ copy(this, dest, s);
+}
+
+void Handle::copyfrom(Handle * src, ssize_t s) {
+ copy(src, this, s);
+}
+
+void copyone(Handle * s, Handle * d, ssize_t size) {
+ long i;
+ unsigned char c;
+ long r;
+
+ if (size < 0)
+ size = s->GetSize();
+
+ for (i = 0; (i < size) || (size < 0); i++) {
+ r = s->read(&c, 1);
+ if (r == 0) {
+ break;
+ }
+ d->write(&c, 1);
+ }
+}
+
+#define BSIZE 20480
+
+void copy(Handle * s, Handle * d, ssize_t size) {
+ long i;
+ static unsigned char b[BSIZE];
+ long r;
+
+ if (size < 0)
+ size = s->GetSize();
+
+ LOCK;
+
+ while (size) {
+ if ((size > BSIZE) || (size < 0)) {
+ r = s->read(b, BSIZE);
+ if (r)
+ d->write(b, r);
+ } else {
+ r = s->read(b, size);
+ if (r)
+ d->write(b, r);
+ }
+ if (!r)
+ break;
+ if (size > 0)
+ size -= r;
+ }
+
+ UNLOCK;
+}
+
+void Handle::Flush() {
+ if (!CanWrite())
+ return;
+ if (h < 0)
+ return;
+ if (z >= 10) {
+
+ } else if (z) {
+ gzflush(&z, Z_FULL_FLUSH);
+ } else {
+#ifdef HAVE_FSYNC
+ fsync(h);
+#endif
+ }
+}
+
+void * Handle::mmap(off_t offset, size_t length) throw (GeneralException) {
+ void * r;
+
+ if (h == -1) {
+ throw GeneralException("Can't mmap() a virtual handle");
+ }
+#ifdef _WIN32
+ if (!hFile) {
+ throw GeneralException("Can't mmap() a non-hFile handle under windows");
+ }
+#endif
+ if (mapped) {
+ throw GeneralException("Handle already mmap()ped");
+ }
+ mapped = true;
+ if (length == -1) {
+ length = GetSize();
+ }
+ maplength = length;
+#ifndef _WIN32
+ r = ::mmap(0, length, (CanRead() ? PROT_READ : 0) | (CanWrite() ? PROT_WRITE : 0), MAP_SHARED, h, offset);
+ if (!r) {
+ throw GeneralException(String("Was not able to mmap(): ") + strerror(errno));
+ }
+#else
+ hMapObject = CreateFileMapping(
+ hFile,
+ 0,
+ CanWrite() ? PAGE_READWRITE : PAGE_READONLY,
+ 0,
+ length,
+ GetName().to_charp());
+ if (hMapObject != NULL) {
+ r = MapViewOfFile(
+ hMapObject,
+ CanWrite() ? FILE_MAP_WRITE : FILE_MAP_READ,
+ 0,
+ offset,
+ length);
+ if (!r) {
+ CloseHandle(hMapObject);
+ throw GeneralException("Was not able to MapViewOfFile()");
+ }
+ } else {
+ throw GeneralException("Was not able to CreateFileMapping()");
+ }
+#endif
+
+ mappedarea = r;
+
+ return r;
+}
+
+void Handle::munmap() throw (GeneralException) {
+ if (!mapped) {
+ throw GeneralException("Can't munmap, was not mapped");
+ }
+#ifndef _WIN32
+ if (::munmap(mappedarea, maplength)) {
+ throw GeneralException(String("Was not able to munmap(): ") + strerror(errno));
+ }
+#else
+ if (!UnmapViewOfFile(mappedarea)) {
+ throw GeneralException("Was not able to UnmapViewOfFile()");
+ }
+ CloseHandle(hMapObject);
+#endif
+ mapped = false;
+ mappedarea = 0;
+ maplength = 0;
+}
|