4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * operations with filenames
11 static char *text_postfix
[]={
12 ".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
13 ".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
14 ".RC", ".TEX", ".TXT", ".Y", ""};
16 static char *text_prefix
[]={
17 "AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
18 "MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
20 void hpfs_decide_conv(struct inode
*inode
, unsigned char *name
, unsigned len
)
22 struct hpfs_inode_info
*hpfs_inode
= hpfs_i(inode
);
24 if (hpfs_inode
->i_conv
!= CONV_AUTO
) return;
25 for (i
= 0; *text_postfix
[i
]; i
++) {
26 int l
= strlen(text_postfix
[i
]);
28 if (!hpfs_compare_names(inode
->i_sb
, text_postfix
[i
], l
, name
+ len
- l
, l
, 0))
31 for (i
= 0; *text_prefix
[i
]; i
++) {
32 int l
= strlen(text_prefix
[i
]);
34 if (!hpfs_compare_names(inode
->i_sb
, text_prefix
[i
], l
, name
, l
, 0))
37 hpfs_inode
->i_conv
= CONV_BINARY
;
40 hpfs_inode
->i_conv
= CONV_TEXT
;
44 static inline int not_allowed_char(unsigned char c
)
46 return c
<' ' || c
=='"' || c
=='*' || c
=='/' || c
==':' || c
=='<' ||
47 c
=='>' || c
=='?' || c
=='\\' || c
=='|';
50 static inline int no_dos_char(unsigned char c
)
51 { /* Characters that are allowed in HPFS but not in DOS */
52 return c
=='+' || c
==',' || c
==';' || c
=='=' || c
=='[' || c
==']';
55 static inline unsigned char upcase(unsigned char *dir
, unsigned char a
)
57 if (a
<128 || a
==255) return a
>='a' && a
<='z' ? a
- 0x20 : a
;
62 unsigned char hpfs_upcase(unsigned char *dir
, unsigned char a
)
64 return upcase(dir
, a
);
67 static inline unsigned char locase(unsigned char *dir
, unsigned char a
)
69 if (a
<128 || a
==255) return a
>='A' && a
<='Z' ? a
+ 0x20 : a
;
74 int hpfs_chk_name(unsigned char *name
, unsigned *len
)
77 if (*len
> 254) return -ENAMETOOLONG
;
78 hpfs_adjust_length(name
, len
);
79 if (!*len
) return -EINVAL
;
80 for (i
= 0; i
< *len
; i
++) if (not_allowed_char(name
[i
])) return -EINVAL
;
81 if (*len
== 1) if (name
[0] == '.') return -EINVAL
;
82 if (*len
== 2) if (name
[0] == '.' && name
[1] == '.') return -EINVAL
;
86 char *hpfs_translate_name(struct super_block
*s
, unsigned char *from
,
87 unsigned len
, int lc
, int lng
)
91 if (hpfs_sb(s
)->sb_chk
>= 2) if (hpfs_is_name_long(from
, len
) != lng
) {
92 printk("HPFS: Long name flag mismatch - name ");
93 for (i
=0; i
<len
; i
++) printk("%c", from
[i
]);
94 printk(" misidentified as %s.\n", lng
? "short" : "long");
95 printk("HPFS: It's nothing serious. It could happen because of bug in OS/2.\nHPFS: Set checks=normal to disable this message.\n");
98 if (!(to
= kmalloc(len
, GFP_KERNEL
))) {
99 printk("HPFS: can't allocate memory for name conversion buffer\n");
102 for (i
= 0; i
< len
; i
++) to
[i
] = locase(hpfs_sb(s
)->sb_cp_table
,from
[i
]);
106 int hpfs_compare_names(struct super_block
*s
, unsigned char *n1
, unsigned l1
,
107 unsigned char *n2
, unsigned l2
, int last
)
109 unsigned l
= l1
< l2
? l1
: l2
;
112 for (i
= 0; i
< l
; i
++) {
113 unsigned char c1
= upcase(hpfs_sb(s
)->sb_cp_table
,n1
[i
]);
114 unsigned char c2
= upcase(hpfs_sb(s
)->sb_cp_table
,n2
[i
]);
115 if (c1
< c2
) return -1;
116 if (c1
> c2
) return 1;
118 if (l1
< l2
) return -1;
119 if (l1
> l2
) return 1;
123 int hpfs_is_name_long(unsigned char *name
, unsigned len
)
126 for (i
= 0; i
< len
&& name
[i
] != '.'; i
++)
127 if (no_dos_char(name
[i
])) return 1;
128 if (!i
|| i
> 8) return 1;
129 if (i
== len
) return 0;
130 for (j
= i
+ 1; j
< len
; j
++)
131 if (name
[j
] == '.' || no_dos_char(name
[i
])) return 1;
135 /* OS/2 clears dots and spaces at the end of file name, so we have to */
137 void hpfs_adjust_length(unsigned char *name
, unsigned *len
)
140 if (*len
== 1 && name
[0] == '.') return;
141 if (*len
== 2 && name
[0] == '.' && name
[1] == '.') return;
142 while (*len
&& (name
[*len
- 1] == '.' || name
[*len
- 1] == ' '))