#include <sys/param.h>
#include <sys/mount.h>
#include <sys/vnode.h>
+#include <sys/iconv.h>
#include "iso.h"
+#include "cd9660_mount.h"
-/*
- * XXX: limited support for loading of Unicode
- * conversion routine as a kld at a run-time.
- * Should be removed when native Unicode kernel
- * interfaces have been introduced.
- */
-u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
+extern struct iconv_functions *cd9660_iconv;
/*
* Get one character out of an iso filename
* Return number of bytes consumed
*/
int
-isochar(u_char *isofn, u_char *isoend, int joliet_level, u_char *c)
+isochar(isofn, isoend, joliet_level, c, clen, flags, handle)
+ u_char *isofn;
+ u_char *isoend;
+ int joliet_level;
+ u_short *c;
+ int *clen;
+ int flags;
+ void *handle;
{
+ size_t i, j, len;
+ char inbuf[3], outbuf[3], *inp, *outp;
*c = *isofn++;
+ if (clen) *clen = 1;
if (joliet_level == 0 || isofn == isoend)
/* (00) and (01) are one byte in Joliet, too */
return 1;
-
- /* No Unicode support yet :-( */
- switch (*c) {
- default:
- *c = '?';
- break;
- case '\0':
- *c = *isofn;
- break;
+ if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ i = j = len = 2;
+ inbuf[0]=(char)*(isofn - 1);
+ inbuf[1]=(char)*isofn;
+ inbuf[2]='\0';
+ inp = inbuf;
+ outp = outbuf;
+ cd9660_iconv->convchr(handle, (const char **)&inp, &i, &outp, &j);
+ len -= j;
+ if (clen) *clen = len;
+ *c = '\0';
+ while(len--)
+ *c |= (*(outp - len - 1) & 0xff) << (len << 3);
+ } else {
+ switch (*c) {
+ default:
+ *c = '?';
+ break;
+ case '\0':
+ *c = *isofn;
+ break;
+ }
}
- /* XXX: if Unicode conversion routine is loaded then use it */
- if (cd9660_wchar2char != NULL)
- *c = cd9660_wchar2char((*(isofn - 1) << 8) | *isofn);
-
return 2;
}
* Note: Version number plus ';' may be omitted.
*/
int
-isofncmp(u_char *fn, int fnlen, u_char *isofn, int isolen, int joliet_level)
+isofncmp(fn, fnlen, isofn, isolen, joliet_level, flags, handle, lhandle)
+ u_char *fn;
+ int fnlen;
+ u_char *isofn;
+ int isolen;
+ int joliet_level;
+ int flags;
+ void *handle;
+ void *lhandle;
{
- int i, j;
- u_char c, *fnend = fn + fnlen, *isoend = isofn + isolen;
-
- for (; fn != fnend; fn++) {
- if (isofn == isoend)
- return *fn;
- isofn += isochar(isofn, isoend, joliet_level, &c);
- if (c == ';') {
- if (*fn++ != ';')
- return fn[-1];
- for (i = 0; fn != fnend; i = i * 10 + *fn++ - '0') {
- if (*fn < '0' || *fn > '9') {
- return -1;
- }
- }
- for (j = 0; isofn != isoend; j = j * 10 + c - '0')
- isofn += isochar(isofn, isoend,
- joliet_level, &c);
- return i - j;
- }
- if (c != *fn) {
- if (c >= 'A' && c <= 'Z') {
- if (c + ('a' - 'A') != *fn) {
- if (*fn >= 'a' && *fn <= 'z')
- return *fn - ('a' - 'A') - c;
- else
- return *fn - c;
- }
- } else
- return *fn - c;
- }
- }
- if (isofn != isoend) {
- isofn += isochar(isofn, isoend, joliet_level, &c);
- switch (c) {
- default:
- return -c;
- case '.':
- if (isofn != isoend) {
- isochar(isofn, isoend, joliet_level, &c);
- if (c == ';')
- return 0;
- }
- return -1;
- case ';':
- return 0;
- }
- }
- return 0;
+ int i, j;
+ u_short c, d;
+ u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
+ for (; fn < fnend; ) {
+ d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle)
+;
+ if (isofn == isoend)
+ return d;
+ isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
+ if (c == ';') {
+ if (d != ';')
+ return d;
+ for (i = 0; fn < fnend; i = i * 10 + *fn++ - '0') {
+ if (*fn < '0' || *fn > '9') {
+ return -1;
+ }
+ }
+ for (j = 0; isofn != isoend; j = j * 10 + c - '0')
+ isofn += isochar(isofn, isoend,
+ joliet_level, &c,
+ NULL, flags, handle);
+ return i - j;
+ }
+ if (c != d) {
+ if (c >= 'A' && c <= 'Z') {
+ if (c + ('a' - 'A') != d) {
+ if (d >= 'a' && d <= 'z')
+ return d - ('a' - 'A') - c;
+ else
+ return d - c;
+ }
+ } else
+ return d - c;
+ }
+ }
+ if (isofn != isoend) {
+ isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
+ switch (c) {
+ default:
+ return -c;
+ case '.':
+ if (isofn != isoend) {
+ isochar(isofn, isoend, joliet_level, &c,
+ NULL, flags, handle);
+ if (c == ';')
+ return 0;
+ }
+ return -1;
+ case ';':
+ return 0;
+ }
+ }
+ return 0;
}
/*
* translate a filename of length > 0
*/
-void
-isofntrans(u_char *infn, int infnlen, u_char *outfn, u_short *outfnlen,
- int original, int assoc, int joliet_level)
+isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level, flags,
+ handle)
+ u_char *infn;
+ int infnlen;
+ u_char *outfn;
+ u_short *outfnlen;
+ int original;
+ int assoc;
+ int joliet_level;
+ int flags;
+ void *handle;
{
- int fnidx = 0;
- u_char c, d = '\0', *infnend = infn + infnlen;
-
- if (assoc) {
- *outfn++ = ASSOCCHAR;
- fnidx++;
- }
- for (; infn != infnend; fnidx++) {
- infn += isochar(infn, infnend, joliet_level, &c);
+ u_short c, d = '\0';
+ u_char *outp = outfn, *infnend = infn + infnlen;
+ int clen;
+ if (assoc) {
+ *outp++ = ASSOCCHAR;
+ }
+ for (; infn != infnend; ) {
+ infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle);
+ if (!original && !joliet_level && c >= 'A' && c <= 'Z')
+ c += ('a' - 'A');
+ else if (!original && c == ';') {
+ outp -= (d == '.');
+ break;
+ }
+ d = c;
+ while(clen--)
+ *outp++ = c >> (clen << 3);
+ }
+ *outfnlen = outp - outfn;
+}
- if (!original && !joliet_level && c >= 'A' && c <= 'Z')
- *outfn++ = c + ('a' - 'A');
- else if (!original && c == ';') {
- fnidx -= (d == '.');
- break;
- } else
- *outfn++ = c;
- d = c;
- }
- *outfnlen = fnidx;
+/*
+ * same as sgetrune(3)
+ */
+u_short
+sgetrune(string, n, result, flags, handle)
+ const char *string;
+ size_t n;
+ char const **result;
+ int flags;
+ void *handle;
+{
+ size_t i, j, len;
+ char outbuf[3], *outp;
+ u_short c = '\0';
+ len = i = (n < 2) ? n : 2;
+ j = 2;
+ outp = outbuf;
+ if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ cd9660_iconv->convchr(handle, (const char **)&string,
+ &i, &outp, &j);
+ len -= i;
+ } else {
+ len = 1;
+ string++;
+ }
+ if (result) *result = string;
+ while(len--) c |= (*(string - len - 1) & 0xff) << (len << 3);
+ return (c);
}
#include <sys/malloc.h>
#include <sys/stat.h>
#include <sys/syslog.h>
+#include <sys/iconv.h>
#include <vm/vm_zone.h>
MALLOC_DEFINE(M_ISOFSMNT, "ISOFS mount", "ISOFS mount structure");
MALLOC_DEFINE(M_ISOFSNODE, "ISOFS node", "ISOFS vnode private part");
+struct iconv_functions *cd9660_iconv = NULL;
+
static int cd9660_mount (struct mount *, char *, caddr_t, struct ucred *);
static int cd9660_unmount (struct mount *, int);
static int cd9660_root (struct mount *, struct vnode **);
struct iso_supplementary_descriptor *sup = NULL;
struct iso_directory_record *rootp;
int logical_block_size;
+ char *cs_local, *cs_disk;
if (!(mp->mnt_flag & MNT_RDONLY))
return EROFS;
}
isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
+ if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ cs_local = "UTF-8";
+ cs_disk = "UTF-16BE";
+ cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l);
+ cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d);
+ } else {
+ isomp->im_d2l = NULL;
+ isomp->im_l2d = NULL;
+ }
if (high_sierra) {
/* this effectively ignores all the mount flags */
isomp = VFSTOISOFS(mp);
+ if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ if (isomp->im_d2l)
+ cd9660_iconv->close(isomp->im_d2l);
+ if (isomp->im_l2d)
+ cd9660_iconv->close(isomp->im_l2d);
+ }
+
isomp->im_devvp->v_rdev->si_mountpoint = NULL;
error = VOP_CLOSE(isomp->im_devvp, FREAD);
vrele(isomp->im_devvp);
int rr_skip0;
int joliet_level;
+
+ void *im_d2l;
+ void *im_l2d;
};
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
#define cd9660_sysctl ((int (*) (int *, u_int, void *, size_t *, void *, \
size_t, struct proc *))eopnotsupp)
-int isochar (u_char *, u_char *, int, u_char *);
-int isofncmp (u_char *, int, u_char *, int, int);
-void isofntrans (u_char *, int, u_char *, u_short *, int, int, int);
+int isochar(u_char *, u_char *, int, u_short *, int *, int, void *);
+int isofncmp(u_char *, int, u_char *, int, int, int, void *, void *);
+void isofntrans(u_char *, int, u_char *, u_short *, int, int, int, int, void *);
ino_t isodirino (struct iso_directory_record *, struct iso_mnt *);
+u_short sgetrune(const char *, size_t, char const **, int, void *);
#endif /* _KERNEL */
* outside the kernel. Thus we don't hide them here.
*/
-static __inline int isonum_711 (u_char *);
-static __inline int
-isonum_711(u_char *p)
+static __inline uint8_t
+isonum_711(unsigned char *p)
{
- return *p;
+ return p[0];
}
-
-static __inline int isonum_712 (char *);
-static __inline int
-isonum_712(char *p)
+static __inline uint8_t
+isonum_712(unsigned char *p)
{
- return *p;
+ return p[0];
}
#ifndef UNALIGNED_ACCESS
-static __inline int isonum_723 (u_char *);
-static __inline int
-isonum_723(u_char *p)
+static __inline uint32_t
+isonum_731(unsigned char *p)
{
- return *p|(p[1] << 8);
+ return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24);
}
-
-static __inline int isonum_733 (u_char *);
-static __inline int
-isonum_733(u_char *p)
+static __inline uint32_t
+isonum_732(unsigned char *p)
+{
+ return (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24);
+}
+static __inline uint32_t
+isonum_733(unsigned char *p)
{
- return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
+ return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24);
}
#else /* UNALIGNED_ACCESS */