From 401608cc69f86bfdf05dba59b231dde06f80a8bb Mon Sep 17 00:00:00 2001 From: Ian Date: Thu, 27 Mar 2014 11:22:32 +0000 Subject: [PATCH 1/5] Refactor of dvr config page and options; addition of user options for file and directory permissions throughout. --- docs/html/config_dvr.html | 184 +++++++++++++---------- src/dvr/dvr.h | 6 + src/dvr/dvr_db.c | 34 +++++ src/dvr/dvr_rec.c | 12 +- src/muxer.h | 4 +- src/muxer/muxer_pass.c | 11 +- src/muxer/muxer_tvh.c | 11 +- src/muxer/tvh/mkmux.c | 8 +- src/muxer/tvh/mkmux.h | 2 +- src/webui/extjs.c | 8 + src/webui/static/app/dvr.js | 286 +++++++++++++++++++++++++----------- 11 files changed, 391 insertions(+), 175 deletions(-) diff --git a/docs/html/config_dvr.html b/docs/html/config_dvr.html index adce28bc..c5417002 100644 --- a/docs/html/config_dvr.html +++ b/docs/html/config_dvr.html @@ -8,11 +8,14 @@

Configuration options: +

-
Recording system path -
Path to where Tvheadend will write recorded events. If components of - the path does not exist, Tvheadend will try to create them. - + +

+
+ DVR Behaviour +
+
Media container
Select the container format used to store recordings. @@ -34,88 +37,18 @@
Combination of two above variants.
- -
Rewrite PAT in passthrough mode -
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. - -
Rewrite PMT in passthrough mode -
Generate a Program Map Table only listing the streams actually in - the output transport stream. When this option is disabled, - Tvheadend will write the original Program Map Table as - broadcast, which may include references to excluded streams such - as data and ECMs. - +
DVR Log retention time (days) -
Time that Tvheadend will keep information about the recording in - its internal database. Notice that the actual recorded file will not - be deleted when the log entry is deleted. +
Time that Tvheadend will keep information about the recording in its internal database. Notice that the actual recorded file will not be deleted when the log entry is deleted.
Extra time before recordings (minutes) -
Specify the number of minutes to record before the events scheduled - start time. Used to cope with small scheduling errors. +
Specify the number of minutes to record before the events scheduled start time. Used to cope with small scheduling errors.
Extra time after recordings (minutes) -
Specify the number of minutes to record after the events scheduled - stop time. Used to cope with small scheduling errors. - -
Make sub-directories per day -
If checked, Tvheadend will 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) - -
Make sub-directories per channel -
If checked, Tvheadend will create a directory per channel when storing - events. If both this and the 'directory per day' checkbox is enabled, - the date-directory will be parent to the per-channel directory. - -
Make sub-directories per title -
If checked, Tvheadend will create a directory per title when storing - events. If the day/channel directory checkboxes are also enabled, those - directories will be parents of this directory. - -
Include channel name in title -
If checked, Tvheadend will include the name of the channel in the - event title. This applies to both the titled stored in the file - and to the file name itself. - -
Include date in title -
If checked, Tvheadend will include the date for the recording in the - event title. This applies to both the titled stored in the file - and to the file name itself. - -
Include time in title -
If checked, Tvheadend will include the time for the recording in the - event title. This applies to both the titled stored in the file - and to the file name itself. - -
Include episode in title -
If checked, Tvheadend will include the season and episode in the - title (if such info is available). - -
Remove all unsafe characters from filename -
If checked, all characters that could possibly cause problems for - filenaming will be removed. - -
Replace whitespace in title with '-' -
If checked, all whitespace characters will be replaced with '-'. - -
Tag files with metadata -
If checked, media containers that support metadata will be tagged with - the metadata associated with the event being recorded. - -
Skip commercials -
If checked, commercials will be dropped from the recordings. At the - moment, commercial detection only works for the swedish channel TV4. +
Specify the number of minutes to record after the events scheduled stop time. Used to cope with small scheduling errors.
Post-processor command -
Command to run after finishing a recording. The command will be - run in background and is executed even if a recording is aborted - or an error occurred. Use the %e error formatting string to check - for errors, the error string is empty if recording finished - successfully. +
Command to run after finishing a recording. The command will be run in background and is executed even if a recording is aborted or an error occurred. Use the %e error formatting string to check for errors, the error string is empty if recording finished successfully.

Support format strings:
@@ -133,7 +66,96 @@
Example usage: /path/to/ffmpeg -i %f -vcodec libx264 -acodec copy "/path/with white space/%b"
You need to use quotes or escape white spaces if you want white spaces in an argument. + +

+
+ Recording File Options +
+ +
Recording system path +
Path to where Tvheadend will write recorded events. If components of the path does not exist, Tvheadend will try to create them. + +
File permissions for recordings (3-byte octal) +
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. + +
+ +
+ + + +
Common examples:
644 == rw-r--r--
664 == rw-rw-r-- (default)
666 == rw-rw-rw-
+ + See also Directory permissions for recordings in Subdirectory Options. + +
Rewrite PAT in passthrough mode +
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. + +
Rewrite PMT in passthrough mode +
Generate a Program Map Table only listing the streams actually in the output transport stream. When this option is disabled, Tvheadend will write the original Program Map Table as broadcast, which may include references to excluded streams such as data and ECMs. + +
Tag files with metadata +
If checked, media containers that support metadata will be tagged with the metadata associated with the event being recorded. + +
Skip commercials +
If checked, commercials will be dropped from the recordings. At the moment, commercial detection only works for the swedish channel TV4. + +

+
+ Subdirectory Options +
+ +
Directory permissions for recordings (3-byte octal) +
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. + + + +
+ + + +
Common examples:
755 == rwxr--r--
775 == rwxrwxr-- (default)
777 == rwxrwxrwx
+ + See also File permissions for recordings in Recroding File Options. + +
Make sub-directories per day +
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) + +
Make sub-directories per channel +
If checked, create a directory per channel when storing events. If both this and the 'directory per day' checkbox is enabled, the date-directory will be parent to the per-channel directory. + +
Make sub-directories per title +
If checked, create a directory per title when storing events. If the day/channel directory checkboxes are also enabled, those directories will be parents of this directory. + +

