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) {
