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