diff options
author | relan <relan@users.noreply.github.com> | 2012-12-04 19:17:52 +0000 |
---|---|---|
committer | relan <relan@users.noreply.github.com> | 2015-08-24 08:26:15 +0300 |
commit | f0d39b5550dd3108a7678b1db5ce2176c22eaccb (patch) | |
tree | a774a04731bc7cd74c348444da443da4e8ce7e8d /libexfat/io.c | |
parent | 84e2bcbecf3c38b385d784a9917db81123dde5a0 (diff) | |
download | android_external_exfat-f0d39b5550dd3108a7678b1db5ce2176c22eaccb.tar.gz android_external_exfat-f0d39b5550dd3108a7678b1db5ce2176c22eaccb.tar.bz2 android_external_exfat-f0d39b5550dd3108a7678b1db5ce2176c22eaccb.zip |
Do BLKROGET ioctl to make sure the device is not read-only.
After "blockdev --setro" Linux kernel still allows to open the device in
read-write mode but fails writes.
Diffstat (limited to 'libexfat/io.c')
-rw-r--r-- | libexfat/io.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/libexfat/io.c b/libexfat/io.c index 755d0d6..e89349b 100644 --- a/libexfat/io.c +++ b/libexfat/io.c @@ -23,6 +23,7 @@ #include <sys/types.h> #include <sys/uio.h> #include <sys/stat.h> +#include <sys/mount.h> #include <fcntl.h> #include <unistd.h> #include <string.h> @@ -45,6 +46,30 @@ struct exfat_dev #endif }; +static int open_ro(const char* spec) +{ + return open(spec, O_RDONLY); +} + +static int open_rw(const char* spec) +{ + int fd = open(spec, O_RDWR); +#ifdef __linux__ + int ro = 0; + + /* + This ioctl is needed because after "blockdev --setro" kernel still + allows to open the device in read-write mode but fails writes. + */ + if (fd != -1 && ioctl(fd, BLKROGET, &ro) == 0 && ro) + { + close(fd); + return -1; + } +#endif + return fd; +} + struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) { struct exfat_dev* dev; @@ -63,7 +88,7 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) switch (mode) { case EXFAT_MODE_RO: - dev->fd = open(spec, O_RDONLY); + dev->fd = open_ro(spec); if (dev->fd == -1) { free(dev); @@ -73,7 +98,7 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) dev->mode = EXFAT_MODE_RO; break; case EXFAT_MODE_RW: - dev->fd = open(spec, O_RDWR); + dev->fd = open_rw(spec); if (dev->fd == -1) { free(dev); @@ -83,13 +108,13 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) dev->mode = EXFAT_MODE_RW; break; case EXFAT_MODE_ANY: - dev->fd = open(spec, O_RDWR); + dev->fd = open_rw(spec); if (dev->fd != -1) { dev->mode = EXFAT_MODE_RW; break; } - dev->fd = open(spec, O_RDONLY); + dev->fd = open_ro(spec); if (dev->fd != -1) { dev->mode = EXFAT_MODE_RO; |