| 1731 | */ |
| 1732 | |
| 1733 | int |
| 1734 | sysctl_handle_string(SYSCTL_HANDLER_ARGS) |
| 1735 | { |
| 1736 | char *tmparg; |
| 1737 | size_t outlen; |
| 1738 | int error = 0, ro_string = 0; |
| 1739 | |
| 1740 | /* |
| 1741 | * If the sysctl isn't writable and isn't a preallocated tunable that |
| 1742 | * can be modified by kenv(2), microoptimise and treat it as a |
| 1743 | * read-only string. |
| 1744 | * A zero-length buffer indicates a fixed size read-only |
| 1745 | * string. In ddb, don't worry about trying to make a malloced |
| 1746 | * snapshot. |
| 1747 | */ |
| 1748 | if ((oidp->oid_kind & (CTLFLAG_WR | CTLFLAG_TUN)) == 0 || |
| 1749 | arg2 == 0 || kdb_active) { |
| 1750 | arg2 = strlen((char *)arg1) + 1; |
| 1751 | ro_string = 1; |
| 1752 | } |
| 1753 | |
| 1754 | if (req->oldptr != NULL) { |
| 1755 | if (ro_string) { |
| 1756 | tmparg = arg1; |
| 1757 | outlen = strlen(tmparg) + 1; |
| 1758 | } else { |
| 1759 | tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK); |
| 1760 | sx_slock(&sysctlstringlock); |
| 1761 | memcpy(tmparg, arg1, arg2); |
| 1762 | sx_sunlock(&sysctlstringlock); |
| 1763 | outlen = strlen(tmparg) + 1; |
| 1764 | } |
| 1765 | |
| 1766 | error = SYSCTL_OUT(req, tmparg, outlen); |
| 1767 | |
| 1768 | if (!ro_string) |
| 1769 | free(tmparg, M_SYSCTLTMP); |
| 1770 | } else { |
| 1771 | if (!ro_string) |
| 1772 | sx_slock(&sysctlstringlock); |
| 1773 | outlen = strlen((char *)arg1) + 1; |
| 1774 | if (!ro_string) |
| 1775 | sx_sunlock(&sysctlstringlock); |
| 1776 | error = SYSCTL_OUT(req, NULL, outlen); |
| 1777 | } |
| 1778 | if (error || !req->newptr) |
| 1779 | return (error); |
| 1780 | |
| 1781 | if (req->newlen - req->newidx >= arg2 || |
| 1782 | req->newlen - req->newidx < 0) { |
| 1783 | error = EINVAL; |
| 1784 | } else if (req->newlen - req->newidx == 0) { |
| 1785 | sx_xlock(&sysctlstringlock); |
| 1786 | ((char *)arg1)[0] = '\0'; |
| 1787 | sx_xunlock(&sysctlstringlock); |
| 1788 | } else { |
| 1789 | arg2 = req->newlen - req->newidx; |
| 1790 | tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK); |
no test coverage detected