diff --git a/libntfs/unix_io.c b/libntfs/unix_io.c index e69de29b..20e5d7e0 100644 --- a/libntfs/unix_io.c +++ b/libntfs/unix_io.c @@ -0,0 +1,187 @@ +/* + * 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, +}; +