1 /* $NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp $ */
4 * Copyright (C) 1995, 1997 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1997 TooLs GmbH.
7 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * Written by Paul Popelka (paulp@uts.amdahl.com)
37 * You can do anything you want with this software, just don't say you wrote
38 * it, and don't remove this notice.
40 * This software is provided "as is".
42 * The author supplies this software to be publicly redistributed on the
43 * understanding that the author is not responsible for the correct
44 * functioning of this software in any circumstances and is not liable for
45 * any damages caused by this software.
50 #if HAVE_NBTOOL_CONFIG_H
51 #include "nbtool_config.h"
54 #include <sys/cdefs.h>
55 __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp $");
58 * System include files.
60 #include <sys/param.h>
63 #include <sys/dirent.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/vnode.h>
71 #include <sys/queue.h>
73 #include <dev/clock_subr.h>
76 * MSDOSFS include files.
78 #include <fs/msdosfs/direntry.h>
79 #include <fs/msdosfs/denode.h>
82 * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
83 * interval there were 8 regular years and 2 leap years.
85 #define DOSBIASYEAR 1980
86 #define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
88 * msdos fs can not store dates beyound the year 2234
90 #define DOSMAXYEAR ((DD_YEAR_MASK >> DD_YEAR_SHIFT) + DOSBIASYEAR)
93 * Convert the unix version of time to dos's idea of time to be used in
94 * file timestamps. The passed in unix time is assumed to be in GMT.
97 unix2dostime(const struct timespec
*tsp
, int gmtoff
, u_int16_t
*ddp
, u_int16_t
*dtp
, u_int8_t
*dhp
)
100 struct clock_ymdhms ymd
;
102 t
= tsp
->tv_sec
+ gmtoff
; /* time zone correction */
105 * DOS timestamps can not represent dates before 1980.
107 if (t
< SECONDSTO1980
)
108 goto invalid_dos_date
;
111 * DOS granularity is 2 seconds
116 * Convert to year/month/day/.. format
118 clock_secs_to_ymdhms(t
, &ymd
);
119 if (ymd
.dt_year
> DOSMAXYEAR
)
120 goto invalid_dos_date
;
123 * Now transform to DOS format
125 *ddp
= (ymd
.dt_day
<< DD_DAY_SHIFT
)
126 + (ymd
.dt_mon
<< DD_MONTH_SHIFT
)
127 + ((ymd
.dt_year
- DOSBIASYEAR
) << DD_YEAR_SHIFT
);
129 *dhp
= (tsp
->tv_sec
& 1) * 100 + tsp
->tv_nsec
/ 10000000;
131 *dtp
= (((t
/ 2) % 30) << DT_2SECONDS_SHIFT
)
132 + (((t
/ 60) % 60) << DT_MINUTES_SHIFT
)
133 + (((t
/ 3600) % 24) << DT_HOURS_SHIFT
);
145 * Convert from dos' idea of time to unix'. This will probably only be
146 * called from the stat(), and fstat() system calls and so probably need
147 * not be too efficient.
150 dos2unixtime(u_int dd
, u_int dt
, u_int dh
, int gmtoff
, struct timespec
*tsp
)
153 struct clock_ymdhms ymd
;
157 * Uninitialized field, return the epoch.
164 memset(&ymd
, 0, sizeof(ymd
));
165 ymd
.dt_year
= ((dd
& DD_YEAR_MASK
) >> DD_YEAR_SHIFT
) + 1980 ;
166 ymd
.dt_mon
= ((dd
& DD_MONTH_MASK
) >> DD_MONTH_SHIFT
);
167 ymd
.dt_day
= ((dd
& DD_DAY_MASK
) >> DD_DAY_SHIFT
);
168 ymd
.dt_hour
= (dt
& DT_HOURS_MASK
) >> DT_HOURS_SHIFT
;
169 ymd
.dt_min
= (dt
& DT_MINUTES_MASK
) >> DT_MINUTES_SHIFT
;
170 ymd
.dt_sec
= ((dt
& DT_2SECONDS_MASK
) >> DT_2SECONDS_SHIFT
) * 2;
172 seconds
= clock_ymdhms_to_secs(&ymd
);
174 tsp
->tv_sec
= seconds
;
175 tsp
->tv_sec
-= gmtoff
; /* time zone correction */
176 tsp
->tv_nsec
= (dh
% 100) * 10000000;
181 0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */
182 0, 0, 0, 0, 0, 0, 0, 0, /* 08-0f */
183 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */
184 0, 0, 0, 0, 0, 0, 0, 0, /* 18-1f */
185 0, '!', 0, '#', '$', '%', '&', '\'', /* 20-27 */
186 '(', ')', 0, '+', 0, '-', 0, 0, /* 28-2f */
187 '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
188 '8', '9', 0, 0, 0, 0, 0, 0, /* 38-3f */
189 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */
190 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */
191 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */
192 'X', 'Y', 'Z', 0, 0, 0, '^', '_', /* 58-5f */
193 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 60-67 */
194 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 68-6f */
195 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 70-77 */
196 'X', 'Y', 'Z', '{', 0, '}', '~', 0, /* 78-7f */
197 0, 0, 0, 0, 0, 0, 0, 0, /* 80-87 */
198 0, 0, 0, 0, 0, 0, 0, 0, /* 88-8f */
199 0, 0, 0, 0, 0, 0, 0, 0, /* 90-97 */
200 0, 0, 0, 0, 0, 0, 0, 0, /* 98-9f */
201 0, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* a0-a7 */
202 0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* a8-af */
203 0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* b0-b7 */
204 0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* b8-bf */
205 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* c0-c7 */
206 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* c8-cf */
207 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* d0-d7 */
208 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* d8-df */
209 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* e0-e7 */
210 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* e8-ef */
211 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6, /* f0-f7 */
212 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98, /* f8-ff */
217 '?', '?', '?', '?', '?', '?', '?', '?', /* 00-07 */
218 '?', '?', '?', '?', '?', '?', '?', '?', /* 08-0f */
219 '?', '?', '?', '?', '?', '?', '?', '?', /* 10-17 */
220 '?', '?', '?', '?', '?', '?', '?', '?', /* 18-1f */
221 ' ', '!', '"', '#', '$', '%', '&', '\'', /* 20-27 */
222 '(', ')', '*', '+', ',', '-', '.', '/', /* 28-2f */
223 '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
224 '8', '9', ':', ';', '<', '=', '>', '?', /* 38-3f */
225 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */
226 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */
227 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */
228 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', /* 58-5f */
229 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 60-67 */
230 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 68-6f */
231 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 70-77 */
232 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, /* 78-7f */
233 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, /* 80-87 */
234 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, /* 88-8f */
235 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, /* 90-97 */
236 0xff, 0xd6, 0xdc, 0xf8, 0xa3, 0xd8, 0xd7, '?', /* 98-9f */
237 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, /* a0-a7 */
238 0xbf, 0xae, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb, /* a8-af */
239 '?', '?', '?', '?', '?', 0xc1, 0xc2, 0xc0, /* b0-b7 */
240 0xa9, '?', '?', '?', '?', 0xa2, 0xa5, '?', /* b8-bf */
241 '?', '?', '?', '?', '?', '?', 0xe3, 0xc3, /* c0-c7 */
242 '?', '?', '?', '?', '?', '?', '?', 0xa4, /* c8-cf */
243 0xf0, 0xd0, 0xca, 0xcb, 0xc8, '?', 0xcd, 0xce, /* d0-d7 */
244 0xcf, '?', '?', '?', '?', 0xa6, 0xcc, '?', /* d8-df */
245 0xd3, 0xdf, 0xd4, 0xd2, 0xf5, 0xd5, 0xb5, 0xfe, /* e0-e7 */
246 0xde, 0xda, 0xdb, 0xd9, 0xfd, 0xdd, 0xaf, 0x3f, /* e8-ef */
247 0xad, 0xb1, '?', 0xbe, 0xb6, 0xa7, 0xf7, 0xb8, /* f0-f7 */
248 0xb0, 0xa8, 0xb7, 0xb9, 0xb3, 0xb2, '?', '?', /* f8-ff */
253 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */
254 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */
255 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */
256 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */
257 ' ', '!', '"', '#', '$', '%', '&', '\'', /* 20-27 */
258 '(', ')', '*', '+', ',', '-', '.', '/', /* 28-2f */
259 '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
260 '8', '9', ':', ';', '<', '=', '>', '?', /* 38-3f */
261 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 40-47 */
262 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 48-4f */
263 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 50-57 */
264 'x', 'y', 'z', '[', '\\', ']', '^', '_', /* 58-5f */
265 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 60-67 */
266 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 68-6f */
267 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 70-77 */
268 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, /* 78-7f */
269 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */
270 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */
271 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */
272 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */
273 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */
274 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */
275 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */
276 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */
277 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */
278 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */
279 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */
280 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */
281 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */
282 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */
283 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */
284 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */
288 * DOS filenames are made of 2 parts, the name part and the extension part.
289 * The name part is 8 characters long and the extension part is 3
290 * characters long. They may contain trailing blanks if the name or
291 * extension are not long enough to fill their respective fields.
295 * Convert a DOS filename to a unix filename. And, return the number of
296 * characters in the resulting unix filename excluding the terminating
300 dos2unixfn(u_char dn
[11], u_char
*un
, int lower
)
307 * If first char of the filename is SLOT_E5 (0x05), then the real
308 * first char of the filename should be 0xe5. But, they couldn't
309 * just have a 0xe5 mean 0xe5 because that is used to mean a freed
310 * directory slot. Another dos quirk.
316 *un
++ = lower
? u2l
[c
] : c
;
319 * Copy the rest into the unix filename string, ignoring
323 for (j
=7; (j
>= 0) && (dn
[j
] == ' '); j
--)
326 for (i
= 1; i
<= j
; i
++) {
328 *un
++ = lower
? u2l
[c
] : c
;
334 * Now, if there is an extension then put in a period and copy in
340 for (i
= 0; i
< 3 && *dn
!= ' '; i
++) {
342 *un
++ = lower
? u2l
[c
] : c
;
352 * Convert a unix filename to a DOS filename according to Win95 rules.
353 * If applicable and gen is not 0, it is inserted into the converted
354 * filename as a generation number.
356 * 0 if name couldn't be converted
357 * 1 if the converted name is the same as the original
358 * (no long filename entry necessary for Win95)
359 * 2 if conversion was successful
360 * 3 if conversion was successful and generation number was inserted
363 unix2dosfn(const u_char
*un
, u_char dn
[12], int unlen
, u_int gen
)
367 const u_char
*cp
, *dp
, *dp1
;
368 u_char gentext
[6], *wcp
;
372 * Fill the dos filename string with blanks. These are DOS's pad
375 for (i
= 0; i
< 11; i
++)
380 * The filenames "." and ".." are handled specially, since they
381 * don't follow dos filename rules.
383 if (un
[0] == '.' && unlen
== 1) {
387 if (un
[0] == '.' && un
[1] == '.' && unlen
== 2) {
394 * Filenames with only blanks and dots are not allowed!
396 for (cp
= un
, i
= unlen
; --i
>= 0; cp
++)
397 if (*cp
!= ' ' && *cp
!= '.')
403 * Now find the extension
404 * Note: dot as first char doesn't start extension
405 * and trailing dots and blanks are ignored
408 for (cp
= un
+ 1, i
= unlen
- 1; --i
>= 0;) {
431 l
= unlen
- (dp
- un
);
432 for (i
= 0, j
= 8; i
< l
&& j
< 11; i
++, j
++) {
433 if (dp
[i
] != (dn
[j
] = unix2dos
[dp
[i
]])
445 for (dp
= cp
; *--dp
== ' ' || *dp
== '.';);
449 shortlen
= (dp
- un
) <= 8;
452 * Now convert the rest of the name
454 for (i
= j
= 0; un
< dp
&& j
< 8; i
++, j
++, un
++) {
455 if ((*un
== ' ') && shortlen
)
458 dn
[j
] = unix2dos
[*un
];
470 * If we didn't have any chars in filename,
477 * The first character cannot be E5,
478 * because that means a deleted entry
484 * If there wasn't any char dropped,
485 * there is no place for generation numbers
494 * Now insert the generation number into the filename part
496 for (wcp
= gentext
+ sizeof(gentext
); wcp
> gentext
&& gen
; gen
/= 10)
497 *--wcp
= gen
% 10 + '0';
500 for (i
= 8; dn
[--i
] == ' ';);
502 if (gentext
+ sizeof(gentext
) - wcp
+ 1 > 8 - i
)
503 i
= 8 - (gentext
+ sizeof(gentext
) - wcp
+ 1);
505 while (wcp
< gentext
+ sizeof(gentext
))
511 * Create a Win95 long name directory entry
512 * Note: assumes that the filename is valid,
513 * i.e. doesn't consist solely of blanks and dots
516 unix2winfn(const u_char
*un
, int unlen
, struct winentry
*wep
, int cnt
, int chksum
)
523 * Drop trailing blanks and dots
525 for (cp
= un
+ unlen
; *--cp
== ' ' || *cp
== '.'; unlen
--);
527 un
+= (cnt
- 1) * WIN_CHARS
;
528 unlen
-= (cnt
- 1) * WIN_CHARS
;
531 * Initialize winentry to some useful default
533 for (wcp
= (u_int8_t
*)wep
, i
= sizeof(*wep
); --i
>= 0; *wcp
++ = 0xff);
535 wep
->weAttributes
= ATTR_WIN95
;
536 wep
->weReserved1
= 0;
537 wep
->weChksum
= chksum
;
538 wep
->weReserved2
= 0;
541 * Now convert the filename parts
543 for (wcp
= wep
->wePart1
, i
= sizeof(wep
->wePart1
)/2; --i
>= 0;) {
549 for (wcp
= wep
->wePart2
, i
= sizeof(wep
->wePart2
)/2; --i
>= 0;) {
555 for (wcp
= wep
->wePart3
, i
= sizeof(wep
->wePart3
)/2; --i
>= 0;) {
562 wep
->weCnt
|= WIN_LAST
;
568 wep
->weCnt
|= WIN_LAST
;
573 * Compare our filename to the one in the Win95 entry
574 * Returns the checksum or -1 if no match
577 winChkName(const u_char
*un
, int unlen
, struct winentry
*wep
, int chksum
)
583 * First compare checksums
585 if (wep
->weCnt
&WIN_LAST
)
586 chksum
= wep
->weChksum
;
587 else if (chksum
!= wep
->weChksum
)
593 * Offset of this entry
595 i
= ((wep
->weCnt
&WIN_CNT
) - 1) * WIN_CHARS
;
597 if ((unlen
-= i
) < 0)
601 * Ignore redundant winentries (those with only \0\0 on start in them).
602 * An appearance of such entry is a bug; unknown if in NetBSD msdosfs
606 if (wep
->wePart1
[0] == '\0' && wep
->wePart1
[1] == '\0')
612 if ((wep
->weCnt
&WIN_LAST
) && unlen
> WIN_CHARS
)
616 * Compare the name parts
618 for (cp
= wep
->wePart1
, i
= sizeof(wep
->wePart1
)/2; --i
>= 0;) {
624 if (u2l
[*cp
++] != u2l
[*un
++] || *cp
++)
627 for (cp
= wep
->wePart2
, i
= sizeof(wep
->wePart2
)/2; --i
>= 0;) {
633 if (u2l
[*cp
++] != u2l
[*un
++] || *cp
++)
636 for (cp
= wep
->wePart3
, i
= sizeof(wep
->wePart3
)/2; --i
>= 0;) {
642 if (u2l
[*cp
++] != u2l
[*un
++] || *cp
++)
649 * Convert Win95 filename to dirbuf.
650 * Returns the checksum or -1 if impossible
653 win2unixfn(struct winentry
*wep
, struct dirent
*dp
, int chksum
)
656 u_int8_t
*np
, *ep
= (u_int8_t
*)dp
->d_name
+ WIN_MAXLEN
;
659 if ((wep
->weCnt
&WIN_CNT
) > howmany(WIN_MAXLEN
, WIN_CHARS
)
660 || !(wep
->weCnt
&WIN_CNT
))
664 * First compare checksums
666 if (wep
->weCnt
&WIN_LAST
) {
667 chksum
= wep
->weChksum
;
669 * This works even though d_namlen is one byte!
672 dp
->d_namlen
= (wep
->weCnt
&WIN_CNT
) * WIN_CHARS
;
674 } else if (chksum
!= wep
->weChksum
)
680 * Offset of this entry
682 i
= ((wep
->weCnt
&WIN_CNT
) - 1) * WIN_CHARS
;
683 np
= (u_int8_t
*)dp
->d_name
+ i
;
686 * Convert the name parts
688 for (cp
= wep
->wePart1
, i
= sizeof(wep
->wePart1
)/2; --i
>= 0;) {
689 switch (*np
++ = *cp
++) {
692 dp
->d_namlen
-= sizeof(wep
->wePart2
)/2
693 + sizeof(wep
->wePart3
)/2 + i
+ 1;
701 * The size comparison should result in the compiler
702 * optimizing the whole if away
704 if (WIN_MAXLEN
% WIN_CHARS
< sizeof(wep
->wePart1
) / 2
712 for (cp
= wep
->wePart2
, i
= sizeof(wep
->wePart2
)/2; --i
>= 0;) {
713 switch (*np
++ = *cp
++) {
716 dp
->d_namlen
-= sizeof(wep
->wePart3
)/2 + i
+ 1;
724 * The size comparisons should be optimized away
726 if (WIN_MAXLEN
% WIN_CHARS
>= sizeof(wep
->wePart1
) / 2
727 && WIN_MAXLEN
% WIN_CHARS
< (sizeof(wep
->wePart1
) + sizeof(wep
->wePart2
)) / 2
735 for (cp
= wep
->wePart3
, i
= sizeof(wep
->wePart3
)/2; --i
>= 0;) {
736 switch (*np
++ = *cp
++) {
739 dp
->d_namlen
-= i
+ 1;
749 if (WIN_MAXLEN
% WIN_CHARS
>= (sizeof(wep
->wePart1
) + sizeof(wep
->wePart2
)) / 2
761 * Compute the checksum of a DOS filename for Win95 use
764 winChksum(u_int8_t
*name
)
769 for (s
= 0, i
= 11; --i
>= 0; s
+= *name
++)
770 s
= (s
<< 7)|(s
>> 1);
775 * Determine the number of slots necessary for Win95 names
778 winSlotCnt(const u_char
*un
, int unlen
)
780 for (un
+= unlen
; unlen
> 0; unlen
--)
781 if (*--un
!= ' ' && *un
!= '.')
783 if (unlen
> WIN_MAXLEN
)
785 return howmany(unlen
, WIN_CHARS
);