From 0a654ec0af23fe5d4225c8d50fb2a6befd513c79 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Fri, 4 Apr 2008 12:29:50 +0000 Subject: [PATCH] libi2ncommon: (tomj) added daemon handling and recursive_delete() --- libi2ncommon.kdevelop | 26 +++++++++++++++ src/Makefile.am | 4 +- src/daemonfunc.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ src/daemonfunc.hxx | 25 ++++++++++++++ src/filefunc.cpp | 74 ++++++++++++++++++++++++++++++++++++++++-- src/filefunc.hxx | 2 + 6 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 src/daemonfunc.cpp create mode 100644 src/daemonfunc.hxx diff --git a/libi2ncommon.kdevelop b/libi2ncommon.kdevelop index 01beb7f..f8f531f 100644 --- a/libi2ncommon.kdevelop +++ b/libi2ncommon.kdevelop @@ -10,6 +10,7 @@ C++ Code + libi2ncommon @@ -125,6 +126,31 @@ 250 400 250 + false + 0 + true + true + false + std=_GLIBCXX_STD;__gnu_cxx=std + true + false + false + false + false + true + true + false + .; + + false + 3 + 3 + /usr/lib/qt-3.3 + EmbeddedKDevDesigner + /usr/lib/qt-3.3/bin/qmake + /usr/lib/qt-3.3/bin/designer + + diff --git a/src/Makefile.am b/src/Makefile.am index f26b4cd..421cca4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,8 +4,8 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu # the library search path. lib_LTLIBRARIES = libi2ncommon.la -include_HEADERS = pidfile.hxx logread.hxx insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx -libi2ncommon_la_SOURCES = pidfile.cpp logread.cpp oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp +include_HEADERS = daemonfunc.hxx pidfile.hxx logread.hxx insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx +libi2ncommon_la_SOURCES = daemonfunc.cpp pidfile.cpp logread.cpp oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp # Note: If you specify a:b:c as the version in the next line, # the library that is made has version (a-c).c.b. In this diff --git a/src/daemonfunc.cpp b/src/daemonfunc.cpp new file mode 100644 index 0000000..cc570e9 --- /dev/null +++ b/src/daemonfunc.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2008 by Intra2net AG - Thomas Jarosch * + * thomas.jarosch@intra2net.com * + * http://www.intra2net.com * + ***************************************************************************/ +#include +#include +#include +#include + +#include +#include +#include "daemonfunc.hxx" + +using namespace std; + +/** + * Fork into the background. + */ +void daemon::daemonize() +{ + int pid=fork(); + + if (pid < 0) + { + throw runtime_error("fork() failed"); + } + if (pid > 0) + { + // parent process + exit (0); + } + // pid==0 -> child process: continue +} + +/** + * Lookup uid for given username + * @param username username to convert + * @return uid of the user + */ +uid_t daemon::lookup_uid(const std::string &username) +{ + struct passwd *user = getpwnam(username.c_str()); + if (user == NULL) { + throw runtime_error("user " + username + " not found"); + } + + return user->pw_uid; +} + +/** + * Lookup gid for given group + * @param group group to convert + * @return gid of the group + */ +gid_t daemon::lookup_gid(const std::string &group) +{ + struct group *my_group = getgrnam(group.c_str()); + if (my_group == NULL) { + throw runtime_error("group " + group + " not found"); + } + + return my_group->gr_gid; +} + +/** + * Drop root priviledges + * @param username User to become. Don't change user if empty + * @param group Group to become. Don't change group if empty + */ +void daemon::drop_root_priviledges(const std::string &username, + const std::string &group) +{ + if (!group.empty()) { + if (setgid(daemon::lookup_gid(group))) { + throw runtime_error("Can't change to group " + group); + } + } + + if (!username.empty()) { + if (setuid(daemon::lookup_uid(username))) { + throw runtime_error("Can't change to user " + username); + } + } +} diff --git a/src/daemonfunc.hxx b/src/daemonfunc.hxx new file mode 100644 index 0000000..4e14560 --- /dev/null +++ b/src/daemonfunc.hxx @@ -0,0 +1,25 @@ +/*************************************************************************** + * Copyright (C) 2008 by Intra2net AG - Thomas Jarosch * + * thomas.jarosch@intra2net.com * + * http://www.intra2net.com * + ***************************************************************************/ +#ifndef DAEMONFUNC_H +#define DAEMONFUNC_H + +#include +#include + +/// Collection of functions for daemons +class daemon +{ +public: + static void daemonize(); + + static uid_t lookup_uid(const std::string &username); + static gid_t lookup_gid(const std::string &group); + + static void drop_root_priviledges(const std::string &username, + const std::string &group); +}; + +#endif diff --git a/src/filefunc.cpp b/src/filefunc.cpp index 6804af7..f65db18 100644 --- a/src/filefunc.cpp +++ b/src/filefunc.cpp @@ -7,13 +7,17 @@ ***************************************************************************/ #include +#include #include +#include #include #include +#include #include #include #include +#include #include @@ -22,7 +26,7 @@ using namespace std; bool file_exists (const string &name) { struct stat statbuff; - + if (stat(name.c_str(), &statbuff) < 0) return false; else @@ -32,15 +36,15 @@ bool file_exists (const string &name) long fsize (const string &name) { long iReturn = -1; - + struct stat statbuff; - + if (lstat(name.c_str(), &statbuff) < 0) return -1; if (!S_ISREG(statbuff.st_mode)) return -1; - + iReturn=statbuff.st_size; return iReturn; @@ -95,4 +99,66 @@ bool chown(const char* file,const char* owner, const char* group) return false; } +/** + * Recursive delete of files and directories + * @param path File or directory to delete + * @param error Will contain the error if the return value is false + * @return true on success, false otherwise + */ +bool recursive_delete(const std::string &path, std::string *error) +{ + bool rtn = true; + + try { + struct stat my_stat; + if (stat(path.c_str(), &my_stat) != 0) { + throw runtime_error("can't stat " + path); + } + + if (S_ISDIR(my_stat.st_mode)) { + DIR *dir = opendir(path.c_str()); + if (!dir) { + throw runtime_error("can't open directory " + path); + } + + struct dirent *entry; + while ((entry = readdir(dir))) { + string filename = entry->d_name; + if (filename == "." || filename == "..") { + continue; + } + + // Delete subdir or file. + rtn = recursive_delete(path + "/" + filename, error); + if (rtn == false) { + break; + } + } + + closedir(dir); + if (rmdir(path.c_str()) != 0) { + throw runtime_error("can't remove directory " + path); + } + } else { + if (unlink(path.c_str()) != 0) { + throw runtime_error("can't unlink " + path); + } + } + } catch (exception &e) { + if (error) { + ostringstream out; + out << e.what() << " (" << strerror(errno) << ")"; + *error = out.str(); + } + rtn = false; + } catch (...) { + if (error) { + ostringstream out; + out << "unknown error (" << strerror(errno) << ")"; + *error = out.str(); + } + rtn = false; + } + return rtn; +} diff --git a/src/filefunc.hxx b/src/filefunc.hxx index a4af02c..14c9ddb 100644 --- a/src/filefunc.hxx +++ b/src/filefunc.hxx @@ -15,4 +15,6 @@ std::string load_file (const std::string &name); bool chown(const char* file,const char* owner, const char* group); +bool recursive_delete(const std::string &path, std::string *error=NULL); + #endif -- 1.7.1