libc: add helper furnction to set sysctl() user.* variables
Testing had revealed that trying to retrieve the user.localbase variable into to small a buffer would return the correct error code, but would not fill the available buffer space with a partial result. A partial result is of no use, but this is still a violation of the documented behavior, which has been fixed in the previous commit to this function. I just checked the code for "user.cs_path" and found that it had the same issue. Instead of fixing the logic for each user.* sysctl string variable individually, this commit adds a helper function set_user_str() that implements the semantics specified in the sysctl() man page. It is currently only used for "user.cs_path" and "user.localbase", but it will offer a significant simplification when further such variables will be added (as I intend to do). MFC after: 3 days
This commit is contained in:
parent
34478b73bf
commit
9535d9f104
@ -46,6 +46,25 @@ __FBSDID("$FreeBSD$");
|
||||
extern int __sysctl(const int *name, u_int namelen, void *oldp,
|
||||
size_t *oldlenp, const void *newp, size_t newlen);
|
||||
|
||||
static int
|
||||
set_user_str(void *dstp, size_t *dstlenp, const char *src, size_t len,
|
||||
size_t maxlen)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
if (dstp != NULL) {
|
||||
if (len > maxlen) {
|
||||
len = maxlen;
|
||||
errno = ENOMEM;
|
||||
retval = -1;
|
||||
}
|
||||
memcpy(dstp, src, len);
|
||||
}
|
||||
*dstlenp = len;
|
||||
return (retval);
|
||||
}
|
||||
|
||||
int
|
||||
sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
|
||||
const void *newp, size_t newlen)
|
||||
@ -74,18 +93,10 @@ sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
|
||||
/* Variables under CLT_USER that may be overridden by kernel values */
|
||||
switch (name[1]) {
|
||||
case USER_LOCALBASE:
|
||||
if (oldlenp != NULL && *oldlenp == 1) {
|
||||
*oldlenp = sizeof(_PATH_LOCALBASE);
|
||||
if (oldp != NULL) {
|
||||
if (*oldlenp > orig_oldlen) {
|
||||
*oldlenp = orig_oldlen;
|
||||
errno = ENOMEM;
|
||||
retval = -1;
|
||||
}
|
||||
memmove(oldp, _PATH_LOCALBASE, *oldlenp);
|
||||
}
|
||||
}
|
||||
return (retval);
|
||||
if (oldlenp == NULL || *oldlenp > sizeof(""))
|
||||
return (0);
|
||||
return (set_user_str(oldp, oldlenp, _PATH_LOCALBASE,
|
||||
sizeof(_PATH_LOCALBASE), orig_oldlen));
|
||||
}
|
||||
|
||||
/* Variables under CLT_USER whose values are immutably defined below */
|
||||
@ -96,14 +107,8 @@ sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
|
||||
|
||||
switch (name[1]) {
|
||||
case USER_CS_PATH:
|
||||
if (oldp != NULL && orig_oldlen < sizeof(_PATH_STDPATH)) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
*oldlenp = sizeof(_PATH_STDPATH);
|
||||
if (oldp != NULL)
|
||||
memmove(oldp, _PATH_STDPATH, sizeof(_PATH_STDPATH));
|
||||
return (0);
|
||||
return (set_user_str(oldp, oldlenp, _PATH_STDPATH,
|
||||
sizeof(_PATH_STDPATH), orig_oldlen));
|
||||
}
|
||||
|
||||
if (oldp != NULL && *oldlenp < sizeof(int)) {
|
||||
|
Loading…
Reference in New Issue
Block a user