ngx_int_t
ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
    ngx_open_file_info_t *of, ngx_pool_t *pool)
{
    time_t                          now;
    uint32_t                        hash;
    ngx_int_t                       rc;
    ngx_pool_cleanup_t             *cln;
    ngx_cached_open_file_t         *file;
    ngx_pool_cleanup_file_t        *clnf;
    ngx_open_file_cache_cleanup_t  *ofcln;
    of->fd = NGX_INVALID_FILE;
    of->err = 0;
    if (cache == NULL) {
        cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
        if (cln == NULL) {
            return NGX_ERROR;
        }
        rc = ngx_open_and_stat_file(name->data, of, pool->log);
        if (rc == NGX_OK && !of->is_dir) {
            cln->handler = ngx_pool_cleanup_file;
            clnf = cln->data;
            clnf->fd = of->fd;
            clnf->name = name->data;
            clnf->log = pool->log;
        }
        return rc;
    }
    cln = ngx_pool_cleanup_add(pool, sizeof(ngx_open_file_cache_cleanup_t));
    if (cln == NULL) {
        return NGX_ERROR;
    }
    now = ngx_time();
    hash = ngx_crc32_long(name->data, name->len);
    file = ngx_open_file_lookup(cache, name, hash);
    if (file) {
        file->uses++;
        ngx_queue_remove(&file->queue);
        if (file->fd == NGX_INVALID_FILE && file->err == 0 && !file->is_dir) {
            rc = ngx_open_and_stat_file(name->data, of, pool->log);
            if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
                goto failed;
            }
            goto add_event;
        }
        if (file->use_event
            || (file->event == NULL
                && (of->uniq == 0 || of->uniq == file->uniq)
                && now - file->created < of->valid))
        {
            if (file->err == 0) {
                of->fd = file->fd;
                of->uniq = file->uniq;
                of->mtime = file->mtime;
                of->size = file->size;
                of->is_dir = file->is_dir;
                of->is_file = file->is_file;
                of->is_link = file->is_link;
                of->is_exec = file->is_exec;
                of->is_directio = file->is_directio;
                if (!file->is_dir) {
                    file->count++;
                    ngx_open_file_add_event(cache, file, of, pool->log);
                }
            } else {
                of->err = file->err;
            }
            goto found;
        }
        ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0,
                       "retest open file: %s, fd:%d, c:%d, e:%d",
                       file->name, file->fd, file->count, file->err);
        if (file->is_dir) {
            of->test_dir = 1;
        }
        of->fd = file->fd;
        of->uniq = file->uniq;
        rc = ngx_open_and_stat_file(name->data, of, pool->log);
        if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
            goto failed;
        }
        if (of->is_dir) {
            if (file->is_dir || file->err) {
                goto update;
            }
        } else if (of->err == 0) {
            if (file->is_dir || file->err) {
                goto add_event;
            }
            if (of->uniq == file->uniq) {
                file->count++;
                if (file->event) {
                    file->use_event = 1;
                }
                goto renew;
            }
        } else {
            if (file->err || file->is_dir) {
                goto update;
            }
        }
        if (file->count == 0) {
            ngx_open_file_del_event(file);
            if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                              ngx_close_file_n " \"%s\" failed",
                              name->data);
            }
            goto add_event;
        }
        ngx_rbtree_delete(&cache->rbtree, &file->node);
        cache->current--;
        file->close = 1;
        goto create;
    }
    rc = ngx_open_and_stat_file(name->data, of, pool->log);
    if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
        goto failed;
    }
create:
    if (cache->current >= cache->max) {
        ngx_expire_old_cached_files(cache, 0, pool->log);
    }
    file = ngx_alloc(sizeof(ngx_cached_open_file_t), pool->log);
    if (file == NULL) {
        goto failed;
    }
    file->name = ngx_alloc(name->len + 1, pool->log);
    if (file->name == NULL) {
        ngx_free(file);
        file = NULL;
        goto failed;
    }
    ngx_cpystrn(file->name, name->data, name->len + 1);
    file->node.key = hash;
    ngx_rbtree_insert(&cache->rbtree, &file->node);
    cache->current++;
    file->uses = 1;
    file->count = 0;
    file->event = NULL;
add_event:
    ngx_open_file_add_event(cache, file, of, pool->log);
