summaryrefslogtreecommitdiff
path: root/metadata/metadata-nautilus.c
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2009-06-22 20:39:03 +0200
committerAlexander Larsson <alexl@redhat.com>2009-06-23 15:10:27 +0200
commitc97601731a5dbc9d34e8c4c208e993a3723deec5 (patch)
treee8e32dc0d08e658898cb43570f6626a7a8e2c605 /metadata/metadata-nautilus.c
parenta8d6c3db07ad5d9dc75b94eb95492b03bc20e788 (diff)
downloadgvfs-c97601731a5dbc9d34e8c4c208e993a3723deec5.tar.gz
Initial code for metadata store
This adds a mmap based metadata store for NFS-safe highly efficient desktop-wide metadata lookup and store.
Diffstat (limited to 'metadata/metadata-nautilus.c')
-rw-r--r--metadata/metadata-nautilus.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/metadata/metadata-nautilus.c b/metadata/metadata-nautilus.c
new file mode 100644
index 00000000..8617f11e
--- /dev/null
+++ b/metadata/metadata-nautilus.c
@@ -0,0 +1,220 @@
+#include <string.h>
+#include "metabuilder.h"
+#include <libxml/tree.h>
+
+static xmlNodePtr
+xml_get_children (xmlNodePtr parent)
+{
+ if (parent == NULL) {
+ return NULL;
+ }
+ return parent->children;
+}
+
+static xmlNodePtr
+xml_get_root_children (xmlDocPtr document)
+{
+ return xml_get_children (xmlDocGetRootElement (document));
+}
+
+
+static char *
+get_uri_from_nautilus_metafile_name (const char *filename)
+{
+ GString *s;
+ char c;
+ char *base_name, *p;
+ int len;
+
+ base_name = g_path_get_basename (filename);
+ len = strlen (base_name);
+ if (len <= 4 ||
+ strcmp (base_name + len - 4, ".xml") != 0)
+ {
+ g_free (base_name);
+ return NULL;
+ }
+ base_name[len-4] = 0;
+
+ s = g_string_new (NULL);
+
+ p = base_name;
+ while (*p)
+ {
+ c = *p++;
+ if (c == '%')
+ {
+ c =
+ g_ascii_xdigit_value (p[0]) << 4 |
+ g_ascii_xdigit_value (p[1]);
+ p += 2;
+ }
+ g_string_append_c (s, c);
+ }
+ g_free (base_name);
+
+ return g_string_free (s, FALSE);
+}
+
+static void
+parse_xml_node (MetaFile *metafile,
+ xmlNodePtr filenode)
+{
+ xmlChar *data;
+ guint64 timestamp;
+ xmlNodePtr node;
+ xmlAttrPtr attr;
+ xmlChar *property;
+ char *combined_key;
+
+ data = xmlGetProp (filenode, (xmlChar *)"timestamp");
+ if (data)
+ {
+ timestamp = g_ascii_strtoll ((char *)data, NULL, 10);
+ if (timestamp != 0)
+ metafile->last_changed = timestamp;
+ }
+
+ for (attr = filenode->properties; attr != NULL; attr = attr->next)
+ {
+ if (strcmp ((char *)attr->name, "name") == 0 ||
+ strcmp ((char *)attr->name, "timestamp") == 0)
+ continue;
+
+ property = xmlGetProp (filenode, attr->name);
+ if (property)
+ metafile_key_set_value (metafile, (char *)attr->name, (char *)property);
+ xmlFree (property);
+ }
+
+ for (node = filenode->children; node != NULL; node = node->next)
+ {
+ for (attr = node->properties; attr != NULL; attr = attr->next)
+ {
+ property = xmlGetProp (node, attr->name);
+ if (property)
+ {
+ combined_key = g_strconcat ((char *)node->name,
+ "-",
+ (char *)attr->name,
+ NULL);
+ metafile_key_list_add (metafile, combined_key, (char *)property);
+ g_free (combined_key);
+ }
+ xmlFree (property);
+ }
+ }
+}
+
+static void
+parse_xml_file (MetaBuilder *builder,
+ xmlDocPtr xml,
+ char *dir)
+{
+ xmlNodePtr node;
+ xmlChar *name;
+ char *unescaped_name;
+ MetaFile *dir_metafile, *metafile;
+
+ dir_metafile = meta_builder_lookup (builder, dir, TRUE);
+
+ for (node = xml_get_root_children (xml);
+ node != NULL; node = node->next)
+ {
+ if (strcmp ((char *)node->name, "file") == 0)
+ {
+ name = xmlGetProp (node, (xmlChar *)"name");
+ unescaped_name = g_uri_unescape_string ((char *)name, "/");
+ xmlFree (name);
+
+ if (strcmp (unescaped_name, ".") == 0)
+ metafile = dir_metafile;
+ else
+ metafile = metafile_lookup_child (dir_metafile, unescaped_name, TRUE);
+
+ parse_xml_node (metafile, node);
+ g_free (unescaped_name);
+ }
+ }
+}
+
+static void
+parse_nautilus_file (MetaBuilder *builder,
+ char *file)
+{
+ char *uri;
+ char *dir;
+ gchar *contents;
+ gsize length;
+ xmlDocPtr xml;
+
+ if (!g_file_get_contents (file, &contents, &length, NULL))
+ {
+ g_print ("failed to load %s\n", file);
+ return;
+ }
+
+ uri = get_uri_from_nautilus_metafile_name (file);
+ if (uri == NULL)
+ {
+ g_free (contents);
+ return;
+ }
+
+ dir = g_filename_from_uri (uri, NULL, NULL);
+ g_free (uri);
+ if (dir == NULL)
+ {
+ g_free (contents);
+ return;
+ }
+
+ xml = xmlParseMemory (contents, length);
+ g_free (contents);
+ if (xml == NULL)
+ return;
+
+ parse_xml_file (builder, xml, dir);
+ xmlFreeDoc (xml);
+}
+
+/*static gboolean recursive = FALSE;*/
+static char *filename = NULL;
+static GOptionEntry entries[] =
+{
+ { "out", 'o', 0, G_OPTION_ARG_FILENAME, &filename, "Output filename", NULL },
+ { NULL }
+};
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ MetaBuilder *builder;
+ GError *error = NULL;
+ int i;
+
+ context = g_option_context_new ("<nautilus metadata files> - convert nautilus metadata");
+ g_option_context_add_main_entries (context, entries, NULL);
+ if (!g_option_context_parse (context, &argc, &argv, &error))
+ {
+ g_printerr ("option parsing failed: %s\n", error->message);
+ return 1;
+ }
+
+ if (argc < 2)
+ {
+ g_print ("No files specified\n");
+ return 1;
+ }
+
+ builder = meta_builder_new ();
+ for (i = 1; i < argc; i++)
+ parse_nautilus_file (builder, argv[i]);
+ if (filename)
+ meta_builder_write (builder, filename);
+ else
+ meta_builder_print (builder);
+
+ return 0;
+}