exfat: Update to 1.2.2

Change-Id: I160389afa074270c398aeb771845500f2445838a
diff --git a/exfat/libexfat/io.c b/exfat/libexfat/io.c
index 306c5dd..3d7aaad 100644
--- a/exfat/libexfat/io.c
+++ b/exfat/libexfat/io.c
@@ -3,7 +3,7 @@
 	exFAT file system implementation library.
 
 	Free exFAT implementation.
-	Copyright (C) 2010-2013  Andrew Nayenko
+	Copyright (C) 2010-2015  Andrew Nayenko
 
 	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
@@ -24,13 +24,19 @@
 #include <inttypes.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/mount.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
-#ifdef __APPLE__
+#include <errno.h>
+#if defined(__APPLE__)
 #include <sys/disk.h>
+#elif defined(__OpenBSD__)
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/dkio.h>
+#include <sys/ioctl.h>
 #endif
+#include <sys/mount.h>
 #ifdef USE_UBLIO
 #include <sys/uio.h>
 #include <ublio.h>
@@ -40,9 +46,9 @@
 {
 	int fd;
 	enum exfat_mode mode;
-	off64_t size; /* in bytes */
+	off_t size; /* in bytes */
 #ifdef USE_UBLIO
-	off64_t pos;
+	off_t pos;
 	ublio_filehandle_t ufh;
 #endif
 };
@@ -65,6 +71,7 @@
 	if (fd != -1 && ioctl(fd, BLKROGET, &ro) == 0 && ro)
 	{
 		close(fd);
+		errno = EROFS;
 		return -1;
 	}
 #endif
@@ -93,7 +100,8 @@
 		if (dev->fd == -1)
 		{
 			free(dev);
-			exfat_error("failed to open `%s' in read-only mode", spec);
+			exfat_error("failed to open '%s' in read-only mode: %s", spec,
+					strerror(errno));
 			return NULL;
 		}
 		dev->mode = EXFAT_MODE_RO;
@@ -103,7 +111,8 @@
 		if (dev->fd == -1)
 		{
 			free(dev);
-			exfat_error("failed to open `%s' in read-write mode", spec);
+			exfat_error("failed to open '%s' in read-write mode: %s", spec,
+					strerror(errno));
 			return NULL;
 		}
 		dev->mode = EXFAT_MODE_RW;
@@ -119,11 +128,11 @@
 		if (dev->fd != -1)
 		{
 			dev->mode = EXFAT_MODE_RO;
-			exfat_warn("`%s' is write-protected, mounting read-only", spec);
+			exfat_warn("'%s' is write-protected, mounting read-only", spec);
 			break;
 		}
 		free(dev);
-		exfat_error("failed to open `%s'", spec);
+		exfat_error("failed to open '%s': %s", spec, strerror(errno));
 		return NULL;
 	}
 