+
+ Filename Options +
+ +
Include channel name in title +
If checked, include the name of the channel in the event title. This applies to both the titled stored in the file and to the file name itself. + +
Include date in title +
If checked, include the date for the recording in the event title. This applies to both the titled stored in the file and to the file name itself. + +
Include time in title +
If checked, include the time for the recording in the event title. This applies to both the titled stored in the file and to the file name itself. + +
Include episode in title +
If checked, include the season and episode in the title (if such info is available). + +
Include subtitle in title +
If checked, include the episode subtitle in the title (if such info is available). + +
Put episode in filename before date and time +
If checked, insert the episode number before the data and time rather than after (assumes Include date, Include time and Include episode options are set). + +
Remove all unsafe characters from filename +
If checked, all characters that could possibly cause problems for filenaming will be removed. + +
Replace whitespace in title with '-' +
If checked, all whitespace characters will be replaced with '-'. + - Changes to any of these settings must be confirmed by pressing the - 'Save configuration' button before taking effect. + Changes to any of these settings must be confirmed by pressing the 'Save configuration' button before taking effect. diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 709b51e8..4b8c6529 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -29,6 +29,8 @@ 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; @@ -332,6 +334,10 @@ 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_directory_permissions_set(dvr_config_t *cfg, const char *permissions); + void dvr_mux_cache_set(dvr_config_t *cfg, int mcache); void dvr_postproc_set(dvr_config_t *cfg, const char *postproc); diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index d37ceb28..3bc68d1f 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1133,6 +1133,8 @@ 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")); if(!htsmsg_get_u32(m, "day-dir", &u32) && u32) cfg->dvr_flags |= DVR_DIR_PER_DAY; @@ -1313,6 +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"); + LIST_INSERT_HEAD(&dvrconfigs, cfg, config_link); return LIST_FIRST(&dvrconfigs); @@ -1354,6 +1360,8 @@ dvr_save(dvr_config_t *cfg) 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, "container", cfg->dvr_mc); htsmsg_add_u32(m, "cache", cfg->dvr_muxcnf.m_cache); htsmsg_add_u32(m, "rewrite-pat", @@ -1398,6 +1406,32 @@ dvr_storage_set(dvr_config_t *cfg, const char *storage) dvr_save(cfg); } +/** + * + */ +void +dvr_file_permissions_set(dvr_config_t *cfg, const char *permissions) +{ + if(cfg->dvr_file_permissions != NULL && !strcmp(cfg->dvr_file_permissions, permissions)) + return; + + tvh_str_set(&cfg->dvr_file_permissions, permissions); + dvr_save(cfg); +} + +/** + * + */ +void +dvr_directory_permissions_set(dvr_config_t *cfg, const char *permissions) +{ + if(cfg->dvr_directory_permissions != NULL && !strcmp(cfg->dvr_directory_permissions, permissions)) + return; + + tvh_str_set(&cfg->dvr_directory_permissions, permissions); + dvr_save(cfg); +} + /** * */ diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index de6169e9..b4a8596d 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -204,9 +204,13 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) free(title); } +/* IH DEBUG */ + 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)); + /* */ - if(makedirs(path, 0755) != 0) { + if(makedirs(path, atoi(cfg->dvr_directory_permissions)) != 0) { return -1; } @@ -320,10 +324,16 @@ 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\", " "service: \"%s\"", + de->de_filename ?: lang_str_get(de->de_title, NULL), si->si_adapter ?: "", si->si_network ?: "", diff --git a/src/muxer.h b/src/muxer.h index 9f147d58..a89c2884 100644 --- a/src/muxer.h +++ b/src/muxer.h @@ -45,8 +45,10 @@ typedef enum { /* Muxer configuration used when creating a muxer. */ typedef struct muxer_config { - int m_flags; + int m_flags; muxer_cache_type_t m_cache; + char *m_file_permissions; + char *m_directory_permissions; } muxer_config_t; struct muxer; diff --git a/src/muxer/muxer_pass.c b/src/muxer/muxer_pass.c index 64b53411..4914c5f4 100644 --- a/src/muxer/muxer_pass.c +++ b/src/muxer/muxer_pass.c @@ -378,7 +378,11 @@ pass_muxer_open_file(muxer_t *m, const char *filename) int fd; pass_muxer_t *pm = (pass_muxer_t*)m; - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); +/* IH DEBUG */ + + tvhlog(LOG_DEBUG, "muxer_pass - pass_muxer_open_file", "Using file permissions: \"%s\"", pm->m_config.m_file_permissions); + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, pm->m_config.m_file_permissions); if(fd < 0) { pm->pm_error = errno; tvhlog(LOG_ERR, "pass", "%s: Unable to create file, open failed -- %s", @@ -547,6 +551,11 @@ 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; diff --git a/src/muxer/muxer_tvh.c b/src/muxer/muxer_tvh.c index 44768dd8..4cd2e126 100644 --- a/src/muxer/muxer_tvh.c +++ b/src/muxer/muxer_tvh.c @@ -138,7 +138,11 @@ tvh_muxer_open_file(muxer_t *m, const char *filename) { tvh_muxer_t *tm = (tvh_muxer_t*)m; - if(mk_mux_open_file(tm->tm_ref, filename)) { +/* 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; } @@ -227,6 +231,11 @@ 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; diff --git a/src/muxer/tvh/mkmux.c b/src/muxer/tvh/mkmux.c index c5a2a8fb..2199676a 100644 --- a/src/muxer/tvh/mkmux.c +++ b/src/muxer/tvh/mkmux.c @@ -1046,11 +1046,15 @@ mk_mux_open_stream(mk_mux_t *mkm, int fd) * */ int -mk_mux_open_file(mk_mux_t *mkm, const char *filename) +mk_mux_open_file(mk_mux_t *mkm, const char *filename, const char *permissions) { int fd; - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); +/* IH DEBUG */ + + tvhlog(LOG_DEBUG, "mkmux - tmk_mux_open_file", "Using file permissions: \"%s\"", permissions); + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, permissions); if(fd < 0) { mkm->error = errno; tvhlog(LOG_ERR, "mkv", "%s: Unable to create file, open failed -- %s", diff --git a/src/muxer/tvh/mkmux.h b/src/muxer/tvh/mkmux.h index 6840d3f1..c9a3908f 100644 --- a/src/muxer/tvh/mkmux.h +++ b/src/muxer/tvh/mkmux.h @@ -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); +int mk_mux_open_file (mk_mux_t *mkm, const char *filename, const char *permissions); int mk_mux_open_stream(mk_mux_t *mkm, int fd); int mk_mux_init(mk_mux_t *mkm, const char *title, diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 00225b9a..8c0de11c 100755 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -1126,6 +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, "cache", cfg->dvr_muxcnf.m_cache); htsmsg_add_u32(r, "rewritePAT", !!(cfg->dvr_muxcnf.m_flags & MC_REWRITE_PAT)); @@ -1167,6 +1169,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); + if((s = http_arg_get(&hc->hc_req_args, "cache")) != NULL) dvr_mux_cache_set(cfg,atoi(s)); diff --git a/src/webui/static/app/dvr.js b/src/webui/static/app/dvr.js index 7a97a183..324045d9 100644 --- a/src/webui/static/app/dvr.js +++ b/src/webui/static/app/dvr.js @@ -747,7 +747,8 @@ tvheadend.dvrsettings = function() { }, [ 'storage', 'postproc', 'retention', 'dayDirs', 'channelDirs', 'channelInTitle', 'container', 'cache', 'dateInTitle', 'timeInTitle', 'preExtraTime', 'postExtraTime', 'whitespaceInTitle', 'titleDirs', - 'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle', 'episodeBeforeDate', 'rewritePAT', 'rewritePMT' ]); + 'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle', + 'episodeBeforeDate', 'rewritePAT', 'rewritePMT', 'filePermissions', 'dirPermissions' ]); var confcombo = new Ext.form.ComboBox({ store : tvheadend.configNames, @@ -768,6 +769,201 @@ tvheadend.dvrsettings = function() { disabled : true }); +/* Config panel variables */ + +/* DVR Behaviour */ + + var recordingContainer = new Ext.form.ComboBox({ + store : tvheadend.containers, + fieldLabel : 'Media container', + triggerAction : 'all', + displayField : 'description', + valueField : 'name', + editable : false, + width : 200, + hiddenName : 'container' + }); + + var cacheScheme = new Ext.form.ComboBox({ + store : tvheadend.caches, + fieldLabel : 'Cache scheme', + triggerAction : 'all', + displayField : 'description', + valueField : 'index', + editable : false, + width : 200, + hiddenName : 'cache' + }); + + var logRetention = new Ext.form.NumberField({ + allowNegative : false, + allowDecimals : false, + minValue : 1, + fieldLabel : 'DVR Log retention time (days)', + name : 'retention' + }); + + var timeBefore = new Ext.form.NumberField({ + allowDecimals : false, + fieldLabel : 'Extra time before recordings (minutes)', + name : 'preExtraTime' + }); + + var timeAfter = new Ext.form.NumberField({ + allowDecimals : false, + fieldLabel : 'Extra time after recordings (minutes)', + name : 'postExtraTime' + }); + + var postProcessing = new Ext.form.TextField({ + width : 300, + fieldLabel : 'Post-processor command', + name : 'postproc' + }); + +/* Recording File Options */ + + var recordingPath = new Ext.form.TextField({ + width : 300, + fieldLabel : 'Recording system path', + name : 'storage' + }); + + var recordingPermissions = new Ext.form.TextField({ + regex : /^[0-7]{3}$/, + maskRe : /[0-7]/, + fieldLabel : 'File permissions for recordings (3-byte octal)', + name : 'filePermissions' + }); + + var PATrewrite = new Ext.form.Checkbox({ + fieldLabel : 'Rewrite PAT in passthrough mode', + name : 'rewritePAT' + }); + + var PMTrewrite = new Ext.form.Checkbox({ + fieldLabel : 'Rewrite PMT in passthrough mode', + name : 'rewritePMT' + }); + + var tagMetadata = new Ext.form.Checkbox({ + fieldLabel : 'Tag files with metadata', + name : 'tagFiles' + }); + + var skipCommercials = new Ext.form.Checkbox({ + fieldLabel : 'Skip commercials', + name : 'commSkip' + }); + +/* Subdirectories and filename handling */ + + var directoryPermissions = new Ext.form.TextField({ + regex : /^[0-7]{3}$/, + maskRe : /[0-7]/, + fieldLabel : 'Directory permissions for recordings (3-byte octal)', + name : 'dirPermissions' + }); + + var dirsPerDay = new Ext.form.Checkbox({ + fieldLabel : 'Make subdirectories per day', + name : 'dayDirs' + }); + + var dirsPerChannel = new Ext.form.Checkbox({ + fieldLabel : 'Make subdirectories per channel', + name : 'channelDirs' + }); + + var dirsPerTitle = new Ext.form.Checkbox({ + fieldLabel : 'Make subdirectories per title', + name : 'titleDirs' + }); + + var incChannelInTitle = new Ext.form.Checkbox({ + fieldLabel : 'Include channel name in filename', + name : 'channelInTitle' + }); + + var incDateInTitle = new Ext.form.Checkbox({ + fieldLabel : 'Include date in filename', + name : 'dateInTitle' + }); + + var incTimeInTitle = new Ext.form.Checkbox({ + fieldLabel : 'Include time in filename', + name : 'timeInTitle' + }); + + var incEpisodeInTitle = new Ext.form.Checkbox({ + fieldLabel : 'Include episode in filename', + name : 'episodeInTitle' + }); + + var incSubtitleInTitle = new Ext.form.Checkbox({ + fieldLabel : 'Include subtitle in filename', + name : 'subtitleInTitle' + }); + + var episodeFirst = new Ext.form.Checkbox({ + fieldLabel : 'Put episode in filename before date and time', + name : 'episodeBeforeDate' + }); + + var stripUnsafeChars = new Ext.form.Checkbox({ + fieldLabel : 'Remove all unsafe characters from filename', + name : 'cleanTitle' + }); + + var stripWhitespace = new Ext.form.Checkbox({ + fieldLabel : 'Replace whitespace in title with \'-\'', + name : 'whitespaceInTitle' + }); + + +/* Sub-Panel - DVR behaviour */ + + var DVRBehaviour = new Ext.form.FieldSet({ + title: 'DVR Behaviour', + width: 700, + autoHeight: true, + collapsible: true, + items : [ recordingContainer, cacheScheme, logRetention, timeBefore, timeAfter, postProcessing ] + }); + +/* Sub-Panel - File Output */ + + var FileOutputPanel = new Ext.form.FieldSet({ + title: 'Recording File Options', + width: 700, + autoHeight: true, + collapsible: true, + items : [ recordingPath, recordingPermissions, PATrewrite, PMTrewrite, tagMetadata, skipCommercials ] + }); + +/* Sub-Panel - Directory operations */ + + var DirHandlingPanel = new Ext.form.FieldSet({ + title: 'Subdirectory Options', + width: 700, + autoHeight: true, + collapsible: true, + items : [ directoryPermissions, dirsPerDay, dirsPerChannel, dirsPerTitle ] + }); + +/* Sub-Panel - File operations */ + + var FileHandlingPanel = new Ext.form.FieldSet({ + title: 'Filename Options', + width: 700, + autoHeight: true, + collapsible: true, + items : [ incChannelInTitle, incDateInTitle, incTimeInTitle, incEpisodeInTitle, + incSubtitleInTitle, episodeFirst, stripUnsafeChars, stripWhitespace ] + }); + +/* Main (form) panel */ + var confpanel = new Ext.FormPanel({ title : 'Digital Video Recorder', iconCls : 'drive', @@ -780,92 +976,8 @@ tvheadend.dvrsettings = function() { reader : confreader, defaultType : 'textfield', layout : 'form', - items : [ { - width : 300, - fieldLabel : 'Recording system path', - name : 'storage' - }, new Ext.form.ComboBox({ - store : tvheadend.containers, - fieldLabel : 'Media container', - triggerAction : 'all', - displayField : 'description', - valueField : 'name', - editable : false, - width : 200, - hiddenName : 'container' - }), new Ext.form.ComboBox({ - store : tvheadend.caches, - fieldLabel : 'Cache scheme', - triggerAction : 'all', - displayField : 'description', - valueField : 'index', - editable : false, - width : 200, - hiddenName : 'cache' - }), new Ext.form.Checkbox({ - fieldLabel : 'Rewrite PAT in passthrough mode', - name : 'rewritePAT' - }), new Ext.form.Checkbox({ - fieldLabel : 'Rewrite PMT in passthrough mode', - name : 'rewritePMT' - }), new Ext.form.NumberField({ - allowNegative : false, - allowDecimals : false, - minValue : 1, - fieldLabel : 'DVR Log retention time (days)', - name : 'retention' - }), new Ext.form.NumberField({ - allowDecimals : false, - fieldLabel : 'Extra time before recordings (minutes)', - name : 'preExtraTime' - }), new Ext.form.NumberField({ - allowDecimals : false, - fieldLabel : 'Extra time after recordings (minutes)', - name : 'postExtraTime' - }), new Ext.form.Checkbox({ - fieldLabel : 'Make subdirectories per day', - name : 'dayDirs' - }), new Ext.form.Checkbox({ - fieldLabel : 'Make subdirectories per channel', - name : 'channelDirs' - }), new Ext.form.Checkbox({ - fieldLabel : 'Make subdirectories per title', - name : 'titleDirs' - }), new Ext.form.Checkbox({ - fieldLabel : 'Include channel name in filename', - name : 'channelInTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Include date in filename', - name : 'dateInTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Include time in filename', - name : 'timeInTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Include episode in filename', - name : 'episodeInTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Remove all unsafe characters from filename', - name : 'cleanTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Replace whitespace in title with \'-\'', - name : 'whitespaceInTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Tag files with metadata', - name : 'tagFiles' - }), new Ext.form.Checkbox({ - fieldLabel : 'Skip commercials', - name : 'commSkip' - }), new Ext.form.Checkbox({ - fieldLabel : 'Include subtitle in filename', - name : 'subtitleInTitle' - }), new Ext.form.Checkbox({ - fieldLabel : 'Put episode in filename before date and time', - name : 'episodeBeforeDate' - }), { - width : 300, - fieldLabel : 'Post-processor command', - name : 'postproc' - } ], + items : [ DVRBehaviour, FileOutputPanel, DirHandlingPanel, FileHandlingPanel ], + tbar : [ confcombo, { tooltip : 'Save changes made to dvr configuration below', iconCls : 'save', From 61e6d67528a19a1ae5491aedf3b3ce08d30426e6 Mon Sep 17 00:00:00 2001 From: Ian Date: Sun, 30 Mar 2014 11:33:34 +0100 Subject: [PATCH 2/5] Further refactor of dvr config page and options; addition of user options for file and directory permissions throughout. --- docs/html/config_dvr.html | 12 ++++++++---- src/dvr/dvr.h | 6 ++---- src/dvr/dvr_db.c | 32 +++++++++++++++++--------------- src/dvr/dvr_rec.c | 19 ++++++++----------- src/muxer.h | 6 ++++-- src/muxer/muxer_pass.c | 17 ++++++++--------- src/muxer/muxer_tvh.c | 9 --------- src/muxer/tvh/mkmux.c | 12 +++++++----- src/muxer/tvh/mkmux.h | 2 +- src/utils.c | 1 + src/webui/extjs.c | 14 +++++++------- src/webui/static/app/dvr.js | 28 +++++++++++++++++++++------- 12 files changed, 84 insertions(+), 74 deletions(-) diff --git a/docs/html/config_dvr.html b/docs/html/config_dvr.html index c5417002..703ef47a 100644 --- a/docs/html/config_dvr.html +++ b/docs/html/config_dvr.html @@ -75,7 +75,7 @@
Recording system path
Path to where Tvheadend will write recorded events. If components of the path does not exist, Tvheadend will try to create them. -
File permissions for recordings (3-byte octal) +
File permissions
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. @@ -86,7 +86,9 @@
666 == rw-rw-rw-
- See also Directory permissions for recordings in Subdirectory Options. + Note that your default user umask applies, so 666 with umask 002 will produce 664. + + See also Directory permissions in Subdirectory Options.
Rewrite PAT in passthrough mode
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. @@ -105,7 +107,7 @@ Subdirectory Options
-
Directory permissions for recordings (3-byte octal) +
Directory permissions
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. @@ -116,7 +118,9 @@
777 == rwxrwxrwx
- See also File permissions for recordings in Recroding File Options. + Note that your default user umask applies, so 777 with umask 002 will produce 775. + + See also File permissions in Recording File Options.
Make sub-directories per day
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) diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 4b8c6529..301aba63 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -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); diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 3bc68d1f..70e3983e 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -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) diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index b4a8596d..2d9938ab 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -204,13 +204,15 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) free(title); } -/* IH DEBUG */ - - 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)); +// Very ugly hack alert! +// Convert my nasty stored-as-decimal permissions into literal octal equivalent (i.e. 777 => 0777) - /* */ - if(makedirs(path, atoi(cfg->dvr_directory_permissions)) != 0) { + int decimal_perms = cfg->dvr_muxcnf.m_directory_permissions; + int octal_perms = ((decimal_perms / 100) << 6) | ((decimal_perms % 100 / 10) << 3) | (decimal_perms % 10); + +// Create directory path + + 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\", " diff --git a/src/muxer.h b/src/muxer.h index a89c2884..1f85822f 100644 --- a/src/muxer.h +++ b/src/muxer.h @@ -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; diff --git a/src/muxer/muxer_pass.c b/src/muxer/muxer_pass.c index 4914c5f4..abde3689 100644 --- a/src/muxer/muxer_pass.c +++ b/src/muxer/muxer_pass.c @@ -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; diff --git a/src/muxer/muxer_tvh.c b/src/muxer/muxer_tvh.c index 4cd2e126..715328ce 100644 --- a/src/muxer/muxer_tvh.c +++ b/src/muxer/muxer_tvh.c @@ -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; diff --git a/src/muxer/tvh/mkmux.c b/src/muxer/tvh/mkmux.c index 2199676a..a810cb35 100644 --- a/src/muxer/tvh/mkmux.c +++ b/src/muxer/tvh/mkmux.c @@ -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", diff --git a/src/muxer/tvh/mkmux.h b/src/muxer/tvh/mkmux.h index c9a3908f..a107ff40 100644 --- a/src/muxer/tvh/mkmux.h +++ b/src/muxer/tvh/mkmux.h @@ -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, diff --git a/src/utils.c b/src/utils.c index 69f51c28..6eab4ec7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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; diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 8c0de11c..9e369644 100755 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -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)); diff --git a/src/webui/static/app/dvr.js b/src/webui/static/app/dvr.js index 324045d9..63fde3f5 100644 --- a/src/webui/static/app/dvr.js +++ b/src/webui/static/app/dvr.js @@ -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', From c0db0f2bd91a3d6c306d70cf9eeef017c2fbbfb6 Mon Sep 17 00:00:00 2001 From: Ian Date: Fri, 4 Apr 2014 16:46:56 +0100 Subject: [PATCH 3/5] Rework on the addition of user options for file/dir permissions Note that this will not work without the intervention of someone who actually knows what they're doing ;-) --- docs/html/config_dvr.html | 16 ++++---- src/dvr/dvr_db.c | 77 +++++++++++++++++++++++++++++++++---- src/dvr/dvr_rec.c | 10 +---- src/muxer/muxer_pass.c | 11 ++---- src/muxer/tvh/mkmux.c | 9 ++--- src/tvheadend.h | 7 ++++ src/utils.c | 22 +++++++++++ src/webui/extjs.c | 40 +++++++++++++++---- src/webui/static/app/dvr.js | 16 ++++---- 9 files changed, 154 insertions(+), 54 deletions(-) diff --git a/docs/html/config_dvr.html b/docs/html/config_dvr.html index 703ef47a..2cc9836a 100644 --- a/docs/html/config_dvr.html +++ b/docs/html/config_dvr.html @@ -81,12 +81,12 @@
- - - + + +
Common examples:
644 == rw-r--r--
664 == rw-rw-r-- (default)
666 == rw-rw-rw-
0644 == rw-r--r--
0664 == rw-rw-r-- (default)
0666 == rw-rw-rw-
- Note that your default user umask applies, so 666 with umask 002 will produce 664. + Note that your default user umask applies, so 666 with umask 0002 will produce 0664. See also Directory permissions in Subdirectory Options. @@ -113,12 +113,12 @@
- - - + + +
Common examples:
755 == rwxr--r--
775 == rwxrwxr-- (default)
777 == rwxrwxrwx
0755 == rwxr--r--
0775 == rwxrwxr-- (default)
0777 == rwxrwxrwx
- Note that your default user umask applies, so 777 with umask 002 will produce 775. + Note that your default user umask applies, so 0777 with umask 0002 will produce 0775. See also File permissions in Recording File Options. diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 70e3983e..ca43c3c5 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1090,7 +1090,7 @@ dvr_init(void) struct stat st; uint32_t u32; dvr_config_t *cfg; - + dvr_iov_max = sysconf(_SC_IOV_MAX); /* Default settings */ @@ -1133,9 +1133,55 @@ 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")); - htsmsg_get_s32(m, "file-permissions", &cfg->dvr_muxcnf.m_file_permissions); - htsmsg_get_s32(m, "directory-permissions", &cfg->dvr_muxcnf.m_directory_permissions); + +//IH + +/* THIS IS WHERE IT ALL GOES HORRIBLY WRONG + * + * I need to pass tvh_str_set a type char**, but I'm genuinely guessing, and that's not good even if it compiles! + * + */ + + tvhlog(LOG_INFO, "loading", "%s Before load octal file-permission \"%o\"", cfg->dvr_config_name, cfg->dvr_muxcnf.m_file_permissions); + + tvhlog(LOG_INFO, "loading", "calling tvh_str_set"); + +// This is embarassingly poor code. Sorry. + char placeholder[5]; // Yes, I know it should be at the start of the function + char *placeholderptr; // Ditto + + placeholderptr = placeholder; + +// tvhlog(LOG_INFO, "loading", "placeholder \"%s\"", placeholder); +// tvhlog(LOG_INFO, "loading", "placeholderptr \"%i\"", &placeholderptr); +// tvhlog(LOG_INFO, "loading", "placeholder \"%i\"", &placeholder); + + tvh_str_set(&placeholderptr, htsmsg_get_str(m, "file-permissions")); + +// tvhlog(LOG_INFO, "loading", "copying cfg"); + +// Thought: we know that strtol will return a type that can be cast to int +// What if someone manually enters 123456789 in the config file? What then? +// Worth checking if strtol returns > int size then throw error and revert to default as it's clearly invalid? +// Isn't the same true of editing it to be "file perms : abolloxstring" or "boolean-flags : aaargh"? It's their fault... + + cfg->dvr_muxcnf.m_file_permissions = (int)strtol(placeholder,NULL,0); + +// tvhlog(LOG_INFO, "loading", "%s Loaded octal placeholder file-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_file_permissions); +// tvhlog(LOG_INFO, "loading", "%s After load octal file-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_file_permissions); + +// tvhlog(LOG_INFO, "loading", "%s Before load octal dir-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_directory_permissions); + +// THIS WILL BREAK AS WELL. Amateur. + + tvh_str_set(&placeholderptr, htsmsg_get_str(m, "directory-permissions")); + cfg->dvr_muxcnf.m_directory_permissions = (int)strtol(placeholder,NULL,0); + +// tvhlog(LOG_INFO, "loading", "%s Loaded octal directory-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_directory_permissions); +// tvhlog(LOG_INFO, "loading", "%s After load octal directory-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_directory_permissions); + + if(!htsmsg_get_u32(m, "day-dir", &u32) && u32) cfg->dvr_flags |= DVR_DIR_PER_DAY; @@ -1316,9 +1362,9 @@ dvr_config_create(const char *name) cfg->dvr_dup_detect_episode = 1; // detect dup episodes /* 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; + + cfg->dvr_muxcnf.m_file_permissions = 0664; + cfg->dvr_muxcnf.m_directory_permissions = 0775; LIST_INSERT_HEAD(&dvrconfigs, cfg, config_link); @@ -1358,12 +1404,27 @@ static void dvr_save(dvr_config_t *cfg) { htsmsg_t *m = htsmsg_create_map(); + char buffer[5]; //IH - leading zero, three octal digits plus terminating null 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_u32(m, "file-permissions", cfg->dvr_muxcnf.m_file_permissions); - htsmsg_add_u32(m, "directory-permissions", cfg->dvr_muxcnf.m_directory_permissions); + +// tvhlog(LOG_INFO, "saving", "****** To be written: file-permission decimal \"%i\"", cfg->dvr_muxcnf.m_file_permissions); +// tvhlog(LOG_INFO, "saving", "****** equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_file_permissions); +// tvhlog(LOG_INFO, "saving", "****** To be written: directory-permission decimal \"%i\"", cfg->dvr_muxcnf.m_directory_permissions); +// tvhlog(LOG_INFO, "saving", "****** equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_directory_permissions); + + snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_file_permissions); + htsmsg_add_str(m, "file-permissions", buffer); + +// tvhlog(LOG_INFO, "saving", "****** Saved file-permission as string \"%s\"", buffer); + + snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_directory_permissions); + htsmsg_add_str(m, "directory-permissions", buffer); + +// tvhlog(LOG_INFO, "saving", "****** Saved directory-permission as string \"%s\"", buffer); + htsmsg_add_u32(m, "container", cfg->dvr_mc); htsmsg_add_u32(m, "cache", cfg->dvr_muxcnf.m_cache); htsmsg_add_u32(m, "rewrite-pat", diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 2d9938ab..25814e81 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -204,15 +204,7 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) free(title); } -// 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); - -// Create directory path - - if(makedirs(path, octal_perms) != 0) { + if(makedirs(path, cfg->dvr_muxcnf.m_directory_permissions) != 0) { return -1; } diff --git a/src/muxer/muxer_pass.c b/src/muxer/muxer_pass.c index abde3689..b9bc3b5e 100644 --- a/src/muxer/muxer_pass.c +++ b/src/muxer/muxer_pass.c @@ -378,14 +378,9 @@ pass_muxer_open_file(muxer_t *m, const char *filename) int fd; pass_muxer_t *pm = (pass_muxer_t*)m; -// Very ugly hack alert! -// Convert my nasty stored-as-decimal permissions into literal octal equivalent (i.e. 777 => 0777) - - 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); + tvhlog(LOG_DEBUG, "pass", "Creating file \"%s\" with file permissions \"%o\"", filename, pm->m_config.m_file_permissions); + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, pm->m_config.m_file_permissions); if(fd < 0) { pm->pm_error = errno; diff --git a/src/muxer/tvh/mkmux.c b/src/muxer/tvh/mkmux.c index a810cb35..35b03507 100644 --- a/src/muxer/tvh/mkmux.c +++ b/src/muxer/tvh/mkmux.c @@ -1050,13 +1050,10 @@ mk_mux_open_file(mk_mux_t *mkm, const char *filename, int permissions) { int fd; -// Very ugly hack alert! -// Convert my nasty stored-as-decimal permissions into literal octal equivalent (i.e. 777 => 0777) + tvhlog(LOG_DEBUG, "mkv", "Creating file \"%s\" with file permissions \"%o\"", filename, permissions); + + 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", diff --git a/src/tvheadend.h b/src/tvheadend.h index ace8a63e..852ceab9 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -628,6 +628,13 @@ int rmtree ( const char *path ); char *regexp_escape ( const char *str ); +//IH +// Helper functions to convert between string/decimal literals and octal notation (i.e. 777 => 0777 => 777) +// Potentially superseded by other methods + +int decimal_to_octal ( const int decimal ); +int octal_to_decimal ( const int octal ); + #define SKEL_DECLARE(name, type) type *name; #define SKEL_ALLOC(name) do { if (!name) name = calloc(1, sizeof(*name)); } while (0) #define SKEL_USED(name) do { name = NULL; } while (0) diff --git a/src/utils.c b/src/utils.c index 6eab4ec7..f8d45f60 100644 --- a/src/utils.c +++ b/src/utils.c @@ -473,3 +473,25 @@ regexp_escape(const char* str) *b = 0; return tmp; } + +//IH - no longer needed? Delete afterwards as required. I think snprintf and strtol have superseded them, though + +int +decimal_to_octal(const int decimal) +{ + int octal; + + octal = ((decimal / 100) * 64) | ((decimal % 100 / 10) * 8) | (decimal % 10); + + return octal; +} + +int +octal_to_decimal(const int octal) +{ + int decimal; + + decimal = ((octal / 64) * 100) | ((octal % 64 / 8) * 10) | (octal % 8); + + return decimal; +} diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 9e369644..81f60c73 100755 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -970,6 +970,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) int flags = 0; dvr_config_t *cfg; epg_broadcast_t *e; + char buffer[5]; //IH - leading zero, three octal digits plus terminating null if(op == NULL) op = "loadSettings"; @@ -1126,8 +1127,15 @@ 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_u32(r, "filePermissions", cfg->dvr_muxcnf.m_file_permissions); - htsmsg_add_u32(r, "dirPermissions", cfg->dvr_muxcnf.m_directory_permissions); + +//IH Convert integer permissions to an octal-format string and store it in the config file + + snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_file_permissions); + htsmsg_add_str(r, "filePermissions", buffer); + snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_directory_permissions); + htsmsg_add_str(r, "dirPermissions", buffer); +// + htsmsg_add_u32(r, "cache", cfg->dvr_muxcnf.m_cache); htsmsg_add_u32(r, "rewritePAT", !!(cfg->dvr_muxcnf.m_flags & MC_REWRITE_PAT)); @@ -1168,13 +1176,31 @@ 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,atoi(s)); +//IH +// Convert the octal string permissions to integer + +// Theoretical risk of overflowing the (int) cast from long, but this shouldn't ever happen in normal use +// Only if someone's been dicking about with the config by hand +// and then a plague be upon their houses + + if((s = http_arg_get(&hc->hc_req_args, "filePermissions")) != NULL) + dvr_file_permissions_set(cfg,(int)strtol(s,NULL,0)); + +// tvhlog(LOG_INFO, "extjs.c", "****** Testing string \"%s\"", s); +// tvhlog(LOG_INFO, "extjs.c", "****** Testing decimal \"%i\"", (int)strtol(s,NULL,0)); +// tvhlog(LOG_INFO, "extjs.c", "****** Testing octal \"%o\"", (int)strtol(s,NULL,0)); + +// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ - File permissions set to decimal \"%i\"", cfg->dvr_muxcnf.m_file_permissions); +// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ - equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_file_permissions); + if((s = http_arg_get(&hc->hc_req_args, "dirPermissions")) != NULL) - dvr_directory_permissions_set(cfg,atoi(s)); - + dvr_directory_permissions_set(cfg,(int)strtol(s,NULL,0)); + +// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ = Dir permissions set to decimal \"%i\"", cfg->dvr_muxcnf.m_directory_permissions); +// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ = equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_directory_permissions); + + if((s = http_arg_get(&hc->hc_req_args, "cache")) != NULL) dvr_mux_cache_set(cfg,atoi(s)); diff --git a/src/webui/static/app/dvr.js b/src/webui/static/app/dvr.js index 63fde3f5..9b9163bf 100644 --- a/src/webui/static/app/dvr.js +++ b/src/webui/static/app/dvr.js @@ -829,15 +829,15 @@ tvheadend.dvrsettings = function() { name : 'storage' }); -/* NB: recordingPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a decimal number */ +/* NB: recordingPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */ var recordingPermissions = new Ext.form.TextField({ - regex : /^[0-7]{3}$/, + regex : /^[0][0-7]{3}$/, maskRe : /[0-7]/, width : 100, allowBlank : false, - blankText : 'You must provide a value - use octal chmod notation, e.g. 664', - fieldLabel : 'File permissions (octal, e.g. 664)', + blankText : 'You must provide a value - use octal chmod notation, e.g. 0664', + fieldLabel : 'File permissions (octal, e.g. 0664)', name : 'filePermissions' }); @@ -865,15 +865,15 @@ 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 */ +/* NB: directoryPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */ var directoryPermissions = new Ext.form.TextField({ - regex : /^[0-7]{3}$/, + regex : /^[0][0-7]{3}$/, maskRe : /[0-7]/, width : 100, allowBlank : false, - blankText : 'You must provide a value - use octal chmod notation, e.g. 775', - fieldLabel : 'Directory permissions (octal, e.g. 775)', + blankText : 'You must provide a value - use octal chmod notation, e.g. 0775', + fieldLabel : 'Directory permissions (octal, e.g. 0775)', name : 'dirPermissions' }); From 2e66b0e1b7f493ab81e171e566a026b9ba541862 Mon Sep 17 00:00:00 2001 From: Ian Date: Fri, 4 Apr 2014 17:57:49 +0100 Subject: [PATCH 4/5] Final fix for user permissions (file/directory) on recordings. I hope! --- docs/html/config_dvr.html | 8 ++--- src/dvr/dvr_db.c | 66 ++++++--------------------------------- src/tvheadend.h | 7 ----- src/utils.c | 22 ------------- src/webui/extjs.c | 28 ++++------------- 5 files changed, 20 insertions(+), 111 deletions(-) diff --git a/docs/html/config_dvr.html b/docs/html/config_dvr.html index 2cc9836a..68a44ee7 100644 --- a/docs/html/config_dvr.html +++ b/docs/html/config_dvr.html @@ -86,7 +86,7 @@ 0666 == rw-rw-rw- - Note that your default user umask applies, so 666 with umask 0002 will produce 0664. + Note that the applicable umask applies, so 0666 with umask 0022 will produce 0644 (rw-r--r--). See also Directory permissions in Subdirectory Options. @@ -113,12 +113,12 @@
- - + +
Common examples:
0755 == rwxr--r--
0775 == rwxrwxr-- (default)
0755 == rwxr-xr-x
0775 == rwxrwxr-x (default)
0777 == rwxrwxrwx
- Note that your default user umask applies, so 0777 with umask 0002 will produce 0775. + Note that the applicable umask applies, so 0777 with umask 0022 will produce 0755 (rwxr-xr-x). See also File permissions in Recording File Options. diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index ca43c3c5..19e85a20 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1134,54 +1134,15 @@ dvr_init(void) htsmsg_get_u32(m, "retention-days", &cfg->dvr_retention_days); tvh_str_set(&cfg->dvr_storage, htsmsg_get_str(m, "storage")); -//IH +// Convert 0xxx format permission strings to integer for internal use +// Note no checking that strtol won't overflow int - this should never happen with three-digit numbers -/* THIS IS WHERE IT ALL GOES HORRIBLY WRONG - * - * I need to pass tvh_str_set a type char**, but I'm genuinely guessing, and that's not good even if it compiles! - * - */ - - tvhlog(LOG_INFO, "loading", "%s Before load octal file-permission \"%o\"", cfg->dvr_config_name, cfg->dvr_muxcnf.m_file_permissions); - - tvhlog(LOG_INFO, "loading", "calling tvh_str_set"); - -// This is embarassingly poor code. Sorry. - - char placeholder[5]; // Yes, I know it should be at the start of the function - char *placeholderptr; // Ditto - - placeholderptr = placeholder; - -// tvhlog(LOG_INFO, "loading", "placeholder \"%s\"", placeholder); -// tvhlog(LOG_INFO, "loading", "placeholderptr \"%i\"", &placeholderptr); -// tvhlog(LOG_INFO, "loading", "placeholder \"%i\"", &placeholder); - - tvh_str_set(&placeholderptr, htsmsg_get_str(m, "file-permissions")); + if ((s = htsmsg_get_str(m, "file-permissions"))) + cfg->dvr_muxcnf.m_file_permissions = (int)strtol(s,NULL,0); -// tvhlog(LOG_INFO, "loading", "copying cfg"); - -// Thought: we know that strtol will return a type that can be cast to int -// What if someone manually enters 123456789 in the config file? What then? -// Worth checking if strtol returns > int size then throw error and revert to default as it's clearly invalid? -// Isn't the same true of editing it to be "file perms : abolloxstring" or "boolean-flags : aaargh"? It's their fault... + if ((s = htsmsg_get_str(m, "directory-permissions"))) + cfg->dvr_muxcnf.m_directory_permissions = (int)strtol(s,NULL,0); - cfg->dvr_muxcnf.m_file_permissions = (int)strtol(placeholder,NULL,0); - -// tvhlog(LOG_INFO, "loading", "%s Loaded octal placeholder file-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_file_permissions); -// tvhlog(LOG_INFO, "loading", "%s After load octal file-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_file_permissions); - -// tvhlog(LOG_INFO, "loading", "%s Before load octal dir-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_directory_permissions); - -// THIS WILL BREAK AS WELL. Amateur. - - tvh_str_set(&placeholderptr, htsmsg_get_str(m, "directory-permissions")); - cfg->dvr_muxcnf.m_directory_permissions = (int)strtol(placeholder,NULL,0); - -// tvhlog(LOG_INFO, "loading", "%s Loaded octal directory-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_directory_permissions); -// tvhlog(LOG_INFO, "loading", "%s After load octal directory-permission \"%o\"", cfg->dvr_config_name,cfg->dvr_muxcnf.m_directory_permissions); - - if(!htsmsg_get_u32(m, "day-dir", &u32) && u32) cfg->dvr_flags |= DVR_DIR_PER_DAY; @@ -1404,27 +1365,20 @@ static void dvr_save(dvr_config_t *cfg) { htsmsg_t *m = htsmsg_create_map(); - char buffer[5]; //IH - leading zero, three octal digits plus terminating null + char buffer[5]; // Permissions buffer: leading zero, three octal digits plus terminating null 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); -// tvhlog(LOG_INFO, "saving", "****** To be written: file-permission decimal \"%i\"", cfg->dvr_muxcnf.m_file_permissions); -// tvhlog(LOG_INFO, "saving", "****** equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_file_permissions); -// tvhlog(LOG_INFO, "saving", "****** To be written: directory-permission decimal \"%i\"", cfg->dvr_muxcnf.m_directory_permissions); -// tvhlog(LOG_INFO, "saving", "****** equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_directory_permissions); +// Convert permissions to 0xxx octal format and output - snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_file_permissions); + snprintf(buffer,sizeof(buffer),"%04o",cfg->dvr_muxcnf.m_file_permissions); htsmsg_add_str(m, "file-permissions", buffer); -// tvhlog(LOG_INFO, "saving", "****** Saved file-permission as string \"%s\"", buffer); - - snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_directory_permissions); + snprintf(buffer,sizeof(buffer),"%04o",cfg->dvr_muxcnf.m_directory_permissions); htsmsg_add_str(m, "directory-permissions", buffer); -// tvhlog(LOG_INFO, "saving", "****** Saved directory-permission as string \"%s\"", buffer); - htsmsg_add_u32(m, "container", cfg->dvr_mc); htsmsg_add_u32(m, "cache", cfg->dvr_muxcnf.m_cache); htsmsg_add_u32(m, "rewrite-pat", diff --git a/src/tvheadend.h b/src/tvheadend.h index 852ceab9..ace8a63e 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -628,13 +628,6 @@ int rmtree ( const char *path ); char *regexp_escape ( const char *str ); -//IH -// Helper functions to convert between string/decimal literals and octal notation (i.e. 777 => 0777 => 777) -// Potentially superseded by other methods - -int decimal_to_octal ( const int decimal ); -int octal_to_decimal ( const int octal ); - #define SKEL_DECLARE(name, type) type *name; #define SKEL_ALLOC(name) do { if (!name) name = calloc(1, sizeof(*name)); } while (0) #define SKEL_USED(name) do { name = NULL; } while (0) diff --git a/src/utils.c b/src/utils.c index f8d45f60..6eab4ec7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -473,25 +473,3 @@ regexp_escape(const char* str) *b = 0; return tmp; } - -//IH - no longer needed? Delete afterwards as required. I think snprintf and strtol have superseded them, though - -int -decimal_to_octal(const int decimal) -{ - int octal; - - octal = ((decimal / 100) * 64) | ((decimal % 100 / 10) * 8) | (decimal % 10); - - return octal; -} - -int -octal_to_decimal(const int octal) -{ - int decimal; - - decimal = ((octal / 64) * 100) | ((octal % 64 / 8) * 10) | (octal % 8); - - return decimal; -} diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 81f60c73..9ddb549b 100755 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -970,7 +970,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) int flags = 0; dvr_config_t *cfg; epg_broadcast_t *e; - char buffer[5]; //IH - leading zero, three octal digits plus terminating null + char buffer[5]; // Permissions buffer: leading zero, three octal digits plus terminating null if(op == NULL) op = "loadSettings"; @@ -1128,13 +1128,12 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) htsmsg_add_str(r, "storage", cfg->dvr_storage); htsmsg_add_str(r, "container", muxer_container_type2txt(cfg->dvr_mc)); -//IH Convert integer permissions to an octal-format string and store it in the config file +// Convert integer permissions to an octal-format 0xxx string and store it in the config file - snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_file_permissions); + snprintf(buffer,sizeof(buffer),"%04o",cfg->dvr_muxcnf.m_file_permissions); htsmsg_add_str(r, "filePermissions", buffer); - snprintf(buffer,5,"%o",cfg->dvr_muxcnf.m_directory_permissions); + snprintf(buffer,sizeof(buffer),"%04o",cfg->dvr_muxcnf.m_directory_permissions); htsmsg_add_str(r, "dirPermissions", buffer); -// htsmsg_add_u32(r, "cache", cfg->dvr_muxcnf.m_cache); htsmsg_add_u32(r, "rewritePAT", @@ -1177,30 +1176,15 @@ 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); -//IH -// Convert the octal string permissions to integer - -// Theoretical risk of overflowing the (int) cast from long, but this shouldn't ever happen in normal use -// Only if someone's been dicking about with the config by hand -// and then a plague be upon their houses +// Convert 0xxx format permission strings to integer for internal use +// Note no checking that strtol won't overflow int - this should never happen with three-digit numbers if((s = http_arg_get(&hc->hc_req_args, "filePermissions")) != NULL) dvr_file_permissions_set(cfg,(int)strtol(s,NULL,0)); -// tvhlog(LOG_INFO, "extjs.c", "****** Testing string \"%s\"", s); -// tvhlog(LOG_INFO, "extjs.c", "****** Testing decimal \"%i\"", (int)strtol(s,NULL,0)); -// tvhlog(LOG_INFO, "extjs.c", "****** Testing octal \"%o\"", (int)strtol(s,NULL,0)); - -// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ - File permissions set to decimal \"%i\"", cfg->dvr_muxcnf.m_file_permissions); -// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ - equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_file_permissions); - if((s = http_arg_get(&hc->hc_req_args, "dirPermissions")) != NULL) dvr_directory_permissions_set(cfg,(int)strtol(s,NULL,0)); -// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ = Dir permissions set to decimal \"%i\"", cfg->dvr_muxcnf.m_directory_permissions); -// tvhlog(LOG_INFO, "extjs.c", "****** Line 1190+ = equivalent to octal \"%o\"", cfg->dvr_muxcnf.m_directory_permissions); - - if((s = http_arg_get(&hc->hc_req_args, "cache")) != NULL) dvr_mux_cache_set(cfg,atoi(s)); From 5bb95e2698add8c455aa095e2f486d00aa27283c Mon Sep 17 00:00:00 2001 From: Ian Date: Tue, 20 May 2014 21:28:14 +0100 Subject: [PATCH 5/5] Formatting cleanup plus change from tvhlog to tvhtrace as per @perexg comments --- src/dvr/dvr_db.c | 10 ++++++---- src/muxer.h | 8 ++++++-- src/muxer/muxer_pass.c | 2 +- src/muxer/tvh/mkmux.c | 2 +- src/utils.c | 2 +- src/webui/extjs.c | 8 +++++--- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 19e85a20..975ae61f 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1090,7 +1090,7 @@ dvr_init(void) struct stat st; uint32_t u32; dvr_config_t *cfg; - + dvr_iov_max = sysconf(_SC_IOV_MAX); /* Default settings */ @@ -1134,8 +1134,10 @@ dvr_init(void) htsmsg_get_u32(m, "retention-days", &cfg->dvr_retention_days); tvh_str_set(&cfg->dvr_storage, htsmsg_get_str(m, "storage")); -// Convert 0xxx format permission strings to integer for internal use -// Note no checking that strtol won't overflow int - this should never happen with three-digit numbers +/* + * Convert 0xxx format permission strings to integer for internal use + * Note no checking that strtol won't overflow int - this should never happen with three-digit numbers + */ if ((s = htsmsg_get_str(m, "file-permissions"))) cfg->dvr_muxcnf.m_file_permissions = (int)strtol(s,NULL,0); @@ -1371,7 +1373,7 @@ dvr_save(dvr_config_t *cfg) htsmsg_add_str(m, "config_name", cfg->dvr_config_name); htsmsg_add_str(m, "storage", cfg->dvr_storage); -// Convert permissions to 0xxx octal format and output +/* Convert permissions to 0xxx octal format and output */ snprintf(buffer,sizeof(buffer),"%04o",cfg->dvr_muxcnf.m_file_permissions); htsmsg_add_str(m, "file-permissions", buffer); diff --git a/src/muxer.h b/src/muxer.h index 1f85822f..1c0a85ae 100644 --- a/src/muxer.h +++ b/src/muxer.h @@ -47,8 +47,12 @@ typedef enum { typedef struct muxer_config { int m_flags; muxer_cache_type_t m_cache; -// 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 + +/* + * 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; diff --git a/src/muxer/muxer_pass.c b/src/muxer/muxer_pass.c index b9bc3b5e..906099a6 100644 --- a/src/muxer/muxer_pass.c +++ b/src/muxer/muxer_pass.c @@ -378,7 +378,7 @@ pass_muxer_open_file(muxer_t *m, const char *filename) int fd; pass_muxer_t *pm = (pass_muxer_t*)m; - tvhlog(LOG_DEBUG, "pass", "Creating file \"%s\" with file permissions \"%o\"", filename, pm->m_config.m_file_permissions); + tvhtrace("pass", "Creating file \"%s\" with file permissions \"%o\"", filename, pm->m_config.m_file_permissions); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, pm->m_config.m_file_permissions); diff --git a/src/muxer/tvh/mkmux.c b/src/muxer/tvh/mkmux.c index 35b03507..5f366717 100644 --- a/src/muxer/tvh/mkmux.c +++ b/src/muxer/tvh/mkmux.c @@ -1050,7 +1050,7 @@ mk_mux_open_file(mk_mux_t *mkm, const char *filename, int permissions) { int fd; - tvhlog(LOG_DEBUG, "mkv", "Creating file \"%s\" with file permissions \"%o\"", filename, permissions); + tvhtrace("mkv", "Creating file \"%s\" with file permissions \"%o\"", filename, permissions); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, permissions); diff --git a/src/utils.c b/src/utils.c index 6eab4ec7..8ec429da 100644 --- a/src/utils.c +++ b/src/utils.c @@ -397,7 +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); + tvhtrace("settings", "Creating directory \"%s\" with octal permissions \"%o\"", path, mode); } else { err = S_ISDIR(st.st_mode) ? 0 : 1; errno = ENOTDIR; diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 9ddb549b..fa50e6be 100755 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -1128,7 +1128,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) htsmsg_add_str(r, "storage", cfg->dvr_storage); htsmsg_add_str(r, "container", muxer_container_type2txt(cfg->dvr_mc)); -// Convert integer permissions to an octal-format 0xxx string and store it in the config file +/* Convert integer permissions to an octal-format 0xxx string and store it in the config file */ snprintf(buffer,sizeof(buffer),"%04o",cfg->dvr_muxcnf.m_file_permissions); htsmsg_add_str(r, "filePermissions", buffer); @@ -1176,8 +1176,10 @@ 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); -// Convert 0xxx format permission strings to integer for internal use -// Note no checking that strtol won't overflow int - this should never happen with three-digit numbers +/* + * Convert 0xxx format permission strings to integer for internal use + * Note no checking that strtol won't overflow int - this should never happen with three-digit numbers + */ if((s = http_arg_get(&hc->hc_req_args, "filePermissions")) != NULL) dvr_file_permissions_set(cfg,(int)strtol(s,NULL,0));