patch-2.4.13 linux/fs/fat/dir.c

Next file: linux/fs/fat/fatfs_syms.c
Previous file: linux/fs/fat/cache.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.12/linux/fs/fat/dir.c linux/fs/fat/dir.c
@@ -10,12 +10,9 @@
  *  VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu>
  *  Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk>
  *  Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV
- *  Short name translation 1999 by Wolfram Pienkoss <wp@bszh.de>
+ *  Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
  */
 
-#define ASC_LINUX_VERSION(V, P, S)	(((V) * 65536) + ((P) * 256) + (S))
-
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/nls.h>
@@ -30,8 +27,6 @@
 
 #include <asm/uaccess.h>
 
-#include "msbuffer.h"
-
 #define PRINTK(X)
 
 struct file_operations fat_dir_operations = {
@@ -163,6 +158,27 @@
 	return 0;
 }
 
+static inline int
+fat_shortname2uni(struct nls_table *nls, char *buf, int buf_size,
+		  wchar_t *uni_buf, unsigned short opt, int lower)
+{
+	int len = 0;
+
+	if (opt & VFAT_SFN_DISPLAY_LOWER)
+		len =  fat_short2lower_uni(nls, buf, buf_size, uni_buf);
+	else if (opt & VFAT_SFN_DISPLAY_WIN95)
+		len = fat_short2uni(nls, buf, buf_size, uni_buf);
+	else if (opt & VFAT_SFN_DISPLAY_WINNT) {
+		if (lower)
+			len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);
+		else 
+			len = fat_short2uni(nls, buf, buf_size, uni_buf);
+	} else
+		len = fat_short2uni(nls, buf, buf_size, uni_buf);
+
+	return len;
+}
+
 /*
  * Return values: negative -> error, 0 -> not found, positive -> found,
  * value is the total amount of slots, including the shortname entry.
@@ -176,11 +192,12 @@
 	struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
 	struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
 	wchar_t bufuname[14];
-	unsigned char xlate_len, long_slots, *unicode = NULL;
+	unsigned char xlate_len, long_slots;
+	wchar_t *unicode = NULL;
 	char work[8], bufname[260];	/* 256 + 4 */
 	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
 	int utf8 = MSDOS_SB(sb)->options.utf8;
-	int nocase = MSDOS_SB(sb)->options.nocase;
+	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
 	int ino, chl, i, j, last_u, res = 0;
 	loff_t cpos = 0;
 
