]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Further refactor of dvr config page and options; addition of user options for file...
authorIan <ian@Server>
Sun, 30 Mar 2014 10:33:34 +0000 (11:33 +0100)
committerIan <ian@Server>
Sun, 30 Mar 2014 10:33:34 +0000 (11:33 +0100)
12 files changed:
docs/html/config_dvr.html
src/dvr/dvr.h
src/dvr/dvr_db.c
src/dvr/dvr_rec.c
src/muxer.h
src/muxer/muxer_pass.c
src/muxer/muxer_tvh.c
src/muxer/tvh/mkmux.c
src/muxer/tvh/mkmux.h
src/utils.c
src/webui/extjs.c
src/webui/static/app/dvr.js

index c541700219bb0de7ea94b61f399527deda05b07f..703ef47aca66c353e3b3e40e276460d165ffeb47 100644 (file)
@@ -75,7 +75,7 @@
   <dt>Recording system path
   <dd>Path to where Tvheadend will write recorded events. If components of the path does not exist, Tvheadend will try to create them.
  
-  <dt>File permissions for recordings (3-byte octal)
+  <dt>File permissions
   <dd>The permissions to be set on the resultant recording files. This is useful if you need to manipulate the files after recording under a different user ID, e.g. to chop out commercials.
       
       <table class="hts-doc-text" border="0">
@@ -86,7 +86,9 @@
          <tr><td>666 == rw-rw-rw-</td></tr>
          </table>
          
-         See also <i>Directory permissions for recordings</i> in <i>Subdirectory Options</i>. 
+         Note that your default user umask applies, so 666 with umask 002 will produce 664.
+         
+         See also <i>Directory permissions</i> in <i>Subdirectory Options</i>. 
          
   <dt>Rewrite PAT in passthrough mode
   <dd>Rewrite the original Program Association Table to only include the active service.  When this option is disabled, Tvheadend will write the original PAT as broadcast, which lists all services from the original multiplex.
   <b>Subdirectory Options</b>
   <hr>
    
-  <dt>Directory permissions for recordings (3-byte octal)
+  <dt>Directory permissions
   <dd>The permissions to be set on any sub-directories created for recordings. This is useful if you need to manipulate the files after recording under a different user ID, e.g. to chop out commercials.
       
       <table class="hts-doc-text" border="0">
          <tr><td>777 == rwxrwxrwx</td></tr>
          </table>
          
-         See also <i>File permissions for recordings</i> in <i>Recroding File Options</i>. 
+         Note that your default user umask applies, so 777 with umask 002 will produce 775.
+         
+         See also <i>File permissions</i> in <i>Recording File Options</i>. 
          
   <dt>Make sub-directories per day
   <dd>If checked, create a new directory per day in the recording system path. Only days when anything is recorded will be created. The format of the directory will be 'YYYY-MM-DD' (ISO standard)
