diff -ru /usr/src/usr.bin/undo/undo.c undo/undo.c --- /usr/src/usr.bin/undo/undo.c 2009-03-09 23:47:33 +0000 +++ undo/undo.c 2009-03-29 03:19:33 +0000 @@ -70,12 +70,15 @@ #define UNDO_FLAG_MULT 0x0001 #define UNDO_FLAG_INOCHG 0x0002 +#define UNDO_FLAG_SETTID1 0x0004 +#define UNDO_FLAG_SETTID2 0x0008 static int undo_hist_entry_compare(struct undo_hist_entry *he1, struct undo_hist_entry *he2); static void doiterate(const char *filename, const char *outFileName, const char *outFilePostfix, int flags, struct hammer_ioc_hist_entry ts1, + struct hammer_ioc_hist_entry ts2, enum undo_cmd cmd, enum undo_type type); static void dogenerate(const char *filename, const char *outFileName, const char *outFilePostfix, @@ -87,7 +90,8 @@ static void collect_dir_history(const char *filename, int *error, struct undo_hist_entry_rb_tree *dir_tree); static void clean_tree(struct undo_hist_entry_rb_tree *tree); -static hammer_tid_t parse_delta_time(const char *timeStr); +static hammer_tid_t parse_delta_time(const char *timeStr, int *flags, + int ind_flag); static void runcmd(int fd, const char *cmd, ...); static char *timestamp(hammer_ioc_hist_entry_t hen); static void usage(void); @@ -108,6 +112,7 @@ struct hammer_ioc_hist_entry ts1; struct hammer_ioc_hist_entry ts2; int c; + int count_t; int flags; bzero(&ts1, sizeof(ts1)); @@ -115,6 +120,8 @@ cmd = CMD_DUMP; type = TYPE_FILE; + count_t = 0; + flags = 0; while ((c = getopt(ac, av, "adDiuvo:t:")) != -1) { switch(c) { @@ -147,12 +154,15 @@ outFileName = optarg; break; case 't': - if (ts1.tid && ts2.tid) - usage(); - else if (ts1.tid == 0) - ts1.tid = parse_delta_time(optarg); + ++count_t; + if (count_t == 1) + ts1.tid = parse_delta_time(optarg, &flags, + UNDO_FLAG_SETTID1); + else if (count_t == 2) + ts2.tid = parse_delta_time(optarg, &flags, + UNDO_FLAG_SETTID2); else - ts2.tid = parse_delta_time(optarg); + usage(); break; default: usage(); @@ -171,7 +181,6 @@ ac -= optind; av += optind; - flags = 0; if (ac > 1) flags |= UNDO_FLAG_MULT; @@ -205,7 +214,7 @@ while (ac) { doiterate(*av, outFileName, outFilePostfix, - flags, ts1, cmd, type); + flags, ts1, ts2, cmd, type); ++av; --ac; } @@ -214,8 +223,8 @@ /* * Iterate through a file's history. If cmd == CMD_DUMP we take the - * next-to-last transaction id. Otherwise if cmd == CMD_ITERATEALL - * we scan all transaction ids. + * next-to-last transaction id, unless another given. Otherwise if + * cmd == CMD_ITERATEALL we scan all transaction ids. * * Also iterate through the directory's history to locate other inodes that * used the particular file name. @@ -225,13 +234,14 @@ doiterate(const char *filename, const char *outFileName, const char *outFilePostfix, int flags, struct hammer_ioc_hist_entry ts1, + struct hammer_ioc_hist_entry ts2, enum undo_cmd cmd, enum undo_type type) { struct undo_hist_entry_rb_tree dir_tree; struct undo_hist_entry_rb_tree tse_tree; struct undo_hist_entry *tse1; struct undo_hist_entry *tse2; - struct hammer_ioc_hist_entry ts2, tid_max; + struct hammer_ioc_hist_entry tid_max; char *path = NULL; int i; int fd; @@ -256,15 +266,40 @@ } } if (cmd == CMD_DUMP) { - /* - * Single entry, most recent prior to current - */ - if (ts1.tid == 0 && RB_EMPTY(&tse_tree)) { + if ((ts1.tid == 0 || + flags & (UNDO_FLAG_SETTID1|UNDO_FLAG_SETTID2)) && + RB_EMPTY(&tse_tree)) { if ((fd = open(filename, O_RDONLY)) > 0) { collect_history(fd, &error, &tse_tree); close(fd); } } + /* + * Find entry if tid set to placeholder index + */ + if (flags & UNDO_FLAG_SETTID1){ + tse1 = RB_MAX(undo_hist_entry_rb_tree, &tse_tree); + while (tse1 && ts1.tid--) + tse1 = RB_PREV(undo_hist_entry_rb_tree, + &tse_tree, tse1); + if (tse1) + ts1 = tse1->tse; + else + ts1.tid = 0; + } + if (flags & UNDO_FLAG_SETTID2){ + tse2 = RB_MAX(undo_hist_entry_rb_tree, &tse_tree); + while (tse2 && ts2.tid--) + tse2 = RB_PREV(undo_hist_entry_rb_tree, + &tse_tree, tse2); + if (tse2) + ts2 = tse2->tse; + else + ts2.tid = 0; + } + /* + * Single entry, most recent prior to current + */ if (ts1.tid == 0) { tse2 = RB_MAX(undo_hist_entry_rb_tree, &tse_tree); if (tse2) { @@ -582,11 +617,15 @@ static hammer_tid_t -parse_delta_time(const char *timeStr) +parse_delta_time(const char *timeStr, int *flags, int ind_flag) { hammer_tid_t tid; tid = strtoull(timeStr, NULL, 0); + if (timeStr[0] == '+') + ++timeStr; + if (timeStr[0] >= '0' && timeStr[0] <= '9' && timeStr[1] != 'x') + *flags |= ind_flag; return(tid); }