444
ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
485
#if (NGX_HAVE_OPENAT)
488
ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
489
ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
493
ngx_file_info_t fi, atfi;
496
* To allow symlinks with the same owner, use openat() (followed
497
* by fstat()) and fstatat(AT_SYMLINK_NOFOLLOW), and then compare
498
* uids between fstat() and fstatat().
500
* As there is a race between openat() and fstatat() we don't
501
* know if openat() in fact opened symlink or not. Therefore,
502
* we have to compare uids even if fstatat() reports the opened
503
* component isn't a symlink (as we don't know whether it was
504
* symlink during openat() or not).
507
fd = ngx_openat_file(at_fd, name, mode, create, access);
509
if (fd == NGX_INVALID_FILE) {
510
return NGX_INVALID_FILE;
513
if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW)
520
if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
525
if (fi.st_uid != atfi.st_uid) {
534
if (ngx_close_file(fd) == NGX_FILE_ERROR) {
535
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
536
ngx_close_file_n " \"%V\" failed", name);
541
return NGX_INVALID_FILE;
548
ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
549
ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
553
#if !(NGX_HAVE_OPENAT)
555
fd = ngx_open_file(name->data, mode, create, access);
557
if (fd == NGX_INVALID_FILE) {
559
of->failed = ngx_open_file_n;
560
return NGX_INVALID_FILE;
567
u_char *p, *cp, *end;
571
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
572
fd = ngx_open_file(name->data, mode, create, access);
574
if (fd == NGX_INVALID_FILE) {
576
of->failed = ngx_open_file_n;
577
return NGX_INVALID_FILE;
588
if (of->disable_symlinks_from) {
590
cp = p + of->disable_symlinks_from;
594
at_fd = ngx_open_file(p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
599
if (at_fd == NGX_INVALID_FILE) {
601
of->failed = ngx_open_file_n;
602
return NGX_INVALID_FILE;
605
at_name.len = of->disable_symlinks_from;
608
} else if (*p == '/') {
610
at_fd = ngx_open_file("/",
611
NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
614
if (at_fd == NGX_INVALID_FILE) {
616
of->failed = ngx_openat_file_n;
617
return NGX_INVALID_FILE;
624
at_fd = NGX_AT_FDCWD;
628
cp = ngx_strlchr(p, end, '/');
640
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
641
fd = ngx_openat_file_owner(at_fd, p,
642
NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
643
NGX_FILE_OPEN, 0, log);
646
fd = ngx_openat_file(at_fd, p,
647
NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
653
if (fd == NGX_INVALID_FILE) {
655
of->failed = ngx_openat_file_n;
659
if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
660
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
661
ngx_close_file_n " \"%V\" failed", &at_name);
666
at_name.len = cp - at_name.data;
672
* If pathname ends with a trailing slash, assume the last path
673
* component is a directory and reopen it with requested flags;
674
* if not, fail with ENOTDIR as per POSIX.
676
* We cannot rely on O_DIRECTORY in the loop above to check
677
* that the last path component is a directory because
678
* O_DIRECTORY doesn't work on FreeBSD 8. Fortunately, by
679
* reopening a directory, we don't depend on it at all.
682
fd = ngx_openat_file(at_fd, ".", mode, create, access);
686
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER
687
&& !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE)))
689
fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
692
fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
697
if (fd == NGX_INVALID_FILE) {
699
of->failed = ngx_openat_file_n;
704
if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
705
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
706
ngx_close_file_n " \"%V\" failed", &at_name);
715
ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
716
ngx_file_info_t *fi, ngx_log_t *log)
720
#if !(NGX_HAVE_OPENAT)
722
rc = ngx_file_info(name->data, fi);
724
if (rc == NGX_FILE_ERROR) {
726
of->failed = ngx_file_info_n;
727
return NGX_FILE_ERROR;
736
if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
738
rc = ngx_file_info(name->data, fi);
740
if (rc == NGX_FILE_ERROR) {
742
of->failed = ngx_file_info_n;
743
return NGX_FILE_ERROR;
749
fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
750
NGX_FILE_OPEN, 0, log);
752
if (fd == NGX_INVALID_FILE) {
753
return NGX_FILE_ERROR;
756
rc = ngx_fd_info(fd, fi);
758
if (rc == NGX_FILE_ERROR) {
760
of->failed = ngx_fd_info_n;
763
if (ngx_close_file(fd) == NGX_FILE_ERROR) {
764
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
765
ngx_close_file_n " \"%V\" failed", name);
774
ngx_open_and_stat_file(ngx_str_t *name, ngx_open_file_info_t *of,
447
778
ngx_file_info_t fi;
449
of->fd = NGX_INVALID_FILE;
453
if (ngx_file_info(name, &fi) == -1) {
459
of->uniq = ngx_file_uniq(&fi);
460
of->mtime = ngx_file_mtime(&fi);
461
of->size = ngx_file_size(&fi);
462
of->is_dir = ngx_is_dir(&fi);
463
of->is_file = ngx_is_file(&fi);
464
of->is_link = ngx_is_link(&fi);
465
of->is_exec = ngx_is_exec(&fi);
472
fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
780
if (of->fd != NGX_INVALID_FILE) {
782
if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
783
of->fd = NGX_INVALID_FILE;
787
if (of->uniq == ngx_file_uniq(&fi)) {
791
} else if (of->test_dir) {
793
if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
794
of->fd = NGX_INVALID_FILE;
798
if (ngx_is_dir(&fi)) {
806
* Use non-blocking open() not to hang on FIFO files, etc.
807
* This flag has no effect on a regular files.
810
fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
811
NGX_FILE_OPEN, 0, log);
814
fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND,
815
NGX_FILE_CREATE_OR_OPEN,
816
NGX_FILE_DEFAULT_ACCESS, log);
474
819
if (fd == NGX_INVALID_FILE) {
820
of->fd = NGX_INVALID_FILE;
476
821
return NGX_ERROR;
479
824
if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
480
825
ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
481
ngx_fd_info_n " \"%s\" failed", name);
826
ngx_fd_info_n " \"%V\" failed", name);
483
828
if (ngx_close_file(fd) == NGX_FILE_ERROR) {
484
829
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
485
ngx_close_file_n " \"%s\" failed", name);
830
ngx_close_file_n " \"%V\" failed", name);
833
of->fd = NGX_INVALID_FILE;
488
835
return NGX_ERROR;
491
838
if (ngx_is_dir(&fi)) {
492
839
if (ngx_close_file(fd) == NGX_FILE_ERROR) {
493
840
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
494
ngx_close_file_n " \"%s\" failed", name);
497
fd = NGX_INVALID_FILE;
841
ngx_close_file_n " \"%V\" failed", name);
844
of->fd = NGX_INVALID_FILE;
849
if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) {
850
if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) {
851
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
852
ngx_read_ahead_n " \"%V\" failed", name);
856
if (of->directio <= ngx_file_size(&fi)) {
857
if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
858
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
859
ngx_directio_on_n " \"%V\" failed", name);
501
869
of->uniq = ngx_file_uniq(&fi);
502
870
of->mtime = ngx_file_mtime(&fi);
503
871
of->size = ngx_file_size(&fi);
872
of->fs_size = ngx_file_fs_size(&fi);
504
873
of->is_dir = ngx_is_dir(&fi);
505
874
of->is_file = ngx_is_file(&fi);
506
875
of->is_link = ngx_is_link(&fi);