FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
MS-DOS-kernel/kernel/lfnapi.c at master · Programuserbash/MS-DOS-kernel · GitHub
Programuserbash
/
MS-DOS-kernel
Public
forked from
FDOS/kernel
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
MS-DOS-kernel
/
kernel
/
lfnapi.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
364 lines (312 loc) · 10.6 KB
Breadcrumbs
MS-DOS-kernel
/
kernel
/
lfnapi.c
Copy path
File metadata and controls
364 lines (312 loc) · 10.6 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/****************************************************************/
/* */
/* lfnapi.c */
/* */
/* Directory access functions for LFN helper API */
/* */
/****************************************************************/
#include
"portab.h"
#include
"globals.h"
#ifdef
VERSION_STRINGS
static
BYTE
*
lfnaidRcsId
=
"$Id: lfnapi.c 1389 2009-05-20 18:13:37Z bartoldeman $"
;
#endif
#ifdef
WITHLFNAPI
#define
RESERVED_FNODES
3
/* # of reserved fnodes for the kernel internal *
* usage. If something wrong happens with the *
* driver using helper API and it grabs all *
* possible fnodes, the kernel doesn't hang. */
/* All possible error codes, returned by directory access functions */
/* Note. SUCCESS is returned if all OK. */
#define
LHE_INVLDHNDL
-1
/* Invalid inode handle passed. */
#define
LHE_NOFREEHNDL
-2
/* Couldn't allocate another inode handle. */
#define
LHE_IOERROR
-3
/* Couldn't do I/O because of the lack of *
* memory or due to a physical damage. */
#define
LHE_INVLDDRV
-4
/* Invalid drive chosen. */
#define
LHE_DAMAGEDFS
-5
/* Damaged file system encountered. */
#define
LHE_NOSPACE
-6
/* There are no free clusters on drive. */
#define
LHE_SEEK
-7
/* Attempt to read beyound the end of the dir. */
#define
lfn
(
fnp
) ((struct lfn_entry FAR *)&(fnp->f_dir))
#define
CHARS_IN_LFN_ENTRY
13
#define
UNICODE_FILLER
0xffff
COUNT
ufstrlen
(
REG
UNICODE
FAR
*
);
/* fstrlen for UNICODE strings */
UBYTE
lfn_checksum
(
UBYTE
FAR
*
);
COUNT
extend_dir
(
f_node_ptr
);
BOOL
lfn_to_unicode
(
UNICODE
FAR
*
*
name
,
struct
lfn_entry
FAR
*
lep
);
VOID
unicode_to_lfn
(
UNICODE
FAR
*
*
name
,
struct
lfn_entry
FAR
*
lep
);
/* Description.
* Allocates internal fnode and returns it's handle.
* Return value.
* LHE_NOFREEHNDL, LHE_INVLDDRV
* >= 0 - handle of the allocated fnode.
*/
COUNT
lfn_allocate_inode
(
VOID
)
{
f_node_ptr
fnp
=
get_f_node
(
&
fnode
[
0
]);
struct
dpb
FAR
*
dpbp
;
COUNT
handle
;
if
(
fnp
==
0
)
return
LHE_NOFREEHNDL
;
handle
=
xlt_fnp
(
fnp
);
/* Check if there is at least # RESERVED_FNODES left for the kernel */
if
(
f_nodes_cnt
-
handle
<
RESERVED_FNODES
)
{
release_f_node
(
fnp
);
return
LHE_NOFREEHNDL
;
}
/* Check that default drive is a block device */
dpbp
=
get_dpb
(
default_drive
);
if
(
dpbp
==
0
)
{
release_f_node
(
fnp
);
return
LHE_INVLDDRV
;
}
fnp
->
f_dpb
=
dpbp
;
if
(
media_check
(
dpbp
)
<
0
)
{
release_f_node
(
fnp
);
return
LHE_INVLDDRV
;
}
return
handle
;
}
/* Description.
* Free allocated internal fnode.
* Return value.
* SUCCESS, LHE_INVLDHNDL
*/
COUNT
lfn_free_inode
(
COUNT
handle
)
{
f_node_ptr
fnp
=
xlt_fd
(
handle
);
if
(
fnp
==
0
||
fnp
->
f_count
<=
0
)
return
LHE_INVLDHNDL
;
dir_close
(
fnp
);
return
SUCCESS
;
}
/* Description.
* Initialize internal fnode, so that it'll point to the directory entry
* at "diroff" entry offset from the start of the directory with the "dirstart"
* starting cluster.
* Return value.
* SUCCESS, LHE_INVLDHNDL
*/
COUNT
lfn_setup_inode
(
COUNT
handle
,
ULONG
dirstart
,
ULONG
diroff
)
{
f_node_ptr
fnp
=
xlt_fd
(
handle
);
if
(
fnp
==
0
||
fnp
->
f_count
<=
0
)
return
LHE_INVLDHNDL
;
dir_init_fnode
(
fnp
, (
CLUSTER
)
dirstart
);
fnp
->
f_diroff
=
diroff
;
return
SUCCESS
;
}
/* Description.
* Create LFN directory entries for the long name "lip->l_name", followed
* by the SFN entry with raw image "lip->l_dir". The "lip->l_diroff" points
* to the SFN entry on return.
* The internal fnode is released on fatal error, except LHE_INVLDHNDL of
* course.
* Return value.
* SUCCESS, LHE_INVLDHNDL, LHE_IOERROR, LHE_NOSPACE
*/
COUNT
lfn_create_entries
(
COUNT
handle
,
lfn_inode_ptr
lip
)
{
f_node_ptr
fnp
=
xlt_fd
(
handle
);
COUNT
entries_needed
,
free_entries
,
i
,
rc
;
UNICODE
FAR
*
lfn_name
=
lip
->
l_name
;
UBYTE
id
=
1
,
sfn_checksum
=
lfn_checksum
(
lip
->
l_dir
.
dir_name
);
unsigned
sfn_offset
;
if
(
fnp
==
0
||
fnp
->
f_count
<=
0
)
return
LHE_INVLDHNDL
;
entries_needed
=
(
ufstrlen
(
lfn_name
)
+
CHARS_IN_LFN_ENTRY
-
1
)
/
CHARS_IN_LFN_ENTRY
+
1
;
/* We want to create SFN entry too */
/* Scan the directory from the very begining for the free directory entries */
lfn_setup_inode
(
handle
,
fnp
->
f_dirstart
,
0
);
free_entries
=
0
;
while
(TRUE)
{
rc
=
dir_read
(
fnp
);
if
(
rc
==
0
||
fnp
->
f_dir
.
dir_name
[
0
]
==
DELETED
)
{
free_entries
++
;
if
(
free_entries
==
entries_needed
)
break
;
}
else
if
(
rc
==
DE_BLKINVLD
)
{
dir_close
(
fnp
);
return
LHE_IOERROR
;
}
else
if
(
rc
==
DE_SEEK
)
{
if
(
extend_dir
(
fnp
)
!=
SUCCESS
)
return
LHE_NOSPACE
;
/* fnp points to the first free dir entry on return from extend_dir,
* so we go to previous entry to read this free entry on next cycle */
fnp
->
f_diroff
--
;
}
else
free_entries
=
0
;
/* rc == 1 here => we've read some sfn entry */
}
sfn_offset
=
fnp
->
f_diroff
;
fnp
->
f_flags
.
f_dmod
=
TRUE;
/* Write SFN entry */
fmemcpy
(
&
fnp
->
f_dir
,
&
lip
->
l_dir
,
sizeof
(
struct
dirent
));
dir_write
(
fnp
);
fnp
->
f_diroff
--
;
/* Go in the reverse direction and create LFN entries */
for
(
i
=
0
;
i
<
entries_needed
-
1
;
i
++
,
id
++
)
{
/* If this is the last LFN entry mark it's as those (6th bit is on) */
if
(
i
==
(
entries_needed
-
2
))
id
|=
0x40
;
lfn_name
=
&
lip
->
l_name
[
i
*
CHARS_IN_LFN_ENTRY
];
unicode_to_lfn
(
&
lfn_name
,
lfn
(
fnp
));
lfn
(
fnp
)
->
lfn_checksum
=
sfn_checksum
;
lfn
(
fnp
)
->
lfn_id
=
id
;
fnp
->
f_dir
.
dir_attrib
=
D_LFN
;
if
(!
dir_write
(
fnp
))
return
LHE_IOERROR
;
fnp
->
f_diroff
--
;
}
fnp
->
f_flags
.
f_dmod
=
FALSE;
fnp
->
f_diroff
=
sfn_offset
;
return
SUCCESS
;
}
/* Description.
* Read next consequitve long file name. The LFN is stored into the
* "lip->l_name" in unicode and the corresponding SFN entry raw image into the
* "lip->l_dir". If directory entry being read is a 8.3 file name, then
* it's image is stored into the "lip->l_dir" and "lip->l_name" has zero
* length, i.e. "lip->l_name[0]" == 0.
* Return value.
* SUCCESS, LHE_INVLDHNDL, LHE_IOERROR, LHE_SEEK, LHE_DAMAGEDFS
*/
COUNT
lfn_dir_read
(
COUNT
handle
,
lfn_inode_ptr
lip
)
{
COUNT
rc
;
UBYTE
id
=
1
,
real_id
;
UNICODE
FAR
*
lfn_name
=
lip
->
l_name
;
UWORD
sfn_diroff
;
BOOL
name_tail
;
f_node_ptr
fnp
=
xlt_fd
(
handle
);
if
(
fnp
==
0
||
fnp
->
f_count
<=
0
)
return
LHE_INVLDHNDL
;
/* Scan a directory for the next valid SFN entry */
while
(TRUE)
{
rc
=
dir_read
(
fnp
);
if
(
rc
==
DE_SEEK
)
return
LHE_SEEK
;
else
if
(
rc
==
DE_BLKINVLD
)
return
LHE_IOERROR
;
if
(
fnp
->
f_dir
.
dir_name
[
0
]
!=
DELETED
&&
fnp
->
f_dir
.
dir_attrib
!=
D_LFN
)
{
fmemcpy
(
&
lip
->
l_dir
,
&
fnp
->
f_dir
,
sizeof
(
struct
dirent
));
sfn_diroff
=
fnp
->
f_diroff
;
break
;
}
}
/* Go in the reverse direction and find the LFN entries corresponding to
* the found SFN entry */
while
(TRUE)
{
if
(
fnp
->
f_diroff
==
0
)
break
;
fnp
->
f_diroff
-=
2
;
rc
=
dir_read
(
fnp
);
if
(
rc
==
DE_BLKINVLD
)
return
LHE_IOERROR
;
if
(
fnp
->
f_dir
.
dir_name
[
0
]
==
DELETED
||
fnp
->
f_dir
.
dir_attrib
!=
D_LFN
)
break
;
real_id
=
lfn
(
fnp
)
->
lfn_id
;
if
((
real_id
&
0x3f
)
>
20
)
return
LHE_DAMAGEDFS
;
name_tail
=
lfn_to_unicode
(
&
lfn_name
,
lfn
(
fnp
));
if
(
real_id
&
0x40
)
{
if
((
id
|
0x40
)
!=
real_id
)
return
LHE_DAMAGEDFS
;
break
;
}
else
{
if
(
name_tail
||
real_id
!=
id
||
lfn
(
fnp
)
->
lfn_checksum
!=
lfn_checksum
(
lip
->
l_dir
.
dir_name
))
return
LHE_DAMAGEDFS
;
}
id
++
;
}
*
lfn_name
=
0
;
/* Terminate LFN string */
fnp
->
f_diroff
=
lip
->
l_diroff
=
sfn_diroff
;
return
SUCCESS
;
}
/* Description.
* Writes directory entry pointed by internal fnode to disk.
* The fnode is released on error.
* Return value.
* SUCCESS, LHE_INVLDHNDL, LHE_IOERROR.
*/
COUNT
lfn_dir_write
(
COUNT
handle
)
{
f_node_ptr
fnp
=
xlt_fd
(
handle
);
if
(
fnp
==
0
||
fnp
->
f_count
<=
0
)
return
LHE_INVLDHNDL
;
fnp
->
f_flags
.
f_dmod
=
TRUE;
if
(!
dir_write
(
fnp
))
return
LHE_IOERROR
;
fnp
->
f_flags
.
f_dmod
=
FALSE;
return
SUCCESS
;
}
/*********************************************************************/
/* Miscellaneous functions. These functions are not part of the API. */
/*********************************************************************/
/* Description.
* Copy the block of "count" unicode characters from source pointed by
* "sptr" to destination pointed by "dptr". The trailing characters of
* destination are filled with "UNICODE_FILLER".
* Return value.
* TRUE - The source string is too short, trailing characters are filled
* with "UNICODE_FILLER".
* FALSE - The unicode strings have the same size, no filling occured.
*/
BOOL
transfer_unicode
(
UNICODE
FAR
*
*
dptr
,
UNICODE
FAR
*
*
sptr
,
COUNT
count
)
{
COUNT
j
;
BOOL
found_zerro
=
FALSE;
for
(
j
=
0
;
j
<
count
;
j
++
, (
*
dptr
)
++
, (
*
sptr
)
++
)
{
if
(
found_zerro
)
*
*
dptr
=
UNICODE_FILLER
;
else
*
*
dptr
=
*
*
sptr
;
if
(
*
*
sptr
==
0
)
found_zerro
=
TRUE;
}
return
found_zerro
;
}
/* Description.
* Retrieve the LFN string chunk from the directory entry "lep" and store it
* to the "name" unicode string.
* Return value.
* TRUE - The LFN string chunk contains zero character.
* FALSE - Doesn't terminate with zero.
*/
BOOL
lfn_to_unicode
(
UNICODE
FAR
*
*
name
,
struct
lfn_entry
FAR
*
lep
)
{
UNICODE
FAR
*
ptr
;
ptr
=
lep
->
lfn_name0_4
;
if
(
transfer_unicode
(
name
,
&
ptr
,
5
))
return
TRUE;
ptr
=
lep
->
lfn_name5_10
;
if
(
transfer_unicode
(
name
,
&
ptr
,
6
))
return
TRUE;
ptr
=
lep
->
lfn_name11_12
;
if
(
transfer_unicode
(
name
,
&
ptr
,
2
))
return
TRUE;
return
FALSE;
}
/* Description.
*/
VOID
unicode_to_lfn
(
UNICODE
FAR
*
*
name
,
struct
lfn_entry
FAR
*
lep
)
{
UNICODE
FAR
*
ptr
;
ptr
=
lep
->
lfn_name0_4
;
transfer_unicode
(
&
ptr
,
name
,
5
);
ptr
=
lep
->
lfn_name5_10
;
transfer_unicode
(
&
ptr
,
name
,
6
);
ptr
=
lep
->
lfn_name11_12
;
transfer_unicode
(
&
ptr
,
name
,
2
);
}
/* Calculate checksum for the 8.3 name */
UBYTE
lfn_checksum
(
UBYTE
FAR
*
sfn_name
)
{
UBYTE
sum
;
COUNT
i
;
for
(
sum
=
0
,
i
=
11
;
--
i
>=
0
;
sum
+=
*
sfn_name
++
)
sum
=
(
sum
<<
7
) | (
sum
>>
1
);
return
sum
;
}
COUNT
ufstrlen
(
REG
UNICODE
FAR
*
s
)
{
REG
COUNT
cnt
=
0
;
while
(
*
s
++
!=
0
)
++
cnt
;
return
cnt
;
}
#endif
Back
|
FazBrowse Home
|
New Git URL