index 4b8c6529e5f87d2bff7c3eb2c718d9fa18b87c46..301aba6312414da939009356f0c7d649e242c5a5 100644 (file)
@@ -29,8 +29,6 @@
 typedef struct dvr_config {
   char *dvr_config_name;
   char *dvr_storage;
-  char *dvr_file_permissions;
-  char *dvr_directory_permissions;
   uint32_t dvr_retention_days;
   int dvr_flags;
   char *dvr_postproc;
@@ -334,9 +332,9 @@ void dvr_storage_set(dvr_config_t *cfg, const char *storage);
 
 void dvr_container_set(dvr_config_t *cfg, const char *container);
 
-void dvr_file_permissions_set(dvr_config_t *cfg, const char *permissions);
+void dvr_file_permissions_set(dvr_config_t *cfg, int permissions);
 
-void dvr_directory_permissions_set(dvr_config_t *cfg, const char *permissions);
+void dvr_directory_permissions_set(dvr_config_t *cfg, int permissions);
 
 void dvr_mux_cache_set(dvr_config_t *cfg, int mcache);
 
index 3bc68d1f09e573fa9c142ab85ed110397f9f5847..70e3983ec6dbdbe38d1bb47216d5fd6e6295e482 100644 (file)
@@ -1133,9 +1133,9 @@ dvr_init(void)
       htsmsg_get_s32(m, "post-extra-time", &cfg->dvr_extra_time_post);
       htsmsg_get_u32(m, "retention-days", &cfg->dvr_retention_days);
       tvh_str_set(&cfg->dvr_storage, htsmsg_get_str(m, "storage"));
-      tvh_str_set(&cfg->dvr_file_permissions, htsmsg_get_str(m, "file-permissions"));
-      tvh_str_set(&cfg->dvr_directory_permissions, htsmsg_get_str(m, "directory-permissions"));
-
+      htsmsg_get_s32(m, "file-permissions", &cfg->dvr_muxcnf.m_file_permissions);
+      htsmsg_get_s32(m, "directory-permissions", &cfg->dvr_muxcnf.m_directory_permissions);
+      
       if(!htsmsg_get_u32(m, "day-dir", &u32) && u32)
         cfg->dvr_flags |= DVR_DIR_PER_DAY;
 
@@ -1315,9 +1315,10 @@ dvr_config_create(const char *name)
   /* dup detect */
   cfg->dvr_dup_detect_episode = 1; // detect dup episodes
 
-  /* Recording file and directory permissions */
-  strcpy(cfg->dvr_file_permissions,"664");
-  strcpy(cfg->dvr_directory_permissions,"775");
+  /* Default recording file and directory permissions */
+  /* Note that these are decimal literal equivalents of the octal - they get converted later. Yes, it's a kludge. Sue me. */  
+  cfg->dvr_muxcnf.m_file_permissions = 664;
+  cfg->dvr_muxcnf.m_directory_permissions = 775;
   
   LIST_INSERT_HEAD(&dvrconfigs, cfg, config_link);
 
@@ -1357,11 +1358,12 @@ static void
 dvr_save(dvr_config_t *cfg)
 {
   htsmsg_t *m = htsmsg_create_map();
+  
   if (cfg->dvr_config_name != NULL && strlen(cfg->dvr_config_name) != 0)
     htsmsg_add_str(m, "config_name", cfg->dvr_config_name);
   htsmsg_add_str(m, "storage", cfg->dvr_storage);
-  htsmsg_add_str(m, "file-permissions", cfg->dvr_file_permissions);
-  htsmsg_add_str(m, "directory-permissions", cfg->dvr_directory_permissions);
+  htsmsg_add_u32(m, "file-permissions", cfg->dvr_muxcnf.m_file_permissions);
+  htsmsg_add_u32(m, "directory-permissions", cfg->dvr_muxcnf.m_directory_permissions);
   htsmsg_add_u32(m, "container", cfg->dvr_mc);
   htsmsg_add_u32(m, "cache", cfg->dvr_muxcnf.m_cache);
   htsmsg_add_u32(m, "rewrite-pat",
@@ -1410,12 +1412,12 @@ dvr_storage_set(dvr_config_t *cfg, const char *storage)
  *
  */
 void
-dvr_file_permissions_set(dvr_config_t *cfg, const char *permissions)
+dvr_file_permissions_set(dvr_config_t *cfg, int permissions)
 {
-  if(cfg->dvr_file_permissions != NULL && !strcmp(cfg->dvr_file_permissions, permissions))
+  if(cfg->dvr_muxcnf.m_file_permissions == permissions)
     return;
 
-  tvh_str_set(&cfg->dvr_file_permissions, permissions);
+  cfg->dvr_muxcnf.m_file_permissions = permissions;
   dvr_save(cfg);
 }
 
@@ -1423,12 +1425,12 @@ dvr_file_permissions_set(dvr_config_t *cfg, const char *permissions)
  *
  */
 void
-dvr_directory_permissions_set(dvr_config_t *cfg, const char *permissions)
+dvr_directory_permissions_set(dvr_config_t *cfg, int permissions)
 {
-  if(cfg->dvr_directory_permissions != NULL && !strcmp(cfg->dvr_directory_permissions, permissions))
+  if(cfg->dvr_muxcnf.m_directory_permissions == permissions)
     return;
 
-  tvh_str_set(&cfg->dvr_directory_permissions, permissions);
+  cfg->dvr_muxcnf.m_directory_permissions = permissions;
   dvr_save(cfg);
 }
 
@@ -1496,7 +1498,7 @@ dvr_retention_set(dvr_config_t *cfg, int days)
 
   cfg->dvr_retention_days = days;
 
-  /* Also, rearm all timres */
+  /* Also, rearm all timers */
 
   LIST_FOREACH(de, &dvrentries, de_global_link)
     if(de->de_sched_state == DVR_COMPLETED)
index b4a8596dcb12490182f57d7f5dcbd265f7def246..2d9938abc29e078f957818530bec4d37cec98dcf 100644 (file)
@@ -204,13 +204,15 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss)
     free(title);
   }
 
-/* IH DEBUG */
+// Very ugly hack alert!
+// Convert my nasty stored-as-decimal permissions into literal octal equivalent (i.e. 777 => 0777)
+  
+  int decimal_perms = cfg->dvr_muxcnf.m_directory_permissions;
+  int octal_perms = ((decimal_perms / 100) << 6) | ((decimal_perms % 100 / 10) << 3) | (decimal_perms % 10);
 
-  tvhlog(LOG_DEBUG, "dvr_rec - pvr_generate_filename", "Using string directory permissions: \"%s\"", cfg->dvr_directory_permissions);
-  tvhlog(LOG_DEBUG, "dvr_rec - pvr_generate_filename", "Using int directory permissions: \"%i\"", atoi(cfg->dvr_directory_permissions));
+// Create directory path
   
-  /* */
-  if(makedirs(path, atoi(cfg->dvr_directory_permissions)) != 0) {
+  if(makedirs(path, octal_perms) != 0) {
     return -1;
   }
   
@@ -324,11 +326,6 @@ dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss)
     }
   }
 
