blob: 74f47176c58d790dc919af0dd18ec675c6b2be54 [file] [log] [blame]
// Copyright 2016 The Chromium OS 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 "broker_client.h"
#include <errno.h>
#include <limits.h> // PATH_MAX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
// Keep sending data until |len| data is sent. If partial data sent, return -1.
int SendAll(int sockfd, const void* buf, int len, int flags) {
int sent = 0;
while (sent < len) {
int rc = send(sockfd, buf+sent, len-sent, flags);
if (rc < 0 && errno != EINTR)
return -1;
sent += len;
}
return sent;
}
int ConnectToBroker(const char *sockname, int socknamelen) {
struct sockaddr_un addr = {0};
int maxpath = sizeof(addr.sun_path);
int pathlen = socknamelen;
if (pathlen >= maxpath) {
errno = EINVAL;
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, sockname, socknamelen);
int s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0)
return -1;
socklen_t addrlen = pathlen + sizeof(addr.sun_family);
if (connect(s, (struct sockaddr*)&addr, addrlen) < 0)
return -1;
return s;
}
int OpenWithPermissions(int sockfd, const char* path) {
ssize_t rc = SendAll(sockfd, path, strlen(path) + 1, 0);
if (rc < 0)
return -1;
struct iovec iov = {0};
char msg_buf[PATH_MAX];
iov.iov_base = msg_buf;
iov.iov_len = sizeof(msg_buf);
struct msghdr msg = {0};
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
char control_buf[PATH_MAX];
msg.msg_control = control_buf;
msg.msg_controllen = sizeof(control_buf);
rc = recvmsg(sockfd, &msg, 0);
if (rc < 0)
return -1;
int fd;
if (msg.msg_controllen == 0) {
fd = -1;
} else {
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
int* recv_cmsg = (int *) CMSG_DATA(cmsg);
fd = recv_cmsg[0];
}
return fd;
}