1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include <errno.h>
8 :
9 : /*
10 : * Native Client Generic I/O backend using seekless operations on
11 : * POSIXesque file descriptors. This is immune to whether the file
12 : * descriptor is shared among multiple processes that might be moving
13 : * its file offset independently.
14 : */
15 :
16 : #include "native_client/src/include/portability.h"
17 : #include "native_client/src/include/portability_io.h"
18 : #include "native_client/src/shared/gio/gio.h"
19 :
20 :
21 : static const struct GioVtbl kGioPioVtbl = {
22 : GioPioDtor,
23 : GioPioRead,
24 : GioPioWrite,
25 : GioPioSeek,
26 : GioPioFlush,
27 : GioPioClose,
28 : };
29 :
30 :
31 1 : int GioPioCtor(struct GioPio *self, int fd) {
32 1 : self->fd = fd;
33 1 : self->pos = 0;
34 1 : self->base.vtbl = &kGioPioVtbl;
35 1 : return 1;
36 1 : }
37 :
38 : #if NACL_WINDOWS
39 1 : static HANDLE GioPioWinSetup(struct GioPio *self, OVERLAPPED *ov) {
40 1 : ov->Offset = self->pos;
41 1 : ov->OffsetHigh = 0;
42 1 : ov->hEvent = 0;
43 1 : return (HANDLE) _get_osfhandle(self->fd);
44 1 : }
45 : #endif
46 :
47 1 : ssize_t GioPioRead(struct Gio *vself, void *buf, size_t count) {
48 1 : struct GioPio *self = (struct GioPio *) vself;
49 : ssize_t ret;
50 :
51 : #if NACL_WINDOWS
52 : OVERLAPPED ov;
53 : DWORD nread;
54 1 : HANDLE fh = GioPioWinSetup(self, &ov);
55 1 : if (ReadFile(fh, buf, (DWORD) count, &nread, &ov)) {
56 1 : ret = nread;
57 1 : } else if (GetLastError() == ERROR_HANDLE_EOF) {
58 1 : ret = 0;
59 1 : } else {
60 0 : errno = EIO;
61 0 : ret = -1;
62 : }
63 : #else
64 : ret = pread(self->fd, buf, count, self->pos);
65 : #endif
66 :
67 1 : if (ret > 0)
68 1 : self->pos += (off_t) ret;
69 :
70 1 : return ret;
71 1 : }
72 :
73 :
74 1 : ssize_t GioPioWrite(struct Gio *vself, const void *buf, size_t count) {
75 1 : struct GioPio *self = (struct GioPio *) vself;
76 : ssize_t ret;
77 :
78 : #if NACL_WINDOWS
79 : OVERLAPPED ov;
80 : DWORD nread;
81 1 : HANDLE fh = GioPioWinSetup(self, &ov);
82 1 : if (WriteFile(fh, buf, (DWORD) count, &nread, &ov)) {
83 1 : ret = nread;
84 1 : } else {
85 0 : errno = EIO;
86 0 : ret = -1;
87 : }
88 : #else
89 : ret = pwrite(self->fd, buf, count, self->pos);
90 : #endif
91 :
92 1 : if (ret > 0)
93 1 : self->pos += (off_t) ret;
94 :
95 1 : return ret;
96 1 : }
97 :
98 :
99 1 : off_t GioPioSeek(struct Gio *vself, off_t offset, int whence) {
100 1 : struct GioPio *self = (struct GioPio *) vself;
101 :
102 1 : switch (whence) {
103 : case SEEK_SET:
104 1 : break;
105 : case SEEK_CUR:
106 1 : offset += self->pos;
107 1 : break;
108 : case SEEK_END:
109 1 : offset = lseek(self->fd, offset, SEEK_END);
110 1 : if (offset < 0)
111 0 : return -1;
112 1 : break;
113 : default:
114 0 : errno = EINVAL;
115 0 : return -1;
116 : }
117 :
118 1 : if (offset < 0) {
119 1 : errno = EINVAL;
120 1 : return -1;
121 : }
122 :
123 1 : self->pos = offset;
124 1 : return offset;
125 1 : }
126 :
127 :
128 1 : int GioPioFlush(struct Gio *vself) {
129 : UNREFERENCED_PARAMETER(vself);
130 1 : return 0;
131 1 : }
132 :
133 :
134 1 : int GioPioClose(struct Gio *vself) {
135 1 : struct GioPio *self = (struct GioPio *) vself;
136 :
137 1 : if (CLOSE(self->fd) == 0) {
138 1 : self->fd = -1;
139 1 : return 0;
140 : }
141 :
142 0 : return -1;
143 1 : }
144 :
145 :
146 1 : void GioPioDtor(struct Gio *vself) {
147 1 : struct GioPio *self = (struct GioPio *) vself;
148 1 : if (-1 != self->fd) {
149 0 : (void) CLOSE(self->fd);
150 : }
151 1 : }
|