Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Oct 1998 11:57:27 -0400 (EDT)
From:      cmascott@world.std.com
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/8383: msdosfs wipes out NT VFAT lower case flags
Message-ID:  <199810201557.LAA00522@europa.local>

next in thread | raw e-mail | index | archive | help

>Number:         8383
>Category:       kern
>Synopsis:       msdosfs wipes out NT VFAT lower case flags
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Oct 20 09:00:00 PDT 1998
>Last-Modified:
>Originator:     Carl Mascott
>Organization:
>Release:        FreeBSD 2.2.7-RELEASE i386
>Environment:

FreeBSD europa.local 2.2.7-RELEASE FreeBSD 2.2.7-RELEASE #0: Mon Aug 24 20:48:25 EDT 1998     cmascott@europa.local:/usr/src/sys/compile/EUR980824  i386

>Description:

The accompanying patch fixes the following three bugs in msdosfs:

1. When msdosfs updates an NT VFAT DOS (short name) directory entry
   it unconditionally clears the lower case flags (in the byte
   immediately following the file attributes).  Thus all NT VFAT
   files with short names when accessed by msdosfs have their NT
   names converted to upper case.

2. msdosfs does not use the NT VFAT lower case flags when converting
   a short name from DOS to UNIX (with -l in effect).  Thus files
   that have short lower case names on NT get upper case names on UNIX.

3. msdosfs updates access times even if the filesystem is mounted
   with "noatime".

Problems #1 and #2 occur because msdosfs is unaware of the
presence of the NT VFAT lower case flags in the directory entry.

NOTE: The Windows 9x VFAT implementation does not use or recognize
      the NT VFAT lower case flags.  Thus it would not be a good
      idea to modify msdosfs to use these flags when creating a
      short lower case filename.

>How-To-Repeat:

Mount an NT VFAT filesystem with -l.
Copy a file with a short lower case (on NT) name.

>Fix:
	
Apply this patch.

--------------------------- (cut here) ------------------------------
*** sys/msdosfs/msdosfs_vnops.c.orig	Wed Jul 15 22:01:44 1998
--- sys/msdosfs/msdosfs_vnops.c	Tue Oct 13 11:59:43 1998
***************
*** 200,205 ****
--- 200,206 ----
  
  	ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ?
  				ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY;
+ 	ndirent.de_LowerCase = 0;
  	ndirent.de_StartCluster = 0;
  	ndirent.de_FileSize = 0;
  	ndirent.de_dev = pdep->de_dev;
***************
*** 847,853 ****
  			return (error);
  		}
  		error = uiomove(bp->b_data + on, (int) n, uio);
! 		if (!isadir)
  			dep->de_flag |= DE_ACCESS;
  		brelse(bp);
  	} while (error == 0 && uio->uio_resid > 0 && n != 0);
--- 848,854 ----
  			return (error);
  		}
  		error = uiomove(bp->b_data + on, (int) n, uio);
! 		if (!isadir && !(vp->v_mount->mnt_flag & MNT_NOATIME))
  			dep->de_flag |= DE_ACCESS;
  		brelse(bp);
  	} while (error == 0 && uio->uio_resid > 0 && n != 0);
***************
*** 1715,1720 ****
--- 1716,1722 ----
  		goto bad;
  
  	ndirent.de_Attributes = ATTR_DIRECTORY;
+ 	ndirent.de_LowerCase = 0;
  	ndirent.de_StartCluster = newcluster;
  	ndirent.de_FileSize = 0;
  	ndirent.de_dev = pdep->de_dev;
