nginxtra 1.0.15.0 → 1.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/VERSION +1 -1
  2. data/bin/nginxtra +1 -1
  3. data/lib/nginxtra/action.rb +10 -0
  4. data/lib/nginxtra/actions/compile.rb +16 -2
  5. data/lib/nginxtra/actions/start.rb +18 -2
  6. data/lib/nginxtra/actions/status.rb +1 -10
  7. data/lib/nginxtra/actions/stop.rb +18 -0
  8. data/lib/nginxtra/cli.rb +12 -3
  9. data/lib/nginxtra/config.rb +10 -0
  10. data/src/nginx/CHANGES +311 -90
  11. data/src/nginx/CHANGES.ru +315 -88
  12. data/src/nginx/auto/lib/pcre/conf +22 -5
  13. data/src/nginx/auto/lib/pcre/make +1 -1
  14. data/src/nginx/auto/modules +14 -3
  15. data/src/nginx/auto/options +17 -3
  16. data/src/nginx/auto/os/freebsd +8 -0
  17. data/src/nginx/auto/os/linux +5 -4
  18. data/src/nginx/auto/os/solaris +2 -1
  19. data/src/nginx/auto/sources +10 -2
  20. data/src/nginx/auto/summary +2 -0
  21. data/src/nginx/auto/types/sizeof +2 -1
  22. data/src/nginx/auto/types/typedef +1 -1
  23. data/src/nginx/auto/types/uintptr_t +7 -4
  24. data/src/nginx/auto/unix +82 -21
  25. data/src/nginx/conf/fastcgi.conf +1 -0
  26. data/src/nginx/conf/fastcgi_params +1 -0
  27. data/src/nginx/conf/scgi_params +1 -0
  28. data/src/nginx/conf/uwsgi_params +1 -0
  29. data/src/nginx/man/nginx.8 +49 -49
  30. data/src/nginx/src/core/nginx.c +10 -12
  31. data/src/nginx/src/core/nginx.h +2 -2
  32. data/src/nginx/src/core/ngx_buf.c +9 -7
  33. data/src/nginx/src/core/ngx_buf.h +2 -2
  34. data/src/nginx/src/core/ngx_conf_file.c +4 -11
  35. data/src/nginx/src/core/ngx_conf_file.h +1 -1
  36. data/src/nginx/src/core/ngx_connection.c +52 -1
  37. data/src/nginx/src/core/ngx_connection.h +6 -0
  38. data/src/nginx/src/core/ngx_core.h +5 -0
  39. data/src/nginx/src/core/ngx_cycle.c +1 -1
  40. data/src/nginx/src/core/ngx_cycle.h +2 -2
  41. data/src/nginx/src/core/ngx_file.c +1 -1
  42. data/src/nginx/src/core/ngx_inet.c +11 -8
  43. data/src/nginx/src/core/ngx_murmurhash.h +1 -1
  44. data/src/nginx/src/core/ngx_open_file_cache.c +343 -38
  45. data/src/nginx/src/core/ngx_open_file_cache.h +10 -0
  46. data/src/nginx/src/core/ngx_output_chain.c +2 -1
  47. data/src/nginx/src/core/ngx_parse.h +0 -3
  48. data/src/nginx/src/core/ngx_rbtree.c +1 -2
  49. data/src/nginx/src/core/ngx_regex.c +263 -5
  50. data/src/nginx/src/core/ngx_regex.h +6 -2
  51. data/src/nginx/src/core/ngx_resolver.c +88 -21
  52. data/src/nginx/src/core/ngx_resolver.h +7 -8
  53. data/src/nginx/src/core/ngx_shmtx.c +69 -44
  54. data/src/nginx/src/core/ngx_shmtx.h +12 -1
  55. data/src/nginx/src/core/ngx_slab.c +3 -3
  56. data/src/nginx/src/core/ngx_slab.h +1 -1
  57. data/src/nginx/src/core/ngx_string.c +19 -16
  58. data/src/nginx/src/core/ngx_times.c +2 -2
  59. data/src/nginx/src/event/modules/ngx_epoll_module.c +2 -2
  60. data/src/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  61. data/src/nginx/src/event/modules/ngx_kqueue_module.c +1 -1
  62. data/src/nginx/src/event/ngx_event.c +25 -17
  63. data/src/nginx/src/event/ngx_event_openssl.c +3 -1
  64. data/src/nginx/src/event/ngx_event_pipe.c +108 -85
  65. data/src/nginx/src/event/ngx_event_pipe.h +1 -2
  66. data/src/nginx/src/event/ngx_event_timer.c +2 -3
  67. data/src/nginx/src/http/modules/ngx_http_access_module.c +9 -4
  68. data/src/nginx/src/http/modules/ngx_http_browser_module.c +5 -3
  69. data/src/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -1
  70. data/src/nginx/src/http/modules/ngx_http_degradation_module.c +1 -1
  71. data/src/nginx/src/http/modules/ngx_http_fastcgi_module.c +144 -22
  72. data/src/nginx/src/http/modules/ngx_http_flv_module.c +8 -0
  73. data/src/nginx/src/http/modules/ngx_http_geo_module.c +3 -3
  74. data/src/nginx/src/http/modules/ngx_http_gzip_filter_module.c +20 -6
  75. data/src/nginx/src/http/modules/ngx_http_gzip_static_module.c +8 -0
  76. data/src/nginx/src/http/modules/ngx_http_headers_filter_module.c +23 -27
  77. data/src/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -3
  78. data/src/nginx/src/http/modules/ngx_http_index_module.c +24 -0
  79. data/src/nginx/src/http/modules/ngx_http_limit_conn_module.c +747 -0
  80. data/src/nginx/src/http/modules/ngx_http_limit_req_module.c +289 -133
  81. data/src/nginx/src/http/modules/ngx_http_log_module.c +34 -6
  82. data/src/nginx/src/http/modules/ngx_http_memcached_module.c +19 -3
  83. data/src/nginx/src/http/modules/ngx_http_mp4_module.c +8 -0
  84. data/src/nginx/src/http/modules/ngx_http_proxy_module.c +1446 -239
  85. data/src/nginx/src/http/modules/ngx_http_realip_module.c +4 -10
  86. data/src/nginx/src/http/modules/ngx_http_scgi_module.c +90 -21
  87. data/src/nginx/src/http/modules/ngx_http_split_clients_module.c +8 -11
  88. data/src/nginx/src/http/modules/ngx_http_ssi_filter_module.c +16 -6
  89. data/src/nginx/src/http/modules/ngx_http_static_module.c +8 -0
  90. data/src/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +2 -2
  91. data/src/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +570 -0
  92. data/src/nginx/src/http/modules/ngx_http_userid_filter_module.c +1 -5
  93. data/src/nginx/src/http/modules/ngx_http_uwsgi_module.c +77 -26
  94. data/src/nginx/src/http/modules/ngx_http_xslt_filter_module.c +171 -37
  95. data/src/nginx/src/http/modules/perl/nginx.pm +2 -1
  96. data/src/nginx/src/http/modules/perl/nginx.xs +4 -0
  97. data/src/nginx/src/http/ngx_http.c +8 -1
  98. data/src/nginx/src/http/ngx_http.h +1 -0
  99. data/src/nginx/src/http/ngx_http_busy_lock.c +2 -2
  100. data/src/nginx/src/http/ngx_http_cache.h +12 -1
  101. data/src/nginx/src/http/ngx_http_copy_filter_module.c +4 -3
  102. data/src/nginx/src/http/ngx_http_core_module.c +303 -37
  103. data/src/nginx/src/http/ngx_http_core_module.h +15 -0
  104. data/src/nginx/src/http/ngx_http_file_cache.c +226 -52
  105. data/src/nginx/src/http/ngx_http_parse.c +69 -3
  106. data/src/nginx/src/http/ngx_http_postpone_filter_module.c +4 -4
  107. data/src/nginx/src/http/ngx_http_request.c +61 -27
  108. data/src/nginx/src/http/ngx_http_request.h +3 -3
  109. data/src/nginx/src/http/ngx_http_request_body.c +1 -1
  110. data/src/nginx/src/http/ngx_http_script.c +6 -0
  111. data/src/nginx/src/http/ngx_http_upstream.c +200 -47
  112. data/src/nginx/src/http/ngx_http_upstream.h +20 -1
  113. data/src/nginx/src/http/ngx_http_upstream_round_robin.c +22 -6
  114. data/src/nginx/src/http/ngx_http_upstream_round_robin.h +1 -0
  115. data/src/nginx/src/http/ngx_http_variables.c +123 -4
  116. data/src/nginx/src/mail/ngx_mail.c +13 -0
  117. data/src/nginx/src/mail/ngx_mail.h +12 -0
  118. data/src/nginx/src/mail/ngx_mail_core_module.c +100 -15
  119. data/src/nginx/src/os/unix/ngx_daemon.c +2 -1
  120. data/src/nginx/src/os/unix/ngx_darwin.h +3 -0
  121. data/src/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  122. data/src/nginx/src/os/unix/ngx_darwin_init.c +30 -0
  123. data/src/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +11 -5
  124. data/src/nginx/src/os/unix/ngx_errno.h +5 -0
  125. data/src/nginx/src/os/unix/ngx_files.h +50 -1
  126. data/src/nginx/src/os/unix/ngx_freebsd.h +2 -1
  127. data/src/nginx/src/os/unix/ngx_freebsd_config.h +2 -0
  128. data/src/nginx/src/os/unix/ngx_freebsd_init.c +4 -3
  129. data/src/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +2 -2
  130. data/src/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +12 -6
  131. data/src/nginx/src/os/unix/ngx_gcc_atomic_sparc64.h +1 -1
  132. data/src/nginx/src/os/unix/ngx_linux_config.h +1 -0
  133. data/src/nginx/src/os/unix/ngx_linux_sendfile_chain.c +6 -4
  134. data/src/nginx/src/os/unix/ngx_os.h +0 -1
  135. data/src/nginx/src/os/unix/ngx_posix_config.h +3 -0
  136. data/src/nginx/src/os/unix/ngx_process.c +50 -11
  137. data/src/nginx/src/os/unix/ngx_process.h +1 -0
  138. data/src/nginx/src/os/unix/ngx_process_cycle.c +6 -15
  139. data/src/nginx/src/os/unix/ngx_readv_chain.c +8 -0
  140. data/src/nginx/src/os/unix/ngx_setaffinity.c +69 -0
  141. data/src/nginx/src/os/unix/ngx_setaffinity.h +23 -0
  142. data/src/nginx/src/os/unix/ngx_setproctitle.c +1 -1
  143. data/src/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  144. data/src/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +11 -3
  145. data/src/nginx/src/os/unix/ngx_writev_chain.c +7 -3
  146. metadata +7 -4
  147. data/src/nginx/src/http/modules/ngx_http_limit_zone_module.c +0 -553
