]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Fix a couple of bugs related to sending files > 2GB
authorAndreas Öman <andreas@lonelycoder.com>
Wed, 2 Mar 2011 22:32:45 +0000 (23:32 +0100)
committerAndreas Öman <andreas@lonelycoder.com>
Wed, 2 Mar 2011 22:33:13 +0000 (23:33 +0100)
Ticket #391

src/http.c
src/http.h
src/webui/webui.c

index 9cca5036fef53b0184449ecd369df6252daa7ffb..8d94c8bc6648d7dfb2ab32cdf2a849849afcca5d 100644 (file)
@@ -123,7 +123,8 @@ static const char *
 http_rc2str(int code)
 {
   switch(code) {
-  case HTTP_STATUS_OK:              return "Ok";
+  case HTTP_STATUS_OK:              return "OK";
+  case HTTP_STATUS_PARTIAL_CONTENT: return "Partial Content";
   case HTTP_STATUS_NOT_FOUND:       return "Not found";
   case HTTP_STATUS_UNAUTHORIZED:    return "Unauthorized";
   case HTTP_STATUS_BAD_REQUEST:     return "Bad request";
@@ -149,7 +150,8 @@ static const char *cachemonths[12] = {
  */
 void
 http_send_header(http_connection_t *hc, int rc, const char *content, 
-                int contentlen, const char *encoding, const char *location, 
+                int64_t contentlen,
+                const char *encoding, const char *location, 
                 int maxage, const char *range)
 {
   struct tm tm0, *tm;
@@ -204,7 +206,7 @@ http_send_header(http_connection_t *hc, int rc, const char *content,
     htsbuf_qprintf(&hdrs, "Content-Type: %s\r\n", content);
 
   if(contentlen > 0)
-    htsbuf_qprintf(&hdrs, "Content-Length: %d\r\n", contentlen);
+    htsbuf_qprintf(&hdrs, "Content-Length: %"PRId64"\r\n", contentlen);
 
   if(range) {
     htsbuf_qprintf(&hdrs, "Accept-Ranges: %s\r\n", "bytes");
index 27897dfe9bf991b48bbc970365a08141051f6c57..86adf1b0e74834d1cead033fb8e020f2e4792cfa 100644 (file)
@@ -30,6 +30,7 @@ typedef struct http_arg {
 } http_arg_t;
 
 #define HTTP_STATUS_OK           200
+#define HTTP_STATUS_PARTIAL_CONTENT 206
 #define HTTP_STATUS_FOUND        302
 #define HTTP_STATUS_BAD_REQUEST  400
 #define HTTP_STATUS_UNAUTHORIZED 401
@@ -111,7 +112,7 @@ void http_output_content(http_connection_t *hc, const char *content);
 void http_redirect(http_connection_t *hc, const char *location);
 
 void http_send_header(http_connection_t *hc, int rc, const char *content, 
-                     int contentlen, const char *encoding,
+                     int64_t contentlen, const char *encoding,
                      const char *location, int maxage, const char *range);
 
 typedef int (http_callback_t)(http_connection_t *hc, 
index 723d5676a63deafa9dfdb98be24251905c77d88c..6c721ac69dc1688e067d509fe79369b0acc79324 100644 (file)
@@ -525,7 +525,8 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque)
   dvr_entry_t *de;
   char *fname;
   char range_buf[255];
-  off_t content_len, file_start, file_end;
+  off_t content_len, file_start, file_end, chunk;
+  ssize_t r;
   
   if(remain == NULL)
     return 404;
@@ -577,19 +578,27 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque)
 
   content_len = file_end - file_start+1;
   
-  sprintf(range_buf, "bytes %"PRId64"-%"PRId64"/%"PRId64"", file_start, file_end, st.st_size);
+  sprintf(range_buf, "bytes %"PRId64"-%"PRId64"/%"PRId64"",
+         file_start, file_end, st.st_size);
 
   if(file_start > 0)
     lseek(fd, file_start, SEEK_SET);
 
-  http_send_header(hc, 200, content, content_len, NULL, NULL, 10, range_buf);
-  sendfile(hc->hc_fd, fd, NULL, content_len);
+  http_send_header(hc, range ? HTTP_STATUS_PARTIAL_CONTENT : HTTP_STATUS_OK,
+                  content, content_len, NULL, NULL, 10, 
+                  range ? range_buf : NULL);
+
+  if(!hc->hc_no_output) {
+    while(content_len > 0) {
+      chunk = MIN(1024 * 1024 * 1024, content_len);
+      r = sendfile(hc->hc_fd, fd, NULL, chunk);
+      if(r == -1)
+       return -1;
+      content_len -= r;
+    }
+  }
   close(fd);
-
-  if(range)
-    return 206;
-  else
-    return 0;
+  return 0;
 }