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,
|
506
|
25 "pread() \"%s\" failed", file->name.data);
|
0
|
26 return NGX_ERROR;
|
|
27 }
|
|
28
|
|
29 #else
|
|
30
|
|
31 if (file->sys_offset != offset) {
|
|
32 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
506
|
33 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
34 "lseek() \"%s\" failed", file->name.data);
|
0
|
35 return NGX_ERROR;
|
|
36 }
|
|
37
|
|
38 file->sys_offset = offset;
|
|
39 }
|
|
40
|
|
41 n = read(file->fd, buf, size);
|
|
42
|
|
43 if (n == -1) {
|
506
|
44 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
45 "read() \"%s\" failed", file->name.data);
|
0
|
46 return NGX_ERROR;
|
|
47 }
|
|
48
|
|
49 file->sys_offset += n;
|
|
50
|
|
51 #endif
|
|
52
|
|
53 file->offset += n;
|
|
54
|
|
55 return n;
|
|
56 }
|
|
57
|
|
58
|
110
|
59 ssize_t
|
|
60 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
0
|
61 {
|
506
|
62 ssize_t n, written;
|
0
|
63
|
10
|
64 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
|
|
65 "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
|
|
66
|
506
|
67 written = 0;
|
|
68
|
18
|
69 #if (NGX_HAVE_PWRITE)
|
0
|
70
|
506
|
71 for ( ;; ) {
|
|
72 n = pwrite(file->fd, buf, size, offset);
|
|
73
|
|
74 if (n == -1) {
|
|
75 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
76 "pwrite() \"%s\" failed", file->name.data);
|
|
77 return NGX_ERROR;
|
|
78 }
|
0
|
79
|
506
|
80 file->offset += n;
|
|
81 written += n;
|
0
|
82
|
506
|
83 if ((size_t) n == size) {
|
|
84 return written;
|
|
85 }
|
|
86
|
|
87 offset += n;
|
|
88 size -= n;
|
0
|
89 }
|
|
90
|
|
91 #else
|
|
92
|
|
93 if (file->sys_offset != offset) {
|
|
94 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
506
|
95 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
96 "lseek() \"%s\" failed", file->name.data);
|
0
|
97 return NGX_ERROR;
|
|
98 }
|
|
99
|
|
100 file->sys_offset = offset;
|
|
101 }
|
|
102
|
506
|
103 for ( ;; ) {
|
|
104 n = write(file->fd, buf, size);
|
0
|
105
|
506
|
106 if (n == -1) {
|
|
107 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
108 "write() \"%s\" failed", file->name.data);
|
|
109 return NGX_ERROR;
|
|
110 }
|
0
|
111
|
506
|
112 file->offset += n;
|
|
113 written += n;
|
0
|
114
|
506
|
115 if ((size_t) n == size) {
|
|
116 return written;
|
|
117 }
|
0
|
118
|
506
|
119 size -= n;
|
|
120 }
|
|
121 #endif
|
0
|
122 }
|
|
123
|
|
124
|
110
|
125 ngx_fd_t
|
276
|
126 ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
|
0
|
127 {
|
|
128 ngx_fd_t fd;
|
|
129
|
276
|
130 fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
|
|
131 access ? access : 0600);
|
0
|
132
|
|
133 if (fd != -1 && !persistent) {
|
|
134 unlink((const char *) name);
|
|
135 }
|
|
136
|
|
137 return fd;
|
|
138 }
|
|
139
|
|
140
|
10
|
141 #define NGX_IOVS 8
|
|
142
|
110
|
143 ssize_t
|
|
144 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
|
|
145 ngx_pool_t *pool)
|
0
|
146 {
|
|
147 u_char *prev;
|
|
148 size_t size;
|
|
149 ssize_t n;
|
10
|
150 ngx_array_t vec;
|
|
151 struct iovec *iov, iovs[NGX_IOVS];
|
0
|
152
|
10
|
153 /* use pwrite() if there is the only buf in a chain */
|
0
|
154
|
|
155 if (cl->next == NULL) {
|
|
156 return ngx_write_file(file, cl->buf->pos,
|
|
157 (size_t) (cl->buf->last - cl->buf->pos),
|
|
158 offset);
|
|
159 }
|
|
160
|
10
|
161 vec.elts = iovs;
|
|
162 vec.size = sizeof(struct iovec);
|
126
|
163 vec.nalloc = NGX_IOVS;
|
10
|
164 vec.pool = pool;
|
0
|
165
|
10
|
166 do {
|
|
167 prev = NULL;
|
|
168 iov = NULL;
|
|
169 size = 0;
|
0
|
170
|
10
|
171 vec.nelts = 0;
|
|
172
|
|
173 /* create the iovec and coalesce the neighbouring bufs */
|
0
|
174
|
10
|
175 while (cl && vec.nelts < IOV_MAX) {
|
|
176 if (prev == cl->buf->pos) {
|
|
177 iov->iov_len += cl->buf->last - cl->buf->pos;
|
0
|
178
|
10
|
179 } else {
|
50
|
180 iov = ngx_array_push(&vec);
|
|
181 if (iov == NULL) {
|
10
|
182 return NGX_ERROR;
|
|
183 }
|
|
184
|
|
185 iov->iov_base = (void *) cl->buf->pos;
|
|
186 iov->iov_len = cl->buf->last - cl->buf->pos;
|
|
187 }
|
|
188
|
|
189 size += cl->buf->last - cl->buf->pos;
|
|
190 prev = cl->buf->last;
|
|
191 cl = cl->next;
|
0
|
192 }
|
|
193
|
10
|
194 /* use pwrite() if there is the only iovec buffer */
|
0
|
195
|
10
|
196 if (vec.nelts == 1) {
|
|
197 iov = vec.elts;
|
|
198 return ngx_write_file(file, (u_char *) iov[0].iov_base,
|
|
199 iov[0].iov_len, offset);
|
|
200 }
|
0
|
201
|
10
|
202 if (file->sys_offset != offset) {
|
|
203 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
204 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
506
|
205 "lseek() \"%s\" failed", file->name.data);
|
10
|
206 return NGX_ERROR;
|
|
207 }
|
0
|
208
|
10
|
209 file->sys_offset = offset;
|
|
210 }
|
|
211
|
|
212 n = writev(file->fd, vec.elts, vec.nelts);
|
|
213
|
|
214 if (n == -1) {
|
|
215 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
506
|
216 "writev() \"%s\" failed", file->name.data);
|
0
|
217 return NGX_ERROR;
|
|
218 }
|
|
219
|
10
|
220 if ((size_t) n != size) {
|
|
221 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
506
|
222 "writev() \"%s\" has written only %z of %uz",
|
|
223 file->name.data, n, size);
|
10
|
224 return NGX_ERROR;
|
|
225 }
|
0
|
226
|
10
|
227 file->sys_offset += n;
|
|
228 file->offset += n;
|
0
|
229
|
10
|
230 } while (cl);
|
0
|
231
|
|
232 return n;
|
|
233 }
|
|
234
|
|
235
|
110
|
236 ngx_int_t
|
230
|
237 ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
|
|
238 {
|
|
239 struct timeval tv[2];
|
|
240
|
|
241 tv[0].tv_sec = s;
|
|
242 tv[0].tv_usec = 0;
|
|
243 tv[1].tv_sec = s;
|
|
244 tv[1].tv_usec = 0;
|
|
245
|
|
246 if (utimes((char *) name, tv) != -1) {
|
|
247 return NGX_OK;
|
|
248 }
|
|
249
|
|
250 return NGX_ERROR;
|
|
251 }
|
|
252
|
|
253
|
|
254 ngx_int_t
|
110
|
255 ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
|
0
|
256 {
|
|
257 dir->dir = opendir((const char *) name->data);
|
|
258
|
|
259 if (dir->dir == NULL) {
|
|
260 return NGX_ERROR;
|
|
261 }
|
|
262
|
6
|
263 dir->valid_info = 0;
|
0
|
264
|
|
265 return NGX_OK;
|
|
266 }
|
110
|
267
|
|
268
|
238
|
269 ngx_int_t
|
406
|
270 ngx_read_dir(ngx_dir_t *dir)
|
|
271 {
|
|
272 dir->de = readdir(dir->dir);
|
|
273
|
|
274 if (dir->de) {
|
|
275 #if (NGX_HAVE_D_TYPE)
|
|
276 dir->type = dir->de->d_type;
|
456
|
277 #else
|
506
|
278 dir->type = 0;
|
406
|
279 #endif
|
|
280 return NGX_OK;
|
|
281 }
|
|
282
|
|
283 return NGX_ERROR;
|
|
284 }
|
|
285
|
|
286
|
|
287 ngx_int_t
|
238
|
288 ngx_open_glob(ngx_glob_t *gl)
|
|
289 {
|
372
|
290 int n;
|
|
291
|
|
292 n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
|
|
293
|
|
294 if (n == 0) {
|
|
295 return NGX_OK;
|
|
296 }
|
|
297
|
400
|
298 #ifdef GLOB_NOMATCH
|
|
299
|
372
|
300 if (n == GLOB_NOMATCH && gl->test) {
|
238
|
301 return NGX_OK;
|
|
302 }
|
|
303
|
400
|
304 #endif
|
|
305
|
238
|
306 return NGX_ERROR;
|
|
307 }
|
|
308
|
|
309
|
|
310 ngx_int_t
|
|
311 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
|
|
312 {
|
402
|
313 size_t count;
|
|
314
|
|
315 #ifdef GLOB_NOMATCH
|
|
316 count = (size_t) gl->pglob.gl_pathc;
|
|
317 #else
|
|
318 count = (size_t) gl->pglob.gl_matchc;
|
|
319 #endif
|
|
320
|
|
321 if (gl->n < count) {
|
238
|
322
|
|
323 name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
|
|
324 name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
|
|
325 gl->n++;
|
|
326
|
|
327 return NGX_OK;
|
|
328 }
|
|
329
|
|
330 return NGX_DONE;
|
|
331 }
|
|
332
|
|
333
|
|
334 void
|
|
335 ngx_close_glob(ngx_glob_t *gl)
|
|
336 {
|
|
337 globfree(&gl->pglob);
|
|
338 }
|
|
339
|
|
340
|
160
|
341 ngx_err_t
|
|
342 ngx_trylock_fd(ngx_fd_t fd)
|
110
|
343 {
|
|
344 struct flock fl;
|
|
345
|
160
|
346 fl.l_start = 0;
|
|
347 fl.l_len = 0;
|
|
348 fl.l_pid = 0;
|
|
349 fl.l_type = F_WRLCK;
|
110
|
350 fl.l_whence = SEEK_SET;
|
160
|
351
|
|
352 if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
353 return ngx_errno;
|
|
354 }
|
|
355
|
|
356 return 0;
|
|
357 }
|
|
358
|
|
359
|
|
360 ngx_err_t
|
|
361 ngx_lock_fd(ngx_fd_t fd)
|
|
362 {
|
|
363 struct flock fl;
|
|
364
|
|
365 fl.l_start = 0;
|
110
|
366 fl.l_len = 0;
|
|
367 fl.l_pid = 0;
|
|
368 fl.l_type = F_WRLCK;
|
160
|
369 fl.l_whence = SEEK_SET;
|
110
|
370
|
160
|
371 if (fcntl(fd, F_SETLKW, &fl) == -1) {
|
|
372 return ngx_errno;
|
110
|
373 }
|
|
374
|
160
|
375 return 0;
|
110
|
376 }
|
|
377
|
|
378
|
160
|
379 ngx_err_t
|
|
380 ngx_unlock_fd(ngx_fd_t fd)
|
110
|
381 {
|
|
382 struct flock fl;
|
|
383
|
160
|
384 fl.l_start = 0;
|
110
|
385 fl.l_len = 0;
|
|
386 fl.l_pid = 0;
|
|
387 fl.l_type = F_UNLCK;
|
160
|
388 fl.l_whence = SEEK_SET;
|
110
|
389
|
160
|
390 if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
391 return ngx_errno;
|
110
|
392 }
|
|
393
|
160
|
394 return 0;
|
110
|
395 }
|
390
|
396
|
|
397
|
|
398 #if (NGX_HAVE_O_DIRECT)
|
|
399
|
|
400 ngx_int_t
|
410
|
401 ngx_directio_on(ngx_fd_t fd)
|
390
|
402 {
|
|
403 int flags;
|
|
404
|
|
405 flags = fcntl(fd, F_GETFL);
|
|
406
|
|
407 if (flags == -1) {
|
506
|
408 return NGX_FILE_ERROR;
|
390
|
409 }
|
|
410
|
|
411 return fcntl(fd, F_SETFL, flags | O_DIRECT);
|
|
412 }
|
|
413
|
410
|
414
|
|
415 ngx_int_t
|
|
416 ngx_directio_off(ngx_fd_t fd)
|
|
417 {
|
|
418 int flags;
|
|
419
|
|
420 flags = fcntl(fd, F_GETFL);
|
|
421
|
|
422 if (flags == -1) {
|
506
|
423 return NGX_FILE_ERROR;
|
410
|
424 }
|
|
425
|
|
426 return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
|
|
427 }
|
|
428
|
390
|
429 #endif
|
468
|
430
|
|
431
|
|
432 #if (NGX_HAVE_STATFS)
|
|
433
|
|
434 size_t
|
|
435 ngx_fs_bsize(u_char *name)
|
|
436 {
|
|
437 struct statfs fs;
|
|
438
|
|
439 if (statfs((char *) name, &fs) == -1) {
|
|
440 return 512;
|
|
441 }
|
|
442
|
|
443 if ((fs.f_bsize % 512) != 0) {
|
|
444 return 512;
|
|
445 }
|
|
446
|
|
447 return (size_t) fs.f_bsize;
|
|
448 }
|
|
449
|
|
450 #elif (NGX_HAVE_STATVFS)
|
|
451
|
|
452 size_t
|
|
453 ngx_fs_bsize(u_char *name)
|
|
454 {
|
|
455 struct statvfs fs;
|
|
456
|
|
457 if (statvfs((char *) name, &fs) == -1) {
|
|
458 return 512;
|
|
459 }
|
|
460
|
|
461 if ((fs.f_frsize % 512) != 0) {
|
|
462 return 512;
|
|
463 }
|
|
464
|
|
465 return (size_t) fs.f_frsize;
|
|
466 }
|
|
467
|
|
468 #else
|
|
469
|
|
470 size_t
|
|
471 ngx_fs_bsize(u_char *name)
|
|
472 {
|
|
473 return 512;
|
|
474 }
|
|
475
|
|
476 #endif
|