4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * operations with filenames
11 static inline int not_allowed_char(unsigned char c
)
13 return c
<' ' || c
=='"' || c
=='*' || c
=='/' || c
==':' || c
=='<' ||
14 c
=='>' || c
=='?' || c
=='\\' || c
=='|';
17 static inline int no_dos_char(unsigned char c
)
18 { /* Characters that are allowed in HPFS but not in DOS */
19 return c
=='+' || c
==',' || c
==';' || c
=='=' || c
=='[' || c
==']';
22 static inline unsigned char upcase(unsigned char *dir
, unsigned char a
)
24 if (a
<128 || a
==255) return a
>='a' && a
<='z' ? a
- 0x20 : a
;
29 unsigned char hpfs_upcase(unsigned char *dir
, unsigned char a
)
31 return upcase(dir
, a
);
34 static inline unsigned char locase(unsigned char *dir
, unsigned char a
)
36 if (a
<128 || a
==255) return a
>='A' && a
<='Z' ? a
+ 0x20 : a
;
41 int hpfs_chk_name(const unsigned char *name
, unsigned *len
)
44 if (*len
> 254) return -ENAMETOOLONG
;
45 hpfs_adjust_length(name
, len
);
46 if (!*len
) return -EINVAL
;
47 for (i
= 0; i
< *len
; i
++) if (not_allowed_char(name
[i
])) return -EINVAL
;
48 if (*len
== 1) if (name
[0] == '.') return -EINVAL
;
49 if (*len
== 2) if (name
[0] == '.' && name
[1] == '.') return -EINVAL
;
53 unsigned char *hpfs_translate_name(struct super_block
*s
, unsigned char *from
,
54 unsigned len
, int lc
, int lng
)
58 if (hpfs_sb(s
)->sb_chk
>= 2) if (hpfs_is_name_long(from
, len
) != lng
) {
59 pr_err("Long name flag mismatch - name ");
60 for (i
= 0; i
< len
; i
++)
61 pr_cont("%c", from
[i
]);
62 pr_cont(" misidentified as %s.\n", lng
? "short" : "long");
63 pr_err("It's nothing serious. It could happen because of bug in OS/2.\nSet checks=normal to disable this message.\n");
66 if (!(to
= kmalloc(len
, GFP_KERNEL
))) {
67 pr_err("can't allocate memory for name conversion buffer\n");
70 for (i
= 0; i
< len
; i
++) to
[i
] = locase(hpfs_sb(s
)->sb_cp_table
,from
[i
]);
74 int hpfs_compare_names(struct super_block
*s
,
75 const unsigned char *n1
, unsigned l1
,
76 const unsigned char *n2
, unsigned l2
, int last
)
78 unsigned l
= l1
< l2
? l1
: l2
;
81 for (i
= 0; i
< l
; i
++) {
82 unsigned char c1
= upcase(hpfs_sb(s
)->sb_cp_table
,n1
[i
]);
83 unsigned char c2
= upcase(hpfs_sb(s
)->sb_cp_table
,n2
[i
]);
84 if (c1
< c2
) return -1;
85 if (c1
> c2
) return 1;
87 if (l1
< l2
) return -1;
88 if (l1
> l2
) return 1;
92 int hpfs_is_name_long(const unsigned char *name
, unsigned len
)
95 for (i
= 0; i
< len
&& name
[i
] != '.'; i
++)
96 if (no_dos_char(name
[i
])) return 1;
97 if (!i
|| i
> 8) return 1;
98 if (i
== len
) return 0;
99 for (j
= i
+ 1; j
< len
; j
++)
100 if (name
[j
] == '.' || no_dos_char(name
[i
])) return 1;
104 /* OS/2 clears dots and spaces at the end of file name, so we have to */
106 void hpfs_adjust_length(const unsigned char *name
, unsigned *len
)
109 if (*len
== 1 && name
[0] == '.') return;
110 if (*len
== 2 && name
[0] == '.' && name
[1] == '.') return;
111 while (*len
&& (name
[*len
- 1] == '.' || name
[*len
- 1] == ' '))