{
return mkdir(directoryName, pg_dir_create_mode);
}
+
+/*
+ * Send data over a unix domain socket, optionally (when fd != -1) including a
+ * file descriptor.
+ */
+ssize_t
+pg_uds_send_with_fd(int sock, void *buf, ssize_t buflen, int fd)
+{
+ ssize_t size;
+ struct msghdr msg = {0};
+ struct iovec iov;
+ /* cmsg header, union for correct alignment */
+ union
+ {
+ struct cmsghdr cmsghdr;
+ char control[CMSG_SPACE(sizeof (int))];
+ } cmsgu;
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (fd >= 0)
+ {
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof (int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ *((int *) CMSG_DATA(cmsg)) = fd;
+ }
+
+ size = sendmsg(sock, &msg, 0);
+
+ /* errors are returned directly */
+ return size;
+}
+
+/*
+ * Receive data from a unix domain socket. If a file is sent over the socket,
+ * store it in *fd.
+ */
+ssize_t
+pg_uds_recv_with_fd(int sock, void *buf, ssize_t bufsize, int *fd)
+{
+ ssize_t size;
+ struct msghdr msg;
+ struct iovec iov;
+ /* cmsg header, union for correct alignment */
+ union
+ {
+ struct cmsghdr cmsghdr;
+ char control[CMSG_SPACE(sizeof (int))];
+ } cmsgu;
+ struct cmsghdr *cmsg;
+
+ Assert(fd != NULL);
+
+ iov.iov_base = buf;
+ iov.iov_len = bufsize;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
+
+ size = recvmsg (sock, &msg, 0);
+
+ if (size < 0)
+ {
+ *fd = -1;
+ return size;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ elog(FATAL, "unexpected cmsg_level");
+
+ if (cmsg->cmsg_type != SCM_RIGHTS)
+ elog(FATAL, "unexpected cmsg_type");
+
+ *fd = *((int *) CMSG_DATA(cmsg));
+
+ /* FIXME: check / handle additional cmsg structures */
+ }
+ else
+ *fd = -1;
+
+ return size;
+}
#define PG_TEMP_FILES_DIR "pgsql_tmp"
#define PG_TEMP_FILE_PREFIX "pgsql_tmp"
+/* XXX; This should probably go elsewhere */
+ssize_t pg_uds_send_with_fd(int sock, void *buf, ssize_t buflen, int fd);
+ssize_t pg_uds_recv_with_fd(int sock, void *buf, ssize_t bufsize, int *fd);
+
#endif /* FD_H */