Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv4109/libntfs
Modified Files:
attrib.c disk_io.c unistr.c volume.c
Log Message:
Loads of stuff. Improvements, start on attr pread and attr mst_pread. Write to follow. ntfslabel cleanup and extensions. libntfs cleanups, fixes, etc.
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -U2 -r1.36 -r1.37
--- attrib.c 27 Apr 2002 19:49:09 -0000 1.36
+++ attrib.c 29 Apr 2002 01:53:55 -0000 1.37
@@ -1510,8 +1510,6 @@
if (!rl)
goto map_rl;
- if (vcn < rl[0].vcn) {
- errno = ENOENT;
- return NULL;
- }
+ if (vcn < rl[0].vcn)
+ goto map_rl;
while (rl->length) {
if (vcn < rl[1].vcn) {
@@ -1552,4 +1550,234 @@
return NULL;
}
+
+/**
+ * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
+ * @na: ntfs attribute to read from
+ * @pos: byte position in the attribute to begin reading from
+ * @count: number of bytes to read
+ * @dst: output data buffer
+ *
+ * This function will read @count bytes starting at offset @pos from the ntfs
+ * attribute @na into the buffer @dst.
+ *
+ * On success, return return the number of successfully read bytes. If this
+ * number is lower than @count this means that we have either reached end of
+ * file or we encountered an error during the read so that the read is partial.
+ * 0 means end of file or nothing to read (@count is 0).
+ *
+ * On error and nothing has been read yet, return -1 with errno set
+ * appropriately to the return code of ntfs_pread(), or to EINVAL in case of
+ * invalid arguments.
+ */
+int ntfs_attr_pread(ntfs_attr *na, const __s64 pos, __s64 count, void *dst)
+{
+ __s64 br, to_read, total;
+ ntfs_volume *vol;
+ run_list_element *rl;
+ int f, ofs;
+
+ if (!na || !na->ni || !na->ni->vol || !dst || pos < 0 || count < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ vol = na->ni->vol;
+ f = vol->fd;
+ if (!f) {
+ errno = EBADF;
+ return -1;
+ }
+ if (!count)
+ return 0;
+ /* Find the run list element containing the vcn. */
+ rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
+ 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 (errno == ENOENT)
+ return 0;
+ return -1;
+ }
+ /*
+ * Gather the requested data into the linear destination buffer. Note,
+ * a partial final vcn is taken care of by the @count capping of read
+ * length.
+ */
+ ofs = pos & (vol->cluster_size - 1);
+ for (total = 0; count; rl++, ofs = 0) {
+ /* If we have reached the end of the run list return. */
+ if (!rl->length)
+ return total;
+ 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. */
+ to_read = min(count, (rl->length <<
+ vol->cluster_size_bits) - ofs);
+ memset(dst, 0, to_read);
+ /* Update progress counters. */
+ total += to_read;
+ count -= to_read;
+ dst += to_read;
+ continue;
+ }
+ /* It is a real lcn, read it into @dst. */
+ to_read = min(count, (rl->length << vol->cluster_size_bits) -
+ ofs);
+retry:
+ br = ntfs_pread(f, (rl->lcn << vol->cluster_size_bits) + ofs,
+ to_read, dst);
+ /* If everything ok, update progress counters and continue. */
+ if (br > 0) {
+ total += br;
+ count -= br;
+ dst += br;
+ continue;
+ }
+ /* If the syscall was interrupted, try again. */
+ if (br == (__s64)-1 && errno == EINTR)
+ goto retry;
+ /* If EOF or error, return number of bytes read. */
+ if (!br || total)
+ return total;
+ /* Nothing read, return error. */
+ return br;
+ }
+ /* Finally, return the number of bytes read. */
+ return total;
+}
+
+/**
+ * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read
+ * @na: multi sector transfer protected ntfs attribute to read from
+ * @pos: byte position in the attribute to begin reading from
+ * @bk_cnt: number of mst protected blocks to read
+ * @bk_size: size of each mst protected block in bytes
+ * @dst: output data buffer
+ *
+ * This function will read @bk_cnt blocks of size @bk_size bytes each starting
+ * at offset @pos from the ntfs attribute @na into the buffer @dst.
+ *
+ * On succes, the multi sector transfer fixups are applied and the number of
+ * read blocks is returned. If this number is lower than @bk_cnt this means we
+ * that we have either reached end of file or we encountered an error during
+ * the read so that the read is partial. 0 means end of file or nothing to read
+ * (@bk_cnt is 0).
+ *
+ * On error and nothing has been read yet, return -1 with errno set
+ * appropriately to the return code of ntfs_pread(), or to EINVAL in case of
+ * invalid arguments.
+ *
+ * NOTE: If an incomplete multi sector transfer has been detected the magic
+ * will have been changed to magic_BAAD but no error will be returned.
+ * I.e. it is possible that we return @bk_cnt blocks as being read but
+ * that any number (between zero and @bk_cnt) of these blocks is actually
+ * subject to a multi sector transfer error. This should be detected by
+ * the caller by checking each block with is_baad_recordp(&block).
+ */
+#if 0
+int ntfs_attr_mst_pread(ntfs_attr *na, const __s64 pos, const __s64 bk_cnt,
+ const int bk_size, void *dst)
+{
+ VCN vcn;
+ __s64 br, to_read, total;
+ ntfs_volume *vol;
+ run_list_element *rl;
+ int f, ofs;
+
+ if (!na || !na->ni || !na->ni->vol || !dst || pos < 0 || bk_cnt < 0 ||
+ bk_size < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ vol = na->ni->vol;
+ f = vol->fd;
+ if (!f) {
+ errno = EBADF;
+ return -1;
+ }
+ if (!count)
+ return 0;
+ /* The vcn and ofs in the run list of the first byte to read. */
+ vcn = pos >> vol->cluster_size_bits;
+ ofs = pos & (vol->cluster_size - 1);
+
+ /* Find the run list element containing the vcn. */
+ rl = ntfs_attr_find_vcn(na, vcn);
+ 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 (errno == ENOENT)
+ return 0;
+ return -1;
+ }
+
+ /*
+ * Gather the requested data into the linear destination buffer. Note,
+ * a partial final vcn is taken care of by the @count capping of read
+ * length.
+ */
+ for (total = 0; count; rl++, ofs = 0) {
+ /* If we have reached the end of the run list return. */
+ if (!rl->length)
+ return total;
+ 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. */
+ to_read = min(count, (rl->length <<
+ vol->cluster_size_bits) - ofs);
+ memset(dst, 0, to_read);
+ /* Update progress counters. */
+ total += to_read;
+ count -= to_read;
+ dst += to_read;
+ continue;
+ }
+ /* It is a real lcn, read it into @dst. */
+ to_read = min(count, (rl->length << vol->cluster_size_bits) -
+ ofs);
+retry:
+ br = ntfs_pread(f, (rl->lcn << vol->cluster_size_bits) + ofs,
+ to_read, dst);
+ /* If everything ok, update progress counters and continue. */
+ if (br > 0) {
+ total += br;
+ count -= br;
+ dst += br;
+ continue;
+ }
+ /* If the syscall was interrupted, try again. */
+ if (br == (__s64)-1 && errno == EINTR)
+ goto retry;
+ /* If EOF or error, return number of bytes read. */
+ if (!br || total)
+ return total;
+ /* Nothing read, return error. */
+ return br;
+ }
+ /* Finally, return the number of bytes read. */
+ return total;
+}
+#endif
/*
Index: disk_io.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/disk_io.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -U2 -r1.22 -r1.23
--- disk_io.c 18 Apr 2002 18:15:46 -0000 1.22
+++ disk_io.c 29 Apr 2002 01:53:55 -0000 1.23
@@ -44,13 +44,15 @@
*
* On success, return the number of successfully read bytes. If this number is
- * lower than @count this means that we have reached end of file. 0 means end
- * of file or nothing to read (@count is 0). On error, return -1 with errno set
+ * lower than @count this means that we have either reached end of file or
+ * encountered an error during the read so that the read is partial. 0 means
+ * end of file or nothing to read (@count is 0).
+ *
+ * On error and nothing has been read yet, return -1 with errno set
* appropriately to the return code of either lseek or read, or to EINVAL in
- * case the data pointer @b was NULL.
+ * case of invalid arguments.
*/
__s64 ntfs_pread(const int fd, const __s64 pos, __s64 count, const void *b)
{
__s64 br, total;
- char retry;
if (!b || count < 0 || pos < 0) {
@@ -67,15 +69,15 @@
}
/* Read the data. */
- total = retry = 0;
- do {
+ for (total = 0; count; count -= br, total += br) {
br = read(fd, (char*)b + total, count);
- if (br == -1)
- return br;
- else if (!br)
- ++retry;
- /* We just recycle count as a local variable here. */
- count -= br;
- total += br;
- } while (count && (retry < 3));
+ /* If everything ok, continue. */
+ if (br > 0)
+ continue;
+ /* If EOF or error return number of bytes read. */
+ if (!br || total)
+ return total;
+ /* Nothing read and error, return error status. */
+ return br;
+ }
/* Finally, return the number of bytes read. */
return total;
@@ -94,5 +96,6 @@
* On success return bytes written (0 means nothing written).
* On error return -1 with errno set appropriately to the return code of
- * either lseek, malloc, write or fdatasync. Or errno is EINVAL if @b is null.
+ * either lseek, malloc, write or fdatasync. Or errno is EINVAL if the
+ * arguments are invalid.
*/
__s64 ntfs_pwrite(const int fd, const __s64 pos, __s64 count, const void *b)
@@ -116,5 +119,5 @@
total = retry = 0;
do {
- written = write(fd, ((char *)b) + total, count);
+ written = write(fd, (char *)b + total, count);
if (written == -1)
return written;
@@ -246,5 +249,5 @@
total = retry = 0;
do {
- written = write(fd, ((char *)b) + total, towrite);
+ written = write(fd, (char *)b + total, towrite);
if (written == -1) {
total = -1;
Index: unistr.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/unistr.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -U2 -r1.14 -r1.15
--- unistr.c 28 Apr 2002 21:59:11 -0000 1.14
+++ unistr.c 29 Apr 2002 01:53:55 -0000 1.15
@@ -292,5 +292,4 @@
mbstate_t mbstate;
- Dprintf(__FUNCTION__ "(): MB_CUR_MAX = %i\n", MB_CUR_MAX);
if (!ins || !outs) {
errno = EINVAL;
@@ -364,10 +363,9 @@
* ntfs_mbstoucs - convert a multibyte string to a little endian Unicode string
* @ins: input multibyte string buffer
- * @ins_len: length of input string in bytes
* @outs: on return contains the (allocated) output Unicode string
* @outs_len: length of output buffer in Unicode characters
*
- * Convert the input multibyte string @ins, of length @ins_len from the current
- * locale into the corresponding little endian, 2-byte Unicode string.
+ * Convert the input multibyte string @ins, from the current locale into the
+ * corresponding little endian, 2-byte Unicode string.
*
* If *@outs is NULL, the function allocates the string and the caller is
@@ -386,13 +384,12 @@
* ENOMEM Not enough memory to allocate destination buffer.
*/
-int ntfs_mbstoucs(const char *ins, const int ins_len, uchar_t **outs,
- int outs_len)
+int ntfs_mbstoucs(char *ins, uchar_t **outs, int outs_len)
{
uchar_t *ucs;
+ char *s;
wchar_t wc;
- int i, o, cnt, ucs_len;
+ int i, o, cnt, ins_len, ucs_len;
mbstate_t mbstate;
- Dprintf(__FUNCTION__ "(): MB_CUR_MAX = %i\n", MB_CUR_MAX);
if (!ins || !outs) {
errno = EINVAL;
@@ -405,4 +402,16 @@
return -1;
}
+ /* Determine the length of the multi-byte string. */
+ s = ins;
+ memset(&mbstate, 0, sizeof(mbstate));
+ ins_len = mbsrtowcs(NULL, (const char **)&s, 0, &mbstate);
+ if (ins_len == -1)
+ return ins_len;
+ if ((s != ins) || !mbsinit(&mbstate)) {
+ errno = EILSEQ;
+ return -1;
+ }
+ /* Add the NULL terminator. */
+ ins_len++;
if (!ucs) {
ucs_len = ins_len;
@@ -412,7 +421,7 @@
}
memset(&mbstate, 0, sizeof(mbstate));
- for (i = o = cnt = 0; i < ins_len; i += cnt) {
+ for (i = o = cnt = 0; o < ins_len; i += cnt, o++) {
/* Reallocate memory if necessary or abort. */
- if (o + 1 > ucs_len) {
+ if (o >= ucs_len) {
uchar_t *tc;
if (ucs == *outs) {
@@ -424,12 +433,10 @@
* extra code...
*/
- ucs_len *= sizeof(uchar_t);
- tc = (uchar_t*)malloc((ucs_len + 64) & ~63);
+ ucs_len = (ucs_len * sizeof(uchar_t) + 64) & ~63;
+ tc = (uchar_t*)realloc(ucs, ucs_len);
if (!tc)
goto err_out;
- memcpy(tc, ucs, ucs_len);
- ucs_len = ((ucs_len + 64) & ~63) / sizeof(uchar_t);
- free(ucs);
ucs = tc;
+ ucs_len /= sizeof(uchar_t);
}
/* Convert the multibyte character to a wide character. */
@@ -440,5 +447,5 @@
goto err_out;
if (cnt < -1) {
- Dprintf("Eeek. cnt = %i\n", cnt);
+ Dprintf(__FUNCTION__ "(): Eeek. cnt = %i\n", cnt);
errno = EINVAL;
goto err_out;
@@ -451,14 +458,14 @@
}
/* Convert the CPU wide character to a LE Unicode character. */
- ucs[o++] = cpu_to_le16(wc);
+ ucs[o] = cpu_to_le16(wc);
}
/* Make sure we are back in the initial state. */
if (!mbsinit(&mbstate)) {
- Dputs("Eeek. mbstate not in initial state!");
+ Dputs(__FUNCTION__ "(): Eeek. mbstate not in initial state!");
errno = EILSEQ;
goto err_out;
}
/* Now write the NULL character. */
- ucs[o] = cpu_to_le16((wchar_t)'\0');
+ ucs[o] = cpu_to_le16(L'\0');
if (*outs != ucs)
*outs = ucs;
Index: volume.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/volume.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -U2 -r1.39 -r1.40
--- volume.c 27 Apr 2002 19:49:09 -0000 1.39
+++ volume.c 29 Apr 2002 01:53:55 -0000 1.40
@@ -597,16 +597,15 @@
* @vol: address of ntfs_volume structure of volume to close
* @force: if true force close the volume even if it is busy
- *
+ *
* Deallocate all structures (including @vol itself) associated with the ntfs
* volume @vol.
*
- * Return true on success. On error return false with errno set appropriately
+ * Return 0 on success. On error return -1 with errno set appropriately
* (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that
* an operation is in progress and if you try the close later the operation
* might be completed and the close succeed.
- *
+ *
* If @force is true (i.e. not zero) this function will close the volume even
- * if this means that data might be lost. In this case the function always
- * returns true.
+ * if this means that data might be lost.
*
* @vol must have previously been returned by a call to ntfs_mount().
@@ -615,16 +614,13 @@
* function returns success. If it returns an error then nothing has been done
* so it is safe to continue using @vol.
- *
- * FIXME: Should document all error codes that can be returned and what each
- * means.
*/
-BOOL ntfs_umount(ntfs_volume *vol, const int force)
+int ntfs_umount(ntfs_volume *vol, const BOOL force)
{
if (!vol) {
errno = EINVAL;
- return FALSE;
+ return -1;
}
__release_ntfs_volume(vol);
- return TRUE;
+ return 0;
}
|