Mercurial > hg > nginx-vendor-0-7
comparison src/core/ngx_file.c @ 502:89dc5654117c NGINX_0_7_63
nginx 0.7.63
*) Security: now "/../" are disabled in "Destination" request header
line.
*) Change: minimum supported OpenSSL version is 0.9.7.
*) Change: the "ask" parameter of the "ssl_verify_client" directive was
changed to the "optional" parameter and now it checks a client
certificate if it was offered.
Thanks to Brice Figureau.
*) Feature: now the "-V" switch shows TLS SNI support.
*) Feature: the $ssl_client_verify variable.
Thanks to Brice Figureau.
*) Feature: the "ssl_crl" directive.
Thanks to Brice Figureau.
*) Bugfix: the $ssl_client_cert variable usage corrupted memory; the
bug had appeared in 0.7.7.
Thanks to Sergey Zhuravlev.
*) Feature: now the start cache loader runs in a separate process; this
should improve large caches handling.
*) Feature: now temporary files and permanent storage area may reside
at different file systems.
*) Bugfix: nginx counted incorrectly disk cache size.
*) Change: now directive "gzip_disable msie6" does not disable gzipping
for MSIE 6.0 SV1.
*) Bugfix: nginx always added "Vary: Accept-Encoding" response header
line, if both "gzip_static" and "gzip_vary" were on.
*) Feature: the "proxy" parameter of the "geo" directive.
*) Feature: the ngx_http_geoip_module.
*) Feature: the "limit_rate_after" directive.
Thanks to Ivan Debnar.
*) Feature: the "limit_req_log_level" and "limit_conn_log_level"
directives.
*) Bugfix: now "limit_req" directive conforms to the leaky bucket
algorithm.
Thanks to Maxim Dounin.
*) Bugfix: in ngx_http_limit_req_module.
Thanks to Maxim Dounin.
*) Bugfix: now nginx allows underscores in a request method.
*) Bugfix: "proxy_pass_header" and "fastcgi_pass_header" directives did
not pass to a client the "X-Accel-Redirect", "X-Accel-Limit-Rate",
"X-Accel-Buffering", and "X-Accel-Charset" lines from backend
response header.
Thanks to Maxim Dounin.
*) Bugfix: in handling "Last-Modified" and "Accept-Ranges" backend
response header lines; the bug had appeared in 0.7.44.
Thanks to Maxim Dounin.
*) Feature: the "image_filter_transparency" directive.
*) Feature: the "image_filter" directive supports variables for setting
size.
*) Bugfix: in PNG alpha-channel support in the
ngx_http_image_filter_module.
*) Bugfix: in transparency support in the ngx_http_image_filter_module.
*) Feature: now several "perl_modules" directives may be used.
*) Bugfix: ngx_http_perl_module responses did not work in subrequests.
*) Bugfix: nginx sent '\0' in a "Location" response header line on
MKCOL request.
Thanks to Xie Zhenye.
*) Bugfix: an "error_page" directive did not redirect a 413 error; the
bug had appeared in 0.6.10.
*) Bugfix: in memory allocation error handling.
Thanks to Maxim Dounin and Kirill A. Korinskiy.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 26 Oct 2009 00:00:00 +0300 |
parents | 116d5de7cbb6 |
children | b9fdcaf2062b |
comparison
equal
deleted
inserted
replaced
501:dc87c92181c7 | 502:89dc5654117c |
---|---|
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 | 9 |
10 | 10 |
11 static ngx_atomic_uint_t ngx_temp_number; | 11 static ngx_atomic_t temp_number = 0; |
12 static ngx_atomic_uint_t ngx_random_number; | 12 ngx_atomic_t *ngx_temp_number = &temp_number; |
13 ngx_atomic_int_t ngx_random_number = 123456; | |
13 | 14 |
14 | 15 |
15 ssize_t | 16 ssize_t |
16 ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain) | 17 ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain) |
17 { | 18 { |
97 if (err == NGX_EEXIST) { | 98 if (err == NGX_EEXIST) { |
98 n = (uint32_t) ngx_next_temp_number(1); | 99 n = (uint32_t) ngx_next_temp_number(1); |
99 continue; | 100 continue; |
100 } | 101 } |
101 | 102 |
102 if ((path->level[0] == 0) | 103 if ((path->level[0] == 0) || (err != NGX_ENOPATH)) { |
103 || (err != NGX_ENOENT | |
104 #if (NGX_WIN32) | |
105 && err != NGX_ENOTDIR | |
106 #endif | |
107 )) | |
108 { | |
109 ngx_log_error(NGX_LOG_CRIT, file->log, err, | 104 ngx_log_error(NGX_LOG_CRIT, file->log, err, |
110 ngx_open_tempfile_n " \"%s\" failed", | 105 ngx_open_tempfile_n " \"%s\" failed", |
111 file->name.data); | 106 file->name.data); |
112 return NGX_ERROR; | 107 return NGX_ERROR; |
113 } | 108 } |
209 | 204 |
210 return 0; | 205 return 0; |
211 } | 206 } |
212 | 207 |
213 | 208 |
214 void | |
215 ngx_init_temp_number(void) | |
216 { | |
217 ngx_temp_number = 0; | |
218 ngx_random_number = 123456; | |
219 } | |
220 | |
221 | |
222 ngx_atomic_uint_t | 209 ngx_atomic_uint_t |
223 ngx_next_temp_number(ngx_uint_t collision) | 210 ngx_next_temp_number(ngx_uint_t collision) |
224 { | 211 { |
225 if (collision) { | 212 ngx_atomic_uint_t n, add; |
226 ngx_temp_number += ngx_random_number; | 213 |
227 } | 214 add = collision ? ngx_random_number : 1; |
228 | 215 |
229 return ngx_temp_number++; | 216 n = ngx_atomic_fetch_add(ngx_temp_number, add); |
217 | |
218 return n + add; | |
230 } | 219 } |
231 | 220 |
232 | 221 |
233 char * | 222 char * |
234 ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 223 ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
262 if (ngx_conf_full_name(cf->cycle, &path->name, 0) != NGX_OK) { | 251 if (ngx_conf_full_name(cf->cycle, &path->name, 0) != NGX_OK) { |
263 return NULL; | 252 return NULL; |
264 } | 253 } |
265 | 254 |
266 path->len = 0; | 255 path->len = 0; |
267 path->manager = (ngx_path_manager_pt) cmd->post; | 256 path->manager = NULL; |
257 path->loader = NULL; | |
268 path->conf_file = cf->conf_file->file.name.data; | 258 path->conf_file = cf->conf_file->file.name.data; |
269 path->line = cf->conf_file->line; | 259 path->line = cf->conf_file->line; |
270 | 260 |
271 for (i = 0, n = 2; n < cf->args->nelts; i++, n++) { | 261 for (i = 0, n = 2; n < cf->args->nelts; i++, n++) { |
272 level = ngx_atoi(value[n].data, value[n].len); | 262 level = ngx_atoi(value[n].data, value[n].len); |
323 (*path)->len = init->level[0] + (init->level[0] ? 1 : 0) | 313 (*path)->len = init->level[0] + (init->level[0] ? 1 : 0) |
324 + init->level[1] + (init->level[1] ? 1 : 0) | 314 + init->level[1] + (init->level[1] ? 1 : 0) |
325 + init->level[2] + (init->level[2] ? 1 : 0); | 315 + init->level[2] + (init->level[2] ? 1 : 0); |
326 | 316 |
327 (*path)->manager = NULL; | 317 (*path)->manager = NULL; |
318 (*path)->loader = NULL; | |
328 (*path)->conf_file = NULL; | 319 (*path)->conf_file = NULL; |
329 | 320 |
330 if (ngx_add_path(cf, path) != NGX_OK) { | 321 if (ngx_add_path(cf, path) != NGX_OK) { |
331 return NGX_CONF_ERROR; | 322 return NGX_CONF_ERROR; |
332 } | 323 } |
526 | 517 |
527 | 518 |
528 ngx_int_t | 519 ngx_int_t |
529 ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) | 520 ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) |
530 { | 521 { |
531 ngx_err_t err; | 522 u_char *name; |
523 ngx_err_t err; | |
524 ngx_copy_file_t cf; | |
532 | 525 |
533 #if !(NGX_WIN32) | 526 #if !(NGX_WIN32) |
534 | 527 |
535 if (ext->access) { | 528 if (ext->access) { |
536 if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) { | 529 if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) { |
556 return NGX_OK; | 549 return NGX_OK; |
557 } | 550 } |
558 | 551 |
559 err = ngx_errno; | 552 err = ngx_errno; |
560 | 553 |
561 if (err | 554 if (err == NGX_ENOPATH) { |
562 #if (NGX_WIN32) | 555 |
563 == ERROR_PATH_NOT_FOUND | |
564 #else | |
565 == NGX_ENOENT | |
566 #endif | |
567 ) | |
568 { | |
569 if (!ext->create_path) { | 556 if (!ext->create_path) { |
570 goto failed; | 557 goto failed; |
571 } | 558 } |
572 | 559 |
573 err = ngx_create_full_path(to->data, ngx_dir_access(ext->path_access)); | 560 err = ngx_create_full_path(to->data, ngx_dir_access(ext->path_access)); |
582 if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { | 569 if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { |
583 return NGX_OK; | 570 return NGX_OK; |
584 } | 571 } |
585 | 572 |
586 err = ngx_errno; | 573 err = ngx_errno; |
587 goto failed; | |
588 } | 574 } |
589 | 575 |
590 #if (NGX_WIN32) | 576 #if (NGX_WIN32) |
591 | 577 |
592 if (err == NGX_EEXIST) { | 578 if (err == NGX_EEXIST) { |
602 err = 0; | 588 err = 0; |
603 } | 589 } |
604 } | 590 } |
605 | 591 |
606 #endif | 592 #endif |
593 | |
594 if (err == NGX_EXDEV) { | |
595 | |
596 cf.size = -1; | |
597 cf.buf_size = 0; | |
598 cf.access = ext->access; | |
599 cf.time = ext->time; | |
600 cf.log = ext->log; | |
601 | |
602 name = ngx_alloc(to->len + 1 + 10 + 1, ext->log); | |
603 if (name == NULL) { | |
604 return NGX_ERROR; | |
605 } | |
606 | |
607 (void) ngx_sprintf(name, "%*s.%010uD%Z", to->len, to->data, | |
608 (uint32_t) ngx_next_temp_number(0)); | |
609 | |
610 if (ngx_copy_file(src->data, name, &cf) == NGX_OK) { | |
611 | |
612 if (ngx_rename_file(name, to->data) != NGX_FILE_ERROR) { | |
613 ngx_free(name); | |
614 | |
615 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { | |
616 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, | |
617 ngx_delete_file_n " \"%s\" failed", | |
618 src->data); | |
619 return NGX_ERROR; | |
620 } | |
621 | |
622 return NGX_OK; | |
623 } | |
624 | |
625 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, | |
626 ngx_rename_file_n " \"%s\" to \"%s\" failed", | |
627 name, to->data); | |
628 | |
629 if (ngx_delete_file(name) == NGX_FILE_ERROR) { | |
630 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, | |
631 ngx_delete_file_n " \"%s\" failed", name); | |
632 | |
633 } | |
634 } | |
635 | |
636 ngx_free(name); | |
637 | |
638 err = 0; | |
639 } | |
607 | 640 |
608 failed: | 641 failed: |
609 | 642 |
610 if (ext->delete_file) { | 643 if (ext->delete_file) { |
611 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { | 644 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { |
612 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, | 645 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, |
613 ngx_delete_file_n " \"%s\" failed", src->data); | 646 ngx_delete_file_n " \"%s\" failed", src->data); |
614 } | 647 } |
615 } | 648 } |
616 | 649 |
617 if (err && ext->log_rename_error) { | 650 if (err) { |
618 ngx_log_error(NGX_LOG_CRIT, ext->log, err, | 651 ngx_log_error(NGX_LOG_CRIT, ext->log, err, |
619 ngx_rename_file_n " \"%s\" to \"%s\" failed", | 652 ngx_rename_file_n " \"%s\" to \"%s\" failed", |
620 src->data, to->data); | 653 src->data, to->data); |
621 } | 654 } |
622 | 655 |
623 ext->rename_error = err; | |
624 | |
625 return NGX_ERROR; | 656 return NGX_ERROR; |
657 } | |
658 | |
659 | |
660 ngx_int_t | |
661 ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf) | |
662 { | |
663 char *buf; | |
664 off_t size; | |
665 size_t len; | |
666 ssize_t n; | |
667 ngx_fd_t fd, nfd; | |
668 ngx_int_t rc; | |
669 ngx_file_info_t fi; | |
670 | |
671 rc = NGX_ERROR; | |
672 buf = NULL; | |
673 nfd = NGX_INVALID_FILE; | |
674 | |
675 fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); | |
676 | |
677 if (fd == NGX_INVALID_FILE) { | |
678 ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, | |
679 ngx_open_file_n " \"%s\" failed", from); | |
680 goto failed; | |
681 } | |
682 | |
683 if (cf->size != -1) { | |
684 size = cf->size; | |
685 | |
686 } else { | |
687 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { | |
688 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
689 ngx_fd_info_n " \"%s\" failed", from); | |
690 | |
691 goto failed; | |
692 } | |
693 | |
694 size = ngx_file_size(&fi); | |
695 } | |
696 | |
697 len = cf->buf_size ? cf->buf_size : 65536; | |
698 | |
699 if ((off_t) len > size) { | |
700 len = (size_t) size; | |
701 } | |
702 | |
703 buf = ngx_alloc(len, cf->log); | |
704 if (buf == NULL) { | |
705 goto failed; | |
706 } | |
707 | |
708 nfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, | |
709 cf->access); | |
710 | |
711 if (nfd == NGX_INVALID_FILE) { | |
712 ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, | |
713 ngx_open_file_n " \"%s\" failed", to); | |
714 goto failed; | |
715 } | |
716 | |
717 while (size > 0) { | |
718 | |
719 if ((off_t) len > size) { | |
720 len = (size_t) size; | |
721 } | |
722 | |
723 n = ngx_read_fd(fd, buf, len); | |
724 | |
725 if (n == NGX_FILE_ERROR) { | |
726 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
727 ngx_read_fd_n " \"%s\" failed", from); | |
728 goto failed; | |
729 } | |
730 | |
731 if ((size_t) n != len) { | |
732 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
733 ngx_read_fd_n " has read only %z of %uz from %s", | |
734 n, size, from); | |
735 goto failed; | |
736 } | |
737 | |
738 n = ngx_write_fd(nfd, buf, len); | |
739 | |
740 if (n == NGX_FILE_ERROR) { | |
741 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
742 ngx_write_fd_n " \"%s\" failed", to); | |
743 goto failed; | |
744 } | |
745 | |
746 if ((size_t) n != len) { | |
747 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
748 ngx_write_fd_n " has written only %z of %uz to %s", | |
749 n, size, to); | |
750 goto failed; | |
751 } | |
752 | |
753 size -= n; | |
754 } | |
755 | |
756 if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) { | |
757 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
758 ngx_set_file_time_n " \"%s\" failed", to); | |
759 goto failed; | |
760 } | |
761 | |
762 rc = NGX_OK; | |
763 | |
764 failed: | |
765 | |
766 if (nfd != NGX_INVALID_FILE) { | |
767 if (ngx_close_file(nfd) == NGX_FILE_ERROR) { | |
768 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
769 ngx_close_file_n " \"%s\" failed", to); | |
770 } | |
771 } | |
772 | |
773 if (fd != NGX_INVALID_FILE) { | |
774 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
775 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
776 ngx_close_file_n " \"%s\" failed", from); | |
777 } | |
778 } | |
779 | |
780 if (buf) { | |
781 ngx_free(buf); | |
782 } | |
783 | |
784 return rc; | |
626 } | 785 } |
627 | 786 |
628 | 787 |
629 /* | 788 /* |
630 * ctx->init_handler() - see ctx->alloc | 789 * ctx->init_handler() - see ctx->alloc |