@@ -28,6 +28,11 @@ struct ngx_listening_s {
28
28
  int backlog;
29
29
  int rcvbuf;
30
30
  int sndbuf;
31
+ #if (NGX_HAVE_KEEPALIVE_TUNABLE)
32
+ int keepidle;
33
+ int keepintvl;
34
+ int keepcnt;
35
+ #endif
31
36
 
32
37
  /* handler of accepted connection */
33
38
  ngx_connection_handler_pt handler;
@@ -61,6 +66,7 @@ struct ngx_listening_s {
61
66
  #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
62
67
  unsigned ipv6only:2;
63
68
  #endif
69
+ unsigned keepalive:2;
64
70
 
65
71
  #if (NGX_HAVE_DEFERRED_ACCEPT)
66
72
  unsigned deferred_accept:1;
@@ -91,5 +91,10 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
91
91
 
92
92
  void ngx_cpuinfo(void);
93
93
 
94
+ #if (NGX_HAVE_OPENAT)
95
+ #define NGX_DISABLE_SYMLINKS_OFF 0
96
+ #define NGX_DISABLE_SYMLINKS_ON 1
97
+ #define NGX_DISABLE_SYMLINKS_NOTOWNER 2
98
+ #endif
94
99
 
95
100
  #endif /* _NGX_CORE_H_INCLUDED_ */
@@ -953,7 +953,7 @@ ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
953
953
 
954
954
  #endif
955
955
 
956
- if (ngx_shmtx_create(&sp->mutex, (void *) &sp->lock, file) != NGX_OK) {
956
+ if (ngx_shmtx_create(&sp->mutex, &sp->lock, file) != NGX_OK) {
957
957
  return NGX_ERROR;
958
958
  }
959
959
 
@@ -86,7 +86,7 @@ typedef struct {
86
86
  int priority;
87
87
 
88
88
  ngx_uint_t cpu_affinity_n;
89
- u_long *cpu_affinity;
89
+ uint64_t *cpu_affinity;
90
90
 
91
91
  char *username;
92
92
  ngx_uid_t user;
@@ -124,7 +124,7 @@ ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig);
124
124
  void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user);
125
125
  char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last);
126
126
  ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
127
- u_long ngx_get_cpu_affinity(ngx_uint_t n);
127
+ uint64_t ngx_get_cpu_affinity(ngx_uint_t n);
128
128
  ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
129
129
  size_t size, void *tag);
