#include <fcntl.h>
#include <sys/disk.h>
#include <unistd.h>
+#include <stdlib.h>
+#include <sys/socket.h>
#endif
/**@brief Default filename.*/
static int file_dev_open(struct ext4_blockdev *bdev)
{
#ifdef __APPLE__
- /* The fseek/ftell approach to finding the device's size does not seem
- * to work on macOS so do it this way instead.
+ /* We need to use authopen to open the device. It asks the user for permission
+ * then give us an open fd over a socket.
*/
- int dev = open(fname, O_RDONLY);
- if (dev == -1) {
+
+ int pipe[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe) < 0) {
+ return EFAULT;
+ }
+
+ pid_t pid = fork();
+ if (pid < 0) {
+ return EFAULT;
+ }
+
+ if (pid == 0) {
+ close(pipe[0]);
+ dup2(pipe[1], STDOUT_FILENO);
+ execl("/usr/libexec/authopen", "/usr/libexec/authopen", "-stdoutpipe", "-w", "-a", fname, (char *) 0);
+ exit(-1);
+ }
+
+ close(pipe[1]);
+
+ int dev = -1;
+
+ size_t const data_buffer_size = sizeof(struct cmsghdr) + sizeof(int);
+ char data_buffer[data_buffer_size];
+
+ struct iovec io_vec[1];
+ io_vec[0].iov_base = data_buffer;
+ io_vec[0].iov_len = data_buffer_size;
+
+ socklen_t const cmsg_socket_size = CMSG_SPACE(sizeof(int));
+ char cmsg_socket[cmsg_socket_size];
+ struct msghdr message = { 0 };
+ message.msg_iov = io_vec;
+ message.msg_iovlen = 1;
+ message.msg_control = cmsg_socket;
+ message.msg_controllen = cmsg_socket_size;
+
+ if (recvmsg(pipe[0], &message, 0) <= 0) {
return EIO;
}
+ struct cmsghdr* cmsg_socket_header = CMSG_FIRSTHDR(&message);
+ if (cmsg_socket_header && cmsg_socket_header->cmsg_level == SOL_SOCKET && cmsg_socket_header->cmsg_type == SCM_RIGHTS) {
+ dev = *((int *) CMSG_DATA(cmsg_socket_header));
+ }
+
+ /* The fseek/ftell approach to finding the device's size does not seem
+ * to work on macOS so do it this way instead.
+ */
uint64_t sectors = 0;
if (ioctl(dev, DKIOCGETBLOCKCOUNT, §ors) < 0) {
close(dev);
}
off_t size = sectors * sector_size;
- close(dev);
-#endif
+ dev_file = fdopen(dev, "r+b");
+#else
dev_file = fopen(fname, "r+b");
+#endif
if (!dev_file)
return EIO;