Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
add keyAddName
Browse files Browse the repository at this point in the history
also in binding
refactor with elektraFinalizeName as preparation for fixing #38
fail when no key is there before for adding functions
fix tests that try to do that
refactor keySetName to use keyAddName internally
do keyAddBaseName and keySetBaseName both with escaping
comment out KEY_FLAG_RO_NAME because some tests fail with it
fix mounting with config to properly add conf that contains /
  • Loading branch information
Markus Raab committed Aug 28, 2014
1 parent 90b839d commit 99aa0f4
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 117 deletions.
9 changes: 9 additions & 0 deletions src/bindings/cpp/include/key.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class Key
inline std::string getDirName() const;

inline void setName (const std::string &newName);
inline void addName (const std::string &addedName);
inline void setBaseName (const std::string &baseName);
inline void addBaseName (const std::string &baseName);

Expand Down Expand Up @@ -548,6 +549,14 @@ inline void Key::setName (const std::string &newName)
}
}

inline void Key::addName (const std::string &addedName)
{
if (ckdb::keyAddName (getKey(), addedName.c_str()) == -1)
{
throw KeyInvalidName();
}
}

/**Sets a base name for a key.
*
* @copydoc keySetBaseName
Expand Down
5 changes: 4 additions & 1 deletion src/include/kdb.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,19 @@ int keyIsString(const Key *key);
const char *keyName(const Key *key);
ssize_t keyGetNameSize(const Key *key);
ssize_t keyGetName(const Key *key, char *returnedName, size_t maxSize);

ssize_t keySetName(Key *key, const char *newname);
ssize_t keyAddName(Key *key, const char *addName);

ssize_t keyGetFullNameSize(const Key *key);
ssize_t keyGetFullName(const Key *key, char *returnedName, size_t maxSize);

const char *keyBaseName(const Key *key);
ssize_t keyGetBaseNameSize(const Key *key);
ssize_t keyGetBaseName(const Key *key, char *returned, size_t maxSize);
ssize_t keyAddBaseName(Key *key,const char *baseName);

ssize_t keySetBaseName(Key *key,const char *baseName);
ssize_t keyAddBaseName(Key *key,const char *baseName);

/* Value Manipulation Methods */
const void *keyValue(const Key *key);
Expand Down
260 changes: 153 additions & 107 deletions src/libelektra/keyname.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,28 @@ ssize_t keyGetName(const Key *key, char *returnedName, size_t maxSize)
return key->keySize;
}

/**
* @internal
*
* @brief Call this function after every key changing operation
*
* @pre key->key and key->keySize are set accordingly and the size of
* allocation is twice as what you actually needed.
*
* @post we get a unsynced key with a correctly terminated
* key name suitable for ordering and the name getter methods
*
* It will duplicate the key length and put a second name afterwards
* that is used for sorting keys.
*
* @param key
*/
static void elektraFinalizeName(Key *key)
{
key->key[key->keySize - 1] = 0; /* finalize string */

key->flags |= KEY_FLAG_SYNC;
}



Expand Down Expand Up @@ -340,7 +362,6 @@ ssize_t keySetName(Key *key, const char *newName)
size_t length;
size_t rootLength, userLength, systemLength, ownerLength;
char *p=0;
size_t size=0;

if (!key) return -1;
if (test_bit(key->flags, KEY_FLAG_RO_NAME)) return -1;
Expand Down Expand Up @@ -407,7 +428,7 @@ ssize_t keySetName(Key *key, const char *newName)
key->keySize+=userLength;
}

