1 /*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6 #include <io_requests.h>
7
8 #include "IORequest.h"
9
10
11 // #pragma mark - static helpers
12
13
14 static status_t
transfer_io_request_data(io_request * request,void * buffer,size_t size,bool writeToRequest)15 transfer_io_request_data(io_request* request, void* buffer, size_t size,
16 bool writeToRequest)
17 {
18 if (writeToRequest == request->IsWrite()
19 || request->RemainingBytes() < size) {
20 return B_BAD_VALUE;
21 }
22
23 // lock the request buffer memory, if it is user memory
24 IOBuffer* ioBuffer = request->Buffer();
25 if (ioBuffer->IsUser() && !ioBuffer->IsMemoryLocked()) {
26 status_t error = ioBuffer->LockMemory(request->TeamID(),
27 !writeToRequest);
28 if (error != B_OK)
29 return error;
30 }
31
32 // read/write
33 off_t offset = request->Offset() + request->TransferredBytes();
34 status_t error = writeToRequest
35 ? request->CopyData(buffer, offset, size)
36 : request->CopyData(offset, buffer, size);
37 if (error != B_OK)
38 return error;
39
40 request->Advance(size);
41 return B_OK;
42 }
43
44
45 // #pragma mark - public API
46
47
48 /*! Returns whether the given I/O request is a write request. */
49 bool
io_request_is_write(const io_request * request)50 io_request_is_write(const io_request* request)
51 {
52 return request->IsWrite();
53 }
54
55
56 /*! Returns whether the I/O request has VIP status. */
57 bool
io_request_is_vip(const io_request * request)58 io_request_is_vip(const io_request* request)
59 {
60 return (request->Flags() & B_VIP_IO_REQUEST) != 0;
61 }
62
63
64 /*! Returns the read/write offset of the given I/O request.
65 This is the immutable offset the request was created with;
66 read_from_io_request() and write_to_io_request() don't change it.
67 */
68 off_t
io_request_offset(const io_request * request)69 io_request_offset(const io_request* request)
70 {
71 return request->Offset();
72 }
73
74
75 /*! Returns the read/write length of the given I/O request.
76 This is the immutable length the request was created with;
77 read_from_io_request() and write_to_io_request() don't change it.
78 */
79 off_t
io_request_length(const io_request * request)80 io_request_length(const io_request* request)
81 {
82 return request->Length();
83 }
84
85
86 /*! Reads data from the given I/O request into the given buffer and advances
87 the request's transferred data pointer.
88 Multiple calls to read_from_io_request() are allowed, but the total size
89 must not exceed io_request_length(request).
90 */
91 status_t
read_from_io_request(io_request * request,void * buffer,size_t size)92 read_from_io_request(io_request* request, void* buffer, size_t size)
93 {
94 return transfer_io_request_data(request, buffer, size, false);
95 }
96
97
98 /*! Writes data from the given buffer to the given I/O request and advances
99 the request's transferred data pointer.
100 Multiple calls to write_to_io_request() are allowed, but the total size
101 must not exceed io_request_length(request).
102 */
103 status_t
write_to_io_request(io_request * request,const void * buffer,size_t size)104 write_to_io_request(io_request* request, const void* buffer, size_t size)
105 {
106 return transfer_io_request_data(request, (void*)buffer, size, true);
107 }
108
109
110 /*! Sets the given I/O request's status and notifies listeners that the request
111 is finished.
112 */
113 void
notify_io_request(io_request * request,status_t status)114 notify_io_request(io_request* request, status_t status)
115 {
116 request->SetStatusAndNotify(status);
117 }
118