diff --git a/libntfs/freebsd_io.c b/libntfs/freebsd_io.c deleted file mode 100644 index f5e96c00..00000000 --- a/libntfs/freebsd_io.c +++ /dev/null @@ -1,546 +0,0 @@ -/** - * freebsd_io.c - FreeBSD disk io functions. Part of the Linux-NTFS project. - * - * FreeBSD 5.0+ does not have block devices and requires read/writes from/to - * character devices to be sector aligned. - * - * Copyright (c) 2006 Max Khon - * Copyright (c) 2006 Anton Altaparmakov - * Copyright (c) 2006 Yura Pakhuchiy - * - * 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 -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_LINUX_FD_H -#include -#endif -#include - -#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; -} freebsd_fd; - -#define DEV_FD(dev) (((freebsd_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 freebsd_get_size(struct ntfs_device *dev) -{ - off_t ms; - int bs; - 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; -} - -/** - * freebsd_pread - Aligned read - */ -static inline ssize_t freebsd_pread(struct ntfs_device *dev, char *buf, - size_t count, s64 offset) -{ - return pread(DEV_FD(dev)->fd, buf, count, offset); -} - -/** - * freebsd_pwrite - Aligned write - */ -static inline ssize_t freebsd_pwrite(struct ntfs_device *dev, const char *buf, - size_t count, s64 offset) -{ - return pwrite(DEV_FD(dev)->fd, buf, count, offset); -} - -/** - * ntfs_device_freebsd_io_open - Open a device and lock it exclusively - * @dev: - * @flags: - * - * Description... - * - * Returns: - */ -static int ntfs_device_freebsd_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(freebsd_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; - - 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 (freebsd_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_freebsd_io_close - Close the device, releasing the lock - * @dev: - * - * Description... - * - * Returns: - */ -static int ntfs_device_freebsd_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_freebsd_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_freebsd_io_seek - Seek to a place on the device - * @dev: - * @offset: - * @whence: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_freebsd_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_freebsd_io_read - Read from the device, from the current location - * @dev: - * @buf: - * @count: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_freebsd_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 = freebsd_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 = freebsd_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_freebsd_io_write - Write to the device, at the current location - * @dev: - * @buf: - * @count: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_freebsd_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 = freebsd_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 (freebsd_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 (freebsd_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 = freebsd_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_freebsd_io_sync - Flush any buffered changes to the device - * @dev: - * - * Description... - * - * Returns: - */ -static int ntfs_device_freebsd_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_freebsd_io_stat - Get information about the device - * @dev: - * @buf: - * - * Description... - * - * Returns: - */ -static int ntfs_device_freebsd_io_stat(struct ntfs_device *dev, struct stat *buf) -{ - return fstat(DEV_FD(dev)->fd, buf); -} - -/** - * ntfs_device_freebsd_io_ioctl - Perform an ioctl on the device - * @dev: - * @request: - * @argp: - * - * Description... - * - * Returns: - */ -static int ntfs_device_freebsd_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_freebsd_io_open, - .close = ntfs_device_freebsd_io_close, - .seek = ntfs_device_freebsd_io_seek, - .read = ntfs_device_freebsd_io_read, - .write = ntfs_device_freebsd_io_write, - .sync = ntfs_device_freebsd_io_sync, - .stat = ntfs_device_freebsd_io_stat, - .ioctl = ntfs_device_freebsd_io_ioctl, -};