From 994054cea6ab30ae2f3ca8736194b19455872e3e Mon Sep 17 00:00:00 2001
From: jmallett <jmallett@FreeBSD.org>
Date: Wed, 29 Jan 2003 23:19:46 +0000
Subject: [PATCH] API for opening (and tracking) writable file descriptors per
 disk.

---
 lib/libufs/block.c  | 11 +++--------
 lib/libufs/libufs.h |  1 +
 lib/libufs/type.c   | 26 ++++++++++++++++++++++++++
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/lib/libufs/block.c b/lib/libufs/block.c
index 2b06dbfb4efc..efc39ef86941 100644
--- a/lib/libufs/block.c
+++ b/lib/libufs/block.c
@@ -75,14 +75,12 @@ ssize_t
 bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
 {
 	ssize_t cnt;
-	int rofd;
+	int rv;
 
 	ERROR(disk, NULL);
 
-	rofd = disk->d_fd;
-
-	disk->d_fd = open(disk->d_name, O_WRONLY);
-	if (disk->d_fd < 0) {
+	rv = ufs_disk_write(disk);
+	if (rv == -1) {
 		ERROR(disk, "failed to open disk for writing");
 		return -1;
 	}
@@ -93,8 +91,5 @@ bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
 		return -1;
 	}
 
-	close(disk->d_fd);
-	disk->d_fd = rofd;
-	
 	return cnt;
 }
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
index 34c2439d6701..035f2a5cda2e 100644
--- a/lib/libufs/libufs.h
+++ b/lib/libufs/libufs.h
@@ -130,6 +130,7 @@ int ufs_disk_close(struct uufsd *);
 void ufs_disk_dtor(struct uufsd **);
 int ufs_disk_fillout(struct uufsd *, const char *);
 int ufs_disk_fillout_blank(struct uufsd *, const char *);
+int ufs_disk_write(struct uufsd *);
 
 __END_DECLS
 
diff --git a/lib/libufs/type.c b/lib/libufs/type.c
index 41eacfd6a977..54554654d240 100644
--- a/lib/libufs/type.c
+++ b/lib/libufs/type.c
@@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
 
 /* Internally, track the 'name' value, it's ours. */
 #define	MINE_NAME	0x01
+/* Track if its fd points to a writable device. */
+#define	MINE_WRITE	0x02
 
 struct uufsd *
 ufs_disk_ctor(const char *name)
@@ -175,3 +177,27 @@ again:	if (stat(name, &st) < 0) {
 
 	return 0;
 }
+
+int
+ufs_disk_write(struct uufsd *disk)
+{
+	int rofd;
+
+	ERROR(disk, NULL);
+
+	if (disk->d_mine & MINE_WRITE)
+		return 0;
+
+	rofd = disk->d_fd;
+
+	disk->d_fd = open(disk->d_name, O_RDWR);
+	if (disk->d_fd < 0) {
+		ERROR(disk, "failed to open disk for writing");
+		disk->d_fd = rofd;
+		return -1;
+	}
+
+	disk->d_mine |= MINE_WRITE;
+
+	return 0;
+}