Switch to unified view

a/src/utils/readfile.cpp b/src/utils/readfile.cpp
1
#ifndef lint
1
#ifndef lint
2
static char rcsid[] = "@(#$Id: readfile.cpp,v 1.8 2008-04-18 11:37:50 dockes Exp $ (C) 2004 J.F.Dockes";
2
static char rcsid[] = "@(#$Id: readfile.cpp,v 1.9 2008-12-08 11:22:58 dockes Exp $ (C) 2004 J.F.Dockes";
3
#endif
3
#endif
4
/*
4
/*
5
 *   This program is free software; you can redistribute it and/or modify
5
 *   This program is free software; you can redistribute it and/or modify
6
 *   it under the terms of the GNU General Public License as published by
6
 *   it under the terms of the GNU General Public License as published by
7
 *   the Free Software Foundation; either version 2 of the License, or
7
 *   the Free Software Foundation; either version 2 of the License, or
...
...
15
 *   You should have received a copy of the GNU General Public License
15
 *   You should have received a copy of the GNU General Public License
16
 *   along with this program; if not, write to the
16
 *   along with this program; if not, write to the
17
 *   Free Software Foundation, Inc.,
17
 *   Free Software Foundation, Inc.,
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
 */
19
 */
20
#ifndef TEST_READFILE
20
21
21
#include <unistd.h>
22
#include <unistd.h>
22
#include <fcntl.h>
23
#include <fcntl.h>
24
#include <sys/types.h>
25
#include <sys/stat.h>
26
23
#ifndef O_STREAMING
27
#ifndef O_STREAMING
24
#define O_STREAMING 0
28
#define O_STREAMING 0
25
#endif
29
#endif
26
#include <errno.h>
30
#include <errno.h>
27
#include <cstring>
31
#include <cstring>
28
32
29
#include <string>
33
#include <string>
34
30
#ifndef NO_NAMESPACES
35
#ifndef NO_NAMESPACES
31
using std::string;
36
using std::string;
32
#endif /* NO_NAMESPACES */
37
#endif /* NO_NAMESPACES */
33
38
34
#include "readfile.h"
39
#include "readfile.h"
35
40
36
static void caterrno(string *reason)
41
static void caterrno(string *reason, const char *what)
37
{
42
{
38
#define ERRBUFSZ 200    
43
#define ERRBUFSZ 200    
39
    char errbuf[ERRBUFSZ];
44
    char errbuf[ERRBUFSZ];
40
  if (reason) {
45
    if (reason) {
46
  *reason += "file_to_string: ";
47
  *reason += what;
48
  *reason += ": ";
41
#ifdef sun
49
#ifdef sun
42
    // Note: sun strerror is noted mt-safe ??
50
  // Note: sun strerror is noted mt-safe ??
43
    *reason += string("file_to_string: open failed: ") + strerror(errno);
51
  *reason += strerror(errno);
44
#else
52
#else
45
    strerror_r(errno, errbuf, ERRBUFSZ);
53
  strerror_r(errno, errbuf, ERRBUFSZ);
46
    *reason += string("file_to_string: open failed: ") + errbuf;
54
  *reason += errbuf;
47
#endif
55
#endif
48
  }
56
    }
49
}
57
}
50
58
59
// Note: the fstat() + reserve() calls divide cpu usage almost by 2
60
// 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
62
// faster on linux.
51
bool file_to_string(const string &fn, string &data, string *reason)
63
bool file_to_string(const string &fn, string &data, string *reason)
52
{
64
{
53
    bool ret = false;
65
    bool ret = false;
54
    bool noclosing = true;
66
    bool noclosing = true;
55
    int fd = 0;
67
    int fd = 0;
68
    struct stat st;
69
    // Initialize st_size: if fn.empty() , the fstat() call won't happen. 
70
    st.st_size = 0;
56
71
72
    // If we have a file name, open it, else use stdin.
57
    if (!fn.empty()) {
73
    if (!fn.empty()) {
58
    fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
74
    fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
59
    if (fd < 0) {
75
    if (fd < 0 
76
#if 1
77
      || fstat(fd, &st) < 0
78
#endif
79
      ) {
60
        caterrno(reason);
80
        caterrno(reason, "open/stat");
61
        return false;
81
        return false;
62
    }
82
    }
63
    noclosing = false;
83
    noclosing = false;
64
    }
84
    }
85
    if (st.st_size > 0)
86
  data.reserve(st.st_size+1);
65
87
66
    char buf[4096];
88
    char buf[4096];
67
    for (;;) {
89
    for (;;) {
68
    int n = read(fd, buf, 4096);
90
    int n = read(fd, buf, 4096);
69
    if (n < 0) {
91
    if (n < 0) {
70
        caterrno(reason);
92
        caterrno(reason, "read");
71
        goto out;
93
        goto out;
72
    }
94
    }
73
    if (n == 0)
95
    if (n == 0)
74
        break;
96
        break;
75
97
76
    try {
98
    try {
77
        data.append(buf, n);
99
        data.append(buf, n);
78
    } catch (...) {
100
    } catch (...) {
79
        caterrno(reason);
101
        caterrno(reason, "append");
80
        goto out;
102
        goto out;
81
    }
103
    }
82
    }
104
    }
83
105
84
    ret = true;
106
    ret = true;
85
 out:
107
 out:
86
    if (fd >= 0 && !noclosing)
108
    if (fd >= 0 && !noclosing)
87
    close(fd);
109
    close(fd);
88
    return ret;
110
    return ret;
89
}
111
}
112
113
#else // Test
114
115
#include <sys/stat.h>
116
#include <stdlib.h>
117
118
#include <string>
119
#include <iostream>
120
using namespace std;
121
122
#include "readfile.h"
123
#include "fstreewalk.h"
124
125
using namespace std;
126
127
static int     op_flags;
128
#define OPT_MOINS 0x1
129
#define OPT_f   0x2
130
#define OPT_F   0x4
131
132
class myCB : public FsTreeWalkerCB {
133
 public:
134
    FsTreeWalker::Status processone(const string &path, 
135
                  const struct stat *st,
136
                  FsTreeWalker::CbFlag flg)
137
    {
138
  if (flg == FsTreeWalker::FtwDirEnter) {
139
      //cout << "[Entering " << path << "]" << endl;
140
  } else if (flg == FsTreeWalker::FtwDirReturn) {
141
      //cout << "[Returning to " << path << "]" << endl;
142
  } else if (flg == FsTreeWalker::FtwRegular) {
143
      //cout << path << endl;
144
      string s, reason;
145
      if (!file_to_string(path, s, &reason)) {
146
      cerr << "Failed: " << reason << " : " << path << endl;
147
      } else {
148
      //cout << 
149
      //"================================================" << endl;
150
      cout << path << endl;
151
      //      cout << s;
152
      }
153
      reason.clear();
154
  }
155
  return FsTreeWalker::FtwOk;
156
    }
157
};
158
159
static const char *thisprog;
160
static char usage [] =
161
"trreadfile topdirorfile\n\n"
162
;
163
static void
164
Usage(void)
165
{
166
    fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
167
    exit(1);
168
}
169
170
int main(int argc, const char **argv)
171
{
172
    list<string> patterns;
173
    list<string> paths;
174
    thisprog = argv[0];
175
    argc--; argv++;
176
177
  while (argc > 0 && **argv == '-') {
178
    (*argv)++;
179
    if (!(**argv))
180
      /* Cas du "adb - core" */
181
      Usage();
182
    while (**argv)
183
      switch (*(*argv)++) {
184
      case 'f':   op_flags |= OPT_f;break;
185
      case 'F':   op_flags |= OPT_F;break;
186
      default: Usage();   break;
187
      }
188
    argc--; argv++;
189
  }
190
191
  if (argc != 1)
192
    Usage();
193
  string top = *argv++;argc--;
194
195
  struct stat st;
196
  if (stat(top.c_str(), &st) < 0) {
197
      perror("stat");
198
      exit(1);
199
  }
200
  if (S_ISDIR(st.st_mode)) {
201
      FsTreeWalker walker;
202
      myCB cb;
203
      walker.walk(top, cb);
204
      if (walker.getErrCnt() > 0)
205
    cout << walker.getReason();
206
  } else if (S_ISREG(st.st_mode)) {
207
      string s, reason;
208
      if (!file_to_string(top, s, &reason)) {
209
    cerr << reason;
210
    exit(1);
211
      } else {
212
    cout << s;
213
      }
214
  }
215
  exit(0);
216
}
217
#endif //TEST_READFILE