static ngx_int_t ngx_rtmp_dash_rename_file(u_char *src, u_char *dst) { /* rename file with overwrite */ #if (NGX_WIN32) return MoveFileEx((LPCTSTR) src, (LPCTSTR) dst, MOVEFILE_REPLACE_EXISTING); #else return ngx_rename_file(src, dst); #endif }
static void ngx_rtmp_play_copy_local_file(ngx_rtmp_session_t *s, u_char *name) { ngx_rtmp_play_app_conf_t *pacf; ngx_rtmp_play_ctx_t *ctx; u_char *path, *p; static u_char dpath[NGX_MAX_PATH + 1]; pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); if (pacf == NULL) { return; } ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx == NULL || ctx->file_id == 0) { return; } path = ngx_rtmp_play_get_local_file_path(s); p = ngx_snprintf(dpath, NGX_MAX_PATH, "%V/%s%V", &pacf->local_path, name + ctx->pfx_size, &ctx->sfx); *p = 0; ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: copy local file '%s' to '%s'", path, dpath); if (ngx_rename_file(path, dpath) == 0) { ctx->file_id = 0; return; } ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "play: error copying local file '%s' to '%s'", path, dpath); ngx_rtmp_play_cleanup_local_file(s); }
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, flags; ngx_str_t path, uri, duri, args; 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; } p = dest->value.data; /* there is always '\0' even after empty header value */ if (p[0] == '/') { last = p + dest->value.len; goto destination_done; } 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: duri.len = last - p; duri.data = p; flags = NGX_HTTP_LOG_UNSAFE; if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) { goto invalid_destination; } 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 = duri; 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_link_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_link_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_link_info(path.data, &fi) == NGX_FILE_ERROR) { return ngx_http_dav_error(r->connection->log, ngx_errno, NGX_HTTP_NOT_FOUND, ngx_link_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; }
ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) { char **env, *var; u_char *p; ngx_uint_t i, n; ngx_pid_t pid; ngx_exec_ctx_t ctx; ngx_core_conf_t *ccf; ngx_listening_t *ls; ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t)); ctx.path = argv[0]; ctx.name = "new binary process"; ctx.argv = argv; n = 2; env = ngx_set_environment(cycle, &n); if (env == NULL) { return NGX_INVALID_PID; } var = ngx_alloc(sizeof(NGINX_VAR) + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2, cycle->log); p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR)); ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { p = ngx_sprintf(p, "%ud;", ls[i].fd); } *p = '\0'; env[n++] = var; #if (NGX_SETPROCTITLE_USES_ENV) /* allocate the spare 300 bytes for the new binary process title */ env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; #endif env[n] = NULL; #if (NGX_DEBUG) { char **e; for (e = env; *e; e++) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e); } } #endif ctx.envp = (char *const *) env; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s to %s failed " "before executing new binary process \"%s\"", ccf->pid.data, ccf->oldpid.data, argv[0]); ngx_free(env); ngx_free(var); return NGX_INVALID_PID; } pid = ngx_execute(cycle, &ctx); if (pid == NGX_INVALID_PID) { if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s back to %s failed after " "the try to execute the new binary process \"%s\"", ccf->oldpid.data, ccf->pid.data, argv[0]); } } ngx_free(env); ngx_free(var); return pid; }
ngx_int_t ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) { u_char *name; ngx_err_t err; ngx_copy_file_t cf; #if !(NGX_WIN32) if (ext->access) { if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_change_file_access_n " \"%s\" failed", src->data); err = 0; goto failed; } } #endif if (ext->time != -1) { if (ngx_set_file_time(src->data, ext->fd, ext->time) != NGX_OK) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", src->data); err = 0; goto failed; } } if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; } err = ngx_errno; if (err == NGX_ENOPATH) { if (!ext->create_path) { goto failed; } err = ngx_create_full_path(to->data, ngx_dir_access(ext->path_access)); if (err) { ngx_log_error(NGX_LOG_CRIT, ext->log, err, ngx_create_dir_n " \"%s\" failed", to->data); err = 0; goto failed; } if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; } err = ngx_errno; } #if (NGX_WIN32) //deleted by fangpeng #endif if (err == NGX_EXDEV) { cf.size = -1; cf.buf_size = 0; cf.access = ext->access; cf.time = ext->time; cf.log = ext->log; name = ngx_alloc(to->len + 1 + 10 + 1, ext->log); if (name == NULL) { return NGX_ERROR; } (void) ngx_sprintf(name, "%*s.%010uD%Z", to->len, to->data, (uint32_t) ngx_next_temp_number(0)); if (ngx_copy_file(src->data, name, &cf) == NGX_OK) { if (ngx_rename_file(name, to->data) != NGX_FILE_ERROR) { ngx_free(name); if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", src->data); return NGX_ERROR; } return NGX_OK; } ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_rename_file_n " \"%s\" to \"%s\" failed", name, to->data); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", name); } } ngx_free(name); err = 0; } failed: if (ext->delete_file) { if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", src->data); } } if (err) { ngx_log_error(NGX_LOG_CRIT, ext->log, err, ngx_rename_file_n " \"%s\" to \"%s\" failed", src->data, to->data); } return NGX_ERROR; }
static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle) { ngx_int_t i, n; ngx_uint_t live; ngx_channel_t ch; ngx_core_conf_t *ccf; ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_CLOSE_CHANNEL; ch.fd = -1; live = 0; for (i = 0; i < ngx_last_process; i++) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "child: %d %P e:%d t:%d d:%d r:%d j:%d", i, ngx_processes[i].pid, ngx_processes[i].exiting, ngx_processes[i].exited, ngx_processes[i].detached, ngx_processes[i].respawn, ngx_processes[i].just_spawn); if (ngx_processes[i].pid == -1) { continue; } if (ngx_processes[i].exited) { if (!ngx_processes[i].detached) { ngx_close_channel(ngx_processes[i].channel, cycle->log); ngx_processes[i].channel[0] = -1; ngx_processes[i].channel[1] = -1; ch.pid = ngx_processes[i].pid; ch.slot = i; for (n = 0; n < ngx_last_process; n++) { if (ngx_processes[n].exited || ngx_processes[n].pid == -1 || ngx_processes[n].channel[0] == -1) { continue; } ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0, "pass close channel s:%i pid:%P to:%P", ch.slot, ch.pid, ngx_processes[n].pid); /* TODO: NGX_AGAIN */ ngx_write_channel(ngx_processes[n].channel[0], &ch, sizeof(ngx_channel_t), cycle->log); } } if (ngx_processes[i].respawn && !ngx_processes[i].exiting && !ngx_terminate && !ngx_quit) { if (ngx_spawn_process(cycle, ngx_processes[i].proc, ngx_processes[i].data, ngx_processes[i].name, i) == NGX_INVALID_PID) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "could not respawn %s", ngx_processes[i].name); continue; } ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); live = 1; continue; } if (ngx_processes[i].pid == ngx_new_binary) { ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_rename_file((char *) ccf->oldpid.data, (char *) ccf->pid.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s back to %s failed " "after the new binary process \"%s\" exited", ccf->oldpid.data, ccf->pid.data, ngx_argv[0]); } ngx_new_binary = 0; if (ngx_noaccepting) { ngx_restart = 1; ngx_noaccepting = 0; } } if (i == ngx_last_process - 1) { ngx_last_process--; } else { ngx_processes[i].pid = -1; } } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) { live = 1; } } return live; }
/*用新的子进程启动新版本的nginx进程*/ ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) { char **env, *var; u_char *p; ngx_uint_t i, n; ngx_pid_t pid; ngx_exec_ctx_t ctx; ngx_core_conf_t *ccf; ngx_listening_t *ls; ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t)); ctx.path = argv[0]; ctx.name = "new binary process"; ctx.argv = argv; n = 2; env = ngx_set_environment(cycle, &n); if (env == NULL) { return NGX_INVALID_PID; } /* * cycle->listening.nelts * (NGX_INT32_LEN + 1)从下面赋值地方可以看出是两个监听socket之间有';',所以需要+1; * 申请内存的时候额外'+2'多申请2个字节内存,从下面拷贝NGINX_VAR时候可以看出多了个'='号,还有就是结尾的'\0'; */ var = ngx_alloc(sizeof(NGINX_VAR) + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2, cycle->log); if (var == NULL) { ngx_free(env); return NGX_INVALID_PID; } /*下面执行的是生成环境变量"NGINX"用以传递老版本nginx监听的端口*/ p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR)); ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { p = ngx_sprintf(p, "%ud;", ls[i].fd); } *p = '\0'; env[n++] = var; //将刚生成的"NGINX"环境变量放在总的环境变量之后 /*申请额外的内存用于新的nginx进程修改名字使用*/ #if (NGX_SETPROCTITLE_USES_ENV) /* allocate the spare 300 bytes for the new binary process title */ env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; #endif env[n] = NULL; #if (NGX_DEBUG) { char **e; for (e = env; *e; e++) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e); } } #endif ctx.envp = (char *const *) env; /*获取核心模块存储配置项的结构体指针*/ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); /*重命名nginx.pid*/ if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s to %s failed " "before executing new binary process \"%s\"", ccf->pid.data, ccf->oldpid.data, argv[0]); ngx_free(env); ngx_free(var); return NGX_INVALID_PID; } /*执行新版本的nginx程序,返回的是用来执行系统调用execve的子进程的id,也是新版本nginx进程的id*/ pid = ngx_execute(cycle, &ctx); if (pid == NGX_INVALID_PID) { if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) //升级失败,回退nginx.pid文件 == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s back to %s failed after " "an attempt to execute new binary process \"%s\"", ccf->oldpid.data, ccf->pid.data, argv[0]); } } ngx_free(env); ngx_free(var); return pid; }
ngx_int_t ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) { ngx_err_t err; #if !(NGX_WIN32) if (ext->access) { if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_change_file_access_n " \"%s\" failed", src->data); err = 0; goto failed; } } #endif if (ext->time != -1) { if (ngx_set_file_time(src->data, ext->fd, ext->time) != NGX_OK) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", src->data); err = 0; goto failed; } } if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; } err = ngx_errno; if (err #if (NGX_WIN32) == ERROR_PATH_NOT_FOUND #else == NGX_ENOENT #endif ) { if (!ext->create_path) { goto failed; } err = ngx_create_full_path(to->data, ngx_dir_access(ext->path_access)); if (err) { ngx_log_error(NGX_LOG_CRIT, ext->log, err, ngx_create_dir_n " \"%s\" failed", to->data); err = 0; goto failed; } if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; } err = ngx_errno; goto failed; } #if (NGX_WIN32) if (err == NGX_EEXIST) { if (ngx_win32_rename_file(src, to, ext->log) == NGX_OK) { if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; } err = ngx_errno; } else { err = 0; } } #endif failed: if (ext->delete_file) { if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", src->data); } } if (err && ext->log_rename_error) { ngx_log_error(NGX_LOG_CRIT, ext->log, err, ngx_rename_file_n " \"%s\" to \"%s\" failed", src->data, to->data); } ext->rename_error = err; return NGX_ERROR; }
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); }
void ngx_http_fsutil_code_common( ngx_http_script_engine_t *e ) { fsutil_code_t *codeobj; ngx_http_variable_value_t *vv_src; ngx_http_variable_value_t *vv_dst; char *dst; char *src; ngx_int_t i; ngx_int_t rc; codeobj = ( fsutil_code_t* )e->ip; _x_getvar( src ); _x_getvar( dst ); # undef _x_getvar # define lg( fmt ... ) \ ngx_log_error(NGX_LOG_ERR, e->request->connection->log, 0, fmt ); dst[ 0 ] = '/'; for ( i = 1; i < vv_dst->len; i++ ) { if ( vv_dst->data[ i ] == '/' ) { dst[ i ] = 0; rc = ngx_http_fsutil_create_dir_if_not_found( e->request->connection->log, dst ); if ( NGX_OK != rc ) { goto error_fserror_to_httpcode; } } dst[ i ] = vv_dst->data[ i ]; } dst[ i ] = 0; ngx_memcpy( src, vv_src->data, vv_src->len ); src[ vv_src->len ] = 0; /* lg( "src=%s dst=%s", src, dst ); */ switch ( codeobj->op ) { case fsutil_op_mv : if ( fsutil_opt_onexist_override & codeobj->opt ) { /* lg( "to rename directly" ); */ rc = ngx_rename_file( src, dst ); } else { /* * Rename does'nt support non-override operation. Thus we * need to link to it first and then remove the original * one */ /* lg( "link and unlink" ); */ rc = link( src, dst ); /* lg( "link rc=%d", rc ); */ if ( NGX_OK == rc ) { rc = unlink( src ); /* lg( "unlink rc=%d", rc ); */ } else if ( NGX_EEXIST == ngx_errno ) { if ( fsutil_opt_onexist_touch & codeobj->opt ) { rc = utimes( dst, NULL ); /* lg( "utimes rc=%d", rc ); */ } else { rc = NGX_OK; } } } break; case fsutil_op_ln : if ( fsutil_opt_onexist_override & codeobj->opt ) { while ( NGX_OK != ( rc = link( src, dst ) ) ) { if ( NGX_EEXIST != ngx_errno ) { break; } rc = unlink( dst ); if ( NGX_OK == rc || NGX_ENOENT == ngx_errno ) { continue; } else { /* other error which can not be handled */ break; } } } else if ( fsutil_opt_onexist_touch & codeobj->opt ) { if ( NGX_OK != ( rc = link( src, dst ) ) ) { if ( NGX_EEXIST == ngx_errno ) { rc = utimes( dst, NULL ); } } } else { /* ignore */ link( src, dst ); rc = NGX_OK; } break; default: goto error_op_unsupported; } if ( 0 != rc ) { u_char errstr[ 1024 ]; ngx_strerror( ngx_errno, errstr, 1024 ); ngx_log_error(NGX_LOG_ERR, e->request->connection->log, 0, "%V failed. src=%s dst=%s, err=%d %s", &opnames[ codeobj->op ], src, dst, ngx_errno, errstr ); goto error_op_failed; } e->ip += sizeof(fsutil_code_t); return; error_op_unsupported: error_var_not_found: e->status = NGX_HTTP_BAD_REQUEST; e->ip += sizeof(fsutil_code_t) - sizeof(uintptr_t); return; error_op_failed: error_fserror_to_httpcode: switch ( rc ) { case NGX_ENOTDIR : e->status = NGX_HTTP_CONFLICT; break; default: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; } e->ip += sizeof(fsutil_code_t) - sizeof(uintptr_t); return; error_500: e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; e->ip += sizeof(fsutil_code_t) - sizeof(uintptr_t); return; }
static ngx_int_t ngx_rtmp_hls_update_playlist(ngx_rtmp_session_t *s) { static u_char buffer[1024]; int fd; u_char *p; ngx_rtmp_hls_ctx_t *ctx; ssize_t n; ngx_int_t ffrag; ngx_rtmp_hls_app_conf_t *hacf; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "hls: open failed: '%V'", &ctx->playlist_bak); return NGX_ERROR; } ffrag = ctx->frag - hacf->nfrags; if (ffrag < 1) { ffrag = 1; } p = ngx_snprintf(buffer, sizeof(buffer), "#EXTM3U\r\n" "#EXT-X-TARGETDURATION:%i\r\n" "#EXT-X-MEDIA-SEQUENCE:%i\r\n\r\n", /*TODO: float*/(ngx_int_t)(hacf->fraglen / 1000), ffrag); n = write(fd, buffer, p - buffer); if (n < 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "hls: write failed: '%V'", &ctx->playlist_bak); ngx_close_file(fd); return NGX_ERROR; } for (; ffrag < ctx->frag; ++ffrag) { p = ngx_snprintf(buffer, sizeof(buffer), "#EXTINF:%i,\r\n" "%V-%i.ts\r\n", /*TODO:float*/(ngx_int_t)(hacf->fraglen / 1000), &ctx->name, ffrag); n = write(fd, buffer, p - buffer); if (n < 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "hls: write failed: '%V'", &ctx->playlist_bak); ngx_close_file(fd); return NGX_ERROR; } } ngx_close_file(fd); if (ngx_rename_file(ctx->playlist_bak.data, ctx->playlist.data)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "hls: rename failed: '%V'->'%V'", &ctx->playlist_bak, &ctx->playlist); return NGX_ERROR; } return NGX_OK; }