Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv17365/libntfs
Modified Files:
attrib.c
Log Message:
ntfs_attr_pread() fixes and finished 1st draft of ntfs_attr_pwrite().
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -U2 -r1.41 -r1.42
--- attrib.c 5 Jun 2002 00:29:18 -0000 1.41
+++ attrib.c 5 Jun 2002 09:19:44 -0000 1.42
@@ -37,5 +37,4 @@
#include "layout.h"
#include "inode.h"
-#include "endians.h"
/* FIXME: Need to write the new flags to disk. */
@@ -1673,5 +1672,5 @@
__s64 ntfs_attr_pread(ntfs_attr *na, const __s64 pos, __s64 count, void *b)
{
- __s64 br, to_read, ofs, total;
+ __s64 br, to_read, ofs, total, total2;
ntfs_volume *vol;
run_list_element *rl;
@@ -1743,5 +1742,5 @@
return count;
}
- total = 0;
+ total = total2 = 0;
/* Zero out reads beyond initialized size. */
if (pos + count > na->initialized_size) {
@@ -1750,7 +1749,7 @@
return count;
}
- total = pos + count - na->initialized_size;
- count -= total;
- memset(b + count, 0, total);
+ total2 = pos + count - na->initialized_size;
+ count -= total2;
+ memset(b + count, 0, total2);
}
/* Find the run list element containing the vcn. */
@@ -1758,9 +1757,10 @@
if (!rl) {
/*
- * If the vcn is not present it is an out of bounds read which
- * means a read beyond end of file, thus just return 0.
+ * If the vcn is not present it is an out of bounds read.
+ * However, we already truncated the read to the data_size,
+ * so getting this here is an error.
*/
if (errno == ENOENT)
- return 0;
+ errno = EIO;
return -1;
}
@@ -1772,19 +1772,10 @@
ofs = pos - (rl->vcn << vol->cluster_size_bits);
for (; count; rl++, ofs = 0) {
- /* If we have reached the end of the run list return. */
if (!rl->length)
- return total;
+ goto rl_err_out;
if (rl->lcn < (LCN)0) {
- if (rl->lcn != (LCN)LCN_HOLE) {
- /*
- * If we have already read anything, return how
- * much. Same if the read is beyond the end.
- */
- if (total || rl->lcn == (LCN)LCN_ENOENT)
- return total;
- errno = EIO;
- return -1;
- }
- /* It is a hole, just zero the matching @dst range. */
+ if (rl->lcn != (LCN)LCN_HOLE)
+ goto rl_err_out;
+ /* It is a hole, just zero the matching @b range. */
to_read = min(count, (rl->length <<
vol->cluster_size_bits) - ofs);
@@ -1815,12 +1806,17 @@
if (br == (__s64)-1 && errno == EINTR)
goto retry;
- /* If EOF or error, return number of bytes read. */
- if (!br || total)
+ if (total)
return total;
- /* Nothing read, return error. */
- return br;
+ if (!br)
+ errno = EIO;
+ return -1;
}
/* Finally, return the number of bytes read. */
- return total;
+ return total + total2;
+rl_err_out:
+ if (total)
+ return total;
+ errno = EIO;
+ return -1;
}
@@ -1849,5 +1845,5 @@
__s64 ntfs_attr_pwrite(ntfs_attr *na, const __s64 pos, __s64 count, void *b)
{
- __s64 br, to_write, ofs, total, old_initialized_size;
+ __s64 written, to_write, ofs, total, old_initialized_size;
ntfs_volume *vol;
ntfs_attr_search_ctx *ctx = NULL;
@@ -1937,9 +1933,10 @@
if (!rl) {
/*
- * If the vcn is not present it is an out of bounds read which
- * means a read beyond end of file, thus just return 0.
+ * If the vcn is not present it is an out of bounds write.
+ * However, we already extended the size of the attribute,
+ * so getting this here must be an error of some kind.
*/
if (errno == ENOENT)
- goto done;
+ errno = EIO;
goto err_out;
}
@@ -1989,69 +1986,101 @@
need_to_undo.initialized_size = 1;
}
-
-// FIXME: Am here! (AIA)
-errno = ENOTSUP;
-goto err_out;
/*
- * Gather the requested data into the linear destination buffer. Note,
- * a partial final vcn is taken care of by the @count capping of read
+ * Scatter the data from the linear data buffer to the volume. Note, a
+ * partial final vcn is taken care of by the @count capping of write
* length.
*/
ofs = pos - (rl->vcn << vol->cluster_size_bits);
for (; count; rl++, ofs = 0) {
- /* If we have reached the end of the run list return. */
- if (!rl->length)
- goto done;
+ if (!rl->length) {
+ errno = EIO;
+ goto rl_err_out;
+ }
if (rl->lcn < (LCN)0) {
+ __s64 t;
+ int cnt;
+
if (rl->lcn != (LCN)LCN_HOLE) {
- /*
- * If we have already read anything, return how
- * much. Same if the read is beyond the end.
- */
- if (total || rl->lcn == (LCN)LCN_ENOENT)
- goto done;
errno = EIO;
- goto err_out;
+ goto rl_err_out;
}
- /* It is a hole, just zero the matching @dst range. */
+ /*
+ * It is a hole. Check if the data buffer is zero in
+ * this region and if not instantiate the hole.
+ */
to_write = min(count, (rl->length <<
vol->cluster_size_bits) - ofs);
- memset(b, 0, to_write);
- /* Update progress counters. */
- total += to_write;
- count -= to_write;
- b += to_write;
- continue;
+ written = to_write / sizeof(unsigned long);
+ eo = 0;
+ for (t = 0; t < written; t++) {
+ if (((unsigned long*)b)[t]) {
+ eo = 1;
+ break;
+ }
+ }
+ cnt = to_write & (sizeof(unsigned long) - 1);
+ if (cnt && !eo) {
+ int i;
+ __u8 *b2;
+
+ b2 = b + (to_write &
+ ~(sizeof(unsigned long) - 1));
+ for (i = 0; i < cnt; i++) {
+ if (b2[i]) {
+ eo = 1;
+ break;
+ }
+ }
+ }
+ if (eo) {
+ // TODO: Need to instantiate the hole. Then get
+ // the run list element again checking if it is
+ // ok and fall through to do the writing. (AIA)
+ errno = ENOTSUP;
+ goto rl_err_out;
+ }
}
- /* It is a real lcn, read it into @dst. */
+ /* It is a real lcn, write it to the volume. */
to_write = min(count, (rl->length << vol->cluster_size_bits) -
ofs);
retry:
- Dprintf(__FUNCTION__ "(): Reading 0x%Lx bytes from vcn "
+ Dprintf(__FUNCTION__ "(): Writing 0x%Lx bytes to vcn "
"0x%Lx, lcn 0x%Lx, ofs 0x%Lx.\n", to_write,
rl->vcn, rl->lcn, ofs);
- br = ntfs_pread(f, (rl->lcn << vol->cluster_size_bits) + ofs,
- to_write, b);
+ written = ntfs_pwrite(f, (rl->lcn << vol->cluster_size_bits) +
+ ofs, to_write, b);
/* If everything ok, update progress counters and continue. */
- if (br > 0) {
- total += br;
- count -= br;
- b += br;
+ if (written > 0) {
+ total += written;
+ count -= written;
+ b += written;
continue;
}
/* If the syscall was interrupted, try again. */
- if (br == (__s64)-1 && errno == EINTR)
+ if (written == (__s64)-1 && errno == EINTR)
goto retry;
- /* If EOF or error, return number of bytes read. */
- if (!br || total)
- goto done;
- /* Nothing read, return error. */
- goto err_out;
+ if (!written)
+ errno = EIO;
+ goto rl_err_out;
}
done:
if (ctx)
ntfs_put_attr_search_ctx(ctx);
- /* Finally, return the number of bytes read. */
+ /* Finally, return the number of bytes written. */
return total;
+rl_err_out:
+ eo = errno;
+ if (total) {
+ if (need_to_undo.initialized_size) {
+ if (pos + total > na->initialized_size)
+ goto done;
+ // TODO: Need to try to change initialized_size. If it
+ // succeeds goto done, otherwise goto err_out. (AIA)
+ errno = ENOTSUP;
+ goto err_out;
+ }
+ goto done;
+ }
+ errno = eo;
err_out:
eo = errno;
|