Function: set-file-selinux-context

set-file-selinux-context is a function defined in fileio.c.

Signature

(set-file-selinux-context FILENAME CONTEXT)

Documentation

Set SELinux context of file named FILENAME to CONTEXT.

CONTEXT should be a list (USER ROLE TYPE RANGE), where the list elements are strings naming the components of a SELinux context.

Value is t if setting of SELinux context was successful, nil otherwise.

This function does nothing and returns nil if SELinux is disabled, or if Emacs was not compiled with SELinux support.

Other relevant functions are documented in the file group.

Probably introduced at or before Emacs version 24.1.

Shortdoc

;; file
(set-file-selinux-context "/tmp/foo" '(unconfined_u object_r user_home_t s0))
    e.g. => t

Source Code

// Defined in /usr/src/emacs/src/fileio.c
{
  Lisp_Object absname;
  Lisp_Object handler;
#if HAVE_LIBSELINUX
  Lisp_Object encoded_absname;
  Lisp_Object user = CAR_SAFE (context);
  Lisp_Object role = CAR_SAFE (CDR_SAFE (context));
  Lisp_Object type = CAR_SAFE (CDR_SAFE (CDR_SAFE (context)));
  Lisp_Object range = CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (context))));
  char *con;
  bool fail;
  int conlength;
  context_t parsed_con;
#endif

  absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));

  /* If the file name has special constructs in it,
     call the corresponding file name handler.  */
  handler = Ffind_file_name_handler (absname, Qset_file_selinux_context);
  if (!NILP (handler))
    return call3 (handler, Qset_file_selinux_context, absname, context);

#if HAVE_LIBSELINUX
  if (is_selinux_enabled ())
    {
      /* Get current file context. */
      encoded_absname = ENCODE_FILE (absname);
      conlength = lgetfilecon (SSDATA (encoded_absname), &con);
      if (conlength > 0)
	{
	  parsed_con = context_new (con);
	  /* Change the parts defined in the parameter.*/
	  if (STRINGP (user))
	    {
	      if (context_user_set (parsed_con, SSDATA (user)))
		error ("Doing context_user_set");
	    }
	  if (STRINGP (role))
	    {
	      if (context_role_set (parsed_con, SSDATA (role)))
		error ("Doing context_role_set");
	    }
	  if (STRINGP (type))
	    {
	      if (context_type_set (parsed_con, SSDATA (type)))
		error ("Doing context_type_set");
	    }
	  if (STRINGP (range))
	    {
	      if (context_range_set (parsed_con, SSDATA (range)))
		error ("Doing context_range_set");
	    }

	  /* Set the modified context back to the file.  */
	  fail = (lsetfilecon (SSDATA (encoded_absname),
			       context_str (parsed_con))
		  != 0);
          /* See https://debbugs.gnu.org/11245 for ENOTSUP.  */
	  if (fail && errno != ENOTSUP)
	    report_file_error ("Doing lsetfilecon", absname);

	  context_free (parsed_con);
	  freecon (con);
	  return fail ? Qnil : Qt;
	}
      else
	report_file_error ("Doing lgetfilecon", absname);
    }
#endif

  return Qnil;
}