TOMOYO: Use common code for policy reading.

tomoyo_print_..._acl() are similar. Merge them.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 6c68981..a3c3b5d 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -746,217 +746,121 @@
 }
 
 /**
- * tomoyo_print_path_acl - Print a single path ACL entry.
+ * tomoyo_fns - Find next set bit.
  *
- * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_path_acl".
+ * @perm: 8 bits value.
+ * @bit:  First bit to find.
  *
- * Returns true on success, false otherwise.
+ * Returns next on-bit on success, 8 otherwise.
  */
-static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head,
-				  struct tomoyo_path_acl *ptr)
+static u8 tomoyo_fns(const u8 perm, u8 bit)
 {
-	int pos;
-	u8 bit;
-	const u16 perm = ptr->perm;
-
-	for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
-		if (!(perm & (1 << bit)))
-			continue;
-		if (head->print_execute_only && bit != TOMOYO_TYPE_EXECUTE)
-			continue;
-		/* Print "read/write" instead of "read" and "write". */
-		if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
-		    && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
-			continue;
-		pos = head->read_avail;
-		if (!tomoyo_io_printf(head, "allow_%s ",
-				      tomoyo_path_keyword[bit]) ||
-		    !tomoyo_print_name_union(head, &ptr->name) ||
-		    !tomoyo_io_printf(head, "\n"))
-			goto out;
-	}
-	head->read_bit = 0;
-	return true;
- out:
-	head->read_bit = bit;
-	head->read_avail = pos;
-	return false;
-}
-
-/**
- * tomoyo_print_path2_acl - Print a double path ACL entry.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_path2_acl".
- *
- * Returns true on success, false otherwise.
- */
-static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head,
-				   struct tomoyo_path2_acl *ptr)
-{
-	int pos;
-	const u8 perm = ptr->perm;
-	u8 bit;
-
-	for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
-		if (!(perm & (1 << bit)))
-			continue;
-		pos = head->read_avail;
-		if (!tomoyo_io_printf(head, "allow_%s ",
-				      tomoyo_path2_keyword[bit]) ||
-		    !tomoyo_print_name_union(head, &ptr->name1) ||
-		    !tomoyo_print_name_union(head, &ptr->name2) ||
-		    !tomoyo_io_printf(head, "\n"))
-			goto out;
-	}
-	head->read_bit = 0;
-	return true;
- out:
-	head->read_bit = bit;
-	head->read_avail = pos;
-	return false;
-}
-
-/**
- * tomoyo_print_path_number_acl - Print a path_number ACL entry.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_path_number_acl".
- *
- * Returns true on success, false otherwise.
- */
-static bool tomoyo_print_path_number_acl(struct tomoyo_io_buffer *head,
-					 struct tomoyo_path_number_acl *ptr)
-{
-	int pos;
-	u8 bit;
-	const u8 perm = ptr->perm;
-	for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION;
-	     bit++) {
-		if (!(perm & (1 << bit)))
-			continue;
-		pos = head->read_avail;
-		if (!tomoyo_io_printf(head, "allow_%s",
-				      tomoyo_path_number_keyword[bit]) ||
-		    !tomoyo_print_name_union(head, &ptr->name) ||
-		    !tomoyo_print_number_union(head, &ptr->number) ||
-		    !tomoyo_io_printf(head, "\n"))
-			goto out;
-	}
-	head->read_bit = 0;
-	return true;
- out:
-	head->read_bit = bit;
-	head->read_avail = pos;
-	return false;
-}
-
-/**
- * tomoyo_print_mkdev_acl - Print a mkdev ACL entry.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_mkdev_acl".
- *
- * Returns true on success, false otherwise.
- */
-static bool tomoyo_print_mkdev_acl(struct tomoyo_io_buffer *head,
-					  struct tomoyo_mkdev_acl *ptr)
-{
-	int pos;
-	u8 bit;
-	const u16 perm = ptr->perm;
-	for (bit = head->read_bit; bit < TOMOYO_MAX_MKDEV_OPERATION;
-	     bit++) {
-		if (!(perm & (1 << bit)))
-			continue;
-		pos = head->read_avail;
-		if (!tomoyo_io_printf(head, "allow_%s",
-				      tomoyo_mkdev_keyword[bit]) ||
-		    !tomoyo_print_name_union(head, &ptr->name) ||
-		    !tomoyo_print_number_union(head, &ptr->mode) ||
-		    !tomoyo_print_number_union(head, &ptr->major) ||
-		    !tomoyo_print_number_union(head, &ptr->minor) ||
-		    !tomoyo_io_printf(head, "\n"))
-			goto out;
-	}
-	head->read_bit = 0;
-	return true;
- out:
-	head->read_bit = bit;
-	head->read_avail = pos;
-	return false;
-}
-
-/**
- * tomoyo_print_mount_acl - Print a mount ACL entry.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_mount_acl".
- *
- * Returns true on success, false otherwise.
- */
-static bool tomoyo_print_mount_acl(struct tomoyo_io_buffer *head,
-				   struct tomoyo_mount_acl *ptr)
-{
-	const int pos = head->read_avail;
-	if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_MOUNT) ||
-	    !tomoyo_print_name_union(head, &ptr->dev_name) ||
-	    !tomoyo_print_name_union(head, &ptr->dir_name) ||
-	    !tomoyo_print_name_union(head, &ptr->fs_type) ||
-	    !tomoyo_print_number_union(head, &ptr->flags) ||
-	    !tomoyo_io_printf(head, "\n")) {
-		head->read_avail = pos;
-		return false;
-	}
-	return true;
+	for ( ; bit < 8; bit++)
+		if (perm & (1 << bit))
+			break;
+	return bit;
 }
 
 /**
  * tomoyo_print_entry - Print an ACL entry.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to an ACL entry.
+ * @acl:  Pointer to an ACL entry.
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
-			       struct tomoyo_acl_info *ptr)
+			       struct tomoyo_acl_info *acl)
 {
-	const u8 acl_type = ptr->type;
+	const u8 acl_type = acl->type;
+	u8 bit = head->read_bit;
+	int pos = head->read_avail;
 
-	if (ptr->is_deleted)
+	if (acl->is_deleted)
 		return true;
+ next:
 	if (acl_type == TOMOYO_TYPE_PATH_ACL) {
-		struct tomoyo_path_acl *acl
-			= container_of(ptr, struct tomoyo_path_acl, head);
-		return tomoyo_print_path_acl(head, acl);
-	}
-	if (head->print_execute_only)
+		struct tomoyo_path_acl *ptr =
+			container_of(acl, typeof(*ptr), head);
+		const u16 perm = ptr->perm;
+		for ( ; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
+			if (!(perm & (1 << bit)))
+				continue;
+			if (head->print_execute_only &&
+			    bit != TOMOYO_TYPE_EXECUTE)
+				continue;
+			/* Print "read/write" instead of "read" and "write". */
+			if ((bit == TOMOYO_TYPE_READ ||
+			     bit == TOMOYO_TYPE_WRITE)
+			    && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
+				continue;
+			break;
+		}
+		if (bit >= TOMOYO_MAX_PATH_OPERATION)
+			goto done;
+		if (!tomoyo_io_printf(head, "allow_%s ",
+				      tomoyo_path_keyword[bit]) ||
+		    !tomoyo_print_name_union(head, &ptr->name))
+			goto out;
+	} else if (head->print_execute_only) {
 		return true;
-	if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
-		struct tomoyo_path2_acl *acl
-			= container_of(ptr, struct tomoyo_path2_acl, head);
-		return tomoyo_print_path2_acl(head, acl);
+	} else if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
+		struct tomoyo_path2_acl *ptr =
+			container_of(acl, typeof(*ptr), head);
+		bit = tomoyo_fns(ptr->perm, bit);
+		if (bit >= TOMOYO_MAX_PATH2_OPERATION)
+			goto done;
+		if (!tomoyo_io_printf(head, "allow_%s ",
+				      tomoyo_path2_keyword[bit]) ||
+		    !tomoyo_print_name_union(head, &ptr->name1) ||
+		    !tomoyo_print_name_union(head, &ptr->name2))
+			goto out;
+	} else if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) {
+		struct tomoyo_path_number_acl *ptr =
+			container_of(acl, typeof(*ptr), head);
+		bit = tomoyo_fns(ptr->perm, bit);
+		if (bit >= TOMOYO_MAX_PATH_NUMBER_OPERATION)
+			goto done;
+		if (!tomoyo_io_printf(head, "allow_%s",
+				      tomoyo_path_number_keyword[bit]) ||
+		    !tomoyo_print_name_union(head, &ptr->name) ||
+		    !tomoyo_print_number_union(head, &ptr->number))
+			goto out;
+	} else if (acl_type == TOMOYO_TYPE_MKDEV_ACL) {
+		struct tomoyo_mkdev_acl *ptr =
+			container_of(acl, typeof(*ptr), head);
+		bit = tomoyo_fns(ptr->perm, bit);
+		if (bit >= TOMOYO_MAX_MKDEV_OPERATION)
+			goto done;
+		if (!tomoyo_io_printf(head, "allow_%s",
+				      tomoyo_mkdev_keyword[bit]) ||
+		    !tomoyo_print_name_union(head, &ptr->name) ||
+		    !tomoyo_print_number_union(head, &ptr->mode) ||
+		    !tomoyo_print_number_union(head, &ptr->major) ||
+		    !tomoyo_print_number_union(head, &ptr->minor))
+			goto out;
+	} else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
+		struct tomoyo_mount_acl *ptr =
+			container_of(acl, typeof(*ptr), head);
+		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_MOUNT) ||
+		    !tomoyo_print_name_union(head, &ptr->dev_name) ||
+		    !tomoyo_print_name_union(head, &ptr->dir_name) ||
+		    !tomoyo_print_name_union(head, &ptr->fs_type) ||
+		    !tomoyo_print_number_union(head, &ptr->flags))
+			goto out;
 	}
-	if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) {
-		struct tomoyo_path_number_acl *acl
-			= container_of(ptr, struct tomoyo_path_number_acl,
-				       head);
-		return tomoyo_print_path_number_acl(head, acl);
+	if (!tomoyo_io_printf(head, "\n"))
+		goto out;
+	head->read_bit = bit;
+	if (acl_type != TOMOYO_TYPE_MOUNT_ACL) {
+		bit++;
+		goto next;
 	}
-	if (acl_type == TOMOYO_TYPE_MKDEV_ACL) {
-		struct tomoyo_mkdev_acl *acl
-			= container_of(ptr, struct tomoyo_mkdev_acl,
-				       head);
-		return tomoyo_print_mkdev_acl(head, acl);
-	}
-	if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
-		struct tomoyo_mount_acl *acl
-			= container_of(ptr, struct tomoyo_mount_acl, head);
-		return tomoyo_print_mount_acl(head, acl);
-	}
-	BUG(); /* This must not happen. */
+ done:
+	head->read_bit = 0;
+	return true;
+ out:
+	head->read_avail = pos;
 	return false;
 }