/** * Generate a C-Style key and stream it. * * This keyset can be used to include as c-code for * applikations using elektra. * * @param key the key object to work with * @param stream the file pointer where to send the stream * @param options KDB_O_SHOWINDICES, KDB_O_IGNORE_COMMENT, KDB_O_SHOWINFO * @retval 1 on success * @ingroup stream */ int keyGenerate(const Key * key, FILE *stream, option_t options) { size_t s; char * str; size_t c; char * com; size_t n; char * nam; n = keyGetNameSize (key); if (n>1) { nam = (char*) elektraMalloc (n); if (nam == NULL) return -1; keyGetName (key, nam, n); fprintf(stream,"\tkeyNew (\"%s\"", nam); elektraFree (nam); } s = keyGetValueSize (key); if (s>1) { str = (char*) elektraMalloc (s); if (str == NULL) return -1; if (keyIsBinary(key)) keyGetBinary(key, str, s); else keyGetString (key, str, s); fprintf(stream,", KEY_VALUE, \"%s\"", str); elektraFree (str); } c = keyGetCommentSize (key); if (c>1) { com = (char*) elektraMalloc (c); if (com == NULL) return -1; keyGetComment (key, com, c); fprintf(stream,", KEY_COMMENT, \"%s\"", com); elektraFree (com); } if (! (keyGetMode(key) == 0664 || (keyGetMode(key) == 0775))) { fprintf(stream,", KEY_MODE, 0%3o", keyGetMode(key)); } fprintf(stream,", KEY_END)"); if (options == 0) return 1; /* dummy to make icc happy */ return 1; }
void test_comment() { Key *key; char ret[10]; succeed_if (key = keyNew(0), "could not create new key"); succeed_if (strcmp (keyComment(key), "") == 0, "Empty comment problem"); succeed_if (keyGetCommentSize(key) == 1, "Empty comment size problem"); succeed_if (keyValue(keyGetMeta(key, "comment")) == 0, "No comment up to now"); succeed_if (keySetComment (key,0) == 1, "could not remove comment"); succeed_if (keyValue(keyGetMeta(key, "comment")) == 0, "There should be an no comment"); succeed_if (!strcmp (keyComment(key), ""), "Empty comment problem"); succeed_if (keyGetCommentSize(key) == 1, "Empty comment size problem"); succeed_if (keyGetComment(key, ret, 0) == -1, "Could not get empty comment"); succeed_if (keyGetComment(key, ret, 1) == 1, "Could not get empty comment"); succeed_if (ret[0] == 0, "keyGetComment did not return empty comment"); succeed_if (keySetComment (key,"") == 1, "could not remove comment"); succeed_if (keyValue(keyGetMeta(key, "comment")) == 0, "There should be an no comment"); succeed_if (!strcmp (keyComment(key), ""), "Empty comment problem"); succeed_if (keyGetCommentSize(key) == 1, "Empty comment size problem"); succeed_if (keyGetComment(key, ret, 0) == -1, "Could not get empty comment"); succeed_if (keyGetComment(key, ret, 1) == 1, "Could not get empty comment"); succeed_if (ret[0] == 0, "keyGetComment did not return empty comment"); succeed_if (keySetComment (key,"mycom") == sizeof("mycom"), "could not set comment"); succeed_if (!strcmp(keyValue(keyGetMeta(key, "comment")), "mycom"), "There should be my comment"); succeed_if (!strcmp (keyComment(key), "mycom"), "My comment problem"); succeed_if (keyGetCommentSize(key) == sizeof("mycom"), "My comment size problem"); succeed_if (keyGetComment(key, ret, 0) == -1, "Could not get my comment"); succeed_if (keyGetComment(key, ret, 1) == -1, "Could not get my comment"); succeed_if (keyGetComment(key, ret, sizeof("mycom")) == sizeof("mycom"), "Could not get my comment"); succeed_if (!strcmp (ret, "mycom"), "keyGetComment did not return my comment"); succeed_if (keyDel (key) == 0, "could not delete key"); }
/* * Processes the current <key> node from reader, converting from XML * to a Key object, and ksAppendKey() it to ks. * * See keyToStream() for an example of a <key> node. * * This function is completelly dependent on libxml. * * @param ks where to put the resulting reded key * @param context a prent key name, so a full name can be calculated * if the XML node for the current key only provides a basename * @param reader where to read from */ static int consumeKeyNode(KeySet *ks, const char *context, xmlTextReaderPtr reader) { xmlChar *nodeName=0; xmlChar *keyNodeName=0; xmlChar *buffer=0; xmlChar *privateContext=0; Key *newKey=0; int appended=0; /* printf("%s", KDB_SCHEMA_PATH); */ keyNodeName=xmlTextReaderName(reader); if (!strcmp((char *)keyNodeName,"key")) { mode_t isdir=0; int isbin=0; int end=0; newKey=keyNew(0); /* a <key> must have one of the following: - a "name" attribute, used as an absolute name overriding the context - a "basename" attribute, that will be appended to the current context - a "parent" plus "basename" attributes, both appended to current context - only a "parent", appended to current context */ buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"name"); if (buffer) { /* set absolute name */ keySetName(newKey,(char *)buffer); xmlFree(buffer); buffer=0; } else { /* logic for relative name calculation */ privateContext=xmlTextReaderGetAttribute(reader, (const xmlChar *)"parent"); buffer=xmlTextReaderGetAttribute(reader, (const xmlChar *)"basename"); if (context) keySetName(newKey,context); if (privateContext) keyAddName(newKey, (char *)privateContext); if (buffer) keyAddName(newKey,(char *)buffer); xmlFree(privateContext); privateContext=0; xmlFree(buffer); buffer=0; } /* test for a short value attribute, instead of <value> bellow */ buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"value"); if (buffer) { keySetRaw(newKey,buffer,elektraStrLen((char *)buffer)); xmlFree(buffer); buffer=0; } /* Parse UID */ buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"uid"); if (buffer) { int errsave = errno; char * endptr; long int uid = strtol ((const char *)buffer, &endptr, 10); errno = errsave; if (endptr != '\0' && *endptr == '\0') { keySetUID(newKey,uid); } xmlFree(buffer); buffer=0; } /* Parse GID */ buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"gid"); if (buffer) { int errsave = errno; char * endptr; long int gid = strtol ((const char *)buffer, &endptr, 10); errno = errsave; if (endptr != '\0' && *endptr == '\0') { keySetGID(newKey,gid); } xmlFree(buffer); buffer=0; } /* Parse mode permissions */ buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"mode"); int errsave = errno; if (buffer) keySetMode(newKey,strtol((char *)buffer,0,0)); errno = errsave; xmlFree(buffer); if (xmlTextReaderIsEmptyElement(reader)) { /* we have a <key ..../> element */ if (newKey && !appended) { ksAppendKey(ks,newKey); appended=1; end=1; } } buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"type"); if (buffer) { if (!strcmp((char *)buffer,"binary")) isbin = 1; else if (!strcmp((char *)buffer,"bin")) isbin = 1; } xmlFree(buffer); /* If "isdir" appears, everything different from "0", "false" or "no" marks it as a dir key */ buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"isdir"); if (!isdir && buffer) { if ( strcmp((char *)buffer,"0") && strcmp((char *)buffer,"false") && strcmp((char *)buffer,"no")) isdir = 1; else isdir = 0; } xmlFree(buffer); if (isdir) keySetDir(newKey); if (isbin) keySetMeta (newKey, "binary", ""); // TODO: should parse arbitrary attributes as metadata /* Parse everything else */ while (!end) { xmlTextReaderRead(reader); nodeName=xmlTextReaderName(reader); if (!strcmp((char *)nodeName,"value")) { if (xmlTextReaderIsEmptyElement(reader) || xmlTextReaderNodeType(reader)==15) { xmlFree (nodeName); continue; } xmlTextReaderRead(reader); buffer=xmlTextReaderValue(reader); if (buffer) { /* Key's value type was already set above */ if (keyIsBinary(newKey)) { /* TODO binary values char *unencoded=0; size_t unencodedSize; unencodedSize=elektraStrLen((char *)buffer)/2; unencoded=elektraMalloc(unencodedSize); unencodedSize=kdbbDecode((char *)buffer,unencoded); if (!unencodedSize) return -1; keySetRaw(newKey,unencoded,unencodedSize); elektraFree (unencoded); */ } else keySetRaw(newKey,buffer,elektraStrLen((char *)buffer)); } xmlFree(buffer); } else if (!strcmp((char *)nodeName,"comment")) { ssize_t commentSize=0; if (xmlTextReaderIsEmptyElement(reader) || xmlTextReaderNodeType(reader)==15) { xmlFree (nodeName); continue; } xmlTextReaderRead(reader); buffer=xmlTextReaderValue(reader); if ((commentSize=keyGetCommentSize(newKey)) > 1) { /*Multiple line comment*/ char *tmpComment=0; tmpComment=elektraMalloc(commentSize+ xmlStrlen(buffer)*sizeof(xmlChar)+1); if (tmpComment) { keyGetComment(newKey,tmpComment,commentSize); strcat(tmpComment,"\n"); strcat(tmpComment,(char *)buffer); keySetComment(newKey,tmpComment); elektraFree (tmpComment); tmpComment=0; } } else keySetComment(newKey,(char *)buffer); xmlFree(buffer); } else if (!strcmp((char *)nodeName,"key")) { /* Here we found </key> or a sub <key>. So include current key in the KeySet. */ if (newKey && !appended) { ksAppendKey(ks,newKey); appended=1; } if (xmlTextReaderNodeType(reader)==15) /* found a </key> */ end=1; else { /* found a sub <key> */ /* prepare the context (parent) */ consumeKeyNode(ks,newKey->key,reader); } } xmlFree (nodeName); } if (privateContext) xmlFree(privateContext); /* seems like we forgot the key, lets delete it */ if (newKey && !appended) { keyDel (newKey); appended=1; } } xmlFree(keyNodeName); return 0; }
/** * Output every information of a single key depending on options. * * The format is not very strict and only intend to be read * by human eyes for debugging purposes. Don't rely on the * format in your applications. * * @param k the key object to work with * @param stream the file pointer where to send the stream * @param options see text above * @see ksOutput() * @retval 1 on success * @retval -1 on allocation errors * @ingroup stream */ int keyOutput (const Key * k, FILE *stream, option_t options) { time_t t; size_t s; char * tmc; char * str; size_t c; char * com; size_t n; char * nam; n = keyGetNameSize (k); if (n>1) { nam = (char*) elektraMalloc (n); if (nam == NULL) return -1; keyGetName (k, nam, n); fprintf(stream,"Name[%d]: %s : ", (int)n, nam); elektraFree (nam); } s = keyGetValueSize (k); if (options & KEY_VALUE && s>1) { str = (char*) elektraMalloc (s); if (str == NULL) return -1; if (keyIsBinary(k)) { /* char * bin; bin = (char*) elektraMalloc (s*3+1); keyGetBinary(k, str, s); kdbbEncode (str, s, bin); elektraFree (bin); */ keyGetBinary (k, str, s); fprintf(stream,"Binary[%d]: %s : ", (int)s, str); } else { keyGetString (k, str, s); fprintf(stream,"String[%d]: %s : ", (int)s, str); } elektraFree (str); } c = keyGetCommentSize (k); if (options & KEY_COMMENT && c>1) { com = (char*) elektraMalloc (c); if (com == NULL) return -1; keyGetComment (k, com, c); fprintf(stream,"Comment[%d]: %s : ", (int)c, com); elektraFree (com); } if (options & KDB_O_SHOWMETA) fprintf(stream," : "); if (options & KEY_UID) fprintf(stream,"UID: %d : ", (int)keyGetUID (k)); if (options & KEY_GID) fprintf(stream,"GID: %d : ", (int)keyGetGID (k)); if (options & KEY_MODE) fprintf(stream,"Mode: %o : ", (int)keyGetMode (k)); if (options & KEY_ATIME) { t=keyGetATime(k); tmc = ctime (& t); tmc[24] = '\0'; fprintf(stream,"ATime: %s : ", tmc); } if (options & KEY_MTIME) { t=keyGetMTime(k); tmc = ctime (& t); tmc[24] = '\0'; fprintf(stream,"MTime: %s : ", tmc); } if (options & KEY_CTIME) { t=keyGetCTime(k); tmc = ctime (& t); tmc[24] = '\0'; fprintf(stream,"CTime: %s : ", tmc); } if (options & KDB_O_SHOWFLAGS) { if (!(options & KDB_O_SHOWMETA)) fprintf(stream, " "); fprintf (stream,"Flags: "); if (keyIsBinary(k)) fprintf(stream,"b"); if (keyIsString(k)) fprintf(stream,"s"); if (keyIsInactive(k)) fprintf(stream,"i"); if (keyNeedSync(k)) fprintf(stream,"s"); } fprintf(stream,"\n"); return 1; }