From 2f280d857c46e7daa1866311a43ee8cd4437be3b Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 3 Nov 2017 10:13:09 -0700 Subject: [PATCH 1/6] test/treeobj: fix memory leaks Fix mem leaks in the test code spotted by @grondo with valgrind. --- src/common/libkvs/test/treeobj.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/libkvs/test/treeobj.c b/src/common/libkvs/test/treeobj.c index 5c19f46824d1..65fde79b6b82 100644 --- a/src/common/libkvs/test/treeobj.c +++ b/src/common/libkvs/test/treeobj.c @@ -23,6 +23,7 @@ json_t *create_large_dir (void) json_decref (dir); return NULL; } + json_decref (ent); } return dir; } @@ -640,8 +641,10 @@ void test_corner_cases (void) ok (treeobj_get_count (val) < 0 && errno == EINVAL, "treeobj_get_count detects invalid type"); - ok (treeobj_decode (treeobj_encode (val)) == NULL && errno == EPROTO, + char *s = treeobj_encode (val); + ok (treeobj_decode (s) == NULL && errno == EPROTO, "treeobj_decode returns EPROTO on bad treeobj"); + free (s); json_decref (val); From f9e4b7707b2a274b0f65431557427ba55c36e9b8 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 1 Nov 2017 14:27:16 -0700 Subject: [PATCH 2/6] libkvs/treeobj: use const on json_t where approp Add a new internal function treeobj_peek() which accepts a const json_t * input parameter, and produces a const json_t *data output parameter. Internally, treeobj_peek() calls json_unpack(), which required the const on the input parameter to be cast away - safe since, while we use the "o" format specifier to extract the data object, we put a const on it before we return it to internal callers. The treeobj_peek() function allows many functions to accept const json_t * where before they did not. There was one other place where a const had to be cast away. In treeobj_validate(), which now calls treeobj_peek() to access the const data member, the data const had to be dropped while iterating over its directory entries with json_object_foreach(), since json_object_iter() does not accept a const object. I'm hopeful that the iterator does not actually modify the object as it seems self-contained, and this is just an oversight in the jansson API design. As discussed in #1264 --- src/common/libkvs/treeobj.c | 74 ++++++++++++++++++++++++++----------- src/common/libkvs/treeobj.h | 24 ++++++------ 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/common/libkvs/treeobj.c b/src/common/libkvs/treeobj.c index f5531b98eef1..1a3d5eac623e 100644 --- a/src/common/libkvs/treeobj.c +++ b/src/common/libkvs/treeobj.c @@ -57,12 +57,38 @@ static int treeobj_unpack (json_t *obj, const char **typep, json_t **datap) return 0; } -int treeobj_validate (json_t *obj) +static int treeobj_peek (const json_t *obj, const char **typep, + const json_t **datap) { - json_t *o, *data; + json_t *data; + int version; const char *type; - if (treeobj_unpack (obj, &type, &data) < 0) + /* N.B. it should be safe to cast away const on 'obj' as long as 'data' + * parameter is not modified. We make 'data' const to ensure that. + */ + if (!obj || json_unpack ((json_t *)obj, "{s:i s:s s:o !}", + "ver", &version, + "type", &type, + "data", &data) < 0 + || version != treeobj_version) { + errno = EINVAL; + return -1; + } + if (typep) + *typep = type; + if (datap) + *datap = data; + return 0; +} + +int treeobj_validate (const json_t *obj) +{ + const json_t *o; + const json_t *data; + const char *type; + + if (treeobj_peek (obj, &type, &data) < 0) goto inval; if (!strcmp (type, "valref") || !strcmp (type, "dirref")) { int i, len; @@ -80,7 +106,10 @@ int treeobj_validate (json_t *obj) const char *key; if (!json_is_object (data)) goto inval; - json_object_foreach (data, key, o) { + /* N.B. it should be safe to cast away const on 'data' as long as + * 'o' is not modified. We make 'o' const to ensure that. + */ + json_object_foreach ((json_t *)data, key, o) { if (treeobj_validate (o) < 0) goto inval; } @@ -102,39 +131,39 @@ int treeobj_validate (json_t *obj) return -1; } -const char *treeobj_get_type (json_t *obj) +const char *treeobj_get_type (const json_t *obj) { const char *type; - if (treeobj_unpack (obj, &type, NULL) < 0) + if (!obj || treeobj_peek (obj, &type, NULL) < 0) return NULL; return type; } -bool treeobj_is_symlink (json_t *obj) +bool treeobj_is_symlink (const json_t *obj) { const char *type = treeobj_get_type (obj); return type && !strcmp (type, "symlink"); } -bool treeobj_is_val (json_t *obj) +bool treeobj_is_val (const json_t *obj) { const char *type = treeobj_get_type (obj); return type && !strcmp (type, "val"); } -bool treeobj_is_valref (json_t *obj) +bool treeobj_is_valref (const json_t *obj) { const char *type = treeobj_get_type (obj); return type && !strcmp (type, "valref"); } -bool treeobj_is_dir (json_t *obj) +bool treeobj_is_dir (const json_t *obj) { const char *type = treeobj_get_type (obj); return type && !strcmp (type, "dir"); } -bool treeobj_is_dirref (json_t *obj) +bool treeobj_is_dirref (const json_t *obj) { const char *type = treeobj_get_type (obj); return type && !strcmp (type, "dirref"); @@ -148,14 +177,14 @@ json_t *treeobj_get_data (json_t *obj) return data; } -int treeobj_decode_val (json_t *obj, void **dp, int *lp) +int treeobj_decode_val (const json_t *obj, void **dp, int *lp) { const char *type, *xdatastr; - json_t *xdata; + const json_t *xdata; int buflen, len, xlen; char *data; - if (treeobj_unpack (obj, &type, &xdata) < 0 + if (treeobj_peek (obj, &type, &xdata) < 0 || strcmp (type, "val") != 0) { errno = EINVAL; return -1; @@ -187,13 +216,13 @@ int treeobj_decode_val (json_t *obj, void **dp, int *lp) return 0; } -int treeobj_get_count (json_t *obj) +int treeobj_get_count (const json_t *obj) { - json_t *data; + const json_t *data; const char *type; int count = -1; - if (treeobj_unpack (obj, &type, &data) < 0) + if (treeobj_peek (obj, &type, &data) < 0) goto done; if (!strcmp (type, "valref") || !strcmp (type, "dirref")) { count = json_array_size (data); @@ -302,7 +331,7 @@ json_t *treeobj_copy (json_t *obj) return cpy; } -json_t *treeobj_deep_copy (json_t *obj) +json_t *treeobj_deep_copy (const json_t *obj) { return json_deep_copy (obj); } @@ -334,12 +363,13 @@ int treeobj_append_blobref (json_t *obj, const char *blobref) return rc; } -const char *treeobj_get_blobref (json_t *obj, int index) +const char *treeobj_get_blobref (const json_t *obj, int index) { - json_t *data, *o; + const json_t *data; + json_t *o; const char *type, *blobref = NULL; - if (treeobj_unpack (obj, &type, &data) < 0 + if (treeobj_peek (obj, &type, &data) < 0 || (strcmp (type, "dirref") != 0 && strcmp (type, "valref") != 0)) { errno = EINVAL; @@ -499,7 +529,7 @@ json_t *treeobj_decodeb (const char *buf, size_t buflen) return NULL; } -char *treeobj_encode (json_t *obj) +char *treeobj_encode (const json_t *obj) { return json_dumps (obj, JSON_COMPACT|JSON_SORT_KEYS); } diff --git a/src/common/libkvs/treeobj.h b/src/common/libkvs/treeobj.h index ba458fa661d1..290c23169e47 100644 --- a/src/common/libkvs/treeobj.h +++ b/src/common/libkvs/treeobj.h @@ -21,19 +21,19 @@ json_t *treeobj_create_dirref (const char *blobref); /* Validate treeobj, recursively. * Return 0 if valid, -1 with errno = EINVAL if invalid. */ -int treeobj_validate (json_t *obj); +int treeobj_validate (const json_t *obj); /* get type (RFC 11 defined strings or NULL on error with errno set). */ -const char *treeobj_get_type (json_t *obj); +const char *treeobj_get_type (const json_t *obj); /* Test for a particular type */ -bool treeobj_is_symlink (json_t *obj); -bool treeobj_is_val (json_t *obj); -bool treeobj_is_valref (json_t *obj); -bool treeobj_is_dir (json_t *obj); -bool treeobj_is_dirref (json_t *obj); +bool treeobj_is_symlink (const json_t *obj); +bool treeobj_is_val (const json_t *obj); +bool treeobj_is_valref (const json_t *obj); +bool treeobj_is_dir (const json_t *obj); +bool treeobj_is_dirref (const json_t *obj); /* get type-specific value. * For dirref/valref, this is an array of blobrefs. @@ -50,7 +50,7 @@ json_t *treeobj_get_data (json_t *obj); * If len > 0, data will be followed by an extra NULL byte in memory. * Caller must free returned data. */ -int treeobj_decode_val (json_t *obj, void **data, int *len); +int treeobj_decode_val (const json_t *obj, void **data, int *len); /* get type-specific count. * For dirref/valref, this is the number of blobrefs. @@ -58,7 +58,7 @@ int treeobj_decode_val (json_t *obj, void **data, int *len); * For symlink or val, this is 1. * Return count on success, -1 on error with errno = EINVAL. */ -int treeobj_get_count (json_t *obj); +int treeobj_get_count (const json_t *obj); /* get/add/remove directory entry * Get returns JSON object (owned by 'obj', do not destory), NULL on error. @@ -77,7 +77,7 @@ int treeobj_delete_entry (json_t *obj, const char *name); json_t *treeobj_copy (json_t *obj); /* Deep copy a treeobj */ -json_t *treeobj_deep_copy (json_t *obj); +json_t *treeobj_deep_copy (const json_t *obj); /* add blobref to dirref,valref object. * Return 0 on success, -1 on failure with errno set. @@ -87,7 +87,7 @@ int treeobj_append_blobref (json_t *obj, const char *blobref); /* get blobref entry at 'index'. * Return blobref on success, NULL on failure with errno set. */ -const char *treeobj_get_blobref (json_t *obj, int index); +const char *treeobj_get_blobref (const json_t *obj, int index); /* Create valref that refers to 'data', a blob of 'len' bytes using * 'hashtype' hash algorithm (e.g. "sha1"). If 'maxblob' > 0, split the @@ -102,7 +102,7 @@ json_t *treeobj_create_valref_buf (const char *hashtype, int maxblob, */ json_t *treeobj_decode (const char *buf); json_t *treeobj_decodeb (const char *buf, size_t buflen); -char *treeobj_encode (json_t *obj); +char *treeobj_encode (const json_t *obj); #endif /* !_FLUX_KVS_TREEOBJ_H */ From 2228d30645466d259afc91c0a9e52afc3fb43348 Mon Sep 17 00:00:00 2001 From: Albert Chu Date: Thu, 2 Nov 2017 15:49:13 -0700 Subject: [PATCH 3/6] modules/kvs/lookup: Refactor return val logic Refactor internal logic when returning values to callers. Do not return pointer to cache entries, as callers could mistakenly modify those entries. Always return a copy of those entries. --- src/modules/kvs/lookup.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/modules/kvs/lookup.c b/src/modules/kvs/lookup.c index a3a8e443fc08..573f61b5518e 100644 --- a/src/modules/kvs/lookup.c +++ b/src/modules/kvs/lookup.c @@ -823,7 +823,10 @@ bool lookup (lookup_t *lh) lh->errnum = ENOTRECOVERABLE; goto done; } - lh->val = json_incref (valtmp); + if (!(lh->val = treeobj_deep_copy (valtmp))) { + lh->errnum = errno; + goto done; + } } goto done; } @@ -844,7 +847,8 @@ bool lookup (lookup_t *lh) /* fallthrough */ case LOOKUP_STATE_VALUE: if ((lh->flags & FLUX_KVS_TREEOBJ)) { - lh->val = json_incref (lh->wdirent); + if (!(lh->val = treeobj_deep_copy (lh->wdirent))) + lh->errnum = errno; goto done; } @@ -886,7 +890,10 @@ bool lookup (lookup_t *lh) lh->errnum = ENOTRECOVERABLE; goto done; } - lh->val = json_incref (valtmp); + if (!(lh->val = treeobj_deep_copy (valtmp))) { + lh->errnum = errno; + goto done; + } } else if (treeobj_is_valref (lh->wdirent)) { bool stall; @@ -931,7 +938,10 @@ bool lookup (lookup_t *lh) lh->errnum = EISDIR; goto done; } - lh->val = json_incref (lh->wdirent); + if (!(lh->val = treeobj_deep_copy (lh->wdirent))) { + lh->errnum = errno; + goto done; + } } else if (treeobj_is_val (lh->wdirent)) { if ((lh->flags & FLUX_KVS_READLINK)) { lh->errnum = EINVAL; @@ -941,7 +951,10 @@ bool lookup (lookup_t *lh) lh->errnum = ENOTDIR; goto done; } - lh->val = json_incref (lh->wdirent); + if (!(lh->val = treeobj_deep_copy (lh->wdirent))) { + lh->errnum = errno; + goto done; + } } else if (treeobj_is_symlink (lh->wdirent)) { /* this should be "impossible" */ if (!(lh->flags & FLUX_KVS_READLINK)) { @@ -952,7 +965,10 @@ bool lookup (lookup_t *lh) lh->errnum = ENOTDIR; goto done; } - lh->val = json_incref (lh->wdirent); + if (!(lh->val = treeobj_deep_copy (lh->wdirent))) { + lh->errnum = errno; + goto done; + } } else { char *s = json_dumps (lh->wdirent, 0); flux_log (lh->h, LOG_ERR, "%s: corrupt dirent: %s", From 6ba26866e0c2c402ba5609124e179bf30fadbcf6 Mon Sep 17 00:00:00 2001 From: Albert Chu Date: Thu, 2 Nov 2017 15:36:16 -0700 Subject: [PATCH 4/6] common/libkvs/treeobj: Add treeobj_peek_entry() Add const version of treeobj_get_entry(), so users can use const treeobjs safely. Add unit tests appropriately. --- src/common/libkvs/test/treeobj.c | 29 +++++++++++++++++++++++++++++ src/common/libkvs/treeobj.c | 17 +++++++++++++++++ src/common/libkvs/treeobj.h | 6 ++++++ 3 files changed, 52 insertions(+) diff --git a/src/common/libkvs/test/treeobj.c b/src/common/libkvs/test/treeobj.c index 65fde79b6b82..bce989e8ee6a 100644 --- a/src/common/libkvs/test/treeobj.c +++ b/src/common/libkvs/test/treeobj.c @@ -357,6 +357,34 @@ void test_dir (void) json_decref (dir); } +void test_dir_peek (void) +{ + json_t *dir; + json_t *val = NULL; + const json_t *result; + + ok (treeobj_peek_entry (NULL, NULL) == NULL, + "treeobj_peek_entry fails on bad input"); + + /* create test value */ + val = treeobj_create_val ("foo", 4); + if (!val) + BAIL_OUT ("can't continue without test values"); + + ok ((dir = treeobj_create_dir ()) != NULL, + "treeobj_create_dir works"); + + ok (treeobj_insert_entry (dir, "foo", val) == 0, + "treeobj_insert_entry works"); + ok ((result = treeobj_peek_entry (dir, "foo")) != NULL, + "treeobj_peek_entry works"); + ok (result == val, + "treeobj_peek_entry returns correct pointer"); + + json_decref (val); + json_decref (dir); +} + void test_copy (void) { json_t *val, *symlink, *dirref, *valref, *dir; @@ -715,6 +743,7 @@ int main(int argc, char** argv) test_val (); test_dirref (); test_dir (); + test_dir_peek (); test_copy (); test_deep_copy (); test_symlink (); diff --git a/src/common/libkvs/treeobj.c b/src/common/libkvs/treeobj.c index 1a3d5eac623e..e5bdb4d0f8e3 100644 --- a/src/common/libkvs/treeobj.c +++ b/src/common/libkvs/treeobj.c @@ -292,6 +292,23 @@ int treeobj_insert_entry (json_t *obj, const char *name, json_t *obj2) return 0; } +const json_t *treeobj_peek_entry (const json_t *obj, const char *name) +{ + const char *type; + const json_t *data, *obj2; + + if (treeobj_peek (obj, &type, &data) < 0 + || strcmp (type, "dir") != 0) { + errno = EINVAL; + return NULL; + } + if (!(obj2 = json_object_get (data, name))) { + errno = ENOENT; + return NULL; + } + return obj2; +} + json_t *treeobj_copy (json_t *obj) { json_t *data; diff --git a/src/common/libkvs/treeobj.h b/src/common/libkvs/treeobj.h index 290c23169e47..e58d5039bcbc 100644 --- a/src/common/libkvs/treeobj.h +++ b/src/common/libkvs/treeobj.h @@ -69,6 +69,12 @@ json_t *treeobj_get_entry (json_t *obj, const char *name); int treeobj_insert_entry (json_t *obj, const char *name, json_t *obj2); int treeobj_delete_entry (json_t *obj, const char *name); +/* peek directory entry + * identical to treeobj_get_entry(), but is a const equivalent. Good + * to use when modifications will not occur. + */ +const json_t *treeobj_peek_entry (const json_t *obj, const char *name); + /* Shallow copy a treeobj * Note that this is not a shallow copy on the json object, but is a * shallow copy on the data within a tree object. For example, for a From e262dabf840d04585429783c12b3079d97122cc0 Mon Sep 17 00:00:00 2001 From: Albert Chu Date: Thu, 2 Nov 2017 16:05:37 -0700 Subject: [PATCH 5/6] common/libkvs/treeobj: Add treeobj_get_symlink() Add convenience function to get symlink string directly from a treeobj entry. This convenience function also allows const symlink tree objects to be used without casting const away. --- src/common/libkvs/test/treeobj.c | 7 +++++++ src/common/libkvs/treeobj.c | 18 ++++++++++++++++++ src/common/libkvs/treeobj.h | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/src/common/libkvs/test/treeobj.c b/src/common/libkvs/test/treeobj.c index bce989e8ee6a..51cde252b11d 100644 --- a/src/common/libkvs/test/treeobj.c +++ b/src/common/libkvs/test/treeobj.c @@ -626,6 +626,7 @@ void test_deep_copy (void) void test_symlink (void) { json_t *o, *data; + const char *str; ok (treeobj_create_symlink (NULL) == NULL && errno == EINVAL, @@ -640,6 +641,12 @@ void test_symlink (void) "treeobj_get_data returned string"); ok (!strcmp (json_string_value (data), "a.b.c"), "and string has right content"); + ok (treeobj_get_symlink (NULL) == NULL, + "treeobj_get_symlink fails on bad input"); + ok ((str = treeobj_get_symlink (o)) != NULL, + "treeobj_get_symlink works"); + ok (!strcmp (str, "a.b.c"), + "treeobj_get_symlink returns correct string"); json_decref (o); } diff --git a/src/common/libkvs/treeobj.c b/src/common/libkvs/treeobj.c index e5bdb4d0f8e3..dd3635a85b00 100644 --- a/src/common/libkvs/treeobj.c +++ b/src/common/libkvs/treeobj.c @@ -177,6 +177,24 @@ json_t *treeobj_get_data (json_t *obj) return data; } +const char *treeobj_get_symlink (const json_t *obj) +{ + const char *type; + const json_t *data; + const char *str; + + if (treeobj_peek (obj, &type, &data) < 0 + || strcmp (type, "symlink") != 0) { + errno = EINVAL; + return NULL; + } + if (!(str = json_string_value (data))) { + errno = EINVAL; + return NULL; + } + return str; +} + int treeobj_decode_val (const json_t *obj, void **dp, int *lp) { const char *type, *xdatastr; diff --git a/src/common/libkvs/treeobj.h b/src/common/libkvs/treeobj.h index e58d5039bcbc..b987b0a47028 100644 --- a/src/common/libkvs/treeobj.h +++ b/src/common/libkvs/treeobj.h @@ -45,6 +45,10 @@ bool treeobj_is_dirref (const json_t *obj); */ json_t *treeobj_get_data (json_t *obj); +/* get convenience functions, operate on type specific objects + */ +const char *treeobj_get_symlink (const json_t *obj); + /* get decoded val data. * If len == 0, data will be NULL. * If len > 0, data will be followed by an extra NULL byte in memory. From bc0a6e2d19c298858db4eeef7e303804a82c7984 Mon Sep 17 00:00:00 2001 From: Albert Chu Date: Thu, 2 Nov 2017 11:58:07 -0700 Subject: [PATCH 6/6] modules/kvs: Refactor cache_entry_get_treeobj() Return const json_t * from function, as we do not want users to modify any json object stored in the cache. --- src/modules/kvs/cache.c | 2 +- src/modules/kvs/cache.h | 2 +- src/modules/kvs/commit.c | 9 +++++---- src/modules/kvs/kvs.c | 2 +- src/modules/kvs/lookup.c | 17 +++++++---------- src/modules/kvs/test/cache.c | 23 ++++++++++++++--------- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/modules/kvs/cache.c b/src/modules/kvs/cache.c index e2a43774bad7..d9f4f5c82c81 100644 --- a/src/modules/kvs/cache.c +++ b/src/modules/kvs/cache.c @@ -186,7 +186,7 @@ int cache_entry_set_raw (struct cache_entry *hp, void *data, int len) return -1; } -json_t *cache_entry_get_treeobj (struct cache_entry *hp) +const json_t *cache_entry_get_treeobj (struct cache_entry *hp) { if (!hp || !hp->valid || !hp->data) return NULL; diff --git a/src/modules/kvs/cache.h b/src/modules/kvs/cache.h index e83c1a59d8ed..c1b29d13572b 100644 --- a/src/modules/kvs/cache.h +++ b/src/modules/kvs/cache.h @@ -82,7 +82,7 @@ int cache_entry_force_clear_dirty (struct cache_entry *hp); int cache_entry_get_raw (struct cache_entry *hp, void **data, int *len); int cache_entry_set_raw (struct cache_entry *hp, void *data, int len); -json_t *cache_entry_get_treeobj (struct cache_entry *hp); +const json_t *cache_entry_get_treeobj (struct cache_entry *hp); int cache_entry_set_treeobj (struct cache_entry *hp, json_t *o); /* Arrange for message handler represented by 'wait' to be restarted diff --git a/src/modules/kvs/commit.c b/src/modules/kvs/commit.c index db8ff1323b44..eb121c09974e 100644 --- a/src/modules/kvs/commit.c +++ b/src/modules/kvs/commit.c @@ -559,6 +559,7 @@ static int commit_link_dirent (commit_t *c, int current_epoch, } else if (treeobj_is_dirref (dir_entry)) { struct cache_entry *hp; const char *ref; + const json_t *subdirtmp; int refcount; if ((refcount = treeobj_get_count (dir_entry)) < 0) { @@ -584,13 +585,13 @@ static int commit_link_dirent (commit_t *c, int current_epoch, goto success; /* stall */ } - if (!(subdir = cache_entry_get_treeobj (hp))) { + if (!(subdirtmp = cache_entry_get_treeobj (hp))) { saved_errno = ENOTRECOVERABLE; goto done; } /* do not corrupt store by modifying orig. */ - if (!(subdir = treeobj_copy (subdir))) { + if (!(subdir = treeobj_deep_copy (subdirtmp))) { saved_errno = errno; goto done; } @@ -699,7 +700,7 @@ commit_process_t commit_process (commit_t *c, /* Make a copy of the root directory. */ struct cache_entry *hp; - json_t *rootdir; + const json_t *rootdir; /* Caller didn't call commit_iter_missing_refs() */ if (zlist_first (c->missing_refs_list)) @@ -725,7 +726,7 @@ commit_process_t commit_process (commit_t *c, return COMMIT_PROCESS_ERROR; } - if (!(c->rootcpy = treeobj_copy (rootdir))) { + if (!(c->rootcpy = treeobj_deep_copy (rootdir))) { c->errnum = errno; return COMMIT_PROCESS_ERROR; } diff --git a/src/modules/kvs/kvs.c b/src/modules/kvs/kvs.c index 4c09215100a2..70c4900d4eec 100644 --- a/src/modules/kvs/kvs.c +++ b/src/modules/kvs/kvs.c @@ -1421,7 +1421,7 @@ static void setroot_event_cb (flux_t *h, flux_msg_handler_t *w, static int setroot_event_send (kvs_ctx_t *ctx, json_t *names) { - json_t *root = NULL; + const json_t *root = NULL; json_t *nullobj = NULL; flux_msg_t *msg = NULL; int saved_errno, rc = -1; diff --git a/src/modules/kvs/lookup.c b/src/modules/kvs/lookup.c index 573f61b5518e..2a97415ffbfb 100644 --- a/src/modules/kvs/lookup.c +++ b/src/modules/kvs/lookup.c @@ -53,7 +53,7 @@ typedef struct { int depth; char *path_copy; /* for internal parsing, do not use */ - json_t *dirent; + const json_t *dirent; zlist_t *pathcomps; } walk_level_t; @@ -82,7 +82,7 @@ struct lookup { /* if valref_missing_refs is true, iterate on refs, else * return missing_ref string. */ - json_t *valref_missing_refs; + const json_t *valref_missing_refs; const char *missing_ref; int errnum; /* errnum if error */ @@ -91,7 +91,7 @@ struct lookup { /* API internal */ json_t *root_dirent; zlist_t *levels; - json_t *wdirent; /* result after walk() */ + const json_t *wdirent; /* result after walk() */ enum { LOOKUP_STATE_INIT, LOOKUP_STATE_CHECK_ROOT, @@ -219,7 +219,7 @@ static walk_level_t *walk_levels_push (lookup_t *lh, */ static bool walk (lookup_t *lh) { - json_t *dir; + const json_t *dir; walk_level_t *wl = NULL; char *pathcomp; @@ -299,7 +299,7 @@ static bool walk (lookup_t *lh) /* Get directory reference of path component from directory */ - if (!(wl->dirent = treeobj_get_entry (dir, pathcomp))) { + if (!(wl->dirent = treeobj_peek_entry (dir, pathcomp))) { /* if entry does not exist, not necessarily ENOENT error, * let caller decide. If error not ENOENT, return to * caller. */ @@ -311,16 +311,13 @@ static bool walk (lookup_t *lh) /* Resolve dirent if it is a link */ if (treeobj_is_symlink (wl->dirent)) { - json_t *link; const char *linkstr; - if (!(link = treeobj_get_data (wl->dirent))) { + if (!(linkstr = treeobj_get_symlink (wl->dirent))) { lh->errnum = errno; goto error; } - linkstr = json_string_value (link); - /* Follow link if in middle of path or if end of path, * flags say we can follow it */ @@ -779,7 +776,7 @@ static int get_multi_blobref_valref_value (lookup_t *lh, int refcount, bool lookup (lookup_t *lh) { - json_t *valtmp = NULL; + const json_t *valtmp = NULL; const char *reftmp; struct cache_entry *hp; int refcount; diff --git a/src/modules/kvs/test/cache.c b/src/modules/kvs/test/cache.c index d2b2c1bc26e3..8c55671c0a41 100644 --- a/src/modules/kvs/test/cache.c +++ b/src/modules/kvs/test/cache.c @@ -190,7 +190,8 @@ void cache_entry_raw_tests (void) void cache_entry_treeobj_tests (void) { struct cache_entry *e; - json_t *otmp, *o1, *o2, *otest; + json_t *o1, *o2, *otest; + const json_t *otmp; char *data; /* Play with one entry. @@ -215,7 +216,7 @@ void cache_entry_treeobj_tests (void) "cache_entry_set_dirty fails b/c entry non-valid"); ok (cache_entry_get_dirty (e) == false, "cache entry does not set dirty, b/c no data"); - ok ((otmp = cache_entry_get_treeobj (e)) == NULL, + ok (cache_entry_get_treeobj (e) == NULL, "cache_entry_get_treeobj returns NULL, no treeobj set"); ok (cache_entry_set_treeobj (e, o1) == 0, "cache_entry_set_treeobj success"); @@ -259,7 +260,8 @@ void cache_entry_treeobj_tests (void) ok ((otmp = cache_entry_get_treeobj (e)) != NULL, "treeobj retrieved from cache entry"); otest = treeobj_create_val ("foo", 3); - ok (json_equal (otmp, otest) == 1, + /* XXX - json_equal takes const in jansson > 2.10 */ + ok (json_equal ((json_t *)otmp, otest) == 1, "expected treeobj object returned"); json_decref (otest); @@ -270,7 +272,8 @@ void cache_entry_treeobj_tests (void) void cache_entry_raw_and_treeobj_tests (void) { struct cache_entry *e; - json_t *o1, *otmp, *otest; + json_t *o1, *otest; + const json_t *otmp; char *data, *datatmp; int len; @@ -283,7 +286,7 @@ void cache_entry_raw_and_treeobj_tests (void) "cache_entry_create works"); ok (cache_entry_set_raw (e, data, strlen (data) + 1) == 0, "cache_entry_set_raw success"); - ok ((otmp = cache_entry_get_treeobj (e)) == NULL, + ok (cache_entry_get_treeobj (e) == NULL, "cache_entry_get_treeobj returns NULL for non-treeobj raw data"); cache_entry_destroy (e); @@ -293,7 +296,7 @@ void cache_entry_raw_and_treeobj_tests (void) "cache_entry_create works"); ok (cache_entry_set_raw (e, NULL, 0) == 0, "cache_entry_set_raw success"); - ok ((otmp = cache_entry_get_treeobj (e)) == NULL, + ok (cache_entry_get_treeobj (e) == NULL, "cache_entry_get_treeobj returns NULL for zero length raw data"); cache_entry_destroy (e); @@ -311,7 +314,8 @@ void cache_entry_raw_and_treeobj_tests (void) ok ((otmp = cache_entry_get_treeobj (e)) != NULL, "cache_entry_get_treeobj returns non-NULL for treeobj-legal raw data"); otest = treeobj_create_val ("foo", 3); - ok (json_equal (otmp, otest) == true, + /* XXX - json_equal takes const in jansson > 2.10 */ + ok (json_equal ((json_t *)otmp, otest) == true, "treeobj returned from cache entry correct"); json_decref (o1); cache_entry_destroy (e); @@ -582,8 +586,8 @@ void cache_expiration_tests (void) tstat_t ts; int size, incomplete, dirty; json_t *o1; - json_t *otmp; json_t *otest; + const json_t *otmp; /* Put entry in cache and test lookup, expire */ @@ -638,7 +642,8 @@ void cache_expiration_tests (void) ok ((otmp = cache_entry_get_treeobj (e4)) != NULL, "cache_entry_get_treeobj found entry"); otest = treeobj_create_val ("foo", 3); - ok (json_equal (otmp, otest) == 1, + /* XXX - json_equal takes const in jansson > 2.10 */ + ok (json_equal ((json_t *)otmp, otest) == 1, "expected treeobj object found"); json_decref (otest); ok (cache_count_entries (cache) == 2,