Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv12122/libntfs
Modified Files:
attrib.c disk_io.c mft.c
Log Message:
read/write_mft_record(s) are here
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -U2 -r1.19 -r1.20
--- attrib.c 15 Apr 2002 00:42:07 -0000 1.19
+++ attrib.c 15 Apr 2002 17:51:26 -0000 1.20
@@ -681,26 +681,58 @@
}
-LCN vcn_to_lcn(const run_list *rl, const VCN vcn)
+/* Already cleaned up code below, but still look for FIXME:... */
+
+/**
+ * vcn_to_lcn - convert a vcn into a lcn given a run list
+ * @rl: run list to use for conversion
+ * @vcn: vcn to convert
+ *
+ * Convert the virtual cluster number @vcn of an attribute into a logical
+ * cluster number (lcn) of a device using the run list @rl to map vcns to their
+ * corresponding lcns.
+ *
+ * Since lcns must be >= 0, we use negative return values with special meaning:
+ *
+ * Return value Meaning / Description
+ * ==================================================
+ * -1 = LCN_HOLE Hole / not allocated on disk.
+ * -2 = LCN_RL_NOT_MAPPED This is part of the run list which has not been
+ * inserted into the run list yet.
+ * -3 = LCN_ENOENT There is no such vcn in the attribute.
+ * -4 = LCN_EINVAL Input parameter error.
+ */
+LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
{
- int i = 0;
-
- if (!rl || vcn < 0) {
- errno = EINVAL;
- return 0;
- }
- if (!rl[0].length || vcn < rl[0].vcn) {
- errno = ENOENT;
- return 0;
- }
- do {
+ int i;
+
+ if (vcn < (VCN)0)
+ return (LCN)LCN_EINVAL;
+ /*
+ * If rl is NULL, assume that we have found an unmapped run list. The
+ * caller can then attempt to map it and fail appropriately if
+ * necessary.
+ */
+ if (!rl)
+ return (LCN)LCN_RL_NOT_MAPPED;
+
+ /* Catch out of lower bounds vcn. */
+ if (vcn < rl[0].vcn)
+ return (LCN)LCN_ENOENT;
+
+ for (i = 0; rl[i].length; i++) {
if (vcn < rl[i+1].vcn) {
- if (rl[i].lcn == (LCN)-1)
- return (LCN)-1;
- errno = 0;
- return rl[i].lcn + (vcn - rl[i].vcn);
+ if (rl[i].lcn >= (LCN)0)
+ return rl[i].lcn + (vcn - rl[i].vcn);
+ return rl[i].lcn;
}
- } while (rl[++i].length);
- errno = ENOENT;
- return 0;
+ }
+ /*
+ * The terminator element is setup to the correct value, i.e. one of
+ * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT.
+ */
+ if (rl[i].lcn < (LCN)0)
+ return rl[i].lcn;
+ /* Just in case... We could replace this with BUG() some day. */
+ return (LCN)LCN_ENOENT;
}
@@ -749,5 +781,5 @@
} /* Attribute list. */
if (ctx->ntfs_ino != ctx->base_ntfs_ino)
- fprintf(stderr, __FUNCTION__ "(): EEEEEK!\n");
+ fprintf(stderr, __FUNCTION__ "(): FIXME: EEEEEK!\n");
// unmap_mft_record(READ, ctx->ntfs_ino);
init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
@@ -782,5 +814,5 @@
{
if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)
- fprintf(stderr, __FUNCTION__ "(): EEEEEK!\n");
+ fprintf(stderr, __FUNCTION__ "(): FIXME: EEEEEK!\n");
//unmap_mft_record(READ, ctx->ntfs_ino);
free(ctx);
Index: disk_io.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/disk_io.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -U2 -r1.17 -r1.18
--- disk_io.c 15 Apr 2002 00:42:07 -0000 1.17
+++ disk_io.c 15 Apr 2002 17:51:26 -0000 1.18
@@ -48,5 +48,5 @@
* case the data pointer @b was NULL.
*/
-__s64 ntfs_pread(const int fd, const __s64 pos, __s64 count, void *b)
+__s64 ntfs_pread(const int fd, const __s64 pos, __s64 count, const void *b)
{
__s64 br, total;
@@ -95,5 +95,5 @@
* either lseek, malloc, write or fdatasync. Or errno is EINVAL if @b is null.
*/
-__s64 ntfs_pwrite(int fd, const __s64 pos, __s64 count, const void *b)
+__s64 ntfs_pwrite(const int fd, const __s64 pos, __s64 count, const void *b)
{
__s64 written, total;
@@ -158,5 +158,5 @@
*/
__s64 ntfs_mst_pread(const int fd, const __s64 pos, __s64 count,
- const __u32 bksize, void *b)
+ const __u32 bksize, const void *b)
{
__s64 br, i;
@@ -208,5 +208,5 @@
* achieved.
*/
-__s64 ntfs_mst_pwrite(int fd, const __s64 pos, const __s64 count,
+__s64 ntfs_mst_pwrite(const int fd, const __s64 pos, const __s64 count,
const __u32 bksize, const void *b)
{
@@ -274,5 +274,5 @@
*/
__s64 ntfs_read_clusters(const ntfs_volume *vol, const __s64 lcn, __s64 count,
- void *b)
+ const void *b)
{
__s64 br;
@@ -315,5 +315,5 @@
* error, with errno set to the error code.
*/
-__s64 ntfs_write_clusters(ntfs_volume *vol, const __s64 lcn, __s64 count,
+__s64 ntfs_write_clusters(const ntfs_volume *vol, const __s64 lcn, __s64 count,
const void *b)
{
Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/mft.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -U2 -r1.14 -r1.15
--- mft.c 15 Apr 2002 00:42:07 -0000 1.14
+++ mft.c 15 Apr 2002 17:51:26 -0000 1.15
@@ -24,22 +24,26 @@
#include "mft.h"
#include "disk_io.h"
+#include "debug.h"
#include "bitmap.h"
/**
- * get_mft_records - read records from the mft from disk
+ * ntfs_read_mft_records - read records from the mft from disk
* @vol: volume to read from
- * @mrec: output data buffer
- * @mref: starting mft record number
+ * @mref: starting mft record number to read
* @count: number of mft records to read
+ * @b: output data buffer
*
* Read @count mft records starting at @mref from volume @vol into buffer
- * @mrec. Return @count on success or -ERRNO on error, where ERRNO is the error
- * code. This function will do the error reporting so caller really only needs
- * to check for sucess / failure.
+ * @b. Return @count on success or -1 on error, with errno set to the error
+ * code.
*
- * NOTE: @mrec has to be at least of size @count * vol->mft_record_size.
+ * The read mft records are mst deprotected and are hence ready to use. The
+ * caller should check each record with is_baad_recordp() in case mst
+ * deprotection failed.
+ *
+ * NOTE: @b has to be at least of size @count * vol->mft_record_size.
*/
-int get_mft_records(const ntfs_volume *vol, const MFT_RECORD *mrec,
- const MFT_REF *mref, const int count)
+__s64 read_mft_records(const ntfs_volume *vol, const MFT_REF mref,
+ const __s64 count, const MFT_RECORD *b)
{
__s64 br, ofs;
@@ -47,35 +51,35 @@
VCN m;
- if (!vol || !mrec)
+ if (!vol || !b)
return -EINVAL;
if (!vol->fd)
return -EBADF;
- m = MREF(*mref);
+ m = MREF(mref);
if (vol->number_of_mft_records < m + count)
return -ESPIPE;
- if (!ntfs_get_bit(vol->mft_bitmap, m))
- return -ENOENT;
+ /* Starting cluster of the first mft record to read. */
lcn = vcn_to_lcn(vol->mft_runlist, m << vol->mft_record_size_bits >>
- vol->cluster_size_bits);
- if (lcn == -1) {
- perror("Error sparse $Mft records are not supported");
- return -ENOTSUP;
+ vol->cluster_size_bits);
+ /*
+ * We always keep the COMPLETE run list for $MFT/$DATA in
+ * vol->mft_runlist.
+ */
+ if (lcn < 0) {
+ Dprintf(__FUNCTION__ "(): BUG! vcn_to_lcn() on $MFT/$DATA "
+ "returned %Li.\n", lcn);
+ return lcn;
}
+ /* Offset within the cluster of the first mft record to read. */
ofs = m << vol->mft_record_size_bits & vol->cluster_size - 1;
- br = mst_pread(vol->fd, (__u8*)mrec, vol->mft_record_size, count,
- (lcn << vol->cluster_size_bits) + ofs);
+ br = ntfs_mst_pread(vol->fd, (lcn << vol->cluster_size_bits) + ofs,
+ count, vol->mft_record_size, b);
if (br != count) {
- int eo = errno;
-#define ESTR "Error reading $Mft record"
- if (br == -1) {
- perror(ESTR);
- return -eo;
- } else if (!br)
- fprintf(stderr, "Error: partition is smaller than "
- "it should be!?! Weird!\n");
+ if (br != -1)
+ errno = EIO;
+ if (!br)
+ Dputs("Error: partition is smaller than it should be!");
else
- fprintf(stderr, ESTR ": unknown error\n");
-#undef ESTR
- return -EIO;
+ Dperror("Error reading $Mft record(s)");
+ return -1;
}
return br;
@@ -83,23 +87,62 @@
/**
- * get_mft_record - read a record from the mft
- * @vol: volume to read from
- * @mrec: output data buffer
- * @mref: starting mft record number
- * @count: number of mft records to read
- *
- * Read mft record specified by @mref from volume @vol into buffer @mrec.
- * Return 1 on success or -ERRNO on error, where ERRNO is the error
- * code. This function will do the error reporting so caller really only needs
- * to check for sucess / failure.
- *
- * NOTE: @mrec has to be at least of size vol->mft_record_size.
+ * write_mft_records - write mft records to disk
+ * @vol: volume to write to
+ * @mref: starting mft record number to write
+ * @count: number of mft records to write
+ * @b: data buffer containing the mft records to write
+ *
+ * Write mft records starting with @mref from buffer @b to volume @vol. Return
+ * @count on success or -1 on error, with errno set to the error code.
+ *
+ * Before the mft records are written, they are mst protected. After the write,
+ * they are deprotected again, thus resulting in an increase in the update
+ * sequence number inside the buffer @b.
*/
-__inline__ int get_mft_record(const ntfs_volume *vol, const MFT_RECORD *mrec,
- const MFT_REF *mref)
+__s64 write_mft_records(const ntfs_volume *vol, const MFT_REF mref,
+ const __s64 count, const MFT_RECORD *b)
{
- return get_mft_records(vol, mrec, mref, 1);
+ __s64 bw, ofs;
+ LCN lcn;
+ VCN m;
+
+ if (!vol || !b)
+ return -EINVAL;
+ if (!vol->fd)
+ return -EBADF;
+ m = MREF(mref);
+ if (vol->number_of_mft_records < m + count)
+ return -ESPIPE;
+ /* Starting cluster of the first mft record to write. */
+ lcn = vcn_to_lcn(vol->mft_runlist, m << vol->mft_record_size_bits >>
+ vol->cluster_size_bits);
+ /*
+ * We always keep the COMPLETE run list for $MFT/$DATA in
+ * vol->mft_runlist.
+ */
+ if (lcn < 0) {
+ Dprintf(__FUNCTION__ "(): BUG! vcn_to_lcn() on $MFT/$DATA "
+ "returned %Li.\n", lcn);
+ return lcn;
+ }
+ /* Offset within the cluster of the first mft record to write. */
+ ofs = m << vol->mft_record_size_bits & vol->cluster_size - 1;
+ bw = ntfs_mst_pwrite(vol->fd, (lcn << vol->cluster_size_bits) + ofs,
+ count, vol->mft_record_size, b);
+ if (bw != count) {
+ if (bw != -1)
+ errno = EIO;
+ if (!bw)
+ Dputs("Error: ran out of input data writing $Mft "
+ "record(s)!\n");
+ else
+ Dperror("Error writing $Mft record(s)");
+ return -1;
+ }
+ return bw;
}
+/* FIXME: Old stuff below here. */
+
/**
* __read_file_record - read a FILE record from the mft from disk
@@ -191,59 +234,4 @@
{
return -ENOTSUP;
-}
-
-/**
- * put_mft_record - write a record to the mft
- * @vol: volume to write to
- * @buf: data buffer containing the mft record to write
- * @mref: mft record number to write to
- *
- * Write mft record @mref from buffer @buf to volume @vol. Return 1 on
- * success or -ERRNO on error, where ERRNO is the error code. This function
- * will do the error reporting so caller really only needs to check for sucess
- * / failure.
- */
-int put_mft_record(ntfs_volume *vol, const __u8 *buf, const MFT_REF *mref)
-{
- __s64 bw, m;
- __s64 lcn, ofs;
-
- if (!vol || !buf)
- return -EINVAL;
- if (!vol->fd)
- return -EBADF;
- m = MREF(*mref);
- if (vol->number_of_mft_records <= m)
- return -ESPIPE;
- if (!ntfs_get_bit(vol->mft_bitmap, m))
- return -ENOENT;
- lcn = vcn_to_lcn(vol->mft_runlist, m << vol->mft_record_size_bits >>
- vol->cluster_size_bits);
- if (lcn == -1) {
- perror("Error sparse $Mft records are not supported");
- return -ENOTSUP;
- }
- ofs = m << vol->mft_record_size_bits & vol->cluster_size - 1;
- if (lcn == -1) {
- int eo = errno;
- perror("Error determining on disk location of $Mft record");
- return -eo;
- }
- bw = mst_pwrite(vol->fd, buf, vol->mft_record_size,
- (lcn << vol->cluster_size_bits) + ofs);
- if (bw != vol->mft_record_size) {
- int eo = errno;
-#define ESTR "Error writing $Mft record"
- if (bw == -1) {
- perror(ESTR);
- return -eo;
- } else if (!bw)
- fprintf(stderr, ESTR ": Ran out of input data!\n");
- else
- fprintf(stderr, ESTR ": unknown error\n");
-#undef ESTR
- return -EIO;
- }
- return 1;
}
|