/* Author: James Athey
 */

%module selinux
%{
	#include "selinux/selinux.h"
%}

%pythoncode %{

import shutil, os, errno, stat

DISABLED = -1
PERMISSIVE = 0
ENFORCING = 1

def restorecon(path, recursive=False):
    """ Restore SELinux context on a given path """

    try:
        mode = os.lstat(path)[stat.ST_MODE]
        status, context = matchpathcon(path, mode)
    except OSError:
        path = os.path.realpath(os.path.expanduser(path))
        mode = os.lstat(path)[stat.ST_MODE]
        status, context = matchpathcon(path, mode)

    if status == 0:
        try:
            status, oldcontext = lgetfilecon(path)
        except OSError as e:
            if e.errno != errno.ENODATA:
                raise
            oldcontext = None
        if context != oldcontext:
            lsetfilecon(path, context)

        if recursive:
            for root, dirs, files in os.walk(path):
                for name in files + dirs:
                   restorecon(os.path.join(root, name))

def chcon(path, context, recursive=False):
    """ Set the SELinux context on a given path """
    lsetfilecon(path, context)
    if recursive:
        for root, dirs, files in os.walk(path):
            for name in files + dirs:
               lsetfilecon(os.path.join(root,name), context)

def copytree(src, dest):
    """ An SELinux-friendly shutil.copytree method """
    shutil.copytree(src, dest)
    restorecon(dest, recursive=True)

def install(src, dest):
    """ An SELinux-friendly shutil.move method """
    shutil.move(src, dest)
    restorecon(dest, recursive=True)
%}

/* security_get_boolean_names() typemap */
%typemap(argout) (char ***names, int *len) {
	PyObject* list = PyList_New(*$2);
	int i;
	for (i = 0; i < *$2; i++) {
		PyList_SetItem(list, i, PyBytes_FromString((*$1)[i]));
	}
	$result = SWIG_Python_AppendOutput($result, list);
}

/* return a sid along with the result */
%typemap(argout) (security_id_t * sid) {
	if (*$1) {
                %append_output(SWIG_NewPointerObj(*$1, $descriptor(security_id_t), 0));
	} else {
		Py_INCREF(Py_None);
		%append_output(Py_None);
	}
}

%typemap(in,numinputs=0) security_id_t *(security_id_t temp) {
  $1 = &temp;
}

%typemap(in, numinputs=0) void *(char *temp=NULL) {
	$1 = temp;
}

/* Makes security_compute_user() return a Python list of contexts */
%typemap(argout) (char ***con) {
	PyObject* plist;
	int i, len = 0;
	
	if (*$1) {
		while((*$1)[len])
			len++;
		plist = PyList_New(len);
		for (i = 0; i < len; i++) {
			PyList_SetItem(plist, i,
                                       PyBytes_FromString((*$1)[i])
                                       );
		}
	} else {
		plist = PyList_New(0);
	}

	$result = SWIG_Python_AppendOutput($result, plist);
}

/* Makes functions in get_context_list.h return a Python list of contexts */
%typemap(argout) (char ***list) {
	PyObject* plist;
	int i;
	
	if (*$1) {
		plist = PyList_New(result);
		for (i = 0; i < result; i++) {
			PyList_SetItem(plist, i,
                                       PyBytes_FromString((*$1)[i])
                                       );
		}
	} else {
		plist = PyList_New(0);
	}
	/* Only return the Python list, don't need to return the length anymore */
	$result = plist;
}

%typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) {
	$1 = &temp;
}
%typemap(freearg,match="in") char ** "";
%typemap(argout,noblock=1) char ** {
	if (*$1) {
		%append_output(SWIG_FromCharPtr(*$1));
		freecon(*$1);
	}
	else {
		Py_INCREF(Py_None);
		%append_output(Py_None);
	}
}

%typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) {
	$1 = &temp;
}
%typemap(freearg,match="in") char ** "";
%typemap(argout,noblock=1) char ** {
	if (*$1) {
		%append_output(SWIG_FromCharPtr(*$1));
		free(*$1);
	}
	else {
		Py_INCREF(Py_None);
		%append_output(Py_None);
	}
}

%typemap(in) char * const [] {
	int i, size;
	PyObject * s;

	if (!PySequence_Check($input)) {
		PyErr_SetString(PyExc_ValueError, "Expected a sequence");
		return NULL;
	}

	size = PySequence_Size($input);
	
	$1 = (char**) malloc(size + 1);

	for(i = 0; i < size; i++) {
		if (!PyBytes_Check(PySequence_GetItem($input, i))) {
			PyErr_SetString(PyExc_ValueError, "Sequence must contain only bytes");

			return NULL;
		}

	}
		
	for(i = 0; i < size; i++) {
		s = PySequence_GetItem($input, i);

		$1[i] = (char*) malloc(PyBytes_Size(s) + 1);
		strcpy($1[i], PyBytes_AsString(s));

	}
	$1[size] = NULL;
}

%typemap(freearg,match="in") char * const [] {
	int i = 0;
	while($1[i]) {
		free($1[i]);
		i++;
	}
	free($1);
}

%include "selinuxswig_python_exception.i"
%include "selinuxswig.i"
