static ngx_int_t ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_log_t *log) { ngx_int_t rc; #if !(NGX_HAVE_OPENAT) rc = ngx_file_info(name->data, fi); if (rc == NGX_FILE_ERROR) { of->err = ngx_errno; of->failed = ngx_file_info_n; return NGX_FILE_ERROR; } return rc; #else ngx_fd_t fd; if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { rc = ngx_file_info(name->data, fi); if (rc == NGX_FILE_ERROR) { of->err = ngx_errno; of->failed = ngx_file_info_n; return NGX_FILE_ERROR; } return rc; } fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0, log); if (fd == NGX_INVALID_FILE) { return NGX_FILE_ERROR; } rc = ngx_fd_info(fd, fi); if (rc == NGX_FILE_ERROR) { of->err = ngx_errno; of->failed = ngx_fd_info_n; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%V\" failed", name); } return rc; #endif }
static void ngx_pipe_create_subdirs(char *filename, ngx_cycle_t *cycle) { ngx_file_info_t stat_buf; char dirname[1024]; char *p; for (p = filename; (p = strchr(p, '/')); p++) { if (p == filename) { continue; // Don't bother with the root directory } ngx_memcpy(dirname, filename, p - filename); dirname[p-filename] = '\0'; if (ngx_file_info(dirname, &stat_buf) < 0) { if (errno != ENOENT) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "stat [%s] failed", dirname); exit(2); } else { if ((ngx_create_dir(dirname, NGX_PIPE_DIR_ACCESS) < 0) && (errno != EEXIST)) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "mkdir [%s] failed", dirname); exit(2); } } } } }
void ngx_pipe_get_last_rollback_time(ngx_pipe_rollback_conf_t *rbcf) { int fd; struct flock lock; int ret; struct stat sb; fd = ngx_open_file(rbcf->logname, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); if (fd < 0) { //open lock file failed just use now rbcf->last_open_time = rbcf->time_now; return; } lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; ret = fcntl(fd, F_SETLKW, &lock); if (ret < 0) { close(fd); //lock failed just use now rbcf->last_open_time = rbcf->time_now; return; } //check time if (rbcf->interval > 0) { if (ngx_file_info(rbcf->backup[0], &sb) == -1) { //no backup file ,so need rollback just set 1 rbcf->last_open_time = 1; } else if (sb.st_ctime / rbcf->interval < ngx_time() / rbcf->interval) { //need rollback just set 1 rbcf->last_open_time = 1; } else { //just no need rollback rbcf->last_open_time = rbcf->time_now; } } else { rbcf->last_open_time = rbcf->time_now; } close(fd); }
static ngx_int_t ngx_http_url_encoding_convert_handler(ngx_http_request_t *r) { u_char *last; size_t root; ngx_int_t rc; ngx_str_t path; ngx_file_info_t of; ngx_http_url_encoding_convert_loc_conf_t *ulcf; ulcf = ngx_http_get_module_loc_conf(r, ngx_http_url_encoding_convert_module); if (!ulcf->enable) { return NGX_DECLINED; } /* before rewrite */ if (r->phase_handler == NGX_HTTP_POST_READ_PHASE && ulcf->phase == NGX_HTTP_PREACCESS_PHASE) { return NGX_DECLINED; } /* after rewrite */ if (r->phase_handler > NGX_HTTP_POST_READ_PHASE && ulcf->phase == NGX_HTTP_POST_READ_PHASE) { return NGX_DECLINED; } last = ngx_http_map_uri_to_path(r, &path, &root, 0); if (last == NULL) { return NGX_DECLINED; } path.len = last - path.data; if (ngx_file_info(path.data, &of) == NGX_FILE_ERROR) { rc = ngx_http_url_encoding_convert_iconv(r, (const char *)ulcf->from_encode.data, (const char *)ulcf->to_encode.data); if (rc == NGX_OK) { return rc; } } return NGX_DECLINED; }
static ngx_int_t ngx_http_fsutil_create_dir_if_not_found( ngx_log_t *log, char *path ) { ngx_file_info_t fi; ngx_int_t rc; if ( ngx_file_info( path, &fi ) == NGX_FILE_ERROR ) { rc = ngx_create_dir( path, 0700 ); if ( 0 != rc ) { ngx_log_error(NGX_LOG_ERR, log, 0, "creating dir failed:%s", path); /* TODO elaborate error */ return rc; } } else { if ( ! ngx_is_dir( &fi ) ) { return NGX_ENOTDIR; } /* * if ( ngx_is_dir( &fi ) ) { * return NGX_OK; * } * else if ( ngx_is_file( &fi ) || ngx_is_link( &fi ) ) { * ngx_log_error(NGX_LOG_ERR, log, 0, * "Normal file or link as path element:%s", path); * [> TODO elaborate error <] * return NGX_ENOTDIR; * } * else { * [> TODO elaborate error <] * return NGX_ENOTDIR; * } */ } return NGX_OK; }
static ngx_inline ngx_str_t get_readme_path(ngx_http_request_t *r, const ngx_str_t *path) { u_char *last; ngx_file_info_t info; ngx_str_t fullpath = ngx_null_string; ngx_http_fancyindex_loc_conf_t *alcf = ngx_http_get_module_loc_conf(r, ngx_http_fancyindex_module); if (alcf->readme.len == 0) /* Readme files are disabled */ return fullpath; fullpath.len = path->len + 2 + alcf->readme.len; fullpath.data = ngx_palloc(r->pool, fullpath.len); last = ngx_cpymem_str(fullpath.data, *path); *last++ = '/'; last = ngx_cpymem_str(last, alcf->readme); *last++ = '\0'; /* File does not exists, or cannot be accessed */ if (ngx_file_info(fullpath.data, &info) != 0) fullpath.len = 0; return fullpath; }
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_file_info_t fi; 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) { if (of->test_only) { if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) { of->err = ngx_errno; of->failed = ngx_file_info_n; return NGX_ERROR; } of->uniq = ngx_file_uniq(&fi); of->mtime = ngx_file_mtime(&fi); of->size = ngx_file_size(&fi); of->fs_size = ngx_file_fs_size(&fi); of->is_dir = ngx_is_dir(&fi); of->is_file = ngx_is_file(&fi); of->is_link = ngx_is_link(&fi); of->is_exec = ngx_is_exec(&fi); return NGX_OK; } 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) { /* file was not used often enough to keep open */ 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; of->failed = ngx_open_file_n; } 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) { /* * chances that directory became file are very small * so test_dir flag allows to use a single syscall * in ngx_file_info() instead of three syscalls */ 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; } /* file became directory */ } else if (of->err == 0) { /* file */ if (file->is_dir || file->err) { goto add_event; } if (of->uniq == file->uniq) { if (file->event) { file->use_event = 1; } of->is_directio = file->is_directio; goto update; } /* file was changed */ } else { /* error to cache */ if (file->err || file->is_dir) { goto update; } /* file was removed, etc. */ } 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; } /* not found */ 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->use_event = 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++; } } 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; }
static ngx_int_t ngx_http_lookup_and_send_cache_file(ngx_http_request_t *r,ngx_chain_t *out) { u_char buf[128]; u_char file_name[128] = "/tmp/image_cache/"; ngx_buf_t *b; ngx_pool_cleanup_t *cln; size_t name_len; u_char *uri_file_name; memset(buf,0,128); name_len = r->uri_end - r->uri_start; memcpy(buf,r->uri_start,name_len); uri_file_name = buf + 12; strncat((char*)file_name,(char *)uri_file_name,128); if(access((char *)file_name,F_OK) == 0) { b = ngx_palloc(r->pool, sizeof(ngx_buf_t)); ngx_memzero(b,sizeof(ngx_buf_t)); b->in_file = 1; b->file = ngx_palloc(r->pool, sizeof(ngx_file_t)); ngx_memzero(b->file,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(file_name,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); b->file->log = r->connection->log; if(b->file->fd <= 0){ return NGX_HTTP_NOT_FOUND; } if(ngx_file_info(file_name,&b->file->info) == NGX_FILE_ERROR){ ngx_http_finalize_request(r,NGX_HTTP_INTERNAL_SERVER_ERROR); } if(b->file->info.st_size < 128) return NGX_HTTP_NOT_FOUND; //r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED; r->headers_out.content_length_n = b->file->info.st_size; if (r->headers_out.content_length) { r->headers_out.content_length->hash = 0; } r->headers_out.content_length = NULL; b->file_pos = 0; b->file_last = b->file->info.st_size; b->last_buf = 1; out->buf = b; out->next = NULL; cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); if(cln == NULL){ ngx_http_finalize_request(r,NGX_ERROR); } cln->handler = ngx_pool_cleanup_file; ngx_pool_cleanup_file_t *clnf = cln->data; clnf->fd = b->file->fd; clnf->log = r->pool->log; return NGX_OK; } return NGX_HTTP_NOT_FOUND; }
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; }
static ngx_int_t ngx_rtmp_dash_ensure_directory(ngx_rtmp_session_t *s) { size_t len; ngx_file_info_t fi; ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_dash_app_conf_t *dacf; static u_char path[NGX_MAX_PATH + 1]; dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); *ngx_snprintf(path, sizeof(path) - 1, "%V", &dacf->path) = 0; if (ngx_file_info(path, &fi) == NGX_FILE_ERROR) { if (ngx_errno != NGX_ENOENT) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: " ngx_file_info_n " failed on '%V'", &dacf->path); return NGX_ERROR; } /* ENOENT */ if (ngx_create_dir(path, NGX_RTMP_DASH_DIR_ACCESS) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: " ngx_create_dir_n " failed on '%V'", &dacf->path); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: directory '%V' created", &dacf->path); } else { if (!ngx_is_dir(&fi)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "dash: '%V' exists and is not a directory", &dacf->path); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: directory '%V' exists", &dacf->path); } if (!dacf->nested) { return NGX_OK; } ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); len = dacf->path.len; if (dacf->path.data[len - 1] == '/') { len--; } *ngx_snprintf(path, sizeof(path) - 1, "%*s/%V", len, dacf->path.data, &ctx->name) = 0; if (ngx_file_info(path, &fi) != NGX_FILE_ERROR) { if (ngx_is_dir(&fi)) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: directory '%s' exists", path); return NGX_OK; } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "dash: '%s' exists and is not a directory", path); return NGX_ERROR; } if (ngx_errno != NGX_ENOENT) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: " ngx_file_info_n " failed on '%s'", path); return NGX_ERROR; } /* NGX_ENOENT */ if (ngx_create_dir(path, NGX_RTMP_DASH_DIR_ACCESS) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: " ngx_create_dir_n " failed on '%s'", path); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: directory '%s' created", path); return NGX_OK; }
static void ngx_rtmp_auto_push_reconnect(ngx_event_t *ev) { ngx_rtmp_session_t *s = ev->data; ngx_rtmp_auto_push_conf_t *apcf; ngx_rtmp_auto_push_ctx_t *ctx; ngx_int_t *slot; ngx_int_t n; ngx_rtmp_relay_target_t at; u_char path[sizeof("unix:") + NGX_MAX_PATH]; u_char flash_ver[sizeof("APSH ,") + NGX_INT_T_LEN * 2]; u_char play_path[NGX_RTMP_MAX_NAME]; ngx_str_t name; u_char *p; ngx_str_t *u; ngx_pid_t pid; ngx_int_t npushed; ngx_core_conf_t *ccf; ngx_file_info_t fi; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: reconnect"); apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_rtmp_auto_push_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_auto_push_module); if (ctx == NULL) { return; } name.data = ctx->name; name.len = ngx_strlen(name.data); ngx_memzero(&at, sizeof(at)); ngx_str_set(&at.page_url, "nginx-auto-push"); at.tag = &ngx_rtmp_auto_push_module; if (ctx->args[0]) { at.play_path.data = play_path; at.play_path.len = ngx_snprintf(play_path, sizeof(play_path), "%s?%s", ctx->name, ctx->args) - play_path; } slot = ctx->slots; npushed = 0; for (n = 0; n < NGX_MAX_PROCESSES; ++n, ++slot) { if (n == ngx_process_slot) { continue; } pid = ngx_processes[n].pid; if (pid == 0 || pid == NGX_INVALID_PID) { continue; } if (*slot) { npushed++; continue; } at.data = &ngx_processes[n]; ngx_memzero(&at.url, sizeof(at.url)); u = &at.url.url; p = ngx_snprintf(path, sizeof(path) - 1, "unix:%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i", &apcf->socket_dir, n); *p = 0; if (ngx_file_info(path + sizeof("unix:") - 1, &fi) != NGX_OK) { ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: " ngx_file_info_n " failed: " "slot=%i pid=%P socket='%s'" "url='%V' name='%s'", n, pid, path, u, ctx->name); continue; } u->data = path; u->len = p - path; if (ngx_parse_url(s->connection->pool, &at.url) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auto_push: auto-push parse_url failed " "url='%V' name='%s'", u, ctx->name); continue; } p = ngx_snprintf(flash_ver, sizeof(flash_ver) - 1, "APSH %i,%i", (ngx_int_t) ngx_process_slot, (ngx_int_t) ngx_pid); at.flash_ver.data = flash_ver; at.flash_ver.len = p - flash_ver; ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: connect slot=%i pid=%P socket='%s' name='%s'", n, pid, path, ctx->name); if (ngx_rtmp_relay_push(s, &name, &at) == NGX_OK) { *slot = 1; npushed++; continue; } ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: connect failed: slot=%i pid=%P socket='%s'" "url='%V' name='%s'", n, pid, path, u, ctx->name); } ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_core_module); ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: pushed=%i total=%i failed=%i", npushed, ccf->worker_processes, ccf->worker_processes - 1 - npushed); if (ccf->worker_processes == npushed + 1) { return; } /* several workers failed */ slot = ctx->slots; for (n = 0; n < NGX_MAX_PROCESSES; ++n, ++slot) { pid = ngx_processes[n].pid; if (n == ngx_process_slot || *slot == 1 || pid == 0 || pid == NGX_INVALID_PID) { continue; } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auto_push: connect failed: slot=%i pid=%P name='%s'", n, pid, ctx->name); } if (!ctx->push_evt.timer_set) { ngx_add_timer(&ctx->push_evt, apcf->push_reconnect); } }
static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r) { u_char *p, *host, *last, ch; size_t len, root; ngx_err_t err; ngx_int_t rc, depth; ngx_uint_t overwrite, slash, dir; ngx_str_t path, uri; ngx_tree_ctx_t tree; ngx_copy_file_t cf; ngx_file_info_t fi; ngx_table_elt_t *dest, *over; ngx_ext_rename_file_t ext; ngx_http_dav_copy_ctx_t copy; ngx_http_dav_loc_conf_t *dlcf; if (r->headers_in.content_length_n > 0) { return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; } dest = r->headers_in.destination; if (dest == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent no \"Destination\" header"); return NGX_HTTP_BAD_REQUEST; } len = r->headers_in.server.len; if (len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent no \"Host\" header"); return NGX_HTTP_BAD_REQUEST; } #if (NGX_HTTP_SSL) if (r->connection->ssl) { if (ngx_strncmp(dest->value.data, "https://", sizeof("https://") - 1) != 0) { goto invalid_destination; } host = dest->value.data + sizeof("https://") - 1; } else #endif { if (ngx_strncmp(dest->value.data, "http://", sizeof("http://") - 1) != 0) { goto invalid_destination; } host = dest->value.data + sizeof("http://") - 1; } if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Destination\" URI \"%V\" is handled by " "different repository than the source URI", &dest->value); return NGX_HTTP_BAD_REQUEST; } last = dest->value.data + dest->value.len; for (p = host + len; p < last; p++) { if (*p == '/') { goto destination_done; } } invalid_destination: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid \"Destination\" header: \"%V\"", &dest->value); return NGX_HTTP_BAD_REQUEST; destination_done: if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/') || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/')) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "both URI \"%V\" and \"Destination\" URI \"%V\" " "should be either collections or non-collections", &r->uri, &dest->value); return NGX_HTTP_CONFLICT; } depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { if (r->method == NGX_HTTP_COPY) { if (depth != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Depth\" header must be 0 or infinity"); return NGX_HTTP_BAD_REQUEST; } } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Depth\" header must be infinity"); return NGX_HTTP_BAD_REQUEST; } } over = r->headers_in.overwrite; if (over) { if (over->value.len == 1) { ch = over->value.data[0]; if (ch == 'T' || ch == 't') { overwrite = 1; goto overwrite_done; } if (ch == 'F' || ch == 'f') { overwrite = 0; goto overwrite_done; } } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid \"Overwrite\" header: \"%V\"", &over->value); return NGX_HTTP_BAD_REQUEST; } overwrite = 1; overwrite_done: ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http copy from: \"%s\"", path.data); uri = r->uri; r->uri.len = last - p; r->uri.data = p; ngx_http_map_uri_to_path(r, ©.path, &root, 0); r->uri = uri; copy.path.len--; /* omit "\0" */ if (copy.path.data[copy.path.len - 1] == '/') { slash = 1; copy.path.len--; copy.path.data[copy.path.len] = '\0'; } else { slash = 0; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http copy to: \"%s\"", copy.path.data); if (ngx_file_info(copy.path.data, &fi) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_ENOENT) { return ngx_http_dav_error(r->connection->log, err, NGX_HTTP_NOT_FOUND, ngx_file_info_n, copy.path.data); } /* destination does not exist */ overwrite = 0; dir = 0; } else { /* destination exists */ if (ngx_is_dir(&fi) && !slash) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"%V\" could not be %Ved to collection \"%V\"", &r->uri, &r->method_name, &dest->value); return NGX_HTTP_CONFLICT; } if (!overwrite) { ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EEXIST, "\"%s\" could not be created", copy.path.data); return NGX_HTTP_PRECONDITION_FAILED; } dir = ngx_is_dir(&fi); } if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) { return ngx_http_dav_error(r->connection->log, ngx_errno, NGX_HTTP_NOT_FOUND, ngx_file_info_n, path.data); } if (ngx_is_dir(&fi)) { if (r->uri.data[r->uri.len - 1] != '/') { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"%V\" is collection", &r->uri); return NGX_HTTP_BAD_REQUEST; } if (overwrite) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http delete: \"%s\"", copy.path.data); rc = ngx_http_dav_delete_path(r, ©.path, dir); if (rc != NGX_OK) { return rc; } } } if (ngx_is_dir(&fi)) { path.len -= 2; /* omit "/\0" */ if (r->method == NGX_HTTP_MOVE) { if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) { return NGX_HTTP_CREATED; } } if (ngx_create_dir(copy.path.data, ngx_file_access(&fi)) == NGX_FILE_ERROR) { return ngx_http_dav_error(r->connection->log, ngx_errno, NGX_HTTP_NOT_FOUND, ngx_create_dir_n, copy.path.data); } copy.len = path.len; tree.init_handler = NULL; tree.file_handler = ngx_http_dav_copy_tree_file; tree.pre_tree_handler = ngx_http_dav_copy_dir; tree.post_tree_handler = ngx_http_dav_copy_dir_time; tree.spec_handler = ngx_http_dav_noop; tree.data = © tree.alloc = 0; tree.log = r->connection->log; if (ngx_walk_tree(&tree, &path) == NGX_OK) { if (r->method == NGX_HTTP_MOVE) { rc = ngx_http_dav_delete_path(r, &path, 1); if (rc != NGX_OK) { return rc; } } return NGX_HTTP_CREATED; } } else { if (r->method == NGX_HTTP_MOVE) { dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); ext.access = 0; ext.path_access = dlcf->access; ext.time = -1; ext.create_path = 1; ext.delete_file = 0; ext.log = r->connection->log; if (ngx_ext_rename_file(&path, ©.path, &ext) == NGX_OK) { return NGX_HTTP_NO_CONTENT; } return NGX_HTTP_INTERNAL_SERVER_ERROR; } dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); cf.size = ngx_file_size(&fi); cf.buf_size = 0; cf.access = dlcf->access; cf.time = ngx_file_mtime(&fi); cf.log = r->connection->log; if (ngx_copy_file(path.data, copy.path.data, &cf) == NGX_OK) { return NGX_HTTP_NO_CONTENT; } } return NGX_HTTP_INTERNAL_SERVER_ERROR; }
static ngx_int_t ngx_hls_handler(ngx_http_request_t *r) { //ngx_log_t *log = r->connection->log; if(!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))){ return NGX_HTTP_NOT_ALLOWED; } ngx_http_hls_loc_conf_t *elcf = ngx_http_get_module_loc_conf(r,ngx_http_hls_module); char* media_type = ngx_http_hls_convert_string(elcf->media_type); char* media_path = ngx_http_hls_convert_string(elcf->media_path); //char *media_type = (char*)elcf->media_type.data; //char *media_path = (char*)elcf->media_path.data; ngx_int_t rc = ngx_http_discard_request_body(r); if(rc != NGX_OK){ return rc; } if(strcmp(media_type,"live") == 0){ //TODO:Live media. } else{ ngx_str_t media_file; ngx_str_t media_start; ngx_str_t media_end; ngx_http_arg(r, (u_char *)"media", 5, &media_file); rc = ngx_http_arg(r,(u_char *)"start",5,&media_start); ngx_http_arg(r, (u_char *)"end", 3 , &media_end); if(rc == NGX_DECLINED || media_start.len == 0){ char filename[512]; bzero(filename,512); ngx_str_t type = ngx_string("application/x-mpegURL");//m3u8文件的content type ngx_snprintf((u_char*)filename,1024,"%s%V.m3u8",media_path,&media_file); //M3U8文件不存在,目前采用直接返回错误的方式,后期采用根据TS文件创建新的M3U8 if(access((char*)filename,F_OK) == -1){ ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"File[%s] is not exist!media_path = %s,media_file=%V",filename,media_path,&media_file); //r->headers_out.status = NGX_HTTP_NOT_FOUND; //rc = ngx_http_send_header(r); return NGX_HTTP_NOT_FOUND; } else{ ngx_chain_t *out = ngx_pcalloc(r->pool,sizeof(ngx_chain_t)); ngx_buf_t *b; //b = ngx_create_temp_buf(r->pool,sizeof(ngx_buf_t)); b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->in_file = 1; b->file = ngx_pcalloc(r->pool,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); if(b->file->fd == -1){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file->name.data = (u_char*)filename; b->file->name.len = sizeof(filename) -1; if(ngx_file_info(filename,&b->file->info) == NGX_FILE_ERROR){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->file->info.st_size; r->headers_out.content_type = type; b->file_pos = 0; b->file_last = b->file->info.st_size; b->last_in_chain = 1; b->file->log = r->connection->log; b->last_buf = 1; //清理文件句柄 /* ngx_pool_cleanup_t *cln = ngx_pool_cleanup_add(r->pool,sizeof(ngx_pool_cleanup_file_t)); if(cln == NULL){ return NGX_ERROR; } cln->handler = ngx_pool_cleanup_file; ngx_pool_cleanup_file_t *clnf = cln->data; clnf->fd = b->file->fd; clnf->name = b->file->name.data; clnf->log = r->pool->log; */ out->buf = b; out->next = NULL; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r,out); } } else{ ngx_str_t type = ngx_string("video/mp2t"); //ts文件的content type //ngx_str_t type = ngx_string("application/octet-stream"); char filename[512]; bzero(filename,512); ngx_snprintf((u_char*)filename,512,"%s%V.ts",media_path,&media_file); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"File[%s] is not exist!media_path = %s,media_file=%V",filename,media_path,&media_file); r->allow_ranges = 1; //开启range选项 char *start = ngx_http_hls_convert_string(media_start); char *end = ngx_http_hls_convert_string(media_end); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"start=%s;end=%s",start,end); ngx_chain_t *out = ngx_pcalloc(r->pool,sizeof(ngx_chain_t)); ngx_buf_t *b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->in_file = 1; b->file = ngx_pcalloc(r->pool,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN,0); if(b->file->fd == -1){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file->name.data = (u_char*)filename; b->file->name.len = sizeof(filename)-1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = atol(end)-atol(start); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"%d",r->headers_out.content_length_n); r->headers_out.content_type = type; b->file_pos = atol(start); b->file_last= atol(end); b->last_in_chain = 1; b->file->log = r->connection->log; b->last_buf = 1; out->buf = b; out->next = NULL; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r,out); } } return NGX_OK; }
static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log) { ngx_fd_t fd; ngx_file_info_t fi; of->fd = NGX_INVALID_FILE; if (of->test_dir) { if (ngx_file_info(name, &fi) == -1) { of->err = ngx_errno; return NGX_ERROR; } of->uniq = ngx_file_uniq(&fi); of->mtime = ngx_file_mtime(&fi); of->size = ngx_file_size(&fi); of->is_dir = ngx_is_dir(&fi); of->is_file = ngx_is_file(&fi); of->is_link = ngx_is_link(&fi); of->is_exec = ngx_is_exec(&fi); if (of->is_dir) { return NGX_OK; } } fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { of->err = ngx_errno; return NGX_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, ngx_fd_info_n " \"%s\" failed", name); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name); } return NGX_ERROR; } if (ngx_is_dir(&fi)) { if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name); } fd = NGX_INVALID_FILE; } of->fd = fd; of->uniq = ngx_file_uniq(&fi); of->mtime = ngx_file_mtime(&fi); of->size = ngx_file_size(&fi); of->is_dir = ngx_is_dir(&fi); of->is_file = ngx_is_file(&fi); of->is_link = ngx_is_link(&fi); of->is_exec = ngx_is_exec(&fi); return NGX_OK; }
static ngx_int_t ngx_http_filetransfer_handler2(ngx_http_request_t *r) { //必须是GET或者HEAD方法,否则返回405 Not Allowed if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } //丢弃请求中的包体 ngx_int_t rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_t type = ngx_string("text/html"); //返回的包体内容 //设置返回状态码 r->headers_out.status = NGX_HTTP_OK; //响应包是有包体内容的,需要设置Content-Length长度 //设置Content-Type r->headers_out.content_type = type; //发送HTTP头部 rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } ngx_buf_t *b; b = ngx_palloc(r->pool, sizeof(ngx_buf_t)); b->in_file=1; u_char* filename = (u_char*)"/usr/local/nginx/html/Google.html"; b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); b->file->log = r->connection->log; b->file->name.data = filename; b->file->name.len = sizeof(filename)-1; if (b->file->fd <= 0) { return NGX_HTTP_NOT_FOUND; } if (ngx_file_info(filename, &b->file->info) == NGX_FILE_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.content_length_n = b->file->info.st_size; b->file_pos = 0; b->file_last = b->file->info.st_size; ngx_pool_cleanup_t* cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_pool_cleanup_file; ngx_pool_cleanup_file_t *clnclnf = cln->data; clnclnf->fd = b->file->fd; clnclnf->name = b->file->name.data; clnclnf->log = r->pool->log; //构造发送时的ngx_chain_t结构体 ngx_chain_t out; //赋值ngx_buf_t out.buf = b; //设置next为NULL out.next = NULL; return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_store_plusplus_add_path(ngx_http_request_t *r, ngx_conhash_t *conhash, ngx_chain_t *out) { ngx_str_t value; size_t len; ngx_int_t rc; ngx_buf_t *b; u_char *p, *path_name; ngx_file_info_t fi; ngx_err_t err; rc = ngx_http_arg(r, (u_char *) STORE_VALUE_STR, sizeof(STORE_VALUE_STR) - 1, &value); if (rc != NGX_OK) { return rc; } b = ngx_create_temp_buf(r->pool, 1024); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (value.data[0] != '/') { b->last = ngx_sprintf(b->last, "ERROR: must be an absolute path." CRLF); rc = NGX_OK; goto done; } if (value.data[value.len - 1] == '/') { value.len--; } // check whether the store path is existent. len = value.len + 1 + sizeof(NGX_STORE_PLUSPLUS_TMP_PATH) - 1; path_name = ngx_pcalloc(r->pool, len + 1); if (path_name == NULL) { return NGX_ERROR; } p = ngx_cpymem(path_name, value.data, value.len); *p = '\0'; rc = ngx_file_info(path_name, &fi); if (rc == NGX_FILE_ERROR) { err = ngx_errno; b->last = ngx_strerror(err, b->last, b->end - b->last); *b->last++ = CR; *b->last++ = LF; rc = NGX_OK; goto done; } // create temp_path in this store path p = ngx_cpymem(path_name, value.data, value.len); *p++ = '/'; p = ngx_cpymem(p, NGX_STORE_PLUSPLUS_TMP_PATH, sizeof(NGX_STORE_PLUSPLUS_TMP_PATH) - 1); *p++ = '\0'; if (ngx_create_dir(path_name, ngx_dir_access(NGX_FILE_OWNER_ACCESS)) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_EEXIST) { b->last = ngx_strerror(err, b->last, b->end - b->last); *b->last++ = CR; *b->last++ = LF; rc = NGX_OK; goto done; } } rc = ngx_conhash_add_node(conhash, value.data, value.len, NULL); if (rc == NGX_OK) { b->last = ngx_sprintf(b->last, "Add node successfully!" CRLF); } if (rc == NGX_DECLINED) { b->last = ngx_sprintf(b->last, "The node already exists!" CRLF); rc = NGX_OK; } if (rc == NGX_AGAIN) { b->last = ngx_sprintf(b->last, "The conhash space is not enough!" CRLF); rc = NGX_OK; } done: b->last_buf = 1; out->buf = b; return rc; }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ssize_t n, len; ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; 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;//如果还有,标记i = 0,重新来 file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } len = file[i].pos - file[i].buffer; if (file[i].buffer && len != 0) {//要写进去吗,确认? n = ngx_write_fd(file[i].fd, file[i].buffer, len); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data); } else if (n != len) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len); } file[i].pos = file[i].buffer; } //再次打开以下这个文件 fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if !(NGX_WIN32)//如果是unix系的操作系统,需要设置文件拥有者啥的 if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; //得到文件的信息 if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } //修改文件所有者 if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } //修改文件权限 if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {//关闭掉老的文件句柄 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed",file[i].name.data); } //赋值为新的文件句柄。放心吧,没有别的地方使用这个fd的,就我一个进程,多线程版本不在此 file[i].fd = fd; } #if !(NGX_WIN32) if (cycle->log->file->fd != STDERR_FILENO) {//int dup2(int oldfd, int newfd); if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {//标准错误输出也设置为日志.那程序的fprint(stderr,)将输出到日志文件 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,"dup2(STDERR) failed"); } } #endif }
void ngx_pipe_do_rollback(ngx_cycle_t *cycle, ngx_pipe_rollback_conf_t *rbcf) { int fd; struct flock lock; int ret; ngx_int_t i; ngx_file_info_t sb; ngx_int_t need_do = 0; fd = ngx_open_file(rbcf->logname, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); if (fd < 0) { //open lock file failed just no need rollback return; } lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; ret = fcntl(fd, F_SETLKW, &lock); if (ret < 0) { ngx_close_file(fd); //lock failed just no need rollback return; } //check time if (rbcf->interval >= 0) { if (ngx_file_info(rbcf->backup[0], &sb) == -1) { need_do = 1; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need rollback [%s]: cannot open backup", rbcf->logname); } else if (sb.st_ctime / rbcf->interval < ngx_time() / rbcf->interval) { need_do = 1; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need rollback [%s]: time on [%d] [%d]", rbcf->logname, sb.st_ctime, rbcf->time_now); } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need rollback [%s]: time not on [%d] [%d]", rbcf->logname, sb.st_ctime, rbcf->time_now); } } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need check rollback [%s] time: no interval", rbcf->logname); } //check size if (rbcf->log_max_size > 0) { if (ngx_file_info(rbcf->logname, &sb) == 0 && (sb.st_size >= rbcf->log_max_size)) { need_do = 1; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need rollback [%s]: size on [%d]", rbcf->logname, sb.st_size); } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need rollback [%s]: size not on", rbcf->logname); } } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need check rollback [%s] size: no max size", rbcf->logname); } if (need_do) { for (i = 1; i < rbcf->backup_num; i++) { ngx_rename_file(rbcf->backup[rbcf->backup_num - i - 1], rbcf->backup[rbcf->backup_num - i]); } if (ngx_rename_file(rbcf->logname, rbcf->backup[0]) < 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "rname %s to %s failed", rbcf->logname, rbcf->backup[0]); } else { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "rollback [%s] success", rbcf->logname); } } ngx_close_file(fd); }
static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log) { int mode; ngx_fd_t fd; ngx_file_info_t fi; if (of->fd != NGX_INVALID_FILE) { if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) { of->failed = ngx_file_info_n; goto failed; } if (of->uniq == ngx_file_uniq(&fi)) { goto done; } } else if (of->test_dir) { if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) { of->failed = ngx_file_info_n; goto failed; } if (ngx_is_dir(&fi)) { goto done; } } if (!of->log) { /* * Use non-blocking open() not to hang on FIFO files, etc. * This flag has no effect on a regular files. */ mode = NGX_FILE_RDONLY|NGX_FILE_NONBLOCK; #if (NGX_WIN32 && NGX_HAVE_FILE_AIO) if (ngx_event_flags & NGX_USE_IOCP_EVENT && of->aio) { mode |= NGX_FILE_OVERLAPPED; } #endif fd = ngx_open_file(name, mode, NGX_FILE_OPEN, 0); } else { fd = ngx_open_file(name, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); } if (fd == NGX_INVALID_FILE) { of->failed = ngx_open_file_n; goto failed; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, ngx_fd_info_n " \"%s\" failed", name); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name); } of->fd = NGX_INVALID_FILE; return NGX_ERROR; } if (ngx_is_dir(&fi)) { if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name); } of->fd = NGX_INVALID_FILE; } else { of->fd = fd; if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) { if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_read_ahead_n " \"%s\" failed", name); } } if (of->directio <= ngx_file_size(&fi)) { if (ngx_directio_on(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_directio_on_n " \"%s\" failed", name); } else { of->is_directio = 1; } } } done: of->uniq = ngx_file_uniq(&fi); of->mtime = ngx_file_mtime(&fi); of->size = ngx_file_size(&fi); of->fs_size = ngx_file_fs_size(&fi); of->is_dir = ngx_is_dir(&fi); of->is_file = ngx_is_file(&fi); of->is_link = ngx_is_link(&fi); of->is_exec = ngx_is_exec(&fi); return NGX_OK; failed: of->fd = NGX_INVALID_FILE; of->err = ngx_errno; return NGX_ERROR; }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ssize_t n, len; ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; 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 (file[i].name.data == NULL) { continue; } len = file[i].pos - file[i].buffer; if (file[i].buffer && len != 0) { n = ngx_write_fd(file[i].fd, file[i].buffer, len); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data); } else if (n != len) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len); } file[i].pos = file[i].buffer; } fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if (NGX_WIN32) if (ngx_file_append_mode(fd) == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_append_mode_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #else if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; if (ngx_file_info((const char *) file[i].name.data, &fi) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } file[i].fd = fd; } #if !(NGX_WIN32) if (cycle->log->file->fd != STDERR_FILENO) { if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "dup2(STDERR) failed"); } } #endif }
static ngx_int_t ngx_http_dav_delete_handler(ngx_http_request_t *r) { size_t root; ngx_err_t err; ngx_int_t rc, depth; ngx_uint_t i, d, dir; ngx_str_t path; ngx_file_info_t fi; ngx_http_dav_loc_conf_t *dlcf; if (r->headers_in.content_length_n > 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "DELETE with body is unsupported"); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; } dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); if (dlcf->min_delete_depth) { d = 0; for (i = 0; i < r->uri.len; /* void */) { if (r->uri.data[i++] == '/') { if (++d >= dlcf->min_delete_depth && i < r->uri.len) { goto ok; } } } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "insufficient URI depth:%i to DELETE", d); return NGX_HTTP_CONFLICT; } ok: ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http delete filename: \"%s\"", path.data); if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) { err = ngx_errno; rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND; return ngx_http_dav_error(r->connection->log, err, rc, ngx_file_info_n, path.data); } if (ngx_is_dir(&fi)) { if (r->uri.data[r->uri.len - 1] != '/') { ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, "DELETE \"%s\" failed", path.data); return NGX_HTTP_CONFLICT; } depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Depth\" header must be infinity"); return NGX_HTTP_BAD_REQUEST; } path.len -= 2; /* omit "/\0" */ dir = 1; } else { /* * we do not need to test (r->uri.data[r->uri.len - 1] == '/') * because ngx_file_info("/file/") returned NGX_ENOTDIR above */ depth = ngx_http_dav_depth(r, 0); if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Depth\" header must be 0 or infinity"); return NGX_HTTP_BAD_REQUEST; } dir = 0; } rc = ngx_http_dav_delete_path(r, &path, dir); if (rc == NGX_OK) { return NGX_HTTP_NO_CONTENT; } return rc; }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; 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 (file[i].name.len == 0) { continue; } if (file[i].flush) { file[i].flush(&file[i], cycle->log); } fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if !(NGX_WIN32) if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } file[i].fd = fd; } (void) ngx_log_redirect_stderr(cycle); }
static ngx_int_t ngx_rtmp_auto_push_init_process(ngx_cycle_t *cycle) { #if (NGX_HAVE_UNIX_DOMAIN) ngx_rtmp_auto_push_conf_t *apcf; ngx_listening_t *ls, *lss; struct sockaddr_un *saun; int reuseaddr; ngx_socket_t s; size_t n; ngx_file_info_t fi; if (ngx_process != NGX_PROCESS_WORKER) { return NGX_OK; } ngx_rtmp_auto_push_module.ctx_index = ngx_rtmp_core_module.ctx_index; apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_rtmp_auto_push_module); if (apcf->auto_push == 0) { return NGX_OK; } next_publish = ngx_rtmp_publish; ngx_rtmp_publish = ngx_rtmp_auto_push_publish; next_delete_stream = ngx_rtmp_delete_stream; ngx_rtmp_delete_stream = ngx_rtmp_auto_push_delete_stream; reuseaddr = 1; s = (ngx_socket_t) -1; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, cycle->log, 0, "auto_push: creating sockets"); /*TODO: clone all RTMP listenings? */ ls = cycle->listening.elts; lss = NULL; for (n = 0; n < cycle->listening.nelts; ++n, ++ls) { if (ls->handler == ngx_stream_init_connection) { lss = ls; break; } } if (lss == NULL) { return NGX_OK; } ls = ngx_array_push(&cycle->listening); if (ls == NULL) { return NGX_ERROR; } *ls = *lss; /* Disable unix socket client address extraction * from accept call * Nginx generates bad addr_text with this enabled */ ls->addr_ntop = 0; ls->socklen = sizeof(struct sockaddr_un); saun = ngx_pcalloc(cycle->pool, ls->socklen); ls->sockaddr = (struct sockaddr *) saun; if (ls->sockaddr == NULL) { return NGX_ERROR; } saun->sun_family = AF_UNIX; *ngx_snprintf((u_char *) saun->sun_path, sizeof(saun->sun_path), "%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i", &apcf->socket_dir, ngx_process_slot) = 0; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0, "auto_push: create socket '%s'", saun->sun_path); if (ngx_file_info(saun->sun_path, &fi) != ENOENT) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0, "auto_push: delete existing socket '%s'", saun->sun_path); ngx_delete_file(saun->sun_path); } ngx_str_set(&ls->addr_text, "worker_socket"); s = ngx_socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_socket_n " worker_socket failed"); return NGX_ERROR; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuseaddr, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, "setsockopt(SO_REUSEADDR) worker_socket failed"); goto sock_error; } if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) { if (ngx_nonblocking(s) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_nonblocking_n " worker_socket failed"); return NGX_ERROR; } } if (bind(s, (struct sockaddr *) saun, sizeof(*saun)) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_nonblocking_n " worker_socket bind failed"); goto sock_error; } if (listen(s, NGX_LISTEN_BACKLOG) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, "listen() to worker_socket, backlog %d failed", NGX_LISTEN_BACKLOG); goto sock_error; } ls->fd = s; ls->listen = 1; return NGX_OK; sock_error: if (s != (ngx_socket_t) -1 && ngx_close_socket(s) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " worker_socket failed"); } ngx_delete_file(saun->sun_path); return NGX_ERROR; #else /* NGX_HAVE_UNIX_DOMAIN */ return NGX_OK; #endif /* NGX_HAVE_UNIX_DOMAIN */ }
static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r) { u_char *last; ngx_fd_t fd; ngx_int_t rc; ngx_uint_t level; ngx_str_t name, location; ngx_err_t err; ngx_log_t *log; ngx_buf_t *b; ngx_chain_t out; ngx_file_info_t fi; ngx_http_cleanup_t *file_cleanup, *redirect_cleanup; ngx_http_log_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; ngx_http_static_loc_conf_t *slcf; #if (NGX_HTTP_CACHE) uint32_t file_crc, redirect_crc; ngx_http_cache_t *file, *redirect; #endif if (r->uri.data[r->uri.len - 1] == '/') { return NGX_DECLINED; } if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_body(r); if (rc != NGX_OK && rc != NGX_AGAIN) { return rc; } #if (NGX_HTTP_CACHE) /* * there is a valid cached open file, i.e by the index handler, * and it should be already registered in r->cleanup */ if (r->cache && !r->cache->expired) { return ngx_http_send_cached(r); } #endif log = r->connection->log; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); /* * make a file name, reserve 2 bytes for a trailing '/' * in a possible redirect and for the last '\0' */ if (clcf->alias) { name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2 - clcf->name.len); if (name.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } last = ngx_cpymem(name.data, clcf->root.data, clcf->root.len); last = ngx_cpystrn(last, r->uri.data + clcf->name.len, r->uri.len + 1 - clcf->name.len); name.len = last - name.data; location.data = ngx_palloc(r->pool, r->uri.len + 2); if (location.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1); #if 0 /* * aliases usually have trailling "/", * set it in the start of the possible redirect */ if (*location.data != '/') { location.data--; } #endif location.len = last - location.data + 1; } else { name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2); if (name.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } location.data = ngx_cpymem(name.data, clcf->root.data, clcf->root.len); last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1); name.len = last - name.data; location.len = last - location.data + 1; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http filename: \"%s\"", name.data); /* allocate cleanups */ if (!(file_cleanup = ngx_push_array(&r->cleanup))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } file_cleanup->valid = 0; slcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module); if (slcf->redirect_cache) { if (!(redirect_cleanup = ngx_push_array(&r->cleanup))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } redirect_cleanup->valid = 0; } else { redirect_cleanup = NULL; } #if (NGX_HTTP_CACHE) /* look up an open files cache */ if (clcf->open_files) { file = ngx_http_cache_get(clcf->open_files, file_cleanup, &name, &file_crc); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http open file cache get: " PTR_FMT, file); if (file && !file->expired) { r->cache = file; return ngx_http_send_cached(r); } } else { file = NULL; } /* look up an redirect cache */ if (slcf->redirect_cache) { redirect = ngx_http_cache_get(slcf->redirect_cache, redirect_cleanup, &name, &redirect_crc); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http redirect cache get: " PTR_FMT, redirect); if (redirect && !redirect->expired) { /* * We do not copy a cached value so the cache entry is locked * until the end of the request. In a single threaded model * the redirected request should complete before other event * will be processed. In a multithreaded model this locking * should keep more popular redirects in cache. */ if (!(r->headers_out.location = ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.location->value = redirect->data.value; return NGX_HTTP_MOVED_PERMANENTLY; } } else { redirect = NULL; } #endif /* open file */ #if (WIN9X) /* TODO: redirect cache */ if (ngx_win32_version < NGX_WIN_NT) { /* * there is no way to open a file or a directory in Win9X with * one syscall because Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag * so we need to check its type before the opening */ if (ngx_file_info(name.data, &fi) == NGX_FILE_ERROR) { err = ngx_errno; ngx_log_error(NGX_LOG_ERR, log, err, ngx_file_info_n " \"%s\" failed", name.data); if (err == NGX_ENOENT || err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { return NGX_HTTP_FORBIDDEN; } else { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } if (ngx_is_dir(&fi)) { ngx_log_debug(log, "HTTP DIR: '%s'" _ name.data); if (!(r->headers_out.location = ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } *last++ = '/'; *last = '\0'; r->headers_out.location->value.len = last - location; r->headers_out.location->value.data = location; return NGX_HTTP_MOVED_PERMANENTLY; } } #endif fd = ngx_open_file(name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); if (fd == NGX_INVALID_FILE) { err = ngx_errno; if (err == NGX_ENOENT || err == NGX_ENOTDIR) { level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; } else { level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(level, log, err, ngx_open_file_n " \"%s\" failed", name.data); return rc; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", fd); if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, ngx_fd_info_n " \"%s\" failed", name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name.data); } return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_is_dir(&fi)) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir"); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name.data); } *last++ = '/'; *last = '\0'; r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.location->value = location; #if (NGX_HTTP_CACHE) if (slcf->redirect_cache) { if (redirect) { if (location.len == redirect->data.value.len && ngx_memcmp(redirect->data.value.data, location.data, location.len) == 0) { redirect->accessed = ngx_cached_time; redirect->updated = ngx_cached_time; /* * we can unlock the cache entry because * we have the local copy anyway */ ngx_http_cache_unlock(slcf->redirect_cache, redirect, log); redirect_cleanup->valid = 0; return NGX_HTTP_MOVED_PERMANENTLY; } } location.len++; redirect = ngx_http_cache_alloc(slcf->redirect_cache, redirect, redirect_cleanup, &name, redirect_crc, &location, log); location.len--; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http redirect cache alloc: " PTR_FMT, redirect); if (redirect) { redirect->fd = NGX_INVALID_FILE; redirect->accessed = ngx_cached_time; redirect->last_modified = 0; redirect->updated = ngx_cached_time; redirect->memory = 1; ngx_http_cache_unlock(slcf->redirect_cache, redirect, log); redirect_cleanup->valid = 0; } } #endif return NGX_HTTP_MOVED_PERMANENTLY; } #if !(WIN32) /* the not regular files are probably Unix specific */ if (!ngx_is_file(&fi)) { ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, "%s is not a regular file", name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name.data); } return NGX_HTTP_NOT_FOUND; } #endif #if (NGX_HTTP_CACHE) if (clcf->open_files) { #if (NGX_USE_HTTP_FILE_CACHE_UNIQ) if (file && file->uniq == ngx_file_uniq(&fi)) { if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name.data); } file->accessed = ngx_cached_time; file->updated = ngx_cached_time; file->expired = 0; r->cache = file; return ngx_http_send_cached(r); } else { if (file) { ngx_http_cache_unlock(clcf->open_files, file, log); file = NULL; } file = ngx_http_cache_alloc(clcf->open_files, file, file_cleanup, &name, file_crc, NULL, log); if (file) { file->uniq = ngx_file_uniq(&fi); } } #else file = ngx_http_cache_alloc(clcf->open_files, file, file_cleanup, &name, file_crc, NULL, log); #endif ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http open file cache alloc: " PTR_FMT, file); if (file) { file->fd = fd; file->data.size = ngx_file_size(&fi); file->accessed = ngx_cached_time; file->last_modified = ngx_file_mtime(&fi); file->updated = ngx_cached_time; r->cache = file; } return ngx_http_send_cached(r); } #endif ctx = log->data; ctx->action = "sending response to client"; file_cleanup->data.file.fd = fd; file_cleanup->data.file.name = name.data; file_cleanup->valid = 1; file_cleanup->cache = 0; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = ngx_file_size(&fi); r->headers_out.last_modified_time = ngx_file_mtime(&fi); if (r->headers_out.content_length_n == 0) { r->header_only = 1; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if (NGX_SUPPRESS_WARN) b = NULL; #endif if (!r->header_only) { /* we need to allocate all before the header would be sent */ if (!(b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!(b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->filter_allow_ranges = 1; } rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } b->in_file = 1; if (!r->main) { b->last_buf = 1; } b->file_pos = 0; b->file_last = ngx_file_size(&fi); b->file->fd = fd; b->file->log = log; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); }
ngx_int_t ngx_http_small_light_imlib2_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imlib2_ctx_t *ictx; ngx_http_small_light_image_size_t sz; Imlib_Image image_org, image_dst, image_tmp; Imlib_Load_Error err; ngx_file_info_t fi; ngx_fd_t fd; char *filename, *sharpen, *blur, *of, *buf; void *data; int w, h, radius, orientation; double iw, ih, q; ngx_int_t type; const char *ext; ssize_t size; ictx = (ngx_http_small_light_imlib2_ctx_t *)ctx->ictx; filename = (char *)ictx->tf->file.name.data; /* adjust image size */ ngx_http_small_light_calc_image_size(r, ctx, &sz, 10000.0, 10000.0); if (sz.jpeghint_flg != 0) { if (ngx_http_small_light_load_jpeg((void**)&data, &w, &h, r, filename, sz.dw, sz.dh) != NGX_OK) { image_org = imlib_load_image_immediately_without_cache(filename); if (image_org == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to load image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } else { image_org = imlib_create_image_using_data(w, h, data); } } else { image_org = imlib_load_image_immediately_without_cache(filename); if (image_org == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to load image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } /* rotate. */ if (sz.angle) { orientation = 0; switch (sz.angle) { case 90: orientation = 1; break; case 180: orientation = 2; break; case 270: orientation = 3; break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%d) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } imlib_context_set_image(image_org); imlib_image_orientate(orientation); } /* calc size. */ imlib_context_set_image(image_org); iw = (double)imlib_image_get_width(); ih = (double)imlib_image_get_height(); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { ctx->of = ctx->inf; return NGX_OK; } /* crop, scale. */ if (sz.scale_flg != 0) { image_dst = imlib_create_cropped_scaled_image((int)sz.sx, (int)sz.sy, (int)sz.sw, (int)sz.sh, (int)sz.dw, (int)sz.dh); imlib_context_set_image(image_org); imlib_free_image(); } else { image_dst = image_org; } if (image_dst == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "imlib_create_cropped_scaled_image failed. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { image_tmp = imlib_create_image(sz.cw, sz.ch); if (image_tmp == NULL) { imlib_context_set_image(image_dst); imlib_free_image(); return NGX_ERROR; } imlib_context_set_image(image_tmp); imlib_context_set_color(sz.cc.r, sz.cc.g, sz.cc.b, sz.cc.a); imlib_image_fill_rectangle(0, 0, sz.cw, sz.ch); imlib_blend_image_onto_image(image_dst, 255, 0, 0, (int)sz.dw, (int)sz.dh, (int)sz.dx, (int)sz.dy, (int)sz.dw, (int)sz.dh); imlib_context_set_image(image_dst); imlib_free_image(); image_dst = image_tmp; } /* effects. */ sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (sharpen) { radius = ngx_http_small_light_parse_int(sharpen); if (radius > 0) { imlib_context_set_image(image_dst); imlib_image_sharpen(radius); } } blur = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "blur"); if (blur) { radius = ngx_http_small_light_parse_int(blur); if (radius > 0) { imlib_context_set_image(image_dst); imlib_image_blur(radius); } } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { imlib_context_set_color(sz.bc.r, sz.bc.g, sz.bc.b, sz.bc.a); imlib_context_set_image(image_dst); if (sz.cw > 0.0 && sz.ch > 0.0) { imlib_image_fill_rectangle(0, 0, sz.cw, sz.bh); imlib_image_fill_rectangle(0, 0, sz.bw, sz.ch); imlib_image_fill_rectangle(0, sz.ch - sz.bh, sz.cw, sz.bh); imlib_image_fill_rectangle(sz.cw - sz.bw, 0, sz.bw, sz.ch); } else { imlib_image_fill_rectangle(0, 0, sz.dw, sz.bh); imlib_image_fill_rectangle(0, 0, sz.bw, sz.ch); imlib_image_fill_rectangle(0, sz.dh - sz.bh, sz.dw, sz.bh); imlib_image_fill_rectangle(sz.dw - sz.bw, 0, sz.bw, sz.dh); } } /* set params. */ imlib_context_set_image(image_dst); q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q > 0.0) { imlib_image_attach_data_value("quality", NULL, q, NULL); } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else { ictx->type = type; } imlib_image_set_format(of); ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; } else { ext = ngx_http_small_light_image_exts[ictx->type - 1]; imlib_image_set_format(ext); ctx->of = ctx->inf; } /* save image. */ imlib_save_image_with_error_return(filename, &err); imlib_free_image(); /* check error. */ if (err != IMLIB_LOAD_ERROR_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to imlib_save_error %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_file_info(filename, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_file_info %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open fd %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_fd_info %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } buf = ngx_palloc(r->pool, ngx_file_size(&fi)); if (buf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } size = ngx_read_fd(fd, buf, ngx_file_size(&fi)); if (size == -1) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_read_fd %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } if ((size_t)size > ctx->content_length) { ctx->content = ngx_palloc(r->pool, size); if (ctx->content == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } } ngx_memcpy(ctx->content, buf, size); ngx_close_file(fd); ctx->content_length = size; return NGX_OK; }
/*重新打开所有文件cycle->open_files*/ void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; 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 (file[i].name.len == 0) { continue; } /*原有文件内容下盘*/ if (file[i].flush) { file[i].flush(&file[i], cycle->log); } /*以追加方式打开文件*/ fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if !(NGX_WIN32) if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; /*获取文件信息,如所有者,权限等*/ if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } /*修改文件所有者*/ if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } } /*修改文件权限*/ if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } } } /*F_SETFD 设置close-on-exec 旗标。该旗标以参数arg 的FD_CLOEXEC位决定。*/ /* * lose_on_exec 是一个进程所有文件描述符(文件句柄)的位图标志,每个比特位代表一个打开的文件描述符, * 用于确定在调用系统调用execve()时需要关闭的文件句柄 */ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif /*关闭文件*/ if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } file[i].fd = fd; } /*重定向标准错误输出*/ (void) ngx_log_redirect_stderr(cycle); }
ngx_int_t ngx_create_paths(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_err_t err; ngx_uint_t i; ngx_path_t **path; path = cycle->paths.elts; for (i = 0; i < cycle->paths.nelts; i++) { if (ngx_create_dir(path[i]->name.data, 0700) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_EEXIST) { ngx_log_error(NGX_LOG_EMERG, cycle->log, err, ngx_create_dir_n " \"%s\" failed", path[i]->name.data); return NGX_ERROR; } } if (user == (ngx_uid_t) NGX_CONF_UNSET_UINT) { continue; } #if !(NGX_WIN32) { ngx_file_info_t fi; if (ngx_file_info((const char *) path[i]->name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", path[i]->name.data); return NGX_ERROR; } if (fi.st_uid != user) { if (chown((const char *) path[i]->name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", path[i]->name.data, user); return NGX_ERROR; } } if ((fi.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR|S_IXUSR); if (chmod((const char *) path[i]->name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", path[i]->name.data); return NGX_ERROR; } } } #endif } return NGX_OK; }
static ngx_int_t ngx_rtmp_dash_cleanup_dir(ngx_str_t *ppath, ngx_msec_t playlen) { time_t mtime, max_age; u_char *p; u_char path[NGX_MAX_PATH + 1], mpd_path[NGX_MAX_PATH + 1]; ngx_dir_t dir; ngx_err_t err; ngx_str_t name, spath, mpd; ngx_int_t nentries, nerased; ngx_file_info_t fi; ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, "dash: cleanup path='%V' playlen=%M", ppath, playlen); if (ngx_open_dir(ppath, &dir) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, ngx_errno, "dash: cleanup open dir failed '%V'", ppath); return NGX_ERROR; } nentries = 0; nerased = 0; for ( ;; ) { ngx_set_errno(0); if (ngx_read_dir(&dir) == NGX_ERROR) { err = ngx_errno; if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, "dash: cleanup " ngx_close_dir_n " \"%V\" failed", ppath); } if (err == NGX_ENOMOREFILES) { return nentries - nerased; } ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, err, "dash: cleanup " ngx_read_dir_n " '%V' failed", ppath); return NGX_ERROR; } name.data = ngx_de_name(&dir); if (name.data[0] == '.') { continue; } name.len = ngx_de_namelen(&dir); p = ngx_snprintf(path, sizeof(path) - 1, "%V/%V", ppath, &name); *p = 0; spath.data = path; spath.len = p - path; nentries++; if (!dir.valid_info && ngx_de_info(path, &dir) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, "dash: cleanup " ngx_de_info_n " \"%V\" failed", &spath); continue; } if (ngx_de_is_dir(&dir)) { if (ngx_rtmp_dash_cleanup_dir(&spath, playlen) == 0) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, "dash: cleanup dir '%V'", &name); /* * null-termination gets spoiled in win32 * version of ngx_open_dir */ *p = 0; if (ngx_delete_dir(path) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno, "dash: cleanup " ngx_delete_dir_n " failed on '%V'", &spath); } else { nerased++; } } continue; } if (!ngx_de_is_file(&dir)) { continue; } if (name.len >= 8 && name.data[name.len - 8] == 'i' && name.data[name.len - 7] == 'n' && name.data[name.len - 6] == 'i' && name.data[name.len - 5] == 't' && name.data[name.len - 4] == '.' && name.data[name.len - 3] == 'm' && name.data[name.len - 2] == '4') { if (name.len == 8) { ngx_str_set(&mpd, "index"); } else { mpd.data = name.data; mpd.len = name.len - 9; } p = ngx_snprintf(mpd_path, sizeof(mpd_path) - 1, "%V/%V.mpd", ppath, &mpd); *p = 0; if (ngx_file_info(mpd_path, &fi) != NGX_FILE_ERROR) { ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, "dash: cleanup '%V' delayed, mpd exists '%s'", &name, mpd_path); continue; } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, "dash: cleanup '%V' allowed, mpd missing '%s'", &name, mpd_path); max_age = 0; } else if (name.len >= 4 && name.data[name.len - 4] == '.' && name.data[name.len - 3] == 'm' && name.data[name.len - 2] == '4' && name.data[name.len - 1] == 'v') { max_age = playlen / 500; } else if (name.len >= 4 && name.data[name.len - 4] == '.' && name.data[name.len - 3] == 'm' && name.data[name.len - 2] == '4' && name.data[name.len - 1] == 'a') { max_age = playlen / 500; } else if (name.len >= 4 && name.data[name.len - 4] == '.' && name.data[name.len - 3] == 'm' && name.data[name.len - 2] == 'p' && name.data[name.len - 1] == 'd') { max_age = playlen / 500; } else if (name.len >= 4 && name.data[name.len - 4] == '.' && name.data[name.len - 3] == 'r' && name.data[name.len - 2] == 'a' && name.data[name.len - 1] == 'w') { max_age = playlen / 1000; } else { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, "dash: cleanup skip unknown file type '%V'", &name); continue; } mtime = ngx_de_mtime(&dir); if (mtime + max_age > ngx_cached_time->sec) { continue; } ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, "dash: cleanup '%V' mtime=%T age=%T", &name, mtime, ngx_cached_time->sec - mtime); if (ngx_delete_file(path) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno, "dash: cleanup " ngx_delete_file_n " failed on '%V'", &spath); continue; } nerased++; } }
static void ngx_http_dav_put_handler(ngx_http_request_t *r) { size_t root; time_t date; ngx_str_t *temp, path; ngx_uint_t status; ngx_file_info_t fi; ngx_ext_rename_file_t ext; ngx_http_dav_loc_conf_t *dlcf; if (r->request_body == NULL || r->request_body->temp_file == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_http_map_uri_to_path(r, &path, &root, 0); path.len--; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http put filename: \"%s\"", path.data); temp = &r->request_body->temp_file->file.name; if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) { status = NGX_HTTP_CREATED; } else { status = NGX_HTTP_NO_CONTENT; if (ngx_is_dir(&fi)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, "\"%s\" could not be created", path.data); if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", temp->data); } ngx_http_finalize_request(r, NGX_HTTP_CONFLICT); return; } } dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); ext.access = dlcf->access; ext.path_access = dlcf->access; ext.time = -1; ext.create_path = dlcf->create_full_put_path; ext.delete_file = 1; ext.log = r->connection->log; if (r->headers_in.date) { date = ngx_http_parse_time(r->headers_in.date->value.data, r->headers_in.date->value.len); if (date != NGX_ERROR) { ext.time = date; ext.fd = r->request_body->temp_file->file.fd; } } if (ngx_ext_rename_file(temp, &path, &ext) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } if (status == NGX_HTTP_CREATED) { if (ngx_http_dav_location(r, path.data) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } r->headers_out.content_length_n = 0; } r->headers_out.status = status; r->header_only = 1; ngx_http_finalize_request(r, ngx_http_send_header(r)); return; }
static ngx_int_t ngx_rtmp_record_ensure_directory(ngx_rtmp_session_t *s, ngx_str_t *path) { size_t len; ngx_file_info_t fi; ngx_rtmp_record_ctx_t *ctx; ngx_rtmp_record_app_conf_t *hacf; static u_char zpath[NGX_MAX_PATH + 1] = {0}; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); if (path->len + 1 > sizeof(zpath)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "record: too long path"); return NGX_ERROR; } ngx_snprintf(zpath, sizeof(zpath), "%V%Z", path); if (ngx_file_info(zpath, &fi) == NGX_FILE_ERROR) { if (ngx_errno != NGX_ENOENT) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "record: " ngx_file_info_n " failed on '%V'", path); return NGX_ERROR; } /* ENOENT */ if (ngx_create_full_path(zpath, NGX_RTMP_RECORD_DIR_ACCESS) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "record: " ngx_create_dir_n " failed on '%V'", path); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: directory '%V' created", path); } else { if (!ngx_is_dir(&fi)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "record: '%V' exists and is not a directory", path); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: directory '%V' exists", path); } ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); len = path->len; if (path->data[len - 1] == '/') { len--; } if (len + 1 + ngx_strlen(ctx->name) + 1 > sizeof(zpath)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "record: too long path"); return NGX_ERROR; } ngx_snprintf(zpath, sizeof(zpath) - 1, "%*s/%s%Z", len, path->data, ctx->name); if (ngx_file_info(zpath, &fi) != NGX_FILE_ERROR) { if (ngx_is_dir(&fi)) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: directory '%s' exists", zpath); return NGX_OK; } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "record: '%s' exists and is not a directory", zpath); return NGX_ERROR; } if (ngx_errno != NGX_ENOENT) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "record: " ngx_file_info_n " failed on '%s'", zpath); return NGX_ERROR; } /* NGX_ENOENT */ if (ngx_create_full_path(zpath, NGX_RTMP_RECORD_DIR_ACCESS) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "record: " ngx_create_dir_n " failed on '%s'", zpath); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: directory '%s' created", zpath); return NGX_OK; }