/*
 * $Id: cap_file.c,v 1.1.1.1.2.1 1999/04/23 06:15:10 morgan Exp $
 *
 * Copyright (c) 1997 Andrew G Morgan <morgan@linux.kernel.org>
 *
 * See end of file for Log.
 *
 * This file deals with setting capabilities on files.
 */

#include "libcap.h"

#if (_LINUX_CAPABILITY_VERSION == 0x19980330)

/* This kernel does not support filesystem capabilities later ones do */

cap_t cap_get_fd(int fildes)
{
    _cap_debug("compilation does not support filecaps");
    errno = ENOSYS;
    return NULL;
}

cap_t cap_get_file(const char *filename)
{
    _cap_debug("compilation does not support filecaps");
    errno = ENOSYS;
    return NULL;
}

int cap_set_fd(int fildes, cap_t cap_d)
{
    _cap_debug("compilation does not support filecaps");
    errno = ENOSYS;
    return -1;
}

int cap_set_file(const char *filename, cap_t cap_d)
{
    _cap_debug("compilation does not support filecaps");
    errno = ENOSYS;
    return -1;
}

#else

/*
 * attempt to have defined behavior when running with an older kernel
 */

static int _libcap_capfile(cap_t cap_d)
{
    cap_d->head.version = _libcap_kernel_version;

    _cap_debug("version: %x, features: %x",
	       cap_d->head.version, cap_d->features);

    if (cap_d->features & CAP_FEATURE_FILE) {
	_cap_debug("ok");
	return 0;
    } else {
	_cap_debug("library compiled with a kernel not supporting filecaps");
	errno = ENOSYS;
	return -1;
    }
}

/*
 * Get the capabilities of an open file, as specified by its file
 * descriptor.
 */

cap_t cap_get_fd(int fildes)
{
    int retval;
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result == NULL) {
	_cap_debug("failed to allocate a result");
	return NULL;
    }

    if (_libcap_capfile(result)) {
	_cap_debug("running kernel has no support for filecaps");
	goto fail;
    }

    result->head.type = _CAPABILITY_TYPE_FILDES;
    result->head.u.fildes = fildes;

    retval = capget(&result->head, &result->set);

    result->head.type = 0;
    result->head.u.pid = 0;

    if (!retval) {
	return result;
    }

fail:
    cap_free(&result);

    return NULL;
}

/*
 * Set the capabilities on a named file.
 */

cap_t cap_get_file(const char *filename)
{
    int retval;
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result == NULL) {
	_cap_debug("failed to allocate a result");
	return NULL;
    }

    if (_libcap_capfile(result)) {
	_cap_debug("running kernel has no support for filecaps");
	goto fail;
    }

    result->head.type = _CAPABILITY_TYPE_FILE;
    result->head.u.path = filename;

    retval = capget(&result->head, &result->set);

    result->head.type = 0;
    result->head.u.pid = 0;

    if (!retval) {
	return result;
    }

fail:
    cap_free(&result);

    return NULL;
}

/*
 * Set the capabilities of an open file, as specified by its file
 * descriptor.
 */

int cap_set_fd(int fildes, cap_t cap_d)
{
    int retval;
    
    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    if (_libcap_capfile(cap_d)) {
	_cap_debug("running kernel has no support for filecaps");
	return -1;
    }

    cap_d->head.type = _CAPABILITY_TYPE_FILDES;
    cap_d->head.u.fildes = fildes;

    retval = capset(&cap_d->head, &cap_d->set);

    cap_d->head.type = 0;
    cap_d->head.u.pid = 0;

    return retval;
}

/*
 * Set the capabilities of a named file.
 */

int cap_set_file(const char *filename, cap_t cap_d)
{
    int retval;

    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    if (_libcap_capfile(cap_d)) {
	_cap_debug("running kernel has no support for filecaps");
	return -1;
    }

    cap_d->head.type = _CAPABILITY_TYPE_FILE;
    cap_d->head.u.path = filename;

    retval = capset(&cap_d->head, &cap_d->set);

    cap_d->head.type = 0;
    cap_d->head.u.pid = 0;

    return retval;
}

#endif

/*
 * $Log: cap_file.c,v $
 * Revision 1.1.1.1.2.1  1999/04/23 06:15:10  morgan
 * added file cap support
 *
 * Revision 1.1.1.1  1999/04/17 22:16:31  morgan
 * release 1.0 of libcap
 *
 * Revision 1.5  1998/05/24 22:54:09  morgan
 * updated for 2.1.104
 *
 * Revision 1.4  1997/05/14 05:17:13  morgan
 * bug-fix from zefram (errno no set on success)
 *
 * Revision 1.3  1997/05/04 05:35:46  morgan
 * fixed errno setting. syscalls do this part
 *
 * Revision 1.2  1997/04/28 00:57:11  morgan
 * fixes and zefram's patches
 *
 * Revision 1.1  1997/04/21 04:32:52  morgan
 * Initial revision
 *
 */
