1 /* 2 * JIIC: Java ISO Image Creator. Copyright (C) 2007, Jens Hatlak <hatlak@rbg.informatik.tu-darmstadt.de> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 */ 19 20 package de.tu_darmstadt.informatik.rbg.hatlak.rockridge.impl; 21 22 import de.tu_darmstadt.informatik.rbg.hatlak.iso9660.impl.ISO9660DateDataReference; 23 import de.tu_darmstadt.informatik.rbg.hatlak.iso9660.impl.ISO9660ShortDateDataReference; 24 import de.tu_darmstadt.informatik.rbg.hatlak.sabre.impl.BothWordDataReference; 25 import de.tu_darmstadt.informatik.rbg.mhartle.sabre.DataReference; 26 import de.tu_darmstadt.informatik.rbg.mhartle.sabre.Fixup; 27 import de.tu_darmstadt.informatik.rbg.mhartle.sabre.HandlerException; 28 import de.tu_darmstadt.informatik.rbg.mhartle.sabre.StreamHandler; 29 import de.tu_darmstadt.informatik.rbg.mhartle.sabre.impl.ByteArrayDataReference; 30 import de.tu_darmstadt.informatik.rbg.mhartle.sabre.impl.ByteDataReference; 31 32 public class RRIPFactory extends SUSPFactory { 33 public static boolean MKISOFS_COMPATIBILITY = true; 34 public static final int CR_CONTINUES = 1; 35 public static final int CR_CURRENT = 2; 36 public static final int CR_PARENT = 4; 37 public static final int CR_ROOT = 8; 38 public static final int NM_CONTINUES = 1; 39 public static final int NM_CURRENT = 2; 40 public static final int NM_PARENT = 4; 41 public static final int TF_CREATION = 1; 42 public static final int TF_MODIFY = 2; 43 public static final int TF_ACCESS = 4; 44 public static final int TF_ATTRIBUTES = 8; 45 public static final int TF_BACKUP = 16; 46 public static final int TF_EXPIRATION = 32; 47 public static final int TF_EFFECTIVE = 64; 48 public static final int TF_LONG_FORM = 128; 49 public static final int RR_PX_RECORDED = 1; 50 public static final int RR_PN_RECORDED = 2; 51 public static final int RR_SL_RECORDED = 4; 52 public static final int RR_NM_RECORDED = 8; 53 public static final int RR_CL_RECORDED = 16; 54 public static final int RR_PL_RECORDED = 32; 55 public static final int RR_RE_RECORDED = 64; 56 public static final int RR_TF_RECORDED = 128; 57 public static final int NM_ENTRY_LENGTH = 5; 58 RRIPFactory(StreamHandler streamHandler)59 public RRIPFactory(StreamHandler streamHandler) { 60 super(streamHandler); 61 } 62 doPXEntry(int fileModes, int fileLinks, int uid, int gid, long serialNumber)63 public void doPXEntry(int fileModes, int fileLinks, int uid, int gid, long serialNumber) throws HandlerException { 64 streamHandler.startElement(new SystemUseEntryElement("PX", 1)); 65 streamHandler.data(new BothWordDataReference(fileModes)); 66 streamHandler.data(new BothWordDataReference(fileLinks)); 67 streamHandler.data(new BothWordDataReference(uid)); 68 streamHandler.data(new BothWordDataReference(gid)); 69 70 if (!MKISOFS_COMPATIBILITY) { 71 // RRIP 1.12 includes the Serial Number field, RRIP 1.09 does not 72 streamHandler.data(new BothWordDataReference(serialNumber)); 73 } 74 75 streamHandler.endElement(); 76 } 77 doPNEntry(int deviceNumberHigh, int deviceNumberLow)78 public void doPNEntry(int deviceNumberHigh, int deviceNumberLow) throws HandlerException { 79 streamHandler.startElement(new SystemUseEntryElement("PN", 1)); 80 streamHandler.data(new BothWordDataReference(deviceNumberHigh)); 81 streamHandler.data(new BothWordDataReference(deviceNumberLow)); 82 streamHandler.endElement(); 83 } 84 startSLEntry(boolean continues)85 public void startSLEntry(boolean continues) throws HandlerException { 86 streamHandler.startElement(new SystemUseEntryElement("SL", 1)); 87 streamHandler.data(new ByteDataReference(continues ? 1 : 0)); 88 } 89 doComponentRecord(int flags)90 public void doComponentRecord(int flags) throws HandlerException { 91 if (flags != CR_CONTINUES && flags != CR_CURRENT && flags != CR_PARENT && flags != CR_ROOT) { 92 throw new HandlerException("Invalid Rock Ridge Component Record flags combination: " + flags); 93 } 94 streamHandler.data(new ByteDataReference(flags)); 95 streamHandler.data(new ByteDataReference(0)); 96 } 97 doComponentRecord(DataReference name)98 public void doComponentRecord(DataReference name) throws HandlerException { 99 streamHandler.data(new ByteDataReference(0)); 100 streamHandler.data(new ByteDataReference(name.getLength())); 101 streamHandler.data(name); 102 } 103 endSLEntry()104 public void endSLEntry() throws HandlerException { 105 streamHandler.endElement(); 106 } 107 doNMEntry(int flags, DataReference name)108 public void doNMEntry(int flags, DataReference name) throws HandlerException { 109 streamHandler.startElement(new SystemUseEntryElement("NM", 1)); 110 111 if (flags != 0 && flags != NM_CONTINUES && flags != NM_CURRENT && flags != NM_PARENT) { 112 throw new HandlerException("Invalid Rock Ridge directory flags combination: " + flags); 113 } 114 streamHandler.data(new ByteDataReference(flags)); 115 116 streamHandler.data(name); 117 streamHandler.endElement(); 118 } 119 doCLEntry()120 public Fixup doCLEntry() throws HandlerException { 121 streamHandler.startElement(new SystemUseEntryElement("CL", 1)); 122 Fixup childLocationFixup = streamHandler.fixup(new BothWordDataReference(0)); 123 streamHandler.endElement(); 124 125 return childLocationFixup; 126 } 127 doPLEntry()128 public Fixup doPLEntry() throws HandlerException { 129 streamHandler.startElement(new SystemUseEntryElement("PL", 1)); 130 Fixup parentLocationFixup = streamHandler.fixup(new BothWordDataReference(0)); 131 streamHandler.endElement(); 132 133 return parentLocationFixup; 134 } 135 doREEntry()136 public void doREEntry() throws HandlerException { 137 streamHandler.startElement(new SystemUseEntryElement("RE", 1)); 138 streamHandler.endElement(); 139 } 140 doTFEntry(int type, ISO9660DateDataReference date)141 public void doTFEntry(int type, ISO9660DateDataReference date) throws HandlerException { 142 streamHandler.startElement(new SystemUseEntryElement("TF", 1)); 143 144 checkTFType(type); 145 streamHandler.data(new ByteDataReference(type | TF_LONG_FORM)); 146 147 streamHandler.data(date); 148 streamHandler.endElement(); 149 } 150 doTFEntry(int type, ISO9660ShortDateDataReference date)151 public void doTFEntry(int type, ISO9660ShortDateDataReference date) throws HandlerException { 152 streamHandler.startElement(new SystemUseEntryElement("TF", 1)); 153 154 checkTFType(type); 155 streamHandler.data(new ByteDataReference(type)); 156 157 streamHandler.data(date); 158 streamHandler.endElement(); 159 } 160 checkTFType(int type)161 private void checkTFType(int type) throws HandlerException { 162 if (type != TF_CREATION && type != TF_MODIFY && type != TF_ACCESS && type != TF_ATTRIBUTES 163 && type != TF_BACKUP && type != TF_EXPIRATION && type != TF_EFFECTIVE) { 164 throw new HandlerException("Invalid Rock Ridge Timestamp type: " + type); 165 } 166 } 167 doSFEntry(long virtualFileSizeHigh, long virtualFileSizeLow, int tableDepth)168 public void doSFEntry(long virtualFileSizeHigh, long virtualFileSizeLow, int tableDepth) throws HandlerException { 169 streamHandler.startElement(new SystemUseEntryElement("SF", 1)); 170 streamHandler.data(new BothWordDataReference(virtualFileSizeHigh)); 171 streamHandler.data(new BothWordDataReference(virtualFileSizeLow)); 172 streamHandler.data(new ByteDataReference(tableDepth)); 173 streamHandler.endElement(); 174 } 175 doEREntry()176 public void doEREntry() throws HandlerException { 177 String id, descriptor, source; 178 if (RRIPFactory.MKISOFS_COMPATIBILITY) { 179 id = "RRIP_1991A"; 180 descriptor = "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS"; 181 source = "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION"; 182 } else { 183 id = "IEEE 1282"; 184 descriptor = "THE IEEE 1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS."; 185 source = "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION."; 186 } 187 188 // TODO Handle character sets 189 ByteArrayDataReference idRef = new ByteArrayDataReference(id.getBytes()); 190 ByteArrayDataReference descriptorRef = new ByteArrayDataReference(descriptor.getBytes()); 191 ByteArrayDataReference sourceRef = new ByteArrayDataReference(source.getBytes()); 192 193 doEREntry(idRef, descriptorRef, sourceRef, 1); 194 } 195 doRREntry(int flags)196 public void doRREntry(int flags) throws HandlerException { 197 if (MKISOFS_COMPATIBILITY) { 198 if (flags<0 || flags>255) { 199 throw new HandlerException("Invalid RR flags: " + flags); 200 } 201 202 streamHandler.startElement(new SystemUseEntryElement("RR", 1)); 203 streamHandler.data(new ByteDataReference(flags)); 204 streamHandler.endElement(); 205 } 206 // Else: Do nothing (RRIP 1.12 does not include the RR Entry type) 207 } 208 } 209