[make-zxcrypt] Add a small utility to create zxcrypt volumes

This CL adds a command line utility, make-zxcrypt, that will create a
zxcrypt volume with a fixed GUID and a single FVM slice.  It's intended
to be used to debug the devcoord hang.  DO NOT COMMIT.

Change-Id: Ie11a5960ea4dd049fbb9675fbc71e3922c55e4de
diff --git a/system/uapp/make-zxcrypt/main.cpp b/system/uapp/make-zxcrypt/main.cpp
new file mode 100644
index 0000000..18496d0
--- /dev/null
+++ b/system/uapp/make-zxcrypt/main.cpp
@@ -0,0 +1,67 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include <fbl/unique_fd.h>
+#include <fs-management/fvm.h>
+#include <zircon/device/block.h>
+#include <zircon/status.h>
+#include <zircon/types.h>
+#include <zxcrypt/volume.h>
+
+constexpr uint8_t kDeadbeefGUID[GUID_LEN] = {
+    0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
+    0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef};
+
+// Quick and dirty hack to add a zxcrypt volume to debug devccord hang.
+int main(int argc, char** argv) {
+    if (argc != 2) {
+        fprintf(stderr, "error: wrong number of arguments\n");
+        fprintf(stderr, "usage: %s /path/to/some/fvm\n", argv[0]);
+        return -1;
+    }
+
+    fbl::unique_fd fd(open(argv[1], O_RDONLY));
+    if (!fd) {
+        fprintf(stderr, "error: failed to open '%s'\n", argv[1]);
+        return -1;
+    }
+
+    // Returns an open fd to the new partition on success, -1 on error.
+    alloc_req_t request;
+    request.slice_count = 1;
+    memcpy(request.type, kDeadbeefGUID, sizeof(request.type));
+    memcpy(request.guid, kDeadbeefGUID, sizeof(request.type));
+    snprintf(request.name, NAME_LEN, "deadbeef");
+    request.flags = 0;
+    if (fvm_allocate_partition(fd.get(), &request) < 0) {
+        fprintf(stderr, "warning: failed to allocate FVM partition\n");
+    }
+
+    char path[PATH_MAX];
+    fd.reset(open_partition(kDeadbeefGUID, kDeadbeefGUID, ZX_SEC(3), path));
+    if (!fd) {
+        fprintf(stderr, "error: failed to FVM partition\n");
+        return -1;
+    }
+
+    zx_status_t rc;
+    crypto::Secret key;
+    uint8_t* buf;
+    if ((rc = key.Allocate(zxcrypt::kZx1130KeyLen, &buf)) != ZX_OK) {
+        fprintf(stderr, "error: failed to allocate key: %s\n", zx_status_get_string(rc));
+        return -1;
+    }
+    memset(buf, 0, zxcrypt::kZx1130KeyLen);
+
+    if ((rc = zxcrypt::Volume::Create(fbl::move(fd), key)) != ZX_OK) {
+        fprintf(stderr, "error: failed to create zxcrypt volume: %s\n", zx_status_get_string(rc));
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/system/uapp/make-zxcrypt/rules.mk b/system/uapp/make-zxcrypt/rules.mk
new file mode 100644
index 0000000..c9956ce
--- /dev/null
+++ b/system/uapp/make-zxcrypt/rules.mk
@@ -0,0 +1,37 @@
+# Copyright 2017 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := userapp
+
+MODULE_NAME := make-zxcrypt
+
+MODULE_GROUP := core
+
+MODULE_SRCS := \
+    $(LOCAL_DIR)/main.cpp \
+
+MODULE_LIBS := \
+    system/ulib/c \
+    system/ulib/zircon \
+    system/ulib/fdio \
+    system/ulib/crypto \
+    system/ulib/fs-management \
+    system/ulib/zxcrypt \
+
+MODULE_STATIC_LIBS := \
+    third_party/ulib/cryptolib \
+    third_party/ulib/uboringssl \
+    system/ulib/ddk \
+    system/ulib/fvm \
+    system/ulib/fs \
+    system/ulib/sync \
+    system/ulib/zx \
+    system/ulib/zxcpp \
+    system/ulib/fbl \
+
+include make/module.mk
diff --git a/system/ulib/fdio/unistd.c b/system/ulib/fdio/unistd.c
index b5f9f45..ddc092d 100644
--- a/system/ulib/fdio/unistd.c
+++ b/system/ulib/fdio/unistd.c
@@ -24,6 +24,7 @@
 
 #include <zircon/assert.h>
 #include <zircon/compiler.h>
+#include <zircon/device/device.h>
 #include <zircon/device/vfs.h>
 #include <zircon/process.h>
 #include <zircon/processargs.h>
@@ -743,6 +744,14 @@
         return ZX_ERR_BAD_HANDLE;
     }
     ssize_t r = io->ops->ioctl(io, op, in_buf, in_len, out_buf, out_len);
+
+    if (r == ZX_ERR_TIMED_OUT) {
+        char path[PATH_MAX];
+        if (io->ops->ioctl(io, IOCTL_DEVICE_GET_TOPO_PATH, NULL, 0, path, PATH_MAX) >= 0) {
+            printf("FDIO ERROR: ioctl to %s timed out\n", path);
+        }
+    }
+
     fdio_release(io);
     return r;
 }