Switch to unified view

a/src/utils/fstreewalk.cpp b/src/utils/fstreewalk.cpp
...
...
18
#include "autoconfig.h"
18
#include "autoconfig.h"
19
#endif
19
#endif
20
20
21
#ifndef TEST_FSTREEWALK
21
#ifndef TEST_FSTREEWALK
22
22
23
#include <stdio.h>
23
#include <dirent.h>
24
#include <dirent.h>
24
#include <sys/stat.h>
25
#include <sys/stat.h>
25
#include <errno.h>
26
#include <errno.h>
26
#include <fnmatch.h>
27
#include <fnmatch.h>
27
#include <cstring>
28
#include <cstring>
...
...
56
    return dev < r.dev || (dev == r.dev && ino < r.ino);
57
    return dev < r.dev || (dev == r.dev && ino < r.ino);
57
    }
58
    }
58
};
59
};
59
60
60
class FsTreeWalker::Internal {
61
class FsTreeWalker::Internal {
62
public:
63
    Internal(int opts)
64
    : options(opts), depthswitch(4), maxdepth(-1), errors(0)
65
    {
66
    }
61
    int options;
67
    int options;
62
    int depthswitch;
68
    int depthswitch;
69
    int maxdepth;
70
    int basedepth;
63
    stringstream reason;
71
    stringstream reason;
64
    vector<string> skippedNames;
72
    vector<string> skippedNames;
65
    vector<string> skippedPaths;
73
    vector<string> skippedPaths;
66
    // When doing Breadth or FilesThenDirs traversal, we keep a list
74
    // When doing Breadth or FilesThenDirs traversal, we keep a list
67
    // of directory paths to be processed, and we do not recurse.
75
    // of directory paths to be processed, and we do not recurse.
...
...
72
    {
80
    {
73
    errors++;
81
    errors++;
74
    reason << call << "(" << param << ") : " << errno << " : " << 
82
    reason << call << "(" << param << ") : " << errno << " : " << 
75
        strerror(errno) << endl;
83
        strerror(errno) << endl;
76
    }
84
    }
77
    friend class FsTreeWalker;
78
};
85
};
79
86
80
FsTreeWalker::FsTreeWalker(int opts)
87
FsTreeWalker::FsTreeWalker(int opts)
81
{
88
{
82
    data = new Internal;
89
    data = new Internal(opts);
90
}
91
92
FsTreeWalker::~FsTreeWalker()
93
{
94
    delete data;
95
}
96
97
void FsTreeWalker::setOpts(int opts)
98
{
83
    if (data) {
99
    if (data) {
84
    data->options = opts;
100
    data->options = opts;
85
        data->depthswitch = 4;
86
  data->errors = 0;
87
    }
101
    }
88
}
102
}
89
103
int FsTreeWalker::getOpts()
90
FsTreeWalker::~FsTreeWalker()
91
{
92
    delete data;
93
}
94
95
void FsTreeWalker::setOpts(Options opts, int depthswitch)
96
{
104
{
97
    if (data) {
105
    if (data) {
98
  data->options = opts;
106
  return data->options;
107
    } else {
108
  return 0;
109
    }
110
}
111
void FsTreeWalker::setDepthSwitch(int ds)
112
{
113
    if (data) {
99
        data->depthswitch = depthswitch;
114
        data->depthswitch = ds;
115
    }
116
}
117
void FsTreeWalker::setMaxDepth(int md)
118
{
119
    if (data) {
120
        data->maxdepth = md;
100
    }
121
    }
101
}
122
}
102
123
103
string FsTreeWalker::getReason()
124
string FsTreeWalker::getReason()
104
{
125
{
...
...
196
217
197
    if ((data->options & FtwTravMask) == 0) {
218
    if ((data->options & FtwTravMask) == 0) {
198
        data->options |= FtwTravNatural;
219
        data->options |= FtwTravNatural;
199
    }
220
    }
200
221
201
    int basedepth = slashcount(top); // Only used for breadthThenDepth
222
    data->basedepth = slashcount(top); // Only used for breadthxx
202
203
    struct stat st;
223
    struct stat st;
204
    // We always follow symlinks at this point. Makes more sense.
224
    // We always follow symlinks at this point. Makes more sense.
205
    if (stat(top.c_str(), &st) == -1) {
225
    if (stat(top.c_str(), &st) == -1) {
206
    // Note that we do not return an error if the stat call
226
    // Note that we do not return an error if the stat call
207
    // fails. A temp file may have gone away.
227
    // fails. A temp file may have gone away.
...
...
238
                data->dirs.pop_front();
258
                data->dirs.pop_front();
239
                nfather = path_getfather(dir);
259
                nfather = path_getfather(dir);
240
                if (data->options & FtwTravBreadthThenDepth) {
260
                if (data->options & FtwTravBreadthThenDepth) {
241
                    // Check if new depth warrants switch to depth first
261
                    // Check if new depth warrants switch to depth first
242
                    // traversal (will happen on next loop iteration).
262
                    // traversal (will happen on next loop iteration).
243
                    int curdepth = slashcount(dir) - basedepth;
263
                    int curdepth = slashcount(dir) - data->basedepth;
244
                    if (curdepth >= data->depthswitch) {
264
                    if (curdepth >= data->depthswitch) {
245
                        //fprintf(stderr, "SWITCHING TO DEPTH FIRST\n");
265
                        //fprintf(stderr, "SWITCHING TO DEPTH FIRST\n");
246
                        data->options &= ~FtwTravMask;
266
                        data->options &= ~FtwTravMask;
247
                        data->options |= FtwTravFilesThenDirs;
267
                        data->options |= FtwTravFilesThenDirs;
248
                    }
268
                    }
...
...
307
    return cb.processone(top, stp, FtwRegular);
327
    return cb.processone(top, stp, FtwRegular);
308
    } else {
328
    } else {
309
    return status;
329
    return status;
310
    }
330
    }
311
331
332
333
    int curdepth = slashcount(top) - data->basedepth;
334
    if (data->maxdepth >= 0 && curdepth >= data->maxdepth) {
335
  LOGDEB1(("FsTreeWalker::iwalk: Maxdepth reached: [%s]\n", top.c_str()));
336
  return status;
337
    }
338
312
    // This is a directory, read it and process entries:
339
    // This is a directory, read it and process entries:
313
340
314
    // Detect if directory already seen. This could just be several
341
    // Detect if directory already seen. This could just be several
315
    // symlinks pointing to the same place (if FtwFollow is set), it
342
    // symlinks pointing to the same place (if FtwFollow is set), it
316
    // could also be some other kind of cycle. In any case, there is
343
    // could also be some other kind of cycle. In any case, there is
...
...
343
370
344
    struct dirent *ent;
371
    struct dirent *ent;
345
    while ((ent = readdir(d)) != 0) {
372
    while ((ent = readdir(d)) != 0) {
346
        string fn;
373
        string fn;
347
        struct stat st;
374
        struct stat st;
375
  // Maybe skip dotfiles
376
  if ((data->options & FtwSkipDotFiles) && ent->d_name[0] == '.')
377
      continue;
348
    // Skip . and ..
378
    // Skip . and ..
349
    if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) 
379
    if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) 
350
        continue;
380
        continue;
351
381
352
    // Skipped file names match ?
382
    // Skipped file names match ?
...
...
437
#define OPT_b     0x20
467
#define OPT_b     0x20
438
#define OPT_d     0x40
468
#define OPT_d     0x40
439
#define OPT_m     0x80
469
#define OPT_m     0x80
440
#define OPT_L     0x100
470
#define OPT_L     0x100
441
#define OPT_w     0x200
471
#define OPT_w     0x200
472
#define OPT_M     0x400
473
#define OPT_D     0x800
442
474
443
class myCB : public FsTreeWalkerCB {
475
class myCB : public FsTreeWalkerCB {
444
 public:
476
 public:
445
    FsTreeWalker::Status processone(const string &path, 
477
    FsTreeWalker::Status processone(const string &path, 
446
                                    const struct stat *st,
478
                                    const struct stat *st,
...
...
487
" -L : follow symbolic links\n"
519
" -L : follow symbolic links\n"
488
" -b : use breadth first walk\n"
520
" -b : use breadth first walk\n"
489
" -d : use almost depth first (dir files, then subdirs)\n"
521
" -d : use almost depth first (dir files, then subdirs)\n"
490
" -m : use breadth up to 4 deep then switch to -d\n"
522
" -m : use breadth up to 4 deep then switch to -d\n"
491
" -w : unset default FNM_PATHNAME when using fnmatch() to match skipped paths\n"
523
" -w : unset default FNM_PATHNAME when using fnmatch() to match skipped paths\n"
524
" -M <depth>: limit depth (works with -b/m/d)\n"
525
" -D : skip dotfiles\n"
492
;
526
;
493
static void
527
static void
494
Usage(void)
528
Usage(void)
495
{
529
{
496
    fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
530
    fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
...
...
499
533
500
int main(int argc, const char **argv)
534
int main(int argc, const char **argv)
501
{
535
{
502
    vector<string> patterns;
536
    vector<string> patterns;
503
    vector<string> paths;
537
    vector<string> paths;
538
    int maxdepth = -1;
539
504
    thisprog = argv[0];
540
    thisprog = argv[0];
505
    argc--; argv++;
541
    argc--; argv++;
506
507
  while (argc > 0 && **argv == '-') {
542
    while (argc > 0 && **argv == '-') {
508
    (*argv)++;
543
  (*argv)++;
509
    if (!(**argv))
544
  if (!(**argv))
510
      /* Cas du "adb - core" */
545
      /* Cas du "adb - core" */
511
      Usage();
546
      Usage();
512
    while (**argv)
547
  while (**argv)
513
      switch (*(*argv)++) {
548
      switch (*(*argv)++) {
514
      case 'b':  op_flags |= OPT_b; break;
549
      case 'b':  op_flags |= OPT_b; break;
515
      case 'c':  op_flags |= OPT_c; break;
550
      case 'c':  op_flags |= OPT_c; break;
516
      case 'd':  op_flags |= OPT_d; break;
551
      case 'd':  op_flags |= OPT_d; break;
552
      case 'D':   op_flags |= OPT_D; break;
517
      case 'L':  op_flags |= OPT_L; break;
553
      case 'L':  op_flags |= OPT_L; break;
518
      case 'm':  op_flags |= OPT_m; break;
554
      case 'm':  op_flags |= OPT_m; break;
555
      case 'M':   op_flags |= OPT_M; if (argc < 2)  Usage();
556
      maxdepth = atoi(*(++argv));
557
      argc--; 
558
      goto b1;
519
      case 'p':  op_flags |= OPT_p; if (argc < 2)  Usage();
559
      case 'p':  op_flags |= OPT_p; if (argc < 2)  Usage();
520
      patterns.push_back(*(++argv));
560
      patterns.push_back(*(++argv));
521
      argc--; 
561
      argc--; 
522
      goto b1;
562
      goto b1;
523
      case 'P':  op_flags |= OPT_P; if (argc < 2)  Usage();
563
      case 'P':  op_flags |= OPT_P; if (argc < 2)  Usage();
524
      paths.push_back(*(++argv));
564
      paths.push_back(*(++argv));
525
    argc--; 
565
     argc--; 
526
    goto b1;
566
     goto b1;
527
      case 'r':  op_flags |= OPT_r; break;
567
      case 'r':  op_flags |= OPT_r; break;
528
      case 'w':  op_flags |= OPT_w; break;
568
      case 'w':  op_flags |= OPT_w; break;
529
      default: Usage();  break;
569
      default: Usage();  break;
530
      }
570
      }
531
  b1: argc--; argv++;
571
    b1: argc--; argv++;
532
  }
572
    }
533
573
534
  if (argc != 1)
574
    if (argc != 1)
535
    Usage();
575
  Usage();
536
  string topdir = *argv++;argc--;
576
    string topdir = *argv++;argc--;
537
577
538
  int opt = 0;
578
    int opt = 0;
539
  if (op_flags & OPT_r)
579
    if (op_flags & OPT_r)
540
      opt |= FsTreeWalker::FtwNoRecurse;
580
  opt |= FsTreeWalker::FtwNoRecurse;
541
  if (op_flags & OPT_c)
581
    if (op_flags & OPT_c)
542
      opt |= FsTreeWalker::FtwNoCanon;
582
  opt |= FsTreeWalker::FtwNoCanon;
543
  if (op_flags & OPT_L)
583
    if (op_flags & OPT_L)
544
      opt |= FsTreeWalker::FtwFollow;
584
  opt |= FsTreeWalker::FtwFollow;
585
    if (op_flags & OPT_D)
586
  opt |= FsTreeWalker::FtwSkipDotFiles;
545
587
546
  if (op_flags & OPT_b)
588
    if (op_flags & OPT_b)
547
      opt |= FsTreeWalker::FtwTravBreadth;
589
  opt |= FsTreeWalker::FtwTravBreadth;
548
  else if (op_flags & OPT_d)
590
    else if (op_flags & OPT_d)
549
      opt |= FsTreeWalker::FtwTravFilesThenDirs;
591
  opt |= FsTreeWalker::FtwTravFilesThenDirs;
550
  else if (op_flags & OPT_m)
592
    else if (op_flags & OPT_m)
551
      opt |= FsTreeWalker::FtwTravBreadthThenDepth;
593
  opt |= FsTreeWalker::FtwTravBreadthThenDepth;
552
594
553
  string reason;
595
    string reason;
554
  if (!recollinit(0, 0, reason)) {
596
    if (!recollinit(0, 0, reason)) {
555
      fprintf(stderr, "Init failed: %s\n", reason.c_str());
597
  fprintf(stderr, "Init failed: %s\n", reason.c_str());
556
      exit(1);
598
  exit(1);
557
  }
599
    }
558
  if (op_flags & OPT_w) {
600
    if (op_flags & OPT_w) {
559
      FsTreeWalker::setNoFnmPathname();
601
  FsTreeWalker::setNoFnmPathname();
560
  }
602
    }
561
  FsTreeWalker walker(opt);
603
    FsTreeWalker walker;
604
    walker.setOpts(opt); 
605
    walker.setMaxDepth(maxdepth);
562
  walker.setSkippedNames(patterns);
606
    walker.setSkippedNames(patterns);
563
  walker.setSkippedPaths(paths);
607
    walker.setSkippedPaths(paths);
564
  myCB cb;
608
    myCB cb;
565
  walker.walk(topdir, cb);
609
    walker.walk(topdir, cb);
566
  if (walker.getErrCnt() > 0)
610
    if (walker.getErrCnt() > 0)
567
      cout << walker.getReason();
611
  cout << walker.getReason();
568
}
612
}
569
613
570
#endif // TEST_FSTREEWALK
614
#endif // TEST_FSTREEWALK