Esempio n. 1
0
/* The do_we_replace logic. Decide, for some existing key, whether it should
 * be replaced with some new contents. Check that names and section
 * extensions match before calling this.
 */
static int replace_if_necessary (struct mandata *newdata,
				 struct mandata *olddata,
				 datum newkey, datum newcont)
{
	/* It's OK to replace ULT_MAN with SO_MAN if the mtime is newer. It
	 * isn't OK to replace a real page (either ULT_MAN or SO_MAN) with a
	 * whatis reference; if the real page really went away then
	 * purge_missing will catch that in time, but a real page that still
	 * exists should always take precedence.
	 */
	if (compare_ids (newdata->id, olddata->id, 1) <= 0 &&
	    newdata->_st_mtime > olddata->_st_mtime) {
		debug ("replace_if_necessary(): newer mtime; replacing\n");
		if (MYDBM_REPLACE (dbf, newkey, newcont))
			gripe_replace_key (MYDBM_DPTR (newkey));
		return 0;
	}

	if (compare_ids (newdata->id, olddata->id, 0) < 0) {
		if (MYDBM_REPLACE (dbf, newkey, newcont))
			gripe_replace_key (MYDBM_DPTR (newkey));
		return 0;
	}

	/* TODO: name fields should be collated with the requested name */

	if (newdata->id == olddata->id) {
		if (STREQ (dash_if_unset (newdata->comp), olddata->comp))
			return 0; /* same file */
		else {
			debug ("ignoring differing compression "
			       "extensions: %s\n", MYDBM_DPTR (newkey));
			return 1; /* differing exts */
		}
	}

	debug ("ignoring differing ids: %s\n", MYDBM_DPTR (newkey));
	return 0;
}
Esempio n. 2
0
int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info)
{
	datum key, cont;

	memset (&key, 0, sizeof key);
	memset (&cont, 0, sizeof cont);

	/* get entry for info */

	debug ("Attempting delete of %s(%s) entry.\n", name, info->ext);

	MYDBM_SET (key, name_to_key (name));
	cont = MYDBM_FETCH (dbf, key);

	if (!MYDBM_DPTR (cont)) {			/* 0 entries */
		MYDBM_FREE_DPTR (key);
		return NO_ENTRY;
	} else if (*MYDBM_DPTR (cont) != '\t') {	/* 1 entry */
		MYDBM_DELETE (dbf, key);
		MYDBM_FREE_DPTR (cont);
	} else {					/* 2+ entries */
		char **names, **ext;
		char *multi_content = NULL;
		datum multi_key;
		int refs, i, j;

		/* Extract all of the extensions associated with
		   this key */

		refs = list_extensions (MYDBM_DPTR (cont) + 1, &names, &ext);

		for (i = 0; i < refs; ++i)
			if (STREQ (names[i], name) &&
			    STREQ (ext[i], info->ext))
				break;

		if (i >= refs) {
			free (names);
			free (ext);
			MYDBM_FREE_DPTR (cont);
			MYDBM_FREE_DPTR (key);
			return NO_ENTRY;
		}

		multi_key = make_multi_key (names[i], ext[i]);
		if (!MYDBM_EXISTS (dbf, multi_key)) {
			error (0, 0,
			       _( "multi key %s does not exist"),
			       MYDBM_DPTR (multi_key));
			gripe_corrupt_data ();
		}
		MYDBM_DELETE (dbf, multi_key);
		MYDBM_FREE_DPTR (multi_key);

		/* refs *may* be 1 if all manual pages with this name
		   have been deleted. In this case, we'll have to remove
		   the key too */

		if (refs == 1) {
			free (names);
			free (ext);
			MYDBM_FREE_DPTR (cont);
			MYDBM_DELETE (dbf, key);
			MYDBM_FREE_DPTR (key);
			return 0;
		}

		/* create our new multi content */
		for (j = 0; j < refs; ++j)
			if (i != j)
				multi_content = appendstr (multi_content,
							   "\t", names[j],
							   "\t", ext[j], NULL);

		MYDBM_FREE_DPTR (cont);

		/* if refs = 2 do something else. Doesn't really matter as
		   the gdbm db file does not shrink any after a deletion
		   anyway */

		MYDBM_SET (cont, multi_content);

		if (MYDBM_REPLACE (dbf, key, cont))
			gripe_replace_key (MYDBM_DPTR (key));

		free (names);
		free (ext);
	}

	MYDBM_FREE_DPTR (key);
	return 0;
}
Esempio n. 3
0
int dbstore (struct mandata *in, const char *base)
{
	datum oldkey, oldcont;

	memset (&oldkey, 0, sizeof oldkey);
	memset (&oldcont, 0, sizeof oldcont);

	/* create a simple key */
	MYDBM_SET (oldkey, name_to_key (base));
 	if (!*base) {
		dbprintf (in);
 		return 2;
 	}

	if (in->name) {
		error (0, 0, "in->name (%s) should not be set when calling "
			     "dbstore()!\n",
		       in->name);
		free (in->name);
		in->name = NULL;
	}

	/* get the content for the simple key */

	oldcont = MYDBM_FETCH (dbf, oldkey);

	if (MYDBM_DPTR (oldcont) == NULL) { 		/* situation (1) */
		if (!STREQ (base, MYDBM_DPTR (oldkey)))
			in->name = xstrdup (base);
		oldcont = make_content (in);
		if (MYDBM_REPLACE (dbf, oldkey, oldcont))
			gripe_replace_key (MYDBM_DPTR (oldkey));
		free (MYDBM_DPTR (oldcont));
		free (in->name);
		in->name = NULL;
	} else if (*MYDBM_DPTR (oldcont) == '\t') { 	/* situation (2) */
		datum newkey, newcont;

		memset (&newkey, 0, sizeof newkey);
		memset (&newcont, 0, sizeof newcont);

		newkey = make_multi_key (base, in->ext);
		newcont = make_content (in);

		/* Try to insert the new multi data */

		if (MYDBM_INSERT (dbf, newkey, newcont)) {
			datum cont;
			struct mandata info;
			int ret;

			MYDBM_FREE (MYDBM_DPTR (oldcont));
			cont = MYDBM_FETCH (dbf, newkey);
			split_content (MYDBM_DPTR (cont), &info);
			ret = replace_if_necessary (in, &info,
						    newkey, newcont);
			/* MYDBM_FREE (MYDBM_DPTR (cont)); */
			free_mandata_elements (&info);
			free (MYDBM_DPTR (newkey));
			free (MYDBM_DPTR (newcont));
			free (MYDBM_DPTR (oldkey));

			return ret;
		}

		/* Now lets add some info to the simple key's cont. */

		/* This next bit needs to be done first as we'll wipe out
		   MYDBM_DPTR (oldcont) otherwise (for NDBM only!) */

		free (MYDBM_DPTR (newkey));
		free (MYDBM_DPTR (newcont));

		MYDBM_SET (newcont, xasprintf (
			"%s\t%s\t%s", MYDBM_DPTR (oldcont), base, in->ext));
		MYDBM_FREE (MYDBM_DPTR (oldcont));

		/* Try to replace the old simple data with the new stuff */

		if (MYDBM_REPLACE (dbf, oldkey, newcont))
			gripe_replace_key (MYDBM_DPTR (oldkey));

		free (MYDBM_DPTR (newcont));
	} else { 				/* situation (3) */
		datum newkey, newcont, lastkey, lastcont;
		struct mandata old;
		char *old_name;

		memset (&newkey, 0, sizeof newkey);
		memset (&newcont, 0, sizeof newcont);
		memset (&lastkey, 0, sizeof lastkey);
		memset (&lastcont, 0, sizeof lastcont);

		/* Extract the old singular reference */

		split_content (MYDBM_DPTR (oldcont), &old);

		/* Create multi keys for both old
		   and new items, create new content */

		if (old.name)
			old_name = xstrdup (old.name);
		else
			old_name = xstrdup (MYDBM_DPTR (oldkey));

		lastkey = make_multi_key (old_name, old.ext);

		/* Check against identical multi keys before inserting
		   into db */

		if (STREQ (old_name, base) && STREQ (old.ext, in->ext)) {
			int ret;

			if (!STREQ (base, MYDBM_DPTR (oldkey)))
				in->name = xstrdup (base);
			newcont = make_content (in);
			ret = replace_if_necessary (in, &old, oldkey, newcont);
			/* MYDBM_FREE (MYDBM_DPTR (oldcont)); */
			free_mandata_elements (&old);
			free (MYDBM_DPTR (newcont));
			free (MYDBM_DPTR (lastkey));
			free (MYDBM_DPTR (oldkey));
			free (old_name);
			free (in->name);
			in->name = NULL;

			return ret;
		}

		/* Multi keys use the proper case, and so don't need a name
		 * field.
		 */
		if (old.name) {
			free (old.name);
			old.name = NULL;
		}

		lastcont = make_content (&old);

		/* We always replace here; if the multi key already exists
		 * in the database, then that indicates some kind of
		 * database corruption, but our new multi key is almost
		 * certainly better.
		 */
		if (MYDBM_REPLACE (dbf, lastkey, lastcont))
			gripe_replace_key (MYDBM_DPTR (lastkey));

		free (MYDBM_DPTR (lastkey));
		free (MYDBM_DPTR (lastcont));

		newkey = make_multi_key (base, in->ext);
		newcont = make_content (in);

		if (MYDBM_REPLACE (dbf, newkey, newcont))
			gripe_replace_key (MYDBM_DPTR (newkey));

		free (MYDBM_DPTR (newkey));
		free (MYDBM_DPTR (newcont));

		/* Now build a simple reference to the above two items */

		MYDBM_SET (newcont, xasprintf (
			"\t%s\t%s\t%s\t%s", old_name, old.ext, base, in->ext));

		if (MYDBM_REPLACE (dbf, oldkey, newcont))
			gripe_replace_key (MYDBM_DPTR (oldkey));

		/* MYDBM_FREE (MYDBM_DPTR (oldcont)); */
		free_mandata_elements (&old);
		free (MYDBM_DPTR (newcont));
		free (old_name);
	}

	free (MYDBM_DPTR (oldkey));
	return 0;
}