130
130
 
@@ -808,7 +808,7 @@ failed:
808
808
  * reallocated if ctx->alloc is nonzero
809
809
  *
810
810
  * ctx->alloc - a size of data structure that is allocated at every level
811
- * and is initilialized by ctx->init_handler()
811
+ * and is initialized by ctx->init_handler()
812
812
  *
813
813
  * ctx->log - a log
814
814
  *
@@ -44,11 +44,7 @@ ngx_inet_addr(u_char *text, size_t len)
44
44
  return INADDR_NONE;
45
45
  }
46
46
 
47
- if (n != 3) {
48
- return INADDR_NONE;
49
- }
50
-
51
- if (octet < 256) {
47
+ if (n == 3 && octet < 256) {
52
48
  addr = (addr << 8) + octet;
53
49
  return htonl(addr);
54
50
  }
@@ -407,6 +403,10 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
407
403
 
408
404
  #if (NGX_HAVE_INET6)
409
405
  case AF_INET6:
406
+ if (shift > 128) {
407
+ return NGX_ERROR;
408
+ }
409
+
410
410
  addr = cidr->u.in6.addr.s6_addr;
411
411
  mask = cidr->u.in6.mask.s6_addr;
412
412
  rc = NGX_OK;
@@ -416,7 +416,7 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
416
416
  s = (shift > 8) ? 8 : shift;
417
417
  shift -= s;
418
418
 
419
- mask[i] = (u_char) (0 - (1 << (8 - s)));
419
+ mask[i] = (u_char) (0xffu << (8 - s));
420
420
 
421
421
  if (addr[i] != (addr[i] & mask[i])) {
422
422
  rc = NGX_DONE;
@@ -428,9 +428,12 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
428
428
  #endif
429
429
 
430
430
  default: /* AF_INET */
431
+ if (shift > 32) {
432
+ return NGX_ERROR;
433
+ }
431
434
 
432
435
  if (shift) {
433
- cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
436
+ cidr->u.in.mask = htonl((uint32_t) (0xffffffffu << (32 - shift)));
434
437
 
435
438
  } else {
436
439
  /* x86 compilers use a shl instruction that shifts by modulo 32 */
@@ -459,7 +462,7 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
459
462
  struct sockaddr_in6 *sin6;
460
463
 
461
464
  /*
462
- * prevent MSVC8 waring:
465
+ * prevent MSVC8 warning:
463
466
  * potentially uninitialized local variable 'inaddr6' used
464
467
  */
465
468
  ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
@@ -16,4 +16,4 @@
16
16
  uint32_t ngx_murmur_hash2(u_char *data, size_t len);
17
17
 
18
18
 
19
- #endif /* _NGX_CRC_H_INCLUDED_ */
19
+ #endif /* _NGX_MURMURHASH_H_INCLUDED_ */
@@ -22,8 +22,17 @@
22
22
 
23
23
 
24
24
  static void ngx_open_file_cache_cleanup(void *data);
25
- static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of,
26
- ngx_log_t *log);
25
+ #if (NGX_HAVE_OPENAT)
26
+ static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
27
+ ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log);
28
+ #endif
29
+ static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
30
+ ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
31
+ ngx_int_t access, ngx_log_t *log);
32
+ static ngx_int_t ngx_file_info_wrapper(ngx_str_t *name,
33
+ ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_log_t *log);
34
+ static ngx_int_t ngx_open_and_stat_file(ngx_str_t *name,
35
+ ngx_open_file_info_t *of, ngx_log_t *log);
27
36
  static void ngx_open_file_add_event(ngx_open_file_cache_t *cache,
28
37
  ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log);