@@ -131,7 +140,7 @@
 	{
 		close(dev->fd);
 		free(dev);
-		exfat_error("failed to fstat `%s'", spec);
+		exfat_error("failed to fstat '%s'", spec);
 		return NULL;
 	}
 	if (!S_ISBLK(stbuf.st_mode) &&
@@ -140,11 +149,11 @@
 	{
 		close(dev->fd);
 		free(dev);
-		exfat_error("`%s' is neither a device, nor a regular file", spec);
+		exfat_error("'%s' is neither a device, nor a regular file", spec);
 		return NULL;
 	}
 
-#ifdef __APPLE__
+#if defined(__APPLE__)
 	if (!S_ISREG(stbuf.st_mode))
 	{
 		uint32_t block_size = 0;
@@ -167,6 +176,32 @@
 		dev->size = blocks * block_size;
 	}
 	else
+#elif defined(__OpenBSD__)
+	if (!S_ISREG(stbuf.st_mode))
+	{
+		struct disklabel lab;
+		struct partition* pp;
+		char* partition;
+
+		if (ioctl(dev->fd, DIOCGDINFO, &lab) == -1)
+		{
+			close(dev->fd);
+			free(dev);
+			exfat_error("failed to get disklabel");
+			return NULL;
+		}
+
+		/* Don't need to check that partition letter is valid as we won't get
+		   this far otherwise. */
+		partition = strchr(spec, '\0') - 1;
+		pp = &(lab.d_partitions[*partition - 'a']);
+		dev->size = DL_GETPSIZE(pp) * lab.d_secsize;
+
+		if (pp->p_fstype != FS_NTFS)
+			exfat_warn("partition type is not 0x07 (NTFS/exFAT); "
+					"you can fix this with fdisk(8)");
+	}
+	else
 #endif
 	{
 		/* works for Linux, FreeBSD, Solaris */
@@ -175,14 +210,14 @@
 		{
 			close(dev->fd);
 			free(dev);
-			exfat_error("failed to get size of `%s'", spec);
+			exfat_error("failed to get size of '%s'", spec);
 			return NULL;
 		}
 		if (exfat_seek(dev, 0, SEEK_SET) == -1)
 		{
 			close(dev->fd);
 			free(dev);
-			exfat_error("failed to seek to the beginning of `%s'", spec);
+			exfat_error("failed to seek to the beginning of '%s'", spec);
 			return NULL;
 		}
 	}
@@ -210,32 +245,41 @@
 
 int exfat_close(struct exfat_dev* dev)
 {
+	int rc = 0;
+
 #ifdef USE_UBLIO
 	if (ublio_close(dev->ufh) != 0)
+	{
 		exfat_error("failed to close ublio");
+		rc = -EIO;
+	}
 #endif
 	if (close(dev->fd) != 0)
 	{
-		free(dev);
-		exfat_error("failed to close device");
-		return 1;
+		exfat_error("failed to close device: %s", strerror(errno));
+		rc = -EIO;
 	}
 	free(dev);
-	return 0;
+	return rc;
 }
 
 int exfat_fsync(struct exfat_dev* dev)
 {
+	int rc = 0;
+
 #ifdef USE_UBLIO
 	if (ublio_fsync(dev->ufh) != 0)
-#else
-	if (fsync(dev->fd) != 0)
-#endif
 	{
-		exfat_error("fsync failed");
-		return 1;
+		exfat_error("ublio fsync failed");
+		rc = -EIO;
 	}
-	return 0;
+#endif
+	if (fsync(dev->fd) != 0)
+	{
+		exfat_error("fsync failed: %s", strerror(errno));
+		rc = -EIO;
+	}
+	return rc;
 }
 
 enum exfat_mode exfat_get_mode(const struct exfat_dev* dev)
@@ -243,18 +287,18 @@
 	return dev->mode;
 }
 
-off64_t exfat_get_size(const struct exfat_dev* dev)
+off_t exfat_get_size(const struct exfat_dev* dev)
 {
 	return dev->size;
 }
 
-off64_t exfat_seek(struct exfat_dev* dev, off64_t offset, int whence)
+off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence)
 {
 #ifdef USE_UBLIO
 	/* XXX SEEK_CUR will be handled incorrectly */
-	return dev->pos = lseek64(dev->fd, offset, whence);
+	return dev->pos = lseek(dev->fd, offset, whence);
 #else
-	return lseek64(dev->fd, offset, whence);
+	return lseek(dev->fd, offset, whence);
 #endif
 }
 
@@ -283,31 +327,31 @@
 }
 
 ssize_t exfat_pread(struct exfat_dev* dev, void* buffer, size_t size,
-		off64_t offset)
+		off_t offset)
 {
 #ifdef USE_UBLIO
 	return ublio_pread(dev->ufh, buffer, size, offset);
 #else
-	return pread64(dev->fd, buffer, size, offset);
+	return pread(dev->fd, buffer, size, offset);
 #endif
 }
 
 ssize_t exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size,
-		off64_t offset)
+		off_t offset)
 {
 #ifdef USE_UBLIO
 	return ublio_pwrite(dev->ufh, buffer, size, offset);
 #else
-	return pwrite64(dev->fd, buffer, size, offset);
+	return pwrite(dev->fd, buffer, size, offset);
 #endif
 }
 
 ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node,
-		void* buffer, size_t size, off64_t offset)
+		void* buffer, size_t size, off_t offset)
 {
 	cluster_t cluster;
 	char* bufp = buffer;
-	off64_t lsize, loffset, remainder;
+	off_t lsize, loffset, remainder;
 
 	if (offset >= node->size)
 		return 0;
@@ -348,11 +392,11 @@
 }
 
 ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
-		const void* buffer, size_t size, off64_t offset)
+		const void* buffer, size_t size, off_t offset)
 {
 	cluster_t cluster;
 	const char* bufp = buffer;
-	off64_t lsize, loffset, remainder;
+	off_t lsize, loffset, remainder;
 
  	if (offset > node->size)
  		if (exfat_truncate(ef, node, offset, true) != 0)