diff 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
line wrap: on
line diff
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -229,6 +229,7 @@ ngx_open_cached_file(ngx_open_file_cache
                 && now - file->created < of->valid
 #if (NGX_HAVE_OPENAT)
                 && of->disable_symlinks == file->disable_symlinks
+                && of->disable_symlinks_from == file->disable_symlinks_from
 #endif
             ))
         {
@@ -395,6 +396,7 @@ update:
     file->err = of->err;
 #if (NGX_HAVE_OPENAT)
     file->disable_symlinks = of->disable_symlinks;
+    file->disable_symlinks_from = of->disable_symlinks_from;
 #endif
 
     if (of->err == 0) {
@@ -504,8 +506,8 @@ ngx_openat_file_owner(ngx_fd_t at_fd, co
 
     fd = ngx_openat_file(at_fd, name, mode, create, access);
 
-    if (fd == NGX_FILE_ERROR) {
-        return NGX_FILE_ERROR;
+    if (fd == NGX_INVALID_FILE) {
+        return NGX_INVALID_FILE;
     }
 
     if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW)
@@ -565,7 +567,6 @@ ngx_open_file_wrapper(ngx_str_t *name, n
     u_char           *p, *cp, *end;
     ngx_fd_t          at_fd;
     ngx_str_t         at_name;
-    ngx_file_info_t   fi;
 
     if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
         fd = ngx_open_file(name->data, mode, create, access);
@@ -582,22 +583,45 @@ ngx_open_file_wrapper(ngx_str_t *name, n
     p = name->data;
     end = p + name->len;
 
-    at_fd = AT_FDCWD;
     at_name = *name;
 
-    if (p[0] == '/') {
-        at_fd = ngx_openat_file(at_fd, "/",
-                                NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
-                                NGX_FILE_OPEN, 0);
+    if (of->disable_symlinks_from) {
+
+        cp = p + of->disable_symlinks_from;
+
+        *cp = '\0';
+
+        at_fd = ngx_open_file(p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
+                              NGX_FILE_OPEN, 0);
+
+        *cp = '/';
 
-        if (at_fd == NGX_FILE_ERROR) {
+        if (at_fd == NGX_INVALID_FILE) {
+            of->err = ngx_errno;
+            of->failed = ngx_open_file_n;
+            return NGX_INVALID_FILE;
+        }
+
+        at_name.len = of->disable_symlinks_from;
+        p = cp + 1;
+
+    } else if (*p == '/') {
+
+        at_fd = ngx_open_file("/",
+                              NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
+                              NGX_FILE_OPEN, 0);
+
+        if (at_fd == NGX_INVALID_FILE) {
             of->err = ngx_errno;
             of->failed = ngx_openat_file_n;
-            return NGX_FILE_ERROR;
+            return NGX_INVALID_FILE;
         }
 
         at_name.len = 1;
         p++;
+
+    } else {
+        at_fd = NGX_AT_FDCWD;
     }
 
     for ( ;; ) {
@@ -615,12 +639,12 @@ ngx_open_file_wrapper(ngx_str_t *name, n
 
         if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
             fd = ngx_openat_file_owner(at_fd, p,
-                                       NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+                                       NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
                                        NGX_FILE_OPEN, 0, log);
 
         } else {
             fd = ngx_openat_file(at_fd, p,
-                           NGX_FILE_RDONLY|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
+                           NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
                            NGX_FILE_OPEN, 0);
         }
 
@@ -632,9 +656,9 @@ ngx_open_file_wrapper(ngx_str_t *name, n
             goto failed;
         }
 
-        if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
+        if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
             ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                          ngx_close_file_n " \"%V\" failed", at_name);
+                          ngx_close_file_n " \"%V\" failed", &at_name);
         }
 
         p = cp + 1;
@@ -642,47 +666,34 @@ ngx_open_file_wrapper(ngx_str_t *name, n
         at_name.len = cp - at_name.data;
     }
 
-    if (p == end && at_fd != AT_FDCWD) {
+    if (p == end) {
 
         /*
-         * If pathname ends with a trailing slash, check if last path
-         * component is a directory; if not, fail with ENOTDIR as per
-         * POSIX.
+         * If pathname ends with a trailing slash, assume the last path
+         * component is a directory and reopen it with requested flags;
+         * if not, fail with ENOTDIR as per POSIX.
          *
-         * We use separate check instead of O_DIRECTORY in the loop above,
-         * as O_DIRECTORY doesn't work on FreeBSD 8.
-         *
-         * Note this returns already opened file descriptor, with different
-         * mode/create/access.  This is believed to be safe as we don't
-         * use this codepath to create directories.
+         * We cannot rely on O_DIRECTORY in the loop above to check
+         * that the last path component is a directory because
+         * O_DIRECTORY doesn't work on FreeBSD 8.  Fortunately, by
+         * reopening a directory, we don't depend on it at all.
          */
 
-        if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) {
-            of->err = ngx_errno;
-            of->failed = ngx_fd_info_n;
-            fd = NGX_INVALID_FILE;
-
-            goto failed;
-        }
-
-        if (ngx_is_dir(&fi)) {
-            return at_fd;
-        }
-
-        of->err = ENOTDIR;
-        of->failed = ngx_openat_file_n;
-        fd = NGX_INVALID_FILE;
-
-        goto failed;
+        fd = ngx_openat_file(at_fd, ".", mode, create, access);
+        goto done;
     }
 
-    if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
+    if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER
+        && !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE)))
+    {
         fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
 
     } else {
         fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
     }
 
+done:
+
     if (fd == NGX_INVALID_FILE) {
         of->err = ngx_errno;
         of->failed = ngx_openat_file_n;
@@ -690,9 +701,9 @@ ngx_open_file_wrapper(ngx_str_t *name, n
 
 failed:
 
-    if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
+    if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      ngx_close_file_n " \"%V\" failed", at_name);
+                      ngx_close_file_n " \"%V\" failed", &at_name);
     }
 
     return fd;
@@ -1131,20 +1142,15 @@ ngx_open_file_lookup(ngx_open_file_cache
 
         /* hash == node->key */
 
-        do {
-            file = (ngx_cached_open_file_t *) node;
+        file = (ngx_cached_open_file_t *) node;
 
-            rc = ngx_strcmp(name->data, file->name);
+        rc = ngx_strcmp(name->data, file->name);
 
-            if (rc == 0) {
-                return file;
-            }
+        if (rc == 0) {
+            return file;
+        }
 
-            node = (rc < 0) ? node->left : node->right;
-
-        } while (node != sentinel && hash == node->key);
-
-        break;
+        node = (rc < 0) ? node->left : node->right;
     }
 
     return NULL;