diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | include/Handle.h | 2 | ||||
-rw-r--r-- | include/Input.h | 42 | ||||
-rw-r--r-- | lib/Handle.cc | 21 | ||||
-rw-r--r-- | lib/Input.cc | 184 |
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; +} |