#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/dirent.h>
#include "direntry.h"
static uint16_t regyear[] = {
31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334, 365
};
static uint16_t leapyear[] = {
31, 60, 91, 121, 152, 182,
213, 244, 274, 305, 335, 366
};
static uint32_t lasttime;
static uint32_t lastday;
static uint16_t lastddate;
static uint16_t lastdtime;
static __inline u_int8_t find_lcode __P((u_int16_t code, u_int16_t *u2w));
__private_extern__ int32_t msdos_secondsWest = 0;
__private_extern__ void
unix2dostime(tsp, ddp, dtp, dhp)
struct timespec *tsp;
u_int16_t *ddp;
u_int16_t *dtp;
u_int8_t *dhp;
{
uint32_t t;
uint32_t days;
uint32_t inc;
uint32_t year;
uint32_t month;
uint16_t *months;
t = tsp->tv_sec - msdos_secondsWest;
t &= ~1;
if (lasttime != t) {
lasttime = t;
lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
+ (((t / 60) % 60) << DT_MINUTES_SHIFT)
+ (((t / 3600) % 24) << DT_HOURS_SHIFT);
days = t / (24 * 60 * 60);
if (days != lastday) {
lastday = days;
for (year = 1970;; year++) {
inc = year & 0x03 ? 365 : 366;
if (days < inc)
break;
days -= inc;
}
months = year & 0x03 ? regyear : leapyear;
for (month = 0; days >= months[month]; month++)
;
if (month > 0)
days -= months[month - 1];
lastddate = ((days + 1) << DD_DAY_SHIFT)
+ ((month + 1) << DD_MONTH_SHIFT);
if (year > 1980)
lastddate += (year - 1980) << DD_YEAR_SHIFT;
}
}
if (dtp)
*dtp = lastdtime;
if (dhp)
*dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
*ddp = lastddate;
}
#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
static uint16_t lastdosdate;
static uint32_t lastseconds;
__private_extern__ void
dos2unixtime(dd, dt, dh, tsp)
u_int dd;
u_int dt;
u_int dh;
struct timespec *tsp;
{
uint32_t seconds;
uint32_t month;
uint32_t year;
uint32_t days;
uint16_t *months;
if (dd == 0) {
tsp->tv_sec = 0;
tsp->tv_nsec = 0;
return;
}
seconds = (((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) << 1)
+ ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
+ ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
+ dh / 100;
if (lastdosdate != dd) {
lastdosdate = dd;
days = 0;
year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
days = year * 365;
days += year / 4 + 1;
if ((year & 0x03) == 0)
days--;
months = year & 0x03 ? regyear : leapyear;
month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
if (month < 1 || month > 12) {
printf("dos2unixtime(): month value out of range (%d)\n",
month);
month = 1;
}
if (month > 1)
days += months[month - 2];
days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
}
tsp->tv_sec = seconds + lastseconds + msdos_secondsWest;
tsp->tv_nsec = (dh % 100) * 10000000;
}
static u_char
unilsb2dos[256] = {
0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
2, 0x21, 1, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 1, 1, 1, 0x2d, 2, 0,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 1, 1, 1, 1, 1, 1,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 1, 1, 1, 0x5e, 0x5f,
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x7b, 1, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};
static u_char
unipunct2dos[48] = {
1, 1, 1, 0x96, 0x97, 1, 1, 1,
0x91, 0x92, 0x82, 1, 0x93, 0x94, 0x84, 1,
0x86, 0x87, 0x95, 1, 1, 1, 0x85, 1,
1, 1, 1, 1, 1, 1, 1, 1,
0x89, 1, 1, 1, 1, 1, 1, 1,
1, 0x8B, 0x9B, 1, 1, 1, 1, 1
};
__private_extern__ u_int16_t
dos2unicode[32] = {
0x20AC, 0x003f, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x003f, 0x017D, 0x003f,
0x003f, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x003f, 0x017E, 0x0178,
};
__private_extern__ u_char
l2u[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};
enum {
CASE_LOWER = 1,
CASE_UPPER = 2,
CASE_LONG = 4,
};
static u_char
ascii_case[128] = {
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
};
#if 0
static u_int16_t
mac2sfm[128] = {
0x0, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
0x20, 0x21, 0xf020, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0xf021, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0xf022, 0x3b, 0xf023, 0x3d, 0xf024, 0xf025,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0xf026, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0xf027, 0x7d, 0x7e, 0x7f,
};
#define MAX_MAC2SFM 0x80
#define MAX_SFM2MAC 0x29
#define SFMCODE_PREFIX_MASK 0xf000
static u_char
sfm2mac[42] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x22, 0x2a, 0x3a, 0x3c, 0x3e, 0x3f, 0x5c, 0x7c,
0x20, 0x2e,
};
#endif
__private_extern__ u_char
unicode2dos(uc)
u_int16_t uc;
{
if (uc < 0x100)
return (unilsb2dos[uc]);
if (uc > 0x2122)
return (1);
if (uc >= 0x2010 && uc <= 0x203F)
return (unipunct2dos[uc - 0x2010]);
if (uc >= 0x0152 && uc <= 0x02DC)
switch (uc) {
case 0x0152:
return (0x8C);
case 0x0153:
return (0x9C);
case 0x0160:
return (0x8A);
case 0x0161:
return (0x9A);
case 0x0178:
return (0x9F);
case 0x017D:
return (0x8E);
case 0x017E:
return (0x9E);
case 0x0192:
return (0x83);
case 0x02C6:
return (0x88);
case 0x02DC:
return (0x98);
default:
return (1);
}
if (uc == 0x20AC)
return (0x80);
if (uc == 0x2122)
return (0x99);
return (1);
}
__private_extern__ size_t
dos2unicodefn(u_char dn[SHORT_NAME_LEN], u_int16_t *un, int lower)
{
int i;
u_char dc;
int unichars = 0;
for (i = 0; i < 8; i++) {
dc = *dn++;
if (i == 0 && dc == SLOT_E5)
dc = 0xe5;
if (lower & LCASE_BASE)
dc = l2u[dc];
un[unichars++] = (dc < 0x80 || dc > 0x9F ? (u_int16_t)dc : dos2unicode[dc - 0x80]);
}
while (unichars > 0 && un[unichars-1]==' ')
{
-- unichars;
}
un[unichars++] = '.';
for (i = 0; i < 3; i++) {
dc = *dn++;
if (lower & LCASE_EXT)
dc = l2u[dc];
un[unichars++] = (dc < 0x80 || dc > 0x9F ? (u_int16_t)dc : dos2unicode[dc - 0x80]);
}
for (i=0; i<3 && un[unichars-1]==' '; ++i)
{
--unichars;
}
if (i==3)
--unichars;
return unichars;
}
__private_extern__ int
unicode2dosfn(const u_int16_t *un, u_char dn[SHORT_NAME_LEN], int unlen, u_int gen, u_int8_t *lower_case)
{
int i, j, l;
int conv = 1;
const u_int16_t *cp, *dp, *dp1;
u_char gentext[6], *wcp;
u_int16_t c;
int case_flags;
*lower_case = 0;
memset(dn, ' ', SHORT_NAME_LEN);
if (unlen == 1 && un[0] == '.') {
dn[0] = '.';
return gen <= 1;
}
if (unlen == 2 && un[0] == '.' && un[1] == '.') {
dn[0] = '.';
dn[1] = '.';
return gen <= 1;
}
for (cp = un, i = unlen; --i >= 0; cp++)
if (unicode2dos(*cp) == 0)
return 0;
dp = dp1 = 0;
for (cp = un + 1, i = unlen - 1; --i >= 0;) {
switch (*cp++) {
case '.':
if (!dp1)
dp1 = cp;
break;
default:
if (dp1)
dp = dp1;
dp1 = 0;
break;
}
}
if (dp) {
if (dp1)
l = dp1 - dp;
else
l = unlen - (dp - un);
for (case_flags = i = 0, j = 8; i < l && j < SHORT_NAME_LEN; i++, j++) {
c = dp[i];
if (c < 0x80)
case_flags |= ascii_case[c];
else
case_flags |= CASE_LONG;
if (c < 0x100)
c = l2u[c];
c = unicode2dos(c);
dn[j] = c;
if (c == 1) {
conv = 3;
dn[j] = '_';
}
if (c == 2) {
conv = 3;
dn[j--] = ' ';
}
}
if ((case_flags & CASE_LONG) != 0 && conv != 3)
conv = 2;
if (conv == 1) {
if ((case_flags & (CASE_LOWER | CASE_UPPER)) == (CASE_LOWER | CASE_UPPER))
conv = 2;
else if (case_flags & CASE_LOWER)
*lower_case |= LCASE_EXT;
}
if (i < l)
conv = 3;
dp--;
} else {
dp = cp;
}
for (case_flags = i = j = 0; un < dp && j < 8; i++, j++, un++) {
c = *un;
if (c < 0x80)
case_flags |= ascii_case[c];
else
case_flags |= CASE_LONG;
if (c < 0x100)
c = l2u[c];
c = unicode2dos(c);
dn[j] = c;
if (c == 1) {
conv = 3;
dn[j] = '_';
}
if (c == 2) {
conv = 3;
dn[j--] = ' ';
}
}
if ((case_flags & CASE_LONG) != 0 && conv != 3)
conv = 2;
if (conv == 1) {
if ((case_flags & (CASE_LOWER | CASE_UPPER)) == (CASE_LOWER | CASE_UPPER))
conv = 2;
else if (case_flags & CASE_LOWER)
*lower_case |= LCASE_BASE;
}
if (un < dp)
conv = 3;
if (!j)
dn[0] = '_';
if (dn[0] == 0xe5)
dn[0] = SLOT_E5;
if (conv != 1)
*lower_case = 0;
if (conv != 3) {
if (gen > 1)
return 0;
return conv;
}
if (gen == 0)
return conv;
for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10)
*--wcp = gen % 10 + '0';
if (gen)
return 0;
for (i = 8; dn[--i] == ' ';);
i++;
if (gentext + sizeof(gentext) - wcp + 1 > 8 - i)
i = 8 - (gentext + sizeof(gentext) - wcp + 1);
dn[i++] = '~';
while (wcp < gentext + sizeof(gentext))
dn[i++] = *wcp++;
return 3;
}
__private_extern__ int
unicode2winfn(un, unlen, wep, cnt, chksum)
const u_int16_t *un;
int unlen;
struct winentry *wep;
int cnt;
int chksum;
{
u_int8_t *wcp;
int i;
u_int16_t code;
un += (cnt - 1) * WIN_CHARS;
unlen -= (cnt - 1) * WIN_CHARS;
for (wcp = (u_int8_t *)wep, i = sizeof(*wep); --i >= 0; *wcp++ = 0xff);
wep->weCnt = cnt;
wep->weAttributes = ATTR_WIN95;
wep->weReserved1 = 0;
wep->weChksum = chksum;
wep->weReserved2 = 0;
for (wcp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) {
if (--unlen < 0)
goto done;
code = *un++;
*wcp++ = code & 0x00ff;
*wcp++ = code >> 8;
}
for (wcp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) {
if (--unlen < 0)
goto done;
code = *un++;
*wcp++ = code & 0x00ff;
*wcp++ = code >> 8;
}
for (wcp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
if (--unlen < 0)
goto done;
code = *un++;
*wcp++ = code & 0x00ff;
*wcp++ = code >> 8;
}
if (!unlen)
wep->weCnt |= WIN_LAST;
return unlen;
done:
*wcp++ = 0;
*wcp++ = 0;
wep->weCnt |= WIN_LAST;
return 0;
}
static __inline u_int8_t
find_lcode(code, u2w)
u_int16_t code;
u_int16_t *u2w;
{
int i;
for (i = 0; i < 128; i++)
if (u2w[i] == code)
return (i | 0x80);
return '?';
}
static inline u_int16_t case_fold(u_int16_t ch)
{
if (ch < 0x100)
return l2u[ch];
else
return ch;
}
__private_extern__ int
compareUnicodeNames(u_int16_t *x, u_int16_t *y, int length)
{
for ( ; length; --length)
{
if (case_fold(*x++) != case_fold(*y++))
return 1;
}
return 0;
}
__private_extern__ int
winChkName(un, ucslen, wep, chksum)
const u_int16_t *un;
int ucslen;
struct winentry *wep;
int chksum;
{
u_int8_t *cp;
int i;
u_int16_t code;
if (wep->weCnt&WIN_LAST)
chksum = wep->weChksum;
else if (chksum != wep->weChksum)
chksum = -1;
if (chksum == -1)
return -1;
i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS;
un += i;
if ((ucslen -= i) < 0)
return -1;
if ((wep->weCnt&WIN_LAST) && ucslen > WIN_CHARS)
return -1;
for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) {
if (--ucslen < 0) {
if (!*cp++ && !*cp)
return chksum;
return -1;
}
code = (cp[1] << 8) | cp[0];
if (case_fold(code) != case_fold(*un))
return (-1);
cp += 2;
un++;
}
for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) {
if (--ucslen < 0) {
if (!*cp++ && !*cp)
return chksum;
return -1;
}
code = (cp[1] << 8) | cp[0];
if (case_fold(code) != case_fold(*un))
return (-1);
cp += 2;
un++;
}
for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
if (--ucslen < 0) {
if (!*cp++ && !*cp)
return chksum;
return -1;
}
code = (cp[1] << 8) | cp[0];
if (case_fold(code) != case_fold(*un))
return (-1);
cp += 2;
un++;
}
return chksum;
}
__private_extern__ int
getunicodefn(wep, ucfn, unichars, chksum)
struct winentry *wep;
u_int16_t *ucfn;
u_int16_t *unichars;
int chksum;
{
u_int8_t *cp;
u_int16_t *np, *ep = ucfn + WIN_MAXLEN;
u_int16_t code;
int i;
if ((wep->weCnt&WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS)
|| !(wep->weCnt&WIN_CNT))
return -1;
if (wep->weCnt&WIN_LAST) {
chksum = wep->weChksum;
*unichars = (wep->weCnt&WIN_CNT) * WIN_CHARS;
} else if (chksum != wep->weChksum)
chksum = -1;
if (chksum == -1)
return -1;
i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS;
np = ucfn + i;
for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) {
code = (cp[1] << 8) | cp[0];
switch (code) {
case 0:
*np = '\0';
*unichars -= sizeof(wep->wePart2)/2
+ sizeof(wep->wePart3)/2 + i + 1;
return chksum;
case '/':
*np = '\0';
return -1;
default:
*np++ = code;
break;
}
if (WIN_MAXLEN % WIN_CHARS < sizeof(wep->wePart1) / 2
&& np > ep) {
np[-1] = 0;
return -1;
}
cp += 2;
}
for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) {
code = (cp[1] << 8) | cp[0];
switch (code) {
case 0:
*np = '\0';
*unichars -= sizeof(wep->wePart3)/2 + i + 1;
return chksum;
case '/':
*np = '\0';
return -1;
default:
*np++ = code;
break;
}
if (WIN_MAXLEN % WIN_CHARS >= sizeof(wep->wePart1) / 2
&& WIN_MAXLEN % WIN_CHARS < (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2
&& np > ep) {
np[-1] = 0;
return -1;
}
cp += 2;
}
for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
code = (cp[1] << 8) | cp[0];
switch (code) {
case 0:
*np = '\0';
*unichars -= i + 1;
return chksum;
case '/':
*np = '\0';
return -1;
default:
*np++ = code;
break;
}
if (WIN_MAXLEN % WIN_CHARS >= (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2
&& np > ep) {
np[-1] = 0;
return -1;
}
cp += 2;
}
return chksum;
}
__private_extern__ u_int8_t
winChksum(name)
u_int8_t *name;
{
int i;
u_int8_t s;
for (s = 0, i = SHORT_NAME_LEN; --i >= 0; s += *name++)
s = (s << 7)|(s >> 1);
return s;
}
__private_extern__ int
winSlotCnt(un, unlen)
const u_int16_t *un;
int unlen;
{
#pragma unused (un)
if (unlen > WIN_MAXLEN)
return 0;
return howmany(unlen, WIN_CHARS);
}
#if 0
__private_extern__ void
mac2sfmfn(un, unlen)
u_int16_t* un;
size_t unlen;
{
size_t i;
unlen--;
if (un[unlen] == 0x20) {
un[unlen] = 0xf028;
} else if (un[unlen] == 0x2e) {
un[unlen] = 0xf029;
} else if (un[unlen] < MAX_MAC2SFM) {
un[unlen] = mac2sfm[un[unlen]];
}
for (i = 0; i < unlen; i++)
if (un[i] < MAX_MAC2SFM)
un[i] = mac2sfm[un[i]];
}
__private_extern__ void
sfm2macfn(un, unlen)
u_int16_t* un;
u_int16_t unlen;
{
u_int16_t i;
for (i = 0; i < unlen; i++) {
if (((un[i] & 0xff00) == SFMCODE_PREFIX_MASK) &&
((un[i] & 0x00ff) <= MAX_SFM2MAC)) {
un[i] = sfm2mac[un[i] & 0x00ff];
}
}
}
#endif