summaryrefslogtreecommitdiff
path: root/lib/Handle.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Handle.cc')
-rw-r--r--lib/Handle.cc1316
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;
+}