29
38
  static void ngx_open_file_cleanup(void *data);
@@ -147,9 +156,9 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
147
156
 
148
157
  if (of->test_only) {
149
158
 
150
- if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
151
- of->err = ngx_errno;
152
- of->failed = ngx_file_info_n;
159
+ if (ngx_file_info_wrapper(name, of, &fi, pool->log)
160
+ == NGX_FILE_ERROR)
161
+ {
153
162
  return NGX_ERROR;
154
163
  }
155
164
 
@@ -170,7 +179,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
170
179
  return NGX_ERROR;
171
180
  }
172
181
 
173
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
182
+ rc = ngx_open_and_stat_file(name, of, pool->log);
174
183
 
175
184
  if (rc == NGX_OK && !of->is_dir) {
176
185
  cln->handler = ngx_pool_cleanup_file;
@@ -205,7 +214,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
205
214
 
206
215
  /* file was not used often enough to keep open */
207
216
 
208
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
217
+ rc = ngx_open_and_stat_file(name, of, pool->log);
209
218
 
210
219
  if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
211
220
  goto failed;
@@ -217,7 +226,12 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
217
226
  if (file->use_event
218
227
  || (file->event == NULL
219
228
  && (of->uniq == 0 || of->uniq == file->uniq)
220
- && now - file->created < of->valid))
229
+ && now - file->created < of->valid
230
+ #if (NGX_HAVE_OPENAT)
231
+ && of->disable_symlinks == file->disable_symlinks
232
+ && of->disable_symlinks_from == file->disable_symlinks_from
233
+ #endif
234
+ ))
221
235
  {
222
236
  if (file->err == 0) {
223
237
 
@@ -239,7 +253,12 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
239
253
 
240
254
  } else {
241
255
  of->err = file->err;
256
+ #if (NGX_HAVE_OPENAT)
257
+ of->failed = file->disable_symlinks ? ngx_openat_file_n
258
+ : ngx_open_file_n;
259
+ #else
242
260
  of->failed = ngx_open_file_n;
261
+ #endif
243
262
  }
244
263
 
245
264
  goto found;
@@ -263,7 +282,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
263
282
  of->fd = file->fd;
264
283
  of->uniq = file->uniq;
265
284
 
266
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
285
+ rc = ngx_open_and_stat_file(name, of, pool->log);
267
286
 
268
287
  if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
269
288
  goto failed;
@@ -311,8 +330,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
311
330
 
312
331
  if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
313
332
  ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
314
- ngx_close_file_n " \"%s\" failed",
315
- name->data);
333
+ ngx_close_file_n " \"%V\" failed", name);
316
334
  }
