diff options
author | das <das@FreeBSD.org> | 2004-04-28 01:27:33 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2004-04-28 01:27:33 +0000 |
commit | 9df402daa402e2e21ffef311a8c008dc0981c94f (patch) | |
tree | e790e511554fc7818e15e46d99819f32e123ed9c /sys/kern | |
parent | 45c4ca11d3df1082a4c95dd15e54bcfdd7bb40ee (diff) | |
download | FreeBSD-src-9df402daa402e2e21ffef311a8c008dc0981c94f.zip FreeBSD-src-9df402daa402e2e21ffef311a8c008dc0981c94f.tar.gz |
If the buffer supplied to kenv(KENV_DUMP, ...) isn't big enough,
return the number of bytes needed instead of 0. The manpage claims
that we do this anyway.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_environment.c | 39 |
1 files changed, 18 insertions, 21 deletions
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c index 9511c90..96b57d9 100644 --- a/sys/kern/kern_environment.c +++ b/sys/kern/kern_environment.c @@ -87,7 +87,7 @@ kenv(td, uap) } */ *uap; { char *name, *value; - size_t len, done; + size_t len, done, needed; int error, i; KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = 0")); @@ -99,30 +99,27 @@ kenv(td, uap) if (error) return (error); #endif - len = 0; - /* Return the size if called with a NULL buffer */ - if (uap->value == NULL) { - sx_slock(&kenv_lock); - for (i = 0; kenvp[i] != NULL; i++) - len += strlen(kenvp[i]) + 1; - sx_sunlock(&kenv_lock); - td->td_retval[0] = len; - return (0); - } - done = 0; + done = needed = 0; sx_slock(&kenv_lock); - for (i = 0; kenvp[i] != NULL && done < uap->len; i++) { - len = min(strlen(kenvp[i]) + 1, uap->len - done); - error = copyout(kenvp[i], uap->value + done, - len); - if (error) { - sx_sunlock(&kenv_lock); - return (error); + for (i = 0; kenvp[i] != NULL; i++) { + len = strlen(kenvp[i]) + 1; + needed += len; + len = min(len, uap->len - done); + /* + * If called with a NULL or insufficiently large + * buffer, just keep computing the required size. + */ + if (uap->value != NULL && len > 0) { + error = copyout(kenvp[i], uap->value + done, + len); + if (error) + break; + done += len; } - done += len; } sx_sunlock(&kenv_lock); - return (0); + td->td_retval[0] = ((done == needed) ? 0 : needed); + return (error); } if ((uap->what == KENV_SET) || |