static ngx_int_t ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir) { char *failed; ngx_tree_ctx_t tree; if (dir) { tree.init_handler = NULL; tree.file_handler = ngx_http_dav_delete_file; tree.pre_tree_handler = ngx_http_dav_noop; tree.post_tree_handler = ngx_http_dav_delete_dir; tree.spec_handler = ngx_http_dav_delete_file; tree.data = NULL; tree.alloc = 0; tree.log = r->connection->log; /* TODO: 207 */ if (ngx_walk_tree(&tree, path) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_delete_dir(path->data) != NGX_FILE_ERROR) { return NGX_OK; } failed = ngx_delete_dir_n; } else { if (ngx_delete_file(path->data) != NGX_FILE_ERROR) { return NGX_OK; } failed = ngx_delete_file_n; } return ngx_http_dav_error(r->connection->log, ngx_errno, NGX_HTTP_NOT_FOUND, failed, path->data); }
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++; } }