317
335
 
318
336
  goto add_event;
@@ -329,7 +347,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
329
347
 
330
348
  /* not found */
331
349
 
332
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
350
+ rc = ngx_open_and_stat_file(name, of, pool->log);
333
351
 
334
352
  if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
335
353
  goto failed;
@@ -376,6 +394,10 @@ update:
376
394
 
377
395
  file->fd = of->fd;
378
396
  file->err = of->err;
397
+ #if (NGX_HAVE_OPENAT)
398
+ file->disable_symlinks = of->disable_symlinks;
399
+ file->disable_symlinks_from = of->disable_symlinks_from;
400
+ #endif
379
401
 
380
402
  if (of->err == 0) {
381
403
  file->uniq = of->uniq;
@@ -452,7 +474,7 @@ failed:
452
474
  if (of->fd != NGX_INVALID_FILE) {
453
475
  if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
454
476
  ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
455
- ngx_close_file_n " \"%s\" failed", name->data);
477
+ ngx_close_file_n " \"%V\" failed", name);
456
478
  }
457
479
  }
458
480
 
@@ -460,17 +482,306 @@ failed:
460
482
  }
461
483
 
462
484
 
485
+ #if (NGX_HAVE_OPENAT)
486
+
487
+ static ngx_fd_t
488
+ ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
489
+ ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
490
+ {
491
+ ngx_fd_t fd;
492
+ ngx_err_t err;
493
+ ngx_file_info_t fi, atfi;
494
+
495
+ /*
496
+ * To allow symlinks with the same owner, use openat() (followed
497
+ * by fstat()) and fstatat(AT_SYMLINK_NOFOLLOW), and then compare
498
+ * uids between fstat() and fstatat().
499
+ *
500
+ * As there is a race between openat() and fstatat() we don't
501
+ * know if openat() in fact opened symlink or not. Therefore,
502
+ * we have to compare uids even if fstatat() reports the opened
503
+ * component isn't a symlink (as we don't know whether it was
504
+ * symlink during openat() or not).
505
+ */
506
+
507
+ fd = ngx_openat_file(at_fd, name, mode, create, access);
508
+
509
+ if (fd == NGX_INVALID_FILE) {
510
+ return NGX_INVALID_FILE;
511
+ }
512
+
513
+ if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW)
514
+ == NGX_FILE_ERROR)
515
+ {
516
+ err = ngx_errno;
517
+ goto failed;
518
+ }
519
+
520
+ if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
521
+ err = ngx_errno;
522
+ goto failed;
523
+ }
524
+
525
+ if (fi.st_uid != atfi.st_uid) {
526
+ err = NGX_ELOOP;
527
+ goto failed;
528
+ }
529
+
530
+ return fd;
531
+
532
+ failed:
533
+
534
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
535
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
536
+ ngx_close_file_n " \"%V\" failed", name);
537
+ }
538
+
539
+ ngx_set_errno(err);
540
+
541
+ return NGX_INVALID_FILE;
542
+ }
543
+
544
+ #endif
545
+
546
+
547
+ static ngx_fd_t
548
+ ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
549
+ ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
550
+ {
551
+ ngx_fd_t fd;
552
+
553
+ #if !(NGX_HAVE_OPENAT)
554
+
555
+ fd = ngx_open_file(name->data, mode, create, access);
556
+
557
+ if (fd == NGX_INVALID_FILE) {
558
+ of->err = ngx_errno;
559
+ of->failed = ngx_open_file_n;
560
+ return NGX_INVALID_FILE;
561
+ }
562
+
563
+ return fd;
564
+
565
+ #else
566
+
567
+ u_char *p, *cp, *end;
568
+ ngx_fd_t at_fd;
569
+ ngx_str_t at_name;
570
+
571
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
572
+ fd = ngx_open_file(name->data, mode, create, access);
573
+
574
+ if (fd == NGX_INVALID_FILE) {
575
+ of->err = ngx_errno;
576
+ of->failed = ngx_open_file_n;
577
+ return NGX_INVALID_FILE;
578
+ }
579
+
580
+ return fd;
581
+ }
582
+
583
+ p = name->data;
584
+ end = p + name->len;
585
+
586
+ at_name = *name;
587
+
588
+ if (of->disable_symlinks_from) {
589
+
590
+ cp = p + of->disable_symlinks_from;
591
+
592
+ *cp = '\0';
593
+
594
+ at_fd = ngx_open_file(p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
595
+ NGX_FILE_OPEN, 0);
596
+
597
+ *cp = '/';
598
+
599
+ if (at_fd == NGX_INVALID_FILE) {
600
+ of->err = ngx_errno;
601
+ of->failed = ngx_open_file_n;
602
+ return NGX_INVALID_FILE;
603
+ }
604
+
605
+ at_name.len = of->disable_symlinks_from;
606
+ p = cp + 1;
607
+
608
+ } else if (*p == '/') {
609
+
610
+ at_fd = ngx_open_file("/",
611
+ NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
612
+ NGX_FILE_OPEN, 0);
613
+
614
+ if (at_fd == NGX_INVALID_FILE) {
615
+ of->err = ngx_errno;
616
+ of->failed = ngx_openat_file_n;
617
+ return NGX_INVALID_FILE;
618
+ }
619
+
620
+ at_name.len = 1;
621
+ p++;
622
+
623
+ } else {
624
+ at_fd = NGX_AT_FDCWD;
625
+ }
626
+
627
+ for ( ;; ) {
628
+ cp = ngx_strlchr(p, end, '/');
629
+ if (cp == NULL) {
630
+ break;
631
+ }
632
+
633
+ if (cp == p) {
634
+ p++;
635
+ continue;
636
+ }
637
+
638
+ *cp = '\0';
639
+
640
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
641
+ fd = ngx_openat_file_owner(at_fd, p,
642
+ NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
643
+ NGX_FILE_OPEN, 0, log);
644
+
645
+ } else {
646
+ fd = ngx_openat_file(at_fd, p,
647
+ NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
648
+ NGX_FILE_OPEN, 0);
649
+ }
650
+
651
+ *cp = '/';
652
+
653
+ if (fd == NGX_INVALID_FILE) {
654
+ of->err = ngx_errno;
655
+ of->failed = ngx_openat_file_n;
656
+ goto failed;
657
+ }
658
+
659
+ if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
660
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
661
+ ngx_close_file_n " \"%V\" failed", &at_name);
662
+ }
663
+
664
+ p = cp + 1;
665
+ at_fd = fd;
666
+ at_name.len = cp - at_name.data;
667
+ }
668
+
669
+ if (p == end) {
670
+
671
+ /*
672
+ * If pathname ends with a trailing slash, assume the last path
673
+ * component is a directory and reopen it with requested flags;
674
+ * if not, fail with ENOTDIR as per POSIX.
675
+ *
676
+ * We cannot rely on O_DIRECTORY in the loop above to check
677
+ * that the last path component is a directory because
678
+ * O_DIRECTORY doesn't work on FreeBSD 8. Fortunately, by
679
+ * reopening a directory, we don't depend on it at all.
680
+ */
681
+
682
+ fd = ngx_openat_file(at_fd, ".", mode, create, access);
683
+ goto done;
684
+ }
685
+
686
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER
687
+ && !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE)))
688
+ {
689
+ fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
690
+
691
+ } else {
692
+ fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
693
+ }
694
+
695
+ done:
696
+
697
+ if (fd == NGX_INVALID_FILE) {
698
+ of->err = ngx_errno;
699
+ of->failed = ngx_openat_file_n;
700
+ }
701
+
702
+ failed:
703
+
704
+ if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
705
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
706
+ ngx_close_file_n " \"%V\" failed", &at_name);
707
+ }
708
+
709
+ return fd;
710
+ #endif
711
+ }
712
+
713
+
463
714
  static ngx_int_t
