-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.cpp
173 lines (145 loc) · 4.8 KB
/
common.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//////////////////////////////////////////////////////////////////////
// common.cpp
//////////////////////////////////////////////////////////////////////
#include <sstream>
#include <fstream>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <sys/stat.h>
#include "common.h"
#include "data.h"
//////////////////////////////////////////////////////////////////////
namespace Jarbinger {
using std::cout;
using std::endl;
using std::string;
using std::stringstream;
using std::ofstream;
//////////////////////////////////////////////////////////////////////
#define MODE_DEFAULT (S_IRUSR | S_IWUSR | S_IXUSR)
//////////////////////////////////////////////////////////////////////
/**
* manages a working directory (temporary by default) that
* is deleted when WorkDir goes out of scope
*/
class WorkDir {
public:
WorkDir(string path, mode_t mode= MODE_DEFAULT) : _path(path), _mode(mode) {
boost::filesystem::path bfPath(path);
mkdirPath(bfPath);
setPermission(mode);
_keep= false;
_lastPath= getCwd();
_stay= false;
if (setCwd(_path)) {
throw Exception("unable to chdir to '"+ _path +"'");
}
}
void keep() { _keep= true; }
void stay() { _stay= true; }
void setPermission(mode_t mode= MODE_DEFAULT) {
if (chmod(_path.c_str(), mode)) {
throw Exception("unable to chmod '"+ _path +"'");
}
}
~WorkDir() {
if (! _stay) {
if (setCwd(_lastPath)) {
throw Exception("unable to chdir to '"+ _lastPath +"'");
}
}
if (! _keep) {
string cleanupCmd("rm -rf "+ _path);
int systemStatus= system(cleanupCmd.c_str());
if (systemStatus) {
throw Exception("executing '"+ cleanupCmd +"'");
}
}
}
private:
void mkdirPath(boost::filesystem::path path) {
boost::filesystem::path parent= path.parent_path();
if (! boost::filesystem::exists(parent.c_str())) {
mkdirPath(parent);
}
if (! boost::filesystem::exists(path.c_str())) {
if (mkdir(path.c_str(), _mode)) {
string p(path.c_str());
throw Exception("unable to mkdir '"+ p +"'");
}
}
}
string _path;
mode_t _mode;
bool _keep;
string _lastPath;
bool _stay;
};
class WorkFile {
public:
WorkFile(string path) : _path(path) { /* nothing */ }
void keep() { _keep= true; }
~WorkFile() {
if (! _keep) {
if (unlink(_path.c_str())) {
throw Exception("removing '"+ _path +"'");
}
}
}
private:
string _path;
bool _keep;
};
//////////////////////////////////////////////////////////////////////
string unArchive(const string& toolName, char* dataAddr, const U64 dataSize) {
string archiveTail("data.tar.bz2");
string logname(getenv("LOGNAME"));
stringstream cacheRootS;
cacheRootS << boost::format(JARBINGER_CACHE_PATH_FORMAT) % logname % toolName % BUILD_TAG;
string cacheDirPath(cacheRootS.str());
string sentinelFilename(cacheDirPath +"/.sentinel");
string archiveFilename(cacheDirPath +"/"+ archiveTail);
if (! boost::filesystem::exists(cacheDirPath)
|| ! boost::filesystem::exists(sentinelFilename)) {
// only done if does not already exist
WorkDir cacheDir(cacheDirPath);
WorkFile archiveFile(archiveFilename);
writeToFile(archiveFilename, dataAddr, dataSize );
stringstream unarchiveCmdS;
unarchiveCmdS << boost::format(UNARCHIVE_CMD_FORMAT)
% archiveFilename.c_str();
int systemStatus= system(unarchiveCmdS.str().c_str());
if (systemStatus) {
throw Exception("executing '"+ unarchiveCmdS.str() +"'");
}
// create sentinel file. if sentinel missing, repeating
// this un-archive flow is required
char sentinelData[]= "I feel FANTASTIC and I'm still alive.\n";
writeToFile(sentinelFilename, sentinelData, sizeof(sentinelData));
cacheDir.keep();
}
return cacheDirPath;
}
void writeToFile(const string& filename, char* dataAddr, const U64 dataSize) {
ofstream os(filename.c_str(), std::ios::binary);
os.write(dataAddr, dataSize);
os.close();
}
string getCwd() {
char* cwdTmp= getcwd(NULL, 0);
string cwd(cwdTmp);
free(cwdTmp);
return cwd;
}
int setCwd(const string& dirName) {
return chdir(dirName.c_str());
}
void replace(string& str, const string& oldText, const string& newText) {
size_t pos= 0;
while((pos= str.find(oldText, pos)) != string::npos) {
str.replace(pos, oldText.length(), newText);
pos+= newText.length();
}
}
//////////////////////////////////////////////////////////////////////
}