- /* IH DEBUG */
-  tvhlog(LOG_DEBUG, "dvr - dvr_rec_start", "Using file/directory permissions: \"%s\", \"%s\"", 
-     cfg->dvr_file_permissions, cfg->dvr_directory_permissions);
-  
   tvhlog(LOG_INFO, "dvr", "%s from "
         "adapter: \"%s\", "
         "network: \"%s\", mux: \"%s\", provider: \"%s\", "
index a89c28846fb166603b6c1a9e27d58638b97be589..1f85822f96c69c99f46a21034d8bc149cfbc0e09 100644 (file)
@@ -47,8 +47,10 @@ typedef enum {
 typedef struct muxer_config {
   int                  m_flags;
   muxer_cache_type_t m_cache;
-  char                 *m_file_permissions;
-  char                 *m_directory_permissions;
+// directory_permissions should really be in dvr.h as it's not really needed for the muxer
+// but it's kept with file_permissions for neatness
+  int                  m_file_permissions;
+  int                  m_directory_permissions; 
 } muxer_config_t;
 
 struct muxer;
index 4914c5f445b2077b6aba467704514cd71ee46e45..abde368950bf4b6b3993b0503763063d72a3a892 100644 (file)
@@ -378,11 +378,15 @@ pass_muxer_open_file(muxer_t *m, const char *filename)
   int fd;
   pass_muxer_t *pm = (pass_muxer_t*)m;
 
-/* IH DEBUG */
-
-  tvhlog(LOG_DEBUG, "muxer_pass - pass_muxer_open_file", "Using file permissions: \"%s\"", pm->m_config.m_file_permissions);
+// Very ugly hack alert!
+// Convert my nasty stored-as-decimal permissions into literal octal equivalent (i.e. 777 => 0777)
   
-  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, pm->m_config.m_file_permissions);
+  int decimal_perms = pm->m_config.m_file_permissions;
+  int octal_perms = ((decimal_perms / 100) << 6) | ((decimal_perms % 100 / 10) << 3) | (decimal_perms % 10);
+
+  tvhlog(LOG_DEBUG, "pass", "Creating file \"%s\" with octal permissions \"%o\"", filename, octal_perms);
+  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, octal_perms);
+
   if(fd < 0) {
     pm->pm_error = errno;
     tvhlog(LOG_ERR, "pass", "%s: Unable to create file, open failed -- %s",
@@ -551,11 +555,6 @@ pass_muxer_create(muxer_container_type_t mc, const muxer_config_t *m_cfg)
   if(mc != MC_PASS && mc != MC_RAW)
     return NULL;
 
-/* debugging to see if the variable is available here */
-/* IH 26 March */
-
-  tvhlog(LOG_DEBUG, "muxer_pass - pass_muxer_create", "Using file permissions: \"%s\"", m_cfg->m_file_permissions);
-    
   pm = calloc(1, sizeof(pass_muxer_t));
   pm->m_open_stream  = pass_muxer_open_stream;
   pm->m_open_file    = pass_muxer_open_file;
index 4cd2e1269f800a3e86d87bf038155cfd43db97b9..715328ce56c189af951a9af57244e0d3603631d2 100644 (file)
@@ -138,10 +138,6 @@ tvh_muxer_open_file(muxer_t *m, const char *filename)
 {
   tvh_muxer_t *tm = (tvh_muxer_t*)m;
   
-/* IH DEBUG */
-
-  tvhlog(LOG_DEBUG, "muxer_tvh - tvh_muxer_open", "Using file permissions: \"%s\"", tm->m_config.m_file_permissions);
   if(mk_mux_open_file(tm->tm_ref, filename, tm->m_config.m_file_permissions)) {
     tm->m_errors++;
     return -1;
@@ -231,11 +227,6 @@ tvh_muxer_create(muxer_container_type_t mc, const muxer_config_t *m_cfg)
   if(mc != MC_MATROSKA && mc != MC_WEBM)
     return NULL;
 
-/* debugging to see if the variable is available here */
-/* IH 26 March */
-
-  tvhlog(LOG_DEBUG, "muxer_tvh - tvh_muxer_create", "Using file permissions: \"%s\"", m_cfg->m_file_permissions);
-
   tm = calloc(1, sizeof(tvh_muxer_t));
   tm->m_open_stream  = tvh_muxer_open_stream;
   tm->m_open_file    = tvh_muxer_open_file;
index 2199676a2a273f2d7ec3b576e46473ee5819f1f0..a810cb35a15485e2749620397abba5801d847946 100644 (file)
@@ -1046,15 +1046,17 @@ mk_mux_open_stream(mk_mux_t *mkm, int fd)
  *
  */
 int
-mk_mux_open_file(mk_mux_t *mkm, const char *filename, const char *permissions)
+mk_mux_open_file(mk_mux_t *mkm, const char *filename, int permissions)
 {
   int fd;
 
-/* IH DEBUG */
-
-  tvhlog(LOG_DEBUG, "mkmux - tmk_mux_open_file", "Using file permissions: \"%s\"", permissions);
+// Very ugly hack alert!
+// Convert my nasty stored-as-decimal permissions into literal octal equivalent (i.e. 777 => 0777)
   
-  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, permissions);
+  int octal_perms = ((permissions / 100) << 6) | ((permissions % 100 / 10) << 3) | (permissions % 10);
+
+  tvhlog(LOG_DEBUG, "mkv", "Creating file \"%s\" with octal permissions \"%o\"", filename, octal_perms);
+  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, octal_perms);
   if(fd < 0) {
     mkm->error = errno;
     tvhlog(LOG_ERR, "mkv", "%s: Unable to create file, open failed -- %s",
index c9a3908fa0face6f0a575ab1920adc9cddd54ddf..a107ff40ffd57db33c5321f23fe3801785f8f9e7 100644 (file)
@@ -30,7 +30,7 @@ struct event;
 
 mk_mux_t *mk_mux_create(muxer_t *m, int webm);
 
-int mk_mux_open_file  (mk_mux_t *mkm, const char *filename, const char *permissions);
+int mk_mux_open_file  (mk_mux_t *mkm, const char *filename, int permissions);
 int mk_mux_open_stream(mk_mux_t *mkm, int fd);
 
 int mk_mux_init(mk_mux_t *mkm, const char *title, 
index 69f51c28424c44faf77ba2a33b330f2d7367863f..6eab4ec7209d7d2994ceaa5bfd035b80cab5b738 100644 (file)
@@ -397,6 +397,7 @@ makedirs ( const char *inpath, int mode )
       path[x] = 0;
       if (stat(path, &st)) {
         err = mkdir(path, mode);
+        tvhlog(LOG_DEBUG, "settings", "Creating directory \"%s\" with octal permissions \"%o\"", path, mode);
       } else {
         err   = S_ISDIR(st.st_mode) ? 0 : 1;
         errno = ENOTDIR;
index 8c0de11c1e43265860bfb0b71bcfe1d304ba5cfa..9e369644c285ec40c3d977c191e9bdf8927302b7 100755 (executable)
@@ -1126,8 +1126,8 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
     r = htsmsg_create_map();
     htsmsg_add_str(r, "storage", cfg->dvr_storage);
     htsmsg_add_str(r, "container", muxer_container_type2txt(cfg->dvr_mc));
-    htsmsg_add_str(r, "file-permissions", cfg->dvr_muxcnf.m_file_permissions);
-    htsmsg_add_str(r, "directory-permissions", cfg->dvr_muxcnf.m_directory_permissions);
+    htsmsg_add_u32(r, "filePermissions", cfg->dvr_muxcnf.m_file_permissions);
+    htsmsg_add_u32(r, "dirPermissions", cfg->dvr_muxcnf.m_directory_permissions);
     htsmsg_add_u32(r, "cache",     cfg->dvr_muxcnf.m_cache);
     htsmsg_add_u32(r, "rewritePAT",
                    !!(cfg->dvr_muxcnf.m_flags & MC_REWRITE_PAT));
@@ -1168,12 +1168,12 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
     
    if((s = http_arg_get(&hc->hc_req_args, "container")) != NULL)
       dvr_container_set(cfg,s);
-
    if((s = http_arg_get(&hc->hc_req_args, "filePermissions")) != NULL)
-      dvr_file_permissions_set(cfg,s);
-      
-   if((s = http_arg_get(&hc->hc_req_args, "directoryPermissions")) != NULL)
-      dvr_directory_permissions_set(cfg,s);
+      dvr_file_permissions_set(cfg,atoi(s));
+
+   if((s = http_arg_get(&hc->hc_req_args, "dirPermissions")) != NULL)
+      dvr_directory_permissions_set(cfg,atoi(s));
       
    if((s = http_arg_get(&hc->hc_req_args, "cache")) != NULL)
       dvr_mux_cache_set(cfg,atoi(s));
index 324045d96bddb8202ceeabd7f86dd8a82873a895..63fde3f528e95e3a7d2804ca1a481b1f8b6be1f7 100644 (file)
@@ -744,11 +744,11 @@ tvheadend.dvrsettings = function() {
 
        var confreader = new Ext.data.JsonReader({
                root : 'dvrSettings'
-       }, [ 'storage', 'postproc', 'retention', 'dayDirs', 'channelDirs',
+       }, [ 'storage', 'filePermissions', 'dirPermissions', 'postproc', 'retention', 'dayDirs', 'channelDirs',
                'channelInTitle', 'container', 'cache', 'dateInTitle', 'timeInTitle',
                'preExtraTime', 'postExtraTime', 'whitespaceInTitle', 'titleDirs',
                'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle', 
-               'episodeBeforeDate', 'rewritePAT', 'rewritePMT', 'filePermissions', 'dirPermissions' ]);
+               'episodeBeforeDate', 'rewritePAT', 'rewritePMT' ]);
 
        var confcombo = new Ext.form.ComboBox({
                store : tvheadend.configNames,
@@ -828,13 +828,20 @@ tvheadend.dvrsettings = function() {
                fieldLabel : 'Recording system path',
                name : 'storage'
        });
+
+/* NB: recordingPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a decimal number */
        
        var recordingPermissions = new Ext.form.TextField({
-           regex : /^[0-7]{3}$/,
+               regex : /^[0-7]{3}$/,
            maskRe : /[0-7]/,
-               fieldLabel : 'File permissions for recordings (3-byte octal)',
+               width : 100,
+               allowBlank : false,
+               blankText : 'You must provide a value - use octal chmod notation, e.g. 664',
+               fieldLabel : 'File permissions (octal, e.g. 664)',
                name : 'filePermissions'
        });
+
+/* TO DO - Add 'override user umask?' option, then trigger fchmod in mkmux.c, muxer_pass.c after file created */
                
        var PATrewrite = new Ext.form.Checkbox({
                fieldLabel : 'Rewrite PAT in passthrough mode',
@@ -858,13 +865,20 @@ tvheadend.dvrsettings = function() {
                
 /* Subdirectories and filename handling */
 
+/* NB: directoryPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a decimal number */
+
        var directoryPermissions = new Ext.form.TextField({
-           regex : /^[0-7]{3}$/,
+               regex : /^[0-7]{3}$/,
            maskRe : /[0-7]/,
-               fieldLabel : 'Directory permissions for recordings (3-byte octal)',
+               width : 100,
+               allowBlank : false,
+               blankText : 'You must provide a value - use octal chmod notation, e.g. 775',
+               fieldLabel : 'Directory permissions (octal, e.g. 775)',
                name : 'dirPermissions'
        });
        
+/* TO DO - Add 'override user umask?' option, then trigger fchmod in utils.c after directory created */
+       
        var dirsPerDay = new Ext.form.Checkbox({
                fieldLabel : 'Make subdirectories per day',
                name : 'dayDirs'
@@ -963,7 +977,7 @@ tvheadend.dvrsettings = function() {
        });
 
 /* Main (form) panel */
-       
+                               
        var confpanel = new Ext.FormPanel({
                title : 'Digital Video Recorder',
                iconCls : 'drive',