예제 #1
0
파일: keyname.c 프로젝트: tryge/libelektra
/**
 * Sets @c baseName as the new basename for @c key.
 *
 * Only the baseName will be affected and no other part of the key.
 *
 * All text after the last @c '/' in the @p key keyname is erased and
 * @p baseName is appended.
 *
 * So let us suppose @p key has name @c "system/dir1/dir2/key1". If @p baseName
 * is @c "key2", the resulting key name will be @c "system/dir1/dir2/key2".
 * If @p baseName is empty or NULL, the resulting key name will
 * be @c "system/dir1/dir2".
 *
 * This function does proper escaping on the supplied name argument.
 *
 * You can use all names to set as basename (e.g. . (dot), ..
 * (dot-dot), % and "" (empty)). They will be properly escaped.
 *
 * A simple example is:
 * @snippet basename.c set base basic
 *
 * If you want to add and not change the basename, use keyAddBaseName()
 * instead. If you do not want escaping, use keyAddName() instead.
 *
 * To add an inactive key name, use:
 * @snippet testabi_key.c base1
 *
 * When you want to add an array item, use:
 * @snippet testabi_key.c base2
 *
 * @see keyname for more details on special names
 *
 * @param key the key object to work with
 * @param baseName the string used to overwrite the basename of the key
 * @return the size in bytes of the new key name
 * @retval -1 on NULL pointers
 * @retval -1 if key was inserted to a keyset before
 * @see keyAddBaseName()
 * @see keySetName() to set a new name
 * @ingroup keyname
 */
ssize_t keySetBaseName(Key *key, const char *baseName)
{
	if (!key) return -1;
	if (test_bit(key->flags,  KEY_FLAG_RO_NAME)) return -1;
	if (!key->key) return -1;

	size_t size=0;
	char *searchBaseName=0;
	size_t searchBaseSize=0;
	char *p = key->key;

	while (*(p=keyNameGetOneLevel(p+size,&size)))
	{
		searchBaseName=p;
		searchBaseSize=size+1;
	}

	if (!searchBaseName || searchBaseName==key->key)
	{
		return -1;
	}

	// truncate the key
	key->keySize -= searchBaseSize;

	if (!baseName)
	{
		// just remove base name, so we are finished
		elektraFinalizeName(key);
		return key->keySize;
	}

	char *escaped = elektraMalloc (strlen (baseName) * 2 + 2);
	elektraEscapeKeyNamePart(baseName, escaped);
	size_t sizeEscaped = elektraStrLen (escaped);

	elektraRealloc((void**)&key->key, (key->keySize+sizeEscaped)*2);
	if (!key->key)
	{
		elektraFree (escaped);
		return -1;
	}

	key->key [key->keySize - 1] = KDB_PATH_SEPARATOR;
	memcpy (key->key + key->keySize,
			escaped, sizeEscaped);

	elektraFree (escaped);

	key->keySize += sizeEscaped;
	elektraFinalizeName(key);

	return key->keySize;
}
예제 #2
0
파일: keyname.c 프로젝트: tryge/libelektra
ssize_t elektraKeySetName(Key *key, const char *newName,
		option_t options)
{
	if (!key) return -1;
	if (test_bit(key->flags,  KEY_FLAG_RO_NAME)) return -1;

	elektraRemoveKeyName(key);
	if (!(options & KEY_META_NAME)) keySetOwner (key, NULL);

	switch (keyGetNameNamespace(newName))
	{
	case KEY_NS_NONE: ELEKTRA_ASSERT(0);
	case KEY_NS_EMPTY:
		elektraFinalizeEmptyName(key);
		return 0; // as documented
	case KEY_NS_CASCADING: key->keyUSize=1;key->keySize=sizeof("/"); break;
	case KEY_NS_SPEC: key->keyUSize=key->keySize=sizeof("spec"); break;
	case KEY_NS_PROC: key->keyUSize=key->keySize=sizeof("proc"); break;
	case KEY_NS_DIR: key->keyUSize=key->keySize=sizeof("dir"); break;
	case KEY_NS_USER: elektraHandleUserName(key, newName); break;
	case KEY_NS_SYSTEM: key->keyUSize=key->keySize=sizeof("system"); break;
	case KEY_NS_META:
		if (!(options & KEY_META_NAME)) return -1;
		keyNameGetOneLevel(newName,&key->keySize);
		key->keyUSize = ++ key->keySize; // for null
		break;
	} // Note that we abused keyUSize for cascading and user:owner

	const size_t length = elektraStrLen(newName);
	key->key=elektraMalloc(key->keySize*2);
	memcpy(key->key, newName, key->keySize);
	if (length == key->keyUSize || length == key->keySize)
	{	// use || because full length is keyUSize in user, but keySize for /
		// newName consisted of root only
		elektraFinalizeName(key);
		return key->keyUSize;
	}

	if (elektraOnlySlashes(newName+key->keyUSize-1))
	{
		elektraFinalizeName(key);
		return key->keySize;
	}

	key->key[key->keySize-1] = '\0';
	const ssize_t ret = keyAddName(key, newName+key->keyUSize);
	if (ret == -1) elektraRemoveKeyName(key);
	else return key->keySize;
	return ret;
}
예제 #3
0
/**
 * @brief Add an already escaped name to the keyname.
 *
 * The same way as in keySetName() this method finds the canonical pathname:
 * - it will ignore /./
 * - it will remove a level when /../ is used
 * - it will remove multiple slashes ////
 *
 * For example:
 * @snippet keyName.c add name
 *
 * Unlike keySetName() it adds relative to the previous name and
 * cannot change the namespace of a key.
 * For example:
 * @snippet keyName.c namespace
 *
 * The passed name needs to be valid according the @link keyname key name rules @endlink.
 * It is not allowed to:
 * - be empty
 * - end with unequal number of \\
 *
 * @param key the key where a name should be added
 * @param newName the new name to append
 *
 * @since 0.8.11
 *
 * @retval size of the new key
 * @retval -1 if key is a null pointer or did not have a valid name before
 * @retval -1 if newName is not a valid escaped name
 * @retval -1 on allocation errors
 * @retval -1 if key was inserted to a keyset before
 * @retval 0 if nothing was done because newName had only slashes, is too short, is empty or is null
 * @ingroup keyname
 */
