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);
 }
 
