0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
|
4 */
|
|
5
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9
|
|
10
|
110
|
11 ssize_t
|
|
12 ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
0
|
13 {
|
110
|
14 ssize_t n;
|
0
|
15
|
|
16 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
|
10
|
17 "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
|
0
|
18
|
18
|
19 #if (NGX_HAVE_PREAD)
|
0
|
20
|
|
21 n = pread(file->fd, buf, size, offset);
|
|
22
|
|
23 if (n == -1) {
|
|
24 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
25 "pread() failed, file \"%s\"", file->name.data);
|
|
26 return NGX_ERROR;
|
|
27 }
|
|
28
|
|
29 #else
|
|
30
|
|
31 if (file->sys_offset != offset) {
|
|
32 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
33 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
|
|
34 return NGX_ERROR;
|
|
35 }
|
|
36
|
|
37 file->sys_offset = offset;
|
|
38 }
|
|
39
|
|
40 n = read(file->fd, buf, size);
|
|
41
|
|
42 if (n == -1) {
|
|
43 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed");
|
|
44 return NGX_ERROR;
|
|
45 }
|
|
46
|
|
47 file->sys_offset += n;
|
|
48
|
|
49 #endif
|
|
50
|
|
51 file->offset += n;
|
|
52
|
|
53 return n;
|
|
54 }
|
|
55
|
|
56
|
110
|
57 ssize_t
|
|
58 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
0
|
59 {
|
110
|
60 ssize_t n;
|
0
|
61
|
10
|
62 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
|
|
63 "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
|
|
64
|
18
|
65 #if (NGX_HAVE_PWRITE)
|
0
|
66
|
|
67 n = pwrite(file->fd, buf, size, offset);
|
|
68
|
|
69 if (n == -1) {
|
|
70 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed");
|
|
71 return NGX_ERROR;
|
|
72 }
|
|
73
|
|
74 if ((size_t) n != size) {
|
|
75 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
10
|
76 "pwrite() has written only %z of %uz", n, size);
|
0
|
77 return NGX_ERROR;
|
|
78 }
|
|
79
|
|
80 #else
|
|
81
|
|
82 if (file->sys_offset != offset) {
|
|
83 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
84 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
|
|
85 return NGX_ERROR;
|
|
86 }
|
|
87
|
|
88 file->sys_offset = offset;
|
|
89 }
|
|
90
|
|
91 n = write(file->fd, buf, size);
|
|
92
|
|
93 if (n == -1) {
|
|
94 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed");
|
|
95 return NGX_ERROR;
|
|
96 }
|
|
97
|
|
98 if ((size_t) n != size) {
|
|
99 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
10
|
100 "write() has written only %z of %uz", n, size);
|
0
|
101 return NGX_ERROR;
|
|
102 }
|
|
103
|
|
104 file->sys_offset += n;
|
|
105
|
|
106 #endif
|
|
107
|
|
108 file->offset += n;
|
|
109
|
|
110 return n;
|
|
111 }
|
|
112
|
|
113
|
110
|
114 ngx_fd_t
|
|
115 ngx_open_tempfile(u_char *name, ngx_uint_t persistent)
|
0
|
116 {
|
|
117 ngx_fd_t fd;
|
|
118
|
|
119 fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR, 0600);
|
|
120
|
|
121 if (fd != -1 && !persistent) {
|
|
122 unlink((const char *) name);
|
|
123 }
|
|
124
|
|
125 return fd;
|
|
126 }
|
|
127
|
|
128
|
10
|
129 #define NGX_IOVS 8
|
|
130
|
110
|
131 ssize_t
|
|
132 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
|
|
133 ngx_pool_t *pool)
|
0
|
134 {
|
|
135 u_char *prev;
|
|
136 size_t size;
|
|
137 ssize_t n;
|
10
|
138 ngx_array_t vec;
|
|
139 struct iovec *iov, iovs[NGX_IOVS];
|
0
|
140
|
10
|
141 /* use pwrite() if there is the only buf in a chain */
|
0
|
142
|
|
143 if (cl->next == NULL) {
|
|
144 return ngx_write_file(file, cl->buf->pos,
|
|
145 (size_t) (cl->buf->last - cl->buf->pos),
|
|
146 offset);
|
|
147 }
|
|
148
|
10
|
149 vec.elts = iovs;
|
|
150 vec.size = sizeof(struct iovec);
|
|
151 vec.nalloc = NGX_IOVS;
|
|
152 vec.pool = pool;
|
0
|
153
|
10
|
154 do {
|
|
155 prev = NULL;
|
|
156 iov = NULL;
|
|
157 size = 0;
|
0
|
158
|
10
|
159 vec.nelts = 0;
|
|
160
|
|
161 /* create the iovec and coalesce the neighbouring bufs */
|
0
|
162
|
10
|
163 while (cl && vec.nelts < IOV_MAX) {
|
|
164 if (prev == cl->buf->pos) {
|
|
165 iov->iov_len += cl->buf->last - cl->buf->pos;
|
0
|
166
|
10
|
167 } else {
|
50
|
168 iov = ngx_array_push(&vec);
|
|
169 if (iov == NULL) {
|
10
|
170 return NGX_ERROR;
|
|
171 }
|
|
172
|
|
173 iov->iov_base = (void *) cl->buf->pos;
|
|
174 iov->iov_len = cl->buf->last - cl->buf->pos;
|
|
175 }
|
|
176
|
|
177 size += cl->buf->last - cl->buf->pos;
|
|
178 prev = cl->buf->last;
|
|
179 cl = cl->next;
|
0
|
180 }
|
|
181
|
10
|
182 /* use pwrite() if there is the only iovec buffer */
|
0
|
183
|
10
|
184 if (vec.nelts == 1) {
|
|
185 iov = vec.elts;
|
|
186 return ngx_write_file(file, (u_char *) iov[0].iov_base,
|
|
187 iov[0].iov_len, offset);
|
|
188 }
|
0
|
189
|
10
|
190 if (file->sys_offset != offset) {
|
|
191 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
192 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
193 "lseek() failed");
|
|
194 return NGX_ERROR;
|
|
195 }
|
0
|
196
|
10
|
197 file->sys_offset = offset;
|
|
198 }
|
|
199
|
|
200 n = writev(file->fd, vec.elts, vec.nelts);
|
|
201
|
|
202 if (n == -1) {
|
|
203 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
204 "writev() failed");
|
0
|
205 return NGX_ERROR;
|
|
206 }
|
|
207
|
10
|
208 if ((size_t) n != size) {
|
|
209 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
|
210 "writev() has written only %z of %uz", n, size);
|
|
211 return NGX_ERROR;
|
|
212 }
|
0
|
213
|
10
|
214 file->sys_offset += n;
|
|
215 file->offset += n;
|
0
|
216
|
10
|
217 } while (cl);
|
0
|
218
|
|
219 return n;
|
|
220 }
|
|
221
|
|
222
|
110
|
223 ngx_int_t
|
|
224 ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
|
0
|
225 {
|
|
226 dir->dir = opendir((const char *) name->data);
|
|
227
|
|
228 if (dir->dir == NULL) {
|
|
229 return NGX_ERROR;
|
|
230 }
|
|
231
|
6
|
232 dir->valid_info = 0;
|
0
|
233
|
|
234 return NGX_OK;
|
|
235 }
|
110
|
236
|
|
237
|
|
238 ngx_int_t
|
|
239 ngx_lock_file(ngx_file_t *file)
|
|
240 {
|
|
241 ngx_err_t err;
|
|
242 struct flock fl;
|
|
243
|
|
244 fl.l_whence = SEEK_SET;
|
|
245 fl.l_len = 0;
|
|
246 fl.l_pid = 0;
|
|
247 fl.l_type = F_WRLCK;
|
|
248 fl.l_start = 0;
|
|
249
|
|
250 if (fcntl(file->fd, F_SETLK, &fl) == -1) {
|
|
251 err = ngx_errno;
|
|
252
|
|
253 if (err == NGX_EAGAIN) {
|
|
254 return NGX_BUSY;
|
|
255 }
|
|
256
|
|
257 ngx_log_error(NGX_LOG_ALERT, file->log, err,
|
|
258 "fcntl(%s, F_SETLK, F_WRLCK) failed", file->name.data);
|
|
259
|
|
260 return NGX_ERROR;
|
|
261 }
|
|
262
|
|
263 return NGX_OK;
|
|
264 }
|
|
265
|
|
266
|
|
267 ngx_int_t
|
|
268 ngx_unlock_file(ngx_file_t *file)
|
|
269 {
|
|
270 ngx_err_t err;
|
|
271 struct flock fl;
|
|
272
|
|
273 fl.l_whence = SEEK_SET;
|
|
274 fl.l_len = 0;
|
|
275 fl.l_pid = 0;
|
|
276 fl.l_type = F_UNLCK;
|
|
277 fl.l_start = 0;
|
|
278
|
|
279 if (fcntl(file->fd, F_SETLK, &fl) == -1) {
|
|
280 err = ngx_errno;
|
|
281
|
|
282 if (err == NGX_EAGAIN) {
|
|
283 return NGX_BUSY;
|
|
284 }
|
|
285
|
|
286 ngx_log_error(NGX_LOG_ALERT, file->log, err,
|
|
287 "fcntl(%s, F_SETLK, F_UNLCK) failed", file->name.data);
|
|
288
|
|
289 return NGX_ERROR;
|
|
290 }
|
|
291
|
|
292 return NGX_OK;
|
|
293 }
|