diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-06 23:51:34 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-06 23:51:34 +0000 |
commit | 230e5ab6a084ed50470f101934782dbf54b0d06b (patch) | |
tree | 5dd821c8d33f450470588e7a543f74bf74306e9e /fs/fat/dir.c | |
parent | c9b1c8a64c6444d189856f1e26bdcb8b4cd0113a (diff) |
Merge with Linux 2.1.67.
Diffstat (limited to 'fs/fat/dir.c')
-rw-r--r-- | fs/fat/dir.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 494f7781b..7568f876a 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -11,8 +11,12 @@ * Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk> */ +#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> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/stat.h> @@ -24,13 +28,11 @@ #include <asm/uaccess.h> #include "msbuffer.h" -#include "tables.h" - #define PRINTK(X) -static long fat_dir_read(struct inode * inode,struct file * filp, - char * buf, unsigned long count) +static ssize_t fat_dir_read(struct file * filp, char * buf, + size_t count, loff_t *ppos) { return -EISDIR; } @@ -40,7 +42,7 @@ struct file_operations fat_dir_operations = { fat_dir_read, /* read */ NULL, /* write - bad */ fat_readdir, /* readdir */ - NULL, /* poll - default */ + NULL, /* select v2.0.x/poll v2.1.x - default */ fat_dir_ioctl, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ @@ -48,7 +50,9 @@ struct file_operations fat_dir_operations = { file_fsync /* fsync */ }; -/* Convert Unicode string to ASCII. If uni_xlate is enabled and we +/* + * Convert Unicode 16 to UTF8, translated unicode, or ascii. + * If uni_xlate is enabled and we * can't get a 1:1 conversion, use a colon as an escape character since * it is normally invalid on the vfat filesystem. The following three * characters are a sort of uuencoded 16 bit Unicode value. This lets @@ -56,10 +60,11 @@ struct file_operations fat_dir_operations = { * into some trouble with long Unicode names, but ignore that right now. */ static int -uni2ascii(unsigned char *uni, unsigned char *ascii, int uni_xlate) +uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate, + struct nls_table *nls) { unsigned char *ip, *op; - unsigned char page, pg_off; + unsigned char ch, cl; unsigned char *uni_page; unsigned short val; @@ -67,21 +72,21 @@ uni2ascii(unsigned char *uni, unsigned char *ascii, int uni_xlate) op = ascii; while (*ip || ip[1]) { - pg_off = *ip++; - page = *ip++; - - uni_page = fat_uni2asc_pg[page]; - if (uni_page && uni_page[pg_off]) { - *op++ = uni_page[pg_off]; + cl = *ip++; + ch = *ip++; + + uni_page = nls->page_uni2charset[ch]; + if (uni_page && uni_page[cl]) { + *op++ = uni_page[cl]; } else { if (uni_xlate == 1) { *op++ = ':'; - val = (pg_off << 8) + page; - op[2] = fat_uni2code[val & 0x3f]; + val = (cl << 8) + ch; + op[2] = fat_uni2esc[val & 0x3f]; val >>= 6; - op[1] = fat_uni2code[val & 0x3f]; + op[1] = fat_uni2esc[val & 0x3f]; val >>= 6; - *op = fat_uni2code[val & 0x3f]; + *op = fat_uni2esc[val & 0x3f]; op += 3; } else { *op++ = '?'; @@ -92,6 +97,19 @@ uni2ascii(unsigned char *uni, unsigned char *ascii, int uni_xlate) return (op - ascii); } +#if 0 +static void dump_de(struct msdos_dir_entry *de) +{ + int i; + unsigned char *p = (unsigned char *) de; + printk("["); + + for (i = 0; i < 32; i++, p++) { + printk("%02x ", *p); + } + printk("]\n"); +} +#endif int fat_readdirx( struct inode *inode, struct file *filp, @@ -115,7 +133,9 @@ int fat_readdirx( unsigned char alias_checksum = 0; /* Make compiler warning go away */ unsigned char long_slots = 0; int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate; + int utf8 = MSDOS_SB(sb)->options.utf8; unsigned char *unicode = NULL; + struct nls_table *nls = MSDOS_SB(sb)->nls_io; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; @@ -138,6 +158,9 @@ int fat_readdirx( is_long = 0; ino = fat_get_entry(inode,&filp->f_pos,&bh,&de); while (ino > -1) { +#if 0 + dump_de(de); +#endif /* Check for long filename entry */ if (MSDOS_SB(sb)->options.isvfat && (de->name[0] == (__s8) DELETED_FLAG)) { is_long = 0; @@ -217,7 +240,6 @@ int fat_readdirx( if (is_long) { unsigned char sum; - long_len = uni2ascii(unicode, longname, uni_xlate); for (sum = 0, i = 0; i < 11; i++) { sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i]; } @@ -226,6 +248,11 @@ int fat_readdirx( PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum)); is_long = 0; } + if (utf8) { + long_len = utf8_wcstombs(longname, (__u16 *) unicode, sizeof(longname)); + } else { + long_len = uni16_to_x8(longname, unicode, uni_xlate, nls); + } } if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) { @@ -390,7 +417,7 @@ int fat_dir_ioctl(struct inode * inode, struct file * filp, switch (cmd) { case VFAT_IOCTL_READDIR_BOTH: { struct dirent *d1 = (struct dirent *)arg; - err = verify_area(VERIFY_WRITE, d1, sizeof (*d1)); + err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2])); if (err) return err; put_user(0, &d1->d_reclen); @@ -400,7 +427,7 @@ int fat_dir_ioctl(struct inode * inode, struct file * filp, case VFAT_IOCTL_READDIR_SHORT: { struct dirent *d1 = (struct dirent *)arg; put_user(0, &d1->d_reclen); - err = verify_area(VERIFY_WRITE, d1, sizeof (*d1)); + err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2])); if (err) return err; return fat_readdirx(inode,filp,(void *)arg, |