1 /***************************************************************************
2 keyhelpers.c - Methods for Key manipulation
4 begin : Mon Dec 29 2003
5 copyright : (C) 2003 by Avi Alkalay
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the BSD License (revised). *
14 ***************************************************************************/
20 #if DEBUG && HAVE_STDIO_H
37 #include "kdbprivate.h"
42 * Returns one level of the key name.
44 * This method is used to skip repeating '/' and to find escaping chars.
45 * Given @p keyName, this method returns a pointer to the next name level
46 * found and changes @p size to the number of bytes on this level name.
48 * This method is used by keySetName() to cleanup parameters
49 * before being accepted in the Key object.
52 // Lets define a key name with a lot of repeating '/' and escaped '/'
53 char *keyName="user////abc/def\/ghi////jkl///";
60 while (*(p=keyNameGetOneLevel(p+size,&size))) {
63 // copy what we found to a buffer, so we can NULL-terminate it
64 strncpy(buffer,p,size);
67 printf("Level %d name: \"%s\"\n",level,buffer);
70 * The above example will produce the following output:
75 Level 3 name: def\/ghi
79 * @param name the string that will be searched
80 * @param size the number of bytes of level name found in @p keyName until
81 * the next delimiter ('/')
82 * @return a pointer to the first char of the next level name, it will point to
86 char *keyNameGetOneLevel(const char *name, size_t *size) {
87 char *real=(char *)name;
92 /* skip all repeating '/' in the begining */
93 while (*real && *real == PATH_SEPARATOR) real++;
95 /* now see where this basename ends handling escaped chars with '\' */
96 while (real[cursor] && ! end) {
97 switch (real[cursor]) {
102 if (! escapeNext) end=1;
109 /* if a '/' stopped our loop, balance the counter */
120 * Gets number of bytes needed to store root name of a key name
122 * Possible root key names are @p system, @p user or @p "user:someuser" .
124 * @return number of bytes needed with ending NULL
125 * @param keyName the name of the key
126 * @see keyGetFullRootNameSize()
129 ssize_t keyNameGetFullRootNameSize(const char *keyName) {
131 int length=strlen(keyName);
133 if (!length) return 0;
139 user:someuser/key/name
140 user:some.user/key/name
145 end=strchr(keyName,PATH_SEPARATOR);
146 if (!end) /* Reached end of string. Root is entire key. */
147 end = (char *)keyName + length;
149 return end-keyName+1;
155 * Gets number of bytes needed to store root name of a key.
157 * Possible root key names are @p system or @p user .
158 * This method does not consider the user domain in @p user:username keys.
160 * @param key the key object to work with
161 * @return number of bytes needed with the ending NULL
162 * @see keyGetFullRootNameSize()
165 ssize_t keyGetRootNameSize(const Key *key) {
166 if (!key->key) return 0;
168 if (keyIsUser(key)) return sizeof("db");
169 else if (keyIsSystem(key)) return sizeof("file");
170 else return sizeof("memory");
176 * Copy to @p returned the root name of @p key.
179 * - root of @p system/some/key is @p system
180 * - root of @p user:denise/some/key is @p user
181 * - root of @p user/env/env1 is @p user
183 * Use keyGetFullRootName() to get also the user domain.
185 * @param key the key to extract root from
186 * @param returned a pre-allocated buffer to store the rootname
187 * @param maxSize size of the @p returned buffer
188 * @return number of bytes needed with ending NULL
189 * @see keyGetRootNameSize(), keyGetFullRootName()
192 ssize_t keyGetRootName(const Key *key, char *returned, size_t maxSize) {
196 /*errno=KDB_ERR_NOKEY;*/
200 if (!(size=keyGetRootNameSize(key))) {
201 /*errno=KDB_ERR_NOKEY;*/
205 if (maxSize < size) {
206 /*errno=KDB_ERR_TRUNC;*/
208 } else strncpy(returned,key->key,size-1);
209 returned[size-1]=0; /* null terminate it */
219 * Gets number of bytes needed to store root name of a key name without
223 * - root of @p system/some/key is @p system
224 * - root of @p user:denise/some/key is @p user
225 * - root of @p user/env/env1 is @p user
227 * @param keyName the name of the key
228 * @return number of bytes needed with ending NULL or -1 if @p keyName is
229 * not a valid name and @c errno is set to KDBErr::KDB_ERR_INVALIDKEY
230 * @see keyGetRootNameSize()
233 ssize_t keyNameGetRootNameSize(const char *keyName) {
234 int length=strlen(keyName);
236 if (!length) return 0;
245 user:someuser/key/name
252 if (keyNameIsUser(keyName)) return sizeof("db");
253 else if (keyNameIsSystem(keyName)) return sizeof("file");
254 else if (keyNameIsMemory(keyName)) return sizeof("memory");
256 /*errno=KDB_ERR_INVALIDKEY;*/
266 * Calculates number of bytes needed to store full root name of a key.
268 * Possible root key names are @p system, @p user or @p user:someuser.
269 * In contrast to keyGetRootNameSize(), this method considers the user
270 * domain part, and you should prefer this one.
272 * @param key the key object to work with
273 * @return number of bytes needed with ending NULL
274 * @see keyGetRootNameSize()
277 ssize_t keyGetFullRootNameSize(const Key *key) {
280 if (keyIsUser(key)) {
281 if (key->owner) size=kdbiStrLen(key->owner);
283 return size+sizeof("db");
285 return keyNameGetRootNameSize(key->key);
291 * Copy to @p returned the full root name of the key.
294 * - root of @p system/some/key is @p system
295 * - root of @p user:denise/some/key is @p user:denise
296 * - root of @p user/env/env1 is @p user:$USER
298 * This method is more robust then keyGetRootName()
300 * @param key the key to extract root from
301 * @param returned a pre-allocated buffer to store the rootname
302 * @param maxSize size of the @p returned buffer
303 * @return number of bytes written to @p returned including ending NULL
304 * @see keyGetFullRootNameSize(), keyGetRootName()
307 ssize_t keyGetFullRootName(const Key *key, char *returned, size_t maxSize) {
313 /*errno=KDB_ERR_NOKEY;*/
317 if (!(size=keyGetFullRootNameSize(key))) {
318 /*errno=KDB_ERR_NOKEY;*/
322 if (maxSize < size) {
323 /*errno=KDB_ERR_TRUNC;*/
327 rootSize = keyGetRootNameSize(key)-1;
328 strncpy(returned,key->key, rootSize); /* copy "user" or "system" */
329 if (keyIsUser(key)) {
330 cursor = returned + rootSize;
331 *cursor = ':'; cursor++;
334 strncpy (cursor, key->owner, size - rootSize - 1); /* -1 for : */
337 returned[rootSize]=0;
349 * Get the number of bytes needed to store this key's parent name without
350 * user domain, and with the ending NULL.
352 * @param key the key object to work with
353 * @see keyGetParentName() for example
356 ssize_t keyGetParentNameSize(const Key *key) {
357 char *parentNameEnd=0;
362 /*errno=KDB_ERR_NOKEY;*/
368 user/parent/base (size=sizeof("user/parent"))
369 user/parent/base/ (size=sizeof("user/parent"))
370 user/parent/base\/name (size=sizeof("user/parent"))
377 /* iterate over level names */
378 while (*(p=keyNameGetOneLevel(p+size,&size))) parentNameEnd=p;
380 /* handle NULL or root key ("user" or "system") */
381 if (!parentNameEnd || parentNameEnd==key->key) return 0;
383 /* at this point, parentNameEnd points to the first char of the basename */
384 /* example: it points to the 'b' of "user/key/basename" */
386 /* the delta is the size we want */
387 return parentNameEnd - key->key;
393 * Copy this key's parent name (without owner) into a pre-allocated buffer.
397 Key *key=keyNew("system/parent/base",KEY_SWITCH_END);
401 parentSize=keyGetParentNameSize(key);
402 parentName=malloc(parentSize);
403 keyGetParentName(key,parentName,parentSize);
404 // work with parentName
407 * @see keyGetParentNameSize()
408 * @param key the key object to work with
409 * @param returnedParent pre-allocated buffer to copy parent name to
410 * @param maxSize number of bytes pre-allocated
411 * @return number of bytes copied including ending NULL
414 ssize_t keyGetParentName(const Key *key, char *returnedParent, size_t maxSize) {
417 parentSize=keyGetParentNameSize(key);
419 if (parentSize > maxSize) {
420 /*errno=KDB_ERR_TRUNC;*/
422 } else strncpy(returnedParent,key->key,parentSize);
424 returnedParent[parentSize-1]=0; /* ending NULL */
433 * Return the namespace of a key name.
435 * Currently valid namespaces are KeyNamespace::KEY_NS_SYSTEM and KeyNamespace::KEY_NS_USER.
437 * @param keyName the name to deduce the namespace from
438 * @return KeyNamespace::KEY_NS_SYSTEM, KeyNamespace::KEY_NS_USER
439 * @return 0 for no valid namespace found (key has no name)
440 * @see keyGetNamespace(), keyIsUser(), keyIsSystem()
445 int keyNameGetNamespace(const char *keyName)
447 if (keyNameIsSystem(keyName)) return KEY_NS_SYSTEM;
448 if (keyNameIsUser(keyName)) return KEY_NS_USER;
449 if (keyNameIsMemory(keyName)) return KEY_NS_MEMORY;
456 * Return the namespace of a key
458 * Currently valid namespaces are KeyNamespace::KEY_NS_SYSTEM and KeyNamespace::KEY_NS_USER.
460 * @param key the key object to work with
462 * @see keyIsUser(), keyIsSystem()
466 int keyGetNamespace(const Key *key)
468 if (keyIsUser (key)) return KEY_NS_USER;
469 else if (keyIsSystem (key)) return KEY_NS_SYSTEM;
470 else if (keyIsMemory(key)) return KEY_NS_MEMORY;
476 * Check whether a key name is under the @p system namespace or not
478 * @return 1 if string begins with @p system , 0 otherwise
479 * @param keyName the name of a key
480 * @see keyIsSystem(), keyIsUser(), keyNameIsUser()
484 int keyNameIsSystem(const char *keyName)
486 if (!strncmp("file",keyName,sizeof("file")-1)) return 1;
492 * Check whether a key name is under the @p user namespace or not
494 * @return 1 if string begins with @p user, 0 otherwise
495 * @param keyName the name of a key
496 * @see keyIsSystem(), keyIsUser(), keyNameIsSystem()
500 int keyNameIsUser(const char *keyName)
502 if (!strncmp("db",keyName,sizeof("db")-1)) return 1;
508 * Check whether a key name is under the @p memory namespace or not
510 * @return 1 if string begins with @p user, 0 otherwise
511 * @param keyName the name of a key
512 * @see keyIsSystem(), keyIsUser(), keyNameIsSystem()
516 int keyNameIsMemory(const char *keyName)
518 if (!strncmp("memory",keyName,sizeof("memory")-1)) return 1;
523 /*********************************************************************
524 * Data constructors (protected) *
525 *********************************************************************/
526 int keyInit(Key *key)
528 memset(key,0,sizeof(Key));
530 key->type = KEY_TYPE_UNDEFINED;
532 key->uid = (uid_t)-1;
533 key->gid = (gid_t)-1;
535 key->mode = KEY_DEF_MODE;