464
- ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
715
+ ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
716
+ ngx_file_info_t *fi, ngx_log_t *log)
717
+ {
718
+ ngx_int_t rc;
719
+
720
+ #if !(NGX_HAVE_OPENAT)
721
+
722
+ rc = ngx_file_info(name->data, fi);
723
+
724
+ if (rc == NGX_FILE_ERROR) {
725
+ of->err = ngx_errno;
726
+ of->failed = ngx_file_info_n;
727
+ return NGX_FILE_ERROR;
728
+ }
729
+
730
+ return rc;
731
+
732
+ #else
733
+
734
+ ngx_fd_t fd;
735
+
736
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
737
+
738
+ rc = ngx_file_info(name->data, fi);
739
+
740
+ if (rc == NGX_FILE_ERROR) {
741
+ of->err = ngx_errno;
742
+ of->failed = ngx_file_info_n;
743
+ return NGX_FILE_ERROR;
744
+ }
745
+
746
+ return rc;
747
+ }
748
+
749
+ fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
750
+ NGX_FILE_OPEN, 0, log);
751
+
752
+ if (fd == NGX_INVALID_FILE) {
753
+ return NGX_FILE_ERROR;
754
+ }
755
+
756
+ rc = ngx_fd_info(fd, fi);
757
+
758
+ if (rc == NGX_FILE_ERROR) {
759
+ of->err = ngx_errno;
760
+ of->failed = ngx_fd_info_n;
761
+ }
762
+
763
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
764
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
765
+ ngx_close_file_n " \"%V\" failed", name);
766
+ }
767
+
768
+ return rc;
769
+ #endif
770
+ }
771
+
772
+
773
+ static ngx_int_t
774
+ ngx_open_and_stat_file(ngx_str_t *name, ngx_open_file_info_t *of,
775
+ ngx_log_t *log)
465
776
  {
466
777
  ngx_fd_t fd;
467
778
  ngx_file_info_t fi;
468
779
 
469
780
  if (of->fd != NGX_INVALID_FILE) {
470
781
 
471
- if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) {
472
- of->failed = ngx_file_info_n;
473
- goto failed;
782
+ if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
783
+ of->fd = NGX_INVALID_FILE;
784
+ return NGX_ERROR;
474
785
  }
475
786
 
476
787
  if (of->uniq == ngx_file_uniq(&fi)) {
@@ -479,9 +790,9 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
479
790
 
480
791
  } else if (of->test_dir) {
481
792
 
482
- if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) {
483
- of->failed = ngx_file_info_n;
484
- goto failed;
793
+ if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
794
+ of->fd = NGX_INVALID_FILE;
795
+ return NGX_ERROR;
485
796
  }
486
797
 
487
798
  if (ngx_is_dir(&fi)) {
@@ -496,26 +807,27 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
496
807
  * This flag has no effect on a regular files.
497
808
  */
498
809
 
499
- fd = ngx_open_file(name, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
500
- NGX_FILE_OPEN, 0);
810
+ fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
811
+ NGX_FILE_OPEN, 0, log);
501
812
 
502
813
  } else {
503
- fd = ngx_open_file(name, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN,
504
- NGX_FILE_DEFAULT_ACCESS);
814
+ fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND,
815
+ NGX_FILE_CREATE_OR_OPEN,
816
+ NGX_FILE_DEFAULT_ACCESS, log);
505
817
  }
