On Fri, 2005-09-30 at 15:56 +0300, Yura Pakhuchiy wrote:
> =D0=92 =D0=9F=D1=82=D0=BD, 30/09/2005 =D0=B2 13:30 +0100, Anton Altaparma=
kov =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
> > On Fri, 2005-09-30 at 14:46 +0300, Yura Pakhuchiy wrote:
> > > =D0=92 =D0=9F=D1=82=D0=BD, 30/09/2005 =D0=B2 11:02 +0100, Anton Altap=
armakov =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
> > > > > --- attrib.c 28 Sep 2005 13:47:47 -0000 1.178
> > > > > +++ attrib.c 30 Sep 2005 09:52:05 -0000 1.179
> > > > > @@ -2554,7 +2554,7 @@ int ntfs_resident_attr_record_add(ntfs_i
> > > > > }
> > > > > =20
> > > > > /* Locate place where record should be. */
> > > > > - ctx =3D ntfs_attr_get_search_ctx(ni, NULL);
> > > > > + ctx =3D ntfs_attr_get_search_ctx(NULL, ni->mrec);
> > > > > if (!ctx)
> > > > > return -1;
> > > > > if (!ntfs_attr_lookup(type, name, name_len,
> > > > > @@ -2679,7 +2679,7 @@ int ntfs_non_resident_attr_record_add(nt
> > > > > }
> > > > > =20
> > > > > /* Locate place where record should be. */
> > > > > - ctx =3D ntfs_attr_get_search_ctx(ni, NULL);
> > > > > + ctx =3D ntfs_attr_get_search_ctx(NULL, ni->mrec);
> > > > > if (!ctx)
> > > > > return -1;
> > > > > if (!ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE,
> > > > > @@ -3342,7 +3342,7 @@ int ntfs_attr_record_move_to(ntfs_attr_s
> > > > > =20
> > > > > /* Find place in MFT record where attribute will be moved. */
> > > > > a =3D ctx->attr;
> > > > > - nctx =3D ntfs_attr_get_search_ctx(ni, NULL);
> > > > > + nctx =3D ntfs_attr_get_search_ctx(NULL, ni->mrec);
> > > > > if (!nctx) {
> > > > > err =3D errno;
> > > > > Dprintf("%s(): Couldn't obtain search context.\n",
> > > >=20
> > > > The above three will now always fail when name !=3D NULL in the cal=
l to
> > > > ntfs_attr_lookup(). You must use ntfs_attr_find() instead.
> > >=20
> > > Why you add such check? What problems can happen in case sensitive
> > > lookup?
> >=20
> > You _cannot_ perform case insensitive lookup without an upcase table by
> > definition of what case insensitive means. attr_find/lookup _have_ to
> > do case insensitive comparison of the name. They cannot do this if no
> > upcase table is present.
> >=20
> > As I said in earlier message the correct fix would be to add either the
> > volume or the upcase table + length to somewhere, either the search
> > context itself so there would be "ntfs_inode_get_search_ctx(ntfs_inode
> > *ni)" and "ntfs_mft_get_search_ctx(ntfs_volume *vol, MFT_RECORD *mrec)"=
.
> > Or alternatively modify ntfs_attr_find() to also take the upcase table
> > (or the volume I suppose but that will cause problems with places that
> > do not have a volume) and then you can pass it in when you have acquire=
d
> > the context with (NULL, mrec)...
> >=20
> > Basically ntfs_attr_find() MUST AT ALL TIMES have access to upcase tabl=
e
> > if a name is provided for the comparisons. At present if you get a
> > search context with (NULL, mrec) you do NOT have an upcase table in
> > _lookup/find so they cannot execute correctly.
> >=20
> > Just read ntfs_attr_find():
> >=20
> > if (name =3D=3D AT_UNNAMED) {
> > /* The search failed if the found attribute is named. */
> > if (a->name_length) {
> > errno =3D ENOENT;
> > return -1;
> > }
> > } else if (name && !ntfs_names_are_equal(name, name_len,
> > (ntfschar*)((char*)a + le16_to_cpu(a->name_offset)),
> > a->name_length, ic, upcase, upcase_len)) {
> > register int rc;
> >=20
> > rc =3D ntfs_names_collate(name, name_len,
> > (ntfschar*)((char*)a +
> > le16_to_cpu(a->name_offset)),
> > a->name_length, 1, IGNORE_CASE,
> > upcase, upcase_len);
> >=20
> >=20
> > ************************************
> > THIS REQUIRES UPCASE TABLE
> > ************************************
> >=20
> >=20
> > /*
> > * If @name collates before a->name, there is no
> > * matching attribute.
> > */
> > if (rc =3D=3D -1) {
> > errno =3D ENOENT;
> > return -1;
> > }
> > /* If the strings are not equal, continue search. */
> > if (rc)
> > continue;
> > rc =3D ntfs_names_collate(name, name_len,
> > (ntfschar*)((char*)a +
> > le16_to_cpu(a->name_offset)),
> > a->name_length, 1, CASE_SENSITIVE,
> > upcase, upcase_len);
> > if (rc =3D=3D -1) {
> > errno =3D ENOENT;
> > return -1;
> > }
> > if (rc)
> > continue;
> > }
> >=20
> > Sorry but which part of this do you not understand? What you were doin=
g
> > worked only by chance/accident/coincidence. It WOULD cause data
> > corruption and I am not having it.
>=20
> Now I understand problem, didn't thought earlier that ntfs_attr_find may
> need upcase table even for case sensitive lookups.=20
Ah! Yes, it does. FWIW I had forgotten/not noticed that, too, until I
came to look into the problem and when I discovered it, I wrote and
committed the mega patch (last week it was I think?). In the kernel you
_always_ have the inode so the problem never arises...
> Thank you for
> explanation. I commit version you proposed to use.
You are welcome! (-:
Sorry about the "somewhat" heated earlier email...
Best regards,
Anton
--=20
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/ & http://www-stu.christs.cam.ac.uk/~aia21/
|