summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--include/Handle.h2
-rw-r--r--include/Input.h42
-rw-r--r--lib/Handle.cc21
-rw-r--r--lib/Input.cc184
5 files changed, 190 insertions, 60 deletions
diff --git a/configure.ac b/configure.ac
index 04b9d60..f69a841 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,7 @@ AC_CHECK_FUNCS([__argz_count __argz_next __argz_stringify getcwd gethostbyname m
AC_SEARCH_LIBS(socket, socket)
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(deflate, z)
+AC_SEARCH_LIBS(EF_Print, efence)
if test x$ac_cv_search_deflate != xno ; then
OLDCPPFLAGS=$CPPFLAGS
diff --git a/include/Handle.h b/include/Handle.h
index 998c126..25b22a7 100644
--- a/include/Handle.h
+++ b/include/Handle.h
@@ -29,7 +29,7 @@ class Handle : public Base {
void close() throw (GeneralException);
int GetHandle();
virtual bool CanWatch() const;
- virtual void Dup(const Handle &);
+ virtual int Dup() const;
virtual void SetZ(int = 9) throw (GeneralException);
protected:
Handle(int h);
diff --git a/include/Input.h b/include/Input.h
index 9395687..19d8f7d 100644
--- a/include/Input.h
+++ b/include/Input.h
@@ -6,6 +6,10 @@
#include <BString.h>
#include <Handle.h>
+enum ArchiveType {
+ ARCHIVE_BUILTIN = 0
+};
+
class Input : public Handle {
public:
Input(const String & = "") throw (GeneralException);
@@ -18,11 +22,23 @@ class Input : public Handle {
virtual String GetName() const;
virtual ssize_t GetSize() const;
virtual time_t GetModif() const;
+ virtual void SetZ(int = 9) throw (GeneralException);
+
+ struct openresults_t {
+ String name;
+ int type;
+ size_t size;
+ size_t ptr;
+ };
protected:
String n;
off_t size;
time_t date_modif;
+ openresults_t results;
+
+ private:
+ static int wrapopen(const String &, openresults_t *);
};
class Stdin_t : public Input {
@@ -35,36 +51,40 @@ class Stdin_t : public Input {
extern Stdin_t Stdin;
-enum ArchiveType {
- ARCHIVE_BUILTIN = 0
-}
-
class Archive : public Base {
public:
- Archive(const String &, ArchiveType = 0) throw (GeneralException);
+ Archive(const String &, int = 0) throw (GeneralException);
virtual ~Archive();
+ protected:
static bool inarchive(const String &);
- static Input & open(const String &) throw (GeneralException);
+ static int open(const String &, Input::openresults_t *) throw (GeneralException);
private:
bool inarchivein(const String &);
- Input & openin(const String &) throw (GeneralException);
+ int openin(const String &, Input::openresults_t *) throw (GeneralException);
class FileTree : public Base {
public:
- FileTree(const String & = "", size_t = 0, FileTree * = 0, int = 0);
+ FileTree(const String & = "", size_t = 0, int = 0, FileTree * = 0);
virtual ~FileTree();
int compute_ptrs(size_t = 0);
- String name;
- int type;
+ FileTree * Father();
+ FileTree * Child();
+ FileTree * Next();
+ FileTree * Prev();
+ String name;
+ int type;
size_t size;
size_t ptr;
private:
- void touched();
+ void touched();
FileTree * next, * prev, * father, * child;
} filetree;
String name;
Input archive;
+ int type;
Archive * next, * prev;
static Archive * header;
+
+ friend class Input;
};
#endif
diff --git a/lib/Handle.cc b/lib/Handle.cc
index 70683b1..912e779 100644
--- a/lib/Handle.cc
+++ b/lib/Handle.cc
@@ -226,11 +226,8 @@ bool Handle::CanWatch(void) const {
return true;
}
-void Handle::Dup(const Handle & H) {
- close();
- if (H.h >= 0) {
- h = dup(H.h);
- }
+int Handle::Dup() const {
+ return dup(h);
}
void Handle::SetZ(int az) throw (GeneralException) {
@@ -316,15 +313,23 @@ ssize_t Handle::uread(void * buf, size_t count) {
}
off_t Handle::tell() const {
- return itell;
+ if (z) {
+ return gztell(zfile);
+ } else {
+ return itell;
+ }
}
bool Handle::CanSeek() const {
return 0;
}
-off_t Handle::seek(off_t, int) throw(GeneralException) {
- throw IOGeneral("Handle " + GetName() + " can't seek");
+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");
+ }
}
void copy(Handle * s, Handle * d, ssize_t size) {
diff --git a/lib/Input.cc b/lib/Input.cc
index c720f9d..4c9ad2e 100644
--- a/lib/Input.cc
+++ b/lib/Input.cc
@@ -20,8 +20,12 @@
#define S_ISREG(x) 1
#endif
+#define DEBUG
+
+#define BUILTIN_SIG 0x5141504e
+
Input::Input(const String & no) throw (GeneralException) :
- Handle(no.strlen() ? open(no.to_charp(), O_RDONLY) : dup(0)),
+ Handle(no.strlen() ? wrapopen(no, &results) : dup(0)),
n(no) {
#ifdef DEBUG
@@ -32,13 +36,21 @@ Input::Input(const String & no) throw (GeneralException) :
throw IOGeneral(String(_("Error opening file ")) + no + _(" for reading: ") + strerror(errno));
}
- struct stat s;
- fstat(GetHandle(), &s);
- date_modif = s.st_mtime;
-
- if (S_ISREG(s.st_mode)) {
- size = seek(0, SEEK_END);
- seek(0, SEEK_SET);
+ if (results.name == "") {
+ struct stat s;
+ fstat(GetHandle(), &s);
+ date_modif = s.st_mtime;
+
+ if (S_ISREG(s.st_mode)) {
+ size = seek(0, SEEK_END);
+ seek(0, SEEK_SET);
+ }
+ } else {
+// size = results.size;
+ seek(results.ptr, SEEK_SET);
+ read(&size, 4);
+ date_modif = 0;
+ SetZ();
}
}
@@ -74,15 +86,41 @@ time_t Input::GetModif() const {
}
off_t Input::seek(off_t offset, int whence) throw (GeneralException) {
- if ((itell = lseek(GetHandle(), offset, whence)) < 0) {
- throw IOGeneral(String(_("Error seeking file ")) + GetName() + _(": ") + strerror(errno));
- }
+ if (results.name == "") {
+ if ((itell = lseek(GetHandle(), offset, whence)) < 0) {
+ throw IOGeneral(String(_("Error seeking file ")) + GetName() + _(": ") + strerror(errno));
+ }
#ifdef PARANOID_SEEK
- if (itell != lseek(GetHandle(), 0, SEEK_CUR)) {
- throw IOGeneral(String(_("Error seeking file ")) + GetName() + _(": the position does not match"));
+ if (itell != lseek(GetHandle(), 0, SEEK_CUR)) {
+ throw IOGeneral(String(_("Error seeking file ")) + GetName() + _(": the position does not match"));
+ }
+#endif
+ return itell;
+ } else {
+ return Handle::seek(offset, whence);
}
+}
+
+int Input::wrapopen(const String & fname, openresults_t * results) {
+#ifdef DEBUG
+ std::cerr << "Wrap-opening " << fname << std::endl;
+#endif
+ if (fname[0] != '/') {
+ bool t;
+ t = Archive::inarchive(fname);
+ if (t) {
+#ifdef DEBUG
+ std::cerr << "Trying to open the file in archive, since it seems to be here\n";
#endif
- return itell;
+ return Archive::open(fname, results);
+ }
+ }
+ return open(fname.to_charp(), O_RDONLY);
+}
+
+void Input::SetZ(int l) throw(GeneralException) {
+ if (results.name == "")
+ Handle::SetZ(l);
}
#ifdef HOOK_STDS
@@ -101,10 +139,39 @@ Stdin_t Stdin;
Archive * Archive::header = 0;
-Archive::Archive(const String & fname, ArchiveType type) : name(fname), archive(fname) throw (GeneralException) {
+Archive::Archive(const String & fname, int atype) throw (GeneralException) :
+ name(fname), archive(fname), type(atype) {
+ char buffer[1024];
+ int len;
+ size_t size;
+ FileTree * p = &filetree, * t;
+ String ifname;
+
switch(type) {
case ARCHIVE_BUILTIN:
-
+ archive.read(buffer, 4);
+ if (*((Uint32 *)buffer) != BUILTIN_SIG)
+ throw GeneralException("Archive: not in built-in format.");
+ while (p) {
+ archive.read(buffer, 1);
+ len = *buffer;
+ if (len) {
+ archive.read(buffer, len);
+ buffer[len] = 0;
+ ifname = buffer;
+ archive.read(&size, 4);
+ archive.read(buffer, 1);
+#ifdef DEBUG
+ std::cerr << "Adding file `" << ifname << "' to node `" << p->name << "'\n";
+#endif
+ t = new FileTree(ifname, size, buffer[0], p);
+ if (buffer[0])
+ p = t;
+ } else {
+ p = p->Father();
+ }
+ }
+ filetree.compute_ptrs(archive.tell());
break;
default:
throw GeneralException("Archive: unsupported archive format.");
@@ -130,30 +197,39 @@ Archive::~Archive() {
bool Archive::inarchive(const String & fname) {
Archive * p;
for (p = header; p; p = p->next) {
- if (p->inarchive(fname))
+#ifdef DEBUG
+ std::cerr << "Looking for file `" << fname << "' in archive " << p->name << std::endl;
+#endif
+ if (p->inarchivein(fname)) {
+#ifdef DEBUG
+ std::cerr << "File `" << fname << "' found in archive " << p->name << std::endl;
+#endif
return true;
+ }
}
return false;
}
-Input & Archive::open(const String & fname) throw (GeneralException) {
+int Archive::open(const String & fname, Input::openresults_t * results) throw (GeneralException) {
Archive * p;
for (p = header; p; p = p->next) {
- if (p->inarchive(fname))
- return p->open(fname);
+ bool t;
+ t = p->inarchive(fname);
+ if (t)
+ return p->openin(fname, results);
}
throw IOGeneral("File `" + fname + "' not found in archive collection.");
}
bool Archive::inarchivein(const String & fname) {
- Archive::FileTree * p = filetree->child;
+ Archive::FileTree * p = filetree.Child();
ssize_t pos;
String name = fname;
String reste;
while((name != "") && p) {
- ssize_t pos = name.strchr('/');
+ pos = name.strchr('/');
if (pos >= 0) {
reste = name.extract(0, pos - 1);
name = name.extract(pos + 1);
@@ -161,13 +237,17 @@ bool Archive::inarchivein(const String & fname) {
reste = name;
name = "";
}
-
+#ifdef DEBUG
+ std::cerr << "inarchivein: reste = `" << reste << "' - name = `" << name << "'\n";
+ std::cerr << "Checking against node `" << p->name << "'\n";
+#endif
while (p) {
if (p->name == reste) {
- p = p->child;
+ if (name != "")
+ p = p->Child();
break;
} else {
- p = p->next;
+ p = p->Next();
}
}
}
@@ -175,14 +255,14 @@ bool Archive::inarchivein(const String & fname) {
return p;
}
-Input & Archive::openin(const String & fname) throw (GeneralException) {
- Archive::FileTree * p = filetree->child;
+int Archive::openin(const String & fname, Input::openresults_t * results) throw (GeneralException) {
+ Archive::FileTree * p = filetree.Child();
ssize_t pos;
String name = fname;
String reste;
while((name != "") && p) {
- ssize_t pos = name.strchr('/');
+ pos = name.strchr('/');
if (pos >= 0) {
reste = name.extract(0, pos - 1);
name = name.extract(pos + 1);
@@ -193,26 +273,29 @@ Input & Archive::openin(const String & fname) throw (GeneralException) {
while (p) {
if (p->name == reste) {
- p = p->child;
+ if (name != "")
+ p = p->Child();
break;
} else {
- p = p->next;
+ p = p->Next();
}
}
}
if (!p)
- throw IOGeneral("File `" + fname + "' not in archive " + name);
+ throw IOGeneral("File `" + fname + "' not in archive " + this->name);
- if (p->child)
- throw IOGeneral("File `" + fname + "' in archive " + name + " is a directory - can't open.");
-
- Input file(archive);
- file->seek(p->ptr);
- return file;
+ if (p->Child())
+ throw IOGeneral("File `" + fname + "' in archive " + this->name + " is a directory - can't open.");
+
+ results->name = p->name;
+ results->ptr = p->ptr;
+ results->size = p->size;
+ results->type = p->type;
+ return archive.Dup();
}
-Archive::FileTree::FileTree(const String & fname, size_t fsize, Archive::FileTree * fFather, int ftype) :
+Archive::FileTree::FileTree(const String & fname, size_t fsize, int ftype, Archive::FileTree * fFather) :
name(fname), type(ftype), size(fsize), next(0), prev(0), father(fFather), child(0) {
if (father) {
if (father->child) {
@@ -220,6 +303,11 @@ Archive::FileTree::FileTree(const String & fname, size_t fsize, Archive::FileTre
for (p = father->child; p->next; p = p->next);
p->next = this;
prev = p;
+ } else {
+#ifdef DEBUG
+ std::cerr << "Adding `" << fname << "' as first child of node `" << father->name << "'\n";
+#endif
+ father->child = this;
}
}
}
@@ -240,12 +328,12 @@ Archive::FileTree::~FileTree() {
void Archive::FileTree::touched() {
if (father)
- father->touched()
+ father->touched();
else
compute_ptrs(ptr);
}
-int Archive::FileTree::compute_ptrs(int cptr) {
+int Archive::FileTree::compute_ptrs(size_t cptr) {
ptr = cptr;
if (child) {
@@ -258,3 +346,19 @@ int Archive::FileTree::compute_ptrs(int cptr) {
return size + ptr;
}
+
+Archive::FileTree * Archive::FileTree::Father() {
+ return father;
+}
+
+Archive::FileTree * Archive::FileTree::Child() {
+ return child;
+}
+
+Archive::FileTree * Archive::FileTree::Next() {
+ return next;
+}
+
+Archive::FileTree * Archive::FileTree::Prev() {
+ return prev;
+}