ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key) { int sslerr; if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { return NGX_ERROR; } sslerr = x509parse_crtfile(&ssl->own_cert, (char *) cert->data); if (sslerr != 0) { ngx_mbedtls_error(NGX_LOG_EMERG, ssl->log, 0, sslerr, "x509parse_crtfile(%p, \"%s\") failed", &ssl->own_cert, cert->data); return NGX_ERROR; } if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { return NGX_ERROR; } sslerr = x509parse_keyfile(&ssl->own_key, (char *) key->data, NULL); if (sslerr != 0) { ngx_mbedtls_error(NGX_LOG_EMERG, ssl->log, 0, sslerr, "x509parse_keyfile(%p, \"%s\", NULL) failed", &ssl->own_key, key->data); return NGX_ERROR; } ssl->have_own_cert = 1; return NGX_OK; }
char * ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ssize_t level; ngx_str_t *value; ngx_uint_t i, n; ngx_path_t *path, **slot; slot = (ngx_path_t **) (p + cmd->offset); if (*slot) { return "is duplicate"; } path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); if (path == NULL) { return NGX_CONF_ERROR; } value = cf->args->elts; path->name = value[1]; if (path->name.data[path->name.len - 1] == '/') { path->name.len--; } if (ngx_conf_full_name(cf->cycle, &path->name, 0) != NGX_OK) { return NULL; } path->len = 0; path->manager = (ngx_path_manager_pt) cmd->post; path->conf_file = cf->conf_file->file.name.data; path->line = cf->conf_file->line; for (i = 0, n = 2; n < cf->args->nelts; i++, n++) { level = ngx_atoi(value[n].data, value[n].len); if (level == NGX_ERROR || level == 0) { return "invalid value"; } path->level[i] = level; path->len += level + 1; } while (i < 3) { path->level[i++] = 0; } *slot = path; if (ngx_add_path(cf, slot) == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_dso_include(ngx_conf_t *cf, ngx_dso_conf_ctx_t *ctx, ngx_str_t *name) { char *rv; ngx_str_t file; ngx_conf_t pcf; file.len = name->len; file.data = ngx_pnalloc(cf->temp_pool, name->len + 1); if (file.data == NULL) { return NGX_CONF_ERROR; } ngx_sprintf(file.data, "%V%Z", name); if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_CORE_MODULE; rv = ngx_conf_parse(cf, &file); *cf = pcf; return rv; }
ngx_int_t ngx_http_lua_mqtt_create_shmtx(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name) { u_char *file; #if (NGX_HAVE_ATOMIC_OPS) file = NULL; #else ngx_str_t logs_dir = ngx_string("logs/"); if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &logs_dir, 0) != NGX_OK) { return NGX_ERROR; } file = ngx_pnalloc(ngx_cycle->pool, logs_dir.len + ngx_strlen(name)); if (file == NULL) { return NGX_ERROR; } (void) ngx_sprintf(file, "%V%s%Z", &logs_dir, name); #endif if (ngx_shmtx_create(mtx, addr, file) != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
static char * ngx_backtrace_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t file, *value; ngx_log_t *log; ngx_backtrace_conf_t *bcf; bcf = (ngx_backtrace_conf_t *) ngx_get_conf(cf->cycle->conf_ctx, ngx_backtrace_module); value = cf->args->elts; file = value[1]; if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } log = ngx_log_create(cf->cycle, &file); if (log == NULL) { return NGX_CONF_ERROR; } bcf->log = log; return NGX_CONF_OK; }
ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl) { int sslerr; if (crl->len == 0) { return NGX_OK; } if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) { return NGX_ERROR; } sslerr = x509parse_crlfile(&ssl->ca_crl, (char *) crl->data); if (sslerr != 0) { ngx_mbedtls_error(NGX_LOG_EMERG, ssl->log, 0, sslerr, "x509parse_crlfile(%p, \"%s\") failed", &ssl->ca_crl, crl->data, sslerr); return NGX_ERROR; } ssl->have_ca_crl = 1; return NGX_ERROR; }
ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth) { int sslerr; if (cert->len == 0) { return NGX_OK; } if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { return NGX_ERROR; } /* Just add the certificate to the CA cert chain */ sslerr = x509parse_crtfile(&ssl->ca_cert, (char *) cert->data); if (sslerr != 0) { ngx_mbedtls_error(NGX_LOG_EMERG, ssl->log, 0, sslerr, "x509parse_crtfile(%p, \"%s\") failed", &ssl->ca_cert, cert->data); return NGX_ERROR; } ssl->have_ca_cert = 1; return NGX_OK; }
static char * ngx_http_modsecurity_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_modsecurity_loc_conf_t *mscf = conf; ngx_str_t *value; const char *msg; if (mscf->config != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; if (ngx_conf_full_name(cf->cycle, &value[1], 1) != NGX_OK) { return NGX_CONF_ERROR; } mscf->config = modsecGetDefaultConfig(); if (mscf->config == NULL) { return NGX_CONF_ERROR; } msg = modsecProcessConfig(mscf->config, (const char *)value[1].data, NULL); if (msg != NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "ModSecurityConfig in %s:%ui: %s", cf->conf_file->file.name.data, cf->conf_file->line, msg); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_http_tfs_rcs_heartbeat(ngx_conf_t *cf, ngx_http_tfs_upstream_t *tu) { ngx_str_t *value, s; ngx_msec_t interval; ngx_uint_t i; value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "lock_file=", 10) == 0) { s.data = value[i].data + 10; s.len = value[i].len - 10; if (ngx_conf_full_name(cf->cycle, &s, 0) != NGX_OK) { goto rcs_timers_error; } tu->lock_file = s; continue; } if (ngx_strncmp(value[i].data, "interval=", 9) == 0) { s.data = value[i].data + 9; s.len = value[i].len - 9; interval = ngx_parse_time(&s, 0); if (interval == (ngx_msec_t) NGX_ERROR) { return "invalid value"; } tu->rcs_interval = interval; continue; } goto rcs_timers_error; } if (tu->lock_file.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "tfs_poll directive must have lock file"); return NGX_CONF_ERROR; } if (tu->rcs_interval < NGX_HTTP_TFS_MIN_TIMER_DELAY) { tu->rcs_interval = NGX_HTTP_TFS_MIN_TIMER_DELAY; ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "tfs_poll interval is small, " "so reset this value to 1000"); } return NGX_CONF_OK; rcs_timers_error: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid value \"%V\" in \"%V\" directive", &value[i], &value[0]); return NGX_CONF_ERROR; }
ngx_open_file_t *ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name) { ngx_str_t full; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; #if (NGX_SUPPRESS_WARN) full.len = 0; full.data = NULL; #endif if (name) { full = *name; if (ngx_conf_full_name(cycle, &full) == NGX_ERROR) { return NULL; } part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (full.len != file[i].name.len) { continue; } if (ngx_strcmp(full.data, file[i].name.data) == 0) { return &file[i]; } } } if (!(file = ngx_list_push(&cycle->open_files))) { return NULL; } if (name) { file->fd = NGX_INVALID_FILE; file->name = full; } else { file->fd = ngx_stderr_fileno; file->name.len = 0; file->name.data = NULL; } return file; }
static char * ngx_http_xrlt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_xrlt_loc_conf_t *xlcf = conf; ngx_http_core_loc_conf_t *clcf; ngx_str_t *value; ngx_pool_cleanup_t *cln; xmlDocPtr doc; xrltRequestsheetPtr sheet; value = cf->args->elts; if (xlcf->sheet != NULL) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "Duplicate xrlt instruction"); return NGX_CONF_ERROR; } if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; } doc = xmlParseFile((const char *)value[1].data); if (doc == NULL) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "xmlParseFile(\"%s\") failed", value[1].data); return NGX_CONF_ERROR; } sheet = xrltRequestsheetCreate(doc); if (sheet == NULL) { xmlFreeDoc(doc); ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "xrltRequestsheetCreate(\"%s\") failed", value[1].data); return NGX_CONF_ERROR; } xlcf->sheet = sheet; cln->handler = ngx_http_xrlt_cleanup_requestsheet; cln->data = sheet; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); if (clcf == NULL) { return NGX_CONF_ERROR; } clcf->handler = ngx_http_xrlt_handler; return NGX_CONF_OK; }
static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { size_t len; ngx_str_t path; ngx_http_core_loc_conf_t *clcf; u_char real[NGX_MAX_PATH]; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->root_lengths == NULL) { path = clcf->root; } else { if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1, clcf->root_values->elts) == NULL) { return NGX_ERROR; } path.data[path.len - 1] = '\0'; if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) { return NGX_ERROR; } } if (ngx_realpath(path.data, real) == NULL) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_realpath_n " \"%s\" failed", path.data); return NGX_ERROR; } len = ngx_strlen(real); v->data = ngx_pnalloc(r->pool, len); if (v->data == NULL) { return NGX_ERROR; } v->len = len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; ngx_memcpy(v->data, real, len); return NGX_OK; }
static char * ngx_http_wd_parse_path(ngx_conf_t *cf, ngx_str_t *conf_path) { ngx_str_t *value; ngx_str_t path; size_t i; int label; value = cf->args->elts; path = value[1]; if (ngx_conf_full_name(cf->cycle, &path, 1) != NGX_OK) { return NGX_CONF_ERROR; } while (conf_path->len > 1) { if (conf_path->data[conf_path->len - 1] != '/') { break; } conf_path->len--; } conf_path->data = ngx_pcalloc(cf->pool, path.len); if (conf_path->data == NULL) { return NGX_CONF_ERROR; } conf_path->len = 0; for (i = 0, label = 0; i < path.len; i++) { if (path.data[i] == '/') { if (label == 0) { label = 1; conf_path->data[conf_path->len] = path.data[i]; conf_path->len++; } else { continue; } } else { label = 0; conf_path->data[conf_path->len] = path.data[i]; conf_path->len++; } } if (conf_path->data[conf_path->len - 1] == '/') { conf_path->len--; } return NGX_CONF_OK; }
static char * ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t n; ngx_str_t *value, file; ngx_glob_t gl; value = cf->args->elts; file = value[1]; ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR) { return NGX_CONF_ERROR; } ngx_memzero(&gl, sizeof(ngx_glob_t)); gl.pattern = file.data; gl.log = cf->log; if (ngx_open_glob(&gl) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_glob_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } rv = NGX_CONF_OK; for ( ;; ) { n = ngx_read_glob(&gl, &file); if (n != NGX_OK) { break; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); rv = ngx_conf_parse(cf, &file); if (rv != NGX_CONF_OK) { break; } } ngx_close_glob(&gl); return rv; }
static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value, file; value = cf->args->elts; file = value[1]; if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); }
static u_char * ngx_http_graphicsmagickd_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *path, size_t *root_length, size_t reserved) { u_char *last; size_t alias; ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); alias = clcf->alias ? clcf->name.len : 0; reserved += uri->len - alias + 1; if (clcf->root_lengths == NULL) { *root_length = clcf->root.len; path->len = clcf->root.len + reserved; path->data = ngx_palloc(r->pool, path->len); if (path->data == NULL) { return NULL; } last = ngx_copy(path->data, clcf->root.data, clcf->root.len); } else { path->len = reserved; path->data = ngx_palloc(r->pool, reserved); if (path->data == NULL) { return NULL; } if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0) == NGX_ERROR) { return NULL; } *root_length = path->len - reserved; last = path->data + *root_length; } last = ngx_cpystrn(last, uri->data + alias, uri->len - alias + 1); return last; }
u_char * ngx_http_map_filename_to_path(ngx_http_request_t *r, ngx_str_t *filename, ngx_str_t *path) { u_char *last; ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->alias) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "At present \"alias\" not supported in static delete " "module"); return NULL; } if (clcf->root_lengths == NULL) { path->len = clcf->root.len + filename->len + 2; path->data = ngx_pnalloc(r->pool, path->len); if (path->data == NULL) { return NULL; } last = ngx_copy(path->data, clcf->root.data, clcf->root.len); } else { if (ngx_http_script_run(r, path, clcf->root_lengths->elts, filename->len + 2, clcf->root_values->elts) == NULL) { return NULL; } if (ngx_conf_full_name((ngx_cycle_t *)ngx_cycle, path, 0) != NGX_OK) { return NULL; } last = path->data + (path->len - filename->len - 2); } if (filename->data[0] != '/') { *last++ = '/'; } last = ngx_cpystrn(last, filename->data, filename->len + 1); return last; }
ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { int sslerr; static unsigned char dh1024_pem[] = { "-----BEGIN DH PARAMETERS-----\n" "MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc\n" "y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl\n" "7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC\n" "-----END DH PARAMETERS-----" }; if (file->len == 0) { sslerr = x509parse_dhm(&ssl->dhm_ctx, dh1024_pem, ngx_strlen(dh1024_pem)); if (sslerr != 0) { ngx_mbedtls_error(NGX_LOG_EMERG, ssl->log, 0, sslerr, "x509parse_dhm() failed"); return NGX_ERROR; } return NGX_OK; } if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) { return NGX_ERROR; } sslerr = x509parse_dhmfile(&ssl->dhm_ctx, (char *) file->data); if (sslerr != 0) { ngx_mbedtls_error(NGX_LOG_EMERG, ssl->log, 0, sslerr, "x509parse_dhmfile(%p, \"%s\") failed", &ssl->dhm_ctx, file->data); return NGX_ERROR; } return NGX_OK; }
char * ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, ngx_path_init_t *init) { if (*path) { return NGX_CONF_OK; } if (prev) { *path = prev; return NGX_CONF_OK; } *path = ngx_palloc(cf->pool, sizeof(ngx_path_t)); if (*path == NULL) { return NGX_CONF_ERROR; } (*path)->name = init->name; if (ngx_conf_full_name(cf->cycle, &(*path)->name, 0) != NGX_OK) { return NGX_CONF_ERROR; } (*path)->level[0] = init->level[0]; (*path)->level[1] = init->level[1]; (*path)->level[2] = init->level[2]; (*path)->len = init->level[0] + (init->level[0] ? 1 : 0) + init->level[1] + (init->level[1] ? 1 : 0) + init->level[2] + (init->level[2] ? 1 : 0); (*path)->manager = NULL; (*path)->loader = NULL; (*path)->conf_file = NULL; if (ngx_add_path(cf, path) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_str_t path; ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->root_lengths == NULL) { v->len = clcf->root.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = clcf->root.data; } else { if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0, clcf->root_values->elts) == NULL) { return NGX_ERROR; } if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) { return NGX_ERROR; } v->len = path.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = path.data; } return NGX_OK; }
char * ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, ngx_path_init_t *init) { ngx_uint_t i; if (*path) { return NGX_CONF_OK; } if (prev) { *path = prev; return NGX_CONF_OK; } *path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); if (*path == NULL) { return NGX_CONF_ERROR; } (*path)->name = init->name; if (ngx_conf_full_name(cf->cycle, &(*path)->name, 0) != NGX_OK) { return NGX_CONF_ERROR; } for (i = 0; i < NGX_MAX_PATH_LEVEL; i++) { (*path)->level[i] = init->level[i]; (*path)->len += init->level[i] + (init->level[i] ? 1 : 0); } if (ngx_add_path(cf, path) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value; value = cf->args->elts; if (value[1].len == 6 && ngx_strcmp(value[1].data, "stderr") == 0) { cf->cycle->new_log->file->fd = ngx_stderr.fd; cf->cycle->new_log->file->name.len = 0; cf->cycle->new_log->file->name.data = NULL; } else { cf->cycle->new_log->file->name = value[1]; if (ngx_conf_full_name(cf->cycle, &cf->cycle->new_log->file->name, 0) == NGX_ERROR) { return NGX_CONF_ERROR; } } return ngx_set_error_log_levels(cf, cf->cycle->new_log); }
//参考: //http://blog.csdn.net/livelylittlefish/article/details/7262750 static char * ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_core_conf_t *ccf = conf; //初始化daemon、master等 ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); ngx_conf_init_msec_value(ccf->timer_resolution, 0); ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); #if (NGX_HAVE_SCHED_SETAFFINITY) if (ccf->cpu_affinity_n && ccf->cpu_affinity_n != 1 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes) { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "number of the \"worker_processes\" is not equal to " "the number of the \"worker_cpu_affinity\" mask, " "using last mask for remaining worker processes"); } #endif #if (NGX_THREADS) ngx_conf_init_value(ccf->worker_threads, 0); ngx_threads_n = ccf->worker_threads; ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024); #endif //初始化pid、oldpid if (ccf->pid.len == 0) { ngx_str_set(&ccf->pid, NGX_PID_PATH); } if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) { return NGX_CONF_ERROR; } ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT); ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len); if (ccf->oldpid.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len), NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT)); #if !(NGX_WIN32) //初始化username,user,group if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) { struct group *grp; struct passwd *pwd; ngx_set_errno(0); pwd = getpwnam(NGX_USER); if (pwd == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getpwnam(\"" NGX_USER "\") failed"); return NGX_CONF_ERROR; } ccf->username = NGX_USER; ccf->user = pwd->pw_uid; ngx_set_errno(0); grp = getgrnam(NGX_GROUP); if (grp == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getgrnam(\"" NGX_GROUP "\") failed"); return NGX_CONF_ERROR; } ccf->group = grp->gr_gid; } if (ccf->lock_file.len == 0) { ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH); } //初始化lock_file if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) { return NGX_CONF_ERROR; } { ngx_str_t lock_file; lock_file = cycle->old_cycle->lock_file; if (lock_file.len) { lock_file.len--; if (ccf->lock_file.len != lock_file.len || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len) != 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "\"lock_file\" could not be changed, ignored"); } //初始化ngx_cycle->lock_file cycle->lock_file.len = lock_file.len + 1; lock_file.len += sizeof(".accept"); cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } } else { cycle->lock_file.len = ccf->lock_file.len + 1; cycle->lock_file.data = ngx_pnalloc(cycle->pool, ccf->lock_file.len + sizeof(".accept")); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data, ccf->lock_file.len), ".accept", sizeof(".accept")); } } #endif return NGX_CONF_OK; }
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) { u_char *p; size_t len; if (ngx_prefix) { len = ngx_strlen(ngx_prefix); p = ngx_prefix; if (!ngx_path_separator(*p)) { p = ngx_pnalloc(cycle->pool, len + 1); if (p == NULL) { return NGX_ERROR; } ngx_memcpy(p, ngx_prefix, len); p[len++] = '/'; } cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; } else { #ifndef NGX_PREFIX p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH); if (p == NULL) { return NGX_ERROR; } if (ngx_getcwd(p, NGX_MAX_PATH) == 0) { ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed"); return NGX_ERROR; } len = ngx_strlen(p); p[len++] = '/'; cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; #else #ifdef NGX_CONF_PREFIX ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX); #else ngx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endif ngx_str_set(&cycle->prefix, NGX_PREFIX); #endif } if (ngx_conf_file) { cycle->conf_file.len = ngx_strlen(ngx_conf_file); cycle->conf_file.data = ngx_conf_file; } else { ngx_str_set(&cycle->conf_file, NGX_CONF_PATH); } if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) { return NGX_ERROR; } for (p = cycle->conf_file.data + cycle->conf_file.len - 1; p > cycle->conf_file.data; p--) { if (ngx_path_separator(*p)) { // 将config_file路径按照分隔符“/”分割 cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1; cycle->conf_prefix.data = ngx_cycle->conf_file.data; break; } } if (ngx_conf_params) { cycle->conf_param.len = ngx_strlen(ngx_conf_params); cycle->conf_param.data = ngx_conf_params; } if (ngx_test_config) { cycle->log->log_level = NGX_LOG_INFO; } return NGX_OK; }
char * ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { off_t max_size; u_char *last, *p; time_t inactive; ssize_t size; ngx_str_t s, name, *value; ngx_uint_t i, n; ngx_http_file_cache_t *cache; cache = ngx_pcalloc(cf->pool, sizeof(ngx_http_file_cache_t)); if (cache == NULL) { return NGX_CONF_ERROR; } cache->path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); if (cache->path == NULL) { return NGX_CONF_ERROR; } inactive = 600; name.len = 0; size = 0; max_size = NGX_MAX_OFF_T_VALUE; value = cf->args->elts; cache->path->name = value[1]; if (cache->path->name.data[cache->path->name.len - 1] == '/') { cache->path->name.len--; } if (ngx_conf_full_name(cf->cycle, &cache->path->name, 0) != NGX_OK) { return NGX_CONF_ERROR; } for (i = 2; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "levels=", 7) == 0) { p = value[i].data + 7; last = value[i].data + value[i].len; for (n = 0; n < 3 && p < last; n++) { if (*p > '0' && *p < '3') { cache->path->level[n] = *p++ - '0'; cache->path->len += cache->path->level[n] + 1; if (p == last) { break; } if (*p++ == ':' && n < 2 && p != last) { continue; } goto invalid_levels; } goto invalid_levels; } if (cache->path->len < 10 + 3) { continue; } invalid_levels: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid \"levels\" \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (ngx_strncmp(value[i].data, "keys_zone=", 10) == 0) { name.data = value[i].data + 10; p = (u_char *) ngx_strchr(name.data, ':'); if (p) { *p = '\0'; name.len = p - name.data; p++; s.len = value[i].data + value[i].len - p; s.data = p; size = ngx_parse_size(&s); if (size > 8191) { continue; } } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid keys zone size \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) { s.len = value[i].len - 9; s.data = value[i].data + 9; inactive = ngx_parse_time(&s, 1); if (inactive < 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid inactive value \"%V\"", &value[i]); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "max_size=", 9) == 0) { s.len = value[i].len - 9; s.data = value[i].data + 9; max_size = ngx_parse_offset(&s); if (max_size < 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid max_size value \"%V\"", &value[i]); return NGX_CONF_ERROR; } continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (name.len == 0 || size == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%V\" must have \"keys_zone\" parameter", &cmd->name); return NGX_CONF_ERROR; } cache->path->manager = ngx_http_file_cache_manager; cache->path->loader = ngx_http_file_cache_loader; cache->path->data = cache; if (ngx_add_path(cf, &cache->path) != NGX_OK) { return NGX_CONF_ERROR; } cache->shm_zone = ngx_shared_memory_add(cf, &name, size, cmd->post); if (cache->shm_zone == NULL) { return NGX_CONF_ERROR; } if (cache->shm_zone->data) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate zone \"%V\"", &name); return NGX_CONF_ERROR; } cache->shm_zone->init = ngx_http_file_cache_init; cache->shm_zone->data = cache; cache->inactive = inactive; cache->max_size = max_size; return NGX_CONF_OK; }
static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ngx_int_t rc; ngx_str_t *value, file; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; ngx_http_variable_value_t *var, **vp; ctx = cf->ctx; value = cf->args->elts; if (cf->args->nelts == 1 && ngx_strcmp(value[0].data, "hostnames") == 0) { ctx->hostnames = 1; return NGX_CONF_OK; } else if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; } else if (value[0].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid first parameter"); return NGX_CONF_ERROR; } if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } key = 0; for (i = 0; i < value[1].len; i++) { key = ngx_hash(key, value[1].data[i]); } key %= ctx->keys.hsize; vp = ctx->values_hash[key].elts; if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { if (value[1].len != (size_t) vp[i]->len) { continue; } if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { var = vp[i]; goto found; } } } else { if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, sizeof(ngx_http_variable_value_t *)) != NGX_OK) { return NGX_CONF_ERROR; } } var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); if (var == NULL) { return NGX_CONF_ERROR; } var->len = value[1].len; var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); if (var->data == NULL) { return NGX_CONF_ERROR; } var->valid = 1; var->no_cacheable = 0; var->not_found = 0; vp = ngx_array_push(&ctx->values_hash[key]); if (vp == NULL) { return NGX_CONF_ERROR; } *vp = var; found: if (ngx_strcmp(value[0].data, "default") == 0) { if (ctx->default_value) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate default map parameter"); return NGX_CONF_ERROR; } ctx->default_value = var; return NGX_CONF_OK; } if (value[0].len && value[0].data[0] == '!') { value[0].len--; value[0].data++; } rc = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); if (rc == NGX_OK) { return NGX_CONF_OK; } if (rc == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } return NGX_CONF_ERROR; }
/* * 打开文件 */ ngx_open_file_t * ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name) { ngx_str_t full; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; #if (NGX_SUPPRESS_WARN) ngx_str_null(&full); #endif if (name->len) { full = *name; if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) { return NULL; } part = &cycle->open_files.part; //文件链表 file = part->elts; //文件 for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { //单个part数据完了,下一个part if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; //重置为0,很重要 } /*检查是否已经有相同文件*/ if (full.len != file[i].name.len) { continue; } if (ngx_strcmp(full.data, file[i].name.data) == 0) { return &file[i]; } } } file = ngx_list_push(&cycle->open_files); //文件压入链表,实际上只是返回了一个槽位 if (file == NULL) { return NULL; } if (name->len) { file->fd = NGX_INVALID_FILE; file->name = full; } else { file->fd = ngx_stderr; file->name = *name; } file->flush = NULL; file->data = NULL; return file; }
/* * 包含一个配置文件,并读取解析配置文件 */ char * ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t n; ngx_str_t *value, file, name; ngx_glob_t gl; value = cf->args->elts; file = value[1]; //配置文件名 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } /*是否包含正则表达式*/ if (strpbrk((char *) file.data, "*?[") == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } ngx_memzero(&gl, sizeof(ngx_glob_t)); gl.pattern = file.data; gl.log = cf->log; gl.test = 1; if (ngx_open_glob(&gl) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_glob_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } rv = NGX_CONF_OK; /*解析配置文件, 所有满足正则表达式的文件 */ for ( ;; ) { n = ngx_read_glob(&gl, &name); if (n != NGX_OK) { break; } file.len = name.len++; file.data = ngx_pstrdup(cf->pool, &name); if (file.data == NULL) { return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); rv = ngx_conf_parse(cf, &file); if (rv != NGX_CONF_OK) { break; } } ngx_close_glob(&gl); return rv; }
static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { BIO *bio; int len; u_char *p, *buf; OCSP_RESPONSE *response; ngx_ssl_stapling_t *staple; staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) { return NGX_ERROR; } bio = BIO_new_file((char *) file->data, "r"); if (bio == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BIO_new_file(\"%s\") failed", file->data); return NGX_ERROR; } response = d2i_OCSP_RESPONSE_bio(bio, NULL); if (response == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data); BIO_free(bio); return NGX_ERROR; } len = i2d_OCSP_RESPONSE(response, NULL); if (len <= 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "i2d_OCSP_RESPONSE(\"%s\") failed", file->data); goto failed; } buf = ngx_alloc(len, ssl->log); if (buf == NULL) { goto failed; } p = buf; len = i2d_OCSP_RESPONSE(response, &p); if (len <= 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "i2d_OCSP_RESPONSE(\"%s\") failed", file->data); ngx_free(buf); goto failed; } OCSP_RESPONSE_free(response); BIO_free(bio); staple->staple.data = buf; staple->staple.len = len; staple->valid = NGX_MAX_TIME_T_VALUE; return NGX_OK; failed: OCSP_RESPONSE_free(response); BIO_free(bio); return NGX_ERROR; }
char * ngx_xconf_include_uri(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *arg, uri, filename, scheme_name; ngx_xconf_ctx_t ctx; ngx_flag_t is_last_elt; ngx_uint_t i; ngx_str_t *cmd_name; u_char need_next; ngx_str_t ofilename_prefix = ngx_string("$file"), ofilename_suffix = ngx_string("l$line.conf"), ofilename_suffix2 = ngx_string("conf"); char *rv; u_char *s; /* 用于临时分配内存用 */; lua_State *L; ngx_xconf_scheme_t *scheme; arg = cf->args->elts; cmd_name = &arg[0]; scheme = ngx_xconf_schemes; if ((scheme == NULL) || (scheme->name.len == 0)) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: no scheme define.", cmd_name); return NGX_CONF_ERROR; } /* 参数说明见 README */ uri.len = 0; /* 如果没设定报错 */ filename.len = 0; /* 如果没设定就默认给一个 */ ctx.evaluri = 1; /* 默认 eval uri */ ctx.keep_error_cachefile = 0; /* 默认删除解析出错的 cachefile */ ctx.pre_usecache = -1; /* 默认不使用 cachefile */ ctx.fail_usecache = -1; /* 默认不使用 cachefile */ ctx.fetch_content = NULL; ctx.do_cachefile = 0; need_next = 0; is_last_elt = 0; /* 解析参数 {{{ */ for (i = 1; i < cf->args->nelts; i++) { if (! (arg[i].len)) { continue; } is_last_elt = i == cf->args->nelts - 1; if (need_next) { switch(need_next) { case 'o': filename.data = arg[i].data; filename.len = arg[i].len; break; case 'O': filename.len = ofilename_prefix.len + arg[i].len + ofilename_suffix.len + sizeof("..") - 1; filename.data = ngx_palloc(cf->pool, filename.len + 1); ngx_snprintf(filename.data, filename.len, "%V.%V.%V", &ofilename_prefix, &arg[i], &ofilename_suffix); break; case 'I': filename.len = ofilename_prefix.len + arg[i].len + ofilename_suffix2.len + sizeof("..") - 1; filename.data = ngx_palloc(cf->pool, filename.len + 1); ngx_snprintf(filename.data, filename.len, "%V.%V.%V", &ofilename_prefix, &arg[i], &ofilename_suffix2); break; case 't': ctx.timeout = ngx_parse_time(&arg[i], 1); if (ctx.timeout == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-t %V] value error.", cmd_name, &arg[i]); return NGX_CONF_ERROR; } break; case 'c': if (arg[i].len == 2 && arg[i].data[0] == '-' && arg[i].data[1] == '1') { ctx.pre_usecache = -1 * (arg[i].data[1] - '0'); } else { ctx.pre_usecache = ngx_parse_time(&arg[i], 1); if (ctx.pre_usecache == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-c %V] value error.", cmd_name, &arg[i]); return NGX_CONF_ERROR; } } break; case 'C': if (arg[i].len == 2 && arg[i].data[0] == '-' && (arg[i].data[1] >= '1' && arg[i].data[1] <= '2')) { ctx.fail_usecache = -1 * (arg[i].data[1] - '0'); } else { ctx.fail_usecache = ngx_parse_time(&arg[i], 1); if (ctx.fail_usecache == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-C %V] value error.", cmd_name, &arg[i]); return NGX_CONF_ERROR; } } break; default: /* 通常不会到这里 */ ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: unknown option [%c] .", cmd_name, need_next); return NGX_CONF_ERROR; } need_next = 0; continue; } else { if (arg[i].data[0] == '-') { /* 现在只支持 -x */ if (arg[i].len != 2) { goto unknow_opt; } switch(arg[i].data[1]) { case 'K': ctx.keep_error_cachefile = 1; break; case 'n': ctx.evaluri = 0; break; case 'c': case 'C': case 'o': case 'I': case 'O': case 't': need_next = arg[i].data[1]; if (is_last_elt) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-%c] need a value.", cmd_name, need_next); return NGX_CONF_ERROR; } break; default: goto unknow_opt; } continue; } else { /* this will be the uri */ uri.data = arg[i].data; uri.len = arg[i].len; continue; } } goto unknow_opt; } /* }}} */ /* 因为上面不需要用到 lua 的功能,所有此刻才初始化 lua vm {{{ */ L = luaL_newstate(); if (L == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: create lua vm fail.", cmd_name); return NGX_CONF_ERROR; } /* XXX 从这以下如果出错,需要 goto error; 因为要 close lua vm */ ctx.lua = L; luaL_openlibs(L); { int rc; ngx_str_t msg; rc = luaL_loadbuffer(L, (const char*) xconf_util_lua, sizeof(xconf_util_lua), "ngx_xconf_util.lua(embed)"); if (rc != 0) { msg.data = (u_char *) lua_tolstring(L, -1, &msg.len); if (msg.data == NULL) { msg.data = (u_char *) "unknown reason"; msg.len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, cf->log, 0, "xconf load lua code error: %V.", &msg); lua_pop(L, 1); rv = NULL; goto error; } } /* 这个 lua 文件会创建 若干个 全局函数,如: format */ if (ngx_xconf_util_lua_pcall(cf, L, 0, 0, 0, 0) != NGX_OK) { rv = NULL; goto error; } /* }}} */ /* 创建变量 table 到 lua vm (var_ctx) 里,用于变量插值 {{{ */ lua_createtable(L, /* i */0, /* key */10); /* var_ctx */ lua_pushlstring(L, (char *)cf->conf_file->file.name.data, cf->conf_file->file.name.len); lua_setfield(L, -2, "file"); lua_pushnumber(L, cf->conf_file->line); lua_setfield(L, -2, "line"); lua_pushlstring(L, (char *)cf->cycle->prefix.data, cf->cycle->prefix.len); lua_setfield(L, -2, "prefix"); lua_pushlstring(L, (char *)cf->cycle->conf_prefix.data, cf->cycle->conf_prefix.len); lua_setfield(L, -2, "conf_prefix"); lua_pushnumber(L, (int) ngx_pid); lua_setfield(L, -2, "pid"); lua_pushlstring(L, (char *)cf->cycle->hostname.data, cf->cycle->hostname.len); lua_setfield(L, -2, "hostname"); { ngx_time_t *tp = ngx_timeofday(); lua_pushnumber(L, (int) (tp->sec)); lua_setfield(L, -2, "time"); /* var_ctx */ } lua_setfield(L, LUA_GLOBALSINDEX, "var_ctx"); /* }}} */ /* 对 uri 进行变量插值 {{{ */ if (ctx.evaluri) { lua_getfield(L, LUA_GLOBALSINDEX, "format"); /* got the format function */ lua_pushlstring(L, (char *) uri.data, uri.len); if (ngx_xconf_util_lua_pcall(cf, L, 1, 1, 0, 0) != NGX_OK) { rv = NULL; goto error; } uri.data = (u_char *) lua_tolstring(L, -1, &uri.len); s = ngx_palloc(cf->pool, uri.len); ngx_memcpy(s, uri.data, uri.len); uri.data = s; s = NULL; lua_pop(L, 1); } if (! (uri.len)) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: must give us uri.", cmd_name); rv = NULL; goto error; } ctx.uri.len = uri.len; ctx.uri.data = uri.data; /* }}} */ /* 计算 uri 的 scheme_name {{{ */ /* 如果以 '//' 开头 认为是 http: */ if (uri.len > 2 && uri.data[0] == '/' && uri.data[1] == '/') { ctx.noscheme_uri.data = uri.data; ctx.noscheme_uri.len = uri.len; scheme_name.len = sizeof("http") - 1; scheme_name.data = ngx_palloc(cf->pool, scheme_name.len + 1); ngx_cpystrn(scheme_name.data, (u_char *)"http", scheme_name.len + 1); /* 如果以 '/' 或 './' 开头 认为是 file: */ } else if (uri.data[0] == '/' || (uri.len > 2 && uri.data[0] == '.' && uri.data[1] == '/')) { size_t is_abs = uri.data[0] == '/'; u_char *data = uri.data + (is_abs ? 0 : 2); size_t len = uri.len - (is_abs ? 0 : 2); ctx.noscheme_uri.len = len + 2; ctx.noscheme_uri.data = ngx_palloc(cf->pool, len + 2 + 1); ctx.noscheme_uri.data[0] = '/'; ctx.noscheme_uri.data[1] = '/'; ngx_cpystrn(ctx.noscheme_uri.data + 2, data, len + 1); scheme_name.len = sizeof("file") - 1; scheme_name.data = ngx_palloc(cf->pool, scheme_name.len + 1); ngx_cpystrn(scheme_name.data, (u_char *)"file", scheme_name.len + 1); } else { u_char c; ngx_str_t tmp_scheme; size_t i, maxi, found; /* find scheme: [a-z_][a-z_0-9+.-]: , max_scheme_len */ tmp_scheme.data = ngx_palloc(cf->pool, max_scheme_len); tmp_scheme.len = 0; i = 0; maxi = uri.len - 1; found = 0; while (i < max_scheme_len && i <= maxi) { c = uri.data[i]; if (c == ':') { found = 1; break; } tmp_scheme.data[i] = c; tmp_scheme.len++; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.') { } else { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: uri (%V...) have no valid scheme name.", cmd_name, &tmp_scheme); rv = NULL; goto error; } /* XXX important */ i++; } if (! (found && tmp_scheme.len)) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: uri (%V) have no valid scheme name.", cmd_name, &uri); rv = NULL; goto error; } scheme_name.len = tmp_scheme.len; scheme_name.data = tmp_scheme.data; scheme_name.data[tmp_scheme.len] = '\0'; /* 1 -> the ':' after scheme name */ ctx.noscheme_uri.len = uri.len - tmp_scheme.len - 1; ctx.noscheme_uri.data = uri.data + tmp_scheme.len + 1; } /* }}} */ /* 查找当前 scheme {{{ */ for ( /* void */ ; scheme->name.len; scheme++) { if (scheme_name.len == scheme->name.len && ngx_strcmp(scheme_name.data, scheme->name.data) == 0) { break; } } if (! scheme->name.len) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: no scheme found for \"%V\".", cmd_name, &ctx.scheme); rv = NULL; goto error; } /* }}} */ ctx.scheme = scheme; /* 如果 scheme usecache 则计算 filename 并 判断 pre_usecache {{{ */ if (scheme->usecache) { /* filename 计算, 插值, 展开 {{{ */ if (! (filename.len)) { filename.len = ofilename_prefix.len + ofilename_suffix.len + sizeof(".") - 1; filename.data = ngx_palloc(cf->pool, filename.len + 1); ngx_snprintf(filename.data, filename.len, "%V.%V", &ofilename_prefix, &ofilename_suffix); } /* FIXME filename.data 是否需要 free ?? */ lua_getfield(L, LUA_GLOBALSINDEX, "format"); /* got the format function */ lua_pushlstring(L, (char *) filename.data, filename.len); if (ngx_xconf_util_lua_pcall(cf, L, 1, 1, 0, 0) != NGX_OK) { rv = NULL; goto error; } filename.data = (u_char *) lua_tolstring(L, -1, &filename.len); s = ngx_palloc(cf->pool, filename.len + 1); ngx_cpystrn(s, filename.data, filename.len + 1); /* 让 ngx_cpystrn 帮忙添加个 \0 */ filename.data = s; s = NULL; lua_pop(L, 1); if (ngx_conf_full_name(cf->cycle, &filename, 1) != NGX_OK) { rv = NULL; goto error; } /* }}} */ ctx.cachefile = ngx_palloc(cf->pool, sizeof(ngx_file_t)); if (ctx.cachefile == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: alloc cachefile error.", cmd_name); rv = NULL; goto error; } ngx_memzero(ctx.cachefile, sizeof(ngx_file_t)); ctx.cachefile->name = filename; ctx.cachefile->log = cf->log; dd("pre-usecache: %d, %d", (int)ctx.scheme->pre_usecache, (int)ctx.pre_usecache); if (ctx.scheme->pre_usecache && ctx.pre_usecache > -1) { ngx_file_t *file; file = ctx.cachefile; /* 获取文件信息 FAIL */ if (ngx_file_info(file->name.data, &file->info) == -1) { /* 如果文件不存在则忽略,否则报错 */ if (errno != ENOENT) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: get file \"%V\" info error: %s.", cmd_name, file->name, strerror(errno)); rv = NULL; goto error; } /* 获取文件信息 OK, 有没可能是个 目录 ?? ,如果谁这么配置 !!! */ } else { int now; /* 只要文件存在就用 */ if (ctx.pre_usecache == 0) { goto do_cachefile; } ngx_time_update(); now = (int)ngx_time(); dd("pre-usecache now: %d, mtime: %d, diff: %d, pref: %d.", now, (int)file->info.st_mtime, now - (int)file->info.st_mtime, (int)ctx.pre_usecache); if (now - file->info.st_mtime <= ctx.pre_usecache) { goto do_cachefile; } } } } /* }}} */ ngx_log_error(NGX_LOG_INFO, cf->log, 0, "\n- - - - - - - -\ncmd_name: %V\nfileneme: %V\nuri: %V\npre_usecache: %d\nfail_usecache: %d\nevaluri: %d\nscheme: %V\nnoscheme_uri: %V\n- - - - - - - -", cmd_name, &filename, &uri, ctx.pre_usecache, ctx.fail_usecache, ctx.evaluri, &ctx.scheme->name, &ctx.noscheme_uri); /* 执行具体 scheme {{{ */ rv = scheme->handler(cf, cmd, conf, &ctx); if (rv == NGX_CONF_OK) { goto done; } else if (rv == NGX_XCONF_FETCH_ERROR) { /* do fail_usecache */ if (scheme->usecache) { goto fetch_fail; } else { /* 不可能 */ ngx_log_error(NGX_LOG_ERR, cf->log, 0, "if you see this error, please report it to author with \"%V\".", &scheme->name); rv = NULL; goto error; } } else if (rv == NGX_XCONF_FETCH_OK) { if (scheme->usecache) { if (ctx.fetch_content != NULL) { goto save_cachefile; } else if (ctx.do_cachefile) { goto do_cachefile; } } goto done; } else { goto error; } /* }}} */ goto done; fetch_fail: dd("fail-usecache: %d, %d", (int)ctx.scheme->fail_usecache, (int)ctx.fail_usecache); if (ctx.scheme->fail_usecache && ctx.fail_usecache != -1) { /* 删除 */ if (ctx.fail_usecache != -2) { ngx_delete_file(ctx.cachefile->name.data); rv = NULL; goto error; } else if (ctx.fail_usecache >= 0) { ngx_file_t *file; file = ctx.cachefile; /* 获取文件信息 FAIL */ if (ngx_file_info(file->name.data, &file->info) == -1) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: get file \"%V\" info in fetch_fail error: %s.", cmd_name, file->name, strerror(errno)); rv = NULL; goto error; /* 获取文件信息 OK, 有没可能是个 目录 ?? ,如果谁这么配置 !!! */ } else { int now; /* 只要文件存在就用 */ if (ctx.fail_usecache == 0) { goto do_cachefile; } ngx_time_update(); now = (int)ngx_time(); dd("fail-usecache now: %d, mtime: %d, diff: %d, pref: %d.", now, (int)file->info.st_mtime, now - (int)file->info.st_mtime, (int)ctx.fail_usecache); if (now - file->info.st_mtime <= ctx.fail_usecache) { goto do_cachefile; } } } else { /* 不可能 */ rv = NULL; goto error; } } rv = NULL; goto error; save_cachefile: { int rc; ctx.cachefile->fd = ngx_open_file(ctx.cachefile->name.data, O_WRONLY, O_CREAT | O_TRUNC , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if (ctx.cachefile->fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: open (%V) error: \"%s\".", cmd_name, &ctx.cachefile->name, strerror(errno)); rv = NULL; goto error; } dd("open cachefd: %s, %d", (char *)ctx.cachefile->name.data, ctx.cachefile->fd); rc = ngx_write_fd(ctx.cachefile->fd, ctx.fetch_content->data, ctx.fetch_content->len); if (rc == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: write data to (%V) error: \"%s\".", cmd_name, ctx.cachefile->name, strerror(errno)); rv = NULL; goto error; } else if ((size_t)rc != ctx.fetch_content->len) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: write data to (%V) incomplete: %z of %uz.", cmd_name, ctx.cachefile->name, rc, ctx.fetch_content->len); rv = NULL; goto error; } if (ngx_close_file(ctx.cachefile->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%: close cachefile error.", cmd_name); rv = NULL; goto error; } goto do_cachefile; } do_cachefile: if (! scheme->usecache) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: current scheme \"%V\" can not usecache.", cmd_name, &scheme->name); rv = NULL; goto error; } dd("do cachefile"); rv = ngx_conf_parse(cf, &ctx.cachefile->name); if (rv != NGX_CONF_OK) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "%V: do cachefile \"%V\" error.", cmd_name, &ctx.cachefile->name); /* 删除解析出错的 cachefile */ if (! ctx.keep_error_cachefile) { if (ngx_delete_file(ctx.cachefile->name.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "%V: delete cachefile \"%V\" error.", cmd_name, &ctx.cachefile->name); } } goto error; } goto done; done: lua_close(L); return NGX_CONF_OK; unknow_opt: ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: unknown option [%V].", cmd_name, &arg[i]); return NGX_CONF_ERROR; error: lua_close(L); return rv == NULL ? NGX_CONF_ERROR : rv; }