/* * unix_io.c - Unix stule disk io functions. Part of the Linux-NTFS project. * * Copyright (c) 2000-2003 Anton Altaparmakov * * 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 Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_LINUX_FD_H # include #endif #include "types.h" #include "mst.h" #include "debug.h" #include "device.h" #if defined(linux) && defined(_IO) && !defined(BLKGETSIZE) # define BLKGETSIZE _IO(0x12,96) /* Get device size in 512byte blocks. */ #endif static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags) { struct flock flk; if (NDevOpen(dev)) { errno = EBUSY; return -1; } /* Open the device/file obtaining the file descriptor. */ if (((int)dev->d_private = open(dev->d_name, flags)) == -1) return -1; /* Setup our read-only flag. */ if ((flags & O_RDWR) != O_RDWR) NDevSetReadOnly(dev); /* Acquire exlusive (mandatory) lock on the whole device. */ 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((int)dev->d_private, F_SETLK, &flk)) { int eo = errno; Dprintf("ntfs_device_unix_io_open: Could not lock %s for %s: " "%s\n", dev->d_name, NDevReadOnly(dev) ? "reading" : "writing", strerror(errno)); if (close((int)dev->d_private)) Dprintf("ntfs_device_unix_io_open: Warning: Could not " "close %s: %s\n", dev->d_name, strerror(errno)); errno = eo; return -1; } /* Set our open flag. */ NDevSetOpen(dev); return 0; } static int ntfs_device_unix_io_close(struct ntfs_device *dev) { struct flock flk; if (!NDevOpen(dev)) { errno = EBADF; return -1; } if (NDevDirty(dev)) fsync((int)dev->d_private); /* Release exlusive (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((int)dev->d_private, F_SETLK, &flk)) Dprintf("ntfs_device_unix_io_close: Warning: Could not unlock " "%s: %s\n", dev->d_name, strerror(errno)); /* Close the file descriptor and clear our open flag. */ if (close((int)dev->d_private)) return -1; NDevClearOpen(dev); return 0; } static s64 ntfs_device_unix_io_seek(struct ntfs_device *dev, s64 offset, int whence) { return lseek((int)dev->d_private, offset, whence); } static s64 ntfs_device_unix_io_read(struct ntfs_device *dev, void *buf, s64 count) { return read((int)dev->d_private, buf, count); } static s64 ntfs_device_unix_io_write(struct ntfs_device *dev, const void *buf, s64 count) { if (NDevReadOnly(dev)) { errno = EROFS; return -1; } NDevSetDirty(dev); return write((int)dev->d_private, buf, count); } static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset) { return ntfs_pread(dev, offset, count, buf); } static s64 ntfs_device_unix_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); } static int ntfs_device_unix_io_sync(struct ntfs_device *dev) { if (!NDevReadOnly(dev) && NDevDirty(dev)) { int res = fsync((int)dev->d_private); if (!res) NDevClearDirty(dev); return res; } return 0; } static int ntfs_device_unix_io_stat(struct ntfs_device *dev, struct stat *buf) { return fstat((int)dev->d_private, buf); } static int ntfs_device_unix_io_ioctl(struct ntfs_device *dev, int request, void *argp) { return ioctl((int)dev->d_private, 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_io_open, .close = ntfs_device_unix_io_close, .seek = ntfs_device_unix_io_seek, .read = ntfs_device_unix_io_read, .write = ntfs_device_unix_io_write, .pread = ntfs_device_unix_io_pread, .pwrite = ntfs_device_unix_io_pwrite, .sync = ntfs_device_unix_io_sync, .stat = ntfs_device_unix_io_stat, .ioctl = ntfs_device_unix_io_ioctl, };