Changes by: antona
Update of /cvsroot/linux-ntfs/ntfsprogs/libntfs
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27122/libntfs
Modified Files:
Makefile.am attrib.c unistr.c volume.c
Log Message:
Megapatch!!! Check evecrything!!! I probably broke everything!!!
Index: Makefile.am
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/Makefile.am,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -p -r1.30 -r1.31
--- Makefile.am 22 Sep 2005 16:41:43 -0000 1.30
+++ Makefile.am 24 Sep 2005 22:54:55 -0000 1.31
@@ -25,7 +25,7 @@
# - If the interface is the same as the previous version, change to C:R+1:A
#
-LTVERSION_LIBNTFS = 7:1:0
+LTVERSION_LIBNTFS = 8:0:0
LTVERSION_LIBNTFS_GNOMEVFS = 1:0:0
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/attrib.c,v
retrieving revision 1.176
retrieving revision 1.177
diff -u -p -r1.176 -r1.177
--- attrib.c 24 Sep 2005 20:28:23 -0000 1.176
+++ attrib.c 24 Sep 2005 22:54:55 -0000 1.177
@@ -1559,10 +1559,23 @@ static int ntfs_attr_find(const ATTR_TYP
const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
{
ATTR_RECORD *a;
- ntfs_volume *vol = ctx->ntfs_ino->vol;
- ntfschar *upcase = vol->upcase;
- u32 upcase_len = vol->upcase_len;
+ ntfs_volume *vol;
+ ntfschar *upcase;
+ u32 upcase_len;
+ if (ctx->ntfs_ino) {
+ vol = ctx->ntfs_ino->vol;
+ upcase = vol->upcase;
+ upcase_len = vol->upcase_len;
+ } else {
+ if (name) {
+ errno = EINVAL;
+ return -1;
+ }
+ vol = NULL;
+ upcase = NULL;
+ upcase_len = 0;
+ }
/*
* Iterate over attributes in mft record starting at @ctx->attr, or the
* attribute following that, if @ctx->is_first is TRUE.
@@ -2196,7 +2209,7 @@ int ntfs_attr_lookup(const ATTR_TYPES ty
static __inline__ void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
ntfs_inode *ni, MFT_RECORD *mrec)
{
- if (ni && !mrec)
+ if (!mrec)
mrec = ni->mrec;
ctx->mrec = mrec;
/* Sanity checks are performed elsewhere. */
@@ -2245,19 +2258,22 @@ void ntfs_attr_reinit_search_ctx(ntfs_at
* Allocate a new attribute search context, initialize it with @ni and @mrec,
* and return it. Return NULL on error with errno set to ENOMEM.
*
- * @ni can be NULL if the search context is only going to be used for searching
- * for the attribute list attribute and for searches ignoring the contents of
- * the attribute list attribute.
+ * @mrec can be NULL, in which case the mft record is taken from @ni.
*
- * If @ni is specified, @mrec can be NULL, in which case the mft record is
- * taken from @ni.
- *
- * If both @ni and @mrec are specified, the mft record is taken from @mrec and
- * the value of @ni->mrec is ignored.
+ * Note: For low level utilities which know what they are doing we allow @ni to
+ * be NULL and @mrec to be set. Do NOT do this unless you understand the
+ * implications!!! For example it is no longer safe to call ntfs_attr_lookup()
+ * if you
*/
ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
{
- ntfs_attr_search_ctx *ctx = malloc(sizeof(ntfs_attr_search_ctx));
+ ntfs_attr_search_ctx *ctx;
+
+ if (!ni && !mrec) {
+ errno = EINVAL;
+ return NULL;
+ }
+ ctx = malloc(sizeof(ntfs_attr_search_ctx));
if (ctx)
ntfs_attr_init_search_ctx(ctx, ni, mrec);
return ctx;
@@ -2530,7 +2546,7 @@ int ntfs_resident_attr_record_add(ntfs_i
}
/* Locate place where record should be. */
- ctx = ntfs_attr_get_search_ctx(NULL, ni->mrec);
+ ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx)
return -1;
if (!ntfs_attr_lookup(type, name, name_len,
@@ -2655,7 +2671,7 @@ int ntfs_non_resident_attr_record_add(nt
}
/* Locate place where record should be. */
- ctx = ntfs_attr_get_search_ctx(NULL, ni->mrec);
+ ctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!ctx)
return -1;
if (!ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE,
@@ -3318,7 +3334,7 @@ int ntfs_attr_record_move_to(ntfs_attr_s
/* Find place in MFT record where attribute will be moved. */
a = ctx->attr;
- nctx = ntfs_attr_get_search_ctx(NULL, ni->mrec);
+ nctx = ntfs_attr_get_search_ctx(ni, NULL);
if (!nctx) {
err = errno;
Dprintf("%s(): Couldn't obtain search context.\n",
Index: unistr.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/unistr.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -p -r1.27 -r1.28
--- unistr.c 24 Sep 2005 20:28:23 -0000 1.27
+++ unistr.c 24 Sep 2005 22:54:55 -0000 1.28
@@ -591,3 +591,69 @@ err_out:
}
return -1;
}
+
+/**
+ * ntfs_upcase_table_build - build the default upcase table for NTFS
+ * @uc: destination buffer where to store the built table
+ * @uc_len: size of destination buffer in bytes
+ *
+ * ntfs_upcase_table_build() builds the default upcase table for NTFS and
+ * stores it in the caller supplied buffer @uc of size @uc_len.
+ *
+ * Note, @uc_len must be at least 128kiB in size or bad things will happen!
+ */
+void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
+{
+ static int uc_run_table[][3] = { /* Start, End, Add */
+ {0x0061, 0x007B, -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72, 74},
+ {0x00E0, 0x00F7, -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76, 86},
+ {0x00F8, 0x00FF, -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100},
+ {0x0256, 0x0258, -205}, {0x1F00, 0x1F08, 8}, {0x1F78, 0x1F7A, 128},
+ {0x028A, 0x028C, -217}, {0x1F10, 0x1F16, 8}, {0x1F7A, 0x1F7C, 112},
+ {0x03AC, 0x03AD, -38}, {0x1F20, 0x1F28, 8}, {0x1F7C, 0x1F7E, 126},
+ {0x03AD, 0x03B0, -37}, {0x1F30, 0x1F38, 8}, {0x1FB0, 0x1FB2, 8},
+ {0x03B1, 0x03C2, -32}, {0x1F40, 0x1F46, 8}, {0x1FD0, 0x1FD2, 8},
+ {0x03C2, 0x03C3, -31}, {0x1F51, 0x1F52, 8}, {0x1FE0, 0x1FE2, 8},
+ {0x03C3, 0x03CC, -32}, {0x1F53, 0x1F54, 8}, {0x1FE5, 0x1FE6, 7},
+ {0x03CC, 0x03CD, -64}, {0x1F55, 0x1F56, 8}, {0x2170, 0x2180, -16},
+ {0x03CD, 0x03CF, -63}, {0x1F57, 0x1F58, 8}, {0x24D0, 0x24EA, -26},
+ {0x0430, 0x0450, -32}, {0x1F60, 0x1F68, 8}, {0xFF41, 0xFF5B, -32},
+ {0}
+ };
+ static int uc_dup_table[][2] = { /* Start, End */
+ {0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC},
+ {0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB},
+ {0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5},
+ {0x014A, 0x0178}, {0x01DE, 0x01EF}, {0x04BF, 0x04BF}, {0x04F8, 0x04F9},
+ {0x0179, 0x017E}, {0x01F4, 0x01F5}, {0x04C1, 0x04C4}, {0x1E00, 0x1E95},
+ {0x018B, 0x018B}, {0x01FA, 0x0218}, {0x04C7, 0x04C8}, {0x1EA0, 0x1EF9},
+ {0}
+ };
+ static int uc_byte_table[][2] = { /* Offset, Value */
+ {0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196},
+ {0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C},
+ {0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D},
+ {0x0188, 0x0187}, {0x01BD, 0x01BC}, {0x0259, 0x018F}, {0x0275, 0x019F},
+ {0x018C, 0x018B}, {0x01C6, 0x01C4}, {0x025B, 0x0190}, {0x0283, 0x01A9},
+ {0x0192, 0x0191}, {0x01C9, 0x01C7}, {0x0260, 0x0193}, {0x0288, 0x01AE},
+ {0x0199, 0x0198}, {0x01CC, 0x01CA}, {0x0263, 0x0194}, {0x0292, 0x01B7},
+ {0x01A8, 0x01A7}, {0x01DD, 0x018E}, {0x0268, 0x0197},
+ {0}
+ };
+ int i, r;
+
+ memset((char*)uc, 0, uc_len);
+ uc_len >>= 1;
+ if (uc_len > 65536)
+ uc_len = 65536;
+ for (i = 0; (u32)i < uc_len; i++)
+ uc[i] = i;
+ for (r = 0; uc_run_table[r][0]; r++)
+ for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++)
+ uc[i] += uc_run_table[r][2];
+ for (r = 0; uc_dup_table[r][0]; r++)
+ for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2)
+ uc[i + 1]--;
+ for (r = 0; uc_byte_table[r][0]; r++)
+ uc[uc_byte_table[r][0]] = uc_byte_table[r][1];
+}
Index: volume.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfsprogs/libntfs/volume.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -p -r1.51 -r1.52
--- volume.c 24 Sep 2005 15:59:53 -0000 1.51
+++ volume.c 24 Sep 2005 22:54:55 -0000 1.52
@@ -79,6 +79,8 @@ ntfs_volume *ntfs_volume_alloc(void)
*/
static void __ntfs_volume_release(ntfs_volume *v)
{
+ if (v->vol_ni && NInoDirty(v->vol_ni))
+ ntfs_inode_close(v->vol_ni);
if (v->lcnbmp_ni && NInoDirty(v->lcnbmp_ni))
ntfs_inode_sync(v->lcnbmp_ni);
if (v->lcnbmp_na)
@@ -166,7 +168,7 @@ static int ntfs_mft_load(ntfs_volume *vo
Dputs("Error: $MFT has invalid magic.");
goto io_error_exit;
}
- ctx = ntfs_attr_get_search_ctx(vol->mft_ni, mb);
+ ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
if (!ctx) {
Dperror("Failed to allocate attribute search context");
goto error_exit;
@@ -416,6 +418,15 @@ ntfs_volume *ntfs_volume_startup(struct
vol = ntfs_volume_alloc();
if (!vol)
goto error_exit;
+ /* Create the default upcase table. */
+ vol->upcase_len = 65536;
+ vol->upcase = (ntfschar*)malloc(vol->upcase_len * sizeof(ntfschar));
+ if (!vol->upcase) {
+ Dperror("Error allocating memory for upcase table.");
+ goto error_exit;
+ }
+ ntfs_upcase_table_build(vol->upcase,
+ vol->upcase_len * sizeof(ntfschar));
if ((rwflag & MS_RDONLY) == MS_RDONLY)
NVolSetReadOnly(vol);
Dprintf("Reading bootsector... ");
@@ -889,12 +900,16 @@ ntfs_volume *ntfs_device_mount(struct nt
errno = EINVAL;
goto error_exit;
}
- vol->upcase_len = na->data_size >> 1;
- vol->upcase = (ntfschar*)malloc(na->data_size);
- if (!vol->upcase) {
- Dputs(FAILED);
- Dputs("Not enough memory to load $UpCase.");
- goto error_exit;
+ if (vol->upcase_len != na->data_size >> 1) {
+ vol->upcase_len = na->data_size >> 1;
+ /* Throw away default table. */
+ free(vol->upcase);
+ vol->upcase = (ntfschar*)malloc(na->data_size);
+ if (!vol->upcase) {
+ Dputs(FAILED);
+ Dputs("Not enough memory to load $UpCase.");
+ goto error_exit;
+ }
}
/* Read in the $DATA attribute value into the buffer. */
l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase);
@@ -916,14 +931,14 @@ ntfs_volume *ntfs_device_mount(struct nt
* vol structure accordingly.
*/
Dprintf("Loading $Volume... ");
- ni = ntfs_inode_open(vol, FILE_Volume);
- if (!ni) {
+ vol->vol_ni = ntfs_inode_open(vol, FILE_Volume);
+ if (!vol->vol_ni) {
Dputs(FAILED);
Dperror("Failed to open inode");
goto error_exit;
}
/* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */
- ctx = ntfs_attr_get_search_ctx(ni, NULL);
+ ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
if (!ctx) {
Dputs(FAILED);
Dperror("Failed to allocate attribute search context");
@@ -1033,9 +1048,6 @@ ntfs_volume *ntfs_device_mount(struct nt
Dputs(OK);
ntfs_attr_put_search_ctx(ctx);
ctx = NULL;
- if (ntfs_inode_close(ni))
- Dperror("Failed to close inode, leaking memory");
-
/* Now load the attribute definitions from $AttrDef. */
Dprintf("Loading $AttrDef... ");
ni = ntfs_inode_open(vol, FILE_AttrDef);
@@ -1080,7 +1092,6 @@ ntfs_volume *ntfs_device_mount(struct nt
ntfs_attr_close(na);
if (ntfs_inode_close(ni))
Dperror("Failed to close inode, leaking memory");
-
/*
* Check for dirty logfile and hibernated Windows.
* We care only about read-write mounts.
@@ -1429,7 +1440,7 @@ error_exit:
}
/**
- * ntfs_volume_set_flags - set the flags of an ntfs volume
+ * ntfs_volume_write_flags - set the flags of an ntfs volume
* @vol: ntfs volume where we set the volume flags
* @flags: new flags
*
@@ -1438,37 +1449,22 @@ error_exit:
*
* Return 0 if successful and -1 if not with errno set to the error code.
*/
-int ntfs_volume_set_flags(ntfs_volume *vol, const u16 flags)
+int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags)
{
- MFT_RECORD *m = NULL;
- ATTR_RECORD *r;
+ ATTR_RECORD *a;
VOLUME_INFORMATION *c;
ntfs_attr_search_ctx *ctx;
int ret = -1; /* failure */
- if (!vol) {
+ if (!vol || !vol->vol_ni) {
errno = EINVAL;
return -1;
}
-
- if (ntfs_file_record_read(vol, FILE_Volume, &m, NULL)) {
- Dperror("Failed to read $Volume");
- return -1;
- }
-
- /* Sanity check */
- if (!(m->flags & MFT_RECORD_IN_USE)) {
- Dprintf("Error: $Volume has been deleted. Cannot "
- "handle this yet. Run chkdsk to fix this.\n");
- errno = EIO;
- goto err_exit;
- }
-
/* Get a pointer to the volume information attribute. */
- ctx = ntfs_attr_get_search_ctx(NULL, m);
+ ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
if (!ctx) {
Dperror("Failed to allocate attribute search context");
- goto err_exit;
+ return -1;
}
if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
0, ctx)) {
@@ -1476,40 +1472,36 @@ int ntfs_volume_set_flags(ntfs_volume *v
"$Volume!");
goto err_out;
}
- r = ctx->attr;
+ a = ctx->attr;
/* Sanity check. */
- if (r->non_resident) {
+ if (a->non_resident) {
Dputs("Error: Attribute $VOLUME_INFORMATION must be resident "
"(and it isn't)!");
errno = EIO;
goto err_out;
}
/* Get a pointer to the value of the attribute. */
- c = (VOLUME_INFORMATION*)(le16_to_cpu(r->value_offset) + (char*)r);
+ c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
/* Sanity checks. */
- if ((char*)c + le32_to_cpu(r->value_length) >
- le16_to_cpu(m->bytes_in_use) + (char*)m ||
- le16_to_cpu(r->value_offset) +
- le32_to_cpu(r->value_length) > le32_to_cpu(r->length)) {
+ if ((char*)c + le32_to_cpu(a->value_length) >
+ le16_to_cpu(ctx->mrec->bytes_in_use) +
+ (char*)ctx->mrec || le16_to_cpu(a->value_offset) +
+ le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
Dputs("Error: Attribute $VOLUME_INFORMATION in $Volume is "
"corrupt!");
errno = EIO;
goto err_out;
}
/* Set the volume flags. */
- vol->flags = c->flags = cpu_to_le16(flags);
-
- if (ntfs_mft_record_write(vol, FILE_Volume, m)) {
+ vol->flags = c->flags = flags & VOLUME_FLAGS_MASK;
+ /* Write them to disk. */
+ ntfs_inode_mark_dirty(vol->vol_ni);
+ if (ntfs_inode_sync(vol->vol_ni)) {
Dperror("Error writing $Volume");
goto err_out;
}
-
ret = 0; /* success */
err_out:
ntfs_attr_put_search_ctx(ctx);
-err_exit:
- if (m)
- free(m);
return ret;
}
-
|