diff --git a/ChangeLog b/ChangeLog index d314a4dd65..56f615d2d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2002-04-12 Thomas Vander Stichele + + * gst/gst*.[ch]: commited GUAD3C code review comments (marked CR1) + + * gst/gstregistry.[ch]: added to handle registry stuff + gst/gst.c: changed to use new --gst-registry option + tools/gst-register.c: use new registry functions + for more info, check docs/random/thomasvs/registry + 2002-03-01 Michael Meeks * docs/manual/Makefile.am: use $(wildcard) instead of strange shell stuff. diff --git a/README b/README index 9e760c4fa1..99fd6aceb4 100644 --- a/README +++ b/README @@ -22,3 +22,11 @@ ATM, most of us have at least these versions : autogen.sh will check for these versions and complain if you don't have them. + +Check autogen.sh options by running autogen.sh --help + +autogen.sh can pass on arguments to configure - you just need to separate them +from autogen.sh with -- between the two. +prefix has been added to autogen.sh but will be passed on to configure because +some build scripts like that. + diff --git a/docs/random/thomasvs/registry b/docs/random/thomasvs/registry index dde3dbea4c..5287133767 100644 --- a/docs/random/thomasvs/registry +++ b/docs/random/thomasvs/registry @@ -31,8 +31,6 @@ Reviewing the registry (thomasvs, April 8 2002) - use gst_registry_read_get to get a GstRegistryRead struct back listing the path of global and local file to read -* QUESTIONS - - maybe it's better to try the global registry first (if unspecified), - and see if you have write permissions ? Because if you do, you might - as well do it there - the system gave you the permission. - useful for doing garnome installs as a user +* gst-register signals it's going to write to the registry (causing it to + be unlinked before the read in post_init ()) by setting a global variable, + _gst_init_write_registry diff --git a/gst/Makefile.am b/gst/Makefile.am index 31c7a88f91..3ddcf3cdad 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -77,6 +77,7 @@ libgstreamer_la_SOURCES = \ gsttype.c \ $(GST_TYPEFIND_SRC) \ gstutils.c \ + gstregistry.c \ gsttimecache.c \ $(GST_PARSE_SRC) \ $(GSTARCH_SRCS) \ @@ -136,6 +137,7 @@ libgstreamerinclude_HEADERS = \ gsttype.h \ gsttypefind.h \ gstutils.h \ + gstregistry.h \ gsttimecache.h \ gstparse.h \ gstversion.h \ diff --git a/gst/gst.c b/gst/gst.c index 138efa557a..42bbab1c82 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -40,7 +40,6 @@ gchar *_gst_progname; extern gint _gst_trace_on; extern gboolean _gst_plugin_spew; - static void load_plugin_func (gpointer data, gpointer user_data); static void init_popt_callback (poptContext context, enum poptCallbackReason reason, const struct poptOption *option, const char *arg, void *data); @@ -70,7 +69,8 @@ enum { ARG_PLUGIN_SPEW, ARG_PLUGIN_PATH, ARG_PLUGIN_LOAD, - ARG_SCHEDULER + ARG_SCHEDULER, + ARG_REGISTRY }; #ifndef NUL @@ -88,6 +88,7 @@ static const struct poptOption options[] = { {"gst-plugin-path", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_PATH, "'" G_SEARCHPATH_SEPARATOR_S "'--separated path list for loading plugins", "PATHS"}, {"gst-plugin-load", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_LOAD, "comma-separated list of plugins to preload in addition to the list stored in env variable GST_PLUGIN_PATH", "PLUGINS"}, {"gst-scheduler", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_SCHEDULER, "scheduler to use ('basic' is the default)", "SCHEDULER"}, + {"gst-registry", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_REGISTRY, "registry to use" , "REGISTRY"}, POPT_TABLEEND }; @@ -339,6 +340,7 @@ gst_mask_help (void) for (i = 0; ival); break; diff --git a/gst/gst.h b/gst/gst.h index 85d1c60a80..96607cda41 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -52,6 +52,7 @@ #include #include +#include #include #ifdef __cplusplus diff --git a/gst/gstplugin.c b/gst/gstplugin.c index 6d5c59a704..761d9239fa 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -28,6 +28,7 @@ #include "gst_private.h" #include "gstplugin.h" #include "gstversion.h" +#include "gstregistry.h" #include "config.h" static GModule *main_module; @@ -49,6 +50,8 @@ gboolean _gst_plugin_spew = FALSE; /* whether or not to warn if registry needs rebuild (gst-register sets * this to false.) */ gboolean _gst_warn_old_registry = TRUE; +/* whether or not the main app will be writing to the registry */ +gboolean _gst_init_registry_write = FALSE; #ifndef GST_DISABLE_REGISTRY static gboolean plugin_times_older_than (time_t regtime); @@ -57,13 +60,14 @@ static time_t get_time (const char * path); static void gst_plugin_register_statics (GModule *module); static GstPlugin* gst_plugin_register_func (GstPluginDesc *desc, GstPlugin *plugin, GModule *module); - void _gst_plugin_initialize (void) { GList *gst_plugin_default_paths = NULL; struct stat stat_buf; #ifndef GST_DISABLE_REGISTRY + GstRegistryRead *gst_reg; + gchar *gst_registry; xmlDocPtr doc = NULL; #endif @@ -86,8 +90,27 @@ _gst_plugin_initialize (void) #endif /* PLUGINS_USE_BUILDDIR */ #ifndef GST_DISABLE_REGISTRY - if (stat (GST_CONFIG_DIR"/reg.xml", &stat_buf) == 0) - doc = xmlParseFile (GST_CONFIG_DIR"/reg.xml"); + /* FIXME: + * we want to check both the global and the local registry here + * at first, we check if there is a local one, and if there is only use + * that one. + * Later, we would like to read the global one first, then have each + * plugin also in the local one override the global one. + */ + + gst_reg = gst_registry_read_get (); + if (gst_reg->local_reg) + gst_registry = gst_reg->local_reg; + else + gst_registry = gst_reg->global_reg; + + if (_gst_init_registry_write) + { + /* delete it before writing */ + unlink (gst_registry); + } + if (stat (gst_registry, &stat_buf) == 0) + doc = xmlParseFile (gst_registry); else doc = NULL; @@ -95,9 +118,10 @@ _gst_plugin_initialize (void) !doc->xmlRootNode || doc->xmlRootNode->name == 0 || strcmp (doc->xmlRootNode->name, "GST-PluginRegistry") || - !plugin_times_older_than(get_time(GST_CONFIG_DIR"/reg.xml"))) + !plugin_times_older_than(get_time(gst_registry))) { - if (_gst_warn_old_registry) + if (_gst_warn_old_registry && + !plugin_times_older_than(get_time(gst_registry))) g_warning ("gstplugin: registry needs rebuild: run gst-register\n"); _gst_plugin_paths = g_list_concat (_gst_plugin_paths, gst_plugin_default_paths); #ifdef PLUGINS_USE_BUILDDIR @@ -269,7 +293,7 @@ gst_plugin_load_recurse (gchar *directory, gchar *name) /** * gst_plugin_load_all: * - * Load all plugins in the path. + * Load all plugins in the path (in the global GList* _gst_plugin_paths). */ void gst_plugin_load_all (void) @@ -277,6 +301,7 @@ gst_plugin_load_all (void) GList *path; path = _gst_plugin_paths; + if (path == NULL) { g_warning ("gst_plugin_load_all: path is NULL !"); } while (path != NULL) { GST_DEBUG (GST_CAT_PLUGIN_LOADING,"loading plugins from %s",(gchar *)path->data); gst_plugin_load_recurse(path->data,NULL); @@ -718,6 +743,8 @@ gst_plugin_find_feature (const gchar *name, GType type) * @feature: feature to add * * Add feature to the list of those provided by the plugin. + * There is a separate namespace for each plugin feature type. + * See #gst_plugin_get_feature_list */ void gst_plugin_add_feature (GstPlugin *plugin, GstPluginFeature *feature) @@ -872,7 +899,7 @@ gst_plugin_load_thyself (xmlNodePtr parent) kinderen = kinderen->next; } - GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d features ", featurecount); + GST_INFO (GST_CAT_PLUGIN_LOADING, " added %d features ", featurecount); } #endif /* GST_DISABLE_REGISTRY */ diff --git a/gst/gstregistry.c b/gst/gstregistry.c new file mode 100644 index 0000000000..0b13f7fa9f --- /dev/null +++ b/gst/gstregistry.c @@ -0,0 +1,130 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstregistry.c: handle registry + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gstinfo.h" +#include "gstregistry.h" + +static gchar *gst_registry_option = NULL; + +/* save the registry specified as an option */ +void +gst_registry_option_set (const gchar *registry) +{ + gst_registry_option = g_strdup (registry); + return; +} + +/* decide if we're going to use the global registry or not + * - if root, use global + * - if not root : + * - if user can write to global, use global + * - else use local + */ +gboolean +gst_registry_use_global (void) +{ + //struct stat reg_stat; + FILE *reg; + + if (getuid () == 0) return TRUE; /* root always uses global */ + + /* check if we can write to the global registry somehow */ + reg = fopen (GLOBAL_REGISTRY_FILE, "a"); + if (reg == NULL) { return FALSE; } + else + { + /* we can write to it, do so for kicks */ + fclose (reg); + } + + /* we can write to it, so now see if we can write in the dir as well */ + if (access (GLOBAL_REGISTRY_DIR, W_OK) == 0) return TRUE; + + return FALSE; +} + +/* get the data that tells us where we can write the registry + * Allocate, fill in the GstRegistryWrite struct according to + * current situation, and return it */ +GstRegistryWrite * +gst_registry_write_get () +{ + GstRegistryWrite *gst_reg = g_malloc (sizeof (GstRegistryWrite)); + + /* if a registry is specified on command line, use that one */ + if (gst_registry_option) + { + /* FIXME: maybe parse the dir from file ? */ + gst_reg->dir = NULL; + gst_reg->file = gst_registry_option; + /* we cannot use the temp dir since the move needs to be on same device */ + gst_reg->tmp_file = g_strdup_printf ("%s.tmp", gst_registry_option); + } + else + { + if (gst_registry_use_global ()) + { + gst_reg->dir = g_strdup (GLOBAL_REGISTRY_DIR); + gst_reg->file = g_strdup (GLOBAL_REGISTRY_FILE); + gst_reg->tmp_file = g_strdup (GLOBAL_REGISTRY_FILE_TMP); + } + else + { + gchar *homedir = (gchar *) g_get_home_dir (); + + gst_reg->dir = g_strjoin ("/", homedir, LOCAL_REGISTRY_DIR, NULL); + gst_reg->file = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL); + gst_reg->tmp_file = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE_TMP, NULL); + } + } + return gst_reg; +} + +/* fill in the GstRegistryRead struct according to current situation */ +GstRegistryRead * +gst_registry_read_get () +{ + GstRegistryRead *gst_reg = g_malloc (sizeof (GstRegistryRead)); + + /* if a registry is specified on command line, use that one */ + if (gst_registry_option) + { + /* FIXME: maybe parse the dir from file ? */ + gst_reg->local_reg = NULL; + gst_reg->global_reg = gst_registry_option; + } + else + { + gchar *homedir = (gchar *) g_get_home_dir (); + gst_reg->local_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL); + gst_reg->global_reg = g_strdup (GLOBAL_REGISTRY_FILE); + } + return gst_reg; +} diff --git a/gst/gstregistry.h b/gst/gstregistry.h new file mode 100644 index 0000000000..f8fcccaf29 --- /dev/null +++ b/gst/gstregistry.h @@ -0,0 +1,69 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstregistry.h: Header for registry handling + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_REGISTRY_H__ +#define __GST_REGISTRY_H__ + +#define GLOBAL_REGISTRY_DIR GST_CONFIG_DIR +#define GLOBAL_REGISTRY_FILE GLOBAL_REGISTRY_DIR"/reg.xml" +#define GLOBAL_REGISTRY_FILE_TMP GLOBAL_REGISTRY_DIR"/.reg.xml.tmp" + +#define LOCAL_REGISTRY_DIR ".gstreamer" +#define LOCAL_REGISTRY_FILE LOCAL_REGISTRY_DIR"/reg.xml" +#define LOCAL_REGISTRY_FILE_TMP LOCAL_REGISTRY_DIR"/.reg.xml.tmp" + +#define REGISTRY_DIR_PERMS (S_ISGID | \ + S_IRUSR | S_IWUSR | S_IXUSR | \ + S_IRGRP | S_IXGRP | \ + S_IROTH | S_IXOTH) +#define REGISTRY_TMPFILE_PERMS (S_IRUSR | S_IWUSR) +#define REGISTRY_FILE_PERMS (S_IRUSR | S_IWUSR | \ + S_IRGRP | S_IWGRP | \ + S_IROTH | S_IWOTH) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _GstRegistryWrite GstRegistryWrite; +struct _GstRegistryWrite { + gchar *dir; + gchar *file; + gchar *tmp_file; +}; + +typedef struct _GstRegistryRead GstRegistryRead; +struct _GstRegistryRead { + gchar *global_reg; + gchar *local_reg; +}; + +GstRegistryWrite *gst_registry_write_get (void); +GstRegistryRead *gst_registry_read_get (void); +void gst_registry_option_set (const gchar *registry); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_REGISTRY_H__ */ diff --git a/tools/gst-register.c b/tools/gst-register.c index 56bb937d28..435b1149b1 100644 --- a/tools/gst-register.c +++ b/tools/gst-register.c @@ -35,22 +35,9 @@ #include "config.h" -#define GLOBAL_REGISTRY_DIR GST_CONFIG_DIR -#define GLOBAL_REGISTRY_FILE GLOBAL_REGISTRY_DIR"/reg.xml" -#define GLOBAL_REGISTRY_FILE_TMP GLOBAL_REGISTRY_DIR"/.reg.xml.tmp" - -#define REGISTRY_DIR_PERMS (S_ISGID | \ - S_IRUSR | S_IWUSR | S_IXUSR | \ - S_IRGRP | S_IXGRP | \ - S_IROTH | S_IXOTH) -#define REGISTRY_TMPFILE_PERMS (S_IRUSR | S_IWUSR) -#define REGISTRY_FILE_PERMS (S_IRUSR | S_IWUSR | \ - S_IRGRP | S_IWGRP | \ - S_IROTH | S_IWOTH) - - extern gboolean _gst_plugin_spew; extern gboolean _gst_warn_old_registry; +extern gboolean _gst_init_registry_write; /* we ask post_init to be delayed */ static void error_perm() { g_print("\n(%s)\n" @@ -184,6 +171,7 @@ int main(int argc,char *argv[]) { xmlDocPtr doc; xmlNodePtr node; + GstRegistryWrite *gst_reg; /* Mode of the file we're saving the repository to; */ mode_t newmode; @@ -195,35 +183,65 @@ int main(int argc,char *argv[]) newmode = REGISTRY_FILE_PERMS & ~ theumask; } - /* remove the old registry file first - If this fails, we simply ignore it since we'll overwrite it later - anyway. */ - unlink(GLOBAL_REGISTRY_FILE); - /* Init gst */ _gst_plugin_spew = TRUE; _gst_warn_old_registry = FALSE; gst_info_enable_category(GST_CAT_PLUGIN_LOADING); + _gst_init_registry_write = TRUE; /* signal that we're writing registry */ gst_init(&argc,&argv); + /* remove the old registry file first + * if a local is returned, then do that, else remove the global one + * If this fails, we simply ignore it since we'll overwrite it later + * anyway */ + gst_reg = gst_registry_write_get (); + unlink (gst_reg->file); + + GST_INFO (GST_CAT_PLUGIN_LOADING, " Writing to registry %s", gst_reg->file); + /* Check args */ if (argc != 1) usage(argv[0]); - /* Check that directory for config exists */ - check_dir(GLOBAL_REGISTRY_DIR); - /* Read the plugins */ doc = xmlNewDoc("1.0"); node = xmlNewDocNode(doc, NULL, "GST-PluginRegistry", NULL); xmlDocSetRootElement (doc, node); gst_plugin_save_thyself(doc->xmlRootNode); - + + if (gst_reg->dir) + check_dir(gst_reg->dir); + /* Save the registry to a tmp file. */ - save_registry(GLOBAL_REGISTRY_FILE_TMP, &doc); + save_registry(gst_reg->tmp_file, &doc); /* Make the tmp file live. */ - move_file(GLOBAL_REGISTRY_FILE_TMP, GLOBAL_REGISTRY_FILE, &newmode); + move_file(gst_reg->tmp_file, gst_reg->file, &newmode); +#ifdef THOMAS + } + else + { + gchar *homedir; + gchar *reg_dir, *reg_file_tmp, *reg_file; + homedir = (gchar *) g_get_home_dir (); + reg_dir = g_strjoin ("/", homedir, LOCAL_REGISTRY_DIR, NULL); + reg_file_tmp = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE_TMP, NULL); + reg_file = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL); + + /* try to make the dir; we'll find out if it fails anyway */ + mkdir(reg_dir, S_IRWXU); + g_free(reg_dir); + + /* Save the registry to a tmp file. */ + save_registry(reg_file_tmp, &doc); + + /* Make the tmp file live. */ + move_file(reg_file_tmp, reg_file, &newmode); + g_free(reg_file_tmp); + g_free(reg_file); + } +#endif + g_free (gst_reg); return(0); }