static gboolean bod_open(bod_state *state) { if (NULL == state->tempfile) { gint fd; GString *tmpfilename; const char tmpl[] = "lighttpd-buffer-XXXXXX", basedir[] = "/var/tmp"; tmpfilename = g_string_sized_new((sizeof(basedir) - 1) + 1 + (sizeof(tmpl) - 1)); g_string_append_len(tmpfilename, CONST_STR_LEN(basedir)); /* TODO: add config option */ li_path_append_slash(tmpfilename); g_string_append_len(tmpfilename, CONST_STR_LEN(tmpl)); fd = g_mkstemp(tmpfilename->str); if (-1 == fd) { VR_ERROR(state->vr, "g_mkstemp failed: %s", g_strerror(errno)); g_string_free(tmpfilename, TRUE); bod_stop(state); return FALSE; } state->tempfile = li_chunkfile_new(tmpfilename, fd, TRUE); state->write_pos = 0; state->flush_pos = 0; g_string_free(tmpfilename, TRUE); } return TRUE; }
static void __chunkqueue_append_file(liChunkQueue *cq, GString *filename, off_t start, off_t length, int fd, gboolean is_temp) { liChunk *c = chunk_new(); c->type = FILE_CHUNK; c->data.file.file = li_chunkfile_new(filename, fd, is_temp); c->data.file.start = start; c->data.file.length = length; g_queue_push_tail_link(&cq->queue, &c->cq_link); cq->length += length; cq->bytes_in += length; }
static liHandlerResult flv(liVRequest *vr, gpointer param, gpointer *context) { gchar *start; guint len; goffset pos; liHandlerResult res; gboolean cachable; struct stat st; int err; int fd = -1; UNUSED(context); UNUSED(param); if (li_vrequest_is_handled(vr)) return LI_HANDLER_GO_ON; res = li_stat_cache_get(vr, vr->physical.path, &st, &err, &fd); if (res == LI_HANDLER_WAIT_FOR_EVENT) return res; if (res == LI_HANDLER_ERROR) { /* open or fstat failed */ if (fd != -1) close(fd); if (!li_vrequest_handle_direct(vr)) return LI_HANDLER_ERROR; switch (err) { case ENOENT: case ENOTDIR: vr->response.http_status = 404; return LI_HANDLER_GO_ON; case EACCES: vr->response.http_status = 403; return LI_HANDLER_GO_ON; default: VR_ERROR(vr, "stat() or open() for '%s' failed: %s", vr->physical.path->str, g_strerror(err)); return LI_HANDLER_ERROR; } } else if (S_ISDIR(st.st_mode)) { if (fd != -1) close(fd); return LI_HANDLER_GO_ON; } else if (!S_ISREG(st.st_mode)) { if (fd != -1) close(fd); if (!li_vrequest_handle_direct(vr)) return LI_HANDLER_ERROR; vr->response.http_status = 403; } else { liChunkFile *cf; #ifdef FD_CLOEXEC fcntl(fd, F_SETFD, FD_CLOEXEC); #endif if (!li_vrequest_handle_direct(vr)) { close(fd); return LI_HANDLER_ERROR; } if (li_querystring_find(vr->request.uri.query, CONST_STR_LEN("start"), &start, &len)) { guint i; pos = 0; for (i = 0; i < len; i++) { if (start[i] >= '0' && start[i] <= '9') { pos *= 10; pos += start[i] - '0'; } } } else { pos = 0; } li_etag_set_header(vr, &st, &cachable); if (cachable) { vr->response.http_status = 304; close(fd); return LI_HANDLER_GO_ON; } vr->response.http_status = 200; li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/x-flv")); if (pos < 0 || pos > st.st_size) pos = 0; if (pos != 0) li_chunkqueue_append_mem(vr->direct_out, CONST_STR_LEN("FLV\x1\x1\0\0\0\x9\0\0\0\x9")); cf = li_chunkfile_new(NULL, fd, FALSE); li_chunkqueue_append_chunkfile(vr->direct_out, cf, pos, st.st_size - pos); li_chunkfile_release(cf); } return LI_HANDLER_GO_ON; }