Implemented labels API.
authorJarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
Mon, 22 Nov 2010 16:31:41 +0000 (08:31 -0800)
committerJarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
Mon, 22 Nov 2010 17:07:31 +0000 (09:07 -0800)
src/smack.h
src/smack_labels.c
src/smack_rules.c

index f48ca86..40722e5 100644 (file)
@@ -188,7 +188,7 @@ extern int smack_xattr_get_from_proc(int pid, char **smack);
  *
  * @return handle to the rule set. Returns NULL if allocation fails.
  */
-extern SmackLabelSet *smack_label_set_new(void);
+extern SmackLabelSet smack_label_set_new(void);
 
 /*!
  * Read labels from a given file.
@@ -204,7 +204,7 @@ extern SmackLabelSet smack_label_set_new_from_file(const char *path,
  *
  * @param handle handle to a rules
  */
-void smack_label_set_delete(SmackLabelSet *handle);
+void smack_label_set_delete(SmackLabelSet handle);
 
 /*!
  * Add new label to a label set.
index 0bd0cca..0e981e7 100644 (file)
+#include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uthash.h>
 #include "smack.h"
 
-SmackLabelSet *smack_label_set_new(void)
+#define SMACK64_LEN 23
+struct smack_label {
+       char *long_label;
+       char *short_label;
+       UT_hash_handle long_hh;
+       UT_hash_handle short_hh;
+};
+
+struct _SmackLabelSet {
+       struct smack_label *labels;
+};
+
+static int add_label(struct smack_label **labels,
+                    const char *long_label,
+                    const char *short_label);
+
+SmackLabelSet smack_label_set_new(void)
 {
-    return NULL;
+       struct _SmackLabelSet *result =
+               calloc(1, sizeof(struct _SmackLabelSet));
+       return result;
 }
 
 extern SmackLabelSet smack_label_set_new_from_file(const char *path,
                                                   const char *subject)
 {
-       return NULL;
-}
+       SmackLabelSet labels;
+       FILE *file;
+       char *buf = NULL;
+       const char *ll, *sl;
+       size_t size;
+       int ret = 0;
 
+       file = fopen(path, "r");
+       if (file == NULL)
+               return NULL;
 
-void smack_label_set_delete(SmackLabelSet *handle)
-{
+       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) {
+                       ret = -1;
+               } else {
+                       ret = add_label(&labels->labels, ll, sl);
+               }
+
+               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;
+
+       HASH_ITER(long_hh, handle->labels, l, tmp) {
+               HASH_DELETE(long_hh, handle->labels, l);
+               HASH_DELETE(short_hh, handle->labels, l);
+               free(l->long_label);
+               free(l->short_label);
+               free(l);
+       }
+}
 
 int smack_label_set_add(SmackLabelSet handle, const char *long_label)
 {
-       return 0;
-}
+       char sl[SMACK64_LEN + 1];
+       int pos, len ,ret;
+
+       if (long_label == NULL || strlen(long_label) == 0)
+               return -EPERM;
 
+       len = strlen(long_label);
+       pos = (len > SMACK64_LEN) ? len - SMACK64_LEN : 0;
+
+       strcpy(sl, &long_label[pos]);
+
+       ret = add_label(&handle->labels, long_label, sl);
+
+       return ret == 0 ? 0  : -1;
+}
 
 const char *smack_label_set_to_short_label(SmackLabelSet handle,
                                           const char *long_label)
 {
-       return NULL;
+       struct smack_label *l;
+       HASH_FIND(long_hh, handle->labels, long_label, strlen(long_label), l);
+       return l->short_label;
 }
 
 const char *smack_label_set_to_long_label(SmackLabelSet handle,
                                          const char *short_label)
 {
-       return NULL;
+       struct smack_label *l;
+       HASH_FIND(short_hh, handle->labels, short_label, strlen(short_label), l);
+       return l->long_label;
+}
+
+static int add_label(struct smack_label **labels,
+                    const char *long_label,
+                    const char *short_label)
+{
+       struct smack_label *l;
+
+       if (strlen(short_label) > SMACK64_LEN)
+               return -ERANGE;
+
+       HASH_FIND(long_hh, *labels, long_label, strlen(long_label), l);
+       if (l != NULL)
+               return -EEXIST;
+
+       HASH_FIND(short_hh, *labels, short_label, strlen(short_label), l);
+       if (l != NULL)
+               return -EEXIST;
+
+       l = calloc(1, sizeof(struct smack_label));
+       if (l == NULL)
+               return -ENOMEM;
+
+       l->long_label = strdup(long_label);
+       l->short_label = strdup(short_label);
+
+       if (l->long_label == NULL || l->short_label == NULL) {
+               free(l->long_label);
+               free(l->short_label);
+               free(l);
+               return -ENOMEM;
+       }
+
+       HASH_ADD_KEYPTR(long_hh, *labels, l->long_label, strlen(l->long_label), l);
+       HASH_ADD_KEYPTR(short_hh, *labels, l->short_label, strlen(l->short_label), l);
+
+       return 0;
 }
 
index 16a73e6..786b46f 100644 (file)
@@ -70,6 +70,7 @@ SmackRuleSet smack_rule_set_new(void)
 SmackRuleSet smack_rule_set_new_from_file(const char *path,
                                         const char *subject_filter)
 {
+       SmackRuleSet rules;
        FILE *file;
        char *buf = NULL;
        const char *subject, *object, *access;
@@ -81,7 +82,7 @@ SmackRuleSet smack_rule_set_new_from_file(const char *path,
        if (file == NULL)
                return NULL;
 
-       SmackRuleSet rules = smack_rule_set_new();
+       rules = smack_rule_set_new();
        if (rules == NULL) {
                fclose(file);
                return NULL;