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
|
276
|
115 ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
|
0
|
116 {
|
|
117 ngx_fd_t fd;
|
|
118
|
276
|
119 fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
|
|
120 access ? access : 0600);
|
0
|
121
|
|
122 if (fd != -1 && !persistent) {
|
|
123 unlink((const char *) name);
|
|
124 }
|
|
125
|
|
126 return fd;
|
|
127 }
|
|
128
|
|
129
|
10
|
130 #define NGX_IOVS 8
|
|
131
|
110
|
132 ssize_t
|
|
133 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
|
|
134 ngx_pool_t *pool)
|
0
|
135 {
|
|
136 u_char *prev;
|
|
137 size_t size;
|
|
138 ssize_t n;
|
10
|
139 ngx_array_t vec;
|
|
140 struct iovec *iov, iovs[NGX_IOVS];
|
0
|
141
|
10
|
142 /* use pwrite() if there is the only buf in a chain */
|
0
|
143
|
|
144 if (cl->next == NULL) {
|
|
145 return ngx_write_file(file, cl->buf->pos,
|
|
146 (size_t) (cl->buf->last - cl->buf->pos),
|
|
147 offset);
|
|
148 }
|
|
149
|
10
|
150 vec.elts = iovs;
|
|
151 vec.size = sizeof(struct iovec);
|
126
|
152 vec.nalloc = NGX_IOVS;
|
10
|
153 vec.pool = pool;
|
0
|
154
|
10
|
155 do {
|
|
156 prev = NULL;
|
|
157 iov = NULL;
|
|
158 size = 0;
|
0
|
159
|
10
|
160 vec.nelts = 0;
|
|
161
|
|
162 /* create the iovec and coalesce the neighbouring bufs */
|
0
|
163
|
10
|
164 while (cl && vec.nelts < IOV_MAX) {
|
|
165 if (prev == cl->buf->pos) {
|
|
166 iov->iov_len += cl->buf->last - cl->buf->pos;
|
0
|
167
|
10
|
168 } else {
|
50
|
169 iov = ngx_array_push(&vec);
|
|
170 if (iov == NULL) {
|
10
|
171 return NGX_ERROR;
|
|
172 }
|
|
173
|
|
174 iov->iov_base = (void *) cl->buf->pos;
|
|
175 iov->iov_len = cl->buf->last - cl->buf->pos;
|
|
176 }
|
|
177
|
|
178 size += cl->buf->last - cl->buf->pos;
|
|
179 prev = cl->buf->last;
|
|
180 cl = cl->next;
|
0
|
181 }
|
|
182
|
10
|
183 /* use pwrite() if there is the only iovec buffer */
|
0
|
184
|
10
|
185 if (vec.nelts == 1) {
|
|
186 iov = vec.elts;
|
|
187 return ngx_write_file(file, (u_char *) iov[0].iov_base,
|
|
188 iov[0].iov_len, offset);
|
|
189 }
|
0
|
190
|
10
|
191 if (file->sys_offset != offset) {
|
|
192 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
193 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
194 "lseek() failed");
|
|
195 return NGX_ERROR;
|
|
196 }
|
0
|
197
|
10
|
198 file->sys_offset = offset;
|
|
199 }
|
|
200
|
|
201 n = writev(file->fd, vec.elts, vec.nelts);
|
|
202
|
|
203 if (n == -1) {
|
|
204 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
205 "writev() failed");
|
0
|
206 return NGX_ERROR;
|
|
207 }
|
|
208
|
10
|
209 if ((size_t) n != size) {
|
|
210 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
|
211 "writev() has written only %z of %uz", n, size);
|
|
212 return NGX_ERROR;
|
|
213 }
|
0
|
214
|
10
|
215 file->sys_offset += n;
|
|
216 file->offset += n;
|
0
|
217
|
10
|
218 } while (cl);
|
0
|
219
|
|
220 return n;
|
|
221 }
|
|
222
|
|
223
|
110
|
224 ngx_int_t
|
230
|
225 ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
|
|
226 {
|
|
227 struct timeval tv[2];
|
|
228
|
|
229 tv[0].tv_sec = s;
|
|
230 tv[0].tv_usec = 0;
|
|
231 tv[1].tv_sec = s;
|
|
232 tv[1].tv_usec = 0;
|
|
233
|
|
234 if (utimes((char *) name, tv) != -1) {
|
|
235 return NGX_OK;
|
|
236 }
|
|
237
|
|
238 return NGX_ERROR;
|
|
239 }
|
|
240
|
|
241
|
|
242 ngx_int_t
|
110
|
243 ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
|
0
|
244 {
|
|
245 dir->dir = opendir((const char *) name->data);
|
|
246
|
|
247 if (dir->dir == NULL) {
|
|
248 return NGX_ERROR;
|
|
249 }
|
|
250
|
6
|
251 dir->valid_info = 0;
|
406
|
252 #if (NGX_HAVE_D_TYPE)
|
|
253 dir->valid_type = 1;
|
|
254 #else
|
|
255 dir->valid_type = 0;
|
|
256 #endif
|
0
|
257
|
|
258 return NGX_OK;
|
|
259 }
|
110
|
260
|
|
261
|
238
|
262 ngx_int_t
|
406
|
263 ngx_read_dir(ngx_dir_t *dir)
|
|
264 {
|
|
265 dir->de = readdir(dir->dir);
|
|
266
|
|
267 if (dir->de) {
|
|
268 #if (NGX_HAVE_D_TYPE)
|
|
269 dir->type = dir->de->d_type;
|
|
270 #endif
|
|
271 return NGX_OK;
|
|
272 }
|
|
273
|
|
274 return NGX_ERROR;
|
|
275 }
|
|
276
|
|
277
|
|
278 ngx_int_t
|
238
|
279 ngx_open_glob(ngx_glob_t *gl)
|
|
280 {
|
372
|
281 int n;
|
|
282
|
|
283 n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
|
|
284
|
|
285 if (n == 0) {
|
|
286 return NGX_OK;
|
|
287 }
|
|
288
|
400
|
289 #ifdef GLOB_NOMATCH
|
|
290
|
372
|
291 if (n == GLOB_NOMATCH && gl->test) {
|
238
|
292 return NGX_OK;
|
|
293 }
|
|
294
|
400
|
295 #endif
|
|
296
|
238
|
297 return NGX_ERROR;
|
|
298 }
|
|
299
|
|
300
|
|
301 ngx_int_t
|
|
302 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
|
|
303 {
|
402
|
304 size_t count;
|
|
305
|
|
306 #ifdef GLOB_NOMATCH
|
|
307 count = (size_t) gl->pglob.gl_pathc;
|
|
308 #else
|
|
309 count = (size_t) gl->pglob.gl_matchc;
|
|
310 #endif
|
|
311
|
|
312 if (gl->n < count) {
|
238
|
313
|
|
314 name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
|
|
315 name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
|
|
316 gl->n++;
|
|
317
|
|
318 return NGX_OK;
|
|
319 }
|
|
320
|
|
321 return NGX_DONE;
|
|
322 }
|
|
323
|
|
324
|
|
325 void
|
|
326 ngx_close_glob(ngx_glob_t *gl)
|
|
327 {
|
|
328 globfree(&gl->pglob);
|
|
329 }
|
|
330
|
|
331
|
160
|
332 ngx_err_t
|
|
333 ngx_trylock_fd(ngx_fd_t fd)
|
110
|
334 {
|
|
335 struct flock fl;
|
|
336
|
160
|
337 fl.l_start = 0;
|
|
338 fl.l_len = 0;
|
|
339 fl.l_pid = 0;
|
|
340 fl.l_type = F_WRLCK;
|
110
|
341 fl.l_whence = SEEK_SET;
|
160
|
342
|
|
343 if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
344 return ngx_errno;
|
|
345 }
|
|
346
|
|
347 return 0;
|
|
348 }
|
|
349
|
|
350
|
|
351 ngx_err_t
|
|
352 ngx_lock_fd(ngx_fd_t fd)
|
|
353 {
|
|
354 struct flock fl;
|
|
355
|
|
356 fl.l_start = 0;
|
110
|
357 fl.l_len = 0;
|
|
358 fl.l_pid = 0;
|
|
359 fl.l_type = F_WRLCK;
|
160
|
360 fl.l_whence = SEEK_SET;
|
110
|
361
|
160
|
362 if (fcntl(fd, F_SETLKW, &fl) == -1) {
|
|
363 return ngx_errno;
|
110
|
364 }
|
|
365
|
160
|
366 return 0;
|
110
|
367 }
|
|
368
|
|
369
|
160
|
370 ngx_err_t
|
|
371 ngx_unlock_fd(ngx_fd_t fd)
|
110
|
372 {
|
|
373 struct flock fl;
|
|
374
|
160
|
375 fl.l_start = 0;
|
110
|
376 fl.l_len = 0;
|
|
377 fl.l_pid = 0;
|
|
378 fl.l_type = F_UNLCK;
|
160
|
379 fl.l_whence = SEEK_SET;
|
110
|
380
|
160
|
381 if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
382 return ngx_errno;
|
110
|
383 }
|
|
384
|
160
|
385 return 0;
|
110
|
386 }
|
390
|
387
|
|
388
|
|
389 #if (NGX_HAVE_O_DIRECT)
|
|
390
|
|
391 ngx_int_t
|
410
|
392 ngx_directio_on(ngx_fd_t fd)
|
390
|
393 {
|
|
394 int flags;
|
|
395
|
|
396 flags = fcntl(fd, F_GETFL);
|
|
397
|
|
398 if (flags == -1) {
|
|
399 return -1;
|
|
400 }
|
|
401
|
|
402 return fcntl(fd, F_SETFL, flags | O_DIRECT);
|
|
403 }
|
|
404
|
410
|
405
|
|
406 ngx_int_t
|
|
407 ngx_directio_off(ngx_fd_t fd)
|
|
408 {
|
|
409 int flags;
|
|
410
|
|
411 flags = fcntl(fd, F_GETFL);
|
|
412
|
|
413 if (flags == -1) {
|
|
414 return -1;
|
|
415 }
|
|
416
|
|
417 return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
|
|
418 }
|
|
419
|
390
|
420 #endif
|