Subject: bug#15356: [PATCH 16/19] libparted: Recognize btrfs filesystem

From: "Brian C. Lane" <[email-masked]>
Date: Wed, 11 Sep 2013 12:25:06 -0700

From: "Brian C. Lane" <[email-masked]>

Add support for showing 'btrfs' in  the 'file system' column. Also
allows the used to enter btrfs as the fs type. It doesn't really do
anything -- just sets the partition type to linux.

* NEWS (Changes in behavior): Mention it.
* doc/parted.texti: Document btrfs fs.
* (libparted/fs/Makefile.am): Add btrfs.c
* (libparted/fs/btrfs/btrfs.c): Probe for btrfs
* (libparted/libparted.c): Register btrfs
---
 NEWS                       |  3 ++
 doc/parted.texi            |  1 +
 libparted/fs/Makefile.am   |  1 +
 libparted/fs/btrfs/btrfs.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++
 libparted/libparted.c      |  4 +++
 5 files changed, 87 insertions(+)
 create mode 100644 libparted/fs/btrfs/btrfs.c

diff --git a/NEWS b/NEWS
index 026e897..df259d6 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,9 @@ GNU parted NEWS                                    -*- outline -*-
 
 ** Changes in behavior
 
+  Added support for recognizing btrfs filesystem. This simply displays
+  btrfs in the 'file system' column of the parted output.
+
   Added new GPT partition type flag, hfs_esp, that sets the GUID to
   47CB5633-7E3E-408B-B7B8-2D915B7B21B1 so that you can distinguish
   between OSX's native HFS+ partition and one used Linux on UEFI. The
diff --git a/doc/parted.texi b/doc/parted.texi
index ee5b3f7..03522e7 100644
--- a/doc/parted.texi
+++ b/doc/parted.texi
@@ -575,6 +575,7 @@ partition table.
 @item NTFS
 @item reiserfs
 @item ufs
+@item btrfs
 @end itemize
 
 For example, the following creates a logical partition that will contain
diff --git a/libparted/fs/Makefile.am b/libparted/fs/Makefile.am
index aac03cc..1949617 100644
--- a/libparted/fs/Makefile.am
+++ b/libparted/fs/Makefile.am
@@ -23,6 +23,7 @@ libfs_la_SOURCES =		\
   amiga/asfs.c			\
   amiga/asfs.h			\
   amiga/a-interface.c		\
+  btrfs/btrfs.c			\
   ext2/ext2.h			\
   ext2/ext2_fs.h		\
   ext2/interface.c		\
diff --git a/libparted/fs/btrfs/btrfs.c b/libparted/fs/btrfs/btrfs.c
new file mode 100644
index 0000000..e5abed6
--- /dev/null
+++ b/libparted/fs/btrfs/btrfs.c
@@ -0,0 +1,78 @@
+/*
+    libparted - a library for manipulating disk partitions
+    Copyright (C) 2013 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#include <parted/parted.h>
+#include <parted/endian.h>
+
+/* Located 64k inside the partition (start of the first btrfs superblock) */
+#define BTRFS_MAGIC 0x4D5F53665248425FULL /* ascii _BHRfS_M, no null */
+#define BTRFS_CSUM_SIZE 32
+#define BTRFS_FSID_SIZE 16
+
+
+static PedGeometry*
+btrfs_probe (PedGeometry* geom)
+{
+        union {
+            struct {
+                /* Just enough of the btrfs_super_block to get the magic */
+                uint8_t csum[BTRFS_CSUM_SIZE];
+                uint8_t fsid[BTRFS_FSID_SIZE];
+                uint64_t bytenr;
+                uint64_t flags;
+                uint64_t magic;
+            } sb;
+            int8_t      sector[8192];
+        } buf;
+        PedSector offset = (64*1024)/geom->dev->sector_size;
+
+        if (geom->length < offset+1)
+                return 0;
+        if (!ped_geometry_read (geom, &buf, offset, 1))
+                return 0;
+
+        if (PED_LE64_TO_CPU(buf.sb.magic) == BTRFS_MAGIC) {
+                return ped_geometry_new (geom->dev, geom->start, geom->length);
+        }
+        return NULL;
+}
+
+static PedFileSystemOps btrfs_ops = {
+        probe:          btrfs_probe,
+};
+
+static PedFileSystemType btrfs_type = {
+        next:   NULL,
+        ops:    &btrfs_ops,
+        name:   "btrfs",
+        block_sizes: ((int[2]){512, 0})
+};
+
+void
+ped_file_system_btrfs_init ()
+{
+        ped_file_system_type_register (&btrfs_type);
+}
+
+void
+ped_file_system_btrfs_done ()
+{
+        ped_file_system_type_unregister (&btrfs_type);
+}
diff --git a/libparted/libparted.c b/libparted/libparted.c
index 9923bfa..3afbf8e 100644
--- a/libparted/libparted.c
+++ b/libparted/libparted.c
@@ -109,6 +109,7 @@ extern void ped_file_system_hfs_init (void);
 extern void ped_file_system_fat_init (void);
 extern void ped_file_system_ext2_init (void);
 extern void ped_file_system_nilfs2_init (void);
+extern void ped_file_system_btrfs_init (void);
 
 static void
 init_file_system_types ()
@@ -124,6 +125,7 @@ init_file_system_types ()
 	ped_file_system_fat_init ();
 	ped_file_system_ext2_init ();
 	ped_file_system_nilfs2_init ();
+	ped_file_system_btrfs_init ();
 }
 
 extern void ped_disk_aix_done ();
@@ -186,6 +188,7 @@ extern void ped_file_system_reiserfs_done (void);
 extern void ped_file_system_ufs_done (void);
 extern void ped_file_system_xfs_done (void);
 extern void ped_file_system_amiga_done (void);
+extern void ped_file_system_btrfs_done (void);
 
 static void
 done_file_system_types ()
@@ -201,6 +204,7 @@ done_file_system_types ()
 	ped_file_system_ufs_done ();
 	ped_file_system_xfs_done ();
 	ped_file_system_amiga_done ();
+	ped_file_system_btrfs_done ();
 }
 
 static void _done() __attribute__ ((destructor));
-- 
1.8.3.1