Imported Upstream version 0.8~alpha1
[platform/upstream/syncevolution.git] / src / SyncEvolutionUtil.cpp
1 /*
2  * Copyright (C) 2008 Patrick Ohly
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
16  * 02111-1307  USA
17  */
18
19 #include <config.h>
20 #include "SyncEvolutionUtil.h"
21 #include "EvolutionSyncClient.h"
22 #include <base/test.h>
23
24 #include <boost/scoped_array.hpp>
25
26 #include <errno.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <dirent.h>
31
32 #ifdef ENABLE_UNIT_TESTS
33 CPPUNIT_REGISTRY_ADD_TO_DEFAULT("SyncEvolution");
34 #endif
35
36 string normalizePath(const string &path)
37 {
38     string res;
39
40     res.reserve(path.size());
41     size_t index = 0;
42     while (index < path.size()) {
43         char curr = path[index];
44         res += curr;
45         index++;
46         if (curr == '/') {
47             while (index < path.size() &&
48                    (path[index] == '/' ||
49                     (path[index] == '.' &&
50                      index + 1 < path.size() &&
51                      (path[index + 1] == '.' ||
52                       path[index + 1] == '/')))) {
53                 index++;
54             }
55         }
56     }
57     if (!res.empty() && res[res.size() - 1] == '/') {
58         res.resize(res.size() - 1);
59     }
60     return res;
61 }
62
63 void mkdir_p(const string &path)
64 {
65     boost::scoped_array<char> dirs(new char[path.size() + 1]);
66     char *curr = dirs.get();
67     strcpy(curr, path.c_str());
68     do {
69         char *nextdir = strchr(curr, '/');
70         if (nextdir) {
71             *nextdir = 0;
72             nextdir++;
73         }
74         if (*curr) {
75             if (access(dirs.get(),
76                        nextdir ? (R_OK|X_OK) : (R_OK|X_OK|W_OK)) &&
77                 (errno != ENOENT ||
78                  mkdir(dirs.get(), 0777))) {
79                 EvolutionSyncClient::throwError(string(dirs.get()) + ": " + strerror(errno));
80             }
81         }
82         if (nextdir) {
83             nextdir[-1] = '/';
84         }
85         curr = nextdir;
86     } while (curr);
87 }
88
89 void rm_r(const string &path)
90 {
91     if (!unlink(path.c_str()) ||
92         errno == ENOENT) {
93         return;
94     }
95
96     if (errno != EISDIR) {
97         EvolutionSyncClient::throwError(path + ": " + strerror(errno));
98     }
99
100     ReadDir dir(path);
101     for (ReadDir::const_iterator it = dir.begin();
102          it != dir.end();
103          ++it) {
104         rm_r(path + "/" + *it);
105     }
106     if (rmdir(path.c_str())) {
107         EvolutionSyncClient::throwError(path + ": " + strerror(errno));
108     }
109 }
110
111 bool isDir(const string &path)
112 {
113     DIR *dir = opendir(path.c_str());
114     if (dir) {
115         closedir(dir);
116         return true;
117     } else if (errno != ENOTDIR && errno != ENOENT) {
118         EvolutionSyncClient::throwError(path + ": " + strerror(errno));
119     }
120
121     return false;
122 }
123
124 UUID::UUID()
125 {
126     static class InitSRand {
127     public:
128         InitSRand() {
129             srand(time(NULL));
130         }
131     } initSRand;
132
133     char buffer[16 * 4 + 5];
134     sprintf(buffer, "%08x-%04x-%04x-%02x%02x-%08x%04x",
135             rand() & 0xFFFFFFFF,
136             rand() & 0xFFFF,
137             rand() & 0x0FFF | 0x4000 /* RFC 4122 time_hi_and_version */,
138             rand() & 0xBF | 0x80 /* clock_seq_hi_and_reserved */,
139             rand() & 0xFF,
140             rand() & 0xFFFFFFFF,
141             rand() & 0xFFFF
142             );
143     this->assign(buffer);
144 }
145
146
147 ReadDir::ReadDir(const string &path) : m_path(path)
148 {
149     DIR *dir = NULL;
150
151     try {
152         dir = opendir(path.c_str());
153         if (!dir) {
154             EvolutionSyncClient::throwError(path + ": " + strerror(errno));
155         }
156         errno = 0;
157         struct dirent *entry = readdir(dir);
158         while (entry) {
159             if (strcmp(entry->d_name, ".") &&
160                 strcmp(entry->d_name, "..")) {
161                 m_entries.push_back(entry->d_name);
162             }
163             entry = readdir(dir);
164         }
165         if (errno) {
166             EvolutionSyncClient::throwError(path + ": " + strerror(errno));
167         }
168     } catch(...) {
169         if (dir) {
170             closedir(dir);
171         }
172         throw;
173     }
174
175     closedir(dir);
176 }