static int handleInvalidConflict (Key * parentKey, Key * key, OnConflict onConflict) { int ret = 0; switch (onConflict) { case ERROR: ELEKTRA_SET_ERRORF (142, parentKey, "Invalid key %s\n", keyName (key)); ret = -1; break; case WARNING: ELEKTRA_ADD_WARNINGF (143, parentKey, "Invalid key %s\n", keyName (key)); break; case INFO: { const char * infoString = "Invalid key "; const size_t len = elektraStrLen (infoString) + elektraStrLen (keyName (key)) - 1; char * buffer = elektraMalloc (len); snprintf (buffer, len, "Invalid key %s\n", keyName (key)); elektraMetaArrayAdd (key, "logs/spec/info", buffer); elektraFree (buffer); } break; case IGNORE: break; } return ret; }
static void test_keyGetBaseName (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; KeySet * ks = metaTestKeySet (); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); const char * name = "user/tests/storage/a"; Key * found = ksLookupByName (ks, name, 0); succeed_if (found, "did not find key"); const char * constBaseName = "a"; size_t constBaseNameSize = elektraStrLen (constBaseName); ssize_t baseNameSize = keyGetFullNameSize (found); char * baseName = elektraMalloc (baseNameSize); ssize_t ret = keyGetBaseName (found, baseName, baseNameSize); if (ret < 1) { yield_error ("Key base name NULL or size error"); } else { succeed_if ((size_t) ret == elektraStrLen (constBaseName), "Key base name has wrong size"); } succeed_if (elektraStrNCmp (constBaseName, baseName, constBaseNameSize) == 0, "Key base name is wrong"); elektraFree (baseName); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
static int handleMissingConflict (Key * parentKey, Key * key, Key * conflictMeta, OnConflict onConflict) { int ret = 0; const char * problemKeys = elektraMetaArrayToString (key, keyName (conflictMeta), ", "); switch (onConflict) { case ERROR: ELEKTRA_SET_ERRORF (142, parentKey, "%s has missing subkeys: %s\n", keyName (key), problemKeys); ret = -1; break; case WARNING: ELEKTRA_ADD_WARNINGF (143, parentKey, "%s has missing subkeys: %s\n", keyName (key), problemKeys); break; case INFO: { const char * infoString = "has missing subkeys:"; const size_t len = elektraStrLen (infoString) + elektraStrLen (problemKeys) + elektraStrLen (keyName (key)); char * buffer = elektraMalloc (len); snprintf (buffer, len, "%s %s %s", keyName (key), infoString, problemKeys); elektraMetaArrayAdd (key, "logs/spec/info", buffer); elektraFree (buffer); } break; case IGNORE: break; } if (problemKeys) { elektraFree ((void *) problemKeys); } return ret; }
static int elektraResolvePasswdHome (resolverHandle * p, Key * warningsKey) { ssize_t bufSize = sysconf (_SC_GETPW_R_SIZE_MAX); if (bufSize == -1) bufSize = 16384; // man 3 getpwuid char * buf = elektraMalloc (bufSize); if (!buf) return -1; struct passwd pwd; struct passwd * result; int s; s = getpwuid_r (getuid (), &pwd, buf, bufSize, &result); if (result == NULL) { elektraFree (buf); if (s != 0) { ELEKTRA_ADD_WARNING (90, warningsKey, strerror (s)); } return -1; } const char * home = pwd.pw_dir; size_t filenameSize = elektraStrLen (home) + elektraStrLen (p->path) - 1; p->filename = elektraMalloc (filenameSize); snprintf (p->filename, filenameSize, "%s/%s", home, (p->path) + 2); elektraFree (buf); return 0; }
static int handleOutOfRangeConflict (Key * parentKey, Key * key, Key * specKey, Key * conflictMeta, OnConflict onConflict) { int ret = 0; switch (onConflict) { case ERROR: ELEKTRA_SET_ERRORF (142, parentKey, "%s has invalid number of members: %s. Expected: %s\n", keyName (key), keyString (conflictMeta), keyString (keyGetMeta (specKey, "array"))); ret = -1; break; case WARNING: ELEKTRA_ADD_WARNINGF (143, parentKey, "%s has invalid number of members: %s. Expected: %s\n", keyName (key), keyString (conflictMeta), keyString (keyGetMeta (specKey, "array"))); break; case INFO: { const char * infoString = "%s has invalid number of member: %s. Expected: %s"; const size_t len = elektraStrLen (infoString) + elektraStrLen (keyName (key)) + MAX_CHARS_IN_LONG + keyGetValueSize (keyGetMeta (specKey, "array")) - 2; char * buffer = elektraMalloc (len); snprintf (buffer, len, infoString, keyName (key), keyString (conflictMeta), keyString (keyGetMeta (specKey, "array"))); elektraMetaArrayAdd (key, "logs/spec/info", buffer); elektraFree (buffer); } break; case IGNORE: break; } return ret; }
static void elektraResolveSystemXDGHelper (char ** filename, const char * path, const char * result) { size_t configDirSize = elektraStrLen (result); size_t pathSize = elektraStrLen (path); size_t filenameSize = configDirSize + pathSize + sizeof ("/") + 1; elektraRealloc ((void **) filename, filenameSize); strcpy (*filename, result); strcat (*filename, "/"); strcat (*filename, path); }
static void elektraResolveSystemXDGHelper (resolverHandle * p, const char * result) { size_t configDirSize = elektraStrLen (result); size_t pathSize = elektraStrLen (p->path); size_t filenameSize = configDirSize + pathSize + sizeof ("/") + 1; elektraRealloc ((void *)&p->filename, filenameSize); strcpy (p->filename, result); strcat (p->filename, "/"); strcat (p->filename, p->path); }
static int elektraResolveSystemPasswd (ElektraResolved * handle, Key * warningsKey) { char * dir = elektraResolvePasswd (warningsKey); if (!dir) return -1; size_t filenameSize = elektraStrLen (dir) + elektraStrLen (handle->relPath) - 1; char * resolved = elektraMalloc (filenameSize); snprintf (resolved, filenameSize, "%s/%s", dir, handle->relPath + 2); elektraFree (dir); handle->fullPath = resolved; return 0; }
static void elektraResolveFinishByDirname (ElektraResolved * handle, ElektraResolveTempfile tmpDir) { size_t filenameSize = elektraStrLen (handle->relPath) + elektraStrLen (handle->dirname); char * filename = elektraMalloc (filenameSize); strcpy (filename, handle->dirname); if (handle->relPath[0] != '/') { strcat (filename, "/"); } strcat (filename, handle->relPath); elektraFree (handle->dirname); handle->fullPath = filename; elektraResolveFinishByFilename (handle, tmpDir); }
static void test_keyGetString (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; KeySet * ks = metaTestKeySet (); const char * name = "user/tests/storage/specialkey"; const char * value = "special value"; size_t realValueSize = elektraStrLen (value); Key * key = keyNew (name, KEY_VALUE, value, KEY_END); ksAppendKey (ks, key); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); Key * found = ksLookupByName (ks, name, 0); succeed_if (found, "did not find key"); ssize_t apiValueSize = keyGetValueSize (found); char * apiString = elektraMalloc (apiValueSize); succeed_if (keyGetString (found, apiString, apiValueSize) == (ssize_t) realValueSize, "Key string has wrong size"); succeed_if (elektraStrNCmp (value, apiString, realValueSize) == 0, "Key string value is wrong"); elektraFree (apiString); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
static void setSubOrderNumber(Key *key, const char *oldOrder) { char *lastIndexPtr = NULL; char *newOrder = elektraMalloc(elektraStrLen(oldOrder)+ELEKTRA_MAX_ARRAY_SIZE); if ((lastIndexPtr = strrchr(oldOrder, '/'))) { kdb_long_long_t subIndex = 0; char *ptr = lastIndexPtr; ++ptr; //skip / ++ptr; //skip # while (*ptr == '_') { ++ptr; } elektraReadArrayNumber(ptr, &subIndex); ++subIndex; int len = (lastIndexPtr+1) - oldOrder; char buffer[ELEKTRA_MAX_ARRAY_SIZE]; elektraWriteArrayNumber(buffer, subIndex); sprintf(newOrder, "%.*s%s", len, oldOrder, buffer); } else { sprintf(newOrder, "%s/#1", oldOrder); } keySetMeta(key, "order", newOrder); elektraFree(newOrder); }
static char *parseLine(char *origLine, char delim, unsigned long offset, Key *parentKey, unsigned long lineNr) { char *line = (origLine + offset); if(*line == '\0') return NULL; char *ptr = strchr(line, delim); if(ptr == NULL) { ssize_t len = elektraStrLen(line); if(line[len-2] == '\n') { line[len-2] = '\0'; } else if(line[len-1] == '\0') { ELEKTRA_ADD_WARNINGF(136, parentKey, "Unexpected end of line(%lu) , expected \\n, got \\0 \n %s\n", lineNr, origLine); } else if(line[len-2] == '\r') { ELEKTRA_ADD_WARNINGF(136, parentKey, "Unexpected end of line(%lu) , expected \\n, found \\r \n %s\n", lineNr, origLine); line[len-2] = '\0'; } else { ELEKTRA_ADD_WARNINGF(136, parentKey, "Unexpected end of line(%lu) , expected \\n, but got 0x%x \n %s\n", lineNr, line[len-2], origLine); } } else { *ptr = '\0'; } return line; }
char * elektraMetaArrayToString (Key * key, const char * metaName, const char * delim) { char * result = NULL; Key * lookupElem = keyDup (keyGetMeta (key, metaName)); keyAddBaseName (lookupElem, "#0"); Key * elem = (Key *)keyGetMeta (key, keyName (lookupElem)); if (elem != NULL) { elektraRealloc ((void **)&result, keyGetValueSize (elem)); snprintf (result, keyGetValueSize (elem), "%s", keyString (elem)); } elektraArrayIncName (lookupElem); elem = (Key *)keyGetMeta (key, keyName (lookupElem)); while (elem != NULL) { elektraRealloc ((void **)&result, elektraStrLen (result) + keyGetValueSize (elem) + 1); // String (incl. +2 times \0) + delimiter + whitespace strcat (result, delim); strcat (result, keyString (elem)); elektraArrayIncName (lookupElem); elem = (Key *)keyGetMeta (key, keyName (lookupElem)); } keyDel (lookupElem); return result; }
/** * @brief Set a formatted string * * @param key the key to set the string value * @param format NULL-terminated text format string * @param ... more arguments * * @return the size of the string as set (with including 0) */ ssize_t keySetStringF (Key * key, const char * format, ...) { va_list arg_list; keySetMeta (key, "binary", 0); va_start (arg_list, format); char * p = elektraVFormat (format, arg_list); va_end (arg_list); if (!p) { return -1; } if (key->data.c) { elektraFree (key->data.c); } key->data.c = p; key->dataSize = elektraStrLen (key->data.c); set_bit (key->flags, KEY_FLAG_SYNC); return key->dataSize; }
static int elektraResolveSystemBuildin (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey) { size_t filenameSize = sizeof (KDB_DB_SYSTEM) + elektraStrLen (handle->relPath) + sizeof ("/"); char * resolved = NULL; if (KDB_DB_SYSTEM[0] == '~') { char * resolvedPath = elektraMalloc (filenameSize); strcpy (resolvedPath, KDB_DB_SYSTEM); strcat (resolvedPath, "/"); strcat (resolvedPath, handle->relPath); char * oldPath = handle->relPath; handle->relPath = resolvedPath; elektraResolveSystemPasswd (handle, warningsKey); elektraFree (resolvedPath); handle->relPath = oldPath; } else { resolved = elektraMalloc (filenameSize); strcpy (resolved, KDB_DB_SYSTEM); strcat (resolved, "/"); strcat (resolved, handle->relPath); handle->fullPath = resolved; } elektraResolveFinishByFilename (handle, tmpDir); return 1; }
// elektra wildcard syntax to fnmatch syntax static char * keyNameToMatchingString (const Key * key) { uint8_t arrayCount = 0; char * name = strchr (keyName (key), '/'); if (!name) return elektraStrDup (keyName (key)); for (char * ptr = name; *ptr != '\0'; ++ptr) if (*ptr == '#') ++arrayCount; char * pattern = elektraMalloc (elektraStrLen (name) + arrayCount); char * dst = pattern; for (char * src = (name + 1); *src != '\0'; ++src) { if (*src == '_' && *(src - 1) == '/' && (*(src + 1) == '/' || *(src + 1) == '\0')) { *dst++ = '*'; } else if (*src == '#' && *(src - 1) == '/' && (*(src + 1) == '/' || *(src + 1) == '\0')) { *dst++ = '#'; *dst++ = '*'; } else { *dst++ = *src; } } *dst = '\0'; return pattern; }
/** * @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; }
/** * Calculates number of bytes needed to store basename of @p key. * * Key names that have only root names (e.g. @c "system" or @c "user" * or @c "user:domain" ) does not have basenames, thus the function will * return 1 bytes to store "". * * Basenames are denoted as: * - @c system/some/thing/basename -> @c basename * - @c user:domain/some/thing/base\\/name > @c base\\/name * * @param key the key object to work with * @return size in bytes of @p key's basename including ending NULL * @see keyBaseName(), keyGetBaseName() * @see keyName(), keyGetName(), keySetName() * @ingroup keyname */ ssize_t keyGetBaseNameSize (const Key * key) { const char * baseName = keyBaseName (key); if (!baseName) return -1; return elektraStrLen (baseName); }
static void appendToKey (Key * key, const char * line) { char * buffer; size_t len = keyGetValueSize (key) + elektraStrLen (line) - 1; buffer = elektraMalloc (len); snprintf (buffer, len, "%s%s", keyString (key), line); keySetString (key, buffer); elektraFree (buffer); }
/** * @internal * Setup ZeroMq for receiving notifications. * * @param data plugin data containing context, socket, etc. */ void elektraZeroMqRecvSetup (ElektraZeroMqRecvPluginData * data) { // create zmq context if (!data->zmqContext) { data->zmqContext = zmq_ctx_new (); if (data->zmqContext == NULL) { ELEKTRA_LOG_WARNING ("zmq_ctx_new failed %s", zmq_strerror (zmq_errno ())); return; } } // create publish socket if (!data->zmqSubscriber) { data->zmqSubscriber = zmq_socket (data->zmqContext, ZMQ_SUB); if (data->zmqSubscriber == NULL) { ELEKTRA_LOG_WARNING ("zmq_socket failed %s", zmq_strerror (zmq_errno ())); zmq_close (data->zmqSubscriber); return; } // subscribe to notifications char * keyCommitType = "Commit"; if (zmq_setsockopt (data->zmqSubscriber, ZMQ_SUBSCRIBE, keyCommitType, elektraStrLen (keyCommitType)) != 0) { ELEKTRA_LOG_WARNING ("failed to subscribe to %s messages", keyCommitType); } // connect to endpoint int result = zmq_connect (data->zmqSubscriber, data->endpoint); if (result != 0) { ELEKTRA_LOG_WARNING ("zmq_connect error: %s\n", zmq_strerror (zmq_errno ())); zmq_close (data->zmqSubscriber); data->zmqSubscriber = NULL; return; } } if (!data->zmqAdapter) { // attach ZeroMq adater and wait for socket to be writable data->zmqAdapter = elektraIoAdapterZeroMqAttach (data->zmqSubscriber, data->ioBinding, ELEKTRA_IO_ADAPTER_ZEROMQCB_READ, zeroMqRecvSocketReadable, data); if (!data->zmqAdapter) { ELEKTRA_LOG_WARNING ("could not attach zmq adapter"); zmq_close (data->zmqSubscriber); data->zmqSubscriber = NULL; return; } } }
/** * 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; }
/** * Set the value for @p key as @p newStringValue. * * The function will allocate and save a private copy of @p newStringValue, so * the parameter can be freed after the call. * * String values will be saved in backend storage, when kdbSetKey() will be * called, in UTF-8 universal encoding, regardless of the program's current * encoding, when iconv plugin is present. * * @note The type will be set to KEY_TYPE_STRING. * When the type of the key is already a string type it won't be changed. * * @param key the key to set the string value * @param newStringValue NULL-terminated text string to be set as @p key's * value * @return the number of bytes actually saved in private struct including final * NULL * @retval 1 if newStringValue is a NULL pointer, this will make the * string empty (string only containing null termination) * @retval -1 if key is a NULL pointer * @see keyGetString(), keyValue(), keyString() * @ingroup keyvalue */ ssize_t keySetString(Key *key, const char *newStringValue) { ssize_t ret=0; if (!key) return -1; keySetMeta (key, "binary", 0); if (!newStringValue || newStringValue[0] == '\0') ret=keySetRaw(key,0,0); else ret=keySetRaw(key,newStringValue,elektraStrLen(newStringValue)); return ret; }
/**Copy string into new allocated memory. * * You need to free the memory yourself. * * @note that size is determined at runtime. * So if you have a size information, don't use * that function. * * @param s the null-terminated string to duplicate * * @ingroup internal * @return 0 if out of memory, a pointer otherwise * @pre s must be a c-string. * @see elektraFree * @see elektraStrLen * @see elektraStrNDup */ char * elektraStrDup (const char * s) { void * tmp = 0; size_t l = 0; ELEKTRA_ASSERT (s, "Tried to duplicate null pointer"); l = elektraStrLen (s); ELEKTRA_ASSERT (l, "Size of string to duplicate is zero"); tmp = elektraMalloc (l); if (tmp) memcpy (tmp, s, l); return tmp; }
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; }
/** Appends a comment to key found in line. * * Comments are marked with number signs, also called pound sign (#). * * White spaces are space and tab. * Lines can not start with blank or tab. * Blank lines are allowed and preserved in oomments * Trailing white spaces are allowed. * Only one host entry per line is allowed. * * * * @param line Will be closed with \0 where the comment begins * @return 0 when the caller should go on * @return 1 when the caller should continue (with next iteration) */ int elektraHostsAppendComment (char *comment, char *line) { size_t i; size_t s = elektraStrLen(line); size_t c = elektraStrLen(comment); char *endline; if (line[0] == '\n') { strncat (comment, "\n", HOSTS_KDB_BUFFER_SIZE-c-1); return 1; /* Empty line, so go on.. */ } if (line[0] == '#') { strncat (comment, line+1, HOSTS_KDB_BUFFER_SIZE-c-2); return 1; /* Complete line is comment, so go on.. */ } for (i=0; i<s; i++) { if (line [i] == '#') /* comment found */ { /* Remove the endline, might be not there * if size limit of fgets hit or at end of file */ endline = strrchr (line, '\n'); if (endline) *endline = '\0'; /* Copy the comment */ strncat (comment, line+i+1, HOSTS_KDB_BUFFER_SIZE-c-s-2); line[i] = '\0'; return 0; /* There should be a key here */ } } return 0; /* No # found */ }
static void test_elektraStrLen (void) { char charSeq[5]; printf ("Test elektraStrLen\n"); for (int i = 1; i < 255; ++i) { charSeq[0] = '\33'; charSeq[1] = 'a'; charSeq[2] = i; // 1..254 charSeq[3] = 256 - i; // 255..2 charSeq[4] = '\0'; // printf ("%s %d %d\n", charSeq, elektraStrLen (charSeq), strlen(charSeq)); succeed_if (elektraStrLen ((char *)charSeq) == 5, "could not deduce correct multichar sequence length"); } }
/** * Create subscriber socket for tests. * @internal * * @param subscribeFilter filter for subscriptions * @return new socket */ static void * createTestSocket (char * subscribeFilter) { // leave the system some time before binding again usleep (TIME_HOLDOFF); void * subSocket = zmq_socket (context, ZMQ_SUB); int result = zmq_bind (subSocket, TEST_ENDPOINT); if (result != 0) { yield_error ("zmq_bind failed"); printf ("zmq error was: %s\n", zmq_strerror (zmq_errno ())); exit (-1); } if (subscribeFilter != NULL) { exit_if_fail (zmq_setsockopt (subSocket, ZMQ_SUBSCRIBE, subscribeFilter, elektraStrLen (subscribeFilter)) == 0, "subscribe failed"); // subscribe to all messages } return subSocket; }
/** * Bytes needed to store the key name including user domain and ending NULL. * * @param key the key object to work with * @return number of bytes needed to store key name including user domain * @retval 1 on empty name * @retval -1 on NULL pointer * @see keyGetFullName(), keyGetNameSize() * @ingroup keyname */ ssize_t keyGetFullNameSize (const Key * key) { size_t returnedSize = 0; if (!key) return -1; if (!key->key) return 1; returnedSize = elektraStrLen (key->key); if (keyNameIsUser (key->key) && keyGetMeta (key, "owner")) returnedSize += keyGetOwnerSize (key); /* After 2 elektraStrLen() calls looks like we counted one more NULL. But we need this byte count because a full key name has an additional ':' char. */ return returnedSize; }
/* * Appends a line to the MetaKey of the supplied Key * If no MetaKey with the given name exists yet, a new * one is created containing the supplied line. If * the MetaKey exists, the supplied line is added as * a new line to the value of the MetaKey (i.e. a newline * followed by the given line is appended to the metadata) * * @param target the Key whose MetaKey is to be modified * @param metaName the name of the MetaKey which is to be modified * @param line the line to be appended to the matadata * @return the new value size of the modified MetaKey * @retval -1 on NULL pointers or if a memory allocation error occurs * * @see keyGetValueSize(Key *key) * */ int elektraKeyAppendMetaLine (Key * target, const char * metaName, const char * line) { if (!target) return 0; if (!metaName) return 0; if (!line) return 0; if (!keyGetMeta (target, metaName)) { keySetMeta (target, metaName, line); return keyGetValueSize (keyGetMeta (target, metaName)); } const Key * existingMeta = keyGetMeta (target, metaName); char * buffer = elektraMalloc (keyGetValueSize (existingMeta) + strlen (line) + 1); if (!buffer) return 0; keyGetString (existingMeta, buffer, keyGetValueSize (existingMeta)); strcat (buffer, "\n"); strncat (buffer, line, elektraStrLen (line)); keySetMeta (target, metaName, buffer); elektraFree (buffer); return keyGetValueSize (keyGetMeta (target, metaName)); }
int keyIsBelow (const Key * key, const Key * check) { const char * keyname = 0; const char * checkname = 0; const char * ukeyname = 0; const char * ucheckname = 0; ssize_t keysize = 0; ssize_t checksize = 0; ssize_t ukeysize = 0; ssize_t uchecksize = 0; if (!key || !check) return -1; keyname = keyName (key); checkname = keyName (check); ukeyname = keyUnescapedName (key); ucheckname = keyUnescapedName (check); keysize = keyGetNameSize (key); checksize = keyGetNameSize (check); ukeysize = keyGetUnescapedNameSize (key); uchecksize = keyGetUnescapedNameSize (check); if (!strcmp (checkname, "/")) return 0; if (!strcmp (keyname, "/")) { if (checkname[0] == '/') return 1; if (strchr (checkname, '/')) return 1; } else if (checkname[0] == '/') { if (keyname[0] == '/') { if (!strncmp (keyname, checkname, keysize - 1)) { if (ucheckname[ukeysize - 1] == '\0' && uchecksize > ukeysize) { return 1; } } } else { size_t size = 0; char * ptr = (char *)keyname; ptr = keyNameGetOneLevel (ptr, &size); if (size == (size_t)keysize) { return 1; } keyname += size; keysize = elektraStrLen (keyname); ptr = strrchr (ukeyname, '\0'); ukeysize -= (ptr - ukeyname); if (!strncmp (keyname, checkname, keysize - 1)) { if (ucheckname[ukeysize - 1] == '\0' && uchecksize > ukeysize) { return 1; } } } } else if (keyname[0] == '/') { size_t size = 0; char * ptr = (char *)checkname; ptr = keyNameGetOneLevel (ptr, &size); if (size == (size_t)checksize) { return 0; } checkname += size; checksize = elektraStrLen (checkname); ptr = strrchr (ucheckname, '\0'); uchecksize -= (ptr - ucheckname); ucheckname = ptr; if (!strncmp (keyname, checkname, keysize - 1)) { if (ucheckname[ukeysize - 1] == '\0' && uchecksize > ukeysize) { return 1; } } } else if (!strncmp (keyname, checkname, keysize - 1)) { if ((ucheckname[ukeysize - 1] == '\0') && (uchecksize > ukeysize)) return 1; } return 0; }