queue2: add temp-template property

Add a new temp-template property so that queue2 can securely allocate a
temporary filename. Deprecate the temp-location property for setting the
location but still use it to notify the allocated temp file.
This commit is contained in:
Wim Taymans 2009-07-10 19:49:46 +01:00 committed by Sebastian Dröge
parent 4843c0947b
commit affe0aef6f

View file

@ -41,11 +41,17 @@
* The default queue size limits are 100 buffers, 2MB of data, or * The default queue size limits are 100 buffers, 2MB of data, or
* two seconds worth of data, whichever is reached first. * two seconds worth of data, whichever is reached first.
* *
* If you set temp-location, the element will buffer data on the file * If you set temp-tmpl to a value such as /tmp/gstreamer-XXXXXX, the element
* specified by it. By using this, it will buffer the entire * will allocate a random free filename and buffer data in the file.
* stream data on the file independently of the queue size limits, they * By using this, it will buffer the entire stream data on the file independently
* will only be used for buffering statistics. * of the queue size limits, they will only be used for buffering statistics.
* *
* Since 0.10.24, setting the temp-location property with a filename is deprecated
* because it's impossible to securely open a temporary file in this way. The
* property will still be used to notify the application of the allocated
* filename, though.
*
* Last reviewed on 2009-07-10 (0.10.24)
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -63,6 +69,8 @@
#define lseek _lseeki64 #define lseek _lseeki64
#undef off_t #undef off_t
#define off_t guint64 #define off_t guint64
#else
#include <unistd.h>
#endif #endif
static const GstElementDetails gst_queue_details = GST_ELEMENT_DETAILS ("Queue", static const GstElementDetails gst_queue_details = GST_ELEMENT_DETAILS ("Queue",
@ -101,7 +109,7 @@ enum
/* other defines */ /* other defines */
#define DEFAULT_BUFFER_SIZE 4096 #define DEFAULT_BUFFER_SIZE 4096
#define QUEUE_IS_USING_TEMP_FILE(queue) (queue->temp_location != NULL) #define QUEUE_IS_USING_TEMP_FILE(queue) ((queue)->temp_location_set || (queue)->temp_template != NULL)
enum enum
{ {
@ -116,6 +124,7 @@ enum
PROP_USE_RATE_ESTIMATE, PROP_USE_RATE_ESTIMATE,
PROP_LOW_PERCENT, PROP_LOW_PERCENT,
PROP_HIGH_PERCENT, PROP_HIGH_PERCENT,
PROP_TEMP_TEMPLATE,
PROP_TEMP_LOCATION PROP_TEMP_LOCATION
}; };
@ -204,6 +213,8 @@ struct _GstQueue
GCond *item_del; /* signals space now available for writing */ GCond *item_del; /* signals space now available for writing */
/* temp location stuff */ /* temp location stuff */
gchar *temp_template;
gboolean temp_location_set;
gchar *temp_location; gchar *temp_location;
FILE *temp_file; FILE *temp_file;
guint64 writing_pos; guint64 writing_pos;
@ -415,9 +426,16 @@ gst_queue_class_init (GstQueueClass * klass)
"High threshold for buffering to finish", 0, 100, "High threshold for buffering to finish", 0, 100,
DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_TEMP_TEMPLATE,
g_param_spec_string ("temp-template", "Temporary File Template",
"File template to store temporary files in, should contain directory "
"and XXXXXX. (NULL == disabled)",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION, g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION,
g_param_spec_string ("temp-location", "Temporary File Location", g_param_spec_string ("temp-location", "Temporary File Location",
"Location of a temporary file to store data in", "Location to store temporary files in (Deprecated: Only read this "
"property, use temp-tmpl to configure the name template)",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_add_pad_template (gstelement_class, gst_element_class_add_pad_template (gstelement_class,
@ -495,8 +513,9 @@ gst_queue_init (GstQueue * queue, GstQueueClass * g_class)
queue->queue = g_queue_new (); queue->queue = g_queue_new ();
/* tempfile related */ /* tempfile related */
queue->temp_template = NULL;
queue->temp_location = NULL; queue->temp_location = NULL;
queue->temp_file = NULL; queue->temp_location_set = FALSE;
GST_DEBUG_OBJECT (queue, GST_DEBUG_OBJECT (queue,
"initialized queue's not_empty & not_full conditions"); "initialized queue's not_empty & not_full conditions");
@ -524,8 +543,8 @@ gst_queue_finalize (GObject * object)
g_timer_destroy (queue->out_timer); g_timer_destroy (queue->out_timer);
/* temp_file path cleanup */ /* temp_file path cleanup */
if (queue->temp_location != NULL) g_free (queue->temp_template);
g_free (queue->temp_location); g_free (queue->temp_location);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -981,17 +1000,45 @@ gst_queue_read_item_from_file (GstQueue * queue)
static gboolean static gboolean
gst_queue_open_temp_location_file (GstQueue * queue) gst_queue_open_temp_location_file (GstQueue * queue)
{ {
/* nothing to do */ gint fd = -1;
if (queue->temp_location == NULL) gchar *name = NULL;
goto no_filename;
GST_DEBUG_OBJECT (queue, "opening temp file %s", queue->temp_location); GST_DEBUG_OBJECT (queue, "opening temp file %s", queue->temp_template);
/* open the file for update/writing */ /* we have two cases:
queue->temp_file = g_fopen (queue->temp_location, "wb+"); * - temp_location was set to something !NULL (Deprecated). in this case we
/* error creating file */ * open the specified filename.
if (queue->temp_file == NULL) * - temp_template was set, allocate a filename and open that filename
goto open_failed; */
if (!queue->temp_location_set) {
/* nothing to do */
if (queue->temp_template == NULL)
goto no_directory;
/* make copy of the template, we don't want to change this */
name = g_strdup (queue->temp_template);
fd = g_mkstemp (name);
if (fd == -1)
goto mkstemp_failed;
/* open the file for update/writing */
queue->temp_file = fdopen (fd, "wb+");
/* error creating file */
if (queue->temp_file == NULL)
goto open_failed;
g_free (queue->temp_location);
queue->temp_location = name;
g_object_notify (G_OBJECT (queue), "temp-location");
} else {
/* open the file for update/writing, this is deprecated but we still need to
* support it for API/ABI compatibility */
queue->temp_file = g_fopen (queue->temp_location, "wb+");
/* error creating file */
if (queue->temp_file == NULL)
goto open_failed;
}
queue->writing_pos = 0; queue->writing_pos = 0;
queue->reading_pos = 0; queue->reading_pos = 0;
@ -999,17 +1046,27 @@ gst_queue_open_temp_location_file (GstQueue * queue)
return TRUE; return TRUE;
/* ERRORS */ /* ERRORS */
no_filename: no_directory:
{ {
GST_ELEMENT_ERROR (queue, RESOURCE, NOT_FOUND, GST_ELEMENT_ERROR (queue, RESOURCE, NOT_FOUND,
(_("No file name specified.")), (NULL)); (_("No Temp directory specified.")), (NULL));
return FALSE;
}
mkstemp_failed:
{
GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ,
(_("Could not create temp file \"%s\"."), queue->temp_template),
GST_ERROR_SYSTEM);
g_free (name);
return FALSE; return FALSE;
} }
open_failed: open_failed:
{ {
GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ, GST_ELEMENT_ERROR (queue, RESOURCE, OPEN_READ,
(_("Could not open file \"%s\" for reading."), queue->temp_location), (_("Could not open file \"%s\" for reading."), name), GST_ERROR_SYSTEM);
GST_ERROR_SYSTEM); g_free (name);
if (fd != -1)
close (fd);
return FALSE; return FALSE;
} }
} }
@ -1942,7 +1999,7 @@ gst_queue_change_state (GstElement * element, GstStateChange transition)
g_cond_signal (queue->item_add); g_cond_signal (queue->item_add);
static void static void
gst_queue_set_temp_location (GstQueue * queue, const gchar * location) gst_queue_set_temp_template (GstQueue * queue, const gchar * template)
{ {
GstState state; GstState state;
@ -1954,15 +2011,15 @@ gst_queue_set_temp_location (GstQueue * queue, const gchar * location)
GST_OBJECT_UNLOCK (queue); GST_OBJECT_UNLOCK (queue);
/* set new location */ /* set new location */
g_free (queue->temp_location); g_free (queue->temp_template);
queue->temp_location = g_strdup (location); queue->temp_template = g_strdup (template);
return; return;
/* ERROR */ /* ERROR */
wrong_state: wrong_state:
{ {
GST_WARNING_OBJECT (queue, "setting temp-location in wrong state"); GST_WARNING_OBJECT (queue, "setting temp-template property in wrong state");
GST_OBJECT_UNLOCK (queue); GST_OBJECT_UNLOCK (queue);
} }
} }
@ -2005,8 +2062,15 @@ gst_queue_set_property (GObject * object,
case PROP_HIGH_PERCENT: case PROP_HIGH_PERCENT:
queue->high_percent = g_value_get_int (value); queue->high_percent = g_value_get_int (value);
break; break;
case PROP_TEMP_TEMPLATE:
gst_queue_set_temp_template (queue, g_value_get_string (value));
break;
case PROP_TEMP_LOCATION: case PROP_TEMP_LOCATION:
gst_queue_set_temp_location (queue, g_value_get_string (value)); g_free (queue->temp_location);
queue->temp_location = g_value_dup_string (value);
/* you can set the property back to NULL to make it use the temp-tmpl
* property. */
queue->temp_location_set = queue->temp_location != NULL;
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -2055,6 +2119,9 @@ gst_queue_get_property (GObject * object,
case PROP_HIGH_PERCENT: case PROP_HIGH_PERCENT:
g_value_set_int (value, queue->high_percent); g_value_set_int (value, queue->high_percent);
break; break;
case PROP_TEMP_TEMPLATE:
g_value_set_string (value, queue->temp_template);
break;
case PROP_TEMP_LOCATION: case PROP_TEMP_LOCATION:
g_value_set_string (value, queue->temp_location); g_value_set_string (value, queue->temp_location);
break; break;