- Implement ntfs_pread() and ntfs_pwrite() in terms of device

operations pread() and pwrite() respectively and fall back to using
  seek() + read()/write() if no pread()/pwrite() device operation is
  supplied or the OS does not support the pread()/pwrite() system call.
  Adapt unix_io pread()/pwrite() device operations to use pread()/
  pwrite() system call and adapt win32_io device operations to not
  supply pread()/pwrite().  (Csaba Henk, Anton)
edge.strict_endians
aia21 2006-12-09 14:01:12 +00:00
parent 8640540b53
commit f73d77d568
6 changed files with 84 additions and 35 deletions

View File

@ -17,6 +17,7 @@ Matthew J. Fanto <mattjf at uncompiled.com>
Yuval Fledel <yuvalfl at gmail.com>
Marcin Gibuła <m.gibula at conecto.pl>
Christophe Grenier <grenier at cgsecurity.org>
Csaba Henk <csaba.henk at creo.hu>
Ian Jackson <ian at davenant.greenend.org.uk>
Carmelo Kintana <kintana at berkeley.edu>
Jan Kratochvil <project-captive at jankratochvil.net>

View File

@ -99,6 +99,13 @@ xx/xx/2006 - x.xx.x - .
- ntfsmount: fix rename if destination already exists. (Yura)
- ntfsfix: do not set VOLUME_MOUNTED_ON_NT4 flag as it causes Vista to
not boot any more.
- Implement ntfs_pread() and ntfs_pwrite() in terms of device
operations pread() and pwrite() respectively and fall back to using
seek() + read()/write() if no pread()/pwrite() device operation is
supplied or the OS does not support the pread()/pwrite() system call.
Adapt unix_io pread()/pwrite() device operations to use pread()/
pwrite() system call and adapt win32_io device operations to not
supply pread()/pwrite(). (Csaba Henk, Anton)
21/06/2006 - 1.13.1 - Various fixes.

View File

