aboutsummaryrefslogtreecommitdiff
path: root/sysutils/ntfsprogs
diff options
context:
space:
mode:
authorMax Khon <fjoe@FreeBSD.org>2006-12-13 17:03:02 +0000
committerMax Khon <fjoe@FreeBSD.org>2006-12-13 17:03:02 +0000
commit92167387a1541b3ae6e756ca89d9183e7aa6c20e (patch)
tree291fb7003b2e0c02ec0bc76e1c467eedecf09306 /sysutils/ntfsprogs
parent6781af104daf728baeb0e8ecbd769c3cb1a4926f (diff)
downloadports-92167387a1541b3ae6e756ca89d9183e7aa6c20e.tar.gz
ports-92167387a1541b3ae6e756ca89d9183e7aa6c20e.zip
- Fix mkntfs by providing device io module that always reads/write
blocksize-aligned blocks - Remove several now unnecessary hacks - Bump PORTREVISION Approved by: MAINTAINER
Notes
Notes: svn path=/head/; revision=179674
Diffstat (limited to 'sysutils/ntfsprogs')
-rw-r--r--sysutils/ntfsprogs/Makefile2
-rw-r--r--sysutils/ntfsprogs/files/patch-libntfs-attrib.c39
-rw-r--r--sysutils/ntfsprogs/files/patch-libntfs-device.c15
-rw-r--r--sysutils/ntfsprogs/files/patch-libntfs-device_io.c14
-rw-r--r--sysutils/ntfsprogs/files/patch-libntfs::unix_io.c30
-rw-r--r--sysutils/ntfsprogs/files/unix_io_raw.c593
6 files changed, 609 insertions, 84 deletions
diff --git a/sysutils/ntfsprogs/Makefile b/sysutils/ntfsprogs/Makefile
index 45b92649db93..ef4f6040237a 100644
--- a/sysutils/ntfsprogs/Makefile
+++ b/sysutils/ntfsprogs/Makefile
@@ -7,6 +7,7 @@
PORTNAME= ntfsprogs
PORTVERSION= 1.13.1
+PORTREVISION= 1
CATEGORIES= sysutils
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE}
MASTER_SITE_SUBDIR= linux-ntfs
@@ -76,5 +77,6 @@ post-patch:
's|$$(libdir)/\(gnome-vfs-2.0/modules\)|${X11BASE}/lib/\1|; \
s|$$(sysconfdir)/\(gnome-vfs-2.0/modules\)|${X11BASE}/etc/\1|' \
${WRKSRC}/libntfs/Makefile.in
+ @${CP} ${FILESDIR}/unix_io_raw.c ${WRKSRC}/libntfs
.include <bsd.port.post.mk>
diff --git a/sysutils/ntfsprogs/files/patch-libntfs-attrib.c b/sysutils/ntfsprogs/files/patch-libntfs-attrib.c
deleted file mode 100644
index fabb701b43b7..000000000000
--- a/sysutils/ntfsprogs/files/patch-libntfs-attrib.c
+++ /dev/null
@@ -1,39 +0,0 @@
---- libntfs/attrib.c.orig Fri Feb 24 10:17:49 2006
-+++ libntfs/attrib.c Thu May 4 04:44:07 2006
-@@ -763,7 +763,7 @@
- */
- s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
- {
-- s64 br, to_read, ofs, total, total2;
-+ s64 br, old_to_read, to_read, ofs, total, total2;
- ntfs_volume *vol;
- runlist_element *rl;
-
-@@ -799,6 +799,7 @@
- if (pos + count > na->data_size) {
- if (pos >= na->data_size)
- return 0;
-+ ntfs_log_trace("trunacting read pos=%lld, na->data_size=%lld, (old) count=%lld\n", pos, na->data_size, count);
- count = na->data_size - pos;
- }
- /* If it is a resident attribute, get the value from the mft record. */
-@@ -887,6 +888,10 @@
- /* It is a real lcn, read it into @dst. */
- to_read = min(count, (rl->length << vol->cluster_size_bits) -
- ofs);
-+ old_to_read = to_read;
-+ to_read = (to_read + 511) / 512 * 512;
-+ if(old_to_read != to_read)
-+ ntfs_log_trace("adjusted %lld->%lld\n", old_to_read, to_read);
- retry:
- ntfs_log_trace("Reading 0x%llx bytes from vcn 0x%llx, lcn 0x%llx, "
- "ofs 0x%llx.\n", to_read, rl->vcn, rl->lcn, ofs);
-@@ -894,6 +899,8 @@
- ofs, to_read, b);
- /* If everything ok, update progress counters and continue. */
- if (br > 0) {
-+ if(br > old_to_read)
-+ br = old_to_read;
- total += br;
- count -= br;
- b = (u8*)b + br;
diff --git a/sysutils/ntfsprogs/files/patch-libntfs-device.c b/sysutils/ntfsprogs/files/patch-libntfs-device.c
deleted file mode 100644
index 947c5e31830c..000000000000
--- a/sysutils/ntfsprogs/files/patch-libntfs-device.c
+++ /dev/null
@@ -1,15 +0,0 @@
---- libntfs/device.c Sat Sep 4 13:16:32 2004
-+++ libntfs/device.c Mon Jul 11 23:27:55 2005
-@@ -441,10 +441,10 @@
- */
- static inline int ntfs_device_offset_valid(struct ntfs_device *dev, s64 ofs)
- {
-- char ch;
-+ char ch[512];
-
- if (dev->d_ops->seek(dev, ofs, SEEK_SET) >= 0 &&
-- dev->d_ops->read(dev, &ch, 1) == 1)
-+ dev->d_ops->read(dev, &ch, 512) > 0)
- return 0;
- return -1;
- }
diff --git a/sysutils/ntfsprogs/files/patch-libntfs-device_io.c b/sysutils/ntfsprogs/files/patch-libntfs-device_io.c
new file mode 100644
index 000000000000..13cf4a9e3991
--- /dev/null
+++ b/sysutils/ntfsprogs/files/patch-libntfs-device_io.c
@@ -0,0 +1,14 @@
+--- libntfs/device_io.c.orig Wed Dec 6 03:57:01 2006
++++ libntfs/device_io.c Wed Dec 6 03:05:24 2006
+@@ -26,7 +26,11 @@
+ #ifndef __CYGWIN32__
+
+ /* Not on Cygwin; use standard Unix style low level device operations. */
++#if defined(__FreeBSD__)
++#include "unix_io_raw.c"
++#else
+ #include "unix_io.c"
++#endif
+
+ #else /* __CYGWIN32__ */
+
diff --git a/sysutils/ntfsprogs/files/patch-libntfs::unix_io.c b/sysutils/ntfsprogs/files/patch-libntfs::unix_io.c
deleted file mode 100644
index a632af7a69b0..000000000000
--- a/sysutils/ntfsprogs/files/patch-libntfs::unix_io.c
+++ /dev/null
@@ -1,30 +0,0 @@
---- libntfs/unix_io.c.orig Sat Feb 4 03:42:15 2006
-+++ libntfs/unix_io.c Thu May 4 03:59:59 2006
-@@ -110,6 +110,7 @@
- flk.l_type = F_WRLCK;
- flk.l_whence = SEEK_SET;
- flk.l_start = flk.l_len = 0LL;
-+#if 0
- if (fcntl(DEV_FD(dev), F_SETLK, &flk)) {
- err = errno;
- ntfs_log_debug("ntfs_device_unix_io_open: Could not lock %s for %s\n",
-@@ -119,6 +120,7 @@
- "close %s", dev->d_name);
- goto err_out;
- }
-+#endif
- /* Determine if device is a block device or not, ignoring errors. */
- if (!fstat(DEV_FD(dev), &sbuf) && S_ISBLK(sbuf.st_mode))
- NDevSetBlock(dev);
-@@ -155,9 +157,11 @@
- flk.l_type = F_UNLCK;
- flk.l_whence = SEEK_SET;
- flk.l_start = flk.l_len = 0LL;
-+#if 0
- if (fcntl(DEV_FD(dev), F_SETLK, &flk))
- ntfs_log_perror("ntfs_device_unix_io_close: Warning: Could not "
- "unlock %s", dev->d_name);
-+#endif
- /* Close the file descriptor and clear our open flag. */
- if (close(DEV_FD(dev)))
- return -1;
diff --git a/sysutils/ntfsprogs/files/unix_io_raw.c b/sysutils/ntfsprogs/files/unix_io_raw.c
new file mode 100644
index 000000000000..5a2cccc7d2ab
--- /dev/null
+++ b/sysutils/ntfsprogs/files/unix_io_raw.c
@@ -0,0 +1,593 @@
+/**
+ * unix_io.c - Unix style disk io functions. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2006 Max Khon
+ *
+ * This program/include file 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file 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 (in the main directory of the NTFS-3G
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+#include <sys/disk.h>
+
+#include "types.h"
+#include "mst.h"
+#include "debug.h"
+#include "device.h"
+#include "logging.h"
+
+typedef struct {
+ int fd;
+ s64 pos;
+ s32 block_size;
+ s64 media_size;
+} unix_raw_fd;
+
+#define DEV_FD(dev) (((unix_raw_fd *) dev->d_private))
+#define RAW_IO_ALIGNED(dev, offset, count) \
+ (DEV_FD(dev)->block_size == 0 || \
+ ((offset) % DEV_FD(dev)->block_size == 0 && \
+ (count) % DEV_FD(dev)->block_size == 0))
+#define RAW_IO_ALIGN(dev, offset) \
+ ((offset) / DEV_FD(dev)->block_size * DEV_FD(dev)->block_size)
+#define RAW_IO_MAX_SIZE (128 * 1024 * 1024)
+
+/* Define to nothing if not present on this system. */
+#ifndef O_EXCL
+# define O_EXCL 0
+#endif
+
+/**
+ * Get block_size and media_size
+ */
+static int
+raw_io_get_size(struct ntfs_device *dev)
+{
+ int bs;
+ off_t ms;
+ struct stat sb;
+
+ if (fstat(DEV_FD(dev)->fd, &sb) < 0) {
+ ntfs_log_perror("Failed to stat '%s'", dev->d_name);
+ return -1;
+ }
+
+ if (S_ISREG(sb.st_mode)) {
+ DEV_FD(dev)->media_size = sb.st_size;
+ ntfs_log_trace("%s: regular file (media_size %lld)\n",
+ dev->d_name, DEV_FD(dev)->media_size);
+ return 0;
+ }
+
+ if (ioctl(DEV_FD(dev)->fd, DIOCGSECTORSIZE, &bs) < 0) {
+ ntfs_log_perror("Failed to ioctl(DIOCGSECTORSIZE) '%s'",
+ dev->d_name);
+ return -1;
+ }
+ DEV_FD(dev)->block_size = bs;
+ ntfs_log_trace("%s: block size %d\n", dev->d_name, bs);
+
+ if (ioctl(DEV_FD(dev)->fd, DIOCGMEDIASIZE, &ms) < 0) {
+ ntfs_log_perror("Failed to ioctl(DIOCGMEDIASIZE) '%s'",
+ dev->d_name);
+ return -1;
+ }
+ DEV_FD(dev)->media_size = ms;
+ ntfs_log_trace("%s: media size %lld\n", dev->d_name, ms);
+ return 0;
+}
+
+/**
+ * Aligned read
+ */
+static ssize_t
+raw_io_pread(struct ntfs_device *dev, char *buf, size_t count, s64 offset)
+{
+ return pread(DEV_FD(dev)->fd, buf, count, offset);
+}
+
+/**
+ * Aligned write
+ */
+static ssize_t
+raw_io_pwrite(struct ntfs_device *dev, const char *buf, size_t count, s64 offset)
+{
+ return pwrite(DEV_FD(dev)->fd, buf, count, offset);
+}
+
+/**
+ * ntfs_device_unix_raw_io_open - Open a device and lock it exclusively
+ * @dev:
+ * @flags:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_raw_io_open(struct ntfs_device *dev, int flags)
+{
+#if 0
+ struct flock flk;
+#endif
+ struct stat sbuf;
+ int err;
+
+ if (NDevOpen(dev)) {
+ errno = EBUSY;
+ return -1;
+ }
+ if (stat(dev->d_name, &sbuf)) {
+ ntfs_log_perror("Failed to access '%s'", dev->d_name);
+ return -1;
+ }
+ if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode))
+ NDevSetBlock(dev);
+
+ dev->d_private = malloc(sizeof(unix_raw_fd));
+ if (!dev->d_private)
+ return -1;
+ DEV_FD(dev)->fd = -1;
+ DEV_FD(dev)->pos = 0;
+ DEV_FD(dev)->block_size = 0;
+ DEV_FD(dev)->media_size = 0;
+
+ /*
+ * Open file for exclusive access if mounting r/w.
+ * Fuseblk takes care about block devices.
+ */
+ if (!NDevBlock(dev) && (flags & O_RDWR) == O_RDWR)
+ flags |= O_EXCL;
+ DEV_FD(dev)->fd = open(dev->d_name, flags);
+ if (DEV_FD(dev)->fd == -1) {
+ err = errno;
+ goto err_out;
+ }
+
+ if ((flags & O_RDWR) != O_RDWR)
+ NDevSetReadOnly(dev);
+
+#if 0
+ memset(&flk, 0, sizeof(flk));
+ if (NDevReadOnly(dev))
+ flk.l_type = F_RDLCK;
+ else
+ flk.l_type = F_WRLCK;
+ flk.l_whence = SEEK_SET;
+ flk.l_start = flk.l_len = 0LL;
+ if (fcntl(DEV_FD(dev)->fd, F_SETLK, &flk)) {
+ err = errno;
+ ntfs_log_perror("Failed to %s lock '%s'", NDevReadOnly(dev) ?
+ "read" : "write", dev->d_name);
+ if (close(DEV_FD(dev)->fd))
+ ntfs_log_perror("Failed to close '%s'", dev->d_name);
+ goto err_out;
+ }
+#endif
+
+ if (raw_io_get_size(dev) < 0) {
+ err = errno;
+ close(DEV_FD(dev)->fd);
+ goto err_out;
+ }
+
+ NDevSetOpen(dev);
+ return 0;
+err_out:
+ free(dev->d_private);
+ dev->d_private = NULL;
+ errno = err;
+ return -1;
+}
+
+/**
+ * ntfs_device_unix_raw_io_close - Close the device, releasing the lock
+ * @dev:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_raw_io_close(struct ntfs_device *dev)
+{
+#if 0
+ struct flock flk;
+#endif
+
+ if (!NDevOpen(dev)) {
+ errno = EBADF;
+ return -1;
+ }
+ if (NDevDirty(dev))
+ fsync(DEV_FD(dev)->fd);
+
+#if 0
+ /* Release exclusive (mandatory) lock on the whole device. */
+ memset(&flk, 0, sizeof(flk));
+ flk.l_type = F_UNLCK;
+ flk.l_whence = SEEK_SET;
+ flk.l_start = flk.l_len = 0LL;
+ if (fcntl(DEV_FD(dev)->fd, F_SETLK, &flk))
+ ntfs_log_perror("ntfs_device_unix_raw_io_close: Warning: Could not "
+ "unlock %s", dev->d_name);
+#endif
+
+ /* Close the file descriptor and clear our open flag. */
+ if (close(DEV_FD(dev)->fd))
+ return -1;
+ NDevClearOpen(dev);
+ free(dev->d_private);
+ dev->d_private = NULL;
+ return 0;
+}
+
+/**
+ * ntfs_device_unix_raw_io_seek - Seek to a place on the device
+ * @dev:
+ * @offset:
+ * @whence:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_raw_io_seek(struct ntfs_device *dev, s64 offset,
+ int whence)
+{
+ s64 abs_pos;
+
+ ntfs_log_trace("seek offset = 0x%llx, whence = %d.\n", offset, whence);
+ switch (whence) {
+ case SEEK_SET:
+ abs_pos = offset;
+ break;
+
+ case SEEK_CUR:
+ abs_pos = DEV_FD(dev)->pos + offset;
+ break;
+
+ case SEEK_END:
+ abs_pos = DEV_FD(dev)->media_size + offset;
+ break;
+
+ default:
+ ntfs_log_trace("Wrong mode %d.\n", whence);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (abs_pos < 0 || abs_pos > DEV_FD(dev)->media_size) {
+ ntfs_log_trace("Seeking outsize seekable area.\n");
+ errno = EINVAL;
+ return -1;
+ }
+ DEV_FD(dev)->pos = abs_pos;
+ return abs_pos;
+}
+
+/**
+ * ntfs_device_unix_raw_io_read - Read from the device, from the current location
+ * @dev:
+ * @buf:
+ * @count:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_raw_io_read(struct ntfs_device *dev, void *buf,
+ s64 count)
+{
+ s64 start, start_aligned;
+ s64 end, end_aligned;
+ size_t count_aligned;
+ char *buf_aligned;
+ ssize_t nr;
+
+ /* short-circuit for regular files */
+ start = DEV_FD(dev)->pos;
+ if (count > RAW_IO_MAX_SIZE)
+ count = RAW_IO_MAX_SIZE;
+ if (RAW_IO_ALIGNED(dev, start, count)) {
+ nr = raw_io_pread(dev, buf, count, start);
+ if (nr <= 0)
+ return nr;
+
+ DEV_FD(dev)->pos += nr;
+ return nr;
+ }
+
+ /*
+ * +- start_aligned +- end_aligned
+ * | |
+ * | +- start +- end |
+ * v v v v
+ * |----------|----------|----------|
+ * ^ ^
+ * +----- count ------+
+ * ^ ^
+ * +-------- count_aligned ---------+
+ */
+ start_aligned = RAW_IO_ALIGN(dev, start);
+ end = start + count;
+ end_aligned = RAW_IO_ALIGN(dev, end) +
+ (RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_FD(dev)->block_size);
+ count_aligned = end_aligned - start_aligned;
+ ntfs_log_trace(
+ "%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
+ dev->d_name, count, count_aligned,
+ start, start_aligned, end, end_aligned);
+
+ /* allocate buffer */
+ buf_aligned = malloc(count_aligned);
+ if (buf_aligned == NULL) {
+ ntfs_log_trace("malloc(%d) failed\n", count_aligned);
+ return -1;
+ }
+
+ /* read aligned data */
+ nr = raw_io_pread(dev, buf_aligned, count_aligned, start_aligned);
+ if (nr == 0)
+ return 0;
+ if (nr < 0 || nr < start - start_aligned) {
+ free(buf_aligned);
+ return -1;
+ }
+
+ /* copy out */
+ memcpy(buf, buf_aligned + (start - start_aligned), count);
+ free(buf_aligned);
+
+ nr -= start - start_aligned;
+ if (nr > count)
+ nr = count;
+ DEV_FD(dev)->pos += nr;
+ return nr;
+}
+
+/**
+ * ntfs_device_unix_raw_io_write - Write to the device, at the current location
+ * @dev:
+ * @buf:
+ * @count:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_raw_io_write(struct ntfs_device *dev, const void *buf,
+ s64 count)
+{
+ s64 start, start_aligned;
+ s64 end, end_aligned;
+ size_t count_aligned;
+ char *buf_aligned;
+ ssize_t nw;
+
+ if (NDevReadOnly(dev)) {
+ errno = EROFS;
+ return -1;
+ }
+ NDevSetDirty(dev);
+
+ /* short-circuit for regular files */
+ start = DEV_FD(dev)->pos;
+ if (count > RAW_IO_MAX_SIZE)
+ count = RAW_IO_MAX_SIZE;
+ if (RAW_IO_ALIGNED(dev, start, count)) {
+ nw = raw_io_pwrite(dev, buf, count, start);
+ if (nw <= 0)
+ return nw;
+
+ DEV_FD(dev)->pos += nw;
+ return nw;
+ }
+
+ /*
+ * +- start_aligned +- end_aligned
+ * | |
+ * | +- start +- end |
+ * v v v v
+ * |----------|----------|----------|
+ * ^ ^
+ * +----- count ------+
+ * ^ ^
+ * +-------- count_aligned ---------+
+ */
+ start_aligned = RAW_IO_ALIGN(dev, start);
+ end = start + count;
+ end_aligned = RAW_IO_ALIGN(dev, end) +
+ (RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_FD(dev)->block_size);
+ count_aligned = end_aligned - start_aligned;
+ ntfs_log_trace(
+ "%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
+ dev->d_name, count, count_aligned,
+ start, start_aligned, end, end_aligned);
+
+ /* allocate buffer */
+ buf_aligned = malloc(count_aligned);
+ if (buf_aligned == NULL) {
+ ntfs_log_trace("malloc(%d) failed\n", count_aligned);
+ return -1;
+ }
+
+ /* read aligned lead-in */
+ if (raw_io_pread(dev, buf_aligned, DEV_FD(dev)->block_size, start_aligned) != DEV_FD(dev)->block_size) {
+ ntfs_log_trace("read lead-in failed\n");
+ free(buf_aligned);
+ return -1;
+ }
+
+ /* read aligned lead-out */
+ if (end != end_aligned && count_aligned > DEV_FD(dev)->block_size) {
+ if (raw_io_pread(dev, buf_aligned + count_aligned - DEV_FD(dev)->block_size, DEV_FD(dev)->block_size, end_aligned - DEV_FD(dev)->block_size) != DEV_FD(dev)->block_size) {
+ ntfs_log_trace("read lead-out failed\n");
+ free(buf_aligned);
+ return -1;
+ }
+ }
+
+ /* copy data to write */
+ memcpy(buf_aligned + (start - start_aligned), buf, count);
+
+ /* write aligned data */
+ nw = raw_io_pwrite(dev, buf_aligned, count_aligned, start_aligned);
+ free(buf_aligned);
+ if (nw < 0 || nw < start - start_aligned)
+ return -1;
+
+ nw -= start - start_aligned;
+ if (nw > count)
+ nw = count;
+ DEV_FD(dev)->pos += nw;
+ return nw;
+}
+
+/**
+ * ntfs_device_unix_raw_io_pread - Perform a positioned read from the device
+ * @dev:
+ * @buf:
+ * @count:
+ * @offset:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_raw_io_pread(struct ntfs_device *dev, void *buf,
+ s64 count, s64 offset)
+{
+ return ntfs_pread(dev, offset, count, buf);
+}
+
+/**
+ * ntfs_device_unix_raw_io_pwrite - Perform a positioned write to the device
+ * @dev:
+ * @buf:
+ * @count:
+ * @offset:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_raw_io_pwrite(struct ntfs_device *dev, const void *buf,
+ s64 count, s64 offset)
+{
+ if (NDevReadOnly(dev)) {
+ errno = EROFS;
+ return -1;
+ }
+ NDevSetDirty(dev);
+
+ return ntfs_pwrite(dev, offset, count, buf);
+}
+
+/**
+ * ntfs_device_unix_raw_io_sync - Flush any buffered changes to the device
+ * @dev:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_raw_io_sync(struct ntfs_device *dev)
+{
+ if (!NDevReadOnly(dev)) {
+ int res = fsync(DEV_FD(dev)->fd);
+ if (!res)
+ NDevClearDirty(dev);
+ return res;
+ }
+ return 0;
+}
+
+/**
+ * ntfs_device_unix_raw_io_stat - Get information about the device
+ * @dev:
+ * @buf:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_raw_io_stat(struct ntfs_device *dev, struct stat *buf)
+{
+ return fstat(DEV_FD(dev)->fd, buf);
+}
+
+/**
+ * ntfs_device_unix_raw_io_ioctl - Perform an ioctl on the device
+ * @dev:
+ * @request:
+ * @argp:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_raw_io_ioctl(struct ntfs_device *dev, int request,
+ void *argp)
+{
+ return ioctl(DEV_FD(dev)->fd, request, argp);
+}
+
+/**
+ * Device operations for working with unix style devices and files.
+ */
+struct ntfs_device_operations ntfs_device_unix_io_ops = {
+ .open = ntfs_device_unix_raw_io_open,
+ .close = ntfs_device_unix_raw_io_close,
+ .seek = ntfs_device_unix_raw_io_seek,
+ .read = ntfs_device_unix_raw_io_read,
+ .write = ntfs_device_unix_raw_io_write,
+ .pread = ntfs_device_unix_raw_io_pread,
+ .pwrite = ntfs_device_unix_raw_io_pwrite,
+ .sync = ntfs_device_unix_raw_io_sync,
+ .stat = ntfs_device_unix_raw_io_stat,
+ .ioctl = ntfs_device_unix_raw_io_ioctl,
+};