blob: 7dc4f26cf1f0bec2e4ab1f4b79b2c2c7e4944545 [file] [log] [blame] [edit]
/*
* Copyright © 2013 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2 or 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by:
* Alexandros Frantzis <alexandros.frantzis@canonical.com>
*/
#include "helpers.h"
#include "shared_library.h"
#include <boost/throw_exception.hpp>
#include <system_error>
#include <fcntl.h>
#include <linux/memfd.h>
#include <sys/syscall.h>
namespace
{
bool error_indicates_tmpfile_not_supported(int error)
{
return
error == EISDIR || // Directory exists, but no support for O_TMPFILE
error == ENOENT || // Directory doesn't exist, and no support for O_TMPFILE
error == EOPNOTSUPP || // Filesystem that directory resides on does not support O_TMPFILE
error == EINVAL; // There apparently exists at least one development board that has a kernel
// that incorrectly returns EINVAL. Yay.
}
int memfd_create(char const* name, unsigned int flags)
{
return static_cast<int>(syscall(SYS_memfd_create, name, flags));
}
}
int wlcs::helpers::create_anonymous_file(size_t size)
{
int fd = memfd_create("wlcs-unnamed", MFD_CLOEXEC);
if (fd == -1 && errno == ENOSYS)
{
fd = open("/dev/shm", O_TMPFILE | O_RDWR | O_EXCL | O_CLOEXEC, S_IRWXU);
// Workaround for filesystems that don't support O_TMPFILE
if (fd == -1 && error_indicates_tmpfile_not_supported(errno))
{
char template_filename[] = "/dev/shm/wlcs-buffer-XXXXXX";
fd = mkostemp(template_filename, O_CLOEXEC);
if (fd != -1)
{
if (unlink(template_filename) < 0)
{
close(fd);
fd = -1;
}
}
}
}
if (fd == -1)
{
BOOST_THROW_EXCEPTION(
std::system_error(errno, std::system_category(), "Failed to open temporary file"));
}
if (ftruncate(fd, size) == -1)
{
close(fd);
BOOST_THROW_EXCEPTION(
std::system_error(errno, std::system_category(), "Failed to resize temporary file"));
}
return fd;
}
namespace
{
static int argc;
static char const** argv;
std::shared_ptr<WlcsServerIntegration const> entry_point;
}
void wlcs::helpers::set_command_line(int argc, char const** argv)
{
::argc = argc;
::argv = argv;
}
int wlcs::helpers::get_argc()
{
return ::argc;
}
char const** wlcs::helpers::get_argv()
{
return ::argv;
}
void wlcs::helpers::set_entry_point(std::shared_ptr<WlcsServerIntegration const> const& entry_point)
{
::entry_point = entry_point;
}
std::shared_ptr<WlcsServerIntegration const> wlcs::helpers::get_test_hooks()
{
return ::entry_point;
}