/* Helper to give local IO capabilities to a target.
Copyright (C) 2023-2024 Free Software Foundation, Inc.
Copyright (C) 2023-2024 Advanced Micro Devices, Inc. All rights reserved.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include "local-fileio-target.h"
#include "gdbsupport/fileio.h"
#include "gdbsupport/filestuff.h"
/* See local-fileio-target.h. */
int
local_fileio_open (struct inferior *inf, const char *filename, int flags,
int mode, int warn_if_slow, fileio_error *target_errno)
{
int nat_flags;
mode_t nat_mode;
int fd;
if (fileio_to_host_openflags (flags, &nat_flags) == -1
|| fileio_to_host_mode (mode, &nat_mode) == -1)
{
*target_errno = FILEIO_EINVAL;
return -1;
}
fd = gdb_open_cloexec (filename, nat_flags, nat_mode).release ();
if (fd == -1)
*target_errno = host_to_fileio_error (errno);
return fd;
}
/* See local-fileio-target.h. */
int
local_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, fileio_error *target_errno)
{
int ret;
#ifdef HAVE_PWRITE
ret = pwrite (fd, write_buf, len, (long) offset);
#else
ret = -1;
#endif
/* If we have no pwrite or it failed for this file, use lseek/write. */
if (ret == -1)
{
ret = lseek (fd, (long) offset, SEEK_SET);
if (ret != -1)
ret = write (fd, write_buf, len);
}
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
return ret;
}
/* See local-fileio-target.h. */
int
local_fileio_pread (int fd, gdb_byte *read_buf, int len, ULONGEST offset,
fileio_error *target_errno)
{
int ret;
#ifdef HAVE_PREAD
ret = pread (fd, read_buf, len, (long) offset);
#else
ret = -1;
#endif
/* If we have no pread or it failed for this file, use lseek/read. */
if (ret == -1)
{
ret = lseek (fd, (long) offset, SEEK_SET);
if (ret != -1)
ret = read (fd, read_buf, len);
}
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
return ret;
}
/* See local-fileio-target.h. */
int
local_fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno)
{
int ret;
ret = fstat (fd, sb);
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
return ret;
}
/* See local-fileio-target.h. */
int
local_fileio_stat (inferior *inf, const char *filename, struct stat *sb,
fileio_error *target_errno)
{
int ret;
ret = lstat (filename, sb);
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
return ret;
}
/* See local-fileio-target.h. */
int
local_fileio_close (int fd, fileio_error *target_errno)
{
int ret;
ret = ::close (fd);
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
return ret;
}
/* See local-fileio-target.h. */
int
local_fileio_unlink (struct inferior *inf, const char *filename,
fileio_error *target_errno)
{
int ret;
ret = unlink (filename);
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
return ret;
}
/* See local-fileio-target.h. */
std::optional
local_fileio_readlink (struct inferior *inf, const char *filename,
fileio_error *target_errno)
{
/* We support readlink only on systems that also provide a compile-time
maximum path length (PATH_MAX), at least for now. */
#if defined (PATH_MAX)
char buf[PATH_MAX];
int len;
len = readlink (filename, buf, sizeof buf);
if (len < 0)
{
*target_errno = host_to_fileio_error (errno);
return {};
}
return std::string (buf, len);
#else
*target_errno = FILEIO_ENOSYS;
return {};
#endif
}