Mercurial > hg > nginx
comparison src/core/ngx_file.c @ 3024:8101d9101ed8
allow cross device temporary files atomic copying:
*) ngx_copy_file()
*) delete ngx_ext_rename_file_t.log_rename_error and .rename_error fields
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 12 Aug 2009 12:05:33 +0000 |
parents | 7d5501988fe3 |
children | 3e1b653fd22f |
comparison
equal
deleted
inserted
replaced
3023:7d5501988fe3 | 3024:8101d9101ed8 |
---|---|
522 | 522 |
523 | 523 |
524 ngx_int_t | 524 ngx_int_t |
525 ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) | 525 ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) |
526 { | 526 { |
527 ngx_err_t err; | 527 u_char *name; |
528 ngx_err_t err; | |
529 ngx_copy_file_t cf; | |
528 | 530 |
529 #if !(NGX_WIN32) | 531 #if !(NGX_WIN32) |
530 | 532 |
531 if (ext->access) { | 533 if (ext->access) { |
532 if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) { | 534 if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) { |
593 } | 595 } |
594 } | 596 } |
595 | 597 |
596 #endif | 598 #endif |
597 | 599 |
600 if (err == NGX_EXDEV) { | |
601 | |
602 cf.size = -1; | |
603 cf.buf_size = 0; | |
604 cf.access = ext->access; | |
605 cf.time = ext->time; | |
606 cf.log = ext->log; | |
607 | |
608 name = ngx_alloc(to->len + 1 + 10, ext->log); | |
609 if (name == NULL) { | |
610 return NGX_ERROR; | |
611 } | |
612 | |
613 (void) ngx_sprintf(name, "%*s.%010uD%Z", to->len - 1, to->data, | |
614 (uint32_t) ngx_next_temp_number(0)); | |
615 | |
616 if (ngx_copy_file(src->data, name, &cf) == NGX_OK) { | |
617 | |
618 if (ngx_rename_file(name, to->data) == NGX_FILE_ERROR) { | |
619 ngx_free(name); | |
620 goto failed; | |
621 } | |
622 | |
623 ngx_free(name); | |
624 | |
625 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { | |
626 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, | |
627 ngx_delete_file_n " \"%s\" failed", src->data); | |
628 | |
629 return NGX_ERROR; | |
630 } | |
631 | |
632 return NGX_OK; | |
633 } | |
634 | |
635 ngx_free(name); | |
636 } | |
637 | |
598 failed: | 638 failed: |
599 | 639 |
600 if (ext->delete_file) { | 640 if (ext->delete_file) { |
601 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { | 641 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { |
602 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, | 642 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, |
603 ngx_delete_file_n " \"%s\" failed", src->data); | 643 ngx_delete_file_n " \"%s\" failed", src->data); |
604 } | 644 } |
605 } | 645 } |
606 | 646 |
607 if (err && ext->log_rename_error) { | 647 if (err) { |
608 ngx_log_error(NGX_LOG_CRIT, ext->log, err, | 648 ngx_log_error(NGX_LOG_CRIT, ext->log, err, |
609 ngx_rename_file_n " \"%s\" to \"%s\" failed", | 649 ngx_rename_file_n " \"%s\" to \"%s\" failed", |
610 src->data, to->data); | 650 src->data, to->data); |
611 } | 651 } |
612 | 652 |
613 ext->rename_error = err; | |
614 | |
615 return NGX_ERROR; | 653 return NGX_ERROR; |
654 } | |
655 | |
656 | |
657 ngx_int_t | |
658 ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf) | |
659 { | |
660 char *buf; | |
661 off_t size; | |
662 size_t len; | |
663 ssize_t n; | |
664 ngx_fd_t fd, nfd; | |
665 ngx_int_t rc; | |
666 ngx_file_info_t fi; | |
667 | |
668 rc = NGX_ERROR; | |
669 buf = NULL; | |
670 nfd = NGX_INVALID_FILE; | |
671 | |
672 fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); | |
673 | |
674 if (fd == NGX_INVALID_FILE) { | |
675 ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, | |
676 ngx_open_file_n " \"%s\" failed", from); | |
677 goto failed; | |
678 } | |
679 | |
680 if (cf->size != -1) { | |
681 size = cf->size; | |
682 | |
683 } else { | |
684 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { | |
685 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
686 ngx_fd_info_n " \"%s\" failed", from); | |
687 | |
688 goto failed; | |
689 } | |
690 | |
691 size = ngx_file_size(&fi); | |
692 } | |
693 | |
694 len = cf->buf_size ? cf->buf_size : 65536; | |
695 | |
696 if (len > size) { | |
697 len = (size_t) size; | |
698 } | |
699 | |
700 buf = ngx_alloc(len, cf->log); | |
701 if (buf == NULL) { | |
702 goto failed; | |
703 } | |
704 | |
705 nfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, | |
706 cf->access); | |
707 | |
708 if (nfd == NGX_INVALID_FILE) { | |
709 ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, | |
710 ngx_open_file_n " \"%s\" failed", to); | |
711 goto failed; | |
712 } | |
713 | |
714 while (size > 0) { | |
715 | |
716 if (len > size) { | |
717 len = (size_t) size; | |
718 } | |
719 | |
720 n = ngx_read_fd(fd, buf, len); | |
721 | |
722 if (n == NGX_FILE_ERROR) { | |
723 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
724 ngx_read_fd_n " \"%s\" failed", from); | |
725 goto failed; | |
726 } | |
727 | |
728 if ((size_t) n != len) { | |
729 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
730 ngx_read_fd_n " has read only %z of %uz from %s", | |
731 n, size, from); | |
732 goto failed; | |
733 } | |
734 | |
735 n = ngx_write_fd(nfd, buf, len); | |
736 | |
737 if (n == NGX_FILE_ERROR) { | |
738 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
739 ngx_write_fd_n " \"%s\" failed", to); | |
740 goto failed; | |
741 } | |
742 | |
743 if ((size_t) n != len) { | |
744 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
745 ngx_write_fd_n " has written only %z of %uz to %s", | |
746 n, size, to); | |
747 goto failed; | |
748 } | |
749 | |
750 size -= n; | |
751 } | |
752 | |
753 if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) { | |
754 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
755 ngx_set_file_time_n " \"%s\" failed", to); | |
756 goto failed; | |
757 } | |
758 | |
759 rc = NGX_OK; | |
760 | |
761 failed: | |
762 | |
763 if (nfd != NGX_INVALID_FILE) { | |
764 if (ngx_close_file(nfd) == NGX_FILE_ERROR) { | |
765 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
766 ngx_close_file_n " \"%s\" failed", to); | |
767 } | |
768 } | |
769 | |
770 if (fd != NGX_INVALID_FILE) { | |
771 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
772 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
773 ngx_close_file_n " \"%s\" failed", from); | |
774 } | |
775 } | |
776 | |
777 if (buf) { | |
778 ngx_free(buf); | |
779 } | |
780 | |
781 return rc; | |
616 } | 782 } |
617 | 783 |
618 | 784 |
619 /* | 785 /* |
620 * ctx->init_handler() - see ctx->alloc | 786 * ctx->init_handler() - see ctx->alloc |