libi2ncommon: (tomj) added daemon handling and recursive_delete()
[libi2ncommon] / src / filefunc.cpp
1 /***************************************************************************
2                           escape.cpp  -  escaping of strings
3                              -------------------
4     begin                : Sun Nov 14 1999
5     copyright            : (C) 1999 by Intra2net AG
6     email                : info@intra2net.com
7  ***************************************************************************/
8
9 #include <string>
10 #include <sstream>
11 #include <iostream>
12 #include <stdexcept>
13
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <dirent.h>
17 #include <pwd.h>
18 #include <grp.h>
19 #include <unistd.h>
20 #include <errno.h>
21
22 #include <filefunc.hxx>
23
24 using namespace std;
25
26 bool file_exists (const string &name)
27 {
28     struct stat statbuff;
29
30     if (stat(name.c_str(), &statbuff) < 0)
31         return false;
32     else
33         return true;
34 }
35
36 long fsize (const string &name)
37 {
38     long iReturn = -1;
39
40     struct stat statbuff;
41
42     if (lstat(name.c_str(), &statbuff) < 0)
43         return -1;
44
45     if (!S_ISREG(statbuff.st_mode))
46         return -1;
47
48     iReturn=statbuff.st_size;
49
50     return iReturn;
51 }
52
53 string load_file(const string &name)
54 {
55     FILE *f;
56     string s;
57
58     if (name.find ("..") != string::npos)
59         return ("can't load file (..): " + name);
60
61     f=::fopen(name.c_str(),"rb");
62     if (!f)
63     {
64         return ("");
65     }
66
67     ::fseek(f,0,SEEK_END);
68     int size=::ftell(f);
69     ::fseek(f,0,SEEK_SET);
70     char *c=new char[size+1];
71     ::fread(c,1,size,f);
72     s.assign(c,size);
73     delete[] c;
74     ::fclose (f);
75
76     return s;
77 }
78
79 bool chown(const char* file,const char* owner, const char* group)
80 {
81     struct passwd *p;
82     struct group *g;
83     uid_t uid;
84     gid_t gid;
85
86     p = getpwnam(owner);
87     if (p == NULL)
88         return false;
89     uid=p->pw_uid;
90
91     g = getgrnam(group);
92     if (g == NULL)
93         return false;
94     gid=g->gr_gid;
95
96     if (!::chown(file,uid,gid))
97         return true;
98     else
99         return false;
100 }
101
102 /**
103  * Recursive delete of files and directories
104  * @param path File or directory to delete
105  * @param error Will contain the error if the return value is false
106  * @return true on success, false otherwise
107  */
108 bool recursive_delete(const std::string &path, std::string *error)
109 {
110     bool rtn = true;
111
112     try {
113         struct stat my_stat;
114         if (stat(path.c_str(), &my_stat) != 0) {
115             throw runtime_error("can't stat " + path);
116         }
117
118         if (S_ISDIR(my_stat.st_mode)) {
119             DIR *dir = opendir(path.c_str());
120             if (!dir) {
121                 throw runtime_error("can't open directory " + path);
122             }
123
124             struct dirent *entry;
125             while ((entry = readdir(dir))) {
126                 string filename = entry->d_name;
127                 if (filename == "." || filename == "..") {
128                     continue;
129                 }
130
131                 // Delete subdir or file.
132                 rtn = recursive_delete(path + "/" + filename, error);
133                 if (rtn == false) {
134                     break;
135                 }
136             }
137
138             closedir(dir);
139             if (rmdir(path.c_str()) != 0) {
140                 throw runtime_error("can't remove directory " + path);
141             }
142         } else {
143             if (unlink(path.c_str()) != 0) {
144                 throw runtime_error("can't unlink " + path);
145             }
146         }
147     } catch (exception &e) {
148         if (error) {
149             ostringstream out;
150             out << e.what() << " (" << strerror(errno) << ")";
151             *error = out.str();
152         }
153         rtn = false;
154     } catch (...) {
155         if (error) {
156             ostringstream out;
157             out << "unknown error (" << strerror(errno) << ")";
158             *error = out.str();
159         }
160         rtn = false;
161     }
162
163     return rtn;
164 }