Stole unicode translation table from mount_msdos. Add kernel code

to support this translation.

MFC after:	2 weeks
This commit is contained in:
Semen Ustimenko 2001-09-08 23:03:52 +00:00
parent 76c1f1f63d
commit cc6b9b02be
9 changed files with 222 additions and 20 deletions

View File

@ -5,6 +5,8 @@
PROG= mount_ntfs
SRCS= mount_ntfs.c getmntopts.c
MAN= mount_ntfs.8
DPADD= ${LIBUTIL}
LDADD= -lutil
MOUNT= ${.CURDIR}/../mount
CFLAGS+=-I${MOUNT}

View File

@ -43,6 +43,7 @@
.Op Fl u Ar uid
.Op Fl g Ar gid
.Op Fl m Ar mask
.Op Fl W Ar u2wtable
.Pa special
.Pa node
.Sh DESCRIPTION
@ -80,6 +81,11 @@ on which the file system is being mounted.
.It Fl m Ar mask
Specify the maximum file permissions for files
in the file system.
.It Fl W Ar u2wtable
Specify unix to unicode translation table. This option is
completly stolen from
.Xr mount_msdos 8
so refer its manpage.
.El
.Sh FEATURES
NTFS file attributes are accessed in following way:

View File

@ -47,6 +47,7 @@
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include <libutil.h>
#include "mntopts.h"
@ -60,6 +61,8 @@ static uid_t a_uid __P((char *));
static mode_t a_mask __P((char *));
static void usage __P((void)) __dead2;
static void load_u2wtable __P((struct ntfs_args *, char *));
int
main(argc, argv)
int argc;
@ -78,7 +81,7 @@ main(argc, argv)
mntflags = set_gid = set_uid = set_mask = 0;
(void)memset(&args, '\0', sizeof(args));
while ((c = getopt(argc, argv, "aiu:g:m:o:")) != -1) {
while ((c = getopt(argc, argv, "aiu:g:m:o:W:")) != -1) {
switch (c) {
case 'u':
args.uid = a_uid(optarg);
@ -101,6 +104,10 @@ main(argc, argv)
case 'o':
getmntopts(optarg, mopts, &mntflags, 0);
break;
case 'W':
load_u2wtable(&args, optarg);
args.flag |= NTFSMNT_U2WTABLE;
break;
case '?':
default:
usage();
@ -233,6 +240,74 @@ a_mask(s)
void
usage()
{
fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] bdev dir\n");
fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] [-W u2wtable] bdev dir\n");
exit(EX_USAGE);
}
void
load_u2wtable (pargs, name)
struct ntfs_args *pargs;
char *name;
{
FILE *f;
int i, j, code[8];
size_t line = 0;
char buf[128];
char *fn, *s, *p;
if (*name == '/')
fn = name;
else {
snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name);
buf[127] = '\0';
fn = buf;
}
if ((f = fopen(fn, "r")) == NULL)
err(EX_NOINPUT, "%s", fn);
p = NULL;
for (i = 0; i < 16; i++) {
do {
if (p != NULL) free(p);
if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL)
errx(EX_DATAERR, "can't read u2w table row %d near line %d", i, line);
while (isspace((unsigned char)*s))
s++;
} while (*s == '\0');
if (sscanf(s, "%i%i%i%i%i%i%i%i",
code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8)
errx(EX_DATAERR, "u2w table: missing item(s) in row %d, line %d", i, line);
for (j = 0; j < 8; j++)
pargs->u2w[i * 8 + j] = code[j];
}
for (i = 0; i < 16; i++) {
do {
free(p);
if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL)
errx(EX_DATAERR, "can't read d2u table row %d near line %d", i, line);
while (isspace((unsigned char)*s))
s++;
} while (*s == '\0');
if (sscanf(s, "%i%i%i%i%i%i%i%i",
code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8)
errx(EX_DATAERR, "d2u table: missing item(s) in row %d, line %d", i, line);
for (j = 0; j < 8; j++)
/* pargs->d2u[i * 8 + j] = code[j] */;
}
for (i = 0; i < 16; i++) {
do {
free(p);
if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL)
errx(EX_DATAERR, "can't read u2d table row %d near line %d", i, line);
while (isspace((unsigned char)*s))
s++;
} while (*s == '\0');
if (sscanf(s, "%i%i%i%i%i%i%i%i",
code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8)
errx(EX_DATAERR, "u2d table: missing item(s) in row %d, line %d", i, line);
for (j = 0; j < 8; j++)
/* pargs->u2d[i * 8 + j] = code[j] */;
}
free(p);
fclose(f);
}