ssize_t keyAddName (Key * key, const char * newName)
{
	if (!key) return -1;
	if (test_bit (key->flags, KEY_FLAG_RO_NAME)) return -1;
	if (!key->key) return -1;
	if (!strcmp (key->key, "")) return -1;
	if (!newName) return 0;
	size_t const nameSize = elektraStrLen (newName);
	if (nameSize < 2) return 0;
	if (!elektraValidateKeyName (newName, nameSize)) return -1;

	const size_t origSize = key->keySize;
	const size_t newSize = origSize + nameSize;
	elektraRealloc ((void **)&key->key, newSize * 2);
	if (!key->key) return -1;

	size_t size = 0;
	const char * p = newName;
	int avoidSlash = 0;

	if (*key->key == '/') avoidSlash = key->keySize == 2;

	--key->keySize; // loop assumes that key->key[key->keySize] is last character and not NULL

	/* iterate over each single folder name removing repeated '/', .  and .. */
	while (*(p = keyNameGetOneLevel (p + size, &size)))
	{
		if (size == 1 && strncmp (p, ".", 1) == 0)
		{
			continue; /* just ignore current directory */
		}
		else if (size == 2 && strncmp (p, "..", 2) == 0) /* give away one level*/
		{
			elektraRemoveOneLevel (key, &avoidSlash);
			continue;
		}

		if (!avoidSlash)
		{
			/* Add a '/' to the end of key name */
			key->key[key->keySize] = KDB_PATH_SEPARATOR;
			key->keySize++;
		}
		else
		{
			avoidSlash = 0;
		}

		/* carefully append basenames */
		char * d = key->key + key->keySize;
		memcpy (d, p, size);
		key->keySize += size;
	}

	++key->keySize; /*for \\0 ending*/

	elektraFinalizeName (key);

	return origSize == key->keySize ? 0 : key->keySize;
}
예제 #4
0
/**
 * Adds @p baseName (that will be escaped) to the current key name.
 *
 * A new baseName will be added, no other part of the key name will be
 * affected.
 *
 * Assumes that @p key is a directory and will append @p baseName to it.
 * The function adds the path separator for concatenating.
 *
 * So if @p key has name @c "system/dir1/dir2" and this method is called with
 * @p baseName @c "mykey", the resulting key will have the name
 * @c "system/dir1/dir2/mykey".
 *
 * When @p baseName is 0 nothing will happen and the size of the name is returned.
 *
 * The escaping rules apply as in @link keyname above @endlink.
 *
 * A simple example is:
 * @snippet basename.c add base basic
 *
 * E.g. if you add . it will be escaped:
 * @snippet testabi_key.c base1 add
 *
 * @see keySetBaseName() to set a base name
 * @see keySetName() to set a new name.
 *
 * @param key the key object to work with
 * @param baseName the string to append to the name
 * @return the size in bytes of the new key name including the ending NULL
 * @retval -1 if the key had no name
 * @retval -1 on NULL pointers
 * @retval -1 if key was inserted to a keyset before
 * @ingroup keyname
 *
 */
ssize_t keyAddBaseName (Key * key, const char * baseName)
{
	if (!key) return -1;
	if (!baseName) return key->keySize;
	if (test_bit (key->flags, KEY_FLAG_RO_NAME)) return -1;
	if (!key->key) return -1;

	char * escaped = elektraMalloc (strlen (baseName) * 2 + 2);
	elektraEscapeKeyNamePart (baseName, escaped);
	size_t len = strlen (escaped);
	if (!strcmp (key->key, "/"))
	{
		key->keySize += len;
	}
	else
	{
		key->keySize += len + 1;
	}

	elektraRealloc ((void **)&key->key, key->keySize * 2);
	if (!key->key)
	{
		elektraFree (escaped);
		return -1;
	}

	if (strcmp (key->key, "/"))
	{
		key->key[key->keySize - len - 2] = KDB_PATH_SEPARATOR;
	}
	memcpy (key->key + key->keySize - len - 1, escaped, len);

	elektraFree (escaped);

	elektraFinalizeName (key);

	return key->keySize;
}