1 // SPDX-License-Identifier: GPL-2.0
5 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
7 * operations with filenames
12 static inline int not_allowed_char(unsigned char c
)
14 return c
<' ' || c
=='"' || c
=='*' || c
=='/' || c
==':' || c
=='<' ||
15 c
=='>' || c
=='?' || c
=='\\' || c
=='|';
18 static inline int no_dos_char(unsigned char c
)
19 { /* Characters that are allowed in HPFS but not in DOS */
20 return c
=='+' || c
==',' || c
==';' || c
=='=' || c
=='[' || c
==']';
23 static inline unsigned char upcase(unsigned char *dir
, unsigned char a
)
25 if (a
<128 || a
==255) return a
>='a' && a
<='z' ? a
- 0x20 : a
;
30 unsigned char hpfs_upcase(unsigned char *dir
, unsigned char a
)
32 return upcase(dir
, a
);
35 static inline unsigned char locase(unsigned char *dir
, unsigned char a
)
37 if (a
<128 || a
==255) return a
>='A' && a
<='Z' ? a
+ 0x20 : a
;
42 int hpfs_chk_name(const unsigned char *name
, unsigned *len
)
45 if (*len
> 254) return -ENAMETOOLONG
;
46 hpfs_adjust_length(name
, len
);
47 if (!*len
) return -EINVAL
;
48 for (i
= 0; i
< *len
; i
++) if (not_allowed_char(name
[i
])) return -EINVAL
;
49 if (*len
== 1) if (name
[0] == '.') return -EINVAL
;
50 if (*len
== 2) if (name
[0] == '.' && name
[1] == '.') return -EINVAL
;
54 unsigned char *hpfs_translate_name(struct super_block
*s
, unsigned char *from
,
55 unsigned len
, int lc
, int lng
)
59 if (hpfs_sb(s
)->sb_chk
>= 2) if (hpfs_is_name_long(from
, len
) != lng
) {
60 pr_err("Long name flag mismatch - name ");
61 for (i
= 0; i
< len
; i
++)
62 pr_cont("%c", from
[i
]);
63 pr_cont(" misidentified as %s.\n", lng
? "short" : "long");
64 pr_err("It's nothing serious. It could happen because of bug in OS/2.\nSet checks=normal to disable this message.\n");
67 if (!(to
= kmalloc(len
, GFP_KERNEL
))) {
68 pr_err("can't allocate memory for name conversion buffer\n");
71 for (i
= 0; i
< len
; i
++) to
[i
] = locase(hpfs_sb(s
)->sb_cp_table
,from
[i
]);
75 int hpfs_compare_names(struct super_block
*s
,
76 const unsigned char *n1
, unsigned l1
,
77 const unsigned char *n2
, unsigned l2
, int last
)
79 unsigned l
= l1
< l2
? l1
: l2
;
82 for (i
= 0; i
< l
; i
++) {
83 unsigned char c1
= upcase(hpfs_sb(s
)->sb_cp_table
,n1
[i
]);
84 unsigned char c2
= upcase(hpfs_sb(s
)->sb_cp_table
,n2
[i
]);
85 if (c1
< c2
) return -1;
86 if (c1
> c2
) return 1;
88 if (l1
< l2
) return -1;
89 if (l1
> l2
) return 1;
93 int hpfs_is_name_long(const unsigned char *name
, unsigned len
)
96 for (i
= 0; i
< len
&& name
[i
] != '.'; i
++)
97 if (no_dos_char(name
[i
])) return 1;
98 if (!i
|| i
> 8) return 1;
99 if (i
== len
) return 0;
100 for (j
= i
+ 1; j
< len
; j
++)
101 if (name
[j
] == '.' || no_dos_char(name
[i
])) return 1;
105 /* OS/2 clears dots and spaces at the end of file name, so we have to */
107 void hpfs_adjust_length(const unsigned char *name
, unsigned *len
)
110 if (*len
== 1 && name
[0] == '.') return;
111 if (*len
== 2 && name
[0] == '.' && name
[1] == '.') return;
112 while (*len
&& (name
[*len
- 1] == '.' || name
[*len
- 1] == ' '))