diff options
Diffstat (limited to 'src/binlogsel.c')
-rw-r--r-- | src/binlogsel.c | 235 |
1 files changed, 223 insertions, 12 deletions
diff --git a/src/binlogsel.c b/src/binlogsel.c index 62299e5..8f1cfce 100644 --- a/src/binlogsel.c +++ b/src/binlogsel.c | |||
@@ -35,27 +35,32 @@ | |||
35 | #include "parse-datetime.h" | 35 | #include "parse-datetime.h" |
36 | 36 | ||
37 | char *timefmt = "%c"; | 37 | char *timefmt = "%c"; |
38 | int number_option; | 38 | int number_option; |
39 | int verbose_option; | 39 | int verbose_option; |
40 | int timediff_option; | 40 | int timediff_option; |
41 | char *directory; | ||
41 | char *pattern; | 42 | char *pattern; |
43 | enum binlog_index_type index_type = index_year; | ||
42 | 44 | ||
43 | #define FROM_TIME 0x01 | 45 | #define FROM_TIME 0x01 |
44 | #define TO_TIME 0x02 | 46 | #define TO_TIME 0x02 |
45 | int timemask; | 47 | int timemask; |
46 | time_t from_time, to_time; | 48 | time_t from_time, to_time; |
47 | 49 | ||
50 | static int matchnames(const char *dir, const char *pat, glob_t *gl); | ||
51 | void selglob(const char *dir, const char *pattern); | ||
52 | |||
48 | void | 53 | void |
49 | help() | 54 | help() |
50 | { | 55 | { |
51 | printf("usage: %s [-dhnv] [-t FORMAT] [-F FROMTIME] [-T TOTIME] [-p PATTERN] [-D DIR] [FILE...]\n", progname); | 56 | printf("usage: %s [-dhnv] [-t FORMAT] [-F FROMTIME] [-T TOTIME] [-p PATTERN] [-D DIR] [FILE...]\n", progname); |
52 | } | 57 | } |
53 | 58 | ||
54 | /* Convert strftime-like pattern into globbing pattern */ | 59 | /* Convert strftime-like pattern into globbing pattern */ |
55 | void | 60 | char * |
56 | convpattern(const char *dir) | 61 | convpattern(const char *dir) |
57 | { | 62 | { |
58 | char *p, *q; | 63 | char *p, *q; |
59 | char *newpat; | 64 | char *newpat; |
60 | size_t size = strlen(pattern) + 1; | 65 | size_t size = strlen(pattern) + 1; |
61 | 66 | ||
@@ -70,19 +75,20 @@ convpattern(const char *dir) | |||
70 | p += strlen(dir); | 75 | p += strlen(dir); |
71 | *p++ = '/'; | 76 | *p++ = '/'; |
72 | } | 77 | } |
73 | 78 | ||
74 | for (q = pattern; *q; ) { | 79 | for (q = pattern; *q; ) { |
75 | if (*q == '%') { | 80 | if (*q == '%') { |
81 | if (p > newpat && p[-1] != '*') | ||
76 | *p++ = '*'; | 82 | *p++ = '*'; |
77 | q += 2; | 83 | q += 2; |
78 | } else | 84 | } else |
79 | *p++ = *q++; | 85 | *p++ = *q++; |
80 | } | 86 | } |
81 | *p = 0; | 87 | *p = 0; |
82 | pattern = newpat; | 88 | return newpat; |
83 | } | 89 | } |
84 | 90 | ||
85 | #define getrec(base, recsize, n) \ | 91 | #define getrec(base, recsize, n) \ |
86 | ((struct binlog_record*)((char *)(base) + (n) * (recsize))) | 92 | ((struct binlog_record*)((char *)(base) + (n) * (recsize))) |
87 | 93 | ||
88 | int | 94 | int |
@@ -330,19 +336,217 @@ void | |||
330 | selfilelist(char **argv) | 336 | selfilelist(char **argv) |
331 | { | 337 | { |
332 | for (;*argv;++argv) | 338 | for (;*argv;++argv) |
333 | selfile(*argv); | 339 | selfile(*argv); |
334 | } | 340 | } |
335 | 341 | ||
342 | static char * | ||
343 | mkfilename(const char *dir, const char *file) | ||
344 | { | ||
345 | size_t dirlen, size; | ||
346 | char *ret; | ||
347 | |||
348 | dirlen = strlen(dir); | ||
349 | while (dirlen > 0 && dir[dirlen-1] == '/') | ||
350 | --dirlen; | ||
351 | size = dirlen + 1 + strlen(file) + 1; | ||
352 | ret = xmalloc(size); | ||
353 | memcpy(ret, dir, dirlen); | ||
354 | ret[dirlen++] = '/'; | ||
355 | strcpy(ret + dirlen, file); | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | int | ||
360 | filename_to_int(char *name) | ||
361 | { | ||
362 | char *p = strrchr(name, '/'); | ||
363 | if (!p) | ||
364 | abort(); | ||
365 | return atoi(p + 1); | ||
366 | } | ||
367 | |||
368 | void | ||
369 | selidx_day(const char *dir) | ||
370 | { | ||
371 | int from_day, to_day; | ||
372 | struct tm *tm; | ||
373 | glob_t gl; | ||
374 | int glinit = 0; | ||
375 | char *dirbuf; | ||
376 | size_t dirlen; | ||
377 | |||
378 | if (index_type == index_month) { | ||
379 | selglob(dir, BINLOG_GLOB_PATTERN); | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | if (timemask & FROM_TIME) | ||
384 | from_day = gmtime(&from_time)->tm_mday; | ||
385 | else { | ||
386 | glinit = matchnames(dir, "[0-9][0-9]", &gl); | ||
387 | if (glinit) | ||
388 | from_day = filename_to_int(gl.gl_pathv[0]); | ||
389 | else { | ||
390 | error("no matching files"); | ||
391 | exit(1); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (timemask & TO_TIME) | ||
396 | to_day = gmtime(&to_time)->tm_mday; | ||
397 | else { | ||
398 | if (!glinit) { | ||
399 | glinit = matchnames(dir, "[0-9][0-9]", &gl); | ||
400 | if (!glinit) { | ||
401 | error("no matching files"); | ||
402 | exit(1); | ||
403 | } | ||
404 | } | ||
405 | to_day = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]); | ||
406 | } | ||
407 | |||
408 | dirlen = strlen(dir) + 4; | ||
409 | dirbuf = xmalloc(dirlen); | ||
410 | for (;from_day <= to_day; from_day++) { | ||
411 | snprintf(dirbuf, dirlen, "%s/%02d", dir, from_day); | ||
412 | selglob(dirbuf, BINLOG_GLOB_PATTERN); | ||
413 | } | ||
414 | free(dirbuf); | ||
415 | if (glinit) | ||
416 | globfree(&gl); | ||
417 | } | ||
418 | |||
419 | void | ||
420 | selidx_month(const char *dir) | ||
421 | { | ||
422 | int from_month, to_month; | ||
423 | struct tm *tm; | ||
424 | glob_t gl; | ||
425 | int glinit = 0; | ||
426 | char *dirbuf; | ||
427 | size_t dirlen; | ||
428 | |||
429 | if (index_type == index_year) { | ||
430 | selglob(dir, BINLOG_GLOB_PATTERN); | ||
431 | return; | ||
432 | } | ||
433 | |||
434 | if (timemask & FROM_TIME) | ||
435 | from_month = 1 + gmtime(&from_time)->tm_mon; | ||
436 | else { | ||
437 | glinit = matchnames(dir, "[0-9][0-9]", &gl); | ||
438 | if (glinit) | ||
439 | from_month = filename_to_int(gl.gl_pathv[0]); | ||
440 | else { | ||
441 | error("no matching files"); | ||
442 | exit(1); | ||
443 | } | ||
444 | } | ||
445 | |||
446 | if (timemask & TO_TIME) | ||
447 | to_month = 1 + gmtime(&to_time)->tm_mon; | ||
448 | else { | ||
449 | if (!glinit) { | ||
450 | glinit = matchnames(dir, "[0-9][0-9]", &gl); | ||
451 | if (!glinit) { | ||
452 | error("no matching files"); | ||
453 | exit(1); | ||
454 | } | ||
455 | } | ||
456 | to_month = filename_to_int(gl.gl_pathv[gl.gl_pathc - 1]); | ||
457 | } | ||
458 | |||
459 | dirlen = strlen(dir) + 4; | ||
460 | dirbuf = xmalloc(dirlen); | ||
461 | for (;from_month <= to_month; from_month++) { | ||
462 | snprintf(dirbuf, dirlen, "%s/%02d", dir, from_month); | ||
463 | selidx_day(dirbuf); | ||
464 | } | ||
465 | free(dirbuf); | ||
466 | if (glinit) | ||
467 | globfree(&gl); | ||
468 | } | ||
469 | |||
470 | void | ||
471 | selidx_year(const char *dir) | ||
472 | { | ||
473 | int from_year, to_year; | ||
474 | struct tm *tm; | ||
475 | glob_t gl; | ||
476 | int glinit = 0; | ||
477 | char *dirbuf; | ||
478 | size_t dirlen; | ||
479 | |||
480 | if (timemask & FROM_TIME) | ||
481 | from_year = 1900 + gmtime(&from_time)->tm_year; | ||
482 | else { | ||
483 | glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl); | ||
484 | if (glinit) | ||
485 | from_year = filename_to_int(gl.gl_pathv[0]); | ||
486 | else { | ||
487 | error("no matching files"); | ||
488 | exit(1); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | if (timemask & TO_TIME) | ||
493 | to_year = 1900 + gmtime(&to_time)->tm_year; | ||
494 | else { | ||
495 | if (!glinit) { | ||
496 | glinit = matchnames(dir, "[0-9][0-9][0-9][0-9]", &gl); | ||
497 | if (!glinit) { | ||