[fbl][unique_fd] Add duplicate call.

This is a fairly common lifecycle management operation.

Tested: runtests -t fbl-test
Change-Id: I0ea7cfb81f1df1d338b4aa66f97f4fd71c260adc
diff --git a/system/ulib/fbl/include/fbl/unique_fd.h b/system/ulib/fbl/include/fbl/unique_fd.h
index b439941..d9e5b77 100644
--- a/system/ulib/fbl/include/fbl/unique_fd.h
+++ b/system/ulib/fbl/include/fbl/unique_fd.h
@@ -42,6 +42,10 @@
     // move semantics only
     DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(unique_fd);
 
+    fbl::unique_fd duplicate() {
+        return fbl::unique_fd(dup(fd_));
+    }
+
     int release() {
         int t = fd_;
         fd_ = InvalidValue();
diff --git a/system/utest/fbl/unique_fd_tests.cpp b/system/utest/fbl/unique_fd_tests.cpp
index 42c6c0e..27d81a9 100644
--- a/system/utest/fbl/unique_fd_tests.cpp
+++ b/system/utest/fbl/unique_fd_tests.cpp
@@ -191,6 +191,28 @@
     END_TEST;
 }
 
+bool duplicate_test() {
+    BEGIN_TEST;
+    int pipes[2];
+    EXPECT_EQ(pipe(pipes), 0);
+
+    fbl::unique_fd in(pipes[1]);
+    fbl::unique_fd out(pipes[0]);
+    EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
+    {
+        fbl::unique_fd in2 = in.duplicate();
+        fbl::unique_fd out2 = out.duplicate();
+        EXPECT_TRUE(verify_pipes_open(in2.get(), out2.get()));
+
+        EXPECT_TRUE(verify_pipes_open(in2.get(), out.get()));
+        EXPECT_TRUE(verify_pipes_open(in.get(), out2.get()));
+        EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
+    }
+    EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
+
+    END_TEST;
+}
+
 } // namespace
 
 BEGIN_TEST_CASE(unique_fd_tests)
@@ -200,4 +222,5 @@
 RUN_TEST(swap_test)
 RUN_TEST(move_test)
 RUN_TEST(reset_test)
+RUN_TEST(duplicate_test)
 END_TEST_CASE(unique_fd_tests)