@ -152,6 +152,22 @@ int ntfs_device_free(struct ntfs_device *dev)
return 0;
}
/**
* fake_pread - read operation disguised as pread
* @dev: device to read from
* @b: output data buffer
* @count: number of bytes to read
* @pos: position in device to read from
*
* Auxiliary function, used when we emulate pread by seek() + a sequence of
* read()s.
*/
static s64 fake_pread(struct ntfs_device *dev, void *b, s64 count,
s64 pos __attribute__((unused)))
{
return dev->d_ops->read(dev, b, count);
}
/**
* ntfs_pread - positioned read from disk
* @dev: device to read from
@ -175,6 +191,7 @@ s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b)
{
s64 br, total;
struct ntfs_device_operations *dops;
s64 (*_pread)(struct ntfs_device *, void *, s64, s64);
ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count);
if (!b || count < 0 || pos < 0) {
@ -184,21 +201,34 @@ s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b)
if (!count)
return 0;
dops = dev->d_ops;
/* Locate to position. */
if (dops->seek(dev, pos, SEEK_SET) == (off_t)-1) {
ntfs_log_perror("ntfs_pread: device seek to 0x%llx returned error",
pos);
_pread = dops->pread;
if (!_pread)
_pread = fake_pread;
seek:
/* Locate to position if pread is to be emulated by seek() + read(). */
if (_pread == fake_pread &&
dops->seek(dev, pos, SEEK_SET) == (off_t)-1) {
ntfs_log_perror("ntfs_pread: device seek to 0x%llx returned "
"error", pos);
return -1;
}
/* Read the data. */
for (total = 0; count; count -= br, total += br) {
br = dops->read(dev, (char*)b + total, count);
br = _pread(dev, (char*)b + total, count, pos + total);
/* If everything ok, continue. */
if (br > 0)
continue;
/* If EOF or error return number of bytes read. */
if (!br || total)
return total;
/*
* If pread is not supported by the OS, fall back to emulating
* it by seek() + read().
*/
if (errno == ENOSYS && _pread != fake_pread) {
_pread = fake_pread;
goto seek;
}
/* Nothing read and error, return error status. */
return br;
}
@ -206,6 +236,22 @@ s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b)
return total;
}
/**
* fake_pwrite - write operation disguised as pwrite
* @dev: device to write to
* @b: input data buffer
* @count: number of bytes to write
* @pos: position in device to write to
*
* Auxiliary function, used when we emulate pwrite by seek() + a sequence of
* write()s.
*/
static s64 fake_pwrite(struct ntfs_device *dev, const void *b, s64 count,
s64 pos __attribute__((unused)))
{
return dev->d_ops->write(dev, b, count);
}
/**
* ntfs_pwrite - positioned write to disk
* @dev: device to write to
@ -230,6 +276,7 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
{
s64 written, total;
struct ntfs_device_operations *dops;
s64 (*_pwrite)(struct ntfs_device *, const void *, s64, s64);
ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count);
if (!b || count < 0 || pos < 0) {
@ -243,8 +290,15 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
return -1;
}
dops = dev->d_ops;
/* Locate to position. */
if (dops->seek(dev, pos, SEEK_SET) == (off_t)-1) {
_pwrite = dops->pwrite;
if (!_pwrite)
_pwrite = fake_pwrite;
seek:
/*
* Locate to position if pwrite is to be emulated by seek() + write().
*/
if (_pwrite == fake_pwrite &&
dops->seek(dev, pos, SEEK_SET) == (off_t)-1) {
ntfs_log_perror("ntfs_pwrite: seek to 0x%llx returned error",
pos);
return -1;
@ -252,7 +306,8 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
NDevSetDirty(dev);
/* Write the data. */
for (total = 0; count; count -= written, total += written) {
written = dops->write(dev, (const char*)b + total, count);
written = _pwrite(dev, (const char*)b + total, count,
pos + total);
/* If everything ok, continue. */
if (written > 0)
continue;
@ -261,6 +316,14 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
*/
if (!written || total)
break;
/*
* If pwrite is not supported by the OS, fall back to emulating
* it by seek() + write().
*/
if (errno == ENOSYS && _pwrite != fake_pwrite) {
_pwrite = fake_pwrite;
goto seek;
}
/* Nothing written and error, return error status. */
return written;
}

View File

@ -486,25 +486,23 @@ close_err_out:
u64 ntfs_pathname_to_inode_num(ntfs_volume *vol, ntfs_inode *parent,
const char *pathname)
{
u64 inum, result = (u64)-1;
u64 inum, result;
int len, err = 0;
char *p, *q;
ntfs_inode *ni = NULL;
ntfschar *unicode = NULL;
char *ascii = NULL;
inum = result = (u64)-1;
if (!vol || !pathname) {
err = EINVAL;
goto close;
}
ntfs_log_trace("Path: '%s'\n", pathname);
if (parent) {
ni = parent;
} else
inum = FILE_root;
unicode = calloc(1, MAX_PATH);
ascii = strdup(pathname);
if (!unicode || !ascii) {
@ -512,7 +510,6 @@ u64 ntfs_pathname_to_inode_num(ntfs_volume *vol, ntfs_inode *parent,
err = ENOMEM;
goto close;
}
p = ascii;
/* Remove leading /'s. */
while (p && *p == PATH_SEP)
@ -527,14 +524,12 @@ u64 ntfs_pathname_to_inode_num(ntfs_volume *vol, ntfs_inode *parent,
goto close;
}
}
/* Find the end of the first token. */
q = strchr(p, PATH_SEP);
if (q != NULL) {
*q = 0;
q++;
}
len = ntfs_mbstoucs(p, &unicode, MAX_PATH);
if (len < 0) {
ntfs_log_debug("Couldn't convert name to Unicode: "
@ -542,20 +537,17 @@ u64 ntfs_pathname_to_inode_num(ntfs_volume *vol, ntfs_inode *parent,
err = EILSEQ;
goto close;
}
inum = ntfs_inode_lookup_by_name(ni, unicode, len);
if (inum == (u64) -1) {
if (inum == (u64)-1) {
ntfs_log_debug("Couldn't find name '%s' in pathname "
"'%s'.\n", p, pathname);
err = ENOENT;
goto close;
}
inum = MREF(inum);
if (ni != parent)
ntfs_inode_close(ni);
ni = NULL;
p = q;
while (p && *p == PATH_SEP)
p++;

View File

@ -229,7 +229,7 @@ static s64 ntfs_device_unix_io_write(struct ntfs_device *dev, const void *buf,
static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf,
s64 count, s64 offset)
{
return ntfs_pread(dev, offset, count, buf);
return pread(DEV_FD(dev), buf, count, offset);
}
/**
@ -251,7 +251,7 @@ static s64 ntfs_device_unix_io_pwrite(struct ntfs_device *dev, const void *buf,
return -1;
}
NDevSetDirty(dev);
return ntfs_pwrite(dev, offset, count, buf);
return pwrite(DEV_FD(dev), buf, count, offset);
}
/**

View File

@ -1449,26 +1449,12 @@ static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
}
}
static s64 ntfs_device_win32_pread(struct ntfs_device *dev, void *b,
s64 count, s64 offset)
{
return ntfs_pread(dev, offset, count, b);
}
static s64 ntfs_device_win32_pwrite(struct ntfs_device *dev, const void *b,
s64 count, s64 offset)
{
return ntfs_pwrite(dev, offset, count, b);
}
struct ntfs_device_operations ntfs_device_win32_io_ops = {
.open = ntfs_device_win32_open,
.close = ntfs_device_win32_close,
.seek = ntfs_device_win32_seek,
.read = ntfs_device_win32_read,
.write = ntfs_device_win32_write,
.pread = ntfs_device_win32_pread,
.pwrite = ntfs_device_win32_pwrite,
.sync = ntfs_device_win32_sync,
.stat = ntfs_device_win32_stat,
.ioctl = ntfs_device_win32_ioctl