summaryrefslogtreecommitdiff
path: root/lib/Handle.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Handle.cc')
-rw-r--r--lib/Handle.cc100
1 files changed, 94 insertions, 6 deletions
diff --git a/lib/Handle.cc b/lib/Handle.cc
index c02bc55..7b56df4 100644
--- a/lib/Handle.cc
+++ b/lib/Handle.cc
@@ -6,13 +6,21 @@
#include "Handle.h"
#include "config.h"
-Handle::Handle(const Handle & nh) : h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(false), nonblock(false) { }
+Handle::Handle(const Handle & nh) : h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(false), nonblock(false), zfile(0), z(0) {
+ cerr << "Duplication of handle " << nh.h << " to " << h << endl;
+ if ((h >= 0) && (nh.z)) {
+ SetZ(nh.z);
+ }
+}
Handle::~Handle() {
+ cerr << "Destroying handle " << h << endl;
close();
}
-Handle::Handle(int nh) : h(nh), closed(false) { }
+Handle::Handle(int nh) : h(nh), closed(false), zfile(0), z(0) {
+ cerr << "Initialising handle " << h << endl;
+}
int Handle::GetHandle() {
return h;
@@ -25,7 +33,7 @@ ssize_t Handle::write(const void *buf, size_t count) throw (GeneralException) {
do {
done = true;
errno = 0;
- if ((r = ::write(h, buf, count)) < 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
@@ -60,7 +68,7 @@ ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) {
ssize_t r;
errno = 0;
- if ((r = ::read(h, buf, count)) < 0) {
+ if ((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.
@@ -124,13 +132,29 @@ Handle & operator>>(Handle & h, String & s) {
return h;
}
-void Handle::close() {
+void Handle::close() throw (GeneralException) {
if (IsClosed()) {
return;
}
if (h >= 0) {
- ::close(h);
+ if (z) {
+ cerr << "Performing gzclose on handle " << h << endl;
+ int err = gzclose(zfile);
+ cerr << "gzclose returned " << err << endl;
+ if (err) {
+ if (err == Z_ERRNO) {
+ throw GeneralException(String(_("Error during close: ")) + strerror(errno));
+ } else {
+ throw GeneralException(_("Error in zlib during gzclose."));
+ }
+ }
+ } else {
+ int err = ::close(h);
+ if (err) {
+ throw GeneralException(String(_("Error during close: ")) + strerror(errno));
+ }
+ }
}
h = -1;
@@ -168,3 +192,67 @@ void Handle::Dup(const Handle & H) {
h = dup(H.h);
}
}
+
+void Handle::SetZ(int az) throw (GeneralException) {
+ if (z) {
+ throw GeneralException(_("Can't SetZ a Handle twice."));
+ }
+ z = az;
+ if (h < 0) {
+ throw GeneralException(_("Can't SetZ a virtual Handle."));
+ }
+ if (z) {
+ char format[4];
+ int index = 0;
+ if (CanRead()) {
+ format[index++] = 'r';
+ }
+ if (CanWrite()) {
+ format[index++] = 'w';
+ }
+ format[index++] = (char) (z + '0');
+ format[index] = 0;
+ cerr << "Performing gzdopen on handle " << h << " with mode \"" << format << "\"\n";
+ if (!(zfile = gzdopen(h, format))) {
+ throw GeneralException(_("Was not able to gzdopen."));
+ }
+ }
+}
+
+ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) {
+ if (z) {
+ cerr << "Performing gzwrite of " << count << " byte for handle " << h << endl;
+ int err = gzwrite(zfile, buf, count);
+ cerr << "gzwrite returned " << err << endl;
+ 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);
+ }
+ }
+ return err;
+ } else {
+ return ::write(h, buf, count);
+ }
+}
+
+ssize_t Handle::uread(void * buf, size_t count) {
+ if (z) {
+ cerr << "Performing gzread of " << count << " byte for handle " << h << endl;
+ int err = gzread(zfile, buf, count);
+ cerr << "gzwrite returned " << err << endl;
+ if (err == -1) {
+ gzerror(zfile, &err);
+ if (err == Z_ERRNO) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ return err;
+ } else {
+ return ::read(h, buf, count);
+ }
+}