private int doNM(FilenameDataReference filename, int drLength) throws HandlerException {
    int lengthToAdd = RRIPFactory.NM_ENTRY_LENGTH;
    // Note: Since DR length must be an even number (see ISO 9660 section 9.1.13),
    // a DR length of 255 would be changed to 256 which does not fit into a byte
    int rest = 254 - drLength;
    if (rest >= filename.getLength() + RRIPFactory.NM_ENTRY_LENGTH) {
      // Filename fits into this System Use Area
      rripFactory.doNMEntry(0, filename);
      lengthToAdd += filename.getLength();
    } else {
      // Filename exceeds space left -> Continuation Area needed
      int prefixLength = rest - (RRIPFactory.NM_ENTRY_LENGTH + RRIPFactory.CE_ENTRY_LENGTH);
      String name = filename.getName();
      DataReference filenameRest = helper.getFilenameDataReference(name.substring(0, prefixLength));
      rripFactory.doNMEntry(RRIPFactory.NM_CONTINUES, filenameRest);

      // Construct CE Entry to continue filename in Continuation Area
      HashMap ceMemory = rripFactory.doCEEntry();
      UnfinishedNMEntry unfinishedNMEntry = new UnfinishedNMEntry();
      unfinishedNMEntry.location = (Fixup) ceMemory.get("ceLocationFixup");
      unfinishedNMEntry.offset = (Fixup) ceMemory.get("ceOffsetFixup");
      unfinishedNMEntry.length = (Fixup) ceMemory.get("ceLengthFixup");
      unfinishedNMEntry.filenameRest = name.substring(prefixLength);
      unfinishedNMEntries.add(unfinishedNMEntry);

      lengthToAdd += prefixLength + RRIPFactory.CE_ENTRY_LENGTH;
    }

    return drLength + lengthToAdd;
  }
  HashMap doDotDotDR(ISO9660Directory dir) throws HandlerException {
    long position = streamHandler.mark();
    HashMap memory = super.doDotDotDR(dir);
    ISO9660Directory parentDir = dir.getParentDirectory();

    if (RRIPFactory.MKISOFS_COMPATIBILITY) {
      // RR: Recorded Fields
      int flags = RRIPFactory.RR_PX_RECORDED | RRIPFactory.RR_TF_RECORDED;
      if (dir.isMoved()) {
        flags |= RRIPFactory.RR_PL_RECORDED;
      }
      rripFactory.doRREntry(flags);
    }

    if (dir.isMoved()) {
      // PL: Real Parent of this relocated directory
      parentLocationFixups.put(dir, rripFactory.doPLEntry());
    }

    // PX: POSIX File Attributes
    POSIXFileMode fileMode = getPOSIXFileModeForObject(dir);
    int fileModes = fileMode.getFileMode();
    int fileLinks = 2 + parentDir.getDirectories().size();
    rripFactory.doPXEntry(fileModes, fileLinks, 0, 0, 1);

    // TF: Timestamp
    ISO9660ShortDateDataReference date =
        new ISO9660ShortDateDataReference(parentDir.lastModified());
    rripFactory.doTFEntry(RRIPFactory.TF_MODIFY, date);

    // Update Directory Record Length
    return finalizeDR(memory, helper.getDifferenceTo(position));
  }
  HashMap doDR(ISO9660File file) throws HandlerException {
    long position = streamHandler.mark();
    HashMap memory = super.doDR(file);

    if (RRIPFactory.MKISOFS_COMPATIBILITY) {
      // RR: Recorded Fields
      int flags =
          RRIPFactory.RR_PX_RECORDED | RRIPFactory.RR_TF_RECORDED | RRIPFactory.RR_NM_RECORDED;
      rripFactory.doRREntry(flags);
    }

    // PX: POSIX File Attributes
    POSIXFileMode fileMode = getPOSIXFileModeForObject(file);
    int fileModes = fileMode.getFileMode();
    rripFactory.doPXEntry(fileModes, 1, 0, 0, 1);

    // TF: Timestamp
    ISO9660ShortDateDataReference date = new ISO9660ShortDateDataReference(file.lastModified());
    rripFactory.doTFEntry(RRIPFactory.TF_MODIFY, date);

    // Compute length up to here
    int length = helper.getDifferenceTo(position);

    // NM: Alternate Name
    length = doNM(helper.getFilenameDataReference(file), length);

    // Update Directory Record Length
    return finalizeDR(memory, length);
  }
  HashMap doFakeDR(ISO9660Directory dir) throws HandlerException {
    long position = streamHandler.mark();
    HashMap memory = super.doFakeDR(dir);

    if (RRIPFactory.MKISOFS_COMPATIBILITY) {
      // RR: Recorded Fields
      int flags =
          RRIPFactory.RR_PX_RECORDED | RRIPFactory.RR_NM_RECORDED | RRIPFactory.RR_CL_RECORDED;
      rripFactory.doRREntry(flags);
    }

    // PX: POSIX File Attributes
    int fileModes = getPOSIXFileModeForObject(dir).getFileMode();
    int fileLinks = 2 + dir.getDirectories().size();
    rripFactory.doPXEntry(fileModes, fileLinks, 0, 0, 1);

    // CL: Child link (location of the actual directory record)
    childLocationFixups.put(dir, rripFactory.doCLEntry());

    // Compute length up to here
    int length = helper.getDifferenceTo(position);

    // NM: Alternate Name
    length = doNM(helper.getFilenameDataReference(dir), length);

    // Update Directory Record Length
    return finalizeDR(memory, length);
  }
  private void doCA() throws HandlerException {
    long position = streamHandler.mark();
    streamHandler.startElement(new LogicalSectorElement("CA"));
    int location = helper.getCurrentLocation();

    // Write and close RRIP ER Location Fixup
    Fixup rripERLocationFixup = (Fixup) volumeFixups.get("rripERLocationFixup");
    rripERLocationFixup.data(new BothWordDataReference(location));
    rripERLocationFixup.close();

    // Write ER Entry
    rripFactory.doEREntry();

    // Write ST Entry and compute length
    int erLength = doST(helper.getDifferenceTo(position));

    // Write and close RRIP ER Length Fixup
    Fixup rripERLengthFixup = (Fixup) volumeFixups.get("rripERLengthFixup");
    rripERLengthFixup.data(new BothWordDataReference(erLength));
    rripERLengthFixup.close();

    // Process unfinished NM Entries
    int offset = erLength;
    Iterator it = unfinishedNMEntries.iterator();
    while (it.hasNext()) {
      UnfinishedNMEntry unfinishedNMEntry = (UnfinishedNMEntry) it.next();
      String name = unfinishedNMEntry.filenameRest;
      rripFactory.doNMEntry(0, helper.getFilenameDataReference(name));

      // Write and close CE Entry Location Fixup
      unfinishedNMEntry.location.data(new BothWordDataReference(location));
      unfinishedNMEntry.location.close();

      // Write and close CE Entry Offset Fixup
      unfinishedNMEntry.offset.data(new BothWordDataReference(offset));
      unfinishedNMEntry.offset.close();

      // Write ST Entry and compute length
      int ceLength = doST(name.length() + RRIPFactory.NM_ENTRY_LENGTH);

      // Write and close CE Entry Length Fixup
      unfinishedNMEntry.length.data(new BothWordDataReference(ceLength));
      unfinishedNMEntry.length.close();

      offset += ceLength;
    }

    streamHandler.endElement();
  }
 private int doST(int length) throws HandlerException {
   if (!RRIPFactory.MKISOFS_COMPATIBILITY) {
     rripFactory.doSTEntry();
     length += 4;
   }
   return length;
 }
  HashMap doDotDR(ISO9660Directory dir) throws HandlerException {
    long position = streamHandler.mark();
    HashMap memory = super.doDotDR(dir);

    if (dir == root) {
      // SP: SUSP Indicator
      rripFactory.doSPEntry(0);
    }

    if (RRIPFactory.MKISOFS_COMPATIBILITY) {
      // RR: Recorded Fields
      int flags = RRIPFactory.RR_PX_RECORDED | RRIPFactory.RR_TF_RECORDED;
      rripFactory.doRREntry(flags);
    }

    // PX: POSIX File Attributes
    POSIXFileMode fileMode = getPOSIXFileModeForObject(dir);
    int fileModes = fileMode.getFileMode();
    int fileLinks = 2 + dir.getDirectories().size();
    rripFactory.doPXEntry(fileModes, fileLinks, 0, 0, 1);

    // TF: Timestamp
    ISO9660ShortDateDataReference date = new ISO9660ShortDateDataReference(dir.lastModified());
    rripFactory.doTFEntry(RRIPFactory.TF_MODIFY, date);

    if (dir == root) {
      // CE: Continuation Area for RRIP ER
      HashMap ceMemory = rripFactory.doCEEntry();
      volumeFixups.put("rripERLocationFixup", ceMemory.get("ceLocationFixup"));
      volumeFixups.put("rripERLengthFixup", ceMemory.get("ceLengthFixup"));

      // Write and close ER Offset Fixup
      Fixup rripEROffsetFixup = (Fixup) ceMemory.get("ceOffsetFixup");
      rripEROffsetFixup.data(new BothWordDataReference(0));
      rripEROffsetFixup.close();
    }

    // Update Directory Record Length
    return finalizeDR(memory, helper.getDifferenceTo(position));
  }