--- a/src/utils/readfile.cpp
+++ b/src/utils/readfile.cpp
@@ -1,5 +1,5 @@
#ifndef lint
-static char rcsid[] = "@(#$Id: readfile.cpp,v 1.8 2008-04-18 11:37:50 dockes Exp $ (C) 2004 J.F.Dockes";
+static char rcsid[] = "@(#$Id: readfile.cpp,v 1.9 2008-12-08 11:22:58 dockes Exp $ (C) 2004 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@@ -17,9 +17,13 @@
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#ifndef TEST_READFILE
#include <unistd.h>
#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
#ifndef O_STREAMING
#define O_STREAMING 0
#endif
@@ -27,47 +31,65 @@
#include <cstring>
#include <string>
+
#ifndef NO_NAMESPACES
using std::string;
#endif /* NO_NAMESPACES */
#include "readfile.h"
-static void caterrno(string *reason)
+static void caterrno(string *reason, const char *what)
{
#define ERRBUFSZ 200
char errbuf[ERRBUFSZ];
- if (reason) {
+ if (reason) {
+ *reason += "file_to_string: ";
+ *reason += what;
+ *reason += ": ";
#ifdef sun
- // Note: sun strerror is noted mt-safe ??
- *reason += string("file_to_string: open failed: ") + strerror(errno);
+ // Note: sun strerror is noted mt-safe ??
+ *reason += strerror(errno);
#else
- strerror_r(errno, errbuf, ERRBUFSZ);
- *reason += string("file_to_string: open failed: ") + errbuf;
-#endif
- }
-}
-
+ strerror_r(errno, errbuf, ERRBUFSZ);
+ *reason += errbuf;
+#endif
+ }
+}
+
+// Note: the fstat() + reserve() calls divide cpu usage almost by 2
+// on both linux i586 and macosx (compared to just append())
+// Also tried a version with mmap, but it's actually slower on the mac and not
+// faster on linux.
bool file_to_string(const string &fn, string &data, string *reason)
{
bool ret = false;
bool noclosing = true;
int fd = 0;
-
+ struct stat st;
+ // Initialize st_size: if fn.empty() , the fstat() call won't happen.
+ st.st_size = 0;
+
+ // If we have a file name, open it, else use stdin.
if (!fn.empty()) {
fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
- if (fd < 0) {
- caterrno(reason);
+ if (fd < 0
+#if 1
+ || fstat(fd, &st) < 0
+#endif
+ ) {
+ caterrno(reason, "open/stat");
return false;
}
noclosing = false;
}
+ if (st.st_size > 0)
+ data.reserve(st.st_size+1);
char buf[4096];
for (;;) {
int n = read(fd, buf, 4096);
if (n < 0) {
- caterrno(reason);
+ caterrno(reason, "read");
goto out;
}
if (n == 0)
@@ -76,7 +98,7 @@
try {
data.append(buf, n);
} catch (...) {
- caterrno(reason);
+ caterrno(reason, "append");
goto out;
}
}
@@ -87,3 +109,109 @@
close(fd);
return ret;
}
+
+#else // Test
+
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include <string>
+#include <iostream>
+using namespace std;
+
+#include "readfile.h"
+#include "fstreewalk.h"
+
+using namespace std;
+
+static int op_flags;
+#define OPT_MOINS 0x1
+#define OPT_f 0x2
+#define OPT_F 0x4
+
+class myCB : public FsTreeWalkerCB {
+ public:
+ FsTreeWalker::Status processone(const string &path,
+ const struct stat *st,
+ FsTreeWalker::CbFlag flg)
+ {
+ if (flg == FsTreeWalker::FtwDirEnter) {
+ //cout << "[Entering " << path << "]" << endl;
+ } else if (flg == FsTreeWalker::FtwDirReturn) {
+ //cout << "[Returning to " << path << "]" << endl;
+ } else if (flg == FsTreeWalker::FtwRegular) {
+ //cout << path << endl;
+ string s, reason;
+ if (!file_to_string(path, s, &reason)) {
+ cerr << "Failed: " << reason << " : " << path << endl;
+ } else {
+ //cout <<
+ //"================================================" << endl;
+ cout << path << endl;
+ // cout << s;
+ }
+ reason.clear();
+ }
+ return FsTreeWalker::FtwOk;
+ }
+};
+
+static const char *thisprog;
+static char usage [] =
+"trreadfile topdirorfile\n\n"
+;
+static void
+Usage(void)
+{
+ fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
+ exit(1);
+}
+
+int main(int argc, const char **argv)
+{
+ list<string> patterns;
+ list<string> paths;
+ thisprog = argv[0];
+ argc--; argv++;
+
+ while (argc > 0 && **argv == '-') {
+ (*argv)++;
+ if (!(**argv))
+ /* Cas du "adb - core" */
+ Usage();
+ while (**argv)
+ switch (*(*argv)++) {
+ case 'f': op_flags |= OPT_f;break;
+ case 'F': op_flags |= OPT_F;break;
+ default: Usage(); break;
+ }
+ argc--; argv++;
+ }
+
+ if (argc != 1)
+ Usage();
+ string top = *argv++;argc--;
+
+ struct stat st;
+ if (stat(top.c_str(), &st) < 0) {
+ perror("stat");
+ exit(1);
+ }
+ if (S_ISDIR(st.st_mode)) {
+ FsTreeWalker walker;
+ myCB cb;
+ walker.walk(top, cb);
+ if (walker.getErrCnt() > 0)
+ cout << walker.getReason();
+ } else if (S_ISREG(st.st_mode)) {
+ string s, reason;
+ if (!file_to_string(top, s, &reason)) {
+ cerr << reason;
+ exit(1);
+ } else {
+ cout << s;
+ }
+ }
+ exit(0);
+}
+#endif //TEST_READFILE