Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv24579/libntfs
Modified Files:
attrib.c mft.c volume.c
Log Message:
Update library, new APIs ntfs_attr_find_vcn(), misc fixes and cleanups, make all the utilities compile, fix bugs I noticed in ntfslabel and it now works properly.
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -U2 -r1.35 -r1.36
--- attrib.c 24 Apr 2002 23:47:42 -0000 1.35
+++ attrib.c 27 Apr 2002 19:49:09 -0000 1.36
@@ -1477,4 +1477,80 @@
}
+/**
+ * ntfs_attr_find_vcn - find a vcn in the run list of an ntfs attribute
+ * @na: ntfs attribute whose run list to search
+ * @vcn: vcn to find
+ *
+ * Find the virtual cluster number @vcn in the run list of the ntfs attribute
+ * @na and return the the address of the run list element containing the @vcn.
+ *
+ * Note you need to distinguish between the lcn of the returned run list
+ * element being >= 0 and LCN_HOLE. In the later case you have to return zeroes
+ * on read and allocate clusters on write. You need to update the run list, the
+ * attribute itself as well as write the modified mft record to disk.
+ *
+ * If there is an error return NULL with errno set to the error code. The
+ * following error codes are defined:
+ * EINVAL Input parameter error.
+ * ENOENT There is no such vcn in the run list.
+ * ENOMEM Not enough memory.
+ * EIO I/O error or corrupt metadata.
+ */
+run_list_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn)
+{
+ run_list_element *rl;
+ BOOL is_retry = FALSE;
+
+ if (!na || !NAttrNonResident(na) || vcn < 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+retry:
+ rl = na->rl;
+ if (!rl)
+ goto map_rl;
+ if (vcn < rl[0].vcn) {
+ errno = ENOENT;
+ return NULL;
+ }
+ while (rl->length) {
+ if (vcn < rl[1].vcn) {
+ if (rl->lcn >= (LCN)LCN_HOLE)
+ return rl;
+ break;
+ }
+ rl++;
+ }
+ switch (rl->lcn) {
+ case (LCN)LCN_RL_NOT_MAPPED:
+ goto map_rl;
+ case (LCN)LCN_ENOENT:
+ errno = ENOENT;
+ break;
+ case (LCN)LCN_EINVAL:
+ errno = EINVAL;
+ break;
+ default:
+ errno = EIO;
+ break;
+ }
+ return NULL;
+map_rl:
+ /* The @vcn is in an unmapped region, map the run list and retry. */
+ if (!is_retry && !ntfs_attr_map_run_list(na, vcn)) {
+ is_retry = TRUE;
+ goto retry;
+ }
+ /*
+ * If we already retried or the mapping attempt failed something has
+ * gone badly wrong. EINVAL and ENOENT coming from a failed mapping
+ * attempt are equivalent to errors for us as they should not happen
+ * in our code paths.
+ */
+ if (is_retry || errno == EINVAL || errno == ENOENT)
+ errno = EIO;
+ return NULL;
+}
+
/*
* Internal function:
Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/mft.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -U2 -r1.24 -r1.25
--- mft.c 24 Apr 2002 23:47:42 -0000 1.24
+++ mft.c 27 Apr 2002 19:49:09 -0000 1.25
@@ -55,5 +55,5 @@
VCN m;
- if (!vol || !b) {
+ if (!vol || !b || count < 0) {
errno = EINVAL;
return -1;
@@ -118,5 +118,5 @@
VCN m;
- if (!vol || !b) {
+ if (!vol || !b || count < 0) {
errno = EINVAL;
return -1;
@@ -194,5 +194,5 @@
MFT_RECORD *m;
ATTR_RECORD *a;
- int er = 0;
+ int err;
if (!vol || !mrec) {
@@ -203,8 +203,6 @@
if (!m)
return -1;
- er = ntfs_read_mft_record(vol, mref, m);
- if (er) {
- if (er != -1)
- errno = EIO;
+ if (ntfs_read_mft_record(vol, mref, m)) {
+ err = errno;
goto read_failed;
}
@@ -224,7 +222,8 @@
file_corrupt:
Dputs("read_file_record(): file is corrupt.");
- errno = EIO;
+ err = EIO;
read_failed:
free(m);
+ errno = err;
return -1;
}
Index: volume.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/volume.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -U2 -r1.38 -r1.39
--- volume.c 25 Apr 2002 08:22:14 -0000 1.38
+++ volume.c 27 Apr 2002 19:49:09 -0000 1.39
@@ -37,4 +37,10 @@
#include "debug.h"
+/*
+ * Internal function:
+ *
+ * __allocate_ntfs_volume -
+ *
+ */
static ntfs_volume *__allocate_ntfs_volume(void)
{
@@ -42,4 +48,10 @@
}
+/*
+ * Internal function:
+ *
+ * __release_ntfs_volume -
+ *
+ */
static void __release_ntfs_volume(ntfs_volume *v)
{
@@ -56,4 +68,6 @@
if (v->mft_rl)
free(v->mft_rl);
+ if (v->mftmirr_rl)
+ free(v->mftmirr_rl);
if (v->upcase)
free(v->upcase);
@@ -220,4 +234,23 @@
Dprintf("MftRecordSize = 0x%x\n", vol->mft_record_size);
Dprintf("MftRecordSizeBits = %u\n", vol->mft_record_size_bits);
+ /*
+ * Work out the size of the MFT mirror in number of mft records. If the
+ * cluster size is less than or equal to the size taken by four mft
+ * records, the mft mirror stores the first four mft records. If the
+ * cluster size is bigger than the size taken by four mft records, the
+ * mft mirror contains as many mft records as will fit into one
+ * cluster.
+ */
+ if (vol->cluster_size <= 4 * vol->mft_record_size)
+ vol->mftmirr_size = 4;
+ else
+ vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;
+ vol->mftmirr_rl = malloc(2 * sizeof(run_list_element));
+ vol->mftmirr_rl[0].vcn = vol->mftmirr_rl[1].length = 0;
+ vol->mftmirr_rl[0].lcn = vol->mftmirr_lcn;
+ vol->mftmirr_rl[1].vcn = vol->mftmirr_rl[0].length = (vol->mftmirr_size
+ * vol->mft_record_size + vol->cluster_size - 1) /
+ vol->cluster_size;
+ vol->mftmirr_rl[1].lcn = LCN_ENOENT;
/* Start with $Mft. */
Dprintf("Loading $Mft... ");
@@ -234,6 +267,4 @@
if (br == -1)
Dperror("Error reading $Mft");
- else if (br < 4)
- Dputs("Error: $Mft is outside of the partition?!?");
else
Dputs("Error reading $Mft.");
|