1/*
2 * Copyright 2007-2008, Ingo Weinhold, bonefish@cs.tu-berlin.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "compatibility.h"
7
8#include "fssh_uio.h"
9
10#if defined(HAIKU_HOST_PLATFORM_FREEBSD)
11#include <unistd.h>
12#endif
13
14#include <new>
15
16#include <errno.h>
17#include <sys/uio.h>
18
19#include "partition_support.h"
20
21#if (!defined(__BEOS__) && !defined(__HAIKU__))
22	// Defined in libroot_build.so.
23#	define _kern_readv	_kernbuild_readv
24#	define _kern_writev	_kernbuild_writev
25	extern "C" ssize_t _kern_readv(int fd, off_t pos, const struct iovec *vecs, size_t count);
26	extern "C" ssize_t _kern_writev(int fd, off_t pos, const struct iovec *vecs, size_t count);
27#endif
28
29
30static const int kMaxIOVecs = 1024;
31
32
33bool
34prepare_iovecs(const struct fssh_iovec *vecs, int count,
35	struct iovec* systemVecs)
36{
37	if (count < 0 || count > kMaxIOVecs) {
38		errno = B_BAD_VALUE;
39		return false;
40	}
41
42	for (int i = 0; i < count; i++) {
43		systemVecs[i].iov_base = vecs[i].iov_base;
44		systemVecs[i].iov_len = vecs[i].iov_len;
45	}
46
47	return true;
48}
49
50
51fssh_ssize_t
52fssh_readv(int fd, const struct fssh_iovec *vector, int count)
53{
54	struct iovec systemVecs[kMaxIOVecs];
55	if (!prepare_iovecs(vector, count, systemVecs))
56		return -1;
57
58	fssh_off_t pos = -1;
59	fssh_size_t length = 0;
60	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
61		return -1;
62
63	#if !defined(HAIKU_HOST_PLATFORM_FREEBSD)
64		return readv(fd, systemVecs, count);
65	#else
66		return _kern_readv(fd, lseek(fd, 0, SEEK_CUR), systemVecs, count);
67	#endif
68}
69
70
71fssh_ssize_t
72fssh_readv_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, int count)
73{
74	struct iovec systemVecs[kMaxIOVecs];
75	if (!prepare_iovecs(vec, count, systemVecs))
76		return -1;
77
78	fssh_size_t length = 0;
79	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
80		return -1;
81
82#if defined(__HAIKU__)
83	return readv_pos(fd, pos, systemVecs, count);
84#else
85	return _kern_readv(fd, pos, systemVecs, count);
86#endif
87}
88
89
90fssh_ssize_t
91fssh_writev(int fd, const struct fssh_iovec *vector, int count)
92{
93	struct iovec systemVecs[kMaxIOVecs];
94	if (!prepare_iovecs(vector, count, systemVecs))
95		return -1;
96
97	fssh_off_t pos = -1;
98	fssh_size_t length = 0;
99	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
100		return -1;
101
102	#if !defined(HAIKU_HOST_PLATFORM_FREEBSD)
103		return writev(fd, systemVecs, count);
104	#else
105		return _kern_writev(fd, lseek(fd, 0, SEEK_CUR), systemVecs, count);
106	#endif
107}
108
109
110fssh_ssize_t
111fssh_writev_pos(int fd, fssh_off_t pos, const struct fssh_iovec *vec, int count)
112{
113	struct iovec systemVecs[kMaxIOVecs];
114	if (!prepare_iovecs(vec, count, systemVecs))
115		return -1;
116
117	fssh_size_t length = 0;
118	if (FSShell::restricted_file_restrict_io(fd, pos, length) < 0)
119		return -1;
120
121#if defined(__HAIKU__)
122	return writev_pos(fd, pos, systemVecs, count);
123#else
124	return _kern_writev(fd, pos, systemVecs, count);
125#endif
126}
127