564 | 564 |
u_char *p, *cp, *end;
|
565 | 565 |
ngx_fd_t at_fd;
|
566 | 566 |
ngx_str_t at_name;
|
567 | |
ngx_file_info_t fi;
|
568 | 567 |
|
569 | 568 |
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
|
570 | 569 |
fd = ngx_open_file(name->data, mode, create, access);
|
|
585 | 584 |
|
586 | 585 |
if (*p == '/') {
|
587 | 586 |
at_fd = ngx_open_file("/",
|
588 | |
NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
|
|
587 |
NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
|
589 | 588 |
NGX_FILE_OPEN, 0);
|
590 | 589 |
|
591 | 590 |
if (at_fd == NGX_INVALID_FILE) {
|
|
616 | 615 |
|
617 | 616 |
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
|
618 | 617 |
fd = ngx_openat_file_owner(at_fd, p,
|
619 | |
NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
|
|
618 |
NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
|
620 | 619 |
NGX_FILE_OPEN, 0, log);
|
621 | 620 |
|
622 | 621 |
} else {
|
623 | 622 |
fd = ngx_openat_file(at_fd, p,
|
624 | |
NGX_FILE_RDONLY|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
|
|
623 |
NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
|
625 | 624 |
NGX_FILE_OPEN, 0);
|
626 | 625 |
}
|
627 | 626 |
|
|
646 | 645 |
if (p == end) {
|
647 | 646 |
|
648 | 647 |
/*
|
649 | |
* If pathname ends with a trailing slash, check if last path
|
650 | |
* component is a directory; if not, fail with ENOTDIR as per
|
651 | |
* POSIX.
|
|
648 |
* If pathname ends with a trailing slash, assume the last path
|
|
649 |
* component is a directory and reopen it with requested flags;
|
|
650 |
* if not, fail with ENOTDIR as per POSIX.
|
652 | 651 |
*
|
653 | |
* We use separate check instead of O_DIRECTORY in the loop above,
|
654 | |
* as O_DIRECTORY doesn't work on FreeBSD 8.
|
655 | |
*
|
656 | |
* Note this returns already opened file descriptor, with different
|
657 | |
* mode/create/access. This is believed to be safe as we don't
|
658 | |
* use this codepath to create directories.
|
|
652 |
* We cannot rely on O_DIRECTORY in the loop above to check
|
|
653 |
* that the last path component is a directory because
|
|
654 |
* O_DIRECTORY doesn't work on FreeBSD 8. Fortunately, by
|
|
655 |
* reopening a directory, we don't depend on it at all.
|
659 | 656 |
*/
|
660 | 657 |
|
661 | |
if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) {
|
662 | |
of->err = ngx_errno;
|
663 | |
of->failed = ngx_fd_info_n;
|
664 | |
fd = NGX_INVALID_FILE;
|
665 | |
|
666 | |
goto failed;
|
667 | |
}
|
668 | |
|
669 | |
if (ngx_is_dir(&fi)) {
|
670 | |
return at_fd;
|
671 | |
}
|
672 | |
|
673 | |
of->err = ENOTDIR;
|
674 | |
of->failed = ngx_openat_file_n;
|
675 | |
fd = NGX_INVALID_FILE;
|
676 | |
|
677 | |
goto failed;
|
|
658 |
fd = ngx_openat_file(at_fd, ".", mode, create, access);
|
|
659 |
goto done;
|
678 | 660 |
}
|
679 | 661 |
|
680 | 662 |
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER
|
|
685 | 667 |
} else {
|
686 | 668 |
fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
|
687 | 669 |
}
|
|
670 |
|
|
671 |
done:
|
688 | 672 |
|
689 | 673 |
if (fd == NGX_INVALID_FILE) {
|
690 | 674 |
of->err = ngx_errno;
|