/*
 * SCM_RIGHTS with unix socket help program for test
 *
 * Copyright IBM, Inc. 2013
 *
 * Authors:
 *  Wenchao Xia    <xiawenc@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 * See the COPYING.LIB file in the top-level directory.
 */

#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/* #define SOCKET_SCM_DEBUG */

/*
 * @fd and @fd_to_send will not be checked for validation in this function,
 * a blank will be sent as iov data to notify qemu.
 */
static int send_fd(int fd, int fd_to_send)
{
    struct msghdr msg;
    struct iovec iov[1];
    int ret;
    char control[CMSG_SPACE(sizeof(int))];
    struct cmsghdr *cmsg;

    memset(&msg, 0, sizeof(msg));
    memset(control, 0, sizeof(control));

    /* Send a blank to notify qemu */
    iov[0].iov_base = (void *)" ";
    iov[0].iov_len = 1;

    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    msg.msg_control = control;
    msg.msg_controllen = sizeof(control);

    cmsg = CMSG_FIRSTHDR(&msg);

    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    memcpy(CMSG_DATA(cmsg), &fd_to_send, sizeof(int));

    do {
        ret = sendmsg(fd, &msg, 0);
    } while (ret < 0 && errno == EINTR);

    if (ret < 0) {
        fprintf(stderr, "Failed to send msg, reason: %s\n", strerror(errno));
    }

    return ret;
}

/* Convert string to fd number. */
static int get_fd_num(const char *fd_str)
{
    int sock;
    char *err;

    errno = 0;
    sock = strtol(fd_str, &err, 10);
    if (errno) {
        fprintf(stderr, "Failed in strtol for socket fd, reason: %s\n",
                strerror(errno));
        return -1;
    }
    if (!*fd_str || *err || sock < 0) {
        fprintf(stderr, "bad numerical value for socket fd '%s'\n", fd_str);
        return -1;
    }

    return sock;
}

/*
 * To make things simple, the caller needs to specify:
 * 1. socket fd.
 * 2. path of the file to be sent.
 */
int main(int argc, char **argv, char **envp)
{
    int sock, fd, ret;

#ifdef SOCKET_SCM_DEBUG
    int i;
    for (i = 0; i < argc; i++) {
        fprintf(stderr, "Parameter %d: %s\n", i, argv[i]);
    }
#endif

    if (argc != 3) {
        fprintf(stderr,
                "Usage: %s < socket-fd > < file-path >\n",
                argv[0]);
        return EXIT_FAILURE;
    }


    sock = get_fd_num(argv[1]);
    if (sock < 0) {
        return EXIT_FAILURE;
    }

    /* Now only open a file in readonly mode for test purpose. If more precise
       control is needed, use python script in file operation, which is
       supposed to fork and exec this program. */
    fd = open(argv[2], O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "Failed to open file '%s'\n", argv[2]);
        return EXIT_FAILURE;
    }

    ret = send_fd(sock, fd);
    if (ret < 0) {
        close(fd);
        return EXIT_FAILURE;
    }

    close(fd);
    return EXIT_SUCCESS;
}
