diff options
| author | Carl Hetherington <cth@carlh.net> | 2020-04-05 00:24:32 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2020-04-05 01:38:29 +0200 |
| commit | 10f7a6720fe6e3f6717620c144f412b46de3024d (patch) | |
| tree | 7443392028498811dd44c860a23970e8d1d36948 | |
| parent | 5ea0fcac300574f0d5dfc69cb1cc64f35119f5d2 (diff) | |
Use authopen to acquire permissions to write to drives on macOS.
| -rw-r--r-- | blockdev/linux/file_dev.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/blockdev/linux/file_dev.c b/blockdev/linux/file_dev.c index ef44028..2797248 100644 --- a/blockdev/linux/file_dev.c +++ b/blockdev/linux/file_dev.c @@ -39,6 +39,8 @@ #include <fcntl.h> #include <sys/disk.h> #include <unistd.h> +#include <stdlib.h> +#include <sys/socket.h> #endif /**@brief Default filename.*/ @@ -68,14 +70,58 @@ EXT4_BLOCKDEV_STATIC_INSTANCE(file_dev, EXT4_FILEDEV_BSIZE, 0, file_dev_open, 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); @@ -88,10 +134,11 @@ static int file_dev_open(struct ext4_blockdev *bdev) } 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; |
