1a38a92c9SIngo Weinhold/*
23e617040SIngo Weinhold * Copyright 2007-2008, Ingo Weinhold, bonefish@cs.tu-berlin.de.
3a38a92c9SIngo Weinhold * Distributed under the terms of the MIT License.
4a38a92c9SIngo Weinhold */
5a38a92c9SIngo Weinhold
6c3c6ad0aSIngo Weinhold#include "compatibility.h"
7a38a92c9SIngo Weinhold
8a38a92c9SIngo Weinhold#include "fssh_uio.h"
9a38a92c9SIngo Weinhold
10aa9d957dSRene Gollent#if defined(HAIKU_HOST_PLATFORM_FREEBSD)
11585080d7SRene Gollent#include <unistd.h>
12aa9d957dSRene Gollent#endif
13aa9d957dSRene Gollent
14a38a92c9SIngo Weinhold#include <new>
15a38a92c9SIngo Weinhold
16a38a92c9SIngo Weinhold#include <errno.h>
17a38a92c9SIngo Weinhold#include <sys/uio.h>
18a38a92c9SIngo Weinhold
193e617040SIngo Weinhold#include "partition_support.h"
203e617040SIngo Weinhold
21a38a92c9SIngo Weinhold
22a38a92c9SIngo Weinholdstatic const fssh_size_t kMaxIOVecs = 1024;
23a38a92c9SIngo Weinhold
24a38a92c9SIngo Weinhold
25a38a92c9SIngo Weinholdbool
26a38a92c9SIngo Weinholdprepare_iovecs(const struct fssh_iovec *vecs, fssh_size_t count,
27a38a92c9SIngo Weinhold	struct iovec* systemVecs)
28a38a92c9SIngo Weinhold{
29a38a92c9SIngo Weinhold	if (count > kMaxIOVecs) {
30a38a92c9SIngo Weinhold		errno = B_BAD_VALUE;
31a38a92c9SIngo Weinhold		return false;
32a38a92c9SIngo Weinhold	}
33a38a92c9SIngo Weinhold
34a38a92c9SIngo Weinhold	for (fssh_size_t i = 0; i < count; i++) {
35a38a92c9SIngo Weinhold		systemVecs[i].iov_base = vecs[i].iov_base;
36a38a92c9SIngo Weinhold		systemVecs[i].iov_len = vecs[i].iov_len;
37a38a92c9SIngo Weinhold	}
38a38a92c9SIngo Weinhold
39a38a92c9SIngo Weinhold	return true;
40a38a92c9SIngo Weinhold}
41a38a92c9SIngo Weinhold
42a38a92c9SIngo Weinhold
43a38a92c9SIngo Weinholdfssh_ssize_t
44a38a92c9SIngo Weinholdfssh_readv(int fd, const struct fssh_iovec *vector, fssh_size_t count)
45a38a92c9SIngo Weinhold{
46a38a92c9SIngo Weinhold	struct iovec systemVecs[kMaxIOVecs];
47a38a92c9SIngo Weinhold	if (!prepare_iovecs(vector, count, systemVecs))
48a38a92c9SIngo Weinhold		return -1;
49a38a92c9SIngo Weinhold
503e617040SIngo Weinhold	fssh_off_t pos = -1;
513e617040SIngo Weinhold	fssh_size_t length = 0;
523e617040SIngo Weinhold	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
533e617040SIngo Weinhold		return -1;
543e617040SIngo Weinhold
5580b2da5eSIngo Weinhold	#if !defined(HAIKU_HOST_PLATFORM_FREEBSD)
5680b2da5eSIngo Weinhold		return readv(fd, systemVecs, count);
5780b2da5eSIngo Weinhold	#else
58585080d7SRene Gollent		return readv_pos(fd, lseek(fd, 0, SEEK_CUR), systemVecs, count);
5980b2da5eSIngo Weinhold	#endif
60a38a92c9SIngo Weinhold}
61a38a92c9SIngo Weinhold
62a38a92c9SIngo Weinhold
63a38a92c9SIngo Weinholdfssh_ssize_t
64a38a92c9SIngo Weinholdfssh_readv_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec,
65a38a92c9SIngo Weinhold	fssh_size_t count)
66a38a92c9SIngo Weinhold{
67a38a92c9SIngo Weinhold	struct iovec systemVecs[kMaxIOVecs];
68a38a92c9SIngo Weinhold	if (!prepare_iovecs(vec, count, systemVecs))
69a38a92c9SIngo Weinhold		return -1;
70a38a92c9SIngo Weinhold
713e617040SIngo Weinhold	fssh_size_t length = 0;
723e617040SIngo Weinhold	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
733e617040SIngo Weinhold		return -1;
743e617040SIngo Weinhold
75a38a92c9SIngo Weinhold	return readv_pos(fd, pos, systemVecs, count);
76a38a92c9SIngo Weinhold}
77a38a92c9SIngo Weinhold
78a38a92c9SIngo Weinhold
79a38a92c9SIngo Weinholdfssh_ssize_t
80a38a92c9SIngo Weinholdfssh_writev(int fd, const struct fssh_iovec *vector, fssh_size_t count)
81a38a92c9SIngo Weinhold{
82a38a92c9SIngo Weinhold	struct iovec systemVecs[kMaxIOVecs];
83a38a92c9SIngo Weinhold	if (!prepare_iovecs(vector, count, systemVecs))
84a38a92c9SIngo Weinhold		return -1;
85a38a92c9SIngo Weinhold
863e617040SIngo Weinhold	fssh_off_t pos = -1;
873e617040SIngo Weinhold	fssh_size_t length = 0;
883e617040SIngo Weinhold	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
893e617040SIngo Weinhold		return -1;
903e617040SIngo Weinhold
9180b2da5eSIngo Weinhold	#if !defined(HAIKU_HOST_PLATFORM_FREEBSD)
9280b2da5eSIngo Weinhold		return writev(fd, systemVecs, count);
9380b2da5eSIngo Weinhold	#else
94585080d7SRene Gollent		return writev_pos(fd, lseek(fd, 0, SEEK_CUR), systemVecs, count);
9580b2da5eSIngo Weinhold	#endif
96a38a92c9SIngo Weinhold}
97a38a92c9SIngo Weinhold
98a38a92c9SIngo Weinhold
99a38a92c9SIngo Weinholdfssh_ssize_t
100a38a92c9SIngo Weinholdfssh_writev_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec,
101a38a92c9SIngo Weinhold				fssh_size_t count)
102a38a92c9SIngo Weinhold{
103a38a92c9SIngo Weinhold	struct iovec systemVecs[kMaxIOVecs];
104a38a92c9SIngo Weinhold	if (!prepare_iovecs(vec, count, systemVecs))
105a38a92c9SIngo Weinhold		return -1;
106a38a92c9SIngo Weinhold
1073e617040SIngo Weinhold	fssh_size_t length = 0;
1083e617040SIngo Weinhold	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
1093e617040SIngo Weinhold		return -1;
1103e617040SIngo Weinhold
111a38a92c9SIngo Weinhold	return writev_pos(fd, pos, systemVecs, count);
112a38a92c9SIngo Weinhold}
113