From 82d87ff8eda1a8e43cda4a5f500fc579477ee606 Mon Sep 17 00:00:00 2001
From: Jakob Unterwurzacher
Date: Thu, 16 Jun 2016 21:29:22 +0200
Subject: Add "-ro" (read-only) flag

From the man page:

  **-ro**
  :      Mount the filesystem read-only

Also add a test.
---
 Documentation/MANPAGE.md            |  3 +++
 main.go                             |  8 +++++++-
 tests/integration_tests/cli_test.go | 18 ++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/MANPAGE.md b/Documentation/MANPAGE.md
index 0ddd772..5f2ae47 100644
--- a/Documentation/MANPAGE.md
+++ b/Documentation/MANPAGE.md
@@ -117,6 +117,9 @@ option.
 **-q, -quiet**
 :	Quiet - silence informational messages
 
+**-ro**
+:	Mount the filesystem read-only
+
 **-scryptn int**
 :	scrypt cost parameter logN. Setting this to a lower value speeds up
 mounting but makes the password susceptible to brute-force attacks (default 16)
diff --git a/main.go b/main.go
index dba10bf..2d7b50f 100644
--- a/main.go
+++ b/main.go
@@ -43,7 +43,7 @@ const (
 type argContainer struct {
 	debug, init, zerokey, fusedebug, openssl, passwd, foreground, version,
 	plaintextnames, quiet, diriv, emenames, gcmiv128, nosyslog, wpanic,
-	longnames, allow_other bool
+	longnames, allow_other, ro bool
 	masterkey, mountpoint, cipherdir, cpuprofile, config, extpass,
 	memprofile string
 	notifypid, scryptn int
@@ -182,6 +182,7 @@ func main() {
 	flagSet.BoolVar(&args.longnames, "longnames", true, "Store names longer than 176 bytes in extra files")
 	flagSet.BoolVar(&args.allow_other, "allow_other", false, "Allow other users to access the filesystem. "+
 		"Only works if user_allow_other is set in /etc/fuse.conf.")
+	flagSet.BoolVar(&args.ro, "ro", false, "Mount the filesystem read-only")
 	flagSet.StringVar(&args.masterkey, "masterkey", "", "Mount with explicit master key")
 	flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
 	flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
@@ -419,6 +420,11 @@ func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFi
 	// Second column, "Type", will be shown as "fuse." + Name
 	mOpts.Name = "gocryptfs"
 
+	// The kernel enforces read-only operation, we just have to pass "ro".
+	if args.ro {
+		mOpts.Options = append(mOpts.Options, "ro")
+	}
+
 	srv, err := fuse.NewServer(conn.RawFS(), args.mountpoint, &mOpts)
 	if err != nil {
 		tlog.Fatal.Printf("Mount failed: %v", err)
diff --git a/tests/integration_tests/cli_test.go b/tests/integration_tests/cli_test.go
index ae6ef7f..0246901 100644
--- a/tests/integration_tests/cli_test.go
+++ b/tests/integration_tests/cli_test.go
@@ -102,3 +102,21 @@ func TestInitPlaintextNames(t *testing.T) {
 		t.Error("FlagEMENames and FlagDirIV should be not set")
 	}
 }
+
+// Test -ro
+func TestRo(t *testing.T) {
+	dir := test_helpers.InitFS(t)
+	mnt := dir + ".mnt"
+	test_helpers.MountOrFatal(t, dir, mnt, "-ro", "-extpass=echo test")
+	defer test_helpers.Unmount(mnt)
+
+	file := mnt + "/file"
+	err := os.Mkdir(file, 0777)
+	if err == nil {
+		t.Errorf("Mkdir should have failed")
+	}
+	_, err = os.Create(file)
+	if err == nil {
+		t.Errorf("Create should have failed")
+	}
+}
-- 
cgit v1.2.3