rootLength = userLength;
rootLength = userLength+1;
} else if (keyNameIsSystem(newName)) {
/* handle "system*" */
if (length > systemLength && *(newName+systemLength)!=KDB_PATH_SEPARATOR)
Expand All @@ -421,7 +442,7 @@ ssize_t keySetName(Key *key, const char *newName)

keySetOwner (key, NULL);

rootLength = systemLength;
rootLength = systemLength+1;
} else {
/* Given newName is neither "system" or "user" */
/*errno=KDB_ERR_INVALIDKEY;*/
Expand All @@ -439,7 +460,7 @@ ssize_t keySetName(Key *key, const char *newName)
- key->keySize has number of bytes that will be allocated for key name
with already removed owner.
- key->owner is already set
- rootLength is sizeof("user")-1 or sizeof("system")-1
- rootLength is sizeof("user") or sizeof("system")
*/

/* Allocate memory for key->key */
Expand All @@ -453,49 +474,17 @@ ssize_t keySetName(Key *key, const char *newName)

/* copy the root of newName to final destination */
strncpy(key->key,newName,rootLength);

/* skip the root */
p=(char *)newName;
size=0;
p=keyNameGetOneLevel(p+size,&size);

/* iterate over each single folder name removing repeated '/' and escaping when needed */
key->keySize=rootLength;
while (*(p=keyNameGetOneLevel(p+size,&size))) {
/* printf ("level: %s, size: %d\n", p, size); */
if (size == 1 && strncmp (p, ".",1) == 0)
{
/* printf ("ignore .\n"); */
continue; /* just ignore current directory */
}
else if (size == 2 && strncmp (p, "..",2) == 0) /* give away directory */
{
key->key[key->keySize] = 0; /* initialize first (valgrind) */
while (key->keySize > rootLength && key->key[key->keySize] != KDB_PATH_SEPARATOR) key->keySize--;
/* printf ("do .. (key->keySize: %d), key->key: %s, rootLength: %d, key->keySize: %d\n",
key->keySize, key->key, rootLength, key->keySize); */
continue;
}
/* Add a '/' to the end of key name */
key->key[key->keySize]=KDB_PATH_SEPARATOR;
key->keySize++;

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

/* remove unescaped trailing slashes */
while (key->key[key->keySize-1] == KDB_PATH_SEPARATOR && key->key[key->keySize-2] != '\\') key->keySize--;
key->key[key->keySize]=0; /* finalize string */
/* finish root name for keyAddName() */
key->keySize=rootLength;
key->key[rootLength] = '\0';

key->flags |= KEY_FLAG_SYNC;
/* skip namespace we already processed */
p=keyNameGetOneLevel(newName,&length);

key->keySize ++; /*for \\0 ending*/
return key->keySize;
return keyAddName(key, p+length);

error_mem:
/*errno=KDB_ERR_NOMEM;*/
return -1;
}

Expand Down Expand Up @@ -809,35 +798,94 @@ ssize_t keyGetBaseName(const Key *key, char *returned, size_t maxSize)
*/
ssize_t keyAddBaseName(Key *key, const char *baseName)
{
size_t size=0;

if (!key) return -1;
if (test_bit(key->flags, KEY_FLAG_RO_NAME)) return -1;

if (!baseName) return key->keySize;
// if (test_bit(key->flags, KEY_FLAG_RO_NAME)) return -1;
if (!key->key) return -1;

size_t size=0;
char *escaped = elektraMalloc (strlen (baseName) * 2 + 2);
elektraKeyNameEscape (baseName, escaped);
if (key->key)
{
size = strlen (escaped);
key->keySize += size + 1;
key->key = realloc (key->key, key->keySize);
size = strlen (escaped);
key->keySize += size + 1;
key->key = realloc (key->key, key->keySize);

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

key->key[key->keySize - 1] = 0; /* finalize string */
elektraFree (escaped);
return key->keySize;
}
else
{
int result = keySetName (key, escaped);
elektraFree (escaped);
return result;
}
elektraFree (escaped);

elektraFinalizeName(key);

return key->keySize;
}

/**
* @brief Add a already escaped name to the keyname.
*
* The same way as in keySetName() this method finds the canonical pathname.
* Unlike, keySetName() it adds it to an already existing name.
*
* @param key the key where a name should be added
* @param newName the new name to append
*
* @retval -1 if key is a null pointer or did not have a valid name before
* @retval -1 if newName is a null pointer or not a valid name (contains \\ in beginning)
* @retval -1 on allocation errors
* @retval size of the new key
*/
ssize_t keyAddName(Key *key, const char *newName)
{
if (!key) return -1;
if (!newName) return key->keySize;
// if (test_bit(key->flags, KEY_FLAG_RO_NAME)) return -1;
// if (!elektraValidateKeyNamePart(newName)) return -1;
if (!key->key) return -1;

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

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

-- key->keySize; // fix keySize for loop below

/* iterate over each single folder name removing repeated '/', . and .. */
while (*(p=keyNameGetOneLevel(p+size,&size))) {
// printf ("level: %s, size: %d\n", p, size);
if (size == 1 && strncmp (p, ".",1) == 0)
{
/* printf ("ignore .\n"); */
continue; /* just ignore current directory */
}
else if (size == 2 && strncmp (p, "..",2) == 0) /* give away directory */
{
key->key[key->keySize] = 0; /* initialize first (valgrind) */
while (key->keySize >= rootLength && key->key[key->keySize] != KDB_PATH_SEPARATOR) key->keySize--;
/* printf ("do .. (key->keySize: %d), key->key: %s, rootLength: %d, key->keySize: %d\n",
key->keySize, key->key, rootLength, key->keySize); */
continue;
}
/* Add a '/' to the end of key name */
key->key[key->keySize]=KDB_PATH_SEPARATOR;
key->keySize++;

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

/* remove unescaped trailing slashes */
while (key->key[key->keySize-1] == KDB_PATH_SEPARATOR && key->key[key->keySize-2] != '\\') key->keySize--;
key->keySize ++; /*for \\0 ending*/


elektraFinalizeName(key);

return key->keySize;
}



Expand Down Expand Up @@ -880,67 +928,65 @@ ssize_t keySetBaseName(Key *key, const char *baseName)
const char *p=0;

if (!key) return -1;
if (test_bit(key->flags, KEY_FLAG_RO_NAME)) return -1;
// if (test_bit(key->flags, KEY_FLAG_RO_NAME)) return -1;

if (!elektraValidateKeyNamePart(baseName)) return -1;

if (key->key) {
if (!key->key) return -1;


/*Throw away basename of key->key*/
p=strrchr (key->key, '/');
if (p == 0)
{
/* we would remove even the namespace */
if (!strcmp (baseName, "")) return -1;
/*Throw away basename of key->key*/
p=strrchr (key->key, '/');
if (p == 0)
{
/* we would remove even the namespace */
if (!strcmp (baseName, "")) return -1;

if (!strcmp (baseName, ".")) return -1;
if (!strcmp (baseName, ".")) return -1;

return keySetName(key, baseName);
}
return keySetName(key, baseName);
}

/* check if the found / is the only one */
if (strchr (key->key, '/') == p)
{
/* we would delete the whole keyname */
if (!strcmp (baseName, "..")) return -1;
}
/* check if the found / is the only one */
if (strchr (key->key, '/') == p)
{
/* we would delete the whole keyname */
if (!strcmp (baseName, "..")) return -1;
}

key->keySize -= (key->key+key->keySize-1)-p;
key->key[key->keySize-1]=0; /* finalize string */

/* remove yet another part */
if (!strcmp (baseName, ".."))
{
p=strrchr (key->key, '/');
key->keySize -= (key->key+key->keySize-1)-p;
key->key[key->keySize-1]=0; /* finalize string */
}

/* remove yet another part */
if (!strcmp (baseName, ".."))
{
p=strrchr (key->key, '/');
key->keySize -= (key->key+key->keySize-1)-p;
key->key[key->keySize-1]=0; /* finalize string */
}
/* free the now unused space */
key->key=realloc(key->key,key->keySize);

/* free the now unused space */
key->key=realloc(key->key,key->keySize);
/* these cases just delete keyname parts so we are done */
if (!strcmp (baseName, "..") ||
!strcmp (baseName, ".") ||
!strcmp (baseName, ""))
{
return key->keySize;
}

/* these cases just delete keyname parts so we are done */
if (!strcmp (baseName, "..") ||
!strcmp (baseName, ".") ||
!strcmp (baseName, ""))
{
return key->keySize;
}
/* Now add new baseName */
size = strlen (baseName);
key->keySize += size + 1;
key->key = realloc (key->key, key->keySize);

/* Now add new baseName */
size = strlen (baseName);
key->keySize += size + 1;
key->key = realloc (key->key, key->keySize);
key->key[key->keySize - size - 2] = KDB_PATH_SEPARATOR;
memcpy (key->key + key->keySize - size - 1, baseName, size);

key->key[key->keySize - size - 2] = KDB_PATH_SEPARATOR;
memcpy (key->key + key->keySize - size - 1, baseName, size);
/* use keySetRawName() internally and not
* key->key*/
elektraFinalizeName(key);

key->key[key->keySize-1]=0; /* finalize string */
return key->keySize;
} else return keySetName(key,baseName); /*that cannot be a good idea*/
return key->keySize;
}


Expand Down
3 changes: 2 additions & 1 deletion src/tools/kdb/mount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ void MountCommand::buildBackend(Cmdline const& cl)
void MountCommand::addConfig (string const& configBasePath, string const& keyName, string const& value)
{
Key configKey = Key (configBasePath, KEY_END);
configKey.addBaseName (keyName);
std:: cout << "appending " << keyName << " to " << configKey.getName() << std::endl;
configKey.addName (keyName);
configKey.setString (value);
mountConf.append (configKey);
}
Expand Down
Loading

0 comments on commit 99aa0f4

Please sign in to comment.