diff -ru undo.old/undo.c undo/undo.c --- undo.old/undo.c 2009-03-22 18:45:42 +0000 +++ undo/undo.c 2009-03-22 18:33:21 +0000 @@ -70,6 +70,8 @@ #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); @@ -108,7 +110,7 @@ enum undo_type type; struct hammer_ioc_hist_entry ts1; struct hammer_ioc_hist_entry ts2; - int c; + int c, i; int flags; bzero(&ts1, sizeof(ts1)); @@ -116,8 +118,27 @@ cmd = CMD_DUMP; type = TYPE_FILE; + flags = 0; - while ((c = getopt(ac, av, "adDiuvo:t:")) != -1) { + i = -1; + while ((c = getopt(ac, av, "adDiuvo:t:0123456789")) != -1) { + if (c >= '0' && c <= '9') { + c -= '0'; + i = (i >= 0) ? i*10 + c : c; + continue; + } else if (i >= 0) INDEX_ARG: { + /* set placeholder IDs for later lookup */ + if (ts1.tid == 0 && !(flags & UNDO_FLAG_SETTID1)) + ts1.tid = i, flags |= UNDO_FLAG_SETTID1; + else if (ts2.tid == 0 && !(flags & UNDO_FLAG_SETTID2)) + ts2.tid = i, flags |= UNDO_FLAG_SETTID2; + else + usage(); + i = -1; + if (c == -1) + /* got here after loop */ + break; + } switch(c) { case 'd': if (type != TYPE_FILE) @@ -148,12 +169,12 @@ outFileName = optarg; break; case 't': - if (ts1.tid && ts2.tid) - usage(); - else if (ts1.tid == 0) + if (ts1.tid == 0 && !(flags & UNDO_FLAG_SETTID1)) ts1.tid = parse_delta_time(optarg); - else + else if (ts2.tid == 0 && !(flags & UNDO_FLAG_SETTID2)) ts2.tid = parse_delta_time(optarg); + else + usage(); break; default: usage(); @@ -161,6 +182,9 @@ break; } } + if (i >= 0) + /* last argument numerical index */ + goto INDEX_ARG; /* * Option validation @@ -172,7 +196,6 @@ ac -= optind; av += optind; - flags = 0; if (ac > 1) flags |= UNDO_FLAG_MULT; @@ -215,8 +238,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. @@ -258,15 +281,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) {