Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Apr 1998 13:07:38 -0500 (EST)
From:      Alfred Perlstein <perlsta@cs.sunyit.edu>
To:        multimedia@FreeBSD.ORG
Subject:   can someone please commit the joliet patches.
Message-ID:  <Pine.BSF.3.96.980426130405.27004A-100000@server.local.sunyit.edu>

next in thread | raw e-mail | index | archive | help

if someone has a few spare minutes could they please commit PR kern/5038?

it's patches to add joliet to cd9660 support.

thank you,
-Alfred

PR-follows, didn't know whether this would annoy or help the person doing
the patch so they don't have to web around looking for it, sorry if this
annoys anyone.

Problem Report kern/5038

FreeBSD can't read MS Joliet CDs.

Confidential
     no
Severity
     non-critical
Priority
     high
Responsible
     freebsd-bugs@freebsd.org
State
     open
Class
     change-request
Submitter-Id
     current-users
Arrival-Date
     Fri Nov 14 00:20:02 PST 1997
Last-Modified
     Wed Apr 1 21:35:49 PST 1998
Originator
     Keith Jang keith@email.gcn.net.tw
Organization

     private site

Release
     FreeBSD 3.0-current
Environment

     FreeBSD 3.0-CURRENT #36: Fri Nov 14 03:27:44 CST 1997

Description

     FreeBSD can't read the long filenames on Joliet CDs.

How-To-Repeat

     Just insert a Joliet CD, and the filenames are changed to xxx~1.

Fix

     I modified some code under /sys/isofs/cd9660, and it can read the long
     filenames, though Unicode is not implemented yet.

