[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Patch] msdosfs: long names are not always long
- To: tech_(_at_)_openbsd_(_dot_)_org
- Subject: [Patch] msdosfs: long names are not always long
- From: Alexey Vatchenko <avv_(_at_)_mail_(_dot_)_zp_(_dot_)_ua>
- Date: Mon, 20 Mar 2006 22:47:34 +0200
Hi!
Situation...
fat is mounted with ``long names'' support, getting list of directory
with >200 files. Some files are shown as their short names.
The problem...
When all parts of ``long name'' is traversed and buffer (for storing
direntries) is totally filled with direntries msdosfs_readdir() returns
error and then is started from position where there are no ``long name''
parts, just short name.
The attached patch fixes it by saving offset where the first (WIN_LAST)
part of ``long name'' is and if buffer space is over it replaces current
offset with saved offset.
cd /usr/src/sys && patch -p0 < msdosfs.diff
--
Alexey V. Vatchenko
mailto: avv_(_at_)_mail_(_dot_)_zp_(_dot_)_ua
JID: avv_(_at_)_jabber_(_dot_)_zp_(_dot_)_ua
ICQ: 162799204
Index: msdosfs/msdosfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.53
diff -u -r1.53 msdosfs_vnops.c
--- msdosfs/msdosfs_vnops.c 14 Mar 2005 22:31:52 -0000 1.53
+++ msdosfs/msdosfs_vnops.c 20 Mar 2006 20:31:32 -0000
@@ -1479,6 +1479,7 @@
u_long *cookies = NULL;
int ncookies = 0;
off_t offset;
+ off_t wlast_off; /* offset of WIN_LAST (in long names) */
int chksum = -1;
#ifdef MSDOSFS_DEBUG
@@ -1513,6 +1514,8 @@
lost = uio->uio_resid - count;
uio->uio_resid = count;
+ wlast_off = -1; /* doesn't point to any WIN_LAST direntry */
+
if (ap->a_ncookies) {
ncookies = uio->uio_resid / sizeof(struct direntry) + 3;
MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
@@ -1614,6 +1617,7 @@
*/
if (dentp->deName[0] == SLOT_DELETED) {
chksum = -1;
+ wlast_off = -1;
continue;
}
@@ -1623,7 +1627,11 @@
if (dentp->deAttributes == ATTR_WIN95) {
if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
continue;
- chksum = win2unixfn((struct winentry *)dentp, &dirbuf, chksum);
+#define wep ((struct winentry *)dentp)
+ chksum = win2unixfn(wep, &dirbuf, chksum);
+ if (wep->weCnt & WIN_LAST)
+ wlast_off = offset;
+#undef wep
continue;
}
@@ -1632,6 +1640,7 @@
*/
if (dentp->deAttributes & ATTR_VOLUME) {
chksum = -1;
+ wlast_off = -1;
continue;
}
@@ -1681,8 +1690,12 @@
dirbuf.d_reclen = DIRENT_SIZE(&dirbuf);
if (uio->uio_resid < dirbuf.d_reclen) {
brelse(bp);
+ /* start from WIN_LAST next time */
+ if (wlast_off >= 0)
+ offset = wlast_off;
goto out;
}
+ wlast_off = -1;
error = uiomove((caddr_t) &dirbuf,
dirbuf.d_reclen, uio);
if (error) {
Visit your host, monkey.org