View File

@ -258,6 +258,8 @@ struct ntfsmount {
#if !defined(__FreeBSD__)
struct netexport ntm_export; /* export information */
#endif
wchar * ntm_82u; /* 8bit to Unicode */
char ** ntm_u28; /* Unicode to 8 bit */
};
#define ntm_mftcn ntm_bootfile.bf_mftcn

View File

@ -63,21 +63,20 @@ MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary");
static int ntfs_ntlookupattr __P((struct ntfsmount *, const char *, int, int *, char **));
static int ntfs_findvattr __P((struct ntfsmount *, struct ntnode *, struct ntvattr **, struct ntvattr **, u_int32_t, const char *, size_t, cn_t));
static int ntfs_uastricmp __P((const wchar *, size_t, const char *, size_t));
static int ntfs_uastrcmp __P((const wchar *, size_t, const char *, size_t));
static int ntfs_uastricmp __P((struct ntfsmount *, const wchar *, size_t, const char *, size_t));
static int ntfs_uastrcmp __P((struct ntfsmount *, const wchar *, size_t, const char *, size_t));
/* table for mapping Unicode chars into uppercase; it's filled upon first
* ntfs mount, freed upon last ntfs umount */
static wchar *ntfs_toupper_tab;
#define NTFS_U28(ch) ((((ch) & 0xFF) == 0) ? '_' : (ch) & 0xFF)
#define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(unsigned char)(ch)])
#define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(ch)])
static struct lock ntfs_toupper_lock;
static signed int ntfs_toupper_usecount;
/* support macro for ntfs_ntvattrget() */
#define NTFS_AALPCMP(aalp,type,name,namelen) ( \
(aalp->al_type == type) && (aalp->al_namelen == namelen) && \
!ntfs_uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) )
!NTFS_UASTRCMP(aalp->al_name,aalp->al_namelen,name,namelen) )
/*
*
@ -662,7 +661,8 @@ ntfs_runtovrun(
* Compare unicode and ascii string case insens.
*/
static int
ntfs_uastricmp(ustr, ustrlen, astr, astrlen)
ntfs_uastricmp(ntmp, ustr, ustrlen, astr, astrlen)
struct ntfsmount *ntmp;
const wchar *ustr;
size_t ustrlen;
const char *astr;
@ -671,9 +671,13 @@ ntfs_uastricmp(ustr, ustrlen, astr, astrlen)
size_t i;
int res;
/*
* XXX We use NTFS_82U(NTFS_U28(c)) to get rid of unicode
* symbols not covered by translation table
*/
for (i = 0; i < ustrlen && i < astrlen; i++) {
res = ((int) NTFS_TOUPPER(NTFS_U28(ustr[i]))) -
((int)NTFS_TOUPPER(astr[i]));
res = ((int) NTFS_TOUPPER(NTFS_82U(NTFS_U28(ustr[i])))) -
((int)NTFS_TOUPPER(NTFS_82U(astr[i])));
if (res)
return res;
}
@ -684,7 +688,8 @@ ntfs_uastricmp(ustr, ustrlen, astr, astrlen)
* Compare unicode and ascii string case sens.
*/
static int
ntfs_uastrcmp(ustr, ustrlen, astr, astrlen)
ntfs_uastrcmp(ntmp, ustr, ustrlen, astr, astrlen)
struct ntfsmount *ntmp;
const wchar *ustr;
size_t ustrlen;
const char *astr;
@ -918,7 +923,7 @@ ntfs_ntlookupfile(
/* check the name - the case-insensitible check
* has to come first, to break from this for loop
* if needed, so we can dive correctly */
res = ntfs_uastricmp(iep->ie_fname, iep->ie_fnamelen,
res = NTFS_UASTRICMP(iep->ie_fname, iep->ie_fnamelen,
fname, fnamelen);
if (res > 0) break;
if (res < 0) continue;
@ -926,7 +931,7 @@ ntfs_ntlookupfile(
if (iep->ie_fnametype == 0 ||
!(ntmp->ntm_flag & NTFS_MFLAG_CASEINS))
{
res = ntfs_uastrcmp(iep->ie_fname,
res = NTFS_UASTRCMP(iep->ie_fname,
iep->ie_fnamelen, fname, fnamelen);
if (res != 0) continue;
}
@ -1956,13 +1961,13 @@ ntfs_toupper_use(mp, ntmp)
* XXX for now, just the first 256 entries are used anyway,
* so don't bother reading more
*/
MALLOC(ntfs_toupper_tab, wchar *, 256 * sizeof(wchar),
MALLOC(ntfs_toupper_tab, wchar *, 65536 * sizeof(wchar),
M_NTFSRDATA, M_WAITOK);
if ((error = VFS_VGET(mp, NTFS_UPCASEINO, &vp)))
goto out;
error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, 256*sizeof(wchar), (char *) ntfs_toupper_tab, NULL);
0, 65536*sizeof(wchar), (char *) ntfs_toupper_tab, NULL);
vput(vp);
out:
@ -1997,6 +2002,86 @@ ntfs_toupper_unuse()
LOCKMGR(&ntfs_toupper_lock, LK_RELEASE, NULL);
}
int
ntfs_u28_init(
struct ntfsmount *ntmp,
wchar *u2w)
{
char ** u28;
int i, j, h, l;
MALLOC(u28, char **, 256 * sizeof(char*), M_TEMP, M_WAITOK | M_ZERO);
for (i=0; i<256; i++) {
h = (u2w[i] >> 8) & 0xFF;
l = (u2w[i]) &0xFF;
if (u28[h] == NULL) {
MALLOC(u28[h], char *, 256 * sizeof(char), M_TEMP, M_WAITOK);
for (j=0; j<256; j++)
u28[h][j] = '_';
}
u28[h][l] = i & 0xFF;
}
ntmp->ntm_u28 = u28;
return (0);
}
int
ntfs_u28_uninit(struct ntfsmount *ntmp)
{
char ** u28;
int i;
if (ntmp->ntm_u28 == NULL)
return (0);
u28 = ntmp->ntm_u28;
for (i=0; i<256; i++)
if (u28[i] != NULL)
FREE(u28[i], M_TEMP);
FREE(u28, M_TEMP);
return (0);
}
int
ntfs_82u_init(
struct ntfsmount *ntmp,
u_int16_t *u2w)
{
wchar * _82u;
int i;
MALLOC(_82u, wchar *, 256 * sizeof(wchar), M_TEMP, M_WAITOK);
if (u2w == NULL) {
for (i=0; i<256; i++)
_82u[i] = i;
} else {
for (i=0; i<128; i++)
_82u[i] = i;
for (i=0; i<128; i++)
_82u[i+128] = u2w[i];
}
ntmp->ntm_82u = _82u;
return (0);
}
int
ntfs_82u_uninit(struct ntfsmount *ntmp)
{
FREE(ntmp->ntm_82u, M_TEMP);
return (0);
}
/*
* maps the Unicode char to 8bit equivalent
* XXX currently only gets lower 8bit from the Unicode char
@ -2004,9 +2089,15 @@ ntfs_toupper_unuse()
* something better has to be definitely though out
*/
char
ntfs_u28(unichar)
wchar unichar;
ntfs_u28(
struct ntfsmount *ntmp,
wchar wc)
{
return (char) NTFS_U28(unichar);
char * p;
p = ntmp->ntm_u28[(wc>>8)&0xFF];
if (p == NULL)
return ('_');
return (p[wc&0xFF]);
}

View File

@ -84,7 +84,6 @@ int ntfs_filesize __P(( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64
int ntfs_times __P(( struct ntfsmount *, struct ntnode *, ntfs_times_t *));
struct timespec ntfs_nttimetounix __P(( u_int64_t ));
int ntfs_ntreaddir __P(( struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **));
char ntfs_u28 __P((wchar));
int ntfs_runtovrun __P(( cn_t **, cn_t **, u_long *, u_int8_t *));
int ntfs_attrtontvattr __P(( struct ntfsmount *, struct ntvattr **, struct attr * ));
void ntfs_freentvattr __P(( struct ntvattr * ));
@ -108,3 +107,15 @@ int ntfs_toupper_use __P((struct mount *, struct ntfsmount *));
void ntfs_toupper_unuse __P((void));
int ntfs_fget __P((struct ntfsmount *, struct ntnode *, int, char *, struct fnode **));
void ntfs_frele __P((struct fnode *));
int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w);
int ntfs_u28_uninit(struct ntfsmount *ntmp);
int ntfs_82u_init(struct ntfsmount *ntmp, u_int16_t *u2w);
int ntfs_82u_uninit(struct ntfsmount *ntmp);
char ntfs_u28(struct ntfsmount *ntmp, wchar wc);
#define NTFS_U28(ch) ntfs_u28(ntmp, (ch))
#define NTFS_82U(ch) (ntmp->ntm_82u[(ch)&0xFF])
#define NTFS_UASTRCMP(ustr, ustrlen, astr, astrlen) \
ntfs_uastrcmp(ntmp, (ustr), (ustrlen), (astr), (astrlen))
#define NTFS_UASTRICMP(ustr, ustrlen, astr, astrlen) \
ntfs_uastricmp(ntmp, (ustr), (ustrlen), (astr), (astrlen))

View File

@ -501,6 +501,17 @@ ntfs_mountfs(devvp, mp, argsp, p)
ntmp->ntm_gid = argsp->gid;
ntmp->ntm_mode = argsp->mode;
ntmp->ntm_flag = argsp->flag;
/* Copy in the 8-bit to Unicode conversion table */
if (argsp->flag & NTFSMNT_U2WTABLE) {
ntfs_82u_init(ntmp, argsp->u2w);
} else {
ntfs_82u_init(ntmp, NULL);
}
/* Initialize Unicode to 8-bit table from 8toU table */
ntfs_u28_init(ntmp, ntmp->ntm_82u);
mp->mnt_data = (qaddr_t)ntmp;
dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
@ -697,6 +708,8 @@ ntfs_unmount(
ntfs_toupper_unuse();
dprintf(("ntfs_umount: freeing memory...\n"));
ntfs_u28_uninit(ntmp);
ntfs_82u_uninit(ntmp);
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
FREE(ntmp->ntm_ad, M_NTFSMNT);

View File

@ -586,7 +586,7 @@ ntfs_readdir(ap)
continue;
for(i=0; i<iep->ie_fnamelen; i++) {
cde.d_name[i] = ntfs_u28(iep->ie_fname[i]);
cde.d_name[i] = NTFS_U28(iep->ie_fname[i]);
}
cde.d_name[i] = '\0';
dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",

View File

@ -30,6 +30,7 @@
#define NTFS_MFLAG_CASEINS 0x00000001
#define NTFS_MFLAG_ALLNAMES 0x00000002
#define NTFSMNT_U2WTABLE 0x00000004
struct ntfs_args {
char *fspec; /* block special device to mount */
@ -38,4 +39,5 @@ struct ntfs_args {
gid_t gid; /* gid that owns ntfs files */
mode_t mode; /* mask to be applied for ntfs perms */
u_long flag; /* additional flags */
u_int16_t u2w[256]; /* Unix to Wchar */
};