Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_files.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 
11 
12 #if (NGX_HAVE_FILE_AIO)
13 
14 ngx_uint_t ngx_file_aio = 1;
15 
16 #endif
17 
18 
19 ssize_t
20 ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
21 {
22  ssize_t n;
23 
25  "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
26 
27 #if (NGX_HAVE_PREAD)
28 
29  n = pread(file->fd, buf, size, offset);
30 
31  if (n == -1) {
33  "pread() \"%s\" failed", file->name.data);
34  return NGX_ERROR;
35  }
36 
37 #else
38 
39  if (file->sys_offset != offset) {
40  if (lseek(file->fd, offset, SEEK_SET) == -1) {
42  "lseek() \"%s\" failed", file->name.data);
43  return NGX_ERROR;
44  }
45 
46  file->sys_offset = offset;
47  }
48 
49  n = read(file->fd, buf, size);
50 
51  if (n == -1) {
53  "read() \"%s\" failed", file->name.data);
54  return NGX_ERROR;
55  }
56 
57  file->sys_offset += n;
58 
59 #endif
60 
61  file->offset += n;
62 
63  return n;
64 }
65 
66 
67 ssize_t
68 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
69 {
70  ssize_t n, written;
71 
73  "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
74 
75  written = 0;
76 
77 #if (NGX_HAVE_PWRITE)
78 
79  for ( ;; ) {
80  n = pwrite(file->fd, buf + written, size, offset);
81 
82  if (n == -1) {
84  "pwrite() \"%s\" failed", file->name.data);
85  return NGX_ERROR;
86  }
87 
88  file->offset += n;
89  written += n;
90 
91  if ((size_t) n == size) {
92  return written;
93  }
94 
95  offset += n;
96  size -= n;
97  }
98 
99 #else
100 
101  if (file->sys_offset != offset) {
102  if (lseek(file->fd, offset, SEEK_SET) == -1) {
104  "lseek() \"%s\" failed", file->name.data);
105  return NGX_ERROR;
106  }
107 
108  file->sys_offset = offset;
109  }
110 
111  for ( ;; ) {
112  n = write(file->fd, buf + written, size);
113 
114  if (n == -1) {
116  "write() \"%s\" failed", file->name.data);
117  return NGX_ERROR;
118  }
119 
120  file->offset += n;
121  written += n;
122 
123  if ((size_t) n == size) {
124  return written;
125  }
126 
127  size -= n;
128  }
129 #endif
130 }
131 
132 
133 ngx_fd_t
134 ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
135 {
136  ngx_fd_t fd;
137 
138  fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
139  access ? access : 0600);
140 
141  if (fd != -1 && !persistent) {
142  (void) unlink((const char *) name);
143  }
144 
145  return fd;
146 }
147 
148 
149 #define NGX_IOVS 8
150 
151 ssize_t
153  ngx_pool_t *pool)
154 {
155  u_char *prev;
156  size_t size;
157  ssize_t total, n;
158  ngx_array_t vec;
159  struct iovec *iov, iovs[NGX_IOVS];
160 
161  /* use pwrite() if there is the only buf in a chain */
162 
163  if (cl->next == NULL) {
164  return ngx_write_file(file, cl->buf->pos,
165  (size_t) (cl->buf->last - cl->buf->pos),
166  offset);
167  }
168 
169  total = 0;
170 
171  vec.elts = iovs;
172  vec.size = sizeof(struct iovec);
173  vec.nalloc = NGX_IOVS;
174  vec.pool = pool;
175 
176  do {
177  prev = NULL;
178  iov = NULL;
179  size = 0;
180 
181  vec.nelts = 0;
182 
183  /* create the iovec and coalesce the neighbouring bufs */
184 
185  while (cl && vec.nelts < IOV_MAX) {
186  if (prev == cl->buf->pos) {
187  iov->iov_len += cl->buf->last - cl->buf->pos;
188 
189  } else {
190  iov = ngx_array_push(&vec);
191  if (iov == NULL) {
192  return NGX_ERROR;
193  }
194 
195  iov->iov_base = (void *) cl->buf->pos;
196  iov->iov_len = cl->buf->last - cl->buf->pos;
197  }
198 
199  size += cl->buf->last - cl->buf->pos;
200  prev = cl->buf->last;
201  cl = cl->next;
202  }
203 
204  /* use pwrite() if there is the only iovec buffer */
205 
206  if (vec.nelts == 1) {
207  iov = vec.elts;
208 
209  n = ngx_write_file(file, (u_char *) iov[0].iov_base,
210  iov[0].iov_len, offset);
211 
212  if (n == NGX_ERROR) {
213  return n;
214  }
215 
216  return total + n;
217  }
218 
219  if (file->sys_offset != offset) {
220  if (lseek(file->fd, offset, SEEK_SET) == -1) {
222  "lseek() \"%s\" failed", file->name.data);
223  return NGX_ERROR;
224  }
225 
226  file->sys_offset = offset;
227  }
228 
229  n = writev(file->fd, vec.elts, vec.nelts);
230 
231  if (n == -1) {
233  "writev() \"%s\" failed", file->name.data);
234  return NGX_ERROR;
235  }
236 
237  if ((size_t) n != size) {
238  ngx_log_error(NGX_LOG_CRIT, file->log, 0,
239  "writev() \"%s\" has written only %z of %uz",
240  file->name.data, n, size);
241  return NGX_ERROR;
242  }
243 
245  "writev: %d, %z", file->fd, n);
246 
247  file->sys_offset += n;
248  file->offset += n;
249  offset += n;
250  total += n;
251 
252  } while (cl);
253 
254  return total;
255 }
256 
257 
258 ngx_int_t
259 ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
260 {
261  struct timeval tv[2];
262 
263  tv[0].tv_sec = ngx_time();
264  tv[0].tv_usec = 0;
265  tv[1].tv_sec = s;
266  tv[1].tv_usec = 0;
267 
268  if (utimes((char *) name, tv) != -1) {
269  return NGX_OK;
270  }
271 
272  return NGX_ERROR;
273 }
274 
275 
276 ngx_int_t
278 {
281  if (fm->fd == NGX_INVALID_FILE) {
283  ngx_open_file_n " \"%s\" failed", fm->name);
284  return NGX_ERROR;
285  }
286 
287  if (ftruncate(fm->fd, fm->size) == -1) {
289  "ftruncate() \"%s\" failed", fm->name);
290  goto failed;
291  }
292 
293  fm->addr = mmap(NULL, fm->size, PROT_READ|PROT_WRITE, MAP_SHARED,
294  fm->fd, 0);
295  if (fm->addr != MAP_FAILED) {
296  return NGX_OK;
297  }
298 
300  "mmap(%uz) \"%s\" failed", fm->size, fm->name);
301 
302 failed:
303 
304  if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
306  ngx_close_file_n " \"%s\" failed", fm->name);
307  }
308 
309  return NGX_ERROR;
310 }
311 
312 
313 void
315 {
316  if (munmap(fm->addr, fm->size) == -1) {
318  "munmap(%uz) \"%s\" failed", fm->size, fm->name);
319  }
320 
321  if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
323  ngx_close_file_n " \"%s\" failed", fm->name);
324  }
325 }
326 
327 
328 ngx_int_t
330 {
331  dir->dir = opendir((const char *) name->data);
332 
333  if (dir->dir == NULL) {
334  return NGX_ERROR;
335  }
336 
337  dir->valid_info = 0;
338 
339  return NGX_OK;
340 }
341 
342 
343 ngx_int_t
345 {
346  dir->de = readdir(dir->dir);
347 
348  if (dir->de) {
349 #if (NGX_HAVE_D_TYPE)
350  dir->type = dir->de->d_type;
351 #else
352  dir->type = 0;
353 #endif
354  return NGX_OK;
355  }
356 
357  return NGX_ERROR;
358 }
359 
360 
361 ngx_int_t
363 {
364  int n;
365 
366  n = glob((char *) gl->pattern, 0, NULL, &gl->pglob);
367 
368  if (n == 0) {
369  return NGX_OK;
370  }
371 
372 #ifdef GLOB_NOMATCH
373 
374  if (n == GLOB_NOMATCH && gl->test) {
375  return NGX_OK;
376  }
377 
378 #endif
379 
380  return NGX_ERROR;
381 }
382 
383 
384 ngx_int_t
386 {
387  size_t count;
388 
389 #ifdef GLOB_NOMATCH
390  count = (size_t) gl->pglob.gl_pathc;
391 #else
392  count = (size_t) gl->pglob.gl_matchc;
393 #endif
394 
395  if (gl->n < count) {
396 
397  name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
398  name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
399  gl->n++;
400 
401  return NGX_OK;
402  }
403 
404  return NGX_DONE;
405 }
406 
407 
408 void
410 {
411  globfree(&gl->pglob);
412 }
413 
414 
415 ngx_err_t
417 {
418  struct flock fl;
419 
420  ngx_memzero(&fl, sizeof(struct flock));
421  fl.l_type = F_WRLCK;
422  fl.l_whence = SEEK_SET;
423 
424  if (fcntl(fd, F_SETLK, &fl) == -1) {
425  return ngx_errno;
426  }
427 
428  return 0;
429 }
430 
431 
432 ngx_err_t
434 {
435  struct flock fl;
436 
437  ngx_memzero(&fl, sizeof(struct flock));
438  fl.l_type = F_WRLCK;
439  fl.l_whence = SEEK_SET;
440 
441  if (fcntl(fd, F_SETLKW, &fl) == -1) {
442  return ngx_errno;
443  }
444 
445  return 0;
446 }
447 
448 
449 ngx_err_t
451 {
452  struct flock fl;
453 
454  ngx_memzero(&fl, sizeof(struct flock));
455  fl.l_type = F_UNLCK;
456  fl.l_whence = SEEK_SET;
457 
458  if (fcntl(fd, F_SETLK, &fl) == -1) {
459  return ngx_errno;
460  }
461 
462  return 0;
463 }
464 
465 
466 #if (NGX_HAVE_POSIX_FADVISE) && !(NGX_HAVE_F_READAHEAD)
467 
468 ngx_int_t
469 ngx_read_ahead(ngx_fd_t fd, size_t n)
470 {
471  int err;
472 
473  err = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
474 
475  if (err == 0) {
476  return 0;
477  }
478 
479  ngx_set_errno(err);
480  return NGX_FILE_ERROR;
481 }
482 
483 #endif
484 
485 
486 #if (NGX_HAVE_O_DIRECT)
487 
488 ngx_int_t
490 {
491  int flags;
492 
493  flags = fcntl(fd, F_GETFL);
494 
495  if (flags == -1) {
496  return NGX_FILE_ERROR;
497  }
498 
499  return fcntl(fd, F_SETFL, flags | O_DIRECT);
500 }
501 
502 
503 ngx_int_t
504 ngx_directio_off(ngx_fd_t fd)
505 {
506  int flags;
507 
508  flags = fcntl(fd, F_GETFL);
509 
510  if (flags == -1) {
511  return NGX_FILE_ERROR;
512  }
513 
514  return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
515 }
516 
517 #endif
518 
519 
520 #if (NGX_HAVE_STATFS)
521 
522 size_t
523 ngx_fs_bsize(u_char *name)
524 {
525  struct statfs fs;
526 
527  if (statfs((char *) name, &fs) == -1) {
528  return 512;
529  }
530 
531  if ((fs.f_bsize % 512) != 0) {
532  return 512;
533  }
534 
535  return (size_t) fs.f_bsize;
536 }
537 
538 #elif (NGX_HAVE_STATVFS)
539 
540 size_t
541 ngx_fs_bsize(u_char *name)
542 {
543  struct statvfs fs;
544 
545  if (statvfs((char *) name, &fs) == -1) {
546  return 512;
547  }
548 
549  if ((fs.f_frsize % 512) != 0) {
550  return 512;
551  }
552 
553  return (size_t) fs.f_frsize;
554 }
555 
556 #else
557 
558 size_t
559 ngx_fs_bsize(u_char *name)
560 {
561  return 512;
562 }
563 
564 #endif