gst-register.c 6.76 KB
Newer Older
1 2 3 4
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wtay@chello.be>
 *
5
 * gst-register.c: Plugin subsystem for loading elements, types, and libs
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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.
 */

23 24
#include <gst/gst.h>

25 26 27
#include <stdlib.h>
#include <stdio.h>

28 29 30 31 32 33 34 35
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#include <string.h>
#include <errno.h>

36 37
#include "config.h"

38
extern gboolean _gst_plugin_spew;
39
extern gboolean _gst_warn_old_registry;
40
extern gboolean _gst_init_registry_write; /* we ask post_init to be delayed */
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
static void error_perm() {
    g_print("\n(%s)\n"
	    "Do you have the appropriate permissions?\n"
	    "You may need to be root to run this command.\n\n",
	    strerror(errno));
    exit(1);
}

static void usage(const char *progname) {
    g_print("usage: %s\n", progname);
    g_print("Builds the plugin registry for gstreamer.\n");
    g_print("This command will usually require superuser privileges.\n\n");
    exit(0);
}

static int is_file(const char * filename) {
  struct stat statbuf;
  if(stat(filename, &statbuf)) return 0;
  return S_ISREG(statbuf.st_mode);
}

static int is_dir(const char * filename) {
  struct stat statbuf;
  if(stat(filename, &statbuf)) return 0;
  return S_ISDIR(statbuf.st_mode);
}

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
static void set_filemode(const char * filename, mode_t mode) {
    if(chmod(filename, mode)) {
	g_print("Cannot set file permissions on `%s' to %o", filename, mode);
	error_perm();
    }
}

static int get_filemode(const char * filename, mode_t * mode) {
    struct stat statbuf;
    if(stat(filename, &statbuf)) return 0;
    *mode = statbuf.st_mode & ~ S_IFMT;
    return 1;
}

static void move_file(const char * nameold,
		      const char * namenew,
		      mode_t * newmode) {
86 87 88 89 90
    if (!is_file(nameold)) {
	g_print("Temporary `%s' is not a file", nameold);
	error_perm();
    }
    if (is_dir(namenew)) {
91
	g_print("Destination path `%s' for registry file is a directory\n", namenew);
92 93 94 95 96 97 98
	g_print("Please remove, or reconfigure GStreamer\n\n");
	exit(1);
    }
    if (rename(nameold, namenew)) {
	g_print("Cannot move `%s' to `%s'", nameold, namenew);
	error_perm();
    }
99
    /* set mode again, to make this public */
100
    set_filemode(namenew, *newmode);
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115
static void make_dir(const char * dirname) {
    mode_t mode = REGISTRY_DIR_PERMS;
    if(mkdir(dirname, mode)) {
	g_print("Cannot create GStreamer registry directory `%s'", dirname);
	error_perm();
    }

    if(chmod(dirname, mode)) {
	g_print("Cannot set permissions on GStreamer registry directory `%s' to %o", dirname, mode);
	error_perm();
    }

    return;
116 117
}

118
static void check_dir(const char * dirname) {
119
    if (!is_dir(dirname)) {
120
	make_dir(dirname);
121 122 123
    }
}

124 125 126
static void save_registry(const char *destfile,
			  xmlDocPtr * doc) {
    mode_t tmpmode = REGISTRY_TMPFILE_PERMS;
127 128
#if 0
    FILE *fp;
129
    int fd;
130

131 132
    fd = open(destfile, O_CREAT | O_TRUNC | O_WRONLY, tmpmode);
    if (fd == -1) {
133 134 135
	g_print("Cannot open `%s' to save new registry to.", destfile);
	error_perm();
    }
136 137 138 139 140
    fp = fdopen (fd, "wb");
    if (!fp) {
	g_print("Cannot fopen `%s' to save new registry to.", destfile);
	error_perm();
    }
141
    /* set mode to make this private */
142
    set_filemode(destfile, tmpmode);
143

144 145 146 147 148
    /*  FIXME: no way to check success of xmlDocDump, which is why
       this piece of code is ifdefed out.
       The version of libxml currently (Jan 2001) in their CVS tree fixes
       this problem. */

Richard Boulton's avatar
Richard Boulton committed
149
    xmlDocDump(fp, *doc);
150 151 152 153 154

    if (!fclose(fp)) {
	g_print("Cannot close `%s' having saved new registry.", destfile);
	error_perm();
    }
155

156 157 158 159
#else
#ifdef HAVE_LIBXML2
    /* indent the document */
    if (xmlSaveFormatFile(destfile, *doc, 1) <= 0) {
160
#else
Richard Boulton's avatar
Richard Boulton committed
161
    if (xmlSaveFile(destfile, *doc) <= 0) {
162
#endif
163 164 165
	g_print("Cannot save new registry to `%s'", destfile);
	error_perm();
    }
166
    set_filemode(destfile, tmpmode);
167 168 169
#endif
}

170 171
int main(int argc,char *argv[]) 
{
172
    xmlDocPtr doc;
Wim Taymans's avatar
Wim Taymans committed
173
    xmlNodePtr node;
174
    GstRegistryWrite *gst_reg;
175

176
    /* Mode of the file we're saving the repository to; */
177 178
    mode_t newmode;

179
    /* Get mode of old repository, or a default. */
180 181 182 183 184 185
    if (!get_filemode(GLOBAL_REGISTRY_FILE, &newmode)) {
	mode_t theumask = umask(0);
	umask(theumask);
	newmode = REGISTRY_FILE_PERMS & ~ theumask;
    }

Wim Taymans's avatar
Wim Taymans committed
186
    /* Init gst */
187
    _gst_plugin_spew = TRUE;
188
    _gst_warn_old_registry = FALSE;
189
    gst_info_enable_category(GST_CAT_PLUGIN_LOADING);
190
    _gst_init_registry_write = TRUE; /* signal that we're writing registry */
191
    gst_init(&argc,&argv);
192

193 194 195 196 197 198 199 200 201
    /* 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);

Wim Taymans's avatar
Wim Taymans committed
202
    /* Check args */
203 204
    if (argc != 1) usage(argv[0]);

205
    /* Read the plugins */
206
    doc = xmlNewDoc("1.0");
Wim Taymans's avatar
Wim Taymans committed
207 208
    node = xmlNewDocNode(doc, NULL, "GST-PluginRegistry", NULL);
    xmlDocSetRootElement (doc, node);
Richard Boulton's avatar
Richard Boulton committed
209
    gst_plugin_save_thyself(doc->xmlRootNode);
210 211 212 213
    
    if (gst_reg->dir)
      check_dir(gst_reg->dir);
    
214
    /* Save the registry to a tmp file. */
215
    save_registry(gst_reg->tmp_file, &doc);
216

217
    /* Make the tmp file live. */
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    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);
245
    return(0);
246 247
}