|
a/src/utils/readfile.cpp |
|
b/src/utils/readfile.cpp |
|
... |
|
... |
38 |
|
38 |
|
39 |
#include "readfile.h"
|
39 |
#include "readfile.h"
|
40 |
|
40 |
|
41 |
static void caterrno(string *reason, const char *what)
|
41 |
static void caterrno(string *reason, const char *what)
|
42 |
{
|
42 |
{
|
43 |
#define ERRBUFSZ 200
|
|
|
44 |
char errbuf[ERRBUFSZ];
|
|
|
45 |
if (reason) {
|
43 |
if (reason) {
|
46 |
*reason += "file_to_string: ";
|
44 |
reason->append("file_to_string: ");
|
47 |
*reason += what;
|
45 |
reason->append(what);
|
48 |
*reason += ": ";
|
46 |
reason->append(": ");
|
49 |
#ifdef sun
|
47 |
#ifdef sun
|
50 |
// Note: sun strerror is noted mt-safe ??
|
48 |
// Note: sun strerror is noted mt-safe ??
|
51 |
*reason += strerror(errno);
|
49 |
reason->append(strerror(errno));
|
52 |
#else
|
50 |
#else
|
|
|
51 |
#define ERRBUFSZ 200
|
|
|
52 |
char errbuf[ERRBUFSZ];
|
53 |
strerror_r(errno, errbuf, ERRBUFSZ);
|
53 |
strerror_r(errno, errbuf, ERRBUFSZ);
|
54 |
*reason += errbuf;
|
54 |
reason->append(errbuf);
|
55 |
#endif
|
55 |
#endif
|
56 |
}
|
56 |
}
|
57 |
}
|
57 |
}
|
58 |
|
58 |
|
|
|
59 |
class FileToString : public FileScanDo {
|
|
|
60 |
public:
|
|
|
61 |
FileToString(string& data) : m_data(data) {}
|
|
|
62 |
string& m_data;
|
|
|
63 |
bool init(unsigned int size, string *reason) {
|
|
|
64 |
if (size > 0)
|
|
|
65 |
m_data.reserve(size);
|
|
|
66 |
return true;
|
|
|
67 |
}
|
|
|
68 |
bool data(const char *buf, int cnt, string *reason) {
|
|
|
69 |
try {
|
|
|
70 |
m_data.append(buf, cnt);
|
|
|
71 |
} catch (...) {
|
|
|
72 |
caterrno(reason, "append");
|
|
|
73 |
return false;
|
|
|
74 |
}
|
|
|
75 |
return true;
|
|
|
76 |
}
|
|
|
77 |
};
|
|
|
78 |
|
|
|
79 |
bool file_to_string(const string &fn, string &data, string *reason)
|
|
|
80 |
{
|
|
|
81 |
FileToString accum(data);
|
|
|
82 |
return file_scan(fn, &accum, reason);
|
|
|
83 |
}
|
|
|
84 |
|
59 |
// Note: the fstat() + reserve() calls divide cpu usage almost by 2
|
85 |
// Note: the fstat() + reserve() (in init()) calls divide cpu usage almost by 2
|
60 |
// on both linux i586 and macosx (compared to just append())
|
86 |
// on both linux i586 and macosx (compared to just append())
|
61 |
// Also tried a version with mmap, but it's actually slower on the mac and not
|
87 |
// Also tried a version with mmap, but it's actually slower on the mac and not
|
62 |
// faster on linux.
|
88 |
// faster on linux.
|
63 |
bool file_to_string(const string &fn, string &data, string *reason)
|
89 |
bool file_scan(const string &fn, FileScanDo* doer, string *reason)
|
64 |
{
|
90 |
{
|
65 |
bool ret = false;
|
91 |
bool ret = false;
|
66 |
bool noclosing = true;
|
92 |
bool noclosing = true;
|
67 |
int fd = 0;
|
93 |
int fd = 0;
|
68 |
struct stat st;
|
94 |
struct stat st;
|
|
... |
|
... |
70 |
st.st_size = 0;
|
96 |
st.st_size = 0;
|
71 |
|
97 |
|
72 |
// If we have a file name, open it, else use stdin.
|
98 |
// If we have a file name, open it, else use stdin.
|
73 |
if (!fn.empty()) {
|
99 |
if (!fn.empty()) {
|
74 |
fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
|
100 |
fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
|
75 |
if (fd < 0
|
|
|
76 |
#if 1
|
|
|
77 |
|| fstat(fd, &st) < 0
|
101 |
if (fd < 0 || fstat(fd, &st) < 0) {
|
78 |
#endif
|
|
|
79 |
) {
|
|
|
80 |
caterrno(reason, "open/stat");
|
102 |
caterrno(reason, "open/stat");
|
81 |
return false;
|
103 |
return false;
|
82 |
}
|
104 |
}
|
83 |
noclosing = false;
|
105 |
noclosing = false;
|
84 |
}
|
106 |
}
|
85 |
if (st.st_size > 0)
|
107 |
if (st.st_size > 0)
|
86 |
data.reserve(st.st_size+1);
|
108 |
doer->init(st.st_size+1, reason);
|
87 |
|
109 |
else
|
|
|
110 |
doer->init(0, reason);
|
88 |
char buf[4096];
|
111 |
char buf[4096];
|
89 |
for (;;) {
|
112 |
for (;;) {
|
90 |
int n = read(fd, buf, 4096);
|
113 |
int n = read(fd, buf, 4096);
|
91 |
if (n < 0) {
|
114 |
if (n < 0) {
|
92 |
caterrno(reason, "read");
|
115 |
caterrno(reason, "read");
|
93 |
goto out;
|
116 |
goto out;
|
94 |
}
|
117 |
}
|
95 |
if (n == 0)
|
118 |
if (n == 0)
|
96 |
break;
|
119 |
break;
|
97 |
|
120 |
|
98 |
try {
|
121 |
if (!doer->data(buf, n, reason)) {
|
99 |
data.append(buf, n);
|
|
|
100 |
} catch (...) {
|
|
|
101 |
caterrno(reason, "append");
|
|
|
102 |
goto out;
|
122 |
goto out;
|
103 |
}
|
123 |
}
|
104 |
}
|
124 |
}
|
105 |
|
125 |
|
106 |
ret = true;
|
126 |
ret = true;
|
|
... |
|
... |
204 |
if (walker.getErrCnt() > 0)
|
224 |
if (walker.getErrCnt() > 0)
|
205 |
cout << walker.getReason();
|
225 |
cout << walker.getReason();
|
206 |
} else if (S_ISREG(st.st_mode)) {
|
226 |
} else if (S_ISREG(st.st_mode)) {
|
207 |
string s, reason;
|
227 |
string s, reason;
|
208 |
if (!file_to_string(top, s, &reason)) {
|
228 |
if (!file_to_string(top, s, &reason)) {
|
209 |
cerr << reason;
|
229 |
cerr << reason << endl;
|
210 |
exit(1);
|
230 |
exit(1);
|
211 |
} else {
|
231 |
} else {
|
212 |
cout << s;
|
232 |
cout << s;
|
213 |
}
|
233 |
}
|
214 |
}
|
234 |
}
|