comparison src/core/ngx_open_file_cache.c @ 664:f5b859b2f097 NGINX_1_1_16

nginx 1.1.16 *) Change: the simultaneous subrequest limit has been raised to 200. *) Feature: the "from" parameter of the "disable_symlinks" directive. *) Feature: the "return" and "error_page" directives can be used to return 307 redirections. *) Bugfix: a segmentation fault might occur in a worker process if the "resolver" directive was used and there was no "error_log" directive specified at global level. Thanks to Roman Arutyunyan. *) Bugfix: a segmentation fault might occur in a worker process if the "proxy_http_version 1.1" or "fastcgi_keep_conn on" directives were used. *) Bugfix: memory leaks. Thanks to Lanshun Zhou. *) Bugfix: in the "disable_symlinks" directive. *) Bugfix: on ZFS filesystem disk cache size might be calculated incorrectly; the bug had appeared in 1.0.1. *) Bugfix: nginx could not be built by the icc 12.1 compiler. *) Bugfix: nginx could not be built by gcc on Solaris; the bug had appeared in 1.1.15.
author Igor Sysoev <http://sysoev.ru>
date Wed, 29 Feb 2012 00:00:00 +0400
parents e5fa0a4a7d27
children
comparison
equal deleted inserted replaced
663:dd668cf20818 664:f5b859b2f097
227 || (file->event == NULL 227 || (file->event == NULL
228 && (of->uniq == 0 || of->uniq == file->uniq) 228 && (of->uniq == 0 || of->uniq == file->uniq)
229 && now - file->created < of->valid 229 && now - file->created < of->valid
230 #if (NGX_HAVE_OPENAT) 230 #if (NGX_HAVE_OPENAT)
231 && of->disable_symlinks == file->disable_symlinks 231 && of->disable_symlinks == file->disable_symlinks
232 && of->disable_symlinks_from == file->disable_symlinks_from
232 #endif 233 #endif
233 )) 234 ))
234 { 235 {
235 if (file->err == 0) { 236 if (file->err == 0) {
236 237
393 394
394 file->fd = of->fd; 395 file->fd = of->fd;
395 file->err = of->err; 396 file->err = of->err;
396 #if (NGX_HAVE_OPENAT) 397 #if (NGX_HAVE_OPENAT)
397 file->disable_symlinks = of->disable_symlinks; 398 file->disable_symlinks = of->disable_symlinks;
399 file->disable_symlinks_from = of->disable_symlinks_from;
398 #endif 400 #endif
399 401
400 if (of->err == 0) { 402 if (of->err == 0) {
401 file->uniq = of->uniq; 403 file->uniq = of->uniq;
402 file->mtime = of->mtime; 404 file->mtime = of->mtime;
502 * symlink during openat() or not). 504 * symlink during openat() or not).
503 */ 505 */
504 506
505 fd = ngx_openat_file(at_fd, name, mode, create, access); 507 fd = ngx_openat_file(at_fd, name, mode, create, access);
506 508
507 if (fd == NGX_FILE_ERROR) { 509 if (fd == NGX_INVALID_FILE) {
508 return NGX_FILE_ERROR; 510 return NGX_INVALID_FILE;
509 } 511 }
510 512
511 if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW) 513 if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW)
512 == NGX_FILE_ERROR) 514 == NGX_FILE_ERROR)
513 { 515 {
563 #else 565 #else
564 566
565 u_char *p, *cp, *end; 567 u_char *p, *cp, *end;
566 ngx_fd_t at_fd; 568 ngx_fd_t at_fd;
567 ngx_str_t at_name; 569 ngx_str_t at_name;
568 ngx_file_info_t fi;
569 570
570 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { 571 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
571 fd = ngx_open_file(name->data, mode, create, access); 572 fd = ngx_open_file(name->data, mode, create, access);
572 573
573 if (fd == NGX_INVALID_FILE) { 574 if (fd == NGX_INVALID_FILE) {
580 } 581 }
581 582
582 p = name->data; 583 p = name->data;
583 end = p + name->len; 584 end = p + name->len;
584 585
585 at_fd = AT_FDCWD;
586 at_name = *name; 586 at_name = *name;
587 587
588 if (p[0] == '/') { 588 if (of->disable_symlinks_from) {
589 at_fd = ngx_openat_file(at_fd, "/", 589
590 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, 590 cp = p + of->disable_symlinks_from;
591 NGX_FILE_OPEN, 0); 591
592 592 *cp = '\0';
593 if (at_fd == NGX_FILE_ERROR) { 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) {
594 of->err = ngx_errno; 615 of->err = ngx_errno;
595 of->failed = ngx_openat_file_n; 616 of->failed = ngx_openat_file_n;
596 return NGX_FILE_ERROR; 617 return NGX_INVALID_FILE;
597 } 618 }
598 619
599 at_name.len = 1; 620 at_name.len = 1;
600 p++; 621 p++;
622
623 } else {
624 at_fd = NGX_AT_FDCWD;
601 } 625 }
602 626
603 for ( ;; ) { 627 for ( ;; ) {
604 cp = ngx_strlchr(p, end, '/'); 628 cp = ngx_strlchr(p, end, '/');
605 if (cp == NULL) { 629 if (cp == NULL) {
613 637
614 *cp = '\0'; 638 *cp = '\0';
615 639
616 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { 640 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
617 fd = ngx_openat_file_owner(at_fd, p, 641 fd = ngx_openat_file_owner(at_fd, p,
618 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, 642 NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
619 NGX_FILE_OPEN, 0, log); 643 NGX_FILE_OPEN, 0, log);
620 644
621 } else { 645 } else {
622 fd = ngx_openat_file(at_fd, p, 646 fd = ngx_openat_file(at_fd, p,
623 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW, 647 NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
624 NGX_FILE_OPEN, 0); 648 NGX_FILE_OPEN, 0);
625 } 649 }
626 650
627 *cp = '/'; 651 *cp = '/';
628 652
630 of->err = ngx_errno; 654 of->err = ngx_errno;
631 of->failed = ngx_openat_file_n; 655 of->failed = ngx_openat_file_n;
632 goto failed; 656 goto failed;
633 } 657 }
634 658
635 if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) { 659 if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
636 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, 660 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
637 ngx_close_file_n " \"%V\" failed", at_name); 661 ngx_close_file_n " \"%V\" failed", &at_name);
638 } 662 }
639 663
640 p = cp + 1; 664 p = cp + 1;
641 at_fd = fd; 665 at_fd = fd;
642 at_name.len = cp - at_name.data; 666 at_name.len = cp - at_name.data;
643 } 667 }
644 668
645 if (p == end && at_fd != AT_FDCWD) { 669 if (p == end) {
646 670
647 /* 671 /*
648 * If pathname ends with a trailing slash, check if last path 672 * If pathname ends with a trailing slash, assume the last path
649 * component is a directory; if not, fail with ENOTDIR as per 673 * component is a directory and reopen it with requested flags;
650 * POSIX. 674 * if not, fail with ENOTDIR as per POSIX.
651 * 675 *
652 * We use separate check instead of O_DIRECTORY in the loop above, 676 * We cannot rely on O_DIRECTORY in the loop above to check
653 * as O_DIRECTORY doesn't work on FreeBSD 8. 677 * that the last path component is a directory because
654 * 678 * O_DIRECTORY doesn't work on FreeBSD 8. Fortunately, by
655 * Note this returns already opened file descriptor, with different 679 * reopening a directory, we don't depend on it at all.
656 * mode/create/access. This is believed to be safe as we don't
657 * use this codepath to create directories.
658 */ 680 */
659 681
660 if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) { 682 fd = ngx_openat_file(at_fd, ".", mode, create, access);
661 of->err = ngx_errno; 683 goto done;
662 of->failed = ngx_fd_info_n; 684 }
663 fd = NGX_INVALID_FILE; 685
664 686 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER
665 goto failed; 687 && !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE)))
666 } 688 {
667
668 if (ngx_is_dir(&fi)) {
669 return at_fd;
670 }
671
672 of->err = ENOTDIR;
673 of->failed = ngx_openat_file_n;
674 fd = NGX_INVALID_FILE;
675
676 goto failed;
677 }
678
679 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
680 fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log); 689 fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
681 690
682 } else { 691 } else {
683 fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access); 692 fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
684 } 693 }
694
695 done:
685 696
686 if (fd == NGX_INVALID_FILE) { 697 if (fd == NGX_INVALID_FILE) {
687 of->err = ngx_errno; 698 of->err = ngx_errno;
688 of->failed = ngx_openat_file_n; 699 of->failed = ngx_openat_file_n;
689 } 700 }
690 701
691 failed: 702 failed:
692 703
693 if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) { 704 if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
694 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, 705 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
695 ngx_close_file_n " \"%V\" failed", at_name); 706 ngx_close_file_n " \"%V\" failed", &at_name);
696 } 707 }
697 708
698 return fd; 709 return fd;
699 #endif 710 #endif
700 } 711 }
1129 continue; 1140 continue;
1130 } 1141 }
1131 1142
1132 /* hash == node->key */ 1143 /* hash == node->key */
1133 1144
1134 do { 1145 file = (ngx_cached_open_file_t *) node;
1135 file = (ngx_cached_open_file_t *) node; 1146
1136 1147 rc = ngx_strcmp(name->data, file->name);
1137 rc = ngx_strcmp(name->data, file->name); 1148
1138 1149 if (rc == 0) {
1139 if (rc == 0) { 1150 return file;
1140 return file; 1151 }
1141 } 1152
1142 1153 node = (rc < 0) ? node->left : node->right;
1143 node = (rc < 0) ? node->left : node->right;
1144
1145 } while (node != sentinel && hash == node->key);
1146
1147 break;
1148 } 1154 }
1149 1155
1150 return NULL; 1156 return NULL;
1151 } 1157 }
1152 1158