update:
    file->fd = of->fd;
    file->err = of->err;
    if (of->err == 0) {
        file->uniq = of->uniq;
        file->mtime = of->mtime;
        file->size = of->size;
        file->close = 0;
        file->is_dir = of->is_dir;
        file->is_file = of->is_file;
        file->is_link = of->is_link;
        file->is_exec = of->is_exec;
        file->is_directio = of->is_directio;
        if (!of->is_dir) {
            file->count++;
        }
    }
renew:
    file->created = now;
found:
    file->accessed = now;
    ngx_queue_insert_head(&cache->expire_queue, &file->queue);
    ngx_log_debug5(NGX_LOG_DEBUG_CORE, pool->log, 0,
                   "cached open file: %s, fd:%d, c:%d, e:%d, u:%d",
                   file->name, file->fd, file->count, file->err, file->uses);
    if (of->err == 0) {
        if (!of->is_dir) {
            cln->handler = ngx_open_file_cleanup;
            ofcln = cln->data;
            ofcln->cache = cache;
            ofcln->file = file;
            ofcln->min_uses = of->min_uses;
            ofcln->log = pool->log;
        }
        return NGX_OK;
    }
    return NGX_ERROR;
failed:
    if (file) {
        ngx_rbtree_delete(&cache->rbtree, &file->node);
        cache->current--;
        if (file->count == 0) {
            if (file->fd != NGX_INVALID_FILE) {
                if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                                  ngx_close_file_n " \"%s\" failed",
                                  file->name);
                }
            }
            ngx_free(file->name);
            ngx_free(file);
        } else {
            file->close = 1;
        }
    }
    if (of->fd != NGX_INVALID_FILE) {
        if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed", name->data);
        }
    }
    return NGX_ERROR;
}
['ngx_int_t\nngx_http_core_try_files_phase(ngx_http_request_t *r,\n    ngx_http_phase_handler_t *ph)\n{\n    size_t                        len, root, alias, reserve, allocated;\n    u_char                       *p, *name;\n    ngx_str_t                     path, args;\n    ngx_uint_t                    test_dir;\n    ngx_http_try_file_t          *tf;\n    ngx_open_file_info_t          of;\n    ngx_http_script_code_pt       code;\n    ngx_http_script_engine_t      e;\n    ngx_http_core_loc_conf_t     *clcf;\n    ngx_http_script_len_code_pt   lcode;\n    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,\n                   "try files phase: %ui", r->phase_handler);\n    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);\n    if (clcf->try_files == NULL) {\n        r->phase_handler++;\n        return NGX_AGAIN;\n    }\n    allocated = 0;\n    root = 0;\n    name = NULL;\n    path.data = NULL;\n    tf = clcf->try_files;\n    alias = clcf->alias ? clcf->name.len : 0;\n    for ( ;; ) {\n        if (tf->lengths) {\n            ngx_memzero(&e, sizeof(ngx_http_script_engine_t));\n            e.ip = tf->lengths->elts;\n            e.request = r;\n            len = 1;\n            while (*(uintptr_t *) e.ip) {\n                lcode = *(ngx_http_script_len_code_pt *) e.ip;\n                len += lcode(&e);\n            }\n        } else {\n            len = tf->name.len;\n        }\n        reserve = ngx_abs((ssize_t) (len - r->uri.len)) + alias + 16;\n        if (reserve > allocated) {\n            if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) {\n                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);\n                return NGX_OK;\n            }\n            name = path.data + root;\n            allocated = path.len - root - (r->uri.len - alias);\n         }\n        if (tf->values == NULL) {\n            ngx_memcpy(name, tf->name.data, tf->name.len);\n            path.len = (name + tf->name.len - 1) - path.data;\n        } else {\n            e.ip = tf->values->elts;\n            e.pos = name;\n            e.flushed = 1;\n            while (*(uintptr_t *) e.ip) {\n                code = *(ngx_http_script_code_pt *) e.ip;\n                code((ngx_http_script_engine_t *) &e);\n            }\n            path.len = e.pos - path.data;\n            *e.pos = \'\\0\';\n            if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {\n                ngx_memcpy(name, name + alias, len - alias);\n                path.len -= alias;\n            }\n        }\n        test_dir = tf->test_dir;\n        tf++;\n        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,\n                       "try to use file: \\"%s\\" \\"%s\\"", name, path.data);\n        if (tf->lengths == NULL && tf->name.len == 0) {\n            if (tf->code) {\n                ngx_http_finalize_request(r, tf->code);\n                return NGX_OK;\n            }\n            path.len -= root;\n            path.data += root;\n            if (path.data[0] == \'@\') {\n                (void) ngx_http_named_location(r, &path);\n            } else {\n                ngx_http_split_args(r, &path, &args);\n                (void) ngx_http_internal_redirect(r, &path, &args);\n            }\n            return NGX_OK;\n        }\n        ngx_memzero(&of, sizeof(ngx_open_file_info_t));\n        of.directio = clcf->directio;\n        of.valid = clcf->open_file_cache_valid;\n        of.min_uses = clcf->open_file_cache_min_uses;\n        of.errors = clcf->open_file_cache_errors;\n        of.events = clcf->open_file_cache_events;\n        if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)\n            != NGX_OK)\n        {\n            if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {\n                ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,\n                              ngx_open_file_n " \\"%s\\" failed", path.data);\n            }\n            continue;\n        }\n        if (of.is_dir && !test_dir) {\n            continue;\n        }\n        path.len -= root;\n        path.data += root;\n        if (!alias) {\n            r->uri = path;\n        } else {\n            r->uri.len = alias + path.len;\n            r->uri.data = ngx_pnalloc(r->pool, r->uri.len);\n            if (r->uri.data == NULL) {\n                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);\n                return NGX_OK;\n            }\n            p = ngx_copy(r->uri.data, clcf->name.data, alias);\n            ngx_memcpy(p, name, path.len);\n        }\n        if (ngx_http_set_exten(r) != NGX_OK) {\n            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);\n            return NGX_OK;\n        }\n        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,\n                       "try file uri: \\"%V\\"", &r->uri);\n        r->phase_handler++;\n        return NGX_AGAIN;\n    }\n}', 'ngx_int_t\nngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,\n    ngx_open_file_info_t *of, ngx_pool_t *pool)\n{\n    time_t                          now;\n    uint32_t                        hash;\n    ngx_int_t                       rc;\n    ngx_pool_cleanup_t             *cln;\n    ngx_cached_open_file_t         *file;\n    ngx_pool_cleanup_file_t        *clnf;\n    ngx_open_file_cache_cleanup_t  *ofcln;\n    of->fd = NGX_INVALID_FILE;\n    of->err = 0;\n    if (cache == NULL) {\n        cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));\n        if (cln == NULL) {\n            return NGX_ERROR;\n        }\n        rc = ngx_open_and_stat_file(name->data, of, pool->log);\n        if (rc == NGX_OK && !of->is_dir) {\n            cln->handler = ngx_pool_cleanup_file;\n            clnf = cln->data;\n            clnf->fd = of->fd;\n            clnf->name = name->data;\n            clnf->log = pool->log;\n        }\n        return rc;\n    }\n    cln = ngx_pool_cleanup_add(pool, sizeof(ngx_open_file_cache_cleanup_t));\n    if (cln == NULL) {\n        return NGX_ERROR;\n    }\n    now = ngx_time();\n    hash = ngx_crc32_long(name->data, name->len);\n    file = ngx_open_file_lookup(cache, name, hash);\n    if (file) {\n        file->uses++;\n        ngx_queue_remove(&file->queue);\n        if (file->fd == NGX_INVALID_FILE && file->err == 0 && !file->is_dir) {\n            rc = ngx_open_and_stat_file(name->data, of, pool->log);\n            if (rc != NGX_OK && (of->err == 0 || !of->errors)) {\n                goto failed;\n            }\n            goto add_event;\n        }\n        if (file->use_event\n            || (file->event == NULL\n                && (of->uniq == 0 || of->uniq == file->uniq)\n                && now - file->created < of->valid))\n        {\n            if (file->err == 0) {\n                of->fd = file->fd;\n                of->uniq = file->uniq;\n                of->mtime = file->mtime;\n                of->size = file->size;\n                of->is_dir = file->is_dir;\n                of->is_file = file->is_file;\n                of->is_link = file->is_link;\n                of->is_exec = file->is_exec;\n                of->is_directio = file->is_directio;\n                if (!file->is_dir) {\n                    file->count++;\n                    ngx_open_file_add_event(cache, file, of, pool->log);\n                }\n            } else {\n                of->err = file->err;\n            }\n            goto found;\n        }\n        ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0,\n                       "retest open file: %s, fd:%d, c:%d, e:%d",\n                       file->name, file->fd, file->count, file->err);\n        if (file->is_dir) {\n            of->test_dir = 1;\n        }\n        of->fd = file->fd;\n        of->uniq = file->uniq;\n        rc = ngx_open_and_stat_file(name->data, of, pool->log);\n        if (rc != NGX_OK && (of->err == 0 || !of->errors)) {\n            goto failed;\n        }\n        if (of->is_dir) {\n            if (file->is_dir || file->err) {\n                goto update;\n            }\n        } else if (of->err == 0) {\n            if (file->is_dir || file->err) {\n                goto add_event;\n            }\n            if (of->uniq == file->uniq) {\n                file->count++;\n                if (file->event) {\n                    file->use_event = 1;\n                }\n                goto renew;\n            }\n        } else {\n            if (file->err || file->is_dir) {\n                goto update;\n            }\n        }\n        if (file->count == 0) {\n            ngx_open_file_del_event(file);\n            if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {\n                ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,\n                              ngx_close_file_n " \\"%s\\" failed",\n                              name->data);\n            }\n            goto add_event;\n        }\n        ngx_rbtree_delete(&cache->rbtree, &file->node);\n        cache->current--;\n        file->close = 1;\n        goto create;\n    }\n    rc = ngx_open_and_stat_file(name->data, of, pool->log);\n    if (rc != NGX_OK && (of->err == 0 || !of->errors)) {\n        goto failed;\n    }\ncreate:\n    if (cache->current >= cache->max) {\n        ngx_expire_old_cached_files(cache, 0, pool->log);\n    }\n    file = ngx_alloc(sizeof(ngx_cached_open_file_t), pool->log);\n    if (file == NULL) {\n        goto failed;\n    }\n    file->name = ngx_alloc(name->len + 1, pool->log);\n    if (file->name == NULL) {\n        ngx_free(file);\n        file = NULL;\n        goto failed;\n    }\n    ngx_cpystrn(file->name, name->data, name->len + 1);\n    file->node.key = hash;\n    ngx_rbtree_insert(&cache->rbtree, &file->node);\n    cache->current++;\n    file->uses = 1;\n    file->count = 0;\n    file->event = NULL;\nadd_event:\n    ngx_open_file_add_event(cache, file, of, pool->log);\nupdate:\n    file->fd = of->fd;\n    file->err = of->err;\n    if (of->err == 0) {\n        file->uniq = of->uniq;\n        file->mtime = of->mtime;\n        file->size = of->size;\n        file->close = 0;\n        file->is_dir = of->is_dir;\n        file->is_file = of->is_file;\n        file->is_link = of->is_link;\n        file->is_exec = of->is_exec;\n        file->is_directio = of->is_directio;\n        if (!of->is_dir) {\n            file->count++;\n        }\n    }\nrenew:\n    file->created = now;\nfound:\n    file->accessed = now;\n    ngx_queue_insert_head(&cache->expire_queue, &file->queue);\n    ngx_log_debug5(NGX_LOG_DEBUG_CORE, pool->log, 0,\n                   "cached open file: %s, fd:%d, c:%d, e:%d, u:%d",\n                   file->name, file->fd, file->count, file->err, file->uses);\n    if (of->err == 0) {\n        if (!of->is_dir) {\n            cln->handler = ngx_open_file_cleanup;\n            ofcln = cln->data;\n            ofcln->cache = cache;\n            ofcln->file = file;\n            ofcln->min_uses = of->min_uses;\n            ofcln->log = pool->log;\n        }\n        return NGX_OK;\n    }\n    return NGX_ERROR;\nfailed:\n    if (file) {\n        ngx_rbtree_delete(&cache->rbtree, &file->node);\n        cache->current--;\n        if (file->count == 0) {\n            if (file->fd != NGX_INVALID_FILE) {\n                if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {\n                    ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,\n                                  ngx_close_file_n " \\"%s\\" failed",\n                                  file->name);\n                }\n            }\n            ngx_free(file->name);\n            ngx_free(file);\n        } else {\n            file->close = 1;\n        }\n    }\n    if (of->fd != NGX_INVALID_FILE) {\n        if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {\n            ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,\n                          ngx_close_file_n " \\"%s\\" failed", name->data);\n        }\n    }\n    return NGX_ERROR;\n}']