@@ -197,7 +214,6 @@
 			continue;
 		if (de->attr == ATTR_EXT) {
 			struct msdos_dir_slot *ds;
-			int offset;
 			unsigned char id;
 			unsigned char slot;
 			unsigned char slots;
@@ -205,7 +221,7 @@
 			unsigned char alias_checksum;
 
 			if (!unicode) {
-				unicode = (unsigned char *)
+				unicode = (wchar_t *)
 					__get_free_page(GFP_KERNEL);
 				if (!unicode) {
 					fat_brelse(sb, bh);
@@ -214,7 +230,6 @@
 			}
 parse_long:
 			slots = 0;
-			offset = 0;
 			ds = (struct msdos_dir_slot *) de;
 			id = ds->id;
 			if (!(id & 0x40))
@@ -227,16 +242,16 @@
 
 			slot = slots;
 			while (1) {
+				int offset;
+
 				slot--;
-				offset = slot * 26;
-				memcpy(&unicode[offset], ds->name0_4, 10);
-				memcpy(&unicode[offset+10], ds->name5_10, 12);
-				memcpy(&unicode[offset+22], ds->name11_12, 4);
-				offset += 26;
+				offset = slot * 13;
+				fat16_towchar(unicode + offset, ds->name0_4, 5);
+				fat16_towchar(unicode + offset + 5, ds->name5_10, 6);
+				fat16_towchar(unicode + offset + 11, ds->name11_12, 2);
 
 				if (ds->id & 0x40) {
-					unicode[offset] = 0;
-					unicode[offset+1] = 0;
+					unicode[offset + 13] = 0;
 				}
 				if (fat_get_entry(inode,&cpos,&bh,&de,&ino)<0)
 					goto EODir;
@@ -271,10 +286,9 @@
 		}
 		for (i = 0, j = 0, last_u = 0; i < 8;) {
 			if (!work[i]) break;
-			if (nocase)
-				chl = fat_short2uni(nls_disk, &work[i], 8 - i, &bufuname[j++]);
-			else
-				chl = fat_short2lower_uni(nls_disk, &work[i], 8 - i, &bufuname[j++]);
+			chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
+						&bufuname[j++], opt_shortname,
+						de->lcase & CASE_LOWER_BASE);
 			if (chl <= 1) {
 				if (work[i] != ' ')
 					last_u = j;
@@ -287,10 +301,9 @@
 		fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
 		for (i = 0; i < 3;) {
 			if (!de->ext[i]) break;
-			if (nocase)
-				chl = fat_short2uni(nls_disk, &de->ext[i], 3 - i, &bufuname[j++]);
-			else
-				chl = fat_short2lower_uni(nls_disk, &de->ext[i], 3 - i, &bufuname[j++]);
+			chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i,
+						&bufuname[j++], opt_shortname,
+						de->lcase & CASE_LOWER_EXT);
 			if (chl <= 1) {
 				if (de->ext[i] != ' ')
 					last_u = j;
@@ -314,8 +327,8 @@
 
 		if (long_slots) {
 			xlate_len = utf8
-				?utf8_wcstombs(bufname, (wchar_t *) unicode, sizeof(bufname))
-				:uni16_to_x8(bufname, (wchar_t *) unicode, uni_xlate, nls_io);
+				?utf8_wcstombs(bufname, unicode, sizeof(bufname))
+				:uni16_to_x8(bufname, unicode, uni_xlate, nls_io);
 			if (xlate_len != name_len)
 				continue;
 			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
@@ -346,13 +359,15 @@
 	struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
 	struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
 	wchar_t bufuname[14];
-	unsigned char long_slots, *unicode = NULL;
+	unsigned char long_slots;
+	wchar_t *unicode = NULL;
 	char c, work[8], bufname[56], *ptname = bufname;
 	unsigned long lpos, dummy, *furrfu = &lpos;
 	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
 	int isvfat = MSDOS_SB(sb)->options.isvfat;
 	int utf8 = MSDOS_SB(sb)->options.utf8;
 	int nocase = MSDOS_SB(sb)->options.nocase;
+	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
 	int ino, inum, chi, chl, i, i2, j, last, last_u, dotoffset = 0;
 	loff_t cpos;
 
@@ -394,7 +409,6 @@
 
 	if (isvfat && de->attr == ATTR_EXT) {
 		struct msdos_dir_slot *ds;
-		int offset;
 		unsigned char id;
 		unsigned char slot;
 		unsigned char slots;
@@ -402,7 +416,7 @@
 		unsigned char alias_checksum;
 
 		if (!unicode) {
-			unicode = (unsigned char *)
+			unicode = (wchar_t *)
 				__get_free_page(GFP_KERNEL);
 			if (!unicode) {
 				filp->f_pos = cpos;
@@ -412,7 +426,6 @@
 		}
 ParseLong:
 		slots = 0;
-		offset = 0;
 		ds = (struct msdos_dir_slot *) de;
 		id = ds->id;
 		if (!(id & 0x40))
@@ -425,16 +438,16 @@
 
 		slot = slots;
 		while (1) {
+			int offset;
+
 			slot--;
-			offset = slot * 26;
-			memcpy(&unicode[offset], ds->name0_4, 10);
-			memcpy(&unicode[offset+10], ds->name5_10, 12);
-			memcpy(&unicode[offset+22], ds->name11_12, 4);
-			offset += 26;
+			offset = slot * 13;
+			fat16_towchar(unicode + offset, ds->name0_4, 5);
+			fat16_towchar(unicode + offset + 5, ds->name5_10, 6);
+			fat16_towchar(unicode + offset + 11, ds->name11_12, 2);
 
 			if (ds->id & 0x40) {
-				unicode[offset] = 0;
-				unicode[offset+1] = 0;
+				unicode[offset + 13] = 0;
 			}
 			if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
 				goto EODir;
@@ -474,10 +487,9 @@
 	}
 	for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {
 		if (!(c = work[i])) break;
-		if (nocase)
-			chl = fat_short2uni(nls_disk, &work[i], 8 - i, &bufuname[j++]);
-		else
-			chl = fat_short2lower_uni(nls_disk, &work[i], 8 - i, &bufuname[j++]);
+		chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
+					&bufuname[j++], opt_shortname,
+					de->lcase & CASE_LOWER_BASE);
 		if (chl <= 1) {
 			ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;
 			if (c != ' ') {
@@ -498,10 +510,9 @@
 	ptname[i++] = '.';
 	for (i2 = 0; i2 < 3;) {
 		if (!(c = de->ext[i2])) break;
-		if (nocase)
-			chl = fat_short2uni(nls_disk, &de->ext[i2], 3 - i2, &bufuname[j++]);
-		else
-			chl = fat_short2lower_uni(nls_disk, &de->ext[i2], 3 - i2, &bufuname[j++]);
+		chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2,
+					&bufuname[j++], opt_shortname,
+					de->lcase & CASE_LOWER_EXT);
 		if (chl <= 1) {
 			i2++;
 			ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;
@@ -553,8 +564,8 @@
 	} else {
 		char longname[275];
 		int long_len = utf8
-			? utf8_wcstombs(longname, (wchar_t *) unicode, sizeof(longname))
-			: uni16_to_x8(longname, (wchar_t *) unicode, uni_xlate,
+			? utf8_wcstombs(longname, unicode, sizeof(longname))
+			: uni16_to_x8(longname, unicode, uni_xlate,
 				      nls_io);
 		if (both) {
 			memcpy(&longname[long_len+1], bufname, i);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)