506
818
 
507
819
  if (fd == NGX_INVALID_FILE) {
508
- of->failed = ngx_open_file_n;
509
- goto failed;
820
+ of->fd = NGX_INVALID_FILE;
821
+ return NGX_ERROR;
510
822
  }
511
823
 
512
824
  if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
513
825
  ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
514
- ngx_fd_info_n " \"%s\" failed", name);
826
+ ngx_fd_info_n " \"%V\" failed", name);
515
827
 
516
828
  if (ngx_close_file(fd) == NGX_FILE_ERROR) {
517
829
  ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
518
- ngx_close_file_n " \"%s\" failed", name);
830
+ ngx_close_file_n " \"%V\" failed", name);
519
831
  }
520
832
 
521
833
  of->fd = NGX_INVALID_FILE;
@@ -526,7 +838,7 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
526
838
  if (ngx_is_dir(&fi)) {
527
839
  if (ngx_close_file(fd) == NGX_FILE_ERROR) {
528
840
  ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
529
- ngx_close_file_n " \"%s\" failed", name);
841
+ ngx_close_file_n " \"%V\" failed", name);
530
842
  }
531
843
 
532
844
  of->fd = NGX_INVALID_FILE;
@@ -537,14 +849,14 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
537
849
  if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) {
538
850
  if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) {
539
851
  ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
540
- ngx_read_ahead_n " \"%s\" failed", name);
852
+ ngx_read_ahead_n " \"%V\" failed", name);
541
853
  }
542
854
  }
543
855
 
544
856
  if (of->directio <= ngx_file_size(&fi)) {
545
857
  if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
546
858
  ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
547
- ngx_directio_on_n " \"%s\" failed", name);
859
+ ngx_directio_on_n " \"%V\" failed", name);
548
860
 
549
861
  } else {
550
862
  of->is_directio = 1;
@@ -564,13 +876,6 @@ done:
564
876
  of->is_exec = ngx_is_exec(&fi);
565
877
 
566
878
  return NGX_OK;
567
-
568
- failed:
569
-
570
- of->fd = NGX_INVALID_FILE;
571
- of->err = ngx_errno;
572
-
573
- return NGX_ERROR;
574
879
  }
575
880
 
576
881