/** * 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; }
/** * 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; }
static void test_elektraEscapeKeyNamePart (void) { printf ("test escape key name part\n"); char dest[2000]; succeed_if_same_string (elektraEscapeKeyNamePart ("abc", dest), "abc"); succeed_if_same_string (elektraEscapeKeyNamePart (".", dest), "\\."); succeed_if_same_string (elektraEscapeKeyNamePart ("..", dest), "\\.."); succeed_if_same_string (elektraEscapeKeyNamePart ("%", dest), "\\%"); succeed_if_same_string (elektraEscapeKeyNamePart ("", dest), "%"); succeed_if_same_string (elektraEscapeKeyNamePart ("///", dest), "\\/\\/\\/"); succeed_if_same_string (elektraEscapeKeyNamePart ("a/b", dest), "a\\/b"); succeed_if_same_string (elektraEscapeKeyNamePart ("a//b", dest), "a\\/\\/b"); succeed_if_same_string (elektraEscapeKeyNamePart ("a/./b", dest), "a\\/.\\/b"); succeed_if_same_string (elektraEscapeKeyNamePart ("a/../b", dest), "a\\/..\\/b"); succeed_if_same_string (elektraEscapeKeyNamePart ("a/%/b", dest), "a\\/%\\/b"); succeed_if_same_string (elektraEscapeKeyNamePart ("a/x/b", dest), "a\\/x\\/b"); succeed_if_same_string (elektraEscapeKeyNamePart ("a\\.", dest), "a\\."); succeed_if_same_string (elektraEscapeKeyNamePart ("\\.", dest), "\\\\."); succeed_if_same_string (elektraEscapeKeyNamePart ("\\\\.", dest), "\\\\\\."); succeed_if_same_string (elektraEscapeKeyNamePart ("\\..", dest), "\\\\.."); succeed_if_same_string (elektraEscapeKeyNamePart ("\\\\..", dest), "\\\\\\.."); succeed_if_same_string (elektraEscapeKeyNamePart ("\\\\\\..", dest), "\\\\\\\\.."); succeed_if_same_string (elektraEscapeKeyNamePart ("/", dest), "\\/"); succeed_if_same_string (elektraEscapeKeyNamePart ("\\/", dest), "\\\\\\/"); // 1 -> 3 succeed_if_same_string (elektraEscapeKeyNamePart ("\\\\/", dest), "\\\\\\\\\\/"); // 2 -> 5 succeed_if_same_string (elektraEscapeKeyNamePart ("ab\\\\/", dest), "ab\\\\\\\\\\/"); // 2 -> 5 succeed_if_same_string (elektraEscapeKeyNamePart ("ab\\\\/de", dest), "ab\\\\\\\\\\/de"); // 2 -> 5 succeed_if_same_string (elektraEscapeKeyNamePart ("\\", dest), "\\\\"); // 1 -> 2 succeed_if_same_string (elektraEscapeKeyNamePart ("\\\\", dest), "\\\\\\\\"); // 2 -> 4 succeed_if_same_string (elektraEscapeKeyNamePart ("\\\\\\", dest), "\\\\\\\\\\\\"); // 3 -> 6 }