Audit-Trail

     From: Keith Jang <keith@keith.private>
     To: freebsd-gnats-submit@freebsd.org
     Cc:  Subject: Re: kern/5038
     Date: Sat, 15 Nov 1997 14:32:48 +0800 (CST)

      The following are three files with a patch for reading joliet.

      /sys/isofs/cd9660/cd9660_joliet.h:

      begin 644 cd9660_joliet.h.gz
      M'XL("`E9;#0``V-D.38V,%]J;VQI970N:`!U4FUKVS`8_.Y?<3`86_'RNI:$
      M?NIB=Z1X-#0A7\8HBOPX%E,L(\EMPMA_WR,EA<(2,+*MTYWN3NI?);C"#R6M
      M<:;R>#!:D4>^]SUX@_GR<7IS,\`L@VM)JDI)X95IF-1/DGXDGRB=(X=EU[::
      M=M1X80]8&]WM"!DY:57KC85P$`V$]F0;%GHAWB1H+*S:G67TL*H)"^%KK,1&
      M$S[BR1B/3%F2C!_P1-+8,HB8"LMUAHWAQ:U1C0\)!$I55639$@JS9?\:W[21
      MO^%KMK)89RE>:R7KH*!-L^4=ND9)4Q(JI:D1.\YER:F2>F=BEU2IAE=L#IYX
      M5Z="/9B\F>'`]UIL78K)],MP-`@3N9.BC6*8GWH;1[X+K!,:<U?*.D[Q:K#K
      M^&-#&.Q'U^R07]6I.M6XSG*/M7+@1[P9FV5'#09L>;1GJ>4@W(3C68*F%])I
      MT!CLOP[2,([C>(V*SRK"&*88I>!Y9O(-"&>F#\<B_*$EC@_G;2<]_B2`K(5%
      M%0(#^,FW)YL5^`1,4O['Y/.OV^1ON%3/#X_%/%\]WQ=WWV^3BTH4NWBO-)FR
      M$O?XGU*^G-TM<M;Z<#R1]]@\&\;BSF.CV.8YK,C7>3&,[5R$1[&VB_`X]IDD
      *_P"42;O1:`,``-;Z
      `
      end

      /sys/isofs/cd9660/cd9660_joliet.c:

      begin 644 cd9660_joliet.c.gz
      M'XL("`E9;#0``V-D.38V,%]J;VQI970N8P"-4LMNFT`47<-77"52`O@)D5(U
      M)%[5E1Q9RJ)5-Y&%"(QC$IA!\W!B6?[W7@8H8!RK"WN8,^?<Q[GW,J%1JF("
      M]V(G)GG(PVR\F9F7'1A_\@3\HM9]<$M93/IPQA25??B=<$K2`F\])(*MQ22*
      MO]_>3B=XZ<HZK^41]'.>8KVQ-"'R#`\O+9*94`D=:?!*)`TS8@G)522AX,<)
      M)Y%D?!?@R7@,#J((#DW#,`"B3<C!84JB64-0@=@P+C60$FJ;>Q-J$+\`BNA!
      M$G_"`TR'&LG"ST"CR$?4PNA49<$WU[6M,M-H5K_;OHF:*G@10M^QV"C?674-
      M%^/Q14E,UF!93CL(/*#(AJNK=A[+4D'9AMU+6`A<V]:5-GE='P&2"O)%"O=,
      MBGY37R3QZB0:GSCPDW&@[`/>E,#1O%+&"5"5IGH&820)%^!,-'N-5*OMM=\X
      M?]^QO'D8#&S8:W7E7+M0^[FFK4H/32-B5"94$;_2-'Z<$5[[URA]X21\[^CV
      MIE'.[[DR8%7MPJE`OFE8]88-!G6<@UG^X\&)5)S67OKFX=2NIV1+TO:F"Y7G
      M*<D(E2%N>TQ$Q),<-Q\<L8W+5=;M67@=S?`YS+&JJ>YK\>LI>'Q:+N:_@\4/
      M/?ZJJB.VVV=[=NV[^$ADM#F6>*MF+E&(7K74R_F?^=*]^]>QZP-TS#TI\!J!
      I]U^"FT9P<RR(R3I4J;PKOBO.",MH<8K!')I-;M-P,G\!MVX89J$%```I
      `
      end

      /sys/isofs/cd9660/iso_joliet.h:

      begin 644 iso_joliet.h.gz
      M'XL("`E9;#0``VES;U]J;VQI970N:`!UD,U.PS`0A,_Q4ZS$!:**AOY)54]`
      M`DI)Z:'`U0KVFAJE=F1OJO+VV#WUX/IB:;X9SZ['.8,<-EHXZZTB6-M.(T%U
      MHGL@"_5NNUPL"G@NP?<HM-*B)6U-"(T9NY&HM,'HXNMM4U<?O"X?H#A-YFDV
      MB4RE6%-]54V,SHJK.*9GTZMX&O$\.=7+^^9Q]Q:X"B?I**NGSU?&M"$0,J[,
      M?\\_P7^03'O`6T]N$`3:6RZU0T'6_?%P6R<A#VH01RS+,@"Q;QWD=J#O08U@
      MX'YO'9V%#LW=*M'1X1&[RP8_]'V'!S34AA:)7CC=AT;(_5&&)_X!ZD!VR;8!
      "``!O
      `
      end

      patch for /sys:

      diff -c -r sys/conf/files sys.keith/conf/files
      *** sys/conf/files     Thu Nov 13 03:25:21 1997
      --- sys.keith/conf/files       Fri Nov 14 22:03:23 1997
      ***************
      *** 61,66 ****
      --- 61,67 ----
        isofs/cd9660/cd9660_util.c   optional cd9660
        isofs/cd9660/cd9660_vfsops.c optional cd9660
        isofs/cd9660/cd9660_vnops.c  optional cd9660
      + isofs/cd9660/cd9660_joliet.c optional cd9660
        kern/imgact_aout.c   standard
        kern/imgact_elf.c    standard
        kern/imgact_gzip.c   optional gzip
      diff -c -r sys/conf/files.newconf sys.keith/conf/files.newconf
      *** sys/conf/files.newconf     Thu Nov 13 03:25:21 1997
      --- sys.keith/conf/files.newconf       Fri Nov 14 22:03:23 1997
      ***************
      *** 39,44 ****
      --- 39,45 ----
        file isofs/cd9660/cd9660_util.c      cd9660
        file isofs/cd9660/cd9660_vfsops.c    cd9660
        file isofs/cd9660/cd9660_vnops.c     cd9660
      + file isofs/cd9660/cd9660_joliet.c    cd9660
        file kern/init_main.c
        file kern/init_sysent.c
        file kern/kern_acct.c
      Only in sys.keith/isofs/cd9660: cd9660_joliet.c
      Only in sys.keith/isofs/cd9660: cd9660_joliet.h
      diff -c -r sys/isofs/cd9660/cd9660_lookup.c sys.keith/isofs/cd9660/cd9660_lookup.c
      *** sys/isofs/cd9660/cd9660_lookup.c   Thu Nov 13 03:26:37 1997
      --- sys.keith/isofs/cd9660/cd9660_lookup.c     Fri Nov 14 22:03:43 1997
      ***************
      *** 50,56 ****
      --- 50,58 ----

        #include <isofs/cd9660/iso.h>
        #include <isofs/cd9660/cd9660_node.h>
      + #include <isofs/cd9660/cd9660_joliet.h>
        #include <isofs/cd9660/iso_rrip.h>
      + #include <isofs/cd9660/iso_joliet.h>

        /*
         * Convert a component of a pathname into a pointer to a locked inode.
      ***************
      *** 267,272 ****
      --- 269,287 ----
                                     goto found;
                             ino = 0;
                             break;
      +              case ISO_FTYPE_JOLIET:
      +                if (isonum_711(ep->flags)&2)
      +                  ino = isodirino(ep, imp);
      +                else
      +                  ino = dbtob(bp->b_blkno) + entryoffsetinblock;
      +
      +                dp->i_ino = ino;
      +                cd9660_joliet_getname(ep,altname,&namelen);
      +                if (namelen == cnp->cn_namelen
      +                    && !bcmp(name, altname, namelen))
      +                  goto found;
      +                ino = 0;
      +                break;
                     }
                     dp->i_offset += reclen;
                     entryoffsetinblock += reclen;
      diff -c -r sys/isofs/cd9660/cd9660_mount.h sys.keith/isofs/cd9660/cd9660_mount.h
      *** sys/isofs/cd9660/cd9660_mount.h    Thu Nov 13 03:26:37 1997
      --- sys.keith/isofs/cd9660/cd9660_mount.h      Fri Nov 14 22:03:43 1997
      ***************
      *** 47,52 ****
             int     flags;                  /* mounting flags, see below */
             int     ssector;                /* starting sector, 0 for 1st session */
        };
      ! #define      ISOFSMNT_NORRIP 0x00000001      /* disable Rock Ridge Ext.*/
      ! #define      ISOFSMNT_GENS   0x00000002      /* enable generation numbers */
      ! #define      ISOFSMNT_EXTATT 0x00000004      /* enable extended attributes */
      --- 47,53 ----
             int     flags;                  /* mounting flags, see below */
             int     ssector;                /* starting sector, 0 for 1st session */
        };
      ! #define      ISOFSMNT_NORRIP   0x00000001    /* disable Rock Ridge Ext.*/
      ! #define      ISOFSMNT_GENS     0x00000002    /* enable generation numbers */
      ! #define      ISOFSMNT_EXTATT   0x00000004    /* enable extended attributes */
      ! #define ISOFSMNT_NOJOLIET 0x00000008    /* disable Microsoft Joliet Ext.*/
      diff -c -r sys/isofs/cd9660/cd9660_vfsops.c sys.keith/isofs/cd9660/cd9660_vfsops.c
      *** sys/isofs/cd9660/cd9660_vfsops.c   Thu Nov 13 03:26:37 1997
      --- sys.keith/isofs/cd9660/cd9660_vfsops.c     Fri Nov 14 22:03:43 1997
      ***************
      *** 55,61 ****
      --- 55,63 ----
        #include <sys/stat.h>

        #include <isofs/cd9660/iso.h>
      + #include <isofs/cd9660/iso_joliet.h>
        #include <isofs/cd9660/iso_rrip.h>
      + #include <isofs/cd9660/cd9660_joliet.h>
        #include <isofs/cd9660/cd9660_node.h>
        #include <isofs/cd9660/cd9660_mount.h>

      ***************
      *** 261,267 ****
             struct iso_args *argp;
        {
             register struct iso_mnt *isomp = (struct iso_mnt *)0;
      !      struct buf *bp = NULL;
             dev_t dev = devvp->v_rdev;
             int error = EINVAL;
             int needclose = 0;
      --- 263,269 ----
             struct iso_args *argp;
        {
             register struct iso_mnt *isomp = (struct iso_mnt *)0;
      !      struct buf *bp = NULL, *joliet_bp = NULL;
             dev_t dev = devvp->v_rdev;
             int error = EINVAL;
             int needclose = 0;
      ***************
      *** 271,279 ****
      --- 273,283 ----
             int iso_blknum;
             struct iso_volume_descriptor *vdp = 0;
             struct iso_primary_descriptor *pri;
      +      struct iso_supplementary_descriptor *sup = NULL;
             struct iso_sierra_primary_descriptor *pri_sierra;
             struct iso_directory_record *rootp;
             int logical_block_size;
      +      int joliet_level = -1;

             if (!ronly)
                     return EROFS;
      ***************
      *** 316,321 ****
      --- 320,344 ----
                                     goto out;
                             } else
                                     high_sierra = 1;
      +              } else {
      +                /*
      +                 * We know it's ISO9660 fs, now get Supplementary Volume
      +                 * Descriptor to check if it's Microsoft Joliet format.
      +                 */
      +                if (error = bread(devvp, (1 + iso_blknum) * btodb(iso_bsize),
      +                                  iso_bsize, NOCRED, &joliet_bp))
      +                  goto out;
      +
      +                sup = (struct iso_supplementary_descriptor *)joliet_bp->b_data;
      +                joliet_level = cd9660_joliet_level(sup);
      +
      +                if (joliet_level < 0) {
      +                  argp->flags |= ISOFSMNT_NOJOLIET;
      +                } else {
      +                  argp->flags |= ISOFSMNT_NORRIP;
      +                  argp->flags &= ~ISOFSMNT_GENS;
      +                }
      +                break;
                     }

                     if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_END) {
      ***************
      *** 328,340 ****
                     brelse(bp);
             }

      !      if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_PRIMARY) {
                     error = EINVAL;
                     goto out;
             }

      -      pri = (struct iso_primary_descriptor *)vdp;
             pri_sierra = (struct iso_sierra_primary_descriptor *)vdp;

             logical_block_size =
                     isonum_723 (high_sierra?
      --- 351,363 ----
                     brelse(bp);
             }

      !      if ((isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_PRIMARY) && (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_SUPPLEMENTARY)) {
                     error = EINVAL;
                     goto out;
             }

             pri_sierra = (struct iso_sierra_primary_descriptor *)vdp;
      +      pri = (struct iso_primary_descriptor *)vdp;

             logical_block_size =
                     isonum_723 (high_sierra?
      ***************
      *** 350,356 ****
             rootp = (struct iso_directory_record *)
                     (high_sierra?
                      pri_sierra->root_directory_record:
      !               pri->root_directory_record);

             isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
             bzero((caddr_t)isomp, sizeof *isomp);
      --- 373,381 ----
             rootp = (struct iso_directory_record *)
                     (high_sierra?
                      pri_sierra->root_directory_record:
      !               ((joliet_level < 0)?
      !                pri->root_directory_record:
      !                sup->root_directory_record));

             isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
             bzero((caddr_t)isomp, sizeof *isomp);
      ***************
      *** 380,385 ****
      --- 405,412 ----
             bp->b_flags |= B_AGE;
             brelse(bp);
             bp = NULL;
      +      brelse(joliet_bp);
      +      joliet_bp = NULL;

             mp->mnt_data = (qaddr_t)isomp;
             mp->mnt_stat.f_fsid.val[0] = (long)dev;
      ***************
      *** 416,439 ****
                     brelse(bp);
                     bp = NULL;
             }
      !      isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);

             if(high_sierra)
                     /* this effectively ignores all the mount flags */
                     isomp->iso_ftype = ISO_FTYPE_HIGH_SIERRA;
             else
      !              switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
                       default:
                               isomp->iso_ftype = ISO_FTYPE_DEFAULT;
                               break;
      !                case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
                               isomp->iso_ftype = ISO_FTYPE_9660;
                               break;
      !                case 0:
                               isomp->iso_ftype = ISO_FTYPE_RRIP;
                               break;
                     }
      -
             return 0;
        out:
             if (bp)
      --- 443,469 ----
                     brelse(bp);
                     bp = NULL;
             }
      !      isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT|ISOFSMNT_NOJOLIET);

             if(high_sierra)
                     /* this effectively ignores all the mount flags */
                     isomp->iso_ftype = ISO_FTYPE_HIGH_SIERRA;
             else
      !              switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|
      !                                       ISOFSMNT_NOJOLIET)) {
                       default:
                               isomp->iso_ftype = ISO_FTYPE_DEFAULT;
                               break;
      !                case ISOFSMNT_GENS|ISOFSMNT_NORRIP|ISOFSMNT_NOJOLIET:
                               isomp->iso_ftype = ISO_FTYPE_9660;
                               break;
      !                case ISOFSMNT_NOJOLIET:
                               isomp->iso_ftype = ISO_FTYPE_RRIP;
                               break;
      +                case ISOFSMNT_NORRIP:
      +                        isomp->iso_ftype = ISO_FTYPE_JOLIET;
      +                        break;
                     }
             return 0;
        out:
             if (bp)
      ***************
      *** 507,513 ****
             struct iso_directory_record *dp =
                 (struct iso_directory_record *)imp->root;
             ino_t ino = isodirino(dp, imp);
      !
             /*
              * With RRIP we must use the `.' entry of the root directory.
              * Simply tell vget, that it's a relocated directory.
      --- 537,543 ----
             struct iso_directory_record *dp =
                 (struct iso_directory_record *)imp->root;
             ino_t ino = isodirino(dp, imp);
      !
             /*
              * With RRIP we must use the `.' entry of the root directory.
              * Simply tell vget, that it's a relocated directory.
      diff -c -r sys/isofs/cd9660/cd9660_vnops.c sys.keith/isofs/cd9660/cd9660_vnops.c
      *** sys/isofs/cd9660/cd9660_vnops.c    Thu Nov 13 03:26:37 1997
      --- sys.keith/isofs/cd9660/cd9660_vnops.c      Fri Nov 14 22:03:43 1997
      ***************
      *** 56,61 ****
      --- 56,62 ----
        #include <isofs/cd9660/iso.h>
        #include <isofs/cd9660/cd9660_node.h>
        #include <isofs/cd9660/iso_rrip.h>
      + #include <isofs/cd9660/iso_joliet.h>

        static int cd9660_setattr __P((struct vop_setattr_args *));
        static int cd9660_access __P((struct vop_access_args *));
      ***************
      *** 540,545 ****
      --- 541,552 ----
                             if (idp->current.d_namlen)
                                     error = iso_uiodir(idp,&idp->current,idp->curroff);
                             break;
      +              case ISO_FTYPE_JOLIET:
      +                cd9660_joliet_getname(ep,idp->current.d_name, &namelen);
      +                idp->current.d_namlen = (u_char)namelen;
      +                if (idp->current.d_namlen)
      +                  error = iso_uiodir(idp,&idp->current,idp->curroff);
      +                break;
                     default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
                             strcpy(idp->current.d_name,"..");
                             switch (ep->name[0]) {
      diff -c -r sys/isofs/cd9660/iso.h sys.keith/isofs/cd9660/iso.h
      *** sys/isofs/cd9660/iso.h     Thu Nov 13 03:26:37 1997
      --- sys.keith/isofs/cd9660/iso.h       Fri Nov 14 22:03:43 1997
      ***************
      *** 54,59 ****
      --- 54,60 ----

        /* volume descriptor types */
        #define ISO_VD_PRIMARY 1
      + #define ISO_VD_SUPPLEMENTARY 2
        #define ISO_VD_END 255

        #define ISO_STANDARD_ID "CD001"
      ***************
      *** 98,103 ****
      --- 99,145 ----
        };
        #define ISO_DEFAULT_BLOCK_SIZE               2048

      + /*
      +  * Used by Microsoft Joliet extension to ISO9660. Almost the same
      +  * as PVD, but byte position 8 is a flag, and 89-120 is for escape.
      +  */
      +
      + struct iso_supplementary_descriptor {
      +      char type                       [ISODCL (  1,   1)]; /* 711 */
      +      char id                         [ISODCL (  2,   6)];
      +      char version                    [ISODCL (  7,   7)]; /* 711 */
      +      char flags                      [ISODCL (  8,   8)];
      +      char system_id                  [ISODCL (  9,  40)]; /* achars */
      +      char volume_id                  [ISODCL ( 41,  72)]; /* dchars */
      +      char unused2                    [ISODCL ( 73,  80)];
      +      char volume_space_size          [ISODCL ( 81,  88)]; /* 733 */
      +      char escape                     [ISODCL ( 89, 120)];
      +      char volume_set_size            [ISODCL (121, 124)]; /* 723 */
      +      char volume_sequence_number     [ISODCL (125, 128)]; /* 723 */
      +      char logical_block_size         [ISODCL (129, 132)]; /* 723 */
      +      char path_table_size            [ISODCL (133, 140)]; /* 733 */
      +      char type_l_path_table          [ISODCL (141, 144)]; /* 731 */
      +      char opt_type_l_path_table      [ISODCL (145, 148)]; /* 731 */
      +      char type_m_path_table          [ISODCL (149, 152)]; /* 732 */
      +      char opt_type_m_path_table      [ISODCL (153, 156)]; /* 732 */
      +      char root_directory_record      [ISODCL (157, 190)]; /* 9.1 */
      +      char volume_set_id              [ISODCL (191, 318)]; /* dchars */
      +      char publisher_id               [ISODCL (319, 446)]; /* achars */
      +      char preparer_id                [ISODCL (447, 574)]; /* achars */
      +      char application_id             [ISODCL (575, 702)]; /* achars */
      +      char copyright_file_id          [ISODCL (703, 739)]; /* 7.5 dchars */
      +      char abstract_file_id           [ISODCL (740, 776)]; /* 7.5 dchars */
      +      char bibliographic_file_id      [ISODCL (777, 813)]; /* 7.5 dchars */
      +      char creation_date              [ISODCL (814, 830)]; /* 8.4.26.1 */
      +      char modification_date          [ISODCL (831, 847)]; /* 8.4.26.1 */
      +      char expiration_date            [ISODCL (848, 864)]; /* 8.4.26.1 */
      +      char effective_date             [ISODCL (865, 881)]; /* 8.4.26.1 */
      +      char file_structure_version     [ISODCL (882, 882)]; /* 711 */
      +      char unused4                    [ISODCL (883, 883)];
      +      char application_data           [ISODCL (884, 1395)];
      +      char unused5                    [ISODCL (1396, 2048)];
      + };
      +
        struct iso_sierra_primary_descriptor {
             char unknown1                   [ISODCL (  1,   8)]; /* 733 */
             char type                       [ISODCL (  9,   9)]; /* 711 */
      ***************
      *** 175,181 ****

        /* CD-ROM Format type */
        enum ISO_FTYPE       { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP,
      !                ISO_FTYPE_ECMA, ISO_FTYPE_HIGH_SIERRA };

        #ifndef      ISOFSMNT_ROOT
        #define      ISOFSMNT_ROOT   0
      --- 217,223 ----

        /* CD-ROM Format type */
        enum ISO_FTYPE       { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP,
      !                ISO_FTYPE_JOLIET, ISO_FTYPE_ECMA, ISO_FTYPE_HIGH_SIERRA };

        #ifndef      ISOFSMNT_ROOT
        #define      ISOFSMNT_ROOT   0
      Only in sys.keith/isofs/cd9660: iso_joliet.h

     From: Joachim Kuebart <joki@kuebart.stuttgart.netsurf.de>
     To: freebsd-gnats-submit@freebsd.org, keith@email.gcn.net.tw
     Cc:  Subject: Re: kern/5038: FreeBSD can't read MS Joliet CDs.
     Date: Sun, 22 Mar 1998 19:47:44 +0100 (CET)

      Hi,

      this is a new diff from /usr/src to support Joliet FS extensions to
      CD9660. It will also run with RRIP, either like this or with minor
      modifications. I can do this as soon as someone supplies me with a
      documentation about mixing RRIP and Joliet (which is expressedly
      allowed in the Joliet documentation) or supplies me with a sample CD.

      This diff is to be used _instead_ of the diff in the original PR.

      This is expected to close PR bin/5567 when merged back to -stable.

      cu Jo

      ---------------------------------------------------------------------
      FreeBSD: The Power to Serve                  <http://www.freebsd.org>;
      Joachim Kuebart
      Tel: +49 711 653706          Replicants are like any other machine --
      Germany                      they're either a benefit or a hazard.


      Index: sbin/mount_cd9660/mount_cd9660.8
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sbin/mount_cd9660/mount_cd9660.8,v
      retrieving revision 1.5
      diff -u -r1.5 mount_cd9660.8
      --- mount_cd9660.8     1997/12/29 07:03:46     1.5
      +++ mount_cd9660.8     1998/03/22 10:27:36
      @@ -67,6 +67,8 @@
       only the last one will be listed.)
       In either case, files may be opened without explicitly stating a
       version number.
      +.It Fl j
      +Do not use any Joliet extensions included in the filesystem.
       .It Fl o
       Options are specified with a
       .Fl o
      Index: sbin/mount_cd9660/mount_cd9660.c
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sbin/mount_cd9660/mount_cd9660.c,v
      retrieving revision 1.12
      diff -u -r1.12 mount_cd9660.c
      --- mount_cd9660.c     1997/04/29 15:56:40     1.12
      +++ mount_cd9660.c     1998/03/16 18:41:59
      @@ -73,6 +73,7 @@
             { "extatt", 0, ISOFSMNT_EXTATT, 1 },
             { "gens", 0, ISOFSMNT_GENS, 1 },
             { "rrip", 1, ISOFSMNT_NORRIP, 1 },
      +      { "joliet", 1, ISOFSMNT_NOJOLIET, 1 },
             { NULL }
       };

      @@ -91,13 +92,16 @@
             mntflags = opts = verbose = 0;
             memset(&args, 0, sizeof args);
             args.ssector = -1;
      -      while ((ch = getopt(argc, argv, "ego:rs:v")) != -1)
      +      while ((ch = getopt(argc, argv, "egjo:rs:v")) != -1)
                     switch (ch) {
                     case 'e':
                             opts |= ISOFSMNT_EXTATT;
                             break;
                     case 'g':
                             opts |= ISOFSMNT_GENS;
      +                      break;
      +              case 'j':
      +                      opts |= ISOFSMNT_NOJOLIET;
                             break;
                     case 'o':
                             getmntopts(optarg, mopts, &mntflags, &opts);
      Index: sys/isofs/cd9660/cd9660_lookup.c
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/cd9660_lookup.c,v
      retrieving revision 1.20
      diff -u -r1.20 cd9660_lookup.c
      --- cd9660_lookup.c    1997/11/07 08:52:50     1.20
      +++ cd9660_lookup.c    1998/03/16 18:14:07
      @@ -237,8 +237,7 @@
                                             if (namelen != 1
                                                 || ep->name[0] != 0)
                                                     goto notfound;
      -                              } else if (!(res = isofncmp(name,len,
      -                                                          ep->name,namelen))) {
      +                              } else if (!(res = isofncmp(name,len,ep->name,namelen,imp->joliet_level))) {
                                             if (isoflags & 2)
                                                     ino = isodirino(ep, imp);
                                             else
      Index: sys/isofs/cd9660/cd9660_mount.h
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/cd9660_mount.h,v
      retrieving revision 1.2
      diff -u -r1.2 cd9660_mount.h
      --- cd9660_mount.h     1997/04/29 15:52:53     1.2
      +++ cd9660_mount.h     1998/03/16 18:42:48
      @@ -50,3 +50,4 @@
       #define       ISOFSMNT_NORRIP 0x00000001      /* disable Rock Ridge Ext.*/
       #define       ISOFSMNT_GENS   0x00000002      /* enable generation numbers */
       #define       ISOFSMNT_EXTATT 0x00000004      /* enable extended attributes */
      +#define       ISOFSMNT_NOJOLIET 0x00000008    /* disable Joliet Ext. */
      Index: sys/isofs/cd9660/cd9660_rrip.c
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/cd9660_rrip.c,v
      retrieving revision 1.13
      diff -u -r1.13 cd9660_rrip.c
      --- cd9660_rrip.c      1997/08/02 14:31:19     1.13
      +++ cd9660_rrip.c      1998/03/22 18:05:34
      @@ -298,18 +298,19 @@
             struct iso_directory_record *isodir;
             ISO_RRIP_ANALYZE *ana;
       {
      -      strcpy(ana->outbuf,"..");
      -      switch (*isodir->name) {
      +      isofntrans(isodir->name,isonum_711(isodir->name_len),
      +                 ana->outbuf,ana->outlen,
      +                 1,isonum_711(isodir->flags)&4,
      +                 ana->imp->joliet_level);
      +      switch (*ana->outbuf) {
             default:
      -              isofntrans(isodir->name,isonum_711(isodir->name_len),
      -                         ana->outbuf,ana->outlen,
      -                         1,isonum_711(isodir->flags)&4);
                     break;
      -      case 0:
      -              *ana->outlen = 1;
      -              break;
             case 1:
                     *ana->outlen = 2;
      +              /* fall through */
      +      case 0:
      +              /* outlen is 1 already */
      +              strcpy(ana->outbuf,"..");
                     break;
             }
       }
      @@ -498,6 +499,7 @@
             register ISO_SUSP_HEADER *pend;
             struct buf *bp = NULL;
             char *pwhead;
      +      u_char c;
             int result;

             /*
      @@ -505,12 +507,11 @@
              *       it will be padding 1 byte after the name
              */
             pwhead = isodir->name + isonum_711(isodir->name_len);
      -      if (!(isonum_711(isodir->name_len)&1))
      -              pwhead++;
      +      isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
      +      pwhead += isonum_711(isodir->name_len) & 1;

             /* If it's not the '.' entry of the root dir obey SP field */
      -      if (*isodir->name != 0
      -          || isonum_733(isodir->extent) != ana->imp->root_extent)
      +      if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
                     pwhead += ana->imp->rr_skip;
             else
                     pwhead += ana->imp->rr_skip0;
      @@ -633,6 +634,7 @@
       {
             ISO_RRIP_ANALYZE analyze;
             RRIP_TABLE *tab;
      +      u_char c;

             analyze.outbuf = outbuf;
             analyze.outlen = outlen;
      @@ -642,9 +644,10 @@
             analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
             *outlen = 0;

      +      isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
      +              imp->joliet_level, &c);
             tab = rrip_table_getname;
      -      if (*isodir->name == 0
      -          || *isodir->name == 1) {
      +      if (c == 0 || c == 1) {
                     cd9660_rrip_defname(isodir,&analyze);

                     analyze.fields &= ~ISO_SUSP_ALTNAME;
      Index: sys/isofs/cd9660/cd9660_util.c
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/cd9660_util.c,v
      retrieving revision 1.10
      diff -u -r1.10 cd9660_util.c
      --- cd9660_util.c      1997/04/10 14:35:11     1.10
      +++ cd9660_util.c      1998/03/17 09:52:35
      @@ -5,7 +5,8 @@
        * This code is derived from software contributed to Berkeley
        * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
        * Support code is derived from software contributed to Berkeley
      - * by Atsushi Murai (amurai@spec.co.jp).
      + * by Atsushi Murai (amurai@spec.co.jp). Joliet support was added by
      + * Joachim Kuebart (joki@kuebart.stuttgart.netsurf.de).
        *
        * Redistribution and use in source and binary forms, with or without
        * modification, are permitted provided that the following conditions
      @@ -46,37 +47,63 @@
       #include <isofs/cd9660/iso.h>

       /*
      + * Get one character out of an iso filename
      + * Obey joliet_level
      + * Return number of bytes consumed
      + */
      +int
      +isochar(isofn, isoend, joliet_level, c)
      +      u_char *isofn;
      +      u_char *isoend;
      +      int joliet_level;
      +      u_char *c;
      +{
      +      *c = *isofn++;
      +      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;
      +      }
      +      return 2;
      +}
      +
      +/*
        * translate and compare a filename
      + * returns (fn - isofn)
        * Note: Version number plus ';' may be omitted.
        */
       int
      -isofncmp(fn, fnlen, isofn, isolen)
      +isofncmp(fn, fnlen, isofn, isolen, joliet_level)
             u_char *fn;
             int fnlen;
             u_char *isofn;
             int isolen;
      +      int joliet_level;
       {
             int i, j;
      -      unsigned char c;
      +      u_char c, *fnend = fn + fnlen, *isoend = isofn + isolen;

      -      while (--fnlen >= 0) {
      -              if (--isolen < 0)
      +      for (; fn != fnend; fn++) {
      +              if (isofn == isoend)
                             return *fn;
      -              if ((c = *isofn++) == ';') {
      -                      switch (*fn++) {
      -                      default:
      -                              return *--fn;
      -                      case 0:
      -                              return 0;
      -                      case ';':
      -                              break;
      -                      }
      -                      for (i = 0; --fnlen >= 0; i = i * 10 + *fn++ - '0') {
      -                              if (*fn < '0' || *fn > '9') {
      +              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; --isolen >= 0; j = j * 10 + *isofn++ - '0');
      +                      for (j = 0; isofn != isoend; j = j * 10 + c - '0')
      +                              isofn += isochar(isofn, isoend,
      +                                      joliet_level, &c);
                             return i - j;
                     }
                     if (c != *fn) {
      @@ -90,15 +117,19 @@
                             } else
                                     return *fn - c;
                     }
      -              fn++;
             }
      -      if (isolen > 0) {
      -              switch (*isofn) {
      +      if (isofn != isoend) {
      +              isofn += isochar(isofn, isoend, joliet_level, &c);
      +              switch (c) {
                     default:
      -                      return -1;
      +                      return -c;
                     case '.':
      -                      if (isofn[1] != ';')
      -                              return -1;
      +                      if (isofn != isoend) {
      +                              isochar(isofn, isoend, joliet_level, &c);
      +                              if (c == ';')
      +                                      return 0;
      +                      }
      +                      return -1;
                     case ';':
                             return 0;
                     }
      @@ -107,35 +138,36 @@
       }

       /*
      - * translate a filename
      + * translate a filename of length > 0
        */
       void
      -isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
      +isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
             u_char *infn;
             int infnlen;
             u_char *outfn;
             u_short *outfnlen;
             int original;
             int assoc;
      +      int joliet_level;
       {
             int fnidx = 0;
      +      u_char c, d = '\0', *infnend = infn + infnlen;

             if (assoc) {
                     *outfn++ = ASSOCCHAR;
                     fnidx++;
      -              infnlen++;
             }
      -      for (; fnidx < infnlen; fnidx++) {
      -              char c = *infn++;
      +      for (; infn != infnend; fnidx++) {
      +              infn += isochar(infn, infnend, joliet_level, &c);

                     if (!original && c >= 'A' && c <= 'Z')
                             *outfn++ = c + ('a' - 'A');
      -              else if (!original && c == '.' && *infn == ';')
      -                      break;
      -              else if (!original && c == ';')
      +              else if (!original && c == ';') {
      +                      fnidx -= (d == '.');
                             break;
      -              else
      +              } else
                             *outfn++ = c;
      +              d = c;
             }
             *outfnlen = fnidx;
       }
      Index: sys/isofs/cd9660/cd9660_vfsops.c
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/cd9660_vfsops.c,v
      retrieving revision 1.35
      diff -u -r1.35 cd9660_vfsops.c
      --- cd9660_vfsops.c    1998/03/08 09:56:41     1.35
      +++ cd9660_vfsops.c    1998/03/16 19:07:13
      @@ -271,9 +271,12 @@
             int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
             int iso_bsize;
             int iso_blknum;
      +      int pri_blknum;
      +      int joliet_level;
             struct iso_volume_descriptor *vdp = 0;
             struct iso_primary_descriptor *pri;
             struct iso_sierra_primary_descriptor *pri_sierra;
      +      struct iso_supplementary_descriptor *supp;
             struct iso_directory_record *rootp;
             int logical_block_size;

      @@ -303,6 +306,8 @@
              */
             iso_bsize = ISO_DEFAULT_BLOCK_SIZE;

      +      joliet_level = 0;
      +      pri_blknum = -1;
             for (iso_blknum = 16 + argp->ssector;
                  iso_blknum < 100 + argp->ssector;
                  iso_blknum++) {
      @@ -320,19 +325,42 @@
                                     high_sierra = 1;
                     }

      -              if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_END) {
      -                      error = EINVAL;
      -                      goto out;
      -              }
      +              if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_END)
      +                      break;

                     if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_PRIMARY)
      -                      break;
      +                      pri_blknum = iso_blknum;
      +
      +              if (!(argp->flags & ISOFSMNT_NOJOLIET) &&
      +                  isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_SUPPLEMENTARY) {
      +                      supp = (struct iso_supplementary_descriptor *)vdp;
      +                      if (bcmp(supp->escape, "%/@", 3) == 0)
      +                              joliet_level = 1;
      +                      if (bcmp(supp->escape, "%/C", 3) == 0)
      +                              joliet_level = 2;
      +                      if (bcmp(supp->escape, "%/E", 3) == 0)
      +                              joliet_level = 3;
      +                      if (isonum_711 (supp->flags) & 1)
      +                              joliet_level = 0;
      +                      if (joliet_level)
      +                              break;
      +              }
      +
                     brelse(bp);
             }

      -      if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_PRIMARY) {
      -              error = EINVAL;
      -              goto out;
      +      if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_SUPPLEMENTARY) {
      +              if (pri_blknum == -1) {
      +                      error = EINVAL;
      +                      goto out;
      +              }
      +
      +              brelse(bp);
      +              if (error = bread(devvp, pri_blknum * btodb(iso_bsize),
      +                                iso_bsize, NOCRED, &bp))
      +                      goto out;
      +              vdp = (struct iso_volume_descriptor *)bp->b_data;
      +              argp->flags |= ISOFSMNT_NOJOLIET;
             }

             pri = (struct iso_primary_descriptor *)vdp;
      @@ -361,6 +389,7 @@
                     isonum_733 (high_sierra?
                                 pri_sierra->volume_space_size:
                                 pri->volume_space_size);
      +      isomp->joliet_level = joliet_level;
             /*
              * Since an ISO9660 multi-session CD can also access previous
              * sessions, we have to include them into the space consider-
      @@ -375,9 +404,7 @@
             isomp->root_size = isonum_733 (rootp->size);

             isomp->im_bmask = logical_block_size - 1;
      -      isomp->im_bshift = 0;
      -      while ((1 << isomp->im_bshift) < isomp->logical_block_size)
      -              isomp->im_bshift++;
      +      isomp->im_bshift = ffs(logical_block_size) - 1;

             bp->b_flags |= B_AGE;
             brelse(bp);
      @@ -418,7 +445,8 @@
                     brelse(bp);
                     bp = NULL;
             }
      -      isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);
      +      isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
      +                                      ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);

             if(high_sierra)
                     /* this effectively ignores all the mount flags */
      Index: sys/isofs/cd9660/cd9660_vnops.c
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/cd9660_vnops.c,v
      retrieving revision 1.52
      diff -u -r1.52 cd9660_vnops.c
      --- cd9660_vnops.c     1998/03/06 09:46:14     1.52
      +++ cd9660_vnops.c     1998/03/16 18:16:01
      @@ -549,26 +549,23 @@
                             break;
                     default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
                             strcpy(idp->current.d_name,"..");
      -                      switch (ep->name[0]) {
      -                      case 0:
      +                      if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
                                     idp->current.d_namlen = 1;
                                     error = iso_uiodir(idp,&idp->current,idp->curroff);
      -                              break;
      -                      case 1:
      +                      } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) {
                                     idp->current.d_namlen = 2;
                                     error = iso_uiodir(idp,&idp->current,idp->curroff);
      -                              break;
      -                      default:
      +                      } else {
                                     isofntrans(ep->name,idp->current.d_namlen,
                                                idp->current.d_name, &namelen,
                                                imp->iso_ftype == ISO_FTYPE_9660,
      -                                         isonum_711(ep->flags)&4);
      +                                         isonum_711(ep->flags)&4,
      +                                         imp->joliet_level);
                                     idp->current.d_namlen = (u_char)namelen;
                                     if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
                                             error = iso_shipdir(idp);
                                     else
                                             error = iso_uiodir(idp,&idp->current,idp->curroff);
      -                              break;
                             }
                     }
                     if (error)
      Index: sys/isofs/cd9660/iso.h
      ===================================================================
      RCS file: /usr/CVS-Repository/src/sys/isofs/cd9660/iso.h,v
      retrieving revision 1.16
      diff -u -r1.16 iso.h
      --- iso.h      1997/05/07 13:23:04     1.16
      +++ iso.h      1998/03/16 19:10:03
      @@ -54,6 +54,7 @@

       /* volume descriptor types */
       #define ISO_VD_PRIMARY 1
      +#define ISO_VD_SUPPLEMENTARY 2
       #define ISO_VD_END 255

       #define ISO_STANDARD_ID "CD001"
      @@ -135,6 +136,42 @@
             char unused4                    [ISODCL (856, 2048)];
       };

      +struct iso_supplementary_descriptor {
      +      char type                       [ISODCL (  1,   1)]; /* 711 */
      +      char id                         [ISODCL (  2,   6)];
      +      char version                    [ISODCL (  7,   7)]; /* 711 */
      +      char flags                      [ISODCL (  8,   8)]; /* 711? */
      +      char system_id                  [ISODCL (  9,  40)]; /* achars */
      +      char volume_id                  [ISODCL ( 41,  72)]; /* dchars */
      +      char unused2                    [ISODCL ( 73,  80)];
      +      char volume_space_size          [ISODCL ( 81,  88)]; /* 733 */
      +      char escape                     [ISODCL ( 89, 120)];
      +      char volume_set_size            [ISODCL (121, 124)]; /* 723 */
      +      char volume_sequence_number     [ISODCL (125, 128)]; /* 723 */
      +      char logical_block_size         [ISODCL (129, 132)]; /* 723 */
      +      char path_table_size            [ISODCL (133, 140)]; /* 733 */
      +      char type_l_path_table          [ISODCL (141, 144)]; /* 731 */
      +      char opt_type_l_path_table      [ISODCL (145, 148)]; /* 731 */
      +      char type_m_path_table          [ISODCL (149, 152)]; /* 732 */
      +      char opt_type_m_path_table      [ISODCL (153, 156)]; /* 732 */
      +      char root_directory_record      [ISODCL (157, 190)]; /* 9.1 */
      +      char volume_set_id              [ISODCL (191, 318)]; /* dchars */
      +      char publisher_id               [ISODCL (319, 446)]; /* achars */
      +      char preparer_id                [ISODCL (447, 574)]; /* achars */
      +      char application_id             [ISODCL (575, 702)]; /* achars */
      +      char copyright_file_id          [ISODCL (703, 739)]; /* 7.5 dchars */
      +      char abstract_file_id           [ISODCL (740, 776)]; /* 7.5 dchars */
      +      char bibliographic_file_id      [ISODCL (777, 813)]; /* 7.5 dchars */
      +      char creation_date              [ISODCL (814, 830)]; /* 8.4.26.1 */
      +      char modification_date          [ISODCL (831, 847)]; /* 8.4.26.1 */
      +      char expiration_date            [ISODCL (848, 864)]; /* 8.4.26.1 */
      +      char effective_date             [ISODCL (865, 881)]; /* 8.4.26.1 */
      +      char file_structure_version     [ISODCL (882, 882)]; /* 711 */
      +      char unused4                    [ISODCL (883, 883)];
      +      char application_data           [ISODCL (884, 1395)];
      +      char unused5                    [ISODCL (1396, 2048)];
      +};
      +
       struct iso_directory_record {
             char length                     [ISODCL (1, 1)]; /* 711 */
             char ext_attr_length            [ISODCL (2, 2)]; /* 711 */
      @@ -202,6 +239,8 @@

             int rr_skip;
             int rr_skip0;
      +
      +      int joliet_level;
       };

       #define VFSTOISOFS(mp)        ((struct iso_mnt *)((mp)->mnt_data))
      @@ -221,8 +260,9 @@
       extern vop_t **cd9660_specop_p;
       extern vop_t **cd9660_fifoop_p;

      -int isofncmp __P((u_char *, int, u_char *, int));
      -void isofntrans __P((u_char *, int, u_char *, u_short *, int, int));
      +int isochar __P((u_char *, u_char *, int, u_char *));
      +int isofncmp __P((u_char *, int, u_char *, int, int));
      +void isofntrans __P((u_char *, int, u_char *, u_short *, int, int, int));
       ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));

       #endif /* KERNEL */

Submit Followup
  ------------------------------------------------------------------------
www@freebsd.org


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-multimedia" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980426130405.27004A-100000>