***************
*** 2050,2055 ****
--- 2052,2058 ----
  				dirbuf.d_namlen = dos2unixfn(dentp->deName,
  				    (u_char *)dirbuf.d_name,
  				    pmp->pm_flags & MSDOSFSMNT_SHORTNAME,
+ 				    dentp->deLowerCase[0],
  				    pmp->pm_flags & MSDOSFSMNT_U2WTABLE,
  				    pmp->pm_d2u,
  				    pmp->pm_flags & MSDOSFSMNT_ULTABLE,
*** sys/msdosfs/direntry.h.orig	Wed Jul 15 22:01:41 1998
--- sys/msdosfs/direntry.h	Tue Oct 13 12:04:49 1998
***************
*** 65,71 ****
  #define	ATTR_VOLUME	0x08		/* entry is a volume label */
  #define	ATTR_DIRECTORY	0x10		/* entry is a directory name */
  #define	ATTR_ARCHIVE	0x20		/* file is new or modified */
! 	u_int8_t	deReserved[1];	/* reserved */
  	u_int8_t	deCHundredth;	/* hundredth of seconds in CTime */
  	u_int8_t	deCTime[2];	/* create time */
  	u_int8_t	deCDate[2];	/* create date */
--- 65,73 ----
  #define	ATTR_VOLUME	0x08		/* entry is a volume label */
  #define	ATTR_DIRECTORY	0x10		/* entry is a directory name */
  #define	ATTR_ARCHIVE	0x20		/* file is new or modified */
! 	u_int8_t	deLowerCase[1];	/* NT VFAT lower case flags */
! #define LCASE_BASE	0x08		/* filename base is lower case */
! #define LCASE_EXT	0x10		/* filename extension is lower case */
  	u_int8_t	deCHundredth;	/* hundredth of seconds in CTime */
  	u_int8_t	deCTime[2];	/* create time */
  	u_int8_t	deCDate[2];	/* create date */
***************
*** 130,136 ****
  void unix2dostime __P((struct timespec *tsp, u_int16_t *ddp, 
  	     u_int16_t *dtp, u_int8_t *dhp));
  void dos2unixtime __P((u_int dd, u_int dt, u_int dh, struct timespec *tsp));
! int dos2unixfn __P((u_char dn[11], u_char *un, int lower, int d2u_loaded, u_int8_t *d2u, int ul_loaded, u_int8_t *ul));
  int unix2dosfn __P((const u_char *un, u_char dn[12], int unlen, u_int gen, int u2d_loaded, u_int8_t *u2d, int lu_loaded, u_int8_t *lu));
  int unix2winfn __P((const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int table_loaded, u_int16_t *u2w));
  int winChkName __P((const u_char *un, int unlen, struct winentry *wep, int chksum, int u2w_loaded, u_int16_t *u2w, int ul_loaded, u_int8_t *ul));
--- 132,138 ----
  void unix2dostime __P((struct timespec *tsp, u_int16_t *ddp, 
  	     u_int16_t *dtp, u_int8_t *dhp));
  void dos2unixtime __P((u_int dd, u_int dt, u_int dh, struct timespec *tsp));
! int dos2unixfn __P((u_char dn[11], u_char *un, int shortname, unsigned lcflags, int d2u_loaded, u_int8_t *d2u, int ul_loaded, u_int8_t *ul));
  int unix2dosfn __P((const u_char *un, u_char dn[12], int unlen, u_int gen, int u2d_loaded, u_int8_t *u2d, int lu_loaded, u_int8_t *lu));
  int unix2winfn __P((const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int table_loaded, u_int16_t *u2w));
  int winChkName __P((const u_char *un, int unlen, struct winentry *wep, int chksum, int u2w_loaded, u_int16_t *u2w, int ul_loaded, u_int8_t *ul));
*** sys/msdosfs/denode.h.orig	Wed Jul 15 22:01:41 1998
--- sys/msdosfs/denode.h	Sun Oct 11 18:21:59 1998
***************
*** 156,161 ****
--- 156,162 ----
  #endif
  	u_char de_Name[12];	/* name, from DOS directory entry */
  	u_char de_Attributes;	/* attributes, from directory entry */
+ 	u_char de_LowerCase;	/* NT VFAT lower case flags */
  	u_char de_CHun;		/* Hundredth of second of CTime*/
  	u_short de_CTime;	/* creation time */
  	u_short de_CDate;	/* creation date */
***************
*** 196,201 ****
--- 197,203 ----
  #define DE_INTERNALIZE(dep, dp)				\
  	(bcopy((dp)->deName, (dep)->de_Name, 11),	\
  	 (dep)->de_Attributes = (dp)->deAttributes,	\
+ 	 (dep)->de_LowerCase = (dp)->deLowerCase[0],	\
  	 (dep)->de_CHun = (dp)->deCHundredth,		\
  	 (dep)->de_CTime = getushort((dp)->deCTime),	\
  	 (dep)->de_CDate = getushort((dp)->deCDate),	\
***************
*** 210,217 ****
  	 putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16)
  #define DE_EXTERNALIZE(dp, dep)				\
  	(bcopy((dep)->de_Name, (dp)->deName, 11),	\
! 	 bzero((dp)->deReserved, 10),                   \
  	 (dp)->deAttributes = (dep)->de_Attributes,	\
  	 (dp)->deCHundredth = (dep)->de_CHun,		\
  	 putushort((dp)->deCTime, (dep)->de_CTime),	\
  	 putushort((dp)->deCDate, (dep)->de_CDate),	\
--- 212,220 ----
  	 putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16)
  #define DE_EXTERNALIZE(dp, dep)				\
  	(bcopy((dep)->de_Name, (dp)->deName, 11),	\
! 	 bzero((dp)->deLowerCase, 10),                  \
  	 (dp)->deAttributes = (dep)->de_Attributes,	\
+ 	 (dp)->deLowerCase[0] = (dep)->de_LowerCase,	\
  	 (dp)->deCHundredth = (dep)->de_CHun,		\
  	 putushort((dp)->deCTime, (dep)->de_CTime),	\
  	 putushort((dp)->deCDate, (dep)->de_CDate),	\
*** sys/msdosfs/msdosfs_denode.c.orig	Wed Jul 15 22:01:42 1998
--- sys/msdosfs/msdosfs_denode.c	Sun Oct 11 18:13:55 1998
***************
*** 324,329 ****
--- 324,330 ----
  		nvp->v_flag |= VROOT; /* should be further down		XXX */
  
  		ldep->de_Attributes = ATTR_DIRECTORY;
+ 		ldep->de_LowerCase = 0;
  		if (FAT32(pmp))
  			ldep->de_StartCluster = pmp->pm_rootdirblk;
  			/* de_FileSize will be filled in further down */
*** sys/msdosfs/msdosfs_conv.c.orig	Wed Jul 15 22:01:42 1998
--- sys/msdosfs/msdosfs_conv.c	Tue Oct 13 11:57:22 1998
***************
*** 394,412 ****
   * null.
   */
  int
! dos2unixfn(dn, un, lower, d2u_loaded, d2u, ul_loaded, ul)
  	u_char dn[11];
  	u_char *un;
! 	int lower;
  	int d2u_loaded;
  	u_int8_t *d2u;
  	int ul_loaded;
  	u_int8_t *ul;
  {
  	int i;
  	int thislong = 1;
  	u_char c;
  
  	/*
  	 * If first char of the filename is SLOT_E5 (0x05), then the real
  	 * first char of the filename should be 0xe5. But, they couldn't
--- 394,416 ----
   * null.
   */
  int
! dos2unixfn(dn, un, shortname, lcflags, d2u_loaded, d2u, ul_loaded, ul)
  	u_char dn[11];
  	u_char *un;
! 	int shortname;
! 	unsigned lcflags;
  	int d2u_loaded;
  	u_int8_t *d2u;
  	int ul_loaded;
  	u_int8_t *ul;
  {
  	int i;
+ 	int lower;
  	int thislong = 1;
  	u_char c;
  
+ 	lower = shortname || (lcflags & LCASE_BASE);
+ 
  	/*
  	 * If first char of the filename is SLOT_E5 (0x05), then the real
  	 * first char of the filename should be 0xe5. But, they couldn't
***************
*** 440,445 ****
--- 444,450 ----
  	 * the extension.
  	 */
  	if (*dn != ' ') {
+ 		lower = shortname || (lcflags & LCASE_EXT);
  		*un++ = '.';
  		thislong++;
  		for (i = 0; i < 3 && *dn != ' '; i++) {
--------------------------- (cut here) ------------------------------
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199810201557.LAA00522>