Further refactor of dvr config page and options; addition of user options for file and directory permissions throughout.

This commit is contained in:
Ian 2014-03-30 11:33:34 +01:00
parent 401608cc69
commit 61e6d67528
12 changed files with 84 additions and 74 deletions

View 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.
@ -105,7 +107,7 @@
<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">
@ -116,7 +118,9 @@
<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)

View 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);

View 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)

View file

@ -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\", "

View 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;

View 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;

View 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;

View 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",

View 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,

View 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;

View file

@ -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));

View 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',