/*
* System Security Services Daemon. NSS client interface
*
* Copyright (C) Simo Sorce 2011
*
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* NSS interfaces to mmap cache */
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "nss_mc.h"
#include "sss_cli.h"
/* FIXME: hook up to library destructor to avoid leaks */
/* FIXME: temporarily open passwd file on our own, later we will probably
* use socket passing from the main process */
* SSSD or a flag in sss_mc_header? per domain? */
do { \
res = false; \
if (MC_VALID_BARRIER(_b1)) { \
__sync_synchronize(); \
__sync_synchronize(); \
res = true; \
} \
} \
} while(0)
{
struct sss_mc_header h;
bool copy_ok;
int count;
int ret;
/* retry barrier protected reading max 5 times then give up */
sizeof(struct sss_mc_header));
if (copy_ok) {
/* record is consistent so we can proceed */
break;
}
}
if (count == 0) {
/* couldn't successfully read header we have to give up */
return EIO;
}
if (h.major_vno != SSS_MC_MAJOR_VNO ||
h.minor_vno != SSS_MC_MINOR_VNO ||
h.status == SSS_MC_HEADER_RECYCLED) {
return EINVAL;
}
/* first time we check the header, let's fill our own struct */
} else {
return EINVAL;
}
}
if (ret == -1) {
return EIO;
}
/* memory cache was removed; we need to reinitialize it. */
return EINVAL;
}
return 0;
}
{
}
}
/* restore count of active threads */
}
struct sss_cli_mc_ctx *ctx)
{
int ret;
/* check if ctx is initialised by previous thread. */
goto done;
}
if (ret == -1) {
goto done;
}
goto done;
}
if (ret == -1) {
goto done;
}
goto done;
}
goto done;
}
if (ret != 0) {
goto done;
}
ret = 0;
done:
if (ret) {
}
return ret;
}
{
char *envval;
int ret;
bool need_decrement = false;
return EPERM;
}
switch (ctx->initialized) {
case UNINITIALIZED:
if (ret) {
need_decrement = true;
}
break;
case INITIALIZED:
if (ret) {
need_decrement = true;
}
break;
case RECYCLED:
/* we need to safely destroy memory cache */
break;
default:
}
if (ret) {
}
/* just one thread should call munmap */
}
}
if (need_decrement) {
/* In case of error, we will not touch mmapped area => decrement */
}
}
return ret;
}
{
}
{
bool copy_ok;
int count;
int ret;
/* try max 5 times */
/* fetch record length */
/* record is inconsistent, retry */
continue;
}
/* record has invalid length */
return EINVAL;
}
if (!copy_rec) {
goto done;
}
}
/* we cannot access data directly, we must copy data and then
* access the copy */
/* we must check data is consistent again after the copy */
/* record is consistent, use it */
break;
}
}
if (count == 0) {
/* couldn't successfully read header we have to give up */
goto done;
}
ret = 0;
done:
if (ret) {
}
return ret;
}
/*
* returns strings from a buffer.
*
* Call first time with *cookie set to null, then call again
* with the returned cookie.
* On the last string the cookie will be reset to null and
* all strings will have been returned.
* In case the last string is not zero terminated EINVAL is returned.
*/
{
char *ret;
char *p;
p = buf;
} else {
p = *((char **)cookie);
}
ret = p;
while (p < max) {
if (*p == '\0') {
break;
}
p++;
}
if (p >= max) {
return EINVAL;
}
p++;
if (p == max) {
} else {
*cookie = p;
}
return 0;
}
{
} else {
/* it should never happen. */
return MC_INVALID_VAL;
}
}