to be moved into libsmackman.
lib_LTLIBRARIES = libsmack.la
libsmack_la_LDFLAGS = -version-info 1:0
-libsmack_la_SOURCES = smack_rules.c smack_xattr.c smack_labels.c
-
-EXTRA_DIST=smack_internal.h
+libsmack_la_SOURCES = smack.c
#include <stdio.h>
#include <stdlib.h>
#include <uthash.h>
-#include "smack_internal.h"
+
+#define SMACK_LEN 23
+
+#define ACC_R 1
+#define ACC_W 2
+#define ACC_X 4
+#define ACC_A 16
+#define ACC_LEN 4
+
struct smack_object {
char *object;
}
SmackRuleSet smack_rule_set_new_from_file(const char *path,
- const char *subject_filter,
- SmackLabelSet labels)
+ const char *subject_filter)
{
SmackRuleSet rules;
FILE *file;
char *buf = NULL;
const char *subject, *object, *access;
- const char *sstr, *ostr;
unsigned ac;
size_t size;
int err, ret;
break;
}
- if (labels != NULL) {
- sstr = smack_label_set_to_short_name(labels, subject);
- ostr = smack_label_set_to_short_name(labels, object);
- } else {
- sstr = subject;
- ostr = object;
- }
-
- if (sstr == NULL || ostr == NULL) {
- ret = -1;
- break;
- }
-
if (subject_filter == NULL ||
- strcmp(sstr, subject_filter) == 0) {
+ strcmp(subject, subject_filter) == 0) {
ac = str_to_ac(access);
- err = update_rule(&rules->subjects, sstr, ostr,
+ err = update_rule(&rules->subjects, subject, object,
ac);
if (err != 0) {
ret = -1;
free(handle);
}
-int smack_rule_set_save_to_file(SmackRuleSet handle, const char *path,
- SmackLabelSet labels)
+int smack_rule_set_save_to_file(SmackRuleSet handle, const char *path)
{
struct smack_subject *s, *stmp;
struct smack_object *o, *otmp;
- const char *sstr, *ostr;
char astr[ACC_LEN + 1];
FILE *file;
int err, ret;
if (o->ac == 0)
continue;
- if (labels != NULL) {
- sstr = smack_label_set_to_long_name(labels, s->subject);
- ostr = smack_label_set_to_long_name(labels, o->object);
- } else {
- sstr = s->subject;
- ostr = o->object;
- }
-
- if (sstr == NULL || ostr == NULL) {
- ret = -1;
- goto out;
- }
-
ac_to_config_str(o->ac, astr);
err = fprintf(file, "%s %s %s\n",
- sstr, ostr, astr);
+ s->subject, o->object, astr);
if (err < 0) {
ret = -1;
goto out;
}
int smack_rule_set_add(SmackRuleSet handle, const char *subject,
- const char *object, const char *access_str,
- SmackLabelSet labels)
+ const char *object, const char *access_str)
{
unsigned access;
int ret;
- if (labels != NULL) {
- subject = smack_label_set_to_short_name(labels, subject);
- object = smack_label_set_to_short_name(labels, object);
-
- if (subject == NULL || object == NULL)
- return -1;
- }
-
access = str_to_ac(access_str);
ret = update_rule(&handle->subjects, subject, object, access);
return ret == 0 ? 0 : -1;
}
void smack_rule_set_remove(SmackRuleSet handle, const char *subject,
- const char *object, SmackLabelSet labels)
+ const char *object)
{
struct smack_subject *s = NULL;
struct smack_object *o = NULL;
- if (labels != NULL) {
- subject = smack_label_set_to_short_name(labels, subject);
- object = smack_label_set_to_short_name(labels, object);
-
- if (subject == NULL || object == NULL)
- return;
- }
-
HASH_FIND_STR(handle->subjects, subject, s);
if (s == NULL)
return;
return;
}
-void smack_rule_set_remove_by_subject(SmackRuleSet handle, const char *subject,
- SmackLabelSet labels)
+void smack_rule_set_remove_by_subject(SmackRuleSet handle, const char *subject)
{
struct smack_subject *s = NULL;
struct smack_object *o = NULL, *tmp = NULL;
- if (labels != NULL) {
- subject = smack_label_set_to_short_name(labels, subject);
-
- if (subject == NULL)
- return;
- }
-
HASH_FIND_STR(handle->subjects, subject, s);
if (s == NULL)
return;
o->ac = 0;
}
-void smack_rule_set_remove_by_object(SmackRuleSet handle, const char *object,
- SmackLabelSet labels)
+void smack_rule_set_remove_by_object(SmackRuleSet handle, const char *object)
{
struct smack_subject *s = NULL, *tmp = NULL;
struct smack_object *o = NULL;
- if (labels != NULL) {
- object = smack_label_set_to_short_name(labels, object);
-
- if (object == NULL)
- return;
- }
-
HASH_ITER(hh, handle->subjects, s, tmp) {
HASH_FIND_STR(s->objects, object, o);
if (o)
}
int smack_rule_set_have_access(SmackRuleSet handle, const char *subject,
- const char *object, const char *access_str,
- SmackLabelSet labels)
+ const char *object, const char *access_str)
{
struct smack_subject *s = NULL;
struct smack_object *o = NULL;
unsigned ac;
- if (labels != NULL) {
- subject = smack_label_set_to_short_name(labels, subject);
- object = smack_label_set_to_short_name(labels, object);
-
- if (subject == NULL || object == NULL)
- return -1;
- }
-
ac = str_to_ac(access_str);
HASH_FIND_STR(handle->subjects, subject, s);
struct smack_subject *s = NULL;
struct smack_object *o = NULL;
- if (strlen(subject_str) > SMACK64_LEN &&
- strlen(object_str) > SMACK64_LEN)
+ if (strlen(subject_str) > SMACK_LEN &&
+ strlen(object_str) > SMACK_LEN)
return -ERANGE;
HASH_FIND_STR(*subjects, subject_str, s);
#ifndef SMACK_H
#define SMACK_H
-#include <sys/types.h>
-
/*!
* Smack config file default paths.
*/
#define SMACK_ACCESSES_PATH "/etc/smack/accesses"
-#define SMACK_LABELS_PATH "/etc/smack/labels"
-
-/*!
- * Extended attributes.
- */
-#define SMACK64 "security.SMACK64"
-#define SMACK64EXEC "security.SMACK64EXEC"
-#define SMACK64MMAP "security.SMACK64MMAP"
/*!
* Handle to a in-memory representation of set of Smack rules.
*/
typedef struct _SmackRuleSet *SmackRuleSet;
-/*!
- * Handle to a in-memory representation for label repository that contains
- * mapping between long and short names for labels. Short names are essentially
- * standard Smack labels.
- */
-typedef struct _SmackLabelSet *SmackLabelSet;
-
#ifdef __cplusplus
extern "C" {
#endif
* Read rules from a given file. Rules can be optionally filtered by a
* subject.
*
- * Takes subject and object as long names and maps them to short names if the
- * parameter labels is given (not set to NULL). In this case, if short labels
- * are not found, this function fails and executes no action.
- *
* @param path path to the file containing rules
* @param subject read only rules for the given subject if not set to NULL.
* @return SmackRuleSet instance on success
*/
extern SmackRuleSet smack_rule_set_new_from_file(const char *path,
- const char *subject,
- SmackLabelSet labels);
+ const char *subject);
/*!
* Free resources allocated by rules.
/*!
* Write rules to a given file. Does not write rules with no access defined.
*
- * Takes subject and object as long names and maps them to short names if the
- * parameter labels is given (not set to NULL). In this case, if short labels
- * are not found, this function fails and executes no action.
- *
* @param handle handle to a rules
* @param path path to the rules file
- * @param labels handle to a label set
* @return 0 on success
*/
-extern int smack_rule_set_save_to_file(SmackRuleSet handle, const char *path,
- SmackLabelSet labels);
+extern int smack_rule_set_save_to_file(SmackRuleSet handle, const char *path);
/*!
* Write rules to /smack/load. Does not write rules with no access defined.
* Add new rule to a rule set. Updates existing rule if there is already rule
* for the given subject and object.
*
- * Takes subject and object as long names and maps them to short names if the
- * parameter labels is given (not set to NULL). In this case, if short labels
- * are not found, this function fails and executes no action.
- *
* @param handle handle to a rule set
* @param subject subject of the rule
* @param object object of the rule
* @param access access string (rwxa)
- * @param labels handle to a label set
* @return 0 on success
*/
extern int smack_rule_set_add(SmackRuleSet handle, const char *subject,
- const char *object, const char *access,
- SmackLabelSet labels);
+ const char *object, const char *access);
/*!
* Remove rule from a rule set.
*
- * Takes subject and object as long names and maps them to short names if the
- * parameter labels is given (not set to NULL). In this case, if short labels
- * are not found, this function fails and executes no action.
- *
* @param handle handle to a rule set
* @param subject subject of the rule
* @param object object of the rule
- * @param labels handle to a label set
* @return 0 on success
*/
extern void smack_rule_set_remove(SmackRuleSet handle, const char *subject,
- const char *object, SmackLabelSet labels);
+ const char *object);
/*!
* Remove all rules with the given subject from a rule set.
*
- * Takes subject as long name and maps it to short name if the
- * parameter labels is given (not set to NULL). In this case,
- * if short label is not found, this function fails and executes
- * no action.
- *
* @param handle handle to a rule set
* @param subject subject of the rule
- * @param labels handle to a label set
*/
extern void smack_rule_set_remove_by_subject(SmackRuleSet handle,
- const char *subject,
- SmackLabelSet labels);
+ const char *subject);
/*!
* Remove all rules with the given object from a rule set.
- * Takes subject as long name and maps it to short name if the
- * parameter labels is given (not set to NULL). In this case,
- * if short label is not found, this function fails and executes
- * no action.
- *
* @param handle handle to a rule set
* @param object object of the rule
- * @param labels handle to a label set
*/
extern void smack_rule_set_remove_by_object(SmackRuleSet handle,
- const char *object,
- SmackLabelSet labels);
+ const char *object);
/*!
* Check access to a give object.
*
- * Takes subject and object as long names and maps them to short names if the
- * parameter labels is given (not set to NULL). In this case, if short labels
- * are not found, this function returns failure condition.
- *
* @param handle handle to a rule set
* @param subject subject of the rule
* @param object object of the rule
* @param access string defining access type
- * @param labels handle to a label set
* @return 1 if access, 0 if no access and negative number of failure.
*/
extern int smack_rule_set_have_access(SmackRuleSet handle, const char *subject,
- const char *object, const char *access,
- SmackLabelSet labels);
-
-/*!
- * Create a new label set. The returned rule set must be freed with
- * smack_label_set_delete().
- *
- * @return handle to the rule set. Returns NULL if allocation fails.
- */
-extern SmackLabelSet smack_label_set_new(void);
-
-/*!
- * Read labels from a given file.
- *
- * @param path path to the file containing label set
- *
- * @return SmackLabelSet instance on success
- */
-extern SmackLabelSet smack_label_set_new_from_file(const char *path);
-
-/*!
- * Free resources allocated by labels.
- *
- * @param handle handle to a rules
- */
-void smack_label_set_delete(SmackLabelSet handle);
-
-/*!
- * Write labels to a given file.
- *
- * @param handle handle to label set
- * @param path path to the label set file
- * @return 0 on success
- */
-extern int smack_label_set_save_to_file(SmackLabelSet handle, const char *path);
-
-/*!
- * Calculate eight byte short name from long name.
- *
- * @param long_name long name for the label
- * @param short_name short name of the label. Given character
- * array must have size 9 at minimum.
- */
-extern void smack_label_set_get_short_name(const char *long_name,
- char *short_name);
-
-/*!
- * Add new label to a label set.
- *
- * @param handle handle to a label set
- * @param long_name long name for the label as input
- *
- * @return pointer to the short name is returned when the operation is
- * succesful. Otherwise, NULL is returned.
- */
-extern const char *smack_label_set_add(SmackLabelSet handle,
- const char *long_name);
-
-/*!
- * Remove a label from a label set.
- *
- * @param handle handle to a label set
- * @param long_name long label
- */
-extern void smack_label_set_remove(SmackLabelSet handle, const char *long_name);
-
-/*!
- * Get short label.
- *
- * @param handle handle to a label set
- * @param long_name long label
- */
-extern const char *smack_label_set_to_short_name(SmackLabelSet handle,
- const char *long_name);
-
-/*!
- * Get long label.
- *
- * @param handle handle to a label set
- * @param short_name short_name
- */
-extern const char *smack_label_set_to_long_name(SmackLabelSet handle,
- const char *short_name);
-
-
-/*!
- * Set SMACK64 security attribute for a given file.
- *
- * @param path path to a file
- * @param attr attribute name
- * @param smack new value
- * @param labels label set. Not used if set to NULL. Otherwise, converts
- * to short name.
- * @return 0 on success
- */
-extern int smack_xattr_set_to_file(const char *path, const char *attr,
- const char *smack, SmackLabelSet labels);
-
-/*!
- * Get SMACK64 security attribute for a given path.
- * Allocated memory must be freed by the caller.
- *
- * @param path path to a file
- * @param attr attribute name
- * @param smack attribute value
- * @param size size of the character array reserved for the value
- * @param labels label set. Not used if set to NULL. Otherwise, converts
- * to long name.
- * @return 0 on success
- */
-extern ssize_t smack_xattr_get_from_file(const char *path, const char *attr,
- char *smack, size_t size,
- SmackLabelSet labels);
-
-/*!
- * Get SMACK64 security attribute for a given pid.
- *
- * @param pid pid of a process
- * @param smack attribute value
- * @param size size of the character array reserved for the value
- * @param labels label set. Not used if set to NULL. Otherwise, converts
- * to long name.
- * @return 0 on success
- */
-extern ssize_t smack_xattr_get_from_proc(int pid, char *smack,
- size_t size,
- SmackLabelSet labels);
+ const char *object, const char *access);
#ifdef __cplusplus
}
+++ /dev/null
-/*
- * This file is part of libsmack
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- * Authors:
- * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
- */
-
-#ifndef SMACK_INTERNAL_H
-#define SMACK_INTERNAL_H
-
-#define SMACK_PROC_PATH "/proc/%d/attr/current"
-
-#define SMACK64_LEN 23
-
-#define ACC_R 1
-#define ACC_W 2
-#define ACC_X 4
-#define ACC_A 16
-#define ACC_LEN 4
-
-#endif // SMACK_INTERNAL_H
+++ /dev/null
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <uthash.h>
-#include "smack.h"
-#include "smack_internal.h"
-
-struct smack_label {
- char *long_name;
- char *short_name;
- UT_hash_handle long_name_hh;
- UT_hash_handle short_name_hh;
-};
-
-struct _SmackLabelSet {
- struct smack_label *label_by_long_name;
- struct smack_label *label_by_short_name;
-};
-
-static struct smack_label *add_label(struct smack_label **label_by_long_name,
- struct smack_label **label_by_short_name,
- const char *long_name,
- const char *short_name);
-
-extern SmackLabelSet smack_label_set_new(void)
-{
- struct _SmackLabelSet *result =
- calloc(1, sizeof(struct _SmackLabelSet));
- return result;
-}
-
-extern SmackLabelSet smack_label_set_new_from_file(const char *path)
-{
- SmackLabelSet labels;
- FILE *file;
- char *buf = NULL;
- const char *ll, *sl;
- size_t size;
- struct smack_label *l;
- int ret = 0;
-
- file = fopen(path, "r");
- if (file == NULL)
- return NULL;
-
- labels = smack_label_set_new();
- if (labels == NULL) {
- fclose(file);
- return NULL;
- }
-
- while (ret == 0 && getline(&buf, &size, file) != -1) {
- ll = strtok(buf, " \t\n");
- sl = strtok(NULL, " \t\n");
-
- if (ll == NULL || sl == NULL ||
- strtok(NULL, " \t\n") != NULL ||
- strlen(sl) > SMACK64_LEN) {
- ret = -1;
- break;
- }
-
- l = add_label(&labels->label_by_long_name,
- &labels->label_by_short_name,
- ll, sl);
- if (l == NULL) {
- ret = -1;
- break;
- }
-
- free(buf);
- buf = NULL;
- }
-
- if (ret != 0 || ferror(file)) {
- smack_label_set_delete(labels);
- labels = NULL;
- }
-
- free(buf);
- fclose(file);
- return labels;
-}
-
-void smack_label_set_delete(SmackLabelSet handle)
-{
- struct smack_label *l, *tmp;
-
- if (handle == NULL)
- return;
-
- HASH_ITER(long_name_hh, handle->label_by_long_name, l, tmp) {
- HASH_DELETE(long_name_hh, handle->label_by_long_name, l);
- HASH_DELETE(short_name_hh, handle->label_by_short_name, l);
- free(l->long_name);
- free(l->short_name);
- free(l);
- }
-}
-
-int smack_label_set_save_to_file(SmackLabelSet handle, const char *path)
-{
- struct smack_label *s, *stmp;
- FILE *file;
- int err = 0;
-
- file = fopen(path, "w+");
- if (!file)
- return -1;
-
- HASH_ITER(long_name_hh, handle->label_by_long_name, s, stmp) {
- err = fprintf(file, "%s %s\n",
- s->long_name, s->short_name);
-
- if (err < 0) {
- fclose(file);
- return errno;
- }
- }
-
- fclose(file);
- return 0;
-}
-
-void smack_label_set_get_short_name(const char *long_name,
- char *short_name)
-{
- uint32_t h;
- int i, c;
-
- // djb2 based on http://www.cse.yorku.ca/~oz/hash.html
- h = 5381;
-
- for (i = 0; long_name[i] != '\0'; i++) {
- c = long_name[i];
- h = ((h << 5) + h) + c;
- }
-
- sprintf(short_name, "%08X", h);
-}
-
-const char *smack_label_set_add(SmackLabelSet handle, const char *long_name)
-{
- char short_name[SMACK64_LEN + 1];
- struct smack_label *l;
-
- smack_label_set_get_short_name(long_name, short_name);
-
- l = add_label(&handle->label_by_long_name,
- &handle->label_by_short_name,
- long_name, short_name);
-
- return l != NULL ? l->short_name : NULL;
-}
-
-void smack_label_set_remove(SmackLabelSet handle, const char *long_name)
-{
- struct smack_label *l;
-
- HASH_FIND(long_name_hh, handle->label_by_long_name, long_name, strlen(long_name), l);
-
- if (l == NULL)
- return;
-
- HASH_DELETE(long_name_hh, handle->label_by_long_name, l);
- HASH_DELETE(short_name_hh, handle->label_by_short_name, l);
- free(l->long_name);
- free(l->short_name);
- free(l);
-}
-
-const char *smack_label_set_to_short_name(SmackLabelSet handle,
- const char *long_name)
-{
- struct smack_label *l;
- const char *res;
-
- HASH_FIND(long_name_hh, handle->label_by_long_name, long_name, strlen(long_name), l);
-
- if (l == NULL)
- return NULL;
-
- return l->short_name;
-}
-
-const char *smack_label_set_to_long_name(SmackLabelSet handle,
- const char *short_name)
-{
- struct smack_label *l;
- const char *res;
-
- HASH_FIND(short_name_hh, handle->label_by_short_name, short_name, strlen(short_name), l);
-
- if (l == NULL)
- return NULL;
-
- return l->long_name;
-}
-
-static struct smack_label *add_label(struct smack_label **label_by_long_name,
- struct smack_label **label_by_short_name,
- const char *long_name,
- const char *short_name)
-{
- struct smack_label *l;
-
- HASH_FIND(long_name_hh, *label_by_long_name, long_name,
- strlen(long_name), l);
- if (l != NULL)
- return NULL;
-
- HASH_FIND(short_name_hh, *label_by_short_name, short_name,
- strlen(short_name), l);
- if (l != NULL)
- return NULL;
-
- l = calloc(1, sizeof(struct smack_label));
- if (l == NULL)
- return NULL;
-
- l->long_name = strdup(long_name);
- l->short_name = strdup(short_name);
-
- if (l->long_name == NULL || l->short_name == NULL) {
- free(l->long_name);
- free(l->short_name);
- free(l);
- return NULL;
- }
-
- HASH_ADD_KEYPTR(long_name_hh, *label_by_long_name, l->long_name, strlen(l->long_name), l);
- HASH_ADD_KEYPTR(short_name_hh, *label_by_short_name, l->short_name, strlen(l->short_name), l);
-
- return l;
-}
-
+++ /dev/null
-/*
- * This file is part of libsmack
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- * Authors:
- * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
- */
-
-#include <sys/types.h>
-#include <attr/xattr.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <uthash.h>
-#include "smack.h"
-#include "smack_internal.h"
-
-int smack_xattr_set_to_file(const char *path, const char *attr,
- const char *smack, SmackLabelSet labels)
-{
- size_t size;
- int ret;
-
- if (labels != NULL)
- smack = smack_label_set_to_short_name(labels, smack);
-
- if (smack == NULL)
- return -1;
-
- size = strlen(smack);
- if (size > SMACK64_LEN)
- return -1;
-
- ret = setxattr(path, attr, smack, size, 0);
-
- return ret;
-}
-
-ssize_t smack_xattr_get_from_file(const char *path, const char *attr,
- char *smack, size_t size, SmackLabelSet labels)
-{
- ssize_t ret;
- char buf[SMACK64_LEN + 2];
- const char *result;
- size_t rsize;
-
- ret = getxattr(path, attr, buf, SMACK64_LEN + 1);
- if (ret < 0)
- return -1;
-
- buf[ret] = '\0';
-
- if (labels == NULL)
- result = buf;
- else
- result = smack_label_set_to_long_name(labels, buf);
-
- if (result == NULL)
- return -1;
-
- rsize = strlen(result) + 1;
-
- if (smack == NULL)
- return rsize;
- else if (size < rsize)
- return -1;
-
- strcpy(smack, result);
-
- return 0;
-}
-
-ssize_t smack_xattr_get_from_proc(int pid, char *smack,
- size_t size,
- SmackLabelSet labels)
-{
- char buf[512];
- FILE *file;
- const char *result;
- size_t rsize;
-
- snprintf(buf, sizeof(buf), SMACK_PROC_PATH, pid);
-
- file = fopen(buf, "r");
- if (file == NULL)
- return -1;
-
- if (fgets(buf, sizeof(buf), file) == NULL) {
- fclose(file);
- return -1;
- }
-
- fclose(file);
-
- if (labels == NULL)
- result = buf;
- else
- result = smack_label_set_to_long_name(labels, buf);
-
- if (result == NULL)
- return -1;
-
- rsize = strlen(result) + 1;
-
- if (smack == NULL)
- return rsize;
- else if (size < rsize)
- return -1;
-
- strcpy(smack, result);
- return 0;
-}
-
-TESTS = check_rules check_xattr
-check_PROGRAMS = check_rules check_xattr
+TESTS = check_smack
+check_PROGRAMS = check_smack
-check_rules_SOURCES = check_rules.c $(top_builddir)/src/smack.h
-check_rules_CFLAGS = @CHECK_CFLAGS@
-check_rules_LDADD = $(top_builddir)/src/libsmack.la @CHECK_LIBS@
-
-check_xattr_SOURCES = check_xattr.c $(top_builddir)/src/smack.h
-check_xattr_CFLAGS = @CHECK_CFLAGS@
-check_xattr_LDADD = $(top_builddir)/src/libsmack.la @CHECK_LIBS@
+check_smack_SOURCES = check_smack.c $(top_builddir)/src/smack.h
+check_smack_CFLAGS = @CHECK_CFLAGS@
+check_smack_LDADD = $(top_builddir)/src/libsmack.la @CHECK_LIBS@
+++ /dev/null
-/*
- * This file is part of libsmack
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- * Author: Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <check.h>
-#include "../src/smack.h"
-
-#define LONG_LABEL_1 "FooFooFooFooFooFooFooFooFooFooFooFooFoo"
-#define LONG_LABEL_2 "BarBarBarBarBarBarBarBarBarBarBarBarBar"
-
-static int files_equal(const char *filename1, const char *filename2);
-
-START_TEST(test_rule_set_read_from_file_and_save_to_kernel)
-{
- int rc;
- const char *sn;
- SmackLabelSet labels;
- SmackRuleSet rules;
-
- labels = smack_label_set_new();
- fail_unless(labels != NULL, "Creating label set failed");
-
- sn = smack_label_set_add(labels, LONG_LABEL_1);
- fail_unless(sn != NULL, "Adding label was not succesful");
-
- sn = smack_label_set_add(labels, LONG_LABEL_2);
- fail_unless(sn != NULL, "Adding label was not succesful");
-
- rules = smack_rule_set_new_from_file(
- "data/rule_set_read_from_file_and_save_to_kernel-in.txt", NULL, labels);
- fail_unless(rules != NULL, "Reading rules failed");
-
- if (rules == NULL)
- return;
-
- rc = smack_rule_set_save_to_file(rules,
- "rule_set_read_from_file_and_save_to_kernel-result.txt",
- NULL);
- fail_unless(rc == 0, "Failed to write ruleset");
-
- rc = files_equal(
- "rule_set_read_from_file_and_save_to_kernel-result.txt",
- "data/rule_set_read_from_file_and_save_to_kernel-excepted.txt");
- fail_unless(rc == 1, "Unexcepted result");
-
- smack_rule_set_delete(rules);
- smack_label_set_delete(labels);
-}
-END_TEST
-
-START_TEST(test_rule_set_add_and_save_to_file)
-{
- int rc;
- const char *sn;
-
- SmackRuleSet rules = smack_rule_set_new();
- fail_unless(rules != NULL, "Creating rule set failed");
-
- SmackLabelSet labels = smack_label_set_new();
- fail_unless(labels != NULL, "Creating label set failed");
-
- sn = smack_label_set_add(labels, LONG_LABEL_1);
- fail_unless(sn != NULL, "Adding label was not succesful");
-
- sn = smack_label_set_add(labels, LONG_LABEL_2);
- fail_unless(sn != NULL, "Adding label was not succesful");
-
- rc = smack_rule_set_add(rules, LONG_LABEL_1, LONG_LABEL_2, "rx", labels);
- fail_unless(rc == 0, "Adding rule was not succesful");
-
- rc = smack_rule_set_add(rules, LONG_LABEL_2, LONG_LABEL_1, "rwa", labels);
- fail_unless(rc == 0, "Adding rule was not succesful");
-
- rc = smack_rule_set_save_to_file(rules,
- "rule_set_add_and_save_to_config-result.txt",
- labels);
- fail_unless(rc == 0, "Failed to write ruleset");
-
- rc = files_equal(
- "rule_set_add_and_save_to_config-result.txt",
- "data/rule_set_add_and_save_to_config-excepted.txt");
- fail_unless(rc == 1, "Unexcepted result");
-
- smack_rule_set_delete(rules);
- smack_label_set_delete(labels);
-}
-END_TEST
-
-START_TEST(test_rule_set_remove_and_save_to_kernel)
-{
- int rc;
- SmackRuleSet rules;
-
- rules = smack_rule_set_new_from_file(
- "data/rule_set_remove_and_save_to_kernel-in.txt", NULL, NULL);
- fail_unless(rules != NULL, "Reading rules failed");
-
- smack_rule_set_remove(rules, "Orange", "Apple", NULL);
-
- rc = smack_rule_set_save_to_kernel(rules,
- "rule_set_remove_and_save_to_kernel-result.txt");
- fail_unless(rc == 0, "Failed to write ruleset");
-
- rc = files_equal(
- "rule_set_remove_and_save_to_kernel-result.txt",
- "data/rule_set_remove_and_save_to_kernel-excepted.txt");
- fail_unless(rc == 1, "Unexcepted result");
-
- smack_rule_set_delete(rules);
-}
-END_TEST
-
-START_TEST(test_rule_set_remove_by_subject_and_save_to_kernel)
-{
- int rc;
- SmackRuleSet rules;
-
- rules = smack_rule_set_new_from_file(
- "data/rule_set_remove_by_subject_and_save_to_kernel-in.txt",
- NULL, NULL);
- fail_unless(rules != NULL, "Reading rules failed");
-
- smack_rule_set_remove_by_subject(rules, "Foo", NULL);
-
- rc = smack_rule_set_save_to_kernel(rules,
- "rule_set_remove_by_subject_and_save_to_kernel-result.txt");
- fail_unless(rc == 0, "Failed to write ruleset");
-
- rc = files_equal(
- "rule_set_remove_by_subject_and_save_to_kernel-result.txt",
- "data/rule_set_remove_by_subject_and_save_to_kernel-excepted.txt");
- fail_unless(rc == 1, "Unexcepted result");
-
- smack_rule_set_delete(rules);
-}
-END_TEST
-
-START_TEST(test_rule_set_remove_by_object_and_save_to_kernel)
-{
- int rc;
- SmackRuleSet rules;
-
- rules = smack_rule_set_new_from_file(
- "data/rule_set_remove_by_object_and_save_to_kernel-in.txt",
- NULL, NULL);
- fail_unless(rules != NULL, "Reading rules failed");
-
- smack_rule_set_remove_by_object(rules, "Apple", NULL);
-
- rc = smack_rule_set_save_to_kernel(rules,
- "rule_set_remove_by_object_and_save_to_kernel-result.txt");
- fail_unless(rc == 0, "Failed to write ruleset");
-
- rc = files_equal(
- "rule_set_remove_by_object_and_save_to_kernel-result.txt",
- "data/rule_set_remove_by_object_and_save_to_kernel-excepted.txt");
- fail_unless(rc == 1, "Unexcepted result");
-
- smack_rule_set_delete(rules);
-}
-END_TEST
-
-START_TEST(test_rule_set_add_remove_long)
-{
- int rc;
- const char *sn;
-
- SmackRuleSet rules = smack_rule_set_new();
- fail_unless(rules != NULL, "Creating rule set failed");
-
- SmackLabelSet labels = smack_label_set_new();
- fail_unless(labels != NULL, "Creating label set failed");
-
- sn = smack_label_set_add(labels, LONG_LABEL_1);
- fail_unless(sn != NULL, "Adding label was not succesful");
-
- sn = smack_label_set_add(labels, LONG_LABEL_2);
- fail_unless(sn != NULL, "Adding label was not succesful");
-
- rc = smack_rule_set_add(rules, LONG_LABEL_1, LONG_LABEL_2, "rx", labels);
- fail_unless(rc == 0, "Adding rule was not succesful");
-
- rc = smack_rule_set_add(rules, LONG_LABEL_2, LONG_LABEL_1, "rwa", labels);
- fail_unless(rc == 0, "Adding rule was not succesful");
-
- smack_rule_set_remove(rules, LONG_LABEL_1, LONG_LABEL_2, labels);
-
- rc = smack_rule_set_have_access(rules, LONG_LABEL_2, LONG_LABEL_1, "a", labels);
- fail_unless(rc, "Access failure");
-
- rc = smack_rule_set_have_access(rules, LONG_LABEL_1, LONG_LABEL_2, "r", labels);
- fail_unless(!rc, "Access failure");
-
- smack_rule_set_delete(rules);
- smack_label_set_delete(labels);
-}
-END_TEST
-
-START_TEST(test_rule_set_add_long_no_labels)
-{
- int rc;
-
- SmackRuleSet rules = smack_rule_set_new();
- fail_unless(rules != NULL, "Creating rule set failed");
-
- SmackLabelSet labels = smack_label_set_new();
- fail_unless(labels != NULL, "Creating label set failed");
-
- rc = smack_rule_set_add(rules, LONG_LABEL_1, LONG_LABEL_2, "rx", labels);
- fail_unless(rc != 0, "Adding rule was succesful");
-
- smack_rule_set_delete(rules);
- smack_label_set_delete(labels);
-}
-END_TEST
-
-Suite *ruleset_suite (void)
-{
- Suite *s;
- TCase *tc_core;
-
- s = suite_create("Rules");
-
- tc_core = tcase_create("Rules");
- tcase_add_test(tc_core, test_rule_set_read_from_file_and_save_to_kernel);
- tcase_add_test(tc_core, test_rule_set_add_and_save_to_file);
- tcase_add_test(tc_core, test_rule_set_remove_and_save_to_kernel);
- tcase_add_test(tc_core, test_rule_set_remove_by_subject_and_save_to_kernel);
- tcase_add_test(tc_core, test_rule_set_remove_by_object_and_save_to_kernel);
- tcase_add_test(tc_core, test_rule_set_add_remove_long);
- tcase_add_test(tc_core, test_rule_set_add_long_no_labels);
- suite_add_tcase(s, tc_core);
-
- return s;
-}
-
-int main(void)
-{
- int nfailed;
- Suite *s = ruleset_suite();
- SRunner *sr = srunner_create(s);
- srunner_set_log(sr, "check_rules.log");
- srunner_run_all(sr, CK_ENV);
- nfailed = srunner_ntests_failed(sr);
- srunner_free(sr);
- return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int files_equal(const char *filename1, const char *filename2)
-{
- FILE *fp1 = NULL;
- FILE *fp2 = NULL;
- char ch1, ch2;
- int rc = 0;
-
- fp1 = fopen(filename1, "rb");
- if (fp1 == NULL) {
- goto out;
- }
-
- fp2 = fopen(filename2, "rb");
- if (fp2 == NULL) {
- goto out;
- }
-
- rc = 1;
- for (;;) {
- if (feof(fp1) && feof(fp2))
- break;
-
- if (feof(fp1) || feof(fp2)) {
- rc = 0;
- break;
- }
-
- ch1 = fgetc(fp1);
- if (ferror(fp1)) {
- rc = 0;
- break;
- }
-
- ch2 = fgetc(fp2);
- if (ferror(fp2)) {
- rc = 0;
- break;
- }
-
- if (ch1 != ch2) {
- rc = 0;
- break;
- }
- }
-out:
- if (fp1 != NULL)
- fclose(fp1);
- if (fp2 != NULL)
- fclose(fp2);
- return rc;
-}
-
--- /dev/null
+/*
+ * This file is part of libsmack
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Author: Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <check.h>
+#include "../src/smack.h"
+
+static int files_equal(const char *filename1, const char *filename2);
+
+START_TEST(test_save_to_kernel)
+{
+ int rc;
+ const char *sn;
+ SmackRuleSet rules;
+
+ rules = smack_rule_set_new();
+ fail_unless(rules != NULL, "Creating rule set failed");
+ if (rules == NULL)
+ return;
+
+ smack_rule_set_add(rules, "Apple", "Orange", "rwx");
+ smack_rule_set_add(rules, "Plum", "Peach", "rx");
+ smack_rule_set_add(rules, "Banana", "Peach", "xa");
+
+ smack_rule_set_remove(rules, "Plum", "Peach");
+
+ rc = smack_rule_set_save_to_kernel(
+ rules,
+ "test_save_to_kernel-result.txt");
+ fail_unless(rc == 0, "Failed to write the rule set");
+
+ rc = files_equal(
+ "test_save_to_kernel-result.txt",
+ "data/test_save_to_kernel-excepted.txt");
+ fail_unless(rc == 1, "Unexcepted result");
+
+ smack_rule_set_delete(rules);
+}
+END_TEST
+
+START_TEST(test_save_to_file)
+{
+ int rc;
+ const char *sn;
+ SmackRuleSet rules;
+
+ rules = smack_rule_set_new();
+ fail_unless(rules != NULL, "Creating rule set failed");
+ if (rules == NULL)
+ return;
+
+ smack_rule_set_add(rules, "Apple", "Orange", "rwx");
+ smack_rule_set_add(rules, "Plum", "Peach", "rx");
+ smack_rule_set_add(rules, "Banana", "Peach", "xa");
+
+ smack_rule_set_remove(rules, "Plum", "Peach");
+
+ rc = smack_rule_set_save_to_file(
+ rules,
+ "test_save_to_file-result.txt");
+ fail_unless(rc == 0, "Failed to write the rule set");
+
+ rc = files_equal(
+ "test_save_to_file-result.txt",
+ "data/test_save_to_file-excepted.txt");
+ fail_unless(rc == 1, "Unexcepted result");
+
+ smack_rule_set_delete(rules);
+}
+END_TEST
+
+START_TEST(test_rule_set_remove_by_subject)
+{
+ int rc;
+ SmackRuleSet rules;
+
+ rules = smack_rule_set_new();
+ fail_unless(rules != NULL, "Creating rule set failed");
+ if (rules == NULL)
+ return;
+
+ smack_rule_set_add(rules, "Apple", "Orange", "rwx");
+ smack_rule_set_add(rules, "Plum", "Peach", "rx");
+ smack_rule_set_add(rules, "Banana", "Peach", "xa");
+
+ smack_rule_set_remove_by_subject(rules, "Plum");
+
+ rc = smack_rule_set_have_access(rules, "Plum", "Peach", "rx");
+ fail_unless(rc == 0, "Access granted to a removed rule");
+
+ smack_rule_set_delete(rules);
+}
+END_TEST
+
+START_TEST(test_rule_set_remove_by_object)
+{
+ int rc;
+ SmackRuleSet rules;
+
+ rules = smack_rule_set_new();
+ fail_unless(rules != NULL, "Creating rule set failed");
+ if (rules == NULL)
+ return;
+
+ smack_rule_set_add(rules, "Apple", "Orange", "rwx");
+ smack_rule_set_add(rules, "Plum", "Peach", "rx");
+ smack_rule_set_add(rules, "Banana", "Peach", "xa");
+
+ smack_rule_set_remove_by_object(rules, "Peach");
+
+ rc = smack_rule_set_have_access(rules, "Plum", "Peach", "rx");
+ fail_unless(rc == 0, "Access granted to a removed rule");
+
+ smack_rule_set_delete(rules);
+}
+END_TEST
+
+Suite *ruleset_suite (void)
+{
+ Suite *s;
+ TCase *tc_core;
+
+ s = suite_create("Rules");
+
+ tc_core = tcase_create("Rules");
+ tcase_add_test(tc_core, test_save_to_kernel);
+ tcase_add_test(tc_core, test_save_to_file);
+ tcase_add_test(tc_core, test_rule_set_remove_by_subject);
+ tcase_add_test(tc_core, test_rule_set_remove_by_object);
+ suite_add_tcase(s, tc_core);
+
+ return s;
+}
+
+int main(void)
+{
+ int nfailed;
+ Suite *s = ruleset_suite();
+ SRunner *sr = srunner_create(s);
+ srunner_set_log(sr, "check_rules.log");
+ srunner_run_all(sr, CK_ENV);
+ nfailed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static int files_equal(const char *filename1, const char *filename2)
+{
+ FILE *fp1 = NULL;
+ FILE *fp2 = NULL;
+ char ch1, ch2;
+ int rc = 0;
+
+ fp1 = fopen(filename1, "rb");
+ if (fp1 == NULL) {
+ goto out;
+ }
+
+ fp2 = fopen(filename2, "rb");
+ if (fp2 == NULL) {
+ goto out;
+ }
+
+ rc = 1;
+ for (;;) {
+ if (feof(fp1) && feof(fp2))
+ break;
+
+ if (feof(fp1) || feof(fp2)) {
+ rc = 0;
+ break;
+ }
+
+ ch1 = fgetc(fp1);
+ if (ferror(fp1)) {
+ rc = 0;
+ break;
+ }
+
+ ch2 = fgetc(fp2);
+ if (ferror(fp2)) {
+ rc = 0;
+ break;
+ }
+
+ if (ch1 != ch2) {
+ rc = 0;
+ break;
+ }
+ }
+out:
+ if (fp1 != NULL)
+ fclose(fp1);
+ if (fp2 != NULL)
+ fclose(fp2);
+ return rc;
+}
+
+++ /dev/null
-/*
- * This file is part of libsmack
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- * Author: Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <check.h>
-#include "../src/smack.h"
-
-#define LONG_LABEL_1 "FooFooFooFooFooFooFooFooFooFooFooFooFoo"
-
-static int files_equal(const char *filename1, const char *filename2);
-
-START_TEST(test_xattr_set_to_file_smack)
-{
- FILE *file;
- int rc = 0;
- char smack[100];
-
- file = fopen("set_smack-dummy.txt", "w");
- fprintf(file, "dummy\n");
- fclose(file);
-
- rc = smack_xattr_set_to_file("set_smack-dummy.txt", SMACK64, "Apple", NULL);
- fail_unless(rc == 0, "Failed to set SMACK64");
-
- rc = smack_xattr_get_from_file("set_smack-dummy.txt", SMACK64, smack, 100, NULL);
- fail_unless(rc == 0, "Failed to get SMACK64");
-
- rc = strcmp(smack, "Apple");
- fail_unless(rc == 0, "smack %s not equal to Apple", smack);
-}
-END_TEST
-
-START_TEST(test_xattr_set_to_file_smackexec)
-{
- FILE *file;
- int rc;
- char smack[100];
-
- file = fopen("set_smack-dummy.txt", "w");
- fprintf(file, "dummy\n");
- fclose(file);
-
- rc = smack_xattr_set_to_file("set_smack-dummy.txt", SMACK64EXEC, "Apple", NULL);
- fail_unless(rc == 0, "Failed to set SMACK64EXEC");
-
- rc = smack_xattr_get_from_file("set_smack-dummy.txt", SMACK64EXEC, smack, 100, NULL);
- fail_unless(rc == 0, "Failed to get SMACK64EXEC");
-
- rc = strcmp(smack, "Apple");
- fail_unless(rc == 0, "smack %s not equal to Apple", smack);
-}
-END_TEST
-
-START_TEST(test_xattr_set_to_file_smack_long_label)
-{
- FILE *file;
- int rc = 0;
- SmackLabelSet labels;
- char smack[100];
-
- file = fopen("set_smack-dummy.txt", "w");
- fprintf(file, "dummy\n");
- fclose(file);
-
- labels = smack_label_set_new();
- fail_unless(labels != NULL, "Creating label set failed");
-
- smack_label_set_add(labels, LONG_LABEL_1);
- fail_unless(rc == 0, "Adding label was not succesful");
-
- rc = smack_xattr_set_to_file("set_smack-dummy.txt", SMACK64, LONG_LABEL_1, labels);
- fail_unless(rc == 0, "Failed to set SMACK64");
-
- rc = smack_xattr_get_from_file("set_smack-dummy.txt", SMACK64, smack, 100, labels);
- fail_unless(rc == 0, "Failed to get SMACK64");
-
- rc = strcmp(smack, LONG_LABEL_1);
- fail_unless(rc == 0, "smack %s not equal to Apple", smack);
-
- smack_label_set_delete(labels);
-}
-END_TEST
-
-Suite *ruleset_suite (void)
-{
- Suite *s;
- TCase *tc_core;
-
- s = suite_create("Xattr");
-
- tc_core = tcase_create("Xattr");
- tcase_add_test(tc_core, test_xattr_set_to_file_smack);
- tcase_add_test(tc_core, test_xattr_set_to_file_smackexec);
- tcase_add_test(tc_core, test_xattr_set_to_file_smack_long_label);
- suite_add_tcase(s, tc_core);
-
- return s;
-}
-
-int main(void)
-{
- int nfailed;
- Suite *s = ruleset_suite();
- SRunner *sr = srunner_create(s);
- srunner_set_log(sr, "check_xattr.log");
- srunner_run_all(sr, CK_ENV);
- nfailed = srunner_ntests_failed(sr);
- srunner_free(sr);
- return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int files_equal(const char *filename1, const char *filename2)
-{
- FILE *fp1 = NULL;
- FILE *fp2 = NULL;
- char ch1, ch2;
- int rc = 0;
-
- fp1 = fopen(filename1, "rb");
- if (fp1 == NULL) {
- goto out;
- }
-
- fp2 = fopen(filename2, "rb");
- if (fp2 == NULL) {
- goto out;
- }
-
- rc = 1;
- for (;;) {
- if (feof(fp1) && feof(fp2))
- break;
-
- if (feof(fp1) || feof(fp2)) {
- rc = 0;
- break;
- }
-
- ch1 = fgetc(fp1);
- if (ferror(fp1)) {
- rc = 0;
- break;
- }
-
- ch2 = fgetc(fp2);
- if (ferror(fp2)) {
- rc = 0;
- break;
- }
-
- if (ch1 != ch2) {
- rc = 0;
- break;
- }
- }
-out:
- if (fp1 != NULL)
- fclose(fp1);
- if (fp2 != NULL)
- fclose(fp2);
- return rc;
-}
-
+++ /dev/null
-FooFooFooFooFooFooFooFooFooFooFooFooFoo BarBarBarBarBarBarBarBarBarBarBarBarBar rx
-BarBarBarBarBarBarBarBarBarBarBarBarBar FooFooFooFooFooFooFooFooFooFooFooFooFoo rwa
+++ /dev/null
-E6BE6519 E1CEA9D6 rx
-E1CEA9D6 E6BE6519 rwa
+++ /dev/null
-FooFooFooFooFooFooFooFooFooFooFooFooFoo BarBarBarBarBarBarBarBarBarBarBarBarBar rx
-BarBarBarBarBarBarBarBarBarBarBarBarBar FooFooFooFooFooFooFooFooFooFooFooFooFoo rwa
+++ /dev/null
-Foo Bar r-x-
-Foo Apple -wx-
-Orange Apple ----
+++ /dev/null
-Foo Bar rx
-Orange Apple ra
-Foo Apple wx
+++ /dev/null
-Foo Bar r-x-
-Foo Apple ----
-Orange Apple ----
+++ /dev/null
-Foo Bar rx
-Orange Apple ra
-Foo Apple wx
+++ /dev/null
-Foo Bar ----
-Foo Apple ----
-Orange Apple r--a
+++ /dev/null
-Foo Bar rx
-Orange Apple ra
-Foo Apple wx
--- /dev/null
+Apple Orange rwx
+Banana Peach xa
--- /dev/null
+Apple Orange rwx-
+Plum Peach ----
+Banana Peach --xa