Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv26368/libntfs
Modified Files:
attrib.c
Log Message:
Implement attrib.[hc]::ntfs_rl_pwrite(). Fix a dumb bug in ntfs_attr_pwrite().
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -U2 -r1.51 -r1.52
--- attrib.c 6 Jul 2002 20:07:59 -0000 1.51
+++ attrib.c 8 Jul 2002 00:09:41 -0000 1.52
@@ -1651,4 +1651,117 @@
/**
+ * ntfs_rl_pwrite - scatter write to disk
+ * @vol: ntfs volume to write to
+ * @rl: run list specifying where to write the data to
+ * @pos: byte position within run list @rl at which to begin the write
+ * @count: number of bytes to write
+ * @b: data buffer to write to disk
+ *
+ * This function will write @count bytes from data buffer @b to the volume @vol
+ * scattering the data as specified by the run list @rl. The write begins at
+ * offset @pos into the run list @rl.
+ *
+ * On success, return the number of successfully written bytes. If this number
+ * is lower than @count this means that the write has been interrupted in
+ * flight or that an error was encountered during the write so that the write
+ * is partial. 0 means nothing was written (also return 0 when @count is 0).
+ *
+ * On error and nothing has been written, return -1 with errno set
+ * appropriately to the return code of either lseek, write, fdatasync, or set
+ * to EINVAL in case of invalid arguments.
+ */
+s64 ntfs_rl_pwrite(const ntfs_volume *vol, const run_list_element *rl,
+ const s64 pos, s64 count, void *b)
+{
+ s64 written, to_write, ofs, total;
+ int f, err = EIO;
+
+ if (!vol || !rl || pos < 0 || count < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ f = vol->fd;
+ if (!f) {
+ errno = EBADF;
+ return -1;
+ }
+ if (!count)
+ return count;
+ /* Seek in @rl to the run containing @pos. */
+ for (ofs = 0; rl->length && (ofs + rl->length <= pos); rl++)
+ ofs += rl->length;
+ /* Offset in the run at which to begin writing. */
+ ofs = pos - ofs;
+ for (total = 0LL; count; rl++, ofs = 0) {
+ if (!rl->length)
+ goto rl_err_out;
+ if (rl->lcn < (LCN) 0) {
+ s64 t;
+ int cnt;
+
+ if (rl->lcn != (LCN)LCN_HOLE)
+ goto rl_err_out;
+ /*
+ * It is a hole. Check if the buffer is zero in this
+ * region and if not abort with error.
+ */
+ to_write = min(count, (rl->length <<
+ vol->cluster_size_bits) - ofs);
+ written = to_write / sizeof(unsigned long);
+ for (t = 0; t < written; t++) {
+ if (((unsigned long*)b)[t])
+ goto rl_err_out;
+ }
+ cnt = to_write & (sizeof(unsigned long) - 1);
+ if (cnt) {
+ int i;
+ u8 *b2;
+
+ b2 = b + (to_write &
+ ~(sizeof(unsigned long) - 1));
+ for (i = 0; i < cnt; i++) {
+ if (b2[i])
+ goto rl_err_out;
+ }
+ }
+ /*
+ * The buffer region is zero, update progress counters
+ * and proceed with next run.
+ */
+ total += to_write;
+ count -= to_write;
+ b += to_write;
+ continue;
+ }
+ /* It is a real lcn, write it to the volume. */
+ to_write = min(count, (rl->length << vol->cluster_size_bits) -
+ ofs);
+retry:
+ written = ntfs_pwrite(f, (rl->lcn << vol->cluster_size_bits) +
+ ofs, to_write, b);
+ /* If everything ok, update progress counters and continue. */
+ if (written > 0) {
+ total += written;
+ count -= written;
+ b += written;
+ continue;
+ }
+ /* If the syscall was interrupted, try again. */
+ if (written == (s64)-1 && errno == EINTR)
+ goto retry;
+ if (written == -1)
+ err = errno;
+ goto rl_err_out;
+ }
+ /* Finally, return the number of bytes written. */
+ return total;
+rl_err_out:
+ if (total)
+ return total;
+ errno = err;
+ return -1;
+}
+
+/**
* ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
* @na: ntfs attribute to read from
@@ -2040,4 +2153,12 @@
goto rl_err_out;
}
+ /*
+ * The buffer region is zero, update progress counters
+ * and proceed with next run.
+ */
+ total += to_write;
+ count -= to_write;
+ b += to_write;
+ continue;
}
/* It is a real lcn, write it to the volume. */
|