--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/Digest.cc
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#include <cstdio> // snprintf
+#include <openssl/evp.h>
+#include <string>
+
+#include <iostream>
+
+#ifdef DIGEST_TESTSUITE
+#include <fstream>
+#endif
+
+#include "zypp/Digest.h"
+
+namespace zypp {
+
+ // private data
+ class Digest::P
+ {
+ P(const P& p);
+ const P& operator=(const P& p);
+ public:
+ P();
+ ~P();
+
+ EVP_MD_CTX mdctx;
+
+ const EVP_MD *md;
+ unsigned char md_value[EVP_MAX_MD_SIZE];
+ unsigned md_len;
+
+ bool initialized : 1;
+ bool finalized : 1;
+ static bool openssl_digests_added;
+
+ std::string name;
+
+ inline bool maybeInit();
+ inline void cleanup();
+ };
+
+
+ using namespace std;
+
+ bool Digest::P::openssl_digests_added = false;
+
+ Digest::P::P() :
+ md(NULL),
+ initialized(false),
+ finalized(false)
+ {
+ }
+
+ Digest::P::~P()
+ {
+ cleanup();
+ }
+
+ bool Digest::P::maybeInit()
+ {
+ if(!openssl_digests_added)
+ {
+ OpenSSL_add_all_digests();
+ openssl_digests_added = true;
+ }
+
+ if(!initialized)
+ {
+ md = EVP_get_digestbyname(name.c_str());
+ if(!md)
+ return false;
+
+ EVP_MD_CTX_init(&mdctx);
+
+ if(!EVP_DigestInit_ex(&mdctx, md, NULL))
+ return false;
+
+ md_len = 0;
+ ::memset(md_value, 0, sizeof(md_value));
+ initialized = true;
+ }
+
+ return true;
+ }
+
+ void Digest::P::cleanup()
+ {
+ if(initialized)
+ {
+ EVP_MD_CTX_cleanup(&mdctx);
+ initialized = false;
+ }
+ }
+
+ Digest::Digest() : _dp(new P())
+ {
+ }
+
+ Digest::~Digest()
+ {
+ delete _dp;
+ }
+
+ bool Digest::create(const std::string& name)
+ {
+ if(name.empty()) return false;
+
+ if(_dp->initialized)
+ _dp->cleanup();
+
+ _dp->name = name;
+
+ return _dp->maybeInit();
+ }
+
+ const std::string& Digest::name()
+ {
+ return _dp->name;
+ }
+
+ std::string Digest::digest()
+ {
+ if(!_dp->maybeInit())
+ return false;
+
+ if(!_dp->finalized)
+ {
+ if(!EVP_DigestFinal_ex(&_dp->mdctx, _dp->md_value, &_dp->md_len))
+ return false;
+
+ _dp->finalized = true;
+ }
+
+ char mdtxt[_dp->md_len*2 + 1];
+ mdtxt[_dp->md_len*2] = '\0';
+
+ for(unsigned i = 0; i < _dp->md_len; ++i)
+ {
+ ::snprintf(mdtxt + i*2, 3, "%02hhx", _dp->md_value[i]);
+ }
+
+ return std::string(mdtxt);
+ }
+
+ bool Digest::update(const char* bytes, size_t len)
+ {
+ if(!bytes)
+ {
+ return false;
+ }
+
+ if(!_dp->maybeInit())
+ return false;
+
+ if(_dp->finalized)
+ {
+ _dp->cleanup();
+ if(!_dp->maybeInit())
+ return false;
+
+ }
+ if(!EVP_DigestUpdate(&_dp->mdctx, reinterpret_cast<const unsigned char*>(bytes), len))
+ return false;
+
+ return true;
+ }
+
+ std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
+ {
+ if(name.empty() || !is)
+ return string();
+
+ char buf[bufsize];
+ size_t num;
+
+ Digest digest;
+ if(!digest.create(name))
+ return string();
+
+ while(is.good())
+ {
+ for(num = 0; num < bufsize && is.get(buf[num]).good(); ++num);
+
+ if(num && !digest.update(buf, num))
+ return string();
+ }
+
+ return digest.digest();
+ }
+
+#ifdef DIGEST_TESTSUITE
+ int main(int argc, char *argv[])
+ {
+ bool openssl = false;
+ unsigned argpos = 1;
+
+ if(argc > 1 && string(argv[argpos]) == "--openssl")
+ {
+ openssl = true;
+ ++argpos;
+ }
+
+ if(argc - argpos < 2)
+ {
+ cerr << "Usage: " << argv[0] << " <DIGESTNAME> <FILE>" << endl;
+ return 1;
+ }
+
+ const char* digestname = argv[argpos++];
+ const char* fn = argv[argpos++];
+
+ ifstream file(fn);
+
+ string digest = Digest::digest(digestname, file);
+
+ if(openssl)
+ cout << digestname << "(" << fn << ")= " << digest << endl;
+ else
+ cout << digest << " " << fn << endl;
+
+ return 0;
+ }
+#endif
+
+} // namespace zypp
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp//Digest.h
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#ifndef ZYPP_MEDIA_DIGEST_H
+#define ZYPP_MEDIA_DIGEST_H
+
+#include <string>
+#include <iosfwd>
+
+namespace zypp {
+
+ /** \brief Compute Message Digests (MD5, SHA1 etc)
+ *
+ * The computation works by initializing the algorithm using create(). This
+ * will construct an internal state. successive calls to update() deliver the
+ * data for which the digest is to be computed. After all data has been
+ * deliverd, a call to digest() finalizes the computation and returns the
+ * result
+ * */
+ class Digest
+ {
+ private:
+ class P;
+ P* _dp;
+
+ // disabled
+ Digest(const Digest& d);
+ // disabled
+ const Digest& operator=(const Digest& d);
+
+ public:
+ Digest();
+ ~Digest();
+
+ /** \brief initialize creation of a new message digest
+ *
+ * Since openssl is used as backend you may use anything that openssl
+ * supports (see man 1 dgst). Common examples are md5 or sha1. sha1
+ * should be preferred when creating digests to verify the authenticity
+ * of something.
+ *
+ * successive calls to this funcion will destroy the internal state and
+ * reinit from scratch
+ *
+ * @param name name of the message digest algorithm.
+ * @return whether an error occured
+ * */
+ bool create(const std::string& name);
+
+ /** \brief get the name of the current digest algorithm */
+ const std::string& name();
+
+ /** \brief feed data into digest computation algorithm
+ * @param bytes
+ * @param len
+ * @return whether an error occured
+ * */
+ bool update(const char* bytes, size_t len);
+
+ /** \brief get hex string representation of the digest
+ *
+ * this function will finalize the digest computation. calls to update
+ * after this function will start from scratch
+ *
+ * @return hex string representation of the digest
+ * */
+ std::string digest();
+
+ /** \brief compute digest of a stream. convenience function
+ *
+ * calls create, update and digest in one function. The data for the
+ * computation is read from the stream
+ *
+ * @param name name of the digest algorithm, \see create
+ * @param is an input stream to get the data from
+ * @param bufsize size of the buffer used for update(). Be careful, this is on the stack.
+ * @return the digest or empty on error
+ * */
+ static std::string digest(const std::string& name, std::istream& is, size_t bufsize = 4096);
+ };
+
+} // namespace zypp
+
+#endif
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/ExternalProgram.cc
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#define _GNU_SOURCE 1 // for ::getline
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pty.h> // openpty
+#include <stdlib.h> // setenv
+
+#include <cstring> // strsignal
+#include <iostream>
+
+#include "zypp/base/Logger.h"
+#include "zypp/ExternalProgram.h"
+
+using namespace std;
+
+namespace zypp {
+
+ ExternalProgram::ExternalProgram (string commandline,
+ Stderr_Disposition stderr_disp, bool use_pty,
+ int stderr_fd, bool default_locale,
+ const Pathname& root)
+ : use_pty (use_pty)
+ {
+ const char *argv[4];
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = commandline.c_str();
+ argv[3] = 0;
+
+ const char* rootdir = NULL;
+ if(!root.empty() && root != "/")
+ {
+ rootdir = root.asString().c_str();
+ }
+ Environment environment;
+ start_program (argv, environment, stderr_disp, stderr_fd, default_locale, rootdir);
+ }
+
+
+ ExternalProgram::ExternalProgram (const char *const *argv,
+ Stderr_Disposition stderr_disp, bool use_pty,
+ int stderr_fd, bool default_locale,
+ const Pathname& root)
+ : use_pty (use_pty)
+ {
+ const char* rootdir = NULL;
+ if(!root.empty() && root != "/")
+ {
+ rootdir = root.asString().c_str();
+ }
+ Environment environment;
+ start_program (argv, environment, stderr_disp, stderr_fd, default_locale, rootdir);
+ }
+
+
+ ExternalProgram::ExternalProgram (const char *const *argv, const Environment & environment,
+ Stderr_Disposition stderr_disp, bool use_pty,
+ int stderr_fd, bool default_locale,
+ const Pathname& root)
+ : use_pty (use_pty)
+ {
+ const char* rootdir = NULL;
+ if(!root.empty() && root != "/")
+ {
+ rootdir = root.asString().c_str();
+ }
+ start_program (argv, environment, stderr_disp, stderr_fd, default_locale, rootdir);
+ }
+
+
+ ExternalProgram::ExternalProgram (const char *binpath, const char *const *argv_1,
+ bool use_pty)
+ : use_pty (use_pty)
+ {
+ int i = 0;
+ while (argv_1[i++])
+ ;
+ const char *argv[i + 1];
+ argv[0] = binpath;
+ memcpy (&argv[1], argv_1, (i - 1) * sizeof (char *));
+ Environment environment;
+ start_program (argv, environment);
+ }
+
+
+ ExternalProgram::ExternalProgram (const char *binpath, const char *const *argv_1, const Environment & environment,
+ bool use_pty)
+ : use_pty (use_pty)
+ {
+ int i = 0;
+ while (argv_1[i++])
+ ;
+ const char *argv[i + 1];
+ argv[0] = binpath;
+ memcpy (&argv[1], argv_1, (i - 1) * sizeof (char *));
+ start_program (argv, environment);
+ }
+
+
+ ExternalProgram::~ExternalProgram()
+ {
+ }
+
+
+ void
+ ExternalProgram::start_program (const char *const *argv, const Environment & environment,
+ Stderr_Disposition stderr_disp,
+ int stderr_fd, bool default_locale, const char* root)
+ {
+ pid = -1;
+ _exitStatus = 0;
+ int to_external[2], from_external[2]; // fds for pair of pipes
+ int master_tty, slave_tty; // fds for pair of ttys
+
+ if (use_pty)
+ {
+ // Create pair of ttys
+ DBG << "Using ttys for communication with " << argv[0] << endl;
+ if (openpty (&master_tty, &slave_tty, 0, 0, 0) != 0)
+ {
+ ERR << "openpty failed" << endl;
+ return;
+ }
+ }
+ else
+ {
+ // Create pair of pipes
+ if (pipe (to_external) != 0 || pipe (from_external) != 0)
+ {
+ ERR << "pipe failed" << endl;
+ return;
+ }
+ }
+
+ // do not remove the single quotes around every argument, copy&paste of
+ // command to shell will not work otherwise!
+ DBG << "Executing ";
+ for (int i = 0; argv[i]; i++)
+ {
+ if (i>0) DBG << ' ';
+ DBG << '\'';
+ DBG << argv[i];
+ DBG << '\'';
+ }
+ DBG << endl;
+
+ // Create module process
+ if ((pid = fork()) == 0)
+ {
+ if (use_pty)
+ {
+ setsid();
+ if(slave_tty != 1)
+ dup2 (slave_tty, 1); // set new stdout
+ renumber_fd (slave_tty, 0); // set new stdin
+ ::close(master_tty); // Belongs to father process
+
+ // We currently have no controlling terminal (due to setsid).
+ // The first open call will also set the new ctty (due to historical
+ // unix guru knowledge ;-) )
+
+ char name[512];
+ ttyname_r(slave_tty, name, sizeof(name));
+ ::close(open(name, O_RDONLY));
+ }
+ else
+ {
+ renumber_fd (to_external[0], 0); // set new stdin
+ ::close(from_external[0]); // Belongs to father process
+
+ renumber_fd (from_external[1], 1); // set new stdout
+ ::close(to_external [1]); // Belongs to father process
+ }
+
+ // Handle stderr
+ if (stderr_disp == Discard_Stderr)
+ {
+ int null_fd = open("/dev/null", O_WRONLY);
+ dup2(null_fd, 2);
+ ::close(null_fd);
+ }
+ else if (stderr_disp == Stderr_To_Stdout)
+ {
+ dup2(1, 2);
+ }
+ else if (stderr_disp == Stderr_To_FileDesc)
+ {
+ // Note: We don't have to close anything regarding stderr_fd.
+ // Our caller is responsible for that.
+ dup2 (stderr_fd, 2);
+ }
+
+ for ( Environment::const_iterator it = environment.begin(); it != environment.end(); ++it ) {
+ setenv( it->first.c_str(), it->second.c_str(), 1 );
+ }
+
+ if(default_locale)
+ setenv("LC_ALL","C",1);
+
+ if(root)
+ {
+ if(chroot(root) == -1)
+ {
+ ERR << "chroot to " << root << " failed: " << strerror(errno) << endl;
+ _exit (3); // No sense in returning! I am forked away!!
+ }
+ if(chdir("/") == -1)
+ {
+ ERR << "chdir to / inside chroot failed: " << strerror(errno) << endl;
+ _exit (4); // No sense in returning! I am forked away!!
+ }
+ }
+
+ // close all filedesctiptors above stderr
+ for ( int i = ::getdtablesize() - 1; i > 2; --i ) {
+ ::close( i );
+ }
+
+ execvp(argv[0], const_cast<char *const *>(argv));
+ ERR << "Cannot execute external program "
+ << argv[0] << ":" << strerror(errno) << endl;
+ _exit (5); // No sense in returning! I am forked away!!
+ }
+
+ else if (pid == -1) // Fork failed, close everything.
+ {
+ if (use_pty) {
+ ::close(master_tty);
+ ::close(slave_tty);
+ }
+ else {
+ ::close(to_external[0]);
+ ::close(to_external[1]);
+ ::close(from_external[0]);
+ ::close(from_external[1]);
+ }
+ ERR << "Cannot fork " << strerror(errno) << endl;
+ }
+
+ else {
+ if (use_pty)
+ {
+ ::close(slave_tty); // belongs to child process
+ inputfile = fdopen(master_tty, "r");
+ outputfile = fdopen(master_tty, "w");
+ }
+ else
+ {
+ ::close(to_external[0]); // belongs to child process
+ ::close(from_external[1]); // belongs to child process
+ inputfile = fdopen(from_external[0], "r");
+ outputfile = fdopen(to_external[1], "w");
+ }
+
+ DBG << "pid " << pid << " launched" << endl;
+
+ if (!inputfile || !outputfile)
+ {
+ ERR << "Cannot create streams to external program " << argv[0] << endl;
+ close();
+ }
+ }
+ }
+
+
+ int
+ ExternalProgram::close()
+ {
+ if (pid > 0)
+ {
+ ExternalDataSource::close();
+ // Wait for child to exit
+ int ret;
+ int status = 0;
+ do
+ {
+ ret = waitpid(pid, &status, 0);
+ }
+ while (ret == -1 && errno == EINTR);
+
+ if (ret != -1)
+ {
+ status = checkStatus( status );
+ }
+ pid = -1;
+ return status;
+ }
+ else
+ {
+ return _exitStatus;
+ }
+ }
+
+
+ int ExternalProgram::checkStatus( int status )
+ {
+ if (WIFEXITED (status))
+ {
+ status = WEXITSTATUS (status);
+ if(status)
+ {
+ DBG << "pid " << pid << " exited with status " << status << endl;
+ }
+ else
+ {
+ // if 'launch' is logged, completion should be logged,
+ // even if successfull.
+ DBG << "pid " << pid << " successfully completed" << endl;
+ }
+ }
+ else if (WIFSIGNALED (status))
+ {
+ status = WTERMSIG (status);
+ WAR << "pid " << pid << " was killed by signal " << status
+ << " (" << strsignal(status);
+ if (WCOREDUMP (status))
+ {
+ WAR << ", core dumped";
+ }
+ WAR << ")" << endl;
+ status+=128;
+ }
+ else {
+ ERR << "pid " << pid << " exited with unknown error" << endl;
+ }
+
+ return status;
+ }
+
+ bool
+ ExternalProgram::kill()
+ {
+ if (pid > 0)
+ {
+ ::kill(pid, SIGKILL);
+ close();
+ }
+ return true;
+ }
+
+
+ bool
+ ExternalProgram::running()
+ {
+ if ( pid < 0 ) return false;
+
+ int status = 0;
+ int p = waitpid( pid, &status, WNOHANG );
+ if ( p < 0 ) return false;
+
+ status = checkStatus( status );
+
+ if ( status == 0 )
+ {
+ return true;
+ }
+ else
+ {
+ _exitStatus = status;
+ pid = -1;
+ return false;
+ }
+ }
+
+ // origfd will be accessible as newfd and closed (unless they were equal)
+ void ExternalProgram::renumber_fd (int origfd, int newfd)
+ {
+ // It may happen that origfd is already the one we want
+ // (Although in our circumstances, that would mean somebody has closed
+ // our stdin or stdout... weird but has appened to Cray, #49797)
+ if (origfd != newfd)
+ {
+ dup2 (origfd, newfd);
+ ::close (origfd);
+ }
+ }
+
+} // namespace zypp
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/ExternalProgram.h
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+
+#ifndef ZYPP_EXTERNALPROGRAM_H
+#define ZYPP_EXTERNALPROGRAM_H
+
+#include <map>
+#include <string>
+
+#include "zypp/base/ExternalDataSource.h"
+#include "zypp/Pathname.h"
+
+namespace zypp {
+
+ /**
+ * @short Execute a program and give access to its io
+ * An object of this class encapsulates the execution of
+ * an external program. It starts the program using fork
+ * and some exec.. call, gives you access to the program's
+ * stdio and closes the program after use.
+ */
+ class ExternalProgram : public zypp::externalprogram::ExternalDataSource
+ {
+
+ public:
+ /**
+ * Define symbols for different policies on the handling
+ * of stderr
+ */
+ enum Stderr_Disposition {
+ Normal_Stderr,
+ Discard_Stderr,
+ Stderr_To_Stdout,
+ Stderr_To_FileDesc
+ };
+
+ /**
+ * For passing additional environment variables to set
+ */
+ typedef std::map<std::string,std::string> Environment;
+
+ /**
+ * Start the external program by using the shell <tt>/bin/sh<tt>
+ * with the option <tt>-c</tt>. You can use io direction symbols < and >.
+ * @param commandline a shell commandline that is appended to
+ * <tt>/bin/sh -c</tt>.
+ * @param default_locale whether to set LC_ALL=C before starting
+ * @param root directory to chroot into, / or empty to not chroot
+ */
+ ExternalProgram (std::string commandline,
+ Stderr_Disposition stderr_disp = Normal_Stderr,
+ bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
+ const Pathname& root = "");
+
+ /**
+ * Start an external program by giving the arguments as an arry of char *pointers.
+ * If environment is provided, varaiables will be added to the childs environment,
+ * overwriting existing ones.
+ */
+ ExternalProgram (const char *const *argv,
+ Stderr_Disposition stderr_disp = Normal_Stderr,
+ bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
+ const Pathname& root = "");
+
+ ExternalProgram (const char *const *argv, const Environment & environment,
+ Stderr_Disposition stderr_disp = Normal_Stderr,
+ bool use_pty = false, int stderr_fd = -1, bool default_locale = false,
+ const Pathname& root = "");
+
+ ExternalProgram (const char *binpath, const char *const *argv_1,
+ bool use_pty = false);
+
+
+ ExternalProgram (const char *binpath, const char *const *argv_1, const Environment & environment,
+ bool use_pty = false);
+
+
+ ~ExternalProgram();
+
+ int close();
+
+ /**
+ * Kill the program
+ */
+ bool kill();
+
+ /**
+ * Return whether program is running
+ */
+ bool running();
+
+ /**
+ * return pid
+ * */
+ pid_t getpid() { return pid; }
+
+ /**
+ * origfd will be accessible as newfd and closed (unless they were equal)
+ */
+ static void renumber_fd (int origfd, int newfd);
+
+ protected:
+ int checkStatus( int );
+
+ private:
+
+ /**
+ * Set to true, if a pair of ttys is used for communication
+ * instead of a pair of pipes.
+ */
+ bool use_pty;
+
+ pid_t pid;
+ int _exitStatus;
+
+ void start_program (const char *const *argv, const Environment & environment,
+ Stderr_Disposition stderr_disp = Normal_Stderr,
+ int stderr_fd = -1, bool default_locale = false,
+ const char* root = NULL);
+
+ };
+
+} // namespace zypp
+
+#endif // ZYPP_EXTERNALPROGRAM_H
Script.h \
Patch.h \
Product.h \
- Changelog.h
+ Changelog.h \
+ \
+ ExternalProgram.h \
+ Pathname.cc \
+ PathInfo.cc \
+ Digest.cc
## ##################################################
Script.cc \
Patch.cc \
Product.cc \
- Changelog.cc
+ Changelog.cc \
+ \
+ ExternalProgram.cc \
+ Pathname.cc \
+ PathInfo.cc \
+ Digest.cc
lib@PACKAGE@_la_LDFLAGS = @LIB_VERSION_INFO@
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/PathInfo.cc
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+#include "zypp/base/Logger.h"
+#include "zypp/base/stringutil.h"
+#include "zypp/ExternalProgram.h"
+
+#include "zypp/PathInfo.h"
+#include "zypp/Digest.h"
+
+using namespace std;
+using namespace zypp::base;
+
+namespace zypp {
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::PathInfo
+// METHOD TYPE : Constructor
+//
+// DESCRIPTION :
+//
+PathInfo::PathInfo( const Pathname & path, Mode initial )
+ : path_t( path )
+ , mode_e( initial )
+ , error_i( -1 )
+{
+ operator()();
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::PathInfo
+// METHOD TYPE : Constructor
+//
+// DESCRIPTION :
+//
+PathInfo::PathInfo( const string & path, Mode initial )
+ : path_t( path )
+ , mode_e( initial )
+ , error_i( -1 )
+{
+ operator()();
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::PathInfo
+// METHOD TYPE : Constructor
+//
+// DESCRIPTION :
+//
+PathInfo::PathInfo( const char * path, Mode initial )
+ : path_t( path )
+ , mode_e( initial )
+ , error_i( -1 )
+{
+ operator()();
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::~PathInfo
+// METHOD TYPE : Destructor
+//
+// DESCRIPTION :
+//
+PathInfo::~PathInfo()
+{
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::operator()
+// METHOD TYPE : bool
+//
+// DESCRIPTION :
+//
+bool PathInfo::operator()()
+{
+ if ( path_t.empty() ) {
+ error_i = -1;
+ } else {
+ switch ( mode_e ) {
+ case STAT:
+ error_i = ::stat( path_t.asString().c_str(), &statbuf_C );
+ break;
+ case LSTAT:
+ error_i = ::lstat( path_t.asString().c_str(), &statbuf_C );
+ break;
+ }
+ if ( error_i == -1 )
+ error_i = errno;
+ }
+ return !error_i;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::fileType
+// METHOD TYPE : PathInfo::file_type
+//
+PathInfo::file_type PathInfo::fileType() const
+{
+ if ( isExist() )
+ return stat_mode( st_mode() ).fileType();
+ return NOT_EXIST;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::userMay
+// METHOD TYPE : mode_t
+//
+// DESCRIPTION :
+//
+mode_t PathInfo::userMay() const
+{
+ if ( !isExist() )
+ return 0;
+ if ( owner() == getuid() ) {
+ return( uperm()/0100 );
+ } else if ( group() == getgid() ) {
+ return( gperm()/010 );
+ }
+ return operm();
+}
+
+/******************************************************************
+**
+**
+** FUNCTION NAME : operator<<
+** FUNCTION TYPE : ostream &
+**
+** DESCRIPTION :
+*/
+ostream & operator<<( ostream & str, const PathInfo & obj )
+{
+ ios::fmtflags state_ii = str.flags();
+
+ str << obj.asString() << "{";
+ if ( !obj.isExist() ) {
+ str << "does not exist}";
+ } else {
+ str << PathInfo::stat_mode( obj.st_mode() ) << " " << dec << obj.owner() << "/" << obj.group();
+
+ if ( obj.isFile() )
+ str << " size " << obj.size();
+
+ str << "}";
+ }
+ str.flags( state_ii );
+ return str;
+}
+
+/******************************************************************
+**
+**
+** FUNCTION NAME : operator<<
+** FUNCTION TYPE : std::ostream &
+**
+** DESCRIPTION :
+*/
+ostream & operator<<( ostream & str, PathInfo::file_type obj )
+{
+ switch ( obj ) {
+#define EMUMOUT(T) case PathInfo::T: return str << #T; break
+ EMUMOUT( NOT_AVAIL );
+ EMUMOUT( NOT_EXIST );
+ EMUMOUT( T_FILE );
+ EMUMOUT( T_DIR );
+ EMUMOUT( T_CHARDEV );
+ EMUMOUT( T_BLOCKDEV );
+ EMUMOUT( T_FIFO );
+ EMUMOUT( T_LINK );
+ EMUMOUT( T_SOCKET );
+#undef EMUMOUT
+ }
+ return str;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::stat_mode::fileType
+// METHOD TYPE : PathInfo::file_type
+//
+PathInfo::file_type PathInfo::stat_mode::fileType() const
+{
+ if ( isFile() )
+ return T_FILE;
+ if ( isDir() )
+ return T_DIR;
+ if ( isLink() )
+ return T_LINK;
+ if ( isChr() )
+ return T_CHARDEV;
+ if ( isBlk() )
+ return T_BLOCKDEV;
+ if ( isFifo() )
+ return T_FIFO;
+ if ( isSock() )
+ return T_SOCKET ;
+
+ return NOT_AVAIL;
+}
+
+/******************************************************************
+**
+**
+** FUNCTION NAME : operator<<
+** FUNCTION TYPE : std::ostream &
+**
+** DESCRIPTION :
+*/
+std::ostream & operator<<( std::ostream & str, const PathInfo::stat_mode & obj )
+{
+ ios::fmtflags state_ii = str.flags();
+ char t = '?';
+ if ( obj.isFile() )
+ t = '-';
+ else if ( obj.isDir() )
+ t = 'd';
+ else if ( obj.isLink() )
+ t = 'l';
+ else if ( obj.isChr() )
+ t = 'c';
+ else if ( obj.isBlk() )
+ t = 'b';
+ else if ( obj.isFifo() )
+ t = 'p';
+ else if ( obj.isSock() )
+ t = 's';
+
+ str << t << " " << setfill( '0' ) << setw( 4 ) << oct << obj.perm();
+ str.flags( state_ii );
+ return str;
+}
+
+/******************************************************************
+**
+**
+** FUNCTION NAME : _Log_Result
+** FUNCTION TYPE : int
+**
+** DESCRIPTION : Helper function to log return values.
+*/
+inline int _Log_Result( const int res, const char * rclass = "errno" )
+{
+ if ( res )
+ DBG << " FAILED: " << rclass << " " << res;
+ DBG << endl;
+ return res;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::mkdir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::mkdir( const Pathname & path, unsigned mode )
+{
+ DBG << "mkdir " << path << ' ' << stringutil::octstring( mode );
+ if ( ::mkdir( path.asString().c_str(), mode ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::assert_dir()
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::assert_dir( const Pathname & path, unsigned mode )
+{
+ string::size_type pos, lastpos = 0;
+ string spath = path.asString()+"/";
+ int ret = 0;
+
+ if(path.empty())
+ return ENOENT;
+
+ // skip ./
+ if(path.relative())
+ lastpos=2;
+ // skip /
+ else
+ lastpos=1;
+
+// DBG << "about to create " << spath << endl;
+ while((pos = spath.find('/',lastpos)) != string::npos )
+ {
+ string dir = spath.substr(0,pos);
+ ret = ::mkdir(dir.c_str(), mode);
+ if(ret == -1)
+ {
+ // ignore errors about already existing directorys
+ if(errno == EEXIST)
+ ret=0;
+ else
+ ret=errno;
+ }
+// DBG << "creating directory " << dir << (ret?" failed":" succeeded") << endl;
+ lastpos = pos+1;
+ }
+ return ret;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::rmdir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::rmdir( const Pathname & path )
+{
+ DBG << "rmdir " << path;
+ if ( ::rmdir( path.asString().c_str() ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::recursive_rmdir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::recursive_rmdir( const Pathname & path )
+{
+ DBG << "recursive_rmdir " << path << ' ';
+ PathInfo p( path );
+
+ if ( !p.isExist() ) {
+ return _Log_Result( 0 );
+ }
+
+ if ( !p.isDir() ) {
+ return _Log_Result( ENOTDIR );
+ }
+
+ const char *const argv[] = {
+ "/bin/rm",
+ "-rf",
+ "--preserve-root",
+ "--",
+ path.asString().c_str(),
+ NULL
+ };
+
+ ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
+ for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
+ DBG << " " << output;
+ }
+ int ret = prog.close();
+ return _Log_Result( ret, "returned" );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::clean_dir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::clean_dir( const Pathname & path )
+{
+ DBG << "clean_dir " << path << ' ';
+ PathInfo p( path );
+
+ if ( !p.isExist() ) {
+ return _Log_Result( 0 );
+ }
+
+ if ( !p.isDir() ) {
+ return _Log_Result( ENOTDIR );
+ }
+
+ string cmd( stringutil::form( "cd '%s' && rm -rf --preserve-root -- *", path.asString().c_str() ) );
+ ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
+ for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
+ DBG << " " << output;
+ }
+ int ret = prog.close();
+ return _Log_Result( ret, "returned" );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::copy_dir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::copy_dir( const Pathname & srcpath, const Pathname & destpath )
+{
+ DBG << "copy_dir " << srcpath << " -> " << destpath << ' ';
+
+ PathInfo sp( srcpath );
+ if ( !sp.isDir() ) {
+ return _Log_Result( ENOTDIR );
+ }
+
+ PathInfo dp( destpath );
+ if ( !dp.isDir() ) {
+ return _Log_Result( ENOTDIR );
+ }
+
+ PathInfo tp( destpath + srcpath.basename() );
+ if ( tp.isExist() ) {
+ return _Log_Result( EEXIST );
+ }
+
+
+ const char *const argv[] = {
+ "/bin/cp",
+ "-dR",
+ "--",
+ srcpath.asString().c_str(),
+ destpath.asString().c_str(),
+ NULL
+ };
+ ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
+ for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
+ DBG << " " << output;
+ }
+ int ret = prog.close();
+ return _Log_Result( ret, "returned" );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::readdir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::readdir( std::list<std::string> & retlist,
+ const Pathname & path, bool dots )
+{
+ retlist.clear();
+
+ DBG << "readdir " << path << ' ';
+
+ DIR * dir = ::opendir( path.asString().c_str() );
+ if ( ! dir ) {
+ return _Log_Result( errno );
+ }
+
+ struct dirent *entry;
+ while ( (entry = ::readdir( dir )) != 0 ) {
+
+ if ( entry->d_name[0] == '.' ) {
+ if ( !dots )
+ continue;
+ if ( entry->d_name[1] == '\0'
+ || ( entry->d_name[1] == '.'
+ && entry->d_name[2] == '\0' ) )
+ continue;
+ }
+ retlist.push_back( entry->d_name );
+ }
+
+ ::closedir( dir );
+
+ return _Log_Result( 0 );
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::readdir
+// METHOD TYPE : int
+//
+int PathInfo::readdir( dircontent & retlist, const Pathname & path,
+ bool dots, Mode statmode )
+{
+ retlist.clear();
+
+ list<string> content;
+ int res = readdir( content, path, dots );
+
+ if ( !res ) {
+ for ( list<string>::const_iterator it = content.begin(); it != content.end(); ++it ) {
+ PathInfo p( path + *it, statmode );
+ retlist.push_back( direntry( *it, p.fileType() ) );
+ }
+ }
+
+ return res;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::unlink
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::unlink( const Pathname & path )
+{
+ DBG << "unlink " << path;
+ if ( ::unlink( path.asString().c_str() ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::rename
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::rename( const Pathname & oldpath, const Pathname & newpath )
+{
+ DBG << "rename " << oldpath << " -> " << newpath;
+ if ( ::rename( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::copy
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::copy( const Pathname & file, const Pathname & dest )
+{
+ DBG << "copy " << file << " -> " << dest << ' ';
+
+ PathInfo sp( file );
+ if ( !sp.isFile() ) {
+ return _Log_Result( EINVAL );
+ }
+
+ PathInfo dp( dest );
+ if ( dp.isDir() ) {
+ return _Log_Result( EISDIR );
+ }
+
+ const char *const argv[] = {
+ "/bin/cp",
+ "--",
+ file.asString().c_str(),
+ dest.asString().c_str(),
+ NULL
+ };
+ ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
+ for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
+ DBG << " " << output;
+ }
+ int ret = prog.close();
+ return _Log_Result( ret, "returned" );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::symlink
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::symlink( const Pathname & oldpath, const Pathname & newpath )
+{
+ DBG << "symlink " << newpath << " -> " << oldpath;
+ if ( ::symlink( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::hardlink
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::hardlink( const Pathname & oldpath, const Pathname & newpath )
+{
+ DBG << "hardlink " << newpath << " -> " << oldpath;
+ if ( ::link( oldpath.asString().c_str(), newpath.asString().c_str() ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::copy_file2dir
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::copy_file2dir( const Pathname & file, const Pathname & dest )
+{
+ DBG << "copy_file2dir " << file << " -> " << dest << ' ';
+
+ PathInfo sp( file );
+ if ( !sp.isFile() ) {
+ return _Log_Result( EINVAL );
+ }
+
+ PathInfo dp( dest );
+ if ( !dp.isDir() ) {
+ return _Log_Result( ENOTDIR );
+ }
+
+ const char *const argv[] = {
+ "/bin/cp",
+ "--",
+ file.asString().c_str(),
+ dest.asString().c_str(),
+ NULL
+ };
+ ExternalProgram prog( argv, ExternalProgram::Stderr_To_Stdout );
+ for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
+ DBG << " " << output;
+ }
+ int ret = prog.close();
+ return _Log_Result( ret, "returned" );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::md5sum
+// METHOD TYPE : std::string
+//
+std::string PathInfo::md5sum( const Pathname & file )
+{
+ if ( ! PathInfo( file ).isFile() ) {
+ return string();
+ }
+ ifstream istr( file.asString().c_str() );
+ if ( ! istr ) {
+ return string();
+ }
+ return Digest::digest( "MD5", istr );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::sha1sum
+// METHOD TYPE : std::string
+//
+std::string PathInfo::sha1sum( const Pathname & file )
+{
+ if ( ! PathInfo( file ).isFile() ) {
+ return string();
+ }
+ ifstream istr( file.asString().c_str() );
+ if ( ! istr ) {
+ return string();
+ }
+ return Digest::digest( "SHA1", istr );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::erase
+// METHOD TYPE : int
+//
+// DESCRIPTION :
+//
+int PathInfo::erase( const Pathname & path )
+{
+ int res = 0;
+ PathInfo p( path, LSTAT );
+ if ( p.isExist() )
+ {
+ if ( p.isDir() )
+ res = PathInfo::recursive_rmdir( path );
+ else
+ res = PathInfo::unlink( path );
+ }
+ return res;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::chmod
+// METHOD TYPE : int
+//
+int PathInfo::chmod( const Pathname & path, mode_t mode )
+{
+ DBG << "chmod " << path << ' ' << stringutil::octstring( mode );
+ if ( ::chmod( path.asString().c_str(), mode ) == -1 ) {
+ return _Log_Result( errno );
+ }
+ return _Log_Result( 0 );
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : PathInfo::zipType
+// METHOD TYPE : PathInfo::ZIP_TYPE
+//
+PathInfo::ZIP_TYPE PathInfo::zipType( const Pathname & file )
+{
+ ZIP_TYPE ret = ZT_NONE;
+
+ int fd = open( file.asString().c_str(), O_RDONLY );
+
+ if ( fd != -1 ) {
+ const int magicSize = 3;
+ unsigned char magic[magicSize];
+ memset( magic, 0, magicSize );
+ if ( read( fd, magic, magicSize ) == magicSize ) {
+ if ( magic[0] == 0037 && magic[1] == 0213 ) {
+ ret = ZT_GZ;
+ } else if ( magic[0] == 'B' && magic[1] == 'Z' && magic[2] == 'h' ) {
+ ret = ZT_BZ2;
+ }
+ }
+ close( fd );
+ }
+
+ return ret;
+}
+
+} // namespace zypp
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/PathInfo.h
+ *
+ * \todo replace by Blocxx
+ *
+*/
+#ifndef ZYPP_PATHINFO_H
+#define ZYPP_PATHINFO_H
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+}
+
+#include <cerrno>
+#include <iosfwd>
+#include <list>
+#include <set>
+#include <map>
+
+#include "zypp/Pathname.h"
+
+namespace zypp {
+
+///////////////////////////////////////////////////////////////////
+//
+// CLASS NAME : PathInfo
+/**
+ * @short Wrapper class for ::stat/::lstat and other file/directory related operations.
+ **/
+class PathInfo {
+
+ friend std::ostream & operator<<( std::ostream & str, const PathInfo & obj );
+
+ public:
+
+ enum Mode { STAT, LSTAT };
+
+ enum file_type {
+ NOT_AVAIL = 0x00, // no typeinfo available
+ NOT_EXIST = 0x01, // file does not exist
+ T_FILE = 0x02,
+ T_DIR = 0x04,
+ T_CHARDEV = 0x08,
+ T_BLOCKDEV = 0x10,
+ T_FIFO = 0x20,
+ T_LINK = 0x40,
+ T_SOCKET = 0x80
+ };
+ friend std::ostream & operator<<( std::ostream & str, file_type obj );
+
+ /**
+ * Wrapper class for mode_t values as derived from ::stat
+ **/
+ class stat_mode;
+
+ /**
+ * Simple cache remembering device/inode to detect hardlinks.
+ **/
+ class devino_cache;
+
+ private:
+
+ Pathname path_t;
+
+ struct stat statbuf_C;
+ Mode mode_e;
+ int error_i;
+
+ public:
+
+ PathInfo( const Pathname & path = "", Mode initial = STAT );
+ PathInfo( const std::string & path, Mode initial = STAT );
+ PathInfo( const char * path, Mode initial = STAT );
+ virtual ~PathInfo();
+
+ const Pathname & path() const { return path_t; }
+ const std::string & asString() const { return path_t.asString(); }
+ Mode mode() const { return mode_e; }
+ int error() const { return error_i; }
+
+ void setPath( const Pathname & path ) { if ( path != path_t ) error_i = -1; path_t = path; }
+ void setMode( Mode mode ) { if ( mode != mode_e ) error_i = -1; mode_e = mode; }
+
+ bool stat ( const Pathname & path ) { setPath( path ); setMode( STAT ); return operator()(); }
+ bool lstat ( const Pathname & path ) { setPath( path ); setMode( LSTAT ); return operator()(); }
+ bool operator()( const Pathname & path ) { setPath( path ); return operator()(); }
+
+ bool stat() { setMode( STAT ); return operator()(); }
+ bool lstat() { setMode( LSTAT ); return operator()(); }
+ bool operator()();
+
+ public:
+
+ bool isExist() const { return !error_i; }
+
+ // file type
+ file_type fileType() const;
+
+ bool isFile() const { return isExist() && S_ISREG( statbuf_C.st_mode ); }
+ bool isDir () const { return isExist() && S_ISDIR( statbuf_C.st_mode ); }
+ bool isLink() const { return isExist() && S_ISLNK( statbuf_C.st_mode ); }
+ bool isChr() const { return isExist() && S_ISCHR( statbuf_C.st_mode ); }
+ bool isBlk() const { return isExist() && S_ISBLK( statbuf_C.st_mode ); }
+ bool isFifo() const { return isExist() && S_ISFIFO( statbuf_C.st_mode ); }
+ bool isSock() const { return isExist() && S_ISSOCK( statbuf_C.st_mode ); }
+
+ nlink_t nlink() const { return isExist() ? statbuf_C.st_nlink : 0; }
+
+ // owner
+ uid_t owner() const { return isExist() ? statbuf_C.st_uid : 0; }
+ gid_t group() const { return isExist() ? statbuf_C.st_gid : 0; }
+
+ // permission
+ bool isRUsr() const { return isExist() && (statbuf_C.st_mode & S_IRUSR); }
+ bool isWUsr() const { return isExist() && (statbuf_C.st_mode & S_IWUSR); }
+ bool isXUsr() const { return isExist() && (statbuf_C.st_mode & S_IXUSR); }
+
+ bool isR() const { return isRUsr(); }
+ bool isW() const { return isWUsr(); }
+ bool isX() const { return isXUsr(); }
+
+ bool isRGrp() const { return isExist() && (statbuf_C.st_mode & S_IRGRP); }
+ bool isWGrp() const { return isExist() && (statbuf_C.st_mode & S_IWGRP); }
+ bool isXGrp() const { return isExist() && (statbuf_C.st_mode & S_IXGRP); }
+
+ bool isROth() const { return isExist() && (statbuf_C.st_mode & S_IROTH); }
+ bool isWOth() const { return isExist() && (statbuf_C.st_mode & S_IWOTH); }
+ bool isXOth() const { return isExist() && (statbuf_C.st_mode & S_IXOTH); }
+
+ bool isUid() const { return isExist() && (statbuf_C.st_mode & S_ISUID); }
+ bool isGid() const { return isExist() && (statbuf_C.st_mode & S_ISGID); }
+ bool isVtx() const { return isExist() && (statbuf_C.st_mode & S_ISVTX); }
+
+ mode_t uperm() const { return isExist() ? (statbuf_C.st_mode & S_IRWXU) : 0; }
+ mode_t gperm() const { return isExist() ? (statbuf_C.st_mode & S_IRWXG) : 0; }
+ mode_t operm() const { return isExist() ? (statbuf_C.st_mode & S_IRWXO) : 0; }
+ mode_t perm() const { return isExist() ? (statbuf_C.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX)) : 0; }
+
+ bool isPerm ( mode_t m ) const { return (m == perm()); }
+ bool hasPerm( mode_t m ) const { return (m == (m & perm())); }
+
+ mode_t st_mode() const { return isExist() ? statbuf_C.st_mode : 0; }
+
+ // permission according to current uid/gid (returns [0-7])
+ mode_t userMay() const;
+
+ bool userMayR() const { return( userMay() & 01 ); }
+ bool userMayW() const { return( userMay() & 02 ); }
+ bool userMayX() const { return( userMay() & 04 ); }
+
+ bool userMayRW() const { return( (userMay() & 03) == 03 ); }
+ bool userMayRX() const { return( (userMay() & 05) == 05 ); }
+ bool userMayWX() const { return( (userMay() & 06) == 06 ); }
+
+ bool userMayRWX() const { return( userMay() == 07 ); }
+
+ // device
+ dev_t dev() const { return isExist() ? statbuf_C.st_dev : 0; }
+ dev_t rdev() const { return isExist() ? statbuf_C.st_rdev : 0; }
+ ino_t ino() const { return isExist() ? statbuf_C.st_ino : 0; }
+
+ // size
+ off_t size() const { return isExist() ? statbuf_C.st_size : 0; }
+ unsigned long blksize() const { return isExist() ? statbuf_C.st_blksize : 0; }
+ unsigned long blocks() const { return isExist() ? statbuf_C.st_blocks : 0; }
+
+ // time
+ time_t atime() const { return isExist() ? statbuf_C.st_atime : 0; } /* time of last access */
+ time_t mtime() const { return isExist() ? statbuf_C.st_mtime : 0; } /* time of last modification */
+ time_t ctime() const { return isExist() ? statbuf_C.st_ctime : 0; }
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////
+ // convenience stuff
+ ///////////////////////////////////////////////////////////////////
+ // static functions as they may or may not invalidate any stat info
+ // stored by a PathiInfo.
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ // Directories
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Like '::mkdir'. Attempt to create a new directory named path. mode
+ * specifies the permissions to use. It is modified by the process's
+ * umask in the usual way.
+ *
+ * @return 0 on success, errno on failure
+ **/
+ static int mkdir( const Pathname & path, unsigned mode = 0755 );
+
+ /**
+ * Like 'mkdir -p'. No error if directory exists. Make parent directories
+ * as needed. mode specifies the permissions to use, if directories have to
+ * be created. It is modified by the process's umask in the usual way.
+ *
+ * @return 0 on success, errno on failure
+ **/
+ static int assert_dir( const Pathname & path, unsigned mode = 0755 );
+
+ /**
+ * Like '::rmdir'. Delete a directory, which must be empty.
+ *
+ * @return 0 on success, errno on failure
+ **/
+ static int rmdir( const Pathname & path );
+
+ /**
+ * Like 'rm -r DIR'. Delete a directory, recursively removing its contents.
+ *
+ * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
+ * commands return value.
+ **/
+ static int recursive_rmdir( const Pathname & path );
+
+ /**
+ * Like 'rm -r DIR/ *'. Delete directory contents, but keep the directory itself.
+ *
+ * @return 0 on success, ENOTDIR if path is not a directory, otherwise the
+ * commands return value.
+ **/
+ static int clean_dir( const Pathname & path );
+
+ /**
+ * Like 'cp -a srcpath destpath'. Copy directory tree. srcpath/destpath must be
+ * directories. 'basename srcpath' must not exist in destpath.
+ *
+ * @return 0 on success, ENOTDIR if srcpath/destpath is not a directory, EEXIST if
+ * 'basename srcpath' exists in destpath, otherwise the commands return value.
+ **/
+ static int copy_dir( const Pathname & srcpath, const Pathname & destpath );
+
+ /**
+ * Return content of directory via retlist. If dots is false
+ * entries starting with '.' are not reported. "." and ".."
+ * are never reported.
+ *
+ * @return 0 on success, errno on failure.
+ **/
+ static int readdir( std::list<std::string> & retlist,
+ const Pathname & path, bool dots = true );
+
+ struct direntry {
+ std::string name;
+ file_type type;
+ direntry( const std::string & name_r = std::string(), file_type type_r = NOT_AVAIL )
+ : name( name_r )
+ , type( type_r )
+ {}
+ };
+
+ typedef std::list<direntry> dircontent;
+
+ /**
+ * Return content of directory via retlist. If dots is false
+ * entries starting with '.' are not reported. "." and ".."
+ * are never reported.
+ *
+ * The type of individual directory entries is determined accoding to
+ * statmode (i.e. via stat or lstat).
+ *
+ * @return 0 on success, errno on failure.
+ **/
+ static int readdir( dircontent & retlist, const Pathname & path,
+ bool dots = true, Mode statmode = STAT );
+
+ ///////////////////////////////////////////////////////////////////
+ // Files
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Like '::unlink'. Delete a file (symbolic link, socket, fifo or device).
+ *
+ * @return 0 on success, errno on failure
+ **/
+ static int unlink( const Pathname & path );
+
+ /**
+ * Like '::rename'. Renames a file, moving it between directories if required.
+ *
+ * @return 0 on success, errno on failure
+ **/
+ static int rename( const Pathname & oldpath, const Pathname & newpath );
+
+ /**
+ * Like 'cp file dest'. Copy file to destination file.
+ *
+ * @return 0 on success, EINVAL if file is not a file, EISDIR if
+ * destiantion is a directory, otherwise the commands return value.
+ **/
+ static int copy( const Pathname & file, const Pathname & dest );
+
+ /**
+ * Like '::symlink'. Creates a symbolic link named newpath which contains
+ * the string oldpath. If newpath exists it will not be overwritten.
+ *
+ * @return 0 on success, errno on failure.
+ **/
+ static int symlink( const Pathname & oldpath, const Pathname & newpath );
+
+ /**
+ * Like '::link'. Creates a hard link named newpath to an existing file
+ * oldpath. If newpath exists it will not be overwritten.
+ *
+ * @return 0 on success, errno on failure.
+ **/
+ static int hardlink( const Pathname & oldpath, const Pathname & newpath );
+
+ /**
+ * Like 'cp file dest'. Copy file to dest dir.
+ *
+ * @return 0 on success, EINVAL if file is not a file, ENOTDIR if dest
+ * is no directory, otherwise the commands return value.
+ **/
+ static int copy_file2dir( const Pathname & file, const Pathname & dest );
+
+ /**
+ * Compute a files md5sum.
+ *
+ * @return the files md5sum on success, otherwise an empty string..
+ **/
+ static std::string md5sum( const Pathname & file );
+
+ /**
+ * Compute a files sha1sum.
+ *
+ * @return the files sha1sum on success, otherwise an empty string..
+ **/
+ static std::string sha1sum( const Pathname & file );
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Erase whatever happens to be located at path (file or directory).
+ *
+ * @return 0 on success.
+ **/
+ static int erase( const Pathname & path );
+
+ ///////////////////////////////////////////////////////////////////
+ // permissions
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Like '::chmod'. The mode of the file given by path is changed.
+ *
+ * @return 0 on success, errno on failure
+ **/
+ static int chmod( const Pathname & path, mode_t mode );
+
+ ///////////////////////////////////////////////////////////////////
+ // magic
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Test whether a file is compressed (gzip/bzip2).
+ *
+ * @return ZT_GZ, ZT_BZ2 if file is compressed, otherwise ZT_NONE.
+ **/
+ enum ZIP_TYPE { ZT_NONE, ZT_GZ, ZT_BZ2 };
+
+ static ZIP_TYPE zipType( const Pathname & file );
+};
+
+///////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////
+//
+// CLASS NAME : PathInfo::stat_mode
+/**
+ * @short Wrapper class for mode_t values as derived from ::stat
+ **/
+class PathInfo::stat_mode {
+ friend std::ostream & operator<<( std::ostream & str, const stat_mode & obj );
+ private:
+ mode_t _mode;
+ public:
+ stat_mode( const mode_t & mode_r = 0 ) : _mode( mode_r ) {}
+ public:
+ // file type
+ file_type fileType() const;
+
+ bool isFile() const { return S_ISREG( _mode ); }
+ bool isDir () const { return S_ISDIR( _mode ); }
+ bool isLink() const { return S_ISLNK( _mode ); }
+ bool isChr() const { return S_ISCHR( _mode ); }
+ bool isBlk() const { return S_ISBLK( _mode ); }
+ bool isFifo() const { return S_ISFIFO( _mode ); }
+ bool isSock() const { return S_ISSOCK( _mode ); }
+
+ // permission
+ bool isRUsr() const { return (_mode & S_IRUSR); }
+ bool isWUsr() const { return (_mode & S_IWUSR); }
+ bool isXUsr() const { return (_mode & S_IXUSR); }
+
+ bool isR() const { return isRUsr(); }
+ bool isW() const { return isWUsr(); }
+ bool isX() const { return isXUsr(); }
+
+ bool isRGrp() const { return (_mode & S_IRGRP); }
+ bool isWGrp() const { return (_mode & S_IWGRP); }
+ bool isXGrp() const { return (_mode & S_IXGRP); }
+
+ bool isROth() const { return (_mode & S_IROTH); }
+ bool isWOth() const { return (_mode & S_IWOTH); }
+ bool isXOth() const { return (_mode & S_IXOTH); }
+
+ bool isUid() const { return (_mode & S_ISUID); }
+ bool isGid() const { return (_mode & S_ISGID); }
+ bool isVtx() const { return (_mode & S_ISVTX); }
+
+ mode_t uperm() const { return (_mode & S_IRWXU); }
+ mode_t gperm() const { return (_mode & S_IRWXG); }
+ mode_t operm() const { return (_mode & S_IRWXO); }
+ mode_t perm() const { return (_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX)); }
+
+ bool isPerm ( mode_t m ) const { return (m == perm()); }
+ bool hasPerm( mode_t m ) const { return (m == (m & perm())); }
+
+ mode_t st_mode() const { return _mode; }
+};
+
+///////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////
+//
+// CLASS NAME : PathInfo::devino_cache
+/**
+ * @short Simple cache remembering device/inode to detect hardlinks.
+ * <pre>
+ * PathInfo::devino_cache trace;
+ * for ( all files ) {
+ * if ( trace.insert( file.device, file.inode ) ) {
+ * // 1st occurance of file
+ * }
+ * // else: hardlink; already counted this device/inode
+ * }
+ * }
+ * </pre>
+ **/
+class PathInfo::devino_cache {
+
+ private:
+
+ std::map<dev_t,std::set<ino_t> > _devino;
+
+ public:
+ /**
+ * Constructor
+ **/
+ devino_cache() {}
+
+ /**
+ * Clear cache
+ **/
+ void clear() { _devino.clear(); }
+
+ /**
+ * Remember dev/ino. Return <code>true</code> if it's inserted the first
+ * time, <code>false</code> if alredy present in cache (a hardlink to a
+ * previously remembered file.
+ **/
+ bool insert( const dev_t & dev_r, const ino_t & ino_r ) {
+ return _devino[dev_r].insert( ino_r ).second;
+ }
+};
+
+///////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////
+} // namespace zypp
+
+#endif // ZYPP_PATHINFO_H
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/Pathname.cc
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#include <iostream>
+
+#include "zypp/Pathname.h"
+
+using namespace std;
+
+namespace zypp {
+
+///////////////////////////////////////////////////////////////////
+//
+// CLASS NAME : DirStack
+//
+// DESCRIPTION :
+//
+class DirStack {
+
+ struct Dir {
+
+ Dir * up;
+ Dir * dn;
+ string name;
+
+ Dir( const string & n = "" ) {
+ name = n;
+ up = dn = 0;
+ }
+
+ ~Dir() {
+ if ( up )
+ up->dn = dn;
+ if ( dn )
+ dn->up = up;
+ }
+ };
+
+ Dir * top;
+ Dir * bot;
+
+ void Pop() {
+ if ( !top )
+ return;
+ top = top->dn;
+ if ( top )
+ delete top->up;
+ else {
+ delete bot;
+ bot = 0;
+ }
+ }
+
+ public:
+
+ DirStack() { top = bot = 0; }
+ ~DirStack() {
+ while ( bot )
+ Pop();
+ }
+
+ void Push( const string & n ) {
+ if ( n.empty() || n == "." ) { // '.' or '/' only for bot
+ if ( bot )
+ return;
+ } else if ( n == ".." && top ) {
+ if ( top->name == "" ) // "/.." ==> "/"
+ return;
+
+ if ( top->name != "." && top->name != ".." ) { // "somedir/.." ==> ""
+ Pop();
+ return;
+ }
+ // "../.." "./.." stays
+ }
+
+ Dir * d = new Dir( n );
+ if ( !top )
+ top = bot = d;
+ else {
+ top->up = d;
+ d->dn = top;
+ d->up = 0;
+ top = d;
+ }
+ }
+
+ string str() {
+ if ( !bot )
+ return "";
+ string ret;
+ for ( Dir * d = bot; d; d = d->up ) {
+ if ( d != bot )
+ ret += "/";
+ ret += d->name;
+ }
+ if ( ret.empty() )
+ return "/";
+ return ret;
+ }
+};
+
+///////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : Pathname::_assign
+// METHOD TYPE : void
+//
+// DESCRIPTION :
+//
+void Pathname::_assign( const string & name_tv )
+{
+ prfx_i = 0;
+ name_t = name_tv;
+
+ if ( name_t.empty() )
+ return;
+
+ string Tprfx;
+ DirStack Stack_Ci;
+
+ char * Buf_aci = new char[name_tv.length() + 1];
+ char * W_pci = Buf_aci;
+ const char * R_pci = name_tv.c_str();
+
+ // check for prefix
+ if ( name_t.length() >= 2
+ && name_t[1] == ':'
+ && ( 'a' <= name_t[0] && name_t[0] <= 'z'
+ || 'A' <= name_t[0] && name_t[0] <= 'Z' ) ) {
+ Tprfx = name_t.substr( 0, 2 );
+ prfx_i = 2;
+ R_pci += 2;
+ }
+
+ // rel or abs path
+ if ( *R_pci == '/' || *R_pci == '\\' ) {
+ Stack_Ci.Push( "" );
+ ++R_pci;
+ } else {
+ Stack_Ci.Push( "." );
+ }
+
+ do {
+ switch ( *R_pci ) {
+ case '/':
+ case '\\':
+ case '\0':
+ if ( W_pci != Buf_aci ) {
+ *W_pci = '\0';
+ W_pci = Buf_aci;
+ Stack_Ci.Push( Buf_aci );
+ }
+ break;
+
+ default:
+ *W_pci++ = *R_pci;
+ break;
+ }
+ } while( *R_pci++ );
+
+ delete Buf_aci;
+ name_t = Tprfx + Stack_Ci.str();
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : Pathname::dirname
+// METHOD TYPE : Pathname
+//
+// DESCRIPTION :
+//
+Pathname Pathname::dirname( const Pathname & name_tv )
+{
+ if ( name_tv.empty() )
+ return "";
+
+ Pathname ret_t( name_tv );
+ string::size_type idx = ret_t.name_t.find_last_of( '/' );
+
+ if ( idx == string::npos ) {
+ ret_t.name_t.erase( ret_t.prfx_i );
+ ret_t.name_t += ".";
+ } else if ( idx == ret_t.prfx_i ) {
+ ret_t.name_t.erase( ret_t.prfx_i );
+ ret_t.name_t += "/";
+ } else {
+ ret_t.name_t.erase( idx );
+ }
+
+ return ret_t;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : Pathname::basename
+// METHOD TYPE : string
+//
+// DESCRIPTION :
+//
+string Pathname::basename( const Pathname & name_tv )
+{
+ if ( name_tv.empty() )
+ return "";
+
+ string ret_t( name_tv.asString() );
+ ret_t.erase( 0, name_tv.prfx_i );
+ string::size_type idx = ret_t.find_last_of( '/' );
+ if ( idx != string::npos ) {
+ ret_t.erase( 0, idx+1 );
+ }
+
+ return ret_t;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : Pathname::cat
+// METHOD TYPE : Pathname
+//
+// DESCRIPTION :
+//
+Pathname Pathname::cat( const Pathname & name_tv, const Pathname & add_tv )
+{
+ if ( add_tv.empty() )
+ return name_tv;
+ if ( name_tv.empty() )
+ return add_tv;
+
+ string ret_ti( add_tv.asString() );
+ ret_ti.replace( 0, add_tv.prfx_i, "/" );
+
+ return name_tv.asString() + ret_ti;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : Pathname::Extend
+// METHOD TYPE : Pathname
+//
+// DESCRIPTION :
+//
+Pathname Pathname::extend( const Pathname & l, const string & r )
+{
+ return l.asString() + r;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+// METHOD NAME : Pathname::equal
+// METHOD TYPE : bool
+//
+// DESCRIPTION :
+//
+bool Pathname::equal( const Pathname & l, const Pathname & r )
+{
+ return l.asString() == r.asString();
+}
+
+/******************************************************************
+**
+**
+** FUNCTION NAME : operator<<
+** FUNCTION TYPE : inline std::ostream &
+**
+** DESCRIPTION :
+*/
+ostream & operator<<( ostream & str, const Pathname & obj )
+{
+ return str << obj.asString();
+}
+
+} // namespace zypp
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/Pathname.h
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#ifndef ZYPP_PATHNAME_H
+#define ZYPP_PATHNAME_H
+
+#include <iosfwd>
+#include <string>
+
+namespace zypp {
+
+///////////////////////////////////////////////////////////////////
+//
+// CLASS NAME : Pathname
+//
+// DESCRIPTION :
+//
+class Pathname {
+
+ private:
+
+ std::string::size_type prfx_i;
+ std::string name_t;
+
+ protected:
+
+ void _assign( const std::string & name_tv );
+
+ public:
+
+ virtual ~Pathname() {}
+
+ Pathname() {
+ prfx_i = 0;
+ name_t = "";
+ }
+ Pathname( const Pathname & path_tv ) {
+ prfx_i = path_tv.prfx_i;
+ name_t = path_tv.name_t;
+ }
+ Pathname( const std::string & name_tv ) {
+ _assign( name_tv );
+ }
+ Pathname( const char * name_tv ) {
+ _assign( name_tv ? name_tv : "" );
+ }
+
+ Pathname & operator= ( const Pathname & path_tv );
+ Pathname & operator+=( const Pathname & path_tv );
+
+ const std::string & asString() const { return name_t; }
+
+ bool empty() const { return !name_t.size(); }
+ bool absolute() const { return !empty() && name_t[prfx_i] == '/'; }
+ bool relative() const { return !empty() && name_t[prfx_i] != '/'; }
+
+ Pathname dirname() const { return dirname( *this ); }
+ std::string basename() const { return basename( *this ); }
+ Pathname absolutename() const { return absolutename( *this ); }
+ Pathname relativename() const { return relativename( *this ); }
+
+ static Pathname dirname ( const Pathname & name_tv );
+ static std::string basename ( const Pathname & name_tv );
+ static Pathname absolutename( const Pathname & name_tv ) { return name_tv.relative() ? cat( "/", name_tv ) : name_tv; }
+ static Pathname relativename( const Pathname & name_tv ) { return name_tv.absolute() ? cat( ".", name_tv ) : name_tv; }
+
+ Pathname cat( const Pathname & r ) const { return cat( *this, r ); }
+ static Pathname cat( const Pathname & l, const Pathname & r );
+
+ Pathname extend( const std::string & r ) const { return extend( *this, r ); }
+ static Pathname extend( const Pathname & l, const std::string & r );
+
+ bool equal( const Pathname & r ) const { return equal( *this, r ); }
+ static bool equal( const Pathname & l, const Pathname & r );
+};
+
+///////////////////////////////////////////////////////////////////
+
+inline bool operator==( const Pathname & l, const Pathname & r ) {
+ return Pathname::equal( l, r );
+}
+
+inline bool operator!=( const Pathname & l, const Pathname & r ) {
+ return !Pathname::equal( l, r );
+}
+
+inline Pathname operator+( const Pathname & l, const Pathname & r ) {
+ return Pathname::cat( l, r );
+}
+
+inline Pathname & Pathname::operator=( const Pathname & path_tv ) {
+ if ( &path_tv != this ) {
+ prfx_i = path_tv.prfx_i;
+ name_t = path_tv.name_t;
+ }
+ return *this;
+}
+
+inline Pathname & Pathname::operator+=( const Pathname & path_tv ) {
+ return( *this = *this + path_tv );
+}
+
+///////////////////////////////////////////////////////////////////
+
+extern std::ostream & operator<<( std::ostream & str, const Pathname & obj );
+
+///////////////////////////////////////////////////////////////////
+} // namespace zypp
+
+#endif // ZYPP_PATHNAME_H
PtrTypes.h \
ReferenceCounted.h \
String.h \
- StringVal.h
+ StringVal.h \
+ \
+ \
+ ExternalDataSource.h \
+ stringutil.h
noinst_LTLIBRARIES = lib@PACKAGE@_base.la
Logger.cc \
Exception.cc \
String.cc \
- StringVal.cc
+ StringVal.cc \
+ \
+ \
+ ExternalDataSource.cc \
+ stringutil.cc
lib@PACKAGE@_base_la_LIBADD = -lboost_regex
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/base/stringutil.cc
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#include <iostream>
+#include <fstream>
+
+#include "zypp/base/stringutil.h"
+
+using namespace std;
+///////////////////////////////////////////////////////////////////
+namespace zypp {
+ namespace base {
+ namespace stringutil {
+///////////////////////////////////////////////////////////////////
+
+ const unsigned tmpBuffLen = 1024;
+ char tmpBuff[tmpBuffLen];
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : getline
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ static inline std::string _getline( std::istream & str, const Trim trim_r )
+ {
+ string ret;
+ do {
+ str.clear();
+ str.getline( tmpBuff, tmpBuffLen ); // always writes '\0' terminated
+ ret += tmpBuff;
+ } while( str.rdstate() == ios::failbit );
+
+ return trim( ret, trim_r );
+ }
+
+ std::string getline( std::istream & str, const Trim trim_r )
+ {
+ return _getline(str, trim_r);
+ }
+
+ std::string getline( std::istream & str, bool trim )
+ {
+ return _getline(str, trim?TRIM:NO_TRIM);
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : split
+ ** FUNCTION TYPE : unsigned
+ **
+ ** DESCRIPTION :
+ */
+ unsigned split( const std::string line_tv,
+ std::vector<std::string> & words_Vtr,
+ const std::string & sep_tv,
+ const bool singlesep_bv )
+ {
+ words_Vtr.clear();
+ if ( line_tv.empty() )
+ return words_Vtr.size();
+
+ struct sepctrl {
+ const string & sep_t;
+ sepctrl( const string & sep_tv ) : sep_t( sep_tv ) {}
+ // Note that '\0' ist neither Sep nor NonSep
+ inline bool isSep ( const char c ) const { return( sep_t.find( c ) != string::npos ); }
+ inline bool isNonSep ( const char c ) const { return( c && !isSep(c) ); }
+ inline void skipSep ( const char *& p ) const { while ( isSep( *p ) ) ++p; }
+ inline void skipNonSep( const char *& p ) const { while ( isNonSep( *p ) ) ++p; }
+ };
+
+ sepctrl sep_Ci( sep_tv );
+ const char * s_pci = line_tv.c_str();
+ const char * c_pci = s_pci;
+
+ // Start with c_pci at the beginning of the 1st field to add.
+ // In singlesep the beginning might be equal to the next sep,
+ // which makes an empty field before the sep.
+ if ( !singlesep_bv && sep_Ci.isSep( *c_pci ) ) {
+ sep_Ci.skipSep( c_pci );
+ }
+
+ for ( s_pci = c_pci; *s_pci; s_pci = c_pci ) {
+ sep_Ci.skipNonSep( c_pci );
+ words_Vtr.push_back( string( s_pci, c_pci - s_pci ) );
+ if ( *c_pci ) {
+ if ( singlesep_bv ) {
+ if ( !*(++c_pci) ) {
+ // line ends with a sep -> add the empty field behind
+ words_Vtr.push_back( "" );
+ }
+ } else
+ sep_Ci.skipSep( c_pci );
+ }
+ }
+
+ return words_Vtr.size();
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : join
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ std::string join( const std::vector<std::string> & words_r,
+ const std::string & sep_r )
+ {
+ if ( words_r.empty() )
+ return "";
+
+ string ret( words_r[0] );
+
+ for ( unsigned i = 1; i < words_r.size(); ++i ) {
+ ret += sep_r + words_r[i];
+ }
+
+ return ret;
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : stripFirstWord
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ string stripFirstWord( string & line, const bool ltrim_first )
+ {
+ if ( ltrim_first )
+ line = ltrim( line );
+
+ if ( line.empty() )
+ return line;
+
+ string ret;
+ string::size_type p = line.find_first_of( " \t" );
+
+ if ( p == string::npos ) {
+ // no ws on line
+ ret = line;
+ line.erase();
+ } else if ( p == 0 ) {
+ // starts with ws
+ // ret remains empty
+ line = ltrim( line );
+ }
+ else {
+ // strip word and ltim line
+ ret = line.substr( 0, p );
+ line = ltrim( line.erase( 0, p ) );
+ }
+ return ret;
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : ltrim
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ std::string ltrim( const std::string & s )
+ {
+ if ( s.empty() )
+ return s;
+
+ string::size_type p = s.find_first_not_of( " \t\n" );
+ if ( p == string::npos )
+ return "";
+
+ return s.substr( p );
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : rtrim
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ std::string rtrim( const std::string & s )
+ {
+ if ( s.empty() )
+ return s;
+
+ string::size_type p = s.find_last_not_of( " \t\n" );
+ if ( p == string::npos )
+ return "";
+
+ return s.substr( 0, p+1 );
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : toLower
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ std::string toLower( const std::string & s )
+ {
+ if ( s.empty() )
+ return s;
+
+ string ret( s );
+ for ( string::size_type i = 0; i < ret.length(); ++i ) {
+ if ( isupper( ret[i] ) )
+ ret[i] = static_cast<char>(tolower( ret[i] ));
+ }
+ return ret;
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : toUpper
+ ** FUNCTION TYPE : std::string
+ **
+ ** DESCRIPTION :
+ */
+ std::string toUpper( const std::string & s )
+ {
+ if ( s.empty() )
+ return s;
+
+ string ret( s );
+ for ( string::size_type i = 0; i < ret.length(); ++i ) {
+ if ( islower( ret[i] ) )
+ ret[i] = static_cast<char>(toupper( ret[i] ));
+ }
+ return ret;
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : dumpOn
+ ** FUNCTION TYPE : std::ostream &
+ **
+ ** DESCRIPTION :
+ */
+ std::ostream & dumpOn( std::ostream & str, const std::list<std::string> & l, const bool numbered )
+ {
+ unsigned i = 0;
+ for ( std::list<std::string>::const_iterator it = l.begin(); it != l.end(); ++it, ++i ) {
+ if ( numbered )
+ str << '[' << i << ']';
+ str << *it << endl;
+ }
+ return str;
+ }
+
+ /******************************************************************
+ **
+ **
+ ** FUNCTION NAME : dumpOn
+ ** FUNCTION TYPE : std::ostream &
+ **
+ ** DESCRIPTION :
+ */
+ std::ostream & dumpOn( std::ostream & str, const std::vector<std::string> & l, const bool numbered )
+ {
+ for ( unsigned i = 0; i < l.size(); ++i ) {
+ if ( numbered )
+ str << '[' << i << ']';
+ str << l[i] << endl;
+ }
+ return str;
+ }
+
+///////////////////////////////////////////////////////////////////
+ } // namespace stringutil
+///////////////////////////////////////////////////////////////////
+ } // namespace base
+} // namespace zypp
+
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/base/stringutil.h
+ *
+ * \todo replace by Blocxx
+ *
+*/
+
+#ifndef ZYPP_BASE_STRINGUTIL_H
+#define ZYPP_BASE_STRINGUTIL_H
+
+#include <cstdio>
+#include <cstdarg>
+
+#include <iosfwd>
+#include <vector>
+#include <string>
+#include <list>
+
+/**
+ * Utility functions for std::strings. Most of them based on stringutil::form.
+ **/
+///////////////////////////////////////////////////////////////////
+namespace zypp {
+ namespace base {
+ namespace stringutil {
+//////////////////////////////////////////////////////////////////
+
+ enum Trim {
+ NO_TRIM = 0x00,
+ L_TRIM = 0x01,
+ R_TRIM = 0x02,
+ TRIM = (L_TRIM|R_TRIM)
+ };
+
+ inline std::string form( const char * format, ... )
+ __attribute__ ((format (printf, 1, 2)));
+
+ /**
+ * Printf style building of strings via format string.
+ * <PRE>
+ * std::string ex( stringutil::form( "Example number %d", 1 ) );
+ * std::cout << ex << stringutil::form( " and number %d.", 2 ) << endl;
+ *
+ * Will print: Example number 1 and number 2.
+ * </PRE>
+ **/
+ inline std::string form( const char * format, ... ) {
+ char * buf = 0;
+ std::string val;
+
+ va_list ap;
+ va_start( ap, format );
+
+ #if 1
+ vasprintf( &buf, format, ap );
+ if ( buf ) {
+ val = buf;
+ free( buf );
+ }
+ #else
+ // Don't know wheter we actually nedd two va_lists, one to
+ // evaluate the buffer size needed, and one to actually fill
+ // the buffer. Maybe there's a save way to reuse a va_lists.
+ va_list ap1;
+ va_start( ap1, format );
+ buf = new char[vsnprintf( NULL, 0, format, ap ) + 1];
+ vsprintf( buf, format, ap1 );
+ val = buf;
+ delete [] buf;
+ va_end( ap1 );
+ #endif
+
+ va_end( ap );
+ return val;
+ }
+
+ /**
+ * Print number. Optional second argument sets the minimal string width (' ' padded).
+ * Negative values will cause the number to be left adjusted within the string. Default
+ * width is 0.
+ * <PRE>
+ * numstring(42) -> "42"
+ * numstring(42, 4) -> " 42"
+ * numstring(42,-4) -> "42 "
+ * </PRE>
+ **/
+ inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); }
+ inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); }
+ inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); }
+ inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); }
+ inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); }
+ inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); }
+ inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); }
+ inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); }
+ inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); }
+ inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); }
+
+ /**
+ * Print number as hex value with leading '0x'. Optional second argument sets the minimal
+ * string width (0 padded). Negative values will cause the number to be left adjusted
+ * within the string. Default width is 10 (4 for char).
+ * <PRE>
+ * hexstring(42) -> "0x0000002a"
+ * hexstring(42, 4) -> "0x2a"
+ * hexstring(42,-4) -> "0x2a"
+ * </PRE>
+ **/
+ inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
+ inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); }
+ inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
+ inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); }
+ inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); }
+ inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); }
+ inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
+ inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); }
+ inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
+ inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); }
+
+ /**
+ * Print number as octal value with leading '0'. Optional second argument sets the minimal
+ * string width (0 padded). Negative values will cause the number to be left adjusted
+ * within the string. Default width is 5 (4 for char).
+ * <PRE>
+ * octstring(42) -> "00052"
+ * octstring(42, 4) -> "0052"
+ * octstring(42,-4) -> "052 "
+ * </PRE>
+ **/
+ inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
+ inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); }
+ inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
+ inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); }
+ inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); }
+ inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); }
+ inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
+ inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); }
+ inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
+ inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); }
+
+ /**
+ * String to integer type determined by template arg: time_t t = strtonum<time_t>( "42" );
+ **/
+ template<typename _It>
+ inline _It strtonum( const std::string & str );
+
+ template<>
+ inline short strtonum( const std::string & str ) { return ::strtol ( str.c_str(), NULL, 0 ); }
+ template<>
+ inline int strtonum( const std::string & str ) { return ::strtol ( str.c_str(), NULL, 0 ); }
+ template<>
+ inline long strtonum( const std::string & str ) { return ::strtol ( str.c_str(), NULL, 0 ); }
+ template<>
+ inline long long strtonum( const std::string & str ) { return ::strtoll ( str.c_str(), NULL, 0 ); }
+
+ template<>
+ inline unsigned short strtonum( const std::string & str ) { return ::strtoul ( str.c_str(), NULL, 0 ); }
+ template<>
+ inline unsigned strtonum( const std::string & str ) { return ::strtoul ( str.c_str(), NULL, 0 ); }
+ template<>
+ inline unsigned long strtonum( const std::string & str ) { return ::strtoul ( str.c_str(), NULL, 0 ); }
+ template<>
+ inline unsigned long long strtonum( const std::string & str ) { return ::strtoull( str.c_str(), NULL, 0 ); }
+
+ /**
+ * String to integer type detemined function arg: time_t t; strtonum( "42", t );
+ **/
+ template<typename _It>
+ inline _It strtonum( const std::string & str, _It & i ) { return i = strtonum<_It>( str ); }
+
+ /** \brief read one line from a stream
+ * Return one line read from istream. Afterwards the streampos is behind the delimiting '\n'
+ * (or at EOF). The delimiting '\n' is <b>not</b> returned.
+ *
+ * If trim is true, the string returned is trimmed (surrounding whitespaces removed).
+ * <PRE>
+ * ifstream s( "somefile" );
+ *
+ * while ( s ) {
+ * string l = getline( s );
+ * if ( !(s.fail() || s.bad()) ) {
+ *
+ * // l contains valid data to be consumed.
+ * // In case it makes any difference to you:
+ * if ( s.good() ) {
+ * // A delimiting '\n' was read.
+ * } else {
+ * // s.eof() is set: There's no '\n' at the end of file.
+ * // Note: The line returned may netvertheless be empty if trimed is true.
+ * }
+ * }
+ * }
+ * </PRE>
+ **/
+ extern std::string getline( std::istream & str, bool trim = false );
+
+ /** \brief read one line from a stream
+ *
+ * like above but with allows to specify trimming direction
+ * */
+ extern std::string getline( std::istream & str, const Trim trim_r );
+
+ /**
+ * Split line into words
+ *
+ * <b>singlesep_r = false</b>: Separator is any nonenmpty sequence of characters listed in sep_t.
+ * Leading trailing separators are ignored.
+ *
+ * <b>Example:</b> singlesep_r = false, sep_t = ":"
+ * <PRE>
+ * "" -> words 0
+ * ":" -> words 0
+ * "a" -> words 1 |a|
+ * "::a" -> words 1 |a|
+ * "::a::" -> words 1 |a|
+ * ":a::b:c:"-> words 3 |a|b|c|
+ * </PRE>
+ *
+ * <b>singlesep_r = true</b>: Separator is any single character occuring in sep_t.
+ * Leading trailing separators are not ignored (i.e will cause an empty word).
+ *
+ * <b>Example:</b> singlesep_r = true, sep_t = ":"
+ * <PRE>
+ * "" -> words 0
+ * ":" -> words 2 |||
+ * "a" -> words 1 |a|
+ * ":a" -> words 2 ||a|
+ * "a:" -> words 2 |a||
+ * ":a:" -> words 3 ||a||
+ * </PRE>
+ *
+ **/
+ extern unsigned split( const std::string line_r,
+ std::vector<std::string> & words_r,
+ const std::string & sep_t = " \t",
+ const bool singlesep_r = false );
+
+ /**
+ * Join strinngs in words_r using separator sep_r
+ **/
+ extern std::string join( const std::vector<std::string> & words_r,
+ const std::string & sep_r = " " );
+
+
+ /**
+ * Split string into a list of lines using <b>any<\b> char in sep_r as line
+ * delimiter. The delimiter is stripped from the line.
+ *
+ * <PRE>
+ * splitToLines( "start\n\nend" ) -> { "start", "", "end" }
+ * </PRE>
+ **/
+ inline std::list<std::string> splitToLines( const std::string text_r, const std::string & sep_r = "\n" )
+ {
+ std::vector<std::string> lines;
+ stringutil::split( text_r, lines, "\n", true );
+ std::list<std::string> ret;
+ for ( unsigned i = 0; i < lines.size(); ++i ) {
+ ret.push_back( lines[i] );
+ }
+ return ret;
+ }
+
+ /**
+ * Strip the first word (delimited by blank or tab) from value, and return it.
+ * Adjust value to start with the second word afterwards.
+ *
+ * If value starts with blank or tab, the <b>first word is empty</b> and value will be
+ * ltrimmed afterwards.
+ *
+ * If ltrim_first is true, value will be ltrimmed before stripping the first word. Thus
+ * first word is empty, iff value is empty or contains whitespace only.
+ *
+ * <PRE>
+ * stripFirstWord( "1st" ) == "1st" and value truncated to ""
+ * stripFirstWord( "1st word" ) == "1st" and value truncated to "word"
+ * stripFirstWord( " 1st word" ) == "" and value truncated to "1st word"
+ * stripFirstWord( " 1st word", true ) == "1st" and value truncated to "word"
+ * </PRE>
+ **/
+ extern std::string stripFirstWord( std::string & value, const bool ltrim_first = false );
+
+ /**
+ * Return string with leading/trailing/surrounding whitespace removed
+ **/
+ extern std::string ltrim( const std::string & s );
+ extern std::string rtrim( const std::string & s );
+ inline std::string trim( const std::string & s, const Trim trim_r = TRIM ) {
+ switch ( trim_r ) {
+ case L_TRIM:
+ return ltrim( s );
+ case R_TRIM:
+ return rtrim( s );
+ case TRIM:
+ return ltrim( rtrim( s ) );
+ case NO_TRIM:
+ break;
+ }
+ return s;
+ }
+
+ /**
+ * Return string converted to lower/upper case
+ **/
+ extern std::string toLower( const std::string & s );
+ extern std::string toUpper( const std::string & s );
+
+ /**
+ * Helper for stream output
+ **/
+ extern std::ostream & dumpOn( std::ostream & str, const std::list<std::string> & l, const bool numbered = false );
+ extern std::ostream & dumpOn( std::ostream & str, const std::vector<std::string> & l, const bool numbered = false );
+
+///////////////////////////////////////////////////////////////////
+ } // namespace stringutil
+ } // namespace base
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+
+#endif // ZYPP_BASE_STRINGUTIL_H
--- /dev/null
+## Process this file with automake to produce Makefile.in
+## ##################################################
+
+SUBDIRS =
+
+INCLUDES = -I$(oldincludedir)/libxml2
+
+## ##################################################
+
+include_HEADERS = \
+ MediaException.h \
+ MediaAccess.h \
+ MediaHandler.h \
+ MediaCurl.h
+
+
+noinst_LTLIBRARIES = lib@PACKAGE@_media.la
+
+## ##################################################
+
+lib@PACKAGE@_media_la_SOURCES = \
+ MediaAccess.cc \
+ MediaHandler.cc \
+ MediaCurl.cc
+
+lib@PACKAGE@_media_la_LIBADD = -lcurl
+
+## ##################################################