patch-2.4.0-test5 linux/fs/vfat/namei.c
Next file: linux/include/asm-alpha/mc146818rtc.h
Previous file: linux/fs/ufs/inode.c
Back to the patch index
Back to the overall index
- Lines: 415
- Date:
Tue Jul 25 09:12:11 2000
- Orig file:
v2.4.0-test4/linux/fs/vfat/namei.c
- Orig date:
Mon Jul 10 16:47:26 2000
diff -u --recursive --new-file v2.4.0-test4/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
@@ -194,28 +194,29 @@
return 0;
}
-static inline unsigned char
-vfat_uni2short(struct nls_table *t, struct nls_unicode uc)
+static inline int
+vfat_uni2short(struct nls_table *t, wchar_t uc, unsigned char *op, int bound)
{
- unsigned char *up;
+ int charlen;
- up = t->page_uni2charset[uc.uni2];
- if (up)
- return up[uc.uni1];
+ if ( (charlen = t->uni2char(uc, op, bound)) < 0)
+ charlen = 0;
- return 0;
+ return charlen;
}
-static inline unsigned char
-vfat_uni2upper_short(struct nls_table *t, struct nls_unicode uc)
+static inline int
+vfat_uni2upper_short(struct nls_table *t, wchar_t uc, char *op, int bound)
{
- unsigned char *up;
+ int chi, chl;
- up = t->page_uni2charset[uc.uni2];
- if (up)
- return vfat_toupper(t, up[uc.uni1]);
+ if ( (chl = t->uni2char(uc, op, bound)) < 0)
+ chl = 0;
- return 0;
+ for (chi = 0; chi < chl; chi++)
+ op[chi] = vfat_toupper(t, op[chi]);
+
+ return chl;
}
/*
@@ -423,48 +424,66 @@
return 0;
}
-static int vfat_valid_shortname(struct nls_table *nls, struct nls_unicode *name,
- int len)
+static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len)
{
- struct nls_unicode *walk;
- unsigned char c, l;
+ wchar_t *walk;
+ unsigned char c, charbuf[NLS_MAX_CHARSET_SIZE];
+ int chl, chi;
int space;
- c = vfat_uni2upper_short(nls, *name);
- if (IS_FREE(&c))
+ if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)
return -EINVAL;
+ if (IS_FREE(charbuf))
+ return -EINVAL;
+
+ chl = 0;
+ c = 0;
space = 1; /* disallow names starting with a dot */
for (walk = name; len && walk-name < 8;) {
len--;
- l = vfat_uni2short(nls, *walk++);
- c = vfat_getupper(nls, l);
- if (!c) return -EINVAL;
- if (l != vfat_tolower(nls, c)) return -EINVAL;
- if (strchr(replace_chars,c)) return -EINVAL;
- if (c < ' '|| c==':') return -EINVAL;
- if (c == '.') break;
- space = c == ' ';
+ if ( (chl = nls->uni2char(*walk, charbuf, NLS_MAX_CHARSET_SIZE)) < 0) {
+ walk++;
+ return -EINVAL;
+ }
+
+ for (chi = 0; chi < chl; chi++) {
+ c = vfat_getupper(nls, charbuf[chi]);
+ if (!c) return -EINVAL;
+ if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
+ if (strchr(replace_chars,c)) return -EINVAL;
+ if (c < ' '|| c==':') return -EINVAL;
+ if (c == '.') goto dot;
+ space = c == ' ';
+ }
}
+dot:;
if (space) return -EINVAL;
if (len && c != '.') {
len--;
- c = vfat_uni2upper_short(nls, *walk++);
- if (c != '.') return -EINVAL;
+ if (vfat_uni2upper_short(nls, *walk++, charbuf, NLS_MAX_CHARSET_SIZE) == 1) {
+ if (charbuf[0] != '.') return -EINVAL;
+ } else
+ return -EINVAL;
+ c = '.';
}
if (c == '.') {
if (len >= 4) return -EINVAL;
while (len > 0) {
len--;
- l = vfat_uni2short(nls, *walk++);
- c = vfat_getupper(nls, l);
- if (!c) return -EINVAL;
- if (l != vfat_tolower(nls, c)) return -EINVAL;
- if (strchr(replace_chars,c))
+ chl = vfat_uni2short(nls, *walk++, charbuf, NLS_MAX_CHARSET_SIZE);
+ if (chl < 0)
return -EINVAL;
- if (c < ' ' || c == '.'|| c==':')
- return -EINVAL;
- space = c == ' ';
+ for (chi = 0; chi < chl; chi++) {
+ c = vfat_getupper(nls, charbuf[chi]);
+ if (!c) return -EINVAL;
+ if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
+ if (strchr(replace_chars,c))
+ return -EINVAL;
+ if (c < ' ' || c == '.'|| c==':')
+ return -EINVAL;
+ space = c == ' ';
+ }
}
if (space) return -EINVAL;
}
@@ -485,41 +504,54 @@
return 0;
}
-static int vfat_format_name(struct nls_table *nls, struct nls_unicode *name,
+static int vfat_format_name(struct nls_table *nls, wchar_t *name,
int len, char *res)
{
char *walk;
- unsigned char c;
+ unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
+ int chi, chl;
int space;
- c = vfat_uni2upper_short(nls, *name);
- if (IS_FREE(&c))
+ if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)
+ return -EINVAL;
+
+ if (IS_FREE(charbuf))
return -EINVAL;
space = 1; /* disallow names starting with a dot */
- for (walk = res; len--; walk++) {
- c = vfat_uni2upper_short(nls, *name++);
- if (c == '.') break;
- if (!c) return -EINVAL;
- if (walk-res == 8) return -EINVAL;
- if (strchr(replace_chars,c)) return -EINVAL;
- if (c < ' '|| c==':') return -EINVAL;
- space = c == ' ';
- *walk = c;
+ for (walk = res; len--; ) {
+ chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);
+ if (chl == 0)
+ return -EINVAL;
+ for (chi = 0; chi < chl; chi++){
+ if (charbuf[chi] == '.') goto dot;
+ if (!charbuf[chi]) return -EINVAL;
+ if (walk-res == 8) return -EINVAL;
+ if (strchr(replace_chars,charbuf[chi])) return -EINVAL;
+ if (charbuf[chi] < ' '|| charbuf[chi]==':') return -EINVAL;
+ space = charbuf[chi] == ' ';
+ *walk = charbuf[chi];
+ walk++;
+ }
}
+dot:;
if (space) return -EINVAL;
if (len >= 0) {
while (walk-res < 8) *walk++ = ' ';
while (len > 0 && walk-res < MSDOS_NAME) {
- c = vfat_uni2upper_short(nls, *name++);
- len--;
- if (!c) return -EINVAL;
- if (strchr(replace_chars,c))
- return -EINVAL;
- if (c < ' ' || c == '.'|| c==':')
- return -EINVAL;
- space = c == ' ';
- *walk++ = c;
+ chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);
+ if (len < chl)
+ chl = len;
+ len -= chl;
+ for (chi = 0; chi < chl; chi++){
+ if (!charbuf[chi]) return -EINVAL;
+ if (strchr(replace_chars,charbuf[chi]))
+ return -EINVAL;
+ if (charbuf[chi] < ' ' || charbuf[chi] == '.'|| charbuf[chi]==':')
+ return -EINVAL;
+ space = charbuf[chi] == ' ';
+ *walk++ = charbuf[chi];
+ }
}
if (space) return -EINVAL;
if (len) return -EINVAL;
@@ -535,15 +567,18 @@
* shortname does not exist
*/
static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
- struct nls_unicode *name, int len,
+ wchar_t *name, int len,
char *name_res)
{
- struct nls_unicode *ip, *op, *ext_start, *end, *name_start;
- struct nls_unicode msdos_name[13];
+ wchar_t *ip, *op, *ext_start, *end, *name_start;
+ wchar_t msdos_name[13];
char base[9], ext[4], buf[8], *p;
+ unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
+ int chl, chi;
int sz, extlen, baselen, i;
PRINTK2(("Entering vfat_create_shortname\n"));
+ chl = 0;
sz = 0; /* Make compiler happy */
if (len <= 12) {
/* Do a case insensitive search if the name would be a valid
@@ -560,8 +595,14 @@
return 0;
return -EEXIST;
}
- if (vfat_uni2upper_short(nls, *ip) == ' ')
+ chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
+ for (chi = 0; chi < chl; chi++){
+ if (charbuf[chi] == ' ')
+ break;
+ }
+ if (chi < chl)
break;
+
*op = *ip;
}
}
@@ -570,13 +611,18 @@
/* Now, we need to create a shortname from the long name */
ext_start = end = &name[len];
while (--ext_start >= name) {
- if (vfat_uni2upper_short(nls, *ext_start) == '.') {
- if (ext_start == end - 1) {
- sz = len;
- ext_start = NULL;
+ chl = vfat_uni2upper_short(nls, *ext_start, charbuf, NLS_MAX_CHARSET_SIZE);
+ for (chi = 0; chi < chl; chi++) {
+ if (charbuf[chi] == '.') {
+ if (ext_start == end - 1) {
+ sz = len;
+ ext_start = NULL;
+ }
+ break;
}
- break;
}
+ if (charbuf[chi] == '.')
+ break;
}
if (ext_start == name - 1) {
sz = len;
@@ -590,11 +636,12 @@
name_start = &name[0];
while (name_start < ext_start)
{
- unsigned char c = vfat_uni2upper_short(nls, *name_start);
- if (!c)
- break;
- if (!strchr(skip_chars, c))
+ chl = vfat_uni2upper_short(nls, *name_start, charbuf, NLS_MAX_CHARSET_SIZE);
+ if (chl == 0)
break;
+ for (chi = 0; chi < chl; chi++)
+ if (!strchr(skip_chars, charbuf[chi]))
+ break;
name_start++;
}
if (name_start != ext_start) {
@@ -606,38 +653,47 @@
}
}
- for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
+ for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++, ip++)
{
- unsigned char c = vfat_uni2upper_short(nls, *ip);
- if (!c) {
- *p++ = c = '_';
+ chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
+ if (chl == 0){
+ *p++ = '_';
baselen++;
- } else if (!strchr(skip_chars, c)) {
- if (strchr(replace_chars, c))
- *p = '_';
- else
- *p = c;
- p++; baselen++;
+ continue;
+ }
+
+ for (chi = 0; chi < chl; chi++){
+ if (!strchr(skip_chars, charbuf[chi])){
+ if (strchr(replace_chars, charbuf[chi]))
+ *p = '_';
+ else
+ *p = charbuf[chi];
+ p++; baselen++;
+ }
}
- ip++;
}
if (baselen == 0) {
return -EINVAL;
}
-
+
extlen = 0;
if (ext_start) {
for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
- unsigned char c = vfat_uni2upper_short(nls, *ip);
- if (!c) {
- *p++ = c = '_';
+ chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
+ if (chl == 0) {
+ *p++ = '_';
extlen++;
- } else if (!strchr(skip_chars, c)) {
- if (strchr(replace_chars, c))
- *p = '_';
- else
- *p = c;
- p++; extlen++;
+ continue;
+ }
+
+ for (chi = 0; chi < chl; chi++) {
+ if (!strchr(skip_chars, charbuf[chi])) {
+ if (strchr(replace_chars, charbuf[chi]))
+ *p = '_';
+ else
+ *p = charbuf[chi];
+ p++; extlen++;
+ }
}
}
}
@@ -703,6 +759,7 @@
char *op;
unsigned int ec;
int i, k, fill;
+ int charlen;
if (utf8) {
*outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
@@ -742,10 +799,12 @@
ip += 5;
i += 5;
} else {
- *op++ = nls->charset2uni[*ip].uni1;
- *op++ = nls->charset2uni[*ip].uni2;
- ip++;
- i++;
+ if ((charlen = nls->char2uni(ip, len-i, (wchar_t *)op)) < 0)
+ return -EINVAL;
+
+ ip += charlen;
+ i += charlen;
+ op += 2;
}
}
} else {
@@ -783,7 +842,7 @@
int len, int *slots, int uni_xlate)
{
struct nls_table *nls_io, *nls_disk;
- struct nls_unicode *uname;
+ wchar_t *uname;
struct msdos_dir_slot *ps;
struct msdos_dir_entry *de;
unsigned long page;
@@ -802,17 +861,19 @@
if(!(page = __get_free_page(GFP_KERNEL)))
return -ENOMEM;
uniname = (char *) page;
+
res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
utf8, nls_io);
if (res < 0)
goto out_free;
- uname = (struct nls_unicode *) page;
+ uname = (wchar_t *) page;
if (vfat_valid_shortname(nls_disk, uname, ulen) >= 0) {
res = vfat_format_name(nls_disk, uname, ulen, de->name);
if (!res)
goto out_free;
}
+
res = vfat_create_shortname(dir, nls_disk, uname, ulen, msdos_name